Skip to content

Commit e74b774

Browse files
committed
Add support for ext_trie_blake2_256_verify_proof host functions
Implement ext_trie_blake2_256_verify_proof_version_1 and _version_2 which were previously stubbed with host_fn_not_implemented!(). These host functions are needed by runtimes that perform Merkle proof verification, such as Polkadot Bulletin Chain's pallet-transaction-storage. The implementation uses smoldot's existing proof_decode module to decode and verify the proof, then looks up the key and compares against the expected value. For state version V1 (version_2 only), hashed storage values (>= 33 bytes) are handled by comparing blake2b hashes.
1 parent 5bb68b3 commit e74b774

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

lib/src/executor/host.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,8 +2108,59 @@ impl ReadyToRun {
21082108
},
21092109
}
21102110
}
2111-
HostFunction::ext_trie_blake2_256_verify_proof_version_1 => host_fn_not_implemented!(),
2112-
HostFunction::ext_trie_blake2_256_verify_proof_version_2 => host_fn_not_implemented!(),
2111+
HostFunction::ext_trie_blake2_256_verify_proof_version_1
2112+
| HostFunction::ext_trie_blake2_256_verify_proof_version_2 => {
2113+
let state_version = if matches!(
2114+
host_fn,
2115+
HostFunction::ext_trie_blake2_256_verify_proof_version_2
2116+
) {
2117+
expect_state_version!(4)
2118+
} else {
2119+
TrieEntryVersion::V0
2120+
};
2121+
2122+
let root = expect_pointer_constant_size!(0, 32);
2123+
let proof = expect_pointer_size!(1).as_ref().to_vec();
2124+
let key = expect_pointer_size!(2).as_ref().to_vec();
2125+
let value = expect_pointer_size!(3).as_ref().to_vec();
2126+
2127+
let outcome = match trie::proof_decode::decode_and_verify_proof(
2128+
trie::proof_decode::Config { proof: &proof },
2129+
) {
2130+
Ok(decoded) => match decoded.trie_node_info(
2131+
&root,
2132+
trie::bytes_to_nibbles(key.iter().copied()),
2133+
) {
2134+
Ok(info) => match info.storage_value {
2135+
trie::proof_decode::StorageValue::Known {
2136+
value: found_value,
2137+
..
2138+
} => found_value == &value[..],
2139+
trie::proof_decode::StorageValue::HashKnownValueMissing(hash) => {
2140+
// The proof contains only the hash of the value.
2141+
// This happens with state version V1 where values
2142+
// >= 33 bytes are stored as their blake2b hash.
2143+
// Verify by hashing the expected value and comparing.
2144+
matches!(state_version, TrieEntryVersion::V1)
2145+
&& *hash
2146+
== <[u8; 32]>::try_from(
2147+
blake2_rfc::blake2b::blake2b(32, &[], &value)
2148+
.as_bytes(),
2149+
)
2150+
.unwrap_or_else(|_| unreachable!())
2151+
}
2152+
trie::proof_decode::StorageValue::None => false,
2153+
},
2154+
Err(_) => false,
2155+
},
2156+
Err(_) => false,
2157+
};
2158+
2159+
HostVm::ReadyToRun(ReadyToRun {
2160+
resume_value: Some(vm::WasmValue::I32(if outcome { 1 } else { 0 })),
2161+
inner: self.inner,
2162+
})
2163+
}
21132164
HostFunction::ext_trie_keccak_256_verify_proof_version_1 => host_fn_not_implemented!(),
21142165
HostFunction::ext_trie_keccak_256_verify_proof_version_2 => host_fn_not_implemented!(),
21152166
HostFunction::ext_misc_print_num_version_1 => {

wasm-node/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Added
6+
7+
- Add support for the `ext_trie_blake2_256_verify_proof_version_1` and `ext_trie_blake2_256_verify_proof_version_2` host functions. These are used by runtimes that perform Merkle proof verification (e.g. Polkadot Bulletin Chain's `pallet-transaction-storage`).
8+
59
## 2.0.40 - 2025-12-02
610

711
### Added

0 commit comments

Comments
 (0)