def verify_eth_getProof_inclusion(proof, root): trie_root = Binary.fixed_length(32, allow_empty=True) hash32 = Binary.fixed_length(32) class _Account(rlp.Serializable): fields = [('nonce', big_endian_int), ('balance', big_endian_int), ('storage', trie_root), ('code_hash', hash32)] acc = _Account(proof.nonce, proof.balance, proof.storageHash, proof.codeHash) rlp_account = rlp.encode(acc) trie_key = keccak(bytes.fromhex(proof.address[2:])) assert rlp_account == HexaryTrie.get_from_proof( root, trie_key, format_proof_nodes( proof.accountProof)), "Failed to verify account proof {}".format( proof.address) for storage_proof in proof.storageProof: trie_key = keccak(pad_bytes(b'\x00', 32, storage_proof.key)) root = proof.storageHash if storage_proof.value == b'\x00': rlp_value = b'' else: rlp_value = rlp.encode(storage_proof.value) assert rlp_value == HexaryTrie.get_from_proof( root, trie_key, format_proof_nodes(storage_proof.proof) ), "Failed to verify storage proof {}".format(storage_proof.key) return True
def verify_eth_get_proof(self, proof, root): values = [] trie_root = Binary.fixed_length(32, allow_empty=True) hash32 = Binary.fixed_length(32) class _Account(rlp.Serializable): fields = [('nonce', big_endian_int), ('balance', big_endian_int), ('storage', trie_root), ('code_hash', hash32)] acc = _Account(proof.nonce, proof.balance, proof.storageHash, proof.codeHash) rlp_account = rlp.encode(acc) trie_key = keccak(bytes.fromhex(proof.address[2:])) if rlp_account != HexaryTrie.get_from_proof( root, trie_key, self.format_proof_nodes(proof.accountProof)): return False for storage_proof in proof.storageProof: trie_key = keccak(pad_bytes(b'\x00', 32, storage_proof.key)) root = proof.storageHash if storage_proof.value == b'\x00': rlp_value = b'' else: rlp_value = rlp.encode(storage_proof.value) if rlp_value != HexaryTrie.get_from_proof( root, trie_key, self.format_proof_nodes( storage_proof.proof)): return False else: values.append( {storage_proof.key.hex(): storage_proof.value.hex()}) return True, values
async def get_account(self, block_hash: Hash32, address: Address) -> Account: peer = cast(LESPeer, self.peer_pool.highest_td_peer) key = keccak(address) proof = await self._get_proof(peer, block_hash, account_key=b'', key=key) header = await self._get_block_header_by_hash(peer, block_hash) rlp_account = HexaryTrie.get_from_proof(header.state_root, key, proof) return rlp.decode(rlp_account, sedes=Account)
async def get_account( self, block_hash: bytes, address: bytes, cancel_token: CancelToken) -> Account: key = keccak(address) proof = await self._get_proof(cancel_token, block_hash, account_key=b'', key=key) header = await self.get_block_header_by_hash(block_hash, cancel_token) rlp_account = HexaryTrie.get_from_proof(header.state_root, key, proof) return rlp.decode(rlp_account, sedes=Account)
async def get_account(self, block_hash: bytes, address: bytes) -> Account: key = keccak(address) proof = await self._get_proof(block_hash, account_key=b'', key=key) block = await self.get_block_by_hash(block_hash) rlp_account = HexaryTrie.get_from_proof(block.header.state_root, key, proof) return rlp.decode(rlp_account, sedes=Account)
async def _get_account_from_peer( self, block_hash: Hash32, address: ETHAddress, peer: LESPeer) -> Account: key = keccak(address) proof = await self._get_proof(peer, block_hash, account_key=b'', key=key) header = await self._get_block_header_by_hash(block_hash, peer) try: rlp_account = HexaryTrie.get_from_proof(header.state_root, key, proof) except BadTrieProof as exc: raise BadLESResponse( f"Peer {peer} returned an invalid proof for account {encode_hex(address)} " f"at block {encode_hex(block_hash)}" ) from exc return rlp.decode(rlp_account, sedes=Account)
def verify_transaction_hash(self, block_info, tx_hash): txns = block_info.transactions tx_index = 0 # generate the mpt mpt = HexaryTrie(db={}) for tx_dict in txns: if tx_dict.hash == tx_hash: tx_index = tx_dict.transactionIndex key = rlp.encode(utils.parse_as_int(tx_dict['transactionIndex'])) mpt.set(key, self.rlp_transaction(tx_dict)) # verify the tx root if mpt.root_hash != normalize_bytes(block_info.transactionsRoot): return False # generate the proof mpt_key_nibbles = bytes_to_nibbles(rlp.encode(tx_index)) proof = tuple(self.generate_proof(mpt, mpt_key_nibbles)) if HexaryTrie.get_from_proof(mpt.root_hash, rlp.encode(utils.parse_as_int(tx_index)), proof) \ != self.rlp_transaction(txns[tx_index]): return False return True
def verify_eth_get_proof(proof, root): trie_root = Binary.fixed_length(32, allow_empty=True) hash32 = Binary.fixed_length(32) class _Account(rlp.Serializable): fields = [('nonce', big_endian_int), ('balance', big_endian_int), ('storage', trie_root), ('code_hash', hash32)] acc = _Account(proof.nonce, proof.balance, w3.toBytes(hexstr=w3.toHex(proof.storageHash)), w3.toBytes(hexstr=w3.toHex(proof.codeHash))) rlp_account = rlp.encode(acc) trie_key = keccak(w3.toBytes(hexstr=proof.address)) trie_proof = format_proof_nodes(proof.accountProof) leaf = HexaryTrie.get_from_proof(root, trie_key, trie_proof) if acc == b'': print("Verify that the account does not exist") else: assert rlp_account == leaf, "Failed to verify account proof {}".format( proof.address) print("Succeed to verify account proof {}".format(proof.address)) return True
txs.append(raw_tx) trie.set(rlp.encode(key), rlp_tx) # print(rlp_tx) assert block.transactionsRoot == trie.root_hash print(w3.toHex(trie.root_hash)) # Generate Merkle tree proof for per each node proofs = [] for key in range(B): proof = trie.get_proof(rlp.encode(key)) proofs.append(proof) # Verify Merkle tree proof for per each node nodes = [] for key in range(B): node = HexaryTrie.get_from_proof(trie.root_hash, rlp.encode(key), proofs[key]) nodes.append(node) assert nodes[key] == rlp.encode(txs[key]) print("proof of key %d:" % key, proofs[key], nodes[key]) print(True) proof = proofs[3] print(proof) print(proof[0]) print(w3.toHex(rlp.encode(proof[0]))) print(w3.toHex(keccak(rlp.encode(proof[0])))) print(proof[1]) print(w3.toHex(rlp.encode(proof[1]))) print(keccak(rlp.encode(proof[1])))
def assert_proof(trie, key): proof = trie.get_proof(key) proof_value = HexaryTrie.get_from_proof(trie.root_hash, key, proof) assert proof_value == trie.get(key)
trie.set(rlp.encode(2), rlp.encode("TWO")) print(w3.toHex(trie.root_hash)) print(w3.toHex(keccak(rlp.encode(trie.get_node(trie.root_hash))))) assert trie.root_hash == keccak(rlp.encode(trie.get_node(trie.root_hash))) print(trie.get_node(trie.root_hash)) trie.set(rlp.encode(3), rlp.encode("THREE")) print(w3.toHex(trie.root_hash)) print(w3.toHex(keccak(rlp.encode(trie.get_node(trie.root_hash))))) assert trie.root_hash == keccak(rlp.encode(trie.get_node(trie.root_hash))) print(trie.get_node(trie.root_hash)) proof = trie.get_proof(rlp.encode(1)) assert HexaryTrie.get_from_proof(trie.root_hash, rlp.encode(1), proof) == rlp.encode("ONE") print(proof) proof = trie.get_proof(rlp.encode(2)) assert HexaryTrie.get_from_proof(trie.root_hash, rlp.encode(2), proof) == rlp.encode("TWO") print(proof) proof = trie.get_proof(rlp.encode(3)) assert HexaryTrie.get_from_proof(trie.root_hash, rlp.encode(3), proof) == rlp.encode("THREE") print(proof) #([b'\x10', b'\xae\xa5\xd0\x99\xdd\xe25gVx\xdcu\xd5\xecAC]w\xa7E\xcd=\xb20)\xb3\xaa\xf6Jy~\xdd'], # [b'', [b' ', b'\x83ONE'], [b' ', b'\x83TWO'], [b' ', b'\x85THREE'], b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b''], # [b' ', b'\x85THREE']) print(proof[0]) print(w3.toHex(rlp.encode(proof[0])))