Skip to content

Add support for ext_trie_blake2_256_verify_proof host functions#2221

Merged
tomaka merged 3 commits into
paritytech:mainfrom
x3c41a:ndk/add-verify-proof-host-functions
Mar 31, 2026
Merged

Add support for ext_trie_blake2_256_verify_proof host functions#2221
tomaka merged 3 commits into
paritytech:mainfrom
x3c41a:ndk/add-verify-proof-host-functions

Conversation

@x3c41a

@x3c41a x3c41a commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Implemented ext_trie_blake2_256_verify_proof_version_1 and _version_2 host functions

Uses the existing proof_decode module to decode and verify the Merkle proof, look up the key, and compare against the expected value. Handles state version V1 where values >= 33 bytes are stored as blake2b hashes.

Motivation

Chopsticks uses smoldot for WASM execution and fails on runtimes that call these host functions (e.g. Polkadot Bulletin Chain's pallet-transaction-storage).

Reference issue - paritytech/polkadot-bulletin-chain#341

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.
@x3c41a
x3c41a force-pushed the ndk/add-verify-proof-host-functions branch from e74b774 to 8b546d7 Compare March 20, 2026 13:16
tomaka
tomaka previously approved these changes Mar 21, 2026

@tomaka tomaka left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thank you!
If you've tried that it works, then it's good to go.

Comment thread wasm-node/CHANGELOG.md Outdated
Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@x3c41a
x3c41a requested a review from tomaka March 31, 2026 09:15
@x3c41a

x3c41a commented Mar 31, 2026

Copy link
Copy Markdown
Contributor Author

@tomaka could you, please, re-approve. The previous approval was discarded by the recent changes

@tomaka
tomaka added this pull request to the merge queue Mar 31, 2026
Merged via the queue into paritytech:main with commit 82b4cf1 Mar 31, 2026
21 checks passed
xlc pushed a commit to AcalaNetwork/chopsticks that referenced this pull request May 18, 2026
* update smoldot

Pulls in paritytech/smoldot-archive#2221, which implements
ext_trie_blake2_256_verify_proof_version_1 and _version_2.

Unblocks runtimes that perform Merkle proof verification, e.g.
Polkadot Bulletin Chain's pallet-transaction-storage.

* bump wasm-pack to 0.15.0

0.14.0's postinstall fetches its binary from `drager/wasm-pack`,
which was wiped and recreated empty on 2026-05-11, breaking every
CI run (404 on the GitHub release download).

0.15.0 fetches from the canonical `wasm-bindgen/wasm-pack` repo.
rockbmb added a commit to rockbmb/smoldot that referenced this pull request May 29, 2026
…dex param types

Implement ext_trie_keccak_256_verify_proof_version_1 and _version_2
using proof_decode, matching the blake2 variants from paritytech#2221.

Fix ext_transaction_index_index_version_1 and
ext_transaction_index_renew_version_1: both used
expect_pointer_size_raw (expects i64) but the actual signatures are
(i32, i32, i32) and (i32, i32). The type mismatch hit unreachable!()
on any runtime that indexes transactions.
x3c41a added a commit to paritytech/smoldot that referenced this pull request Jun 1, 2026
## Background

`pallet-transaction-storage` (deployed on Polkadot Bulletin Chain, runs
every block on paseo-bulletin) calls
`ext_trie_blake2_256_verify_proof_version_2` from its
`apply_block_inherents` inherent. Smoldot stubs both versions with
`host_fn_not_implemented!()`, so chopsticks can't replay any block that
includes the proof inherent — `run-block` panics on the runtime's
`"Storage proof must be checked once in the block"` assertion.

Refs:
- paritytech/polkadot-bulletin-chain#341 — chopsticks issue
- paritytech/smoldot-archive#2221 — earlier attempt in the archived fork
(used the regular Merkle proof decoder, which fails on compact proofs)

## Implementation

The verifier handles Substrate's **compact** proof format
(`sp_trie::generate_trie_proof` → trie-db's `generate_proof`):

- Path children are replaced by an empty inline placeholder; the actual
child node is the next proof entry.
- The target leaf's value is omitted; reconstructed from the
caller-supplied expected value (hashed via blake2b for state version V1
values >= 32 bytes).

`verify_compact_trie_proof` in `trie::proof_decode` walks proof entries
in order, descends into placeholders by consuming the next entry, and
unwinds by re-encoding each node with reconstructed children. The final
root node's hash must equal the caller-supplied root.

## Tests

Seven unit tests cover a real chain proof captured from
`paseo-bulletin-rpc.polkadot.io` block #1503870: positive case + six
rejection cases (wrong root / value / key / state version / tampered
byte / truncated proof).

End-to-end: replaying six ProofChecked-emitting blocks (1503870,
1504069, 1504256, 1504290, 1504307, 1504375) through chopsticks
`run-block` now finalizes cleanly. Previously all panicked.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants