Skip to content

Commit 86ed316

Browse files
committed
Add python implementation of dynafed block serialization
1 parent 7ec6c53 commit 86ed316

File tree

1 file changed

+133
-8
lines changed

1 file changed

+133
-8
lines changed

test/functional/test_framework/messages.py

Lines changed: 133 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -835,9 +835,101 @@ def __repr__(self):
835835
return "CProof(challenge=%s solution=%s)" \
836836
% (self.challenge, self.solution)
837837

838+
class ConsensusParamEntry:
839+
__slots__ = ("m_serialize_type", "m_signblockscript", "m_sbs_wit_limit", "m_fedpegscript", "m_extension_space")
840+
841+
# Constructor args will define serialization type:
842+
# null = 0
843+
# signblock-related fields = 1, required for m_current on non-epoch-starts
844+
# all fields = 2, required for epoch starts
845+
def __init__(self, m_signblockscript=b"", m_sbs_wit_limit=0, m_fedpegscript=b"", m_extension_space=[]):
846+
self.m_signblockscript = m_signblockscript
847+
self.m_sbs_wit_limit = m_sbs_wit_limit
848+
self.m_fedpegscript = m_fedpegscript
849+
self.m_extension_space = m_extension_space
850+
if self.is_null():
851+
self.m_serialize_type = 0
852+
elif m_fedpegscript==b"" and m_extension_space == []:
853+
self.m_serialize_type = 1
854+
else:
855+
self.m_serialize_type = 2
856+
857+
def set_null(self):
858+
self.m_signblockscript = b""
859+
self.m_sbs_wit_limit = 0
860+
self.m_fedpegscript = b""
861+
self.m_extension_space = []
862+
self.m_serialize_type = 0
863+
864+
def is_null(self):
865+
return self.m_signblockscript == b"" and self.m_sbs_wit_limit == 0 and \
866+
self.m_fedpegscript == b"" and self.m_extension_space == []
867+
868+
def serialize(self):
869+
r = b""
870+
r += struct.pack("B", self.m_serialize_type)
871+
if self.m_serialize_type == 1:
872+
r += ser_string(self.m_signblockscript)
873+
r += struct.pack("<I", self.m_sbs_wit_limit)
874+
elif self.m_serialize_type == 2:
875+
r += ser_string(self.m_signblockscript)
876+
r += struct.pack("<I", self.m_sbs_wit_limit)
877+
r += ser_string(self.m_fedpegscript)
878+
r += ser_string_vector(self.m_extension_space)
879+
elif self.m_serialize_type > 2:
880+
raise Exception("Invalid serialization type for ConsensusParamEntry")
881+
return r
882+
883+
def deserialize(self, f):
884+
self.m_serialize_type = struct.unpack("B", f.read(1))[0]
885+
if self.m_serialize_type == 1:
886+
self.m_signblockscript = deser_string(f)
887+
self.m_sbs_wit_limit = struct.unpack("<I", f.read(4))[0]
888+
elif self.m_serialize_type == 2:
889+
self.m_signblockscript = deser_string(f)
890+
self.m_sbs_wit_limit = struct.unpack("<I", f.read(4))[0]
891+
self.m_fedpegscript = deser_string(f)
892+
self.m_extension_space = deser_string_vector(f)
893+
894+
def __repr__(self):
895+
return "ConsensusParamEntry(m_signblockscript=%s m_fedpegscript=%s m_extension_space=%s)" \
896+
% (self.m_signblockscript, self.m_fedpegscript, self.m_extension_space)
897+
898+
class DynaFedParams:
899+
__slots__ = ("m_current", "m_proposed")
900+
901+
def __init__(self, m_current=ConsensusParamEntry(), m_proposed=ConsensusParamEntry()):
902+
self.m_current = m_current
903+
self.m_proposed = m_proposed
904+
905+
def set_null(self):
906+
self.m_current.set_null()
907+
self.m_proposed.set_null()
908+
909+
def is_null(self):
910+
return self.m_current.is_null() and self.m_proposed.is_null()
911+
912+
def serialize(self):
913+
r = b""
914+
r += self.m_current.serialize()
915+
r += self.m_proposed.serialize()
916+
return r
917+
918+
def deserialize(self, f):
919+
self.m_current.deserialize(f)
920+
self.m_proposed.deserialize(f)
921+
922+
def __repr__(self):
923+
return "DynaFedParams(m_current=%s m_proposed=%s)" \
924+
% (self.m_current, self.m_proposed)
925+
926+
927+
HEADER_HF_BIT = 1 << 31
928+
HEADER_HF_MASK = 0x7fffffff
838929
class CBlockHeader:
839930
__slots__ = ("hash", "hashMerkleRoot", "hashPrevBlock", "nBits", "nNonce",
840-
"nTime", "nVersion", "sha256", "block_height", "proof")
931+
"nTime", "nVersion", "sha256", "block_height", "proof", "m_dyna_params",
932+
"m_signblock_witness")
841933

842934
def __init__(self, header=None):
843935
if header is None:
@@ -851,6 +943,8 @@ def __init__(self, header=None):
851943
self.proof = header.proof
852944
self.sha256 = header.sha256
853945
self.hash = header.hash
946+
self.m_dyna_params = header.m_dyna_params
947+
self.m_signblock_witness = header.m_signblock_witness
854948
self.calc_sha256()
855949

856950
def set_null(self):
@@ -860,38 +954,69 @@ def set_null(self):
860954
self.nTime = 0
861955
self.block_height = 0
862956
self.proof = CProof()
957+
self.m_dyna_params = DynaFedParams()
958+
self.m_signblock_witness = CScriptWitness()
863959
self.sha256 = None
864960
self.hash = None
865961

866962
def deserialize(self, f):
867963
self.nVersion = struct.unpack("<i", f.read(4))[0]
964+
is_dyna = False
965+
966+
if self.nVersion < 0:
967+
is_dyna = True
968+
self.nVersion = HEADER_HF_MASK & self.nVersion
969+
868970
self.hashPrevBlock = deser_uint256(f)
869971
self.hashMerkleRoot = deser_uint256(f)
870972
self.nTime = struct.unpack("<I", f.read(4))[0]
871973
self.block_height = struct.unpack("<I", f.read(4))[0]
872-
self.proof.deserialize(f)
974+
if is_dyna:
975+
self.m_dyna_params.deserialize(f)
976+
self.m_signblock_witness.stack = deser_string_vector(f)
977+
else:
978+
self.proof.deserialize(f)
873979
self.sha256 = None
874980
self.hash = None
875981

876982
def serialize(self):
877983
r = b""
878-
r += struct.pack("<i", self.nVersion)
984+
nVersion = self.nVersion
985+
is_dyna = False
986+
if not self.m_dyna_params.is_null():
987+
nVersion -= HEADER_HF_BIT
988+
is_dyna = True
989+
990+
r += struct.pack("<i", nVersion)
879991
r += ser_uint256(self.hashPrevBlock)
880992
r += ser_uint256(self.hashMerkleRoot)
881993
r += struct.pack("<I", self.nTime)
882994
r += struct.pack("<I", self.block_height)
883-
r += self.proof.serialize()
995+
if is_dyna:
996+
r += self.m_dyna_params.serialize()
997+
r += ser_string_vector(self.m_signblock_witness.stack)
998+
else:
999+
r += self.proof.serialize()
8841000
return r
8851001

8861002
def calc_sha256(self):
8871003
if self.sha256 is None:
1004+
nVersion = self.nVersion
1005+
is_dyna = False
1006+
if not self.m_dyna_params.is_null():
1007+
nVersion -= HEADER_HF_BIT
1008+
is_dyna = True
1009+
8881010
r = b""
889-
r += struct.pack("<i", self.nVersion)
1011+
r += struct.pack("<i", nVersion)
8901012
r += ser_uint256(self.hashPrevBlock)
8911013
r += ser_uint256(self.hashMerkleRoot)
8921014
r += struct.pack("<I", self.nTime)
8931015
r += struct.pack("<I", self.block_height)
894-
r += self.proof.serialize_for_hash()
1016+
if is_dyna:
1017+
r += self.m_dyna_params.serialize()
1018+
else:
1019+
r += self.proof.serialize_for_hash()
8951020
self.sha256 = uint256_from_str(hash256(r))
8961021
self.hash = encode(hash256(r)[::-1], 'hex_codec').decode('ascii')
8971022

@@ -976,9 +1101,9 @@ def solve(self):
9761101
# self.rehash()
9771102

9781103
def __repr__(self):
979-
return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s vtx=%s)" \
1104+
return "CBlock(nVersion=%i hashPrevBlock=%064x hashMerkleRoot=%064x nTime=%s vtx=%s m_dyna_params=%s)" \
9801105
% (self.nVersion, self.hashPrevBlock, self.hashMerkleRoot,
981-
time.ctime(self.nTime), repr(self.vtx))
1106+
time.ctime(self.nTime), repr(self.vtx), self.m_dyna_params)
9821107

9831108

9841109
class PrefilledTransaction:

0 commit comments

Comments
 (0)