fix(runtime): trie viewer view contract code and call function#15437
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #15437 +/- ##
=======================================
Coverage 69.09% 69.09%
=======================================
Files 936 936
Lines 210309 210355 +46
Branches 210309 210355 +46
=======================================
+ Hits 145314 145355 +41
- Misses 58991 58997 +6
+ Partials 6004 6003 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
0d92ea6 to
7f0573c
Compare
93014d7 to
aa1a154
Compare
8a69c21 to
34f5f40
Compare
…code The ViewCode RPC query used AccountContractAccessExt::code which reads raw bytes from the trie. This returned incorrect results for legacy ETH implicit accounts (magic bytes blob instead of actual wallet contract WASM) and didn't handle all global contract edge cases. Replace with RuntimeContractIdentifier::resolve() which already handles all contract resolution cases correctly. Store chain_id and RuntimeConfigStore on TrieViewer to support the resolution. Also simplify call_function to reuse these stored fields. Co-Authored-By: Claude Opus 4.6 <[email protected]>
34f5f40 to
c89f56e
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the runtime trie viewer to correctly resolve and return executable contract code for all contract types (including legacy ETH implicit wallet accounts and global contracts), and fixes view-function execution to use the runtime config for the queried block’s protocol version.
Changes:
- Reworks
view_account_contract_codeto useRuntimeContractIdentifier::resolve()instead of reading raw trie bytes, fixing legacy ETH implicit wallet code resolution. - Fixes
call_functionto useview_state.current_protocol_versionwhen selecting runtime config, and cachesRuntimeConfigStoreonTrieViewer. - Removes the now-unused
AccountContractAccessExthelper trait.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| runtime/runtime/src/state_viewer/mod.rs | Correct contract code resolution + protocol-version-aware view gas selection; stores RuntimeConfigStore on TrieViewer. |
| runtime/runtime/src/contract_code.rs | Removes AccountContractAccessExt (no longer needed with identifier-based resolution). |
| integration-tests/src/user/runtime_user.rs | Updates RuntimeUser to call new view_account_contract_code signature (adds protocol version + chain id args). |
| integration-tests/src/tests/runtime/state_viewer.rs | Updates TrieViewer::new call sites to pass a RuntimeConfigStore. |
| chain/chain/src/runtime/mod.rs | Constructs TrieViewer with a shared RuntimeConfigStore; updates ViewCode path to call new viewer API (but currently passes PROTOCOL_VERSION). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fn max_gas_burnt_view(&self, protocol_version: ProtocolVersion) -> Gas { | ||
| self.max_gas_burnt_view.unwrap_or_else(|| { | ||
| self.runtime_config_store | ||
| .get_config(protocol_version) | ||
| .wasm_config | ||
| .limit_config | ||
| .max_gas_burnt | ||
| }) |
There was a problem hiding this comment.
The struct field max_gas_burnt_view and the helper method max_gas_burnt_view(&self, ...) share the same name. This is easy to misread and may trigger clippy::same_name_method depending on the lint set used in CI. Consider renaming the method to something like resolved_max_gas_burnt_view (or renaming the field) to avoid ambiguity.
wacban
left a comment
There was a problem hiding this comment.
LGTM, but see comment about protocol version
| self.trie_viewer.view_account_contract_code( | ||
| &state_update, | ||
| account_id, | ||
| PROTOCOL_VERSION, |
There was a problem hiding this comment.
this seems wrong, why not use the protocol version matching the state root?
There was a problem hiding this comment.
yes, missed that, fixing now
Co-Authored-By: Claude Opus 4.6 <[email protected]>
- Fix `view_account_contract_code` (ViewCode RPC): was using `AccountContractAccessExt::code` which reads raw bytes from the trie, returning the magic bytes blob instead of actual wallet contract WASM for legacy ETH implicit accounts. Now uses `RuntimeContractIdentifier::resolve()` which correctly handles all contract types: local contracts, global contracts (by hash and by account id), and legacy ETH wallet contracts. - Fix `call_function` (view function calls): was using hardcoded `PROTOCOL_VERSION` to resolve the runtime config instead of `view_state.current_protocol_version`, which could return incorrect config for the actual protocol version of the block being queried. - Store `RuntimeConfigStore` on `TrieViewer` and pass it via `new()` instead of creating a new one on every call. Make `max_gas_burnt_view` an `Option<Gas>` that resolves from the runtime config for the current protocol version when not explicitly set. - Remove now-unused `AccountContractAccessExt` trait. --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
…ract test - Extend test_eth_implicit_global_contract_mainnet_upgrade to verify ViewCode and CallFunction (get_nonce) RPC queries before and after the PV 82 -> 83 protocol upgrade, covering the code paths fixed in #15437. - At PV 82: verify ViewCode returns the legacy localnet wallet contract WASM and get_nonce returns 0. - At PV 83: verify ViewCode returns the deployed global contract WASM for both old (magic-bytes) and new ETH implicit accounts, get_nonce returns 0 before and 1 after rlp_execute. - Refactor NodeRunner::run_jsonrpc_query into run_with_jsonrpc_client (generic, takes closure) and a new run_jsonrpc_query that directly accepts RpcQueryRequest, simplifying all query call sites. Co-Authored-By: Claude Opus 4.6 <[email protected]>
…ract test - Extend test_eth_implicit_global_contract_mainnet_upgrade to verify ViewCode and CallFunction (get_nonce) RPC queries before and after the PV 82 -> 83 protocol upgrade, covering the code paths fixed in #15437. - At PV 82: verify ViewCode returns the legacy localnet wallet contract WASM and get_nonce returns 0. - At PV 83: verify ViewCode returns the deployed global contract WASM for both old (magic-bytes) and new ETH implicit accounts, get_nonce returns 0 before and 1 after rlp_execute. - Refactor NodeRunner::run_jsonrpc_query into run_with_jsonrpc_client (generic, takes closure) and a new run_jsonrpc_query that directly accepts RpcQueryRequest, simplifying all query call sites. Co-Authored-By: Claude Opus 4.6 <[email protected]>
…ract test - Extend test_eth_implicit_global_contract_mainnet_upgrade to verify ViewCode and CallFunction (get_nonce) RPC queries before and after the PV 82 -> 83 protocol upgrade, covering the code paths fixed in #15437. - At PV 82: verify ViewCode returns the legacy localnet wallet contract WASM and get_nonce returns 0. - At PV 83: verify ViewCode returns the deployed global contract WASM for both old (magic-bytes) and new ETH implicit accounts, get_nonce returns 0 before and 1 after rlp_execute. - Refactor NodeRunner::run_jsonrpc_query into run_with_jsonrpc_client (generic, takes closure) and a new run_jsonrpc_query that directly accepts RpcQueryRequest, simplifying all query call sites. Co-Authored-By: Claude Opus 4.6 <[email protected]>
…ract test - Extend test_eth_implicit_global_contract_mainnet_upgrade to verify ViewCode and CallFunction (get_nonce) RPC queries before and after the PV 82 -> 83 protocol upgrade, covering the code paths fixed in #15437. - At PV 82: verify ViewCode returns the legacy localnet wallet contract WASM and get_nonce returns 0. - At PV 83: verify ViewCode returns the deployed global contract WASM for both old (magic-bytes) and new ETH implicit accounts, get_nonce returns 0 before and 1 after rlp_execute. - Refactor NodeRunner::run_jsonrpc_query into run_with_jsonrpc_client (generic, takes closure) and a new run_jsonrpc_query that directly accepts RpcQueryRequest, simplifying all query call sites. Co-Authored-By: Claude Opus 4.6 <[email protected]>
…ract test (#15446) Extend `test_eth_implicit_global_contract_mainnet_upgrade` to verify ViewCode and CallFunction (`get_nonce`) RPC queries before and after the PV 82 -> 83 protocol upgrade, covering the code paths fixed in #15437. - At PV 82: verify ViewCode returns the legacy localnet wallet contract WASM and `get_nonce` returns 0. - At PV 83: verify ViewCode returns the deployed global contract WASM for both old (magic-bytes) and new ETH implicit accounts, `get_nonce` returns 0 before and 1 after `rlp_execute`. - Refactor `NodeRunner::run_jsonrpc_query` into `run_with_jsonrpc_client` (generic, takes closure) and a new `run_jsonrpc_query` that directly accepts `RpcQueryRequest`, simplifying all query call sites. Co-authored-by: Claude Opus 4.6 <[email protected]>
view_account_contract_code(ViewCode RPC): was usingAccountContractAccessExt::codewhich reads raw bytes from the trie, returning the magic bytes blob instead of actual wallet contract WASM for legacy ETH implicit accounts. Now usesRuntimeContractIdentifier::resolve()which correctly handles all contract types: local contracts, global contracts (by hash and by account id), and legacy ETH wallet contracts.call_function(view function calls): was using hardcodedPROTOCOL_VERSIONto resolve the runtime config instead ofview_state.current_protocol_version, which could return incorrect config for the actual protocol version of the block being queried.RuntimeConfigStoreonTrieViewerand pass it vianew()instead of creating a new one on every call. Makemax_gas_burnt_viewanOption<Gas>that resolves from the runtime config for the current protocol version when not explicitly set.AccountContractAccessExttrait.