Merge pull request #4306 from pravblockc/backports-v0.18-pr5

Backports v0.18 PR:14310, 14305 and 14307 with dash specific changes
This commit is contained in:
PastaPastaPasta 2021-08-06 16:16:54 -05:00 committed by GitHub
commit e626522f1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 261 additions and 79 deletions

View File

@ -26,7 +26,15 @@ CScript ParseScript(const std::string& s);
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false); std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
[[nodiscard]] bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx); [[nodiscard]] bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx);
[[nodiscard]] bool DecodeHexBlk(CBlock&, const std::string& strHexBlk); [[nodiscard]] bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
uint256 ParseHashStr(const std::string&, const std::string& strName); /**
* Parse a hex string into 256 bits
* @param[in] strHex a hex-formatted, 64-character string
* @param[out] result the result of the parasing
* @returns true if successful, false if not
*
* @see ParseHashV for an RPC-oriented version of this
*/
bool ParseHashStr(const std::string& strHex, uint256& result);
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName); std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName);
bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error); bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error);
int ParseSighashString(const UniValue& sighash); int ParseSighashString(const UniValue& sighash);

View File

@ -142,14 +142,13 @@ bool DecodePSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx,
return true; return true;
} }
uint256 ParseHashStr(const std::string& strHex, const std::string& strName) bool ParseHashStr(const std::string& strHex, uint256& result)
{ {
if (!IsHex(strHex)) // Note: IsHex("") is false if ((strHex.size() != 64) || !IsHex(strHex))
throw std::runtime_error(strName + " must be hexadecimal string (not '" + strHex + "')"); return false;
uint256 result;
result.SetHex(strHex); result.SetHex(strHex);
return result; return true;
} }
std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName) std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strName)

View File

@ -222,10 +222,10 @@ static void MutateTxAddInput(CMutableTransaction& tx, const std::string& strInpu
throw std::runtime_error("TX input missing separator"); throw std::runtime_error("TX input missing separator");
// extract and validate TXID // extract and validate TXID
std::string strTxid = vStrInputParts[0]; uint256 txid;
if ((strTxid.size() != 64) || !IsHex(strTxid)) if (!ParseHashStr(vStrInputParts[0], txid)) {
throw std::runtime_error("invalid TX input txid"); throw std::runtime_error("invalid TX input txid");
uint256 txid(uint256S(strTxid)); }
static const unsigned int minTxOutSz = 9; static const unsigned int minTxOutSz = 9;
static const unsigned int maxVout = MaxBlockSize() / minTxOutSz; static const unsigned int maxVout = MaxBlockSize() / minTxOutSz;
@ -547,7 +547,10 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
if (!prevOut.checkObject(types)) if (!prevOut.checkObject(types))
throw std::runtime_error("prevtxs internal object typecheck fail"); throw std::runtime_error("prevtxs internal object typecheck fail");
uint256 txid = ParseHashStr(prevOut["txid"].get_str(), "txid"); uint256 txid;
if (!ParseHashStr(prevOut["txid"].get_str(), txid)) {
throw std::runtime_error("txid must be hexadecimal string (not '" + prevOut["txid"].get_str() + "')");
}
const int nOut = prevOut["vout"].get_int(); const int nOut = prevOut["vout"].get_int();
if (nOut < 0) if (nOut < 0)

View File

@ -101,15 +101,6 @@ static std::string AvailableDataFormatsString()
return formats; return formats;
} }
static bool ParseHashStr(const std::string& strReq, uint256& v)
{
if (!IsHex(strReq) || (strReq.size() != 64))
return false;
v.SetHex(strReq);
return true;
}
static bool CheckWarmup(HTTPRequest* req) static bool CheckWarmup(HTTPRequest* req)
{ {
std::string statusmessage; std::string statusmessage;

View File

@ -261,7 +261,7 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request)
LOCK(cs_main); LOCK(cs_main);
uint256 hash = ParseHashStr(request.params[0].get_str(), "txid"); uint256 hash = ParseHashV(request.params[0].get_str(), "txid");
CAmount nAmount = request.params[1].get_int64(); CAmount nAmount = request.params[1].get_int64();
mempool.PrioritiseTransaction(hash, nAmount); mempool.PrioritiseTransaction(hash, nAmount);

View File

@ -114,7 +114,8 @@ BOOST_AUTO_TEST_CASE(blockfilters_json_test)
unsigned int pos = 0; unsigned int pos = 0;
/*int block_height =*/ test[pos++].get_int(); /*int block_height =*/ test[pos++].get_int();
/*uint256 block_hash =*/ ParseHashStr(test[pos++].get_str(), "block_hash"); uint256 block_hash;
BOOST_CHECK(ParseHashStr(test[pos++].get_str(), block_hash));
CBlock block; CBlock block;
BOOST_REQUIRE(DecodeHexBlk(block, test[pos++].get_str())); BOOST_REQUIRE(DecodeHexBlk(block, test[pos++].get_str()));
@ -129,9 +130,11 @@ BOOST_AUTO_TEST_CASE(blockfilters_json_test)
tx_undo.vprevout.emplace_back(txout, 0, false); tx_undo.vprevout.emplace_back(txout, 0, false);
} }
uint256 prev_filter_header_basic = ParseHashStr(test[pos++].get_str(), "prev_filter_header_basic"); uint256 prev_filter_header_basic;
BOOST_CHECK(ParseHashStr(test[pos++].get_str(), prev_filter_header_basic));
std::vector<unsigned char> filter_basic = ParseHex(test[pos++].get_str()); std::vector<unsigned char> filter_basic = ParseHex(test[pos++].get_str());
uint256 filter_header_basic = ParseHashStr(test[pos++].get_str(), "filter_header_basic"); uint256 filter_header_basic;
BOOST_CHECK(ParseHashStr(test[pos++].get_str(), filter_header_basic));
BlockFilter computed_filter_basic(BlockFilterType::BASIC_FILTER, block, block_undo); BlockFilter computed_filter_basic(BlockFilterType::BASIC_FILTER, block, block_undo);
BOOST_CHECK(computed_filter_basic.GetFilter().GetEncoded() == filter_basic); BOOST_CHECK(computed_filter_basic.GetFilter().GetEncoded() == filter_basic);

View File

@ -3945,6 +3945,8 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
// Sign the transaction // Sign the transaction
LOCK2(cs_main, mempool.cs); LOCK2(cs_main, mempool.cs);
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
EnsureWalletIsUnlocked(pwallet);
return SignTransaction(mtx, request.params[1], pwallet, false, request.params[2]); return SignTransaction(mtx, request.params[1], pwallet, false, request.params[2]);
} }

View File

@ -64,6 +64,11 @@ don't have test cases for.
- When calling RPCs with lots of arguments, consider using named keyword - When calling RPCs with lots of arguments, consider using named keyword
arguments instead of positional arguments to make the intent of the call arguments instead of positional arguments to make the intent of the call
clear to readers. clear to readers.
- Many of the core test framework classes such as `CBlock` and `CTransaction`
don't allow new attributes to be added to their objects at runtime like
typical Python objects allow. This helps prevent unpredictable side effects
from typographical errors or usage of the objects outside of their intended
purpose.
#### RPC and P2P definitions #### RPC and P2P definitions
@ -76,7 +81,7 @@ P2P messages. These can be found in the following source files:
#### Using the P2P interface #### Using the P2P interface
- `mininode.py` contains all the definitions for objects that pass - `messages.py` contains all the definitions for objects that pass
over the network (`CBlock`, `CTransaction`, etc, along with the network-level over the network (`CBlock`, `CTransaction`, etc, along with the network-level
wrappers for them, `msg_block`, `msg_tx`, etc). wrappers for them, `msg_block`, `msg_tx`, etc).

View File

@ -23,7 +23,8 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0, 0) assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0, 0)
# Test `prioritisetransaction` invalid `txid` # Test `prioritisetransaction` invalid `txid`
assert_raises_rpc_error(-1, "txid must be hexadecimal string", self.nodes[0].prioritisetransaction, txid='foo', fee_delta=0) assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].prioritisetransaction, txid='foo', fee_delta=0)
assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000')", self.nodes[0].prioritisetransaction, txid='Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000', fee_delta=0)
txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000' txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'

View File

@ -46,6 +46,14 @@ class SignRawTransactionsTest(BitcoinTestFramework):
rawTxSigned2 = self.nodes[0].signrawtransaction(rawTx, inputs, privKeys) rawTxSigned2 = self.nodes[0].signrawtransaction(rawTx, inputs, privKeys)
assert_equal(rawTxSigned, rawTxSigned2) assert_equal(rawTxSigned, rawTxSigned2)
def test_with_lock_outputs(self):
"""Test correct error reporting when trying to sign a locked output"""
self.nodes[0].encryptwallet("password")
rawTx = '020000000156b958f78e3f24e0b2f4e4db1255426b0902027cb37e3ddadb52e37c3557dddb0000000000ffffffff01c0a6b929010000001600149a2ee8c77140a053f36018ac8124a6ececc1668a00000000'
assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].signrawtransactionwithwallet, rawTx)
def script_verification_error_test(self): def script_verification_error_test(self):
"""Create and sign a raw transaction with valid (vin 0), invalid (vin 1) and one missing (vin 2) input script. """Create and sign a raw transaction with valid (vin 0), invalid (vin 1) and one missing (vin 2) input script.
@ -117,6 +125,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
def run_test(self): def run_test(self):
self.successful_signing_test() self.successful_signing_test()
self.script_verification_error_test() self.script_verification_error_test()
self.test_with_lock_outputs()
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -10,7 +10,12 @@ CBlock, CTransaction, CBlockHeader, CTxIn, CTxOut, etc....:
bitcoin/primitives bitcoin/primitives
msg_block, msg_tx, msg_headers, etc.: msg_block, msg_tx, msg_headers, etc.:
data structures that represent network messages data structures that represent network messages
ser_*, deser_*: functions that handle serialization/deserialization."""
ser_*, deser_*: functions that handle serialization/deserialization.
Classes use __slots__ to ensure extraneous attributes aren't accidentally added
by tests, compromising their intended effect.
"""
from codecs import encode from codecs import encode
import copy import copy
from collections import namedtuple from collections import namedtuple
@ -215,7 +220,9 @@ def ToHex(obj):
# Objects that map to dashd objects, which can be serialized/deserialized # Objects that map to dashd objects, which can be serialized/deserialized
class CService(): class CService:
__slots__ = ("ip", "port")
def __init__(self): def __init__(self):
self.ip = "" self.ip = ""
self.port = 0 self.port = 0
@ -234,7 +241,7 @@ class CService():
return "CService(ip=%s port=%i)" % (self.ip, self.port) return "CService(ip=%s port=%i)" % (self.ip, self.port)
class CAddress(): class CAddress:
__slots__ = ("net", "ip", "nServices", "port", "time") __slots__ = ("net", "ip", "nServices", "port", "time")
# see https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki # see https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki
@ -313,7 +320,9 @@ class CAddress():
% (self.nServices, self.ADDRV2_NET_NAME[self.net], self.ip, self.port)) % (self.nServices, self.ADDRV2_NET_NAME[self.net], self.ip, self.port))
class CInv(): class CInv:
__slots__ = ("hash", "type")
typemap = { typemap = {
0: "Error", 0: "Error",
1: "TX", 1: "TX",
@ -340,7 +349,9 @@ class CInv():
% (self.typemap.get(self.type, "%d" % self.type), self.hash) % (self.typemap.get(self.type, "%d" % self.type), self.hash)
class CBlockLocator(): class CBlockLocator:
__slots__ = ("nVersion", "vHave")
def __init__(self): def __init__(self):
self.nVersion = MY_VERSION self.nVersion = MY_VERSION
self.vHave = [] self.vHave = []
@ -360,7 +371,9 @@ class CBlockLocator():
% (self.nVersion, repr(self.vHave)) % (self.nVersion, repr(self.vHave))
class COutPoint(): class COutPoint:
__slots__ = ("hash", "n")
def __init__(self, hash=0, n=0xFFFFFFFF): def __init__(self, hash=0, n=0xFFFFFFFF):
self.hash = hash self.hash = hash
self.n = n self.n = n
@ -379,7 +392,9 @@ class COutPoint():
return "COutPoint(hash=%064x n=%i)" % (self.hash, self.n) return "COutPoint(hash=%064x n=%i)" % (self.hash, self.n)
class CTxIn(): class CTxIn:
__slots__ = ("nSequence", "prevout", "scriptSig")
def __init__(self, outpoint=None, scriptSig=b"", nSequence=0): def __init__(self, outpoint=None, scriptSig=b"", nSequence=0):
if outpoint is None: if outpoint is None:
self.prevout = COutPoint() self.prevout = COutPoint()
@ -407,7 +422,9 @@ class CTxIn():
self.nSequence) self.nSequence)
class CTxOut(): class CTxOut:
__slots__ = ("nValue", "scriptPubKey")
def __init__(self, nValue=0, scriptPubKey=b""): def __init__(self, nValue=0, scriptPubKey=b""):
self.nValue = nValue self.nValue = nValue
self.scriptPubKey = scriptPubKey self.scriptPubKey = scriptPubKey
@ -428,7 +445,10 @@ class CTxOut():
bytes_to_hex_str(self.scriptPubKey)) bytes_to_hex_str(self.scriptPubKey))
class CTransaction(): class CTransaction:
__slots__ = ("hash", "nLockTime", "nVersion", "sha256", "vin", "vout",
"nType", "vExtraPayload")
def __init__(self, tx=None): def __init__(self, tx=None):
if tx is None: if tx is None:
self.nVersion = 1 self.nVersion = 1
@ -494,7 +514,10 @@ class CTransaction():
% (self.nVersion, repr(self.vin), repr(self.vout), self.nLockTime) % (self.nVersion, repr(self.vin), repr(self.vout), self.nLockTime)
class CBlockHeader(): class CBlockHeader:
__slots__ = ("hash", "hashMerkleRoot", "hashPrevBlock", "nBits", "nNonce",
"nTime", "nVersion", "sha256")
def __init__(self, header=None): def __init__(self, header=None):
if header is None: if header is None:
self.set_null() self.set_null()
@ -563,6 +586,8 @@ class CBlockHeader():
class CBlock(CBlockHeader): class CBlock(CBlockHeader):
__slots__ = ("vtx",)
def __init__(self, header=None): def __init__(self, header=None):
super(CBlock, self).__init__(header) super(CBlock, self).__init__(header)
self.vtx = [] self.vtx = []
@ -619,7 +644,9 @@ class CBlock(CBlockHeader):
% (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot, % (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot,
time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.vtx)) time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.vtx))
class PrefilledTransaction(): class PrefilledTransaction:
__slots__ = ("index", "tx")
def __init__(self, index=0, tx = None): def __init__(self, index=0, tx = None):
self.index = index self.index = index
self.tx = tx self.tx = tx
@ -638,8 +665,12 @@ class PrefilledTransaction():
def __repr__(self): def __repr__(self):
return "PrefilledTransaction(index=%d, tx=%s)" % (self.index, repr(self.tx)) return "PrefilledTransaction(index=%d, tx=%s)" % (self.index, repr(self.tx))
# This is what we send on the wire, in a cmpctblock message. # This is what we send on the wire, in a cmpctblock message.
class P2PHeaderAndShortIDs(): class P2PHeaderAndShortIDs:
__slots__ = ("header", "nonce", "prefilled_txn", "prefilled_txn_length",
"shortids", "shortids_length")
def __init__(self): def __init__(self):
self.header = CBlockHeader() self.header = CBlockHeader()
self.nonce = 0 self.nonce = 0
@ -680,9 +711,12 @@ def calculate_shortid(k0, k1, tx_hash):
expected_shortid &= 0x0000ffffffffffff expected_shortid &= 0x0000ffffffffffff
return expected_shortid return expected_shortid
# This version gets rid of the array lengths, and reinterprets the differential # This version gets rid of the array lengths, and reinterprets the differential
# encoding into indices that can be used for lookup. # encoding into indices that can be used for lookup.
class HeaderAndShortIDs(): class HeaderAndShortIDs:
__slots__ = ("header", "nonce", "prefilled_txn", "shortids")
def __init__(self, p2pheaders_and_shortids = None): def __init__(self, p2pheaders_and_shortids = None):
self.header = CBlockHeader() self.header = CBlockHeader()
self.nonce = 0 self.nonce = 0
@ -734,7 +768,8 @@ class HeaderAndShortIDs():
return "HeaderAndShortIDs(header=%s, nonce=%d, shortids=%s, prefilledtxn=%s" % (repr(self.header), self.nonce, repr(self.shortids), repr(self.prefilled_txn)) return "HeaderAndShortIDs(header=%s, nonce=%d, shortids=%s, prefilledtxn=%s" % (repr(self.header), self.nonce, repr(self.shortids), repr(self.prefilled_txn))
class BlockTransactionsRequest(): class BlockTransactionsRequest:
__slots__ = ("blockhash", "indexes")
def __init__(self, blockhash=0, indexes = None): def __init__(self, blockhash=0, indexes = None):
self.blockhash = blockhash self.blockhash = blockhash
@ -774,7 +809,8 @@ class BlockTransactionsRequest():
return "BlockTransactionsRequest(hash=%064x indexes=%s)" % (self.blockhash, repr(self.indexes)) return "BlockTransactionsRequest(hash=%064x indexes=%s)" % (self.blockhash, repr(self.indexes))
class BlockTransactions(): class BlockTransactions:
__slots__ = ("blockhash", "transactions")
def __init__(self, blockhash=0, transactions = None): def __init__(self, blockhash=0, transactions = None):
self.blockhash = blockhash self.blockhash = blockhash
@ -794,7 +830,9 @@ class BlockTransactions():
return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions)) return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions))
class CPartialMerkleTree(): class CPartialMerkleTree:
__slots__ = ("fBad", "nTransactions", "vBits", "vHash")
def __init__(self): def __init__(self):
self.nTransactions = 0 self.nTransactions = 0
self.vBits = [] self.vBits = []
@ -817,7 +855,9 @@ class CPartialMerkleTree():
return "CPartialMerkleTree(nTransactions=%d vBits.size=%d vHash.size=%d)" % (self.nTransactions, len(self.vBits), len(self.vHash)) return "CPartialMerkleTree(nTransactions=%d vBits.size=%d vHash.size=%d)" % (self.nTransactions, len(self.vBits), len(self.vHash))
class CMerkleBlock(): class CMerkleBlock:
__slots__ = ("header", "txn")
def __init__(self, header=CBlockHeader(), txn=CPartialMerkleTree()): def __init__(self, header=CBlockHeader(), txn=CPartialMerkleTree()):
self.header = header self.header = header
self.txn = txn self.txn = txn
@ -836,7 +876,9 @@ class CMerkleBlock():
return "CMerkleBlock(header=%s txn=%s)" % (repr(self.header), repr(self.txn)) return "CMerkleBlock(header=%s txn=%s)" % (repr(self.header), repr(self.txn))
class CCbTx(): class CCbTx:
__slots__ = ("version", "height", "merkleRootMNList", "merkleRootQuorums")
def __init__(self, version=None, height=None, merkleRootMNList=None, merkleRootQuorums=None): def __init__(self, version=None, height=None, merkleRootMNList=None, merkleRootQuorums=None):
self.set_null() self.set_null()
if version is not None: if version is not None:
@ -870,7 +912,9 @@ class CCbTx():
return r return r
class CSimplifiedMNListEntry(): class CSimplifiedMNListEntry:
__slots__ = ("proRegTxHash", "confirmedHash", "service", "pubKeyOperator", "keyIDVoting", "isValid")
def __init__(self): def __init__(self):
self.set_null() self.set_null()
@ -902,6 +946,9 @@ class CSimplifiedMNListEntry():
class CFinalCommitment: class CFinalCommitment:
__slots__ = ("nVersion", "llmqType", "quorumHash", "signers", "validMembers", "quorumPublicKey",
"quorumVvecHash", "quorumSig", "membersSig")
def __init__(self): def __init__(self):
self.set_null() self.set_null()
@ -942,6 +989,9 @@ class CFinalCommitment:
class CGovernanceObject: class CGovernanceObject:
__slots__ = ("nHashParent", "nRevision", "nTime", "nCollateralHash", "vchData", "nObjectType",
"masternodeOutpoint", "vchSig")
def __init__(self): def __init__(self):
self.nHashParent = 0 self.nHashParent = 0
self.nRevision = 0 self.nRevision = 0
@ -982,6 +1032,8 @@ class CGovernanceObject:
class CGovernanceVote: class CGovernanceVote:
__slots__ = ("masternodeOutpoint", "nParentHash", "nVoteOutcome", "nVoteSignal", "nTime", "vchSig")
def __init__(self): def __init__(self):
self.masternodeOutpoint = COutPoint() self.masternodeOutpoint = COutPoint()
self.nParentHash = 0 self.nParentHash = 0
@ -1013,6 +1065,8 @@ class CGovernanceVote:
class CRecoveredSig: class CRecoveredSig:
__slots__ = ("llmqType", "quorumHash", "id", "msgHash", "sig")
def __init__(self): def __init__(self):
self.llmqType = 0 self.llmqType = 0
self.quorumHash = 0 self.quorumHash = 0
@ -1038,6 +1092,8 @@ class CRecoveredSig:
class CSigShare: class CSigShare:
__slots__ = ("llmqType", "quorumHash", "quorumMember", "id", "msgHash", "sigShare")
def __init__(self): def __init__(self):
self.llmqType = 0 self.llmqType = 0
self.quorumHash = 0 self.quorumHash = 0
@ -1066,6 +1122,8 @@ class CSigShare:
class CBLSPublicKey: class CBLSPublicKey:
__slots__ = ("data")
def __init__(self): def __init__(self):
self.data = b'\\x0' * 48 self.data = b'\\x0' * 48
@ -1079,6 +1137,8 @@ class CBLSPublicKey:
class CBLSIESEncryptedSecretKey: class CBLSIESEncryptedSecretKey:
__slots__ = ("ephemeral_pubKey", "iv", "data")
def __init__(self): def __init__(self):
self.ephemeral_pubKey = b'\\x0' * 48 self.ephemeral_pubKey = b'\\x0' * 48
self.iv = b'\\x0' * 32 self.iv = b'\\x0' * 32
@ -1100,7 +1160,9 @@ class CBLSIESEncryptedSecretKey:
# Objects that correspond to messages on the wire # Objects that correspond to messages on the wire
class msg_version(): class msg_version:
__slots__ = ("addrFrom", "addrTo", "nNonce", "nRelay", "nServices",
"nStartingHeight", "nTime", "nVersion", "strSubVer")
command = b"version" command = b"version"
def __init__(self): def __init__(self):
@ -1157,7 +1219,8 @@ class msg_version():
self.strSubVer, self.nStartingHeight, self.nRelay) self.strSubVer, self.nStartingHeight, self.nRelay)
class msg_verack(): class msg_verack:
__slots__ = ()
command = b"verack" command = b"verack"
def __init__(self): def __init__(self):
@ -1173,7 +1236,8 @@ class msg_verack():
return "msg_verack()" return "msg_verack()"
class msg_addr(): class msg_addr:
__slots__ = ("addrs",)
command = b"addr" command = b"addr"
def __init__(self): def __init__(self):
@ -1189,8 +1253,8 @@ class msg_addr():
return "msg_addr(addrs=%s)" % (repr(self.addrs)) return "msg_addr(addrs=%s)" % (repr(self.addrs))
class msg_addrv2(): class msg_addrv2:
# __slots__ = ("addrs",) __slots__ = ("addrs",)
# msgtype = b"addrv2" # msgtype = b"addrv2"
command = b"addrv2" command = b"addrv2"
@ -1207,8 +1271,8 @@ class msg_addrv2():
return "msg_addrv2(addrs=%s)" % (repr(self.addrs)) return "msg_addrv2(addrs=%s)" % (repr(self.addrs))
class msg_sendaddrv2(): class msg_sendaddrv2:
# __slots__ = () __slots__ = ()
# msgtype = b"sendaddrv2" # msgtype = b"sendaddrv2"
command = b"sendaddrv2" command = b"sendaddrv2"
@ -1225,7 +1289,8 @@ class msg_sendaddrv2():
return "msg_sendaddrv2()" return "msg_sendaddrv2()"
class msg_inv(): class msg_inv:
__slots__ = ("inv",)
command = b"inv" command = b"inv"
def __init__(self, inv=None): def __init__(self, inv=None):
@ -1244,7 +1309,8 @@ class msg_inv():
return "msg_inv(inv=%s)" % (repr(self.inv)) return "msg_inv(inv=%s)" % (repr(self.inv))
class msg_getdata(): class msg_getdata:
__slots__ = ("inv",)
command = b"getdata" command = b"getdata"
def __init__(self, inv=None): def __init__(self, inv=None):
@ -1260,7 +1326,8 @@ class msg_getdata():
return "msg_getdata(inv=%s)" % (repr(self.inv)) return "msg_getdata(inv=%s)" % (repr(self.inv))
class msg_getblocks(): class msg_getblocks:
__slots__ = ("locator", "hashstop")
command = b"getblocks" command = b"getblocks"
def __init__(self): def __init__(self):
@ -1283,7 +1350,8 @@ class msg_getblocks():
% (repr(self.locator), self.hashstop) % (repr(self.locator), self.hashstop)
class msg_tx(): class msg_tx:
__slots__ = ("tx",)
command = b"tx" command = b"tx"
def __init__(self, tx=CTransaction()): def __init__(self, tx=CTransaction()):
@ -1299,7 +1367,8 @@ class msg_tx():
return "msg_tx(tx=%s)" % (repr(self.tx)) return "msg_tx(tx=%s)" % (repr(self.tx))
class msg_block(): class msg_block:
__slots__ = ("block",)
command = b"block" command = b"block"
def __init__(self, block=None): def __init__(self, block=None):
@ -1319,7 +1388,9 @@ class msg_block():
# for cases where a user needs tighter control over what is sent over the wire # for cases where a user needs tighter control over what is sent over the wire
# note that the user must supply the name of the command, and the data # note that the user must supply the name of the command, and the data
class msg_generic(): class msg_generic:
__slots__ = ("command", "data")
def __init__(self, command, data=None): def __init__(self, command, data=None):
self.command = command self.command = command
self.data = data self.data = data
@ -1330,7 +1401,9 @@ class msg_generic():
def __repr__(self): def __repr__(self):
return "msg_generic()" return "msg_generic()"
class msg_getaddr():
class msg_getaddr:
__slots__ = ()
command = b"getaddr" command = b"getaddr"
def __init__(self): def __init__(self):
@ -1346,7 +1419,8 @@ class msg_getaddr():
return "msg_getaddr()" return "msg_getaddr()"
class msg_ping(): class msg_ping:
__slots__ = ("nonce",)
command = b"ping" command = b"ping"
def __init__(self, nonce=0): def __init__(self, nonce=0):
@ -1364,7 +1438,8 @@ class msg_ping():
return "msg_ping(nonce=%08x)" % self.nonce return "msg_ping(nonce=%08x)" % self.nonce
class msg_pong(): class msg_pong:
__slots__ = ("nonce",)
command = b"pong" command = b"pong"
def __init__(self, nonce=0): def __init__(self, nonce=0):
@ -1382,7 +1457,8 @@ class msg_pong():
return "msg_pong(nonce=%08x)" % self.nonce return "msg_pong(nonce=%08x)" % self.nonce
class msg_mempool(): class msg_mempool:
__slots__ = ()
command = b"mempool" command = b"mempool"
def __init__(self): def __init__(self):
@ -1414,7 +1490,8 @@ class msg_notfound:
return "msg_notfound(vec=%s)" % (repr(self.vec)) return "msg_notfound(vec=%s)" % (repr(self.vec))
class msg_sendheaders(): class msg_sendheaders:
__slots__ = ()
command = b"sendheaders" command = b"sendheaders"
def __init__(self): def __init__(self):
@ -1434,7 +1511,8 @@ class msg_sendheaders():
# number of entries # number of entries
# vector of hashes # vector of hashes
# hash_stop (hash of last desired block header, 0 to get as many as possible) # hash_stop (hash of last desired block header, 0 to get as many as possible)
class msg_getheaders(): class msg_getheaders:
__slots__ = ("hashstop", "locator",)
command = b"getheaders" command = b"getheaders"
def __init__(self): def __init__(self):
@ -1459,7 +1537,8 @@ class msg_getheaders():
# headers message has # headers message has
# <count> <vector of block headers> # <count> <vector of block headers>
class msg_headers(): class msg_headers:
__slots__ = ("headers",)
command = b"headers" command = b"headers"
def __init__(self, headers=None): def __init__(self, headers=None):
@ -1479,7 +1558,8 @@ class msg_headers():
return "msg_headers(headers=%s)" % repr(self.headers) return "msg_headers(headers=%s)" % repr(self.headers)
class msg_reject(): class msg_reject:
__slots__ = ("code", "data", "message", "reason")
command = b"reject" command = b"reject"
REJECT_MALFORMED = 1 REJECT_MALFORMED = 1
@ -1511,7 +1591,8 @@ class msg_reject():
% (self.message, self.code, self.reason, self.data) % (self.message, self.code, self.reason, self.data)
class msg_sendcmpct(): class msg_sendcmpct:
__slots__ = ("announce", "version")
command = b"sendcmpct" command = b"sendcmpct"
def __init__(self): def __init__(self):
@ -1531,7 +1612,9 @@ class msg_sendcmpct():
def __repr__(self): def __repr__(self):
return "msg_sendcmpct(announce=%s, version=%lu)" % (self.announce, self.version) return "msg_sendcmpct(announce=%s, version=%lu)" % (self.announce, self.version)
class msg_cmpctblock():
class msg_cmpctblock:
__slots__ = ("header_and_shortids",)
command = b"cmpctblock" command = b"cmpctblock"
def __init__(self, header_and_shortids = None): def __init__(self, header_and_shortids = None):
@ -1549,7 +1632,9 @@ class msg_cmpctblock():
def __repr__(self): def __repr__(self):
return "msg_cmpctblock(HeaderAndShortIDs=%s)" % repr(self.header_and_shortids) return "msg_cmpctblock(HeaderAndShortIDs=%s)" % repr(self.header_and_shortids)
class msg_getblocktxn():
class msg_getblocktxn:
__slots__ = ("block_txn_request",)
command = b"getblocktxn" command = b"getblocktxn"
def __init__(self): def __init__(self):
@ -1567,7 +1652,9 @@ class msg_getblocktxn():
def __repr__(self): def __repr__(self):
return "msg_getblocktxn(block_txn_request=%s)" % (repr(self.block_txn_request)) return "msg_getblocktxn(block_txn_request=%s)" % (repr(self.block_txn_request))
class msg_blocktxn():
class msg_blocktxn:
__slots__ = ("block_transactions",)
command = b"blocktxn" command = b"blocktxn"
def __init__(self): def __init__(self):
@ -1584,7 +1671,9 @@ class msg_blocktxn():
def __repr__(self): def __repr__(self):
return "msg_blocktxn(block_transactions=%s)" % (repr(self.block_transactions)) return "msg_blocktxn(block_transactions=%s)" % (repr(self.block_transactions))
class msg_getmnlistd():
class msg_getmnlistd:
__slots__ = ("baseBlockHash", "blockHash",)
command = b"getmnlistd" command = b"getmnlistd"
def __init__(self, baseBlockHash=0, blockHash=0): def __init__(self, baseBlockHash=0, blockHash=0):
@ -1606,7 +1695,8 @@ class msg_getmnlistd():
QuorumId = namedtuple('QuorumId', ['llmqType', 'quorumHash']) QuorumId = namedtuple('QuorumId', ['llmqType', 'quorumHash'])
class msg_mnlistdiff(): class msg_mnlistdiff:
__slots__ = ("baseBlockHash", "blockHash", "merkleProof", "cbTx", "deletedMNs", "mnList", "deletedQuorums", "newQuorums",)
command = b"mnlistdiff" command = b"mnlistdiff"
def __init__(self): def __init__(self):
@ -1648,7 +1738,8 @@ class msg_mnlistdiff():
return "msg_mnlistdiff(baseBlockHash=%064x, blockHash=%064x)" % (self.baseBlockHash, self.blockHash) return "msg_mnlistdiff(baseBlockHash=%064x, blockHash=%064x)" % (self.baseBlockHash, self.blockHash)
class msg_clsig(): class msg_clsig:
__slots__ = ("height", "blockHash", "sig",)
command = b"clsig" command = b"clsig"
def __init__(self, height=0, blockHash=0, sig=b'\\x0' * 96): def __init__(self, height=0, blockHash=0, sig=b'\\x0' * 96):
@ -1672,7 +1763,8 @@ class msg_clsig():
return "msg_clsig(height=%d, blockHash=%064x)" % (self.height, self.blockHash) return "msg_clsig(height=%d, blockHash=%064x)" % (self.height, self.blockHash)
class msg_islock(): class msg_islock:
__slots__ = ("inputs", "txid", "sig",)
command = b"islock" command = b"islock"
def __init__(self, inputs=[], txid=0, sig=b'\\x0' * 96): def __init__(self, inputs=[], txid=0, sig=b'\\x0' * 96):
@ -1696,7 +1788,8 @@ class msg_islock():
return "msg_islock(inputs=%s, txid=%064x)" % (repr(self.inputs), self.txid) return "msg_islock(inputs=%s, txid=%064x)" % (repr(self.inputs), self.txid)
class msg_qsigshare(): class msg_qsigshare:
__slots__ = ("sig_shares",)
command = b"qsigshare" command = b"qsigshare"
def __init__(self, sig_shares=[]): def __init__(self, sig_shares=[]):
@ -1714,7 +1807,8 @@ class msg_qsigshare():
return "msg_qsigshare(sigShares=%d)" % (len(self.sig_shares)) return "msg_qsigshare(sigShares=%d)" % (len(self.sig_shares))
class msg_qwatch(): class msg_qwatch:
__slots__ = ()
command = b"qwatch" command = b"qwatch"
def __init__(self): def __init__(self):
@ -1730,7 +1824,8 @@ class msg_qwatch():
return "msg_qwatch()" return "msg_qwatch()"
class msg_qgetdata(): class msg_qgetdata:
__slots__ = ("quorum_hash", "quorum_type", "data_mask", "protx_hash")
command = b"qgetdata" command = b"qgetdata"
def __init__(self, quorum_hash=0, quorum_type=-1, data_mask=0, protx_hash=0): def __init__(self, quorum_hash=0, quorum_type=-1, data_mask=0, protx_hash=0):
@ -1761,7 +1856,8 @@ class msg_qgetdata():
self.protx_hash) self.protx_hash)
class msg_qdata(): class msg_qdata:
__slots__ = ("quorum_hash", "quorum_type", "data_mask", "protx_hash", "error", "quorum_vvec", "enc_contributions",)
command = b"qdata" command = b"qdata"
def __init__(self): def __init__(self):

View File

@ -25,7 +25,7 @@ def hash160(s):
_opcode_instances = [] _opcode_instances = []
class CScriptOp(int): class CScriptOp(int):
"""A single script opcode""" """A single script opcode"""
__slots__ = [] __slots__ = ()
@staticmethod @staticmethod
def encode_op_pushdata(d): def encode_op_pushdata(d):
@ -362,8 +362,11 @@ class CScriptTruncatedPushDataError(CScriptInvalidError):
self.data = data self.data = data
super(CScriptTruncatedPushDataError, self).__init__(msg) super(CScriptTruncatedPushDataError, self).__init__(msg)
# This is used, eg, for blockchain heights in coinbase scripts (bip34) # This is used, eg, for blockchain heights in coinbase scripts (bip34)
class CScriptNum(): class CScriptNum:
__slots__ = ("value",)
def __init__(self, d=0): def __init__(self, d=0):
self.value = d self.value = d
@ -394,6 +397,8 @@ class CScript(bytes):
iter(script) however does iterate by opcode. iter(script) however does iterate by opcode.
""" """
__slots__ = ()
@classmethod @classmethod
def __coerce_instance(cls, other): def __coerce_instance(cls, other):
# Coerce other into bytes # Coerce other into bytes

View File

@ -102,6 +102,30 @@
"error_txt": "error: Invalid TX locktime requested", "error_txt": "error: Invalid TX locktime requested",
"description": "Tests the check for invalid locktime value" "description": "Tests the check for invalid locktime value"
}, },
{ "exec": "./dash-tx",
"args":
["-create",
"in=Z897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f:0"],
"return_code": 1,
"error_txt": "error: invalid TX input txid",
"description": "Tests the check for an invalid txid invalid hex"
},
{ "exec": "./dash-tx",
"args":
["-create",
"in=5897de6bd6:0"],
"return_code": 1,
"error_txt": "error: invalid TX input txid",
"description": "Tests the check for an invalid txid valid hex but too short"
},
{ "exec": "./dash-tx",
"args":
["-create",
"in=5897de6bd6027a475eadd57019d4e6872c396d0716c4875a5f1a6fcfdf385c1f12:0"],
"return_code": 1,
"error_txt": "error: invalid TX input txid",
"description": "Tests the check for an invalid txid valid hex but too long"
},
{ "exec": "./dash-tx", { "exec": "./dash-tx",
"args": "args":
["-create", ["-create",
@ -251,6 +275,42 @@
"error_txt": "error: prevtxs internal object typecheck fail", "error_txt": "error: prevtxs internal object typecheck fail",
"description": "Tests the check for invalid vout index in prevtxs for sign" "description": "Tests the check for invalid vout index in prevtxs for sign"
}, },
{ "exec": "./dash-tx",
"args":
["-create",
"in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0",
"set=privatekeys:[\"7qYrzJZWqnyCWMYswFcqaRJypGdVceudXPSxmZKsngN7fyo7aAV\"]",
"set=prevtxs:[{\"txid\":\"Zd49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59412\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]",
"sign=ALL",
"outaddr=0.001:XijDvbYpPmznwgpWD3DkdYNfGmRP2KoVSk"],
"return_code": 1,
"error_txt": "error: txid must be hexadecimal string (not 'Zd49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59412')",
"description": "Tests the check for invalid txid due to invalid hex"
},
{ "exec": "./dash-tx",
"args":
["-create",
"in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0",
"set=privatekeys:[\"7qYrzJZWqnyCWMYswFcqaRJypGdVceudXPSxmZKsngN7fyo7aAV\"]",
"set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc594\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]",
"sign=ALL",
"outaddr=0.001:XijDvbYpPmznwgpWD3DkdYNfGmRP2KoVSk"],
"return_code": 1,
"error_txt": "error: txid must be hexadecimal string (not '4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc594')",
"description": "Tests the check for invalid txid valid hex, but too short"
},
{ "exec": "./dash-tx",
"args":
["-create",
"in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0",
"set=privatekeys:[\"7qYrzJZWqnyCWMYswFcqaRJypGdVceudXPSxmZKsngN7fyo7aAV\"]",
"set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc5948512\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]",
"sign=ALL",
"outaddr=0.001:XijDvbYpPmznwgpWD3DkdYNfGmRP2KoVSk"],
"return_code": 1,
"error_txt": "error: txid must be hexadecimal string (not '4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc5948512')",
"description": "Tests the check for invalid txid valid hex, but too long"
},
{ "exec": "./dash-tx", { "exec": "./dash-tx",
"args": "args":
["-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397", "nversion=1"], ["-create", "outpubkey=0:02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397", "nversion=1"],