I'm currently trying to prove a storage entry by verifying the output of getReadProof but am not really sure how to do this.

For some context: I want to query a parachains header from the relay chains storage, and then prove the correctness by using a storage proof. I generate the storage key for the header I'm interested in and query the encoded header. Next, I call getReadProof and receive a proof object.

My question is, how do I verify this thing? I have access to verified headers of the relay chain (and by extension the storage root) but am not sure what to do with it. The proof object kind of looks like a typical merkle path, but the entries have different lengths, so they can't be hashes. They kind of look like storage keys to me, with the padded sections.

1 Answer 1


You can use the read_proof_check method:

read_proof_check(relay_chain_storage_root, proof, keys);

However that only works on the node side.

If you need to do it in the runtime, you can do something like:

let db = proof.into_memory_db();
let res = sp_trie::read_trie_value(&db, &relay_chain_storage_root, parachain_header_key);

match res {
   Ok(value) => // do something with the value,
   Err(err) => // invalid storage proof.
  • Yup, that does it. Thanks for the quick answer! Apr 19, 2022 at 15:27
  • Actually, I have another question. read_trie_value is returning the encoded header, but there are two leading bytes that are not part of the header (0xe902). When I remove them I can decode the header correctly. Any idea what these are? Apr 20, 2022 at 10:47
  • The value in the storage is actually a Vec<u8> that itself contains the encoded header. So, you need to do something like Header::decode(&mut &Vec::<u8>::decode(&mut &data[..])?[..])?.
    – bkchr
    Apr 20, 2022 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.