class Order(rlp.Serializable): fields = [ ('id', BigEndianInt(8)), ('buy_token', raw), ('buy_amount', BigEndianInt(8)), ('sell_token', raw), ('sell_amount', BigEndianInt(8)), ]
class Receipt(rlp.Serializable): fields = [ ('state_root', binary), ('gas_used', big_endian_int), # TODO: this is actually the cumulative gas used. fix it. ('bloom', int256), ('logs', CountableList(Log)), ('contract_address', Binary.fixed_length(20, allow_empty=True)), ('contract_full_shard_id', BigEndianInt(4)), ] def __init__(self, state_root, gas_used, logs, contract_address, contract_full_shard_id, bloom=None): # does not call super.__init__ as bloom should not be an attribute but # a property self.state_root = state_root self.gas_used = gas_used self.logs = logs if bloom is not None and bloom != self.bloom: raise ValueError("Invalid bloom filter") self.contract_address = contract_address self.contract_full_shard_id = contract_full_shard_id self._cached_rlp = None self._mutable = True @property def bloom(self): bloomables = [x.bloomables() for x in self.logs] return bloom.bloom_from_list(utils.flatten(bloomables))
class Log(rlp.Serializable): # TODO: original version used zpad (here replaced by int32.serialize); had # comment "why zpad"? fields = [ ("address", Binary.fixed_length(20, allow_empty=True)), ("topics", CountableList(BigEndianInt(32))), ("data", binary), ] def __init__(self, address, topics, data): if len(address) == 40: address = decode_hex(address) assert len(address) == 20 super(Log, self).__init__(address, topics, data) def bloomables(self): return [self.address] + [BigEndianInt(32).serialize(x) for x in self.topics] def to_dict(self): return { "bloom": encode_hex(bloom.b64(bloom.bloom_from_list(self.bloomables()))), "address": encode_hex(self.address), "data": b"0x" + encode_hex(self.data), "topics": [encode_hex(utils.int32.serialize(t)) for t in self.topics], } def __repr__(self): return "<Log(address=%r, topics=%r, data=%r)>" % ( encode_hex(self.address), self.topics, self.data, )
def test_fixedlength(): s = BigEndianInt(4) for i in (0, 1, 255, 256, 256**3, 256**4 - 1): assert len(s.serialize(i)) == 4 assert s.deserialize(s.serialize(i)) == i for i in (256**4, 256**4 + 1, 256**5, -1, -256, 'asdf'): with pytest.raises(SerializationError): s.serialize(i)
class Receipt(rlp.Serializable): fields = [ ("state_root", binary), ( "gas_used", big_endian_int, ), # TODO: this is actually the cumulative gas used. fix it. ("bloom", int256), ("logs", CountableList(Log)), ("contract_address", Binary.fixed_length(20, allow_empty=True)), ("contract_full_shard_key", BigEndianInt(4)), ] @property def bloom(self): bloomables = [x.bloomables() for x in self.logs] return bloom.bloom_from_list(utils.flatten(bloomables))
class Route(rlp.Serializable): fields = [ ('left_order', BigEndianInt(8)), ('left_amount', BigEndianInt(8)), ('right_order', BigEndianInt(8)), ]
from rlp.sedes import ( BigEndianInt, Binary, ) hash32 = Binary.fixed_length(32) uint24 = BigEndianInt(24) uint64 = BigEndianInt(64) uint384 = BigEndianInt(384)
from rlp.sedes import ( BigEndianInt, Binary, ) address = Binary.fixed_length(20, allow_empty=True) hash32 = Binary.fixed_length(32) uint32 = BigEndianInt(32) uint256 = BigEndianInt(256) trie_root = Binary.fixed_length(32, allow_empty=True)
from rlp.sedes import ( BigEndianInt, Binary, ) hash32 = Binary.fixed_length(32) uint64 = BigEndianInt(64)
def bloomables(self): return [self.address ] + [BigEndianInt(32).serialize(x) for x in self.topics]
def mk_rlp(): from rlp.sedes import ( BigEndianInt, Binary, big_endian_int, binary, CountableList, ) # # RLP # address = Binary.fixed_length(20, allow_empty=True) hash32 = Binary.fixed_length(32) uint32 = BigEndianInt(32) uint256 = BigEndianInt(256) trie_root = Binary.fixed_length(32, allow_empty=True) class BlockHeader(rlp.Serializable): fields = [('parent_hash', hash32), ('uncles_hash', hash32), ('coinbase', address), ('state_root', trie_root), ('transaction_root', trie_root), ('receipt_root', trie_root), ('bloom', uint256), ('difficulty', big_endian_int), ('block_number', big_endian_int), ('gas_limit', big_endian_int), ('gas_used', big_endian_int), ('timestamp', big_endian_int), ('extra_data', binary), ('mix_hash', binary), ('nonce', Binary(8, allow_empty=True))] class Transaction(rlp.Serializable): fields = [ ('nonce', big_endian_int), ('gas_price', big_endian_int), ('gas', big_endian_int), ('to', address), ('value', big_endian_int), ('data', binary), ('v', big_endian_int), ('r', big_endian_int), ('s', big_endian_int), ] class Block(rlp.Serializable): fields = [('header', BlockHeader), ('transactions', CountableList(Transaction)), ('uncles', CountableList(BlockHeader))] class Log(rlp.Serializable): fields = [('address', address), ('topics', CountableList(uint32)), ('data', binary)] class Receipt(rlp.Serializable): fields = [('state_root', binary), ('gas_used', big_endian_int), ('bloom', uint256), ('logs', CountableList(Log))] class Account(rlp.Serializable): fields = [('nonce', big_endian_int), ('balance', big_endian_int), ('storage_root', trie_root), ('code_hash', hash32)] class MiniAccount(rlp.Serializable): fields = [('nonce', big_endian_int), ('balance', big_endian_int), ('storage_root', trie_root), ('code_hash', trie_root)] class Address(rlp.Serializable): fields = [ ('sender_ip', binary), ('sender_udp_port', big_endian_int), ('sender_tcp_port', big_endian_int), ] class Ping(rlp.Serializable): fields = [ ('version', big_endian_int), ('from', Address), ('to', Address), ('expiration', big_endian_int), ] class Pong(rlp.Serializable): fields = [ ('to', Address), ('ping_hash', binary), ('expiration', big_endian_int), ] class FindNode(rlp.Serializable): fields = [ ('target', binary), ('expiration', big_endian_int), ] class Neighbour(rlp.Serializable): fields = [ ('ip', binary), ('udp_port', big_endian_int), ('tcp_port', big_endian_int), ('node_id', binary), ] class Neighbours(rlp.Serializable): fields = [ ('nodes', CountableList(Neighbour)), ('expiration', big_endian_int), ] return BlockHeader, Block, Receipt, CountableList( Receipt ), Account, MiniAccount, Ping, Pong, FindNode, Neighbours # noqa: E501
class Transaction(rlp.Serializable): fields = [ ('nonce', big_endian_int), ('category', big_endian_int), ('to', address), ('afi', BigEndianInt(1)), ('value', binary), ('metadata', raw), ('time', big_endian_int), ('v', big_endian_int), ('r', big_endian_int), ('s', big_endian_int), ] _sender = None def __init__(self, nonce, category, to, afi, value, metadata=b'', time=0, v=0, r=0, s=0): if category == 0 or category == 1: if metadata != b'': raise InvalidTransaction("Invalid Metadata") metadata = b'' elif category == 2: if type(metadata) == list and len(metadata) % 3 == 0: _metadata = [] _afi = 0 if type(metadata[0]) == bytes: _bytes = True elif type(metadata[0]) == int: _bytes = False else: raise InvalidTransaction("Invalid Metadata") i = 0 while i < len(metadata): try: if _bytes: _afi = bytes_to_int(metadata[i]) _metadata.append(metadata[i]) else: _afi = metadata[i] _metadata.append(encode_int8(metadata[i])) if _afi != 1 and _afi != 2: raise InvalidTransaction("Invalid Metadata AFI") except: raise InvalidTransaction("Invalid Metadata AFI") try: if _bytes: if _afi == 1: ip = IPv4Address(Bytes(metadata[i + 1])) else: ip = IPv6Address(Bytes(metadata[i + 1])) _metadata.append(bytes(ip.packed)) addr = normalize_address(metadata[i + 2], allow_blank=True) _metadata.append(addr) else: if _afi == 1: ip = IPv4Address(metadata[i + 1]) else: ip = IPv6Address(metadata[i + 1]) _metadata.append(bytes(ip.packed)) addr = normalize_address(metadata[i + 2], allow_blank=True) _metadata.append(addr) i += 3 except: raise InvalidTransaction("Invalid Metadata") metadata = _metadata else: raise InvalidTransaction("Invalid Metadata") elif category == 3: if type(metadata) == list and len(metadata) % 4 == 0: _metadata = [] _afi = 0 if type(metadata[0]) == bytes: _bytes = True elif type(metadata[0]) == int: _bytes = False else: raise InvalidTransaction("Invalid Metadata") i = 0 while i < len(metadata): try: if _bytes: _afi = bytes_to_int(metadata[i]) _metadata.append(metadata[i]) else: _afi = metadata[i] _metadata.append(encode_int8(metadata[i])) if _afi != 1 and _afi != 2: raise InvalidTransaction("Invalid Metadata AFI") except: raise InvalidTransaction("Invalid Metadata AFI") try: if _bytes: if _afi == 1: ip = IPv4Address(Bytes(metadata[i + 1])) else: ip = IPv6Address(Bytes(metadata[i + 1])) _metadata.append(bytes(ip.packed)) priority = bytes_to_int(metadata[i + 2]) if priority < 0 or priority > 255: raise InvalidTransaction( "Invalid Metadata Priority") _metadata.append(int_to_bytes(priority)) weight = bytes_to_int(metadata[i + 3]) if weight < 0 or weight > 255: raise InvalidTransaction( "Invalid Metadata Weight") _metadata.append(int_to_bytes(weight)) else: if _afi == 1: ip = IPv4Address(metadata[i + 1]) else: ip = IPv6Address(metadata[i + 1]) _metadata.append(bytes(ip.packed)) priority = metadata[i + 2] if priority < 0 or priority > 255: raise InvalidTransaction( "Invalid Metadata Priority") _metadata.append(int_to_bytes(priority)) weight = metadata[i + 3] if weight < 0 or weight > 255: raise InvalidTransaction( "Invalid Metadata Weight") _metadata.append(int_to_bytes(weight)) i += 4 except: raise InvalidTransaction("Invalid Metadata") metadata = _metadata else: raise InvalidTransaction("Invalid Metadata") else: raise InvalidTransaction("Invalid Category") to = normalize_address(to, allow_blank=True) if afi != 1 and afi != 2: raise InvalidTransaction("Invalid AFI") try: if afi == 1: ipnet = IPv4Network(value) else: ipnet = IPv6Network(value) except: if len(value) == 5: try: ip = IPv4Address(Bytes(value[:4])) ipnet = IPv4Network( str(ip) + '/' + str(bytes_to_int(value[4]))) except: raise InvalidTransaction("Invalid Value") elif len(value) == 17: try: ip = IPv6Address(Bytes(value[:16])) ipnet = IPv6Network( str(ip) + '/' + str(bytes_to_int(value[16]))) except: raise InvalidTransaction("Invalid Value") else: raise InvalidTransaction("Invalid Value") value = bytes(ipnet.packed) + encode_int8(ipnet.prefixlen) super(Transaction, self).__init__(nonce, category, to, afi, value, metadata, time, v, r, s) def hash_message(self, msg): prefix = b'' if self.category == 0: prefix = b'Allocate:\n' elif self.category == 1: prefix = b'Delegate:\n' elif self.category == 2: prefix = b'MapServer:\n' elif self.category == 3: prefix = b'Locator:\n' return sha3( int_to_bytes(len(prefix)) + prefix + int_to_bytes(len(msg)) + msg) @property def sender(self): if not self._sender: if self.r == 0 and self.s == 0: self._sender = null_address else: if self.v in (27, 28): vee = self.v sighash = sha3(rlp.encode(self, UnsignedTransaction)) elif self.v >= 37: vee = self.v - self.network_id * 2 - 8 assert vee in (27, 28) rlpdata = rlp.encode( rlp.infer_sedes(self).serialize(self)[:-3] + [self.network_id, '', '']) sighash = sha3(rlpdata) if self.r >= secpk1n or self.s >= secpk1n or self.r == 0 or self.s == 0: raise InvalidTransaction("Invalid signature values!") pub = ecrecover_to_pub(sighash, self.v, self.r, self.s) if pub == b"\x00" * 64: raise InvalidTransaction( "Invalid signature (zero privkey cannot sign)") self._sender = sha3(pub)[-20:] return self._sender @property def network_id(self): if self.r == 0 and self.s == 0: return self.v elif self.v in (27, 28): return None else: return ((self.v - 1) // 2) - 17 def sign(self, key, network_id=None): if network_id is None: rawhash = sha3(rlp.encode(self, UnsignedTransaction)) else: assert 1 <= network_id < 2**63 - 18 rlpdata = rlp.encode( rlp.infer_sedes(self).serialize(self)[:-3] + [network_id, b'', b'']) rawhash = sha3(rlpdata) key = normalize_key(key) self.v, self.r, self.s = ecsign(rawhash, key) if network_id is not None: self.v += 8 + network_id * 2 self._sender = privtoaddr(key) return self @property def hash(self): return sha3(rlp.encode(self)) @property def ip_network(self): if self.afi == 1: ip = IPv4Address(Bytes(self.value[:4])) ipnet = IPv4Network( str(ip) + '/' + str(bytes_to_int(self.value[4]))) else: ip = IPv6Address(Bytes(self.value[:16])) ipnet = IPv6Network( str(ip) + '/' + str(bytes_to_int(self.value[16]))) return IPNetwork(str(ipnet)) def to_dict(self): d = {} for name, _ in self.__class__.fields: d[name] = getattr(self, name) if name in ('to', ): d[name] = '0x' + encode_hex(d[name]) elif name in ('value', ): if self.afi == 1: ip = IPv4Address(Bytes(d[name][:4])) net = IPv4Network( str(ip) + '/' + str(bytes_to_int(d[name][4]))) d[name] = str(net) else: ip = IPv6Address(Bytes(d[name][:16])) net = IPv6Network( str(ip) + '/' + str(bytes_to_int(d[name][16]))) d[name] = str(net) elif name in ('metadata', ) and self.category == 2: _metadata = [] i = 0 while i < len(d[name]): _metadata.append(bytes_to_int(d[name][i])) if _metadata[-1] == 1: ip = IPv4Address(Bytes(d[name][i + 1])) else: ip = IPv6Address(Bytes(d[name][i + 1])) _metadata.append(str(ip)) _metadata.append(encode_hex(d[name][i + 2])) i += 3 d[name] = _metadata elif name in ('metadata', ) and self.category == 3: _metadata = [] i = 0 while i < len(d[name]): _metadata.append(bytes_to_int(d[name][i])) if _metadata[-1] == 1: ip = IPv4Address(Bytes(d[name][i + 1])) else: ip = IPv6Address(Bytes(d[name][i + 1])) _metadata.append(str(ip)) _metadata.append(bytes_to_int(d[name][i + 2])) _metadata.append(bytes_to_int(d[name][i + 3])) i += 4 d[name] = _metadata d['sender'] = '0x' + encode_hex(self.sender) d['hash'] = '0x' + encode_hex(self.hash) return d
class Receipt(rlp.Serializable): fields = [ ('round', BigEndianInt(8)), ('order_digest', raw), ]
)), "storageKeys": apply_formatter_to_array(hexstr_if_str(to_int)) } ), ), 'maxPriorityFeePerGas': hexstr_if_str(to_int), 'maxFeePerGas': hexstr_if_str(to_int), }, ) # Define typed transaction common sedes. # [[{20 bytes}, [{32 bytes}...]]...], where ... means “zero or more of the thing to the left”. access_list_sede_type = CountableList( List([ Binary.fixed_length(20, allow_empty=False), CountableList(BigEndianInt(32)), ]), ) class _TypedTransactionImplementation(ABC): """ Abstract class that every typed transaction must implement. Should not be imported or used by clients of the library. """ @abstractmethod def hash(self) -> bytes: pass @abstractmethod def payload(self) -> bytes:
from rlp.sedes import ( BigEndianInt, Binary, ) from eth.constants import ( COLLATION_SIZE, ) address = Binary.fixed_length(20, allow_empty=True) collation_body = Binary.fixed_length(COLLATION_SIZE) hash32 = Binary.fixed_length(32) int16 = BigEndianInt(16) int24 = BigEndianInt(24) int32 = BigEndianInt(32) int64 = BigEndianInt(64) int128 = BigEndianInt(128) int256 = BigEndianInt(256) trie_root = Binary.fixed_length(32, allow_empty=True)
class Transaction(rlp.Serializable): """ A transaction is stored as: [nonce, gasprice, startgas, to, value, data, v, r, s] nonce is the number of transactions already sent by that account, encoded in binary form (eg. 0 -> '', 7 -> '\x07', 1000 -> '\x03\xd8'). (v,r,s) is the raw Electrum-style signature of the transaction without the signature made with the private key corresponding to the sending account, with 0 <= v <= 3. From an Electrum-style signature (65 bytes) it is possible to extract the public key, and thereby the address, directly. A valid transaction is one where: (i) the signature is well-formed (ie. 0 <= v <= 3, 0 <= r < P, 0 <= s < N, 0 <= r < P - N if v >= 2), and (ii) the sending account has enough funds to pay the fee and the value. There are 3 types of transactions: 1. Value transfer. In-shard transaction if from_full_shard_key and to_full_shard_key refer to the same shard, otherwise it is a cross-shard transaction. 2. Contract creation. 'to' must be empty. from_full_shard_key and to_full_shard_key must refer to the same shard id. The contract address will have the same full shard id as to_full_shard_key. If the contract does not invoke other contract normally the to_full_shard_key should be the same as from_full_shard_key. 3. Contract call. from_full_shard_key and to_full_shard_key must refer to the same shard id based on the current number of shards in the network. It is possible a reshard event would invalidate a tx that was valid before the reshard. """ fields = [ ("nonce", big_endian_int), ("gasprice", big_endian_int), ("startgas", big_endian_int), ("to", utils.address), ("value", big_endian_int), ("data", binary), ("network_id", big_endian_int), ("from_full_shard_key", BigEndianInt(4)), ("to_full_shard_key", BigEndianInt(4)), ("gas_token_id", big_endian_int), ("transfer_token_id", big_endian_int), ("version", big_endian_int), ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ] _sender = None def __init__( self, nonce, gasprice, startgas, to, value, data, gas_token_id, transfer_token_id, v=0, r=0, s=0, from_full_shard_key=0, to_full_shard_key=0, network_id=1, version=0, ): self.quark_chain_config = None to = utils.normalize_address(to, allow_blank=True) super(Transaction, self).__init__( nonce, gasprice, startgas, to, value, data, network_id, from_full_shard_key, to_full_shard_key, gas_token_id, transfer_token_id, version, v, r, s, ) if (self.gasprice >= TT256 or self.startgas >= TT256 or self.value >= TT256 or self.nonce >= TT256): raise InvalidTransaction("Values way too high!") @property def sender(self): if not self._sender: # Determine sender if self.r == 0 and self.s == 0: self._sender = null_address else: if self.r >= secpk1n or self.s >= secpk1n or self.r == 0 or self.s == 0: raise InvalidTransaction("Invalid signature values!") if self.version == 0: pub = ecrecover_to_pub(self.hash_unsigned, self.v, self.r, self.s) if self.version == 1: pub = ecrecover_to_pub(self.hash_typed, self.v, self.r, self.s) if pub == b"\x00" * 64: raise InvalidTransaction( "Invalid signature (zero privkey cannot sign)") self._sender = sha3_256(pub)[-20:] return self._sender @sender.setter def sender(self, value): self._sender = value def sign(self, key, network_id=None): """Sign this transaction with a private key. A potentially already existing signature would be overridden. """ if network_id is not None: self.network_id = network_id key = normalize_key(key) self._in_mutable_context = True self.v, self.r, self.s = ecsign(self.hash_unsigned, key) self.version = 0 self._in_mutable_context = False self._sender = utils.privtoaddr(key) return self @property def hash(self): return sha3_256(rlp.encode(self)) @property def hash_unsigned(self): return sha3_256( rlp.encode(unsigned_tx_from_tx(self), UnsignedTransaction)) @property def hash_typed(self): return bytes.fromhex(typed_signature_hash(tx_to_typed_data(self))[2:]) def to_dict(self): d = {} for name, _ in self.__class__._meta.fields: d[name] = getattr(self, name) if name in ("to", "data"): d[name] = "0x" + encode_hex(d[name]) d["sender"] = "0x" + encode_hex(self.sender) d["hash"] = "0x" + encode_hex(self.hash) return d @property def intrinsic_gas_used(self): num_zero_bytes = str_to_bytes(self.data).count(ascii_chr(0)) num_non_zero_bytes = len(self.data) - num_zero_bytes return (opcodes.GTXCOST + (opcodes.CREATE[3] if not self.to else 0) + opcodes.GTXDATAZERO * num_zero_bytes + opcodes.GTXDATANONZERO * num_non_zero_bytes + (opcodes.GTXXSHARDCOST if self.is_cross_shard else 0)) @property def creates(self): "returns the address of a contract created by this tx" if self.to in (b"", "\0" * 20): return mk_contract_address(self.sender, self.nonce) def set_quark_chain_config(self, quark_chain_config): self.quark_chain_config = quark_chain_config @property def from_chain_id(self): return self.from_full_shard_key >> 16 @property def to_chain_id(self): return self.to_full_shard_key >> 16 @property def from_shard_size(self): check(self.quark_chain_config) return self.quark_chain_config.get_shard_size_by_chain_id( self.from_chain_id) @property def to_shard_size(self): check(self.quark_chain_config) return self.quark_chain_config.get_shard_size_by_chain_id( self.to_chain_id) @property def from_shard_id(self): shard_mask = self.from_shard_size - 1 return self.from_full_shard_key & shard_mask @property def to_shard_id(self): shard_mask = self.to_shard_size - 1 return self.to_full_shard_key & shard_mask @property def from_full_shard_id(self): return self.from_chain_id << 16 | self.from_shard_size | self.from_shard_id @property def to_full_shard_id(self): return self.to_chain_id << 16 | self.to_shard_size | self.to_shard_id @property def is_cross_shard(self): return (self.from_chain_id != self.to_chain_id or self.from_shard_id != self.to_shard_id) def __eq__(self, other): return isinstance(other, self.__class__) and self.hash == other.hash def __lt__(self, other): return isinstance(other, self.__class__) and self.hash < other.hash def __hash__(self): return utils.big_endian_to_int(self.hash) def __ne__(self, other): return not self.__eq__(other) def __repr__(self): return "<Transaction(%s)>" % encode_hex(self.hash)[:4] def __structlog__(self): return encode_hex(self.hash) # This method should be called for block numbers >= HOMESTEAD_FORK_BLKNUM only. # The >= operator is replaced by > because the integer division N/2 always produces the value # which is by 0.5 less than the real N/2 def check_low_s_metropolis(self): if self.s > secpk1n // 2: raise InvalidTransaction("Invalid signature S value!") def check_low_s_homestead(self): if self.s > secpk1n // 2 or self.s == 0: raise InvalidTransaction("Invalid signature S value!")
from hashlib import blake2s blake = lambda x: blake2s(x).digest() from rlp.sedes import big_endian_int, Binary, binary, CountableList, BigEndianInt, Binary int256 = BigEndianInt(256) hash32 = Binary.fixed_length(32) import rlp import bls import random privkeys = [ int.from_bytes(blake(str(i).encode('utf-8')), 'big') for i in range(30) ] keymap = {bls.privtopub(k): k for k in privkeys} class AggregateVote(rlp.Serializable): fields = [('shard_id', int256), ('checkpoint', hash32), ('signer_bitmask', binary), ('aggregate_sig', int256)] def __init__(self, shard_id, checkpoint, signer_bitmask, aggregate_sig): # at the beginning of a method, locals() is a dict of all arguments fields = {k: v for k, v in locals().items() if k != 'self'} super(BlockHeader, self).__init__(**fields) class BeaconBlock(rlp.Serializable): fields = [ # Hash of the parent block ('parent_hash', hash32), # Number of skips (for the full PoS mechanism)
class AccountAccesses(rlp.Serializable): fields = [ ('account', address), ('storage_keys', CountableList(BigEndianInt(32))), ]
class Log(rlp.Serializable): fields = [ ('address', Binary.fixed_length(20, allow_empty=True)), ('topics', CountableList(BigEndianInt(32))), ('data', Binary()) ]
from rlp.sedes import ( BigEndianInt, Binary, ) address = Binary.fixed_length(20, allow_empty=True) hash32 = Binary.fixed_length(32) uint24 = BigEndianInt(24) uint32 = BigEndianInt(32) uint64 = BigEndianInt(64) uint256 = BigEndianInt(256) trie_root = Binary.fixed_length(32, allow_empty=True)
class Denoms(): def __init__(self): self.wei = 1 self.babbage = 10**3 self.lovelace = 10**6 self.shannon = 10**9 self.szabo = 10**12 self.finney = 10**15 self.ether = 10**18 self.turing = 2**256 denoms = Denoms() address = Binary.fixed_length(20, allow_empty=True) int20 = BigEndianInt(20) int32 = BigEndianInt(32) int256 = BigEndianInt(256) hash32 = Binary.fixed_length(32) trie_root = Binary.fixed_length(32, allow_empty=True) class bcolors: HEADER = '\033[95m' OKBLUE = '\033[94m' OKGREEN = '\033[92m' WARNING = '\033[91m' FAIL = '\033[91m' ENDC = '\033[0m' BOLD = '\033[1m' UNDERLINE = '\033[4m'
class Commitment(rlp.Serializable): fields = [ ('round', BigEndianInt(8)), ('merkle_root', raw), ]