aboutsummaryrefslogtreecommitdiff
path: root/test/functional/test_framework/messages.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional/test_framework/messages.py')
-rwxr-xr-xtest/functional/test_framework/messages.py205
1 files changed, 154 insertions, 51 deletions
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index 0a3907cba4..356a45d6d0 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -13,7 +13,11 @@ CBlock, CTransaction, CBlockHeader, CTxIn, CTxOut, etc....:
msg_block, msg_tx, msg_headers, etc.:
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
import copy
import hashlib
@@ -31,7 +35,6 @@ MY_VERSION = 70014 # past bip-31 for ping/pong
MY_SUBVERSION = b"/python-mininode-tester:0.0.3/"
MY_RELAY = 1 # from version 70001 onwards, fRelay should be appended to version messages (BIP37)
-MAX_INV_SZ = 50000
MAX_LOCATOR_SZ = 101
MAX_BLOCK_BASE_SIZE = 1000000
@@ -54,9 +57,6 @@ MSG_TYPE_MASK = 0xffffffff >> 2
def sha256(s):
return hashlib.new('sha256', s).digest()
-def ripemd160(s):
- return hashlib.new('ripemd160', s).digest()
-
def hash256(s):
return sha256(sha256(s))
@@ -185,7 +185,10 @@ def ToHex(obj):
# Objects that map to bitcoind objects, which can be serialized/deserialized
-class CAddress():
+
+class CAddress:
+ __slots__ = ("ip", "nServices", "pchReserved", "port", "time")
+
def __init__(self):
self.time = 0
self.nServices = 1
@@ -215,7 +218,10 @@ class CAddress():
return "CAddress(nServices=%i ip=%s port=%i)" % (self.nServices,
self.ip, self.port)
-class CInv():
+
+class CInv:
+ __slots__ = ("hash", "type")
+
typemap = {
0: "Error",
1: "TX",
@@ -244,7 +250,9 @@ class CInv():
% (self.typemap[self.type], self.hash)
-class CBlockLocator():
+class CBlockLocator:
+ __slots__ = ("nVersion", "vHave")
+
def __init__(self):
self.nVersion = MY_VERSION
self.vHave = []
@@ -264,7 +272,9 @@ class CBlockLocator():
% (self.nVersion, repr(self.vHave))
-class COutPoint():
+class COutPoint:
+ __slots__ = ("hash", "n")
+
def __init__(self, hash=0, n=0):
self.hash = hash
self.n = n
@@ -283,7 +293,9 @@ class COutPoint():
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):
if outpoint is None:
self.prevout = COutPoint()
@@ -311,7 +323,9 @@ class CTxIn():
self.nSequence)
-class CTxOut():
+class CTxOut:
+ __slots__ = ("nValue", "scriptPubKey")
+
def __init__(self, nValue=0, scriptPubKey=b""):
self.nValue = nValue
self.scriptPubKey = scriptPubKey
@@ -332,7 +346,9 @@ class CTxOut():
bytes_to_hex_str(self.scriptPubKey))
-class CScriptWitness():
+class CScriptWitness:
+ __slots__ = ("stack",)
+
def __init__(self):
# stack is a vector of strings
self.stack = []
@@ -347,7 +363,9 @@ class CScriptWitness():
return True
-class CTxInWitness():
+class CTxInWitness:
+ __slots__ = ("scriptWitness",)
+
def __init__(self):
self.scriptWitness = CScriptWitness()
@@ -364,7 +382,9 @@ class CTxInWitness():
return self.scriptWitness.is_null()
-class CTxWitness():
+class CTxWitness:
+ __slots__ = ("vtxinwit",)
+
def __init__(self):
self.vtxinwit = []
@@ -392,7 +412,10 @@ class CTxWitness():
return True
-class CTransaction():
+class CTransaction:
+ __slots__ = ("hash", "nLockTime", "nVersion", "sha256", "vin", "vout",
+ "wit")
+
def __init__(self, tx=None):
if tx is None:
self.nVersion = 1
@@ -427,6 +450,8 @@ class CTransaction():
if flags != 0:
self.wit.vtxinwit = [CTxInWitness() for i in range(len(self.vin))]
self.wit.deserialize(f)
+ else:
+ self.wit = CTxWitness()
self.nLockTime = struct.unpack("<I", f.read(4))[0]
self.sha256 = None
self.hash = None
@@ -496,7 +521,10 @@ class CTransaction():
% (self.nVersion, repr(self.vin), repr(self.vout), repr(self.wit), self.nLockTime)
-class CBlockHeader():
+class CBlockHeader:
+ __slots__ = ("hash", "hashMerkleRoot", "hashPrevBlock", "nBits", "nNonce",
+ "nTime", "nVersion", "sha256")
+
def __init__(self, header=None):
if header is None:
self.set_null()
@@ -565,6 +593,8 @@ class CBlockHeader():
class CBlock(CBlockHeader):
+ __slots__ = ("vtx",)
+
def __init__(self, header=None):
super(CBlock, self).__init__(header)
self.vtx = []
@@ -636,7 +666,9 @@ class CBlock(CBlockHeader):
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):
self.index = index
self.tx = tx
@@ -664,8 +696,12 @@ class PrefilledTransaction():
def __repr__(self):
return "PrefilledTransaction(index=%d, tx=%s)" % (self.index, repr(self.tx))
+
# 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):
self.header = CBlockHeader()
self.nonce = 0
@@ -703,9 +739,11 @@ class P2PHeaderAndShortIDs():
def __repr__(self):
return "P2PHeaderAndShortIDs(header=%s, nonce=%d, shortids_length=%d, shortids=%s, prefilled_txn_length=%d, prefilledtxn=%s" % (repr(self.header), self.nonce, self.shortids_length, repr(self.shortids), self.prefilled_txn_length, repr(self.prefilled_txn))
+
# P2P version of the above that will use witness serialization (for compact
# block version 2)
class P2PHeaderAndShortWitnessIDs(P2PHeaderAndShortIDs):
+ __slots__ = ()
def serialize(self):
return super(P2PHeaderAndShortWitnessIDs, self).serialize(with_witness=True)
@@ -715,9 +753,12 @@ def calculate_shortid(k0, k1, tx_hash):
expected_shortid &= 0x0000ffffffffffff
return expected_shortid
+
# This version gets rid of the array lengths, and reinterprets the differential
# encoding into indices that can be used for lookup.
-class HeaderAndShortIDs():
+class HeaderAndShortIDs:
+ __slots__ = ("header", "nonce", "prefilled_txn", "shortids", "use_witness")
+
def __init__(self, p2pheaders_and_shortids = None):
self.header = CBlockHeader()
self.nonce = 0
@@ -725,7 +766,7 @@ class HeaderAndShortIDs():
self.prefilled_txn = []
self.use_witness = False
- if p2pheaders_and_shortids != None:
+ if p2pheaders_and_shortids is not None:
self.header = p2pheaders_and_shortids.header
self.nonce = p2pheaders_and_shortids.nonce
self.shortids = p2pheaders_and_shortids.shortids
@@ -778,11 +819,12 @@ class HeaderAndShortIDs():
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):
self.blockhash = blockhash
- self.indexes = indexes if indexes != None else []
+ self.indexes = indexes if indexes is not None else []
def deserialize(self, f):
self.blockhash = deser_uint256(f)
@@ -818,11 +860,12 @@ class BlockTransactionsRequest():
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):
self.blockhash = blockhash
- self.transactions = transactions if transactions != None else []
+ self.transactions = transactions if transactions is not None else []
def deserialize(self, f):
self.blockhash = deser_uint256(f)
@@ -840,12 +883,14 @@ class BlockTransactions():
def __repr__(self):
return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions))
-class CPartialMerkleTree():
+
+class CPartialMerkleTree:
+ __slots__ = ("nTransactions", "vBits", "vHash")
+
def __init__(self):
self.nTransactions = 0
self.vHash = []
self.vBits = []
- self.fBad = False
def deserialize(self, f):
self.nTransactions = struct.unpack("<i", f.read(4))[0]
@@ -868,7 +913,10 @@ class CPartialMerkleTree():
def __repr__(self):
return "CPartialMerkleTree(nTransactions=%d, vHash=%s, vBits=%s)" % (self.nTransactions, repr(self.vHash), repr(self.vBits))
-class CMerkleBlock():
+
+class CMerkleBlock:
+ __slots__ = ("header", "txn")
+
def __init__(self):
self.header = CBlockHeader()
self.txn = CPartialMerkleTree()
@@ -888,7 +936,9 @@ class CMerkleBlock():
# 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"
def __init__(self):
@@ -945,7 +995,8 @@ class msg_version():
self.strSubVer, self.nStartingHeight, self.nRelay)
-class msg_verack():
+class msg_verack:
+ __slots__ = ()
command = b"verack"
def __init__(self):
@@ -961,7 +1012,8 @@ class msg_verack():
return "msg_verack()"
-class msg_addr():
+class msg_addr:
+ __slots__ = ("addrs",)
command = b"addr"
def __init__(self):
@@ -977,7 +1029,8 @@ class msg_addr():
return "msg_addr(addrs=%s)" % (repr(self.addrs))
-class msg_inv():
+class msg_inv:
+ __slots__ = ("inv",)
command = b"inv"
def __init__(self, inv=None):
@@ -996,11 +1049,12 @@ class msg_inv():
return "msg_inv(inv=%s)" % (repr(self.inv))
-class msg_getdata():
+class msg_getdata:
+ __slots__ = ("inv",)
command = b"getdata"
def __init__(self, inv=None):
- self.inv = inv if inv != None else []
+ self.inv = inv if inv is not None else []
def deserialize(self, f):
self.inv = deser_vector(f, CInv)
@@ -1012,7 +1066,8 @@ class msg_getdata():
return "msg_getdata(inv=%s)" % (repr(self.inv))
-class msg_getblocks():
+class msg_getblocks:
+ __slots__ = ("locator", "hashstop")
command = b"getblocks"
def __init__(self):
@@ -1035,7 +1090,8 @@ class msg_getblocks():
% (repr(self.locator), self.hashstop)
-class msg_tx():
+class msg_tx:
+ __slots__ = ("tx",)
command = b"tx"
def __init__(self, tx=CTransaction()):
@@ -1050,13 +1106,16 @@ class msg_tx():
def __repr__(self):
return "msg_tx(tx=%s)" % (repr(self.tx))
+
class msg_witness_tx(msg_tx):
+ __slots__ = ()
def serialize(self):
return self.tx.serialize_with_witness()
-class msg_block():
+class msg_block:
+ __slots__ = ("block",)
command = b"block"
def __init__(self, block=None):
@@ -1074,9 +1133,12 @@ class msg_block():
def __repr__(self):
return "msg_block(block=%s)" % (repr(self.block))
+
# 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
-class msg_generic():
+class msg_generic:
+ __slots__ = ("command", "data")
+
def __init__(self, command, data=None):
self.command = command
self.data = data
@@ -1087,13 +1149,16 @@ class msg_generic():
def __repr__(self):
return "msg_generic()"
-class msg_witness_block(msg_block):
+class msg_witness_block(msg_block):
+ __slots__ = ()
def serialize(self):
r = self.block.serialize(with_witness=True)
return r
-class msg_getaddr():
+
+class msg_getaddr:
+ __slots__ = ()
command = b"getaddr"
def __init__(self):
@@ -1109,7 +1174,8 @@ class msg_getaddr():
return "msg_getaddr()"
-class msg_ping():
+class msg_ping:
+ __slots__ = ("nonce",)
command = b"ping"
def __init__(self, nonce=0):
@@ -1127,7 +1193,8 @@ class msg_ping():
return "msg_ping(nonce=%08x)" % self.nonce
-class msg_pong():
+class msg_pong:
+ __slots__ = ("nonce",)
command = b"pong"
def __init__(self, nonce=0):
@@ -1145,7 +1212,8 @@ class msg_pong():
return "msg_pong(nonce=%08x)" % self.nonce
-class msg_mempool():
+class msg_mempool:
+ __slots__ = ()
command = b"mempool"
def __init__(self):
@@ -1160,7 +1228,26 @@ class msg_mempool():
def __repr__(self):
return "msg_mempool()"
-class msg_sendheaders():
+
+class msg_notfound:
+ __slots__ = ("vec", )
+ command = b"notfound"
+
+ def __init__(self, vec=None):
+ self.vec = vec or []
+
+ def deserialize(self, f):
+ self.vec = deser_vector(f, CInv)
+
+ def serialize(self):
+ return ser_vector(self.vec)
+
+ def __repr__(self):
+ return "msg_notfound(vec=%s)" % (repr(self.vec))
+
+
+class msg_sendheaders:
+ __slots__ = ()
command = b"sendheaders"
def __init__(self):
@@ -1180,7 +1267,8 @@ class msg_sendheaders():
# number of entries
# vector of hashes
# 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"
def __init__(self):
@@ -1205,7 +1293,8 @@ class msg_getheaders():
# headers message has
# <count> <vector of block headers>
-class msg_headers():
+class msg_headers:
+ __slots__ = ("headers",)
command = b"headers"
def __init__(self, headers=None):
@@ -1225,7 +1314,8 @@ class msg_headers():
return "msg_headers(headers=%s)" % repr(self.headers)
-class msg_reject():
+class msg_reject:
+ __slots__ = ("code", "data", "message", "reason")
command = b"reject"
REJECT_MALFORMED = 1
@@ -1256,7 +1346,9 @@ class msg_reject():
return "msg_reject: %s %d %s [%064x]" \
% (self.message, self.code, self.reason, self.data)
-class msg_feefilter():
+
+class msg_feefilter:
+ __slots__ = ("feerate",)
command = b"feefilter"
def __init__(self, feerate=0):
@@ -1273,7 +1365,9 @@ class msg_feefilter():
def __repr__(self):
return "msg_feefilter(feerate=%08x)" % self.feerate
-class msg_sendcmpct():
+
+class msg_sendcmpct:
+ __slots__ = ("announce", "version")
command = b"sendcmpct"
def __init__(self):
@@ -1293,7 +1387,9 @@ class msg_sendcmpct():
def __repr__(self):
return "msg_sendcmpct(announce=%s, version=%lu)" % (self.announce, self.version)
-class msg_cmpctblock():
+
+class msg_cmpctblock:
+ __slots__ = ("header_and_shortids",)
command = b"cmpctblock"
def __init__(self, header_and_shortids = None):
@@ -1311,7 +1407,9 @@ class msg_cmpctblock():
def __repr__(self):
return "msg_cmpctblock(HeaderAndShortIDs=%s)" % repr(self.header_and_shortids)
-class msg_getblocktxn():
+
+class msg_getblocktxn:
+ __slots__ = ("block_txn_request",)
command = b"getblocktxn"
def __init__(self):
@@ -1329,7 +1427,9 @@ class msg_getblocktxn():
def __repr__(self):
return "msg_getblocktxn(block_txn_request=%s)" % (repr(self.block_txn_request))
-class msg_blocktxn():
+
+class msg_blocktxn:
+ __slots__ = ("block_transactions",)
command = b"blocktxn"
def __init__(self):
@@ -1346,7 +1446,10 @@ class msg_blocktxn():
def __repr__(self):
return "msg_blocktxn(block_transactions=%s)" % (repr(self.block_transactions))
+
class msg_witness_blocktxn(msg_blocktxn):
+ __slots__ = ()
+
def serialize(self):
r = b""
r += self.block_transactions.serialize(with_witness=True)