Skip to content

Commit 57b086a

Browse files
committed
add proof verification example to docs
1 parent 230b542 commit 57b086a

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

docs/web3.eth.rst

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,72 @@ The following methods are available on the ``web3.eth`` namespace.
235235
]
236236
})
237237
238+
* Merkle proof verification using py-trie.
239+
240+
The following example verifies that the values returned in the AttributeDict are included in the state of given trie ``root``.
241+
242+
.. code-block:: python
243+
244+
from eth_utils import (
245+
keccak,
246+
)
247+
import rlp
248+
from rlp.sedes import (
249+
Binary,
250+
big_endian_int,
251+
)
252+
from trie import (
253+
HexaryTrie,
254+
)
255+
from web3._utils.encoding import (
256+
pad_bytes,
257+
)
258+
259+
def format_proof_nodes(proof):
260+
trie_proof = []
261+
for rlp_node in proof:
262+
trie_proof.append(rlp.decode(bytes(rlp_node)))
263+
return trie_proof
264+
265+
def verify_eth_getProof(proof, root):
266+
trie_root = Binary.fixed_length(32, allow_empty=True)
267+
hash32 = Binary.fixed_length(32)
268+
269+
class _Account(rlp.Serializable):
270+
fields = [
271+
('nonce', big_endian_int),
272+
('balance', big_endian_int),
273+
('storage', trie_root),
274+
('code_hash', hash32)
275+
]
276+
acc = _Account(
277+
proof.nonce, proof.balance, proof.storageHash, proof.codeHash
278+
)
279+
rlp_account = rlp.encode(acc)
280+
trie_key = keccak(bytes.fromhex(proof.address[2:]))
281+
282+
assert rlp_account == HexaryTrie.get_from_proof(
283+
root, trie_key, format_proof_nodes(proof.accountProof)
284+
), "Failed to verify account proof {}".format(proof.address)
285+
286+
for storage_proof in proof.storageProof:
287+
trie_key = keccak(pad_bytes(b'\x00', 32, storage_proof.key))
288+
root = proof.storageHash
289+
if storage_proof.value == b'\x00':
290+
rlp_value = b''
291+
else:
292+
rlp_value = rlp.encode(storage_proof.value)
293+
294+
assert rlp_value == HexaryTrie.get_from_proof(
295+
root, trie_key, format_proof_nodes(storage_proof.proof)
296+
), "Failed to verify storage proof {}".format(storage_proof.key)
297+
298+
return True
299+
300+
block = w3.eth.getBlock(3391)
301+
proof = w3.eth.getProof('0x6c8f2a135f6ed072de4503bd7c4999a1a17f824b', [0, 1], 3391)
302+
assert verify_eth_getProof(proof, block.stateRoot)
303+
238304
239305
.. py:method:: Eth.getCode(account, block_identifier=eth.defaultBlock)
240306

0 commit comments

Comments
 (0)