Draft: stateless validator#4809
Draft
envestcc wants to merge 16 commits into
Draft
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
tools/witnessmeasure: new CLI that fetches block witnesses via debug_traceBlockWitnessByNumber and measures: - witness JSON payload size - contracts/entries/proofNodes/proofBytes per block - VerifyContractStorageWitness timing per block and per contract - linear regression model: proof_bytes and verify_ms vs exec_tx count blockchain/witness: export ContractWitness.ToEVMWitness() so external tools can call proof verification without re-implementing the conversion. testnet_samples.csv contains 15 blocks spread across 5 exec-tx-count quintiles (5-1803 txs/block) from the testnet 28M height range for a representative measurement run. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously verifyContractStorageProof rebuilt the hash→node map on every entry call, making verification O(n²) in the number of witness entries. Now the map is built once in VerifyContractStorageWitness and shared across all entries, reducing complexity to O(n·depth). Also removes the unused in-memory trie construction that served no purpose in the verification path. Benchmark results (Apple M1 Pro): entries=10: 82µs → 24µs (3.4×) entries=50: 1.85ms → 302µs (6.1×) entries=100: 7.53ms → 958µs (7.9×) entries=200: 32.9ms → 3.2ms (10.3×) entries=500: 253ms → 10.7ms (23.6×) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
There was a problem hiding this comment.
Pull request overview
This PR introduces an experimental “stateless validator” workflow by adding contract-storage witness capture/verification, new Web3 debug endpoints to expose witnesses and storage access summaries, and new sync modes (CS sync / standalone sync) to consume blocks plus witness sidecars.
Changes:
- Add Merkle Patricia Trie proof export/verification and EVM contract-storage witness generation/verification primitives.
- Persist and serve per-block witness payloads (via a dedicated witness DB) and expose new Web3 debug RPC methods for block witness/storage tracing and retrieval.
- Add experimental syncing paths (CS sync and standalone sync) and developer tools for validating/measuring witness payloads.
Reviewed changes
Copilot reviewed 52 out of 52 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/witnessmeasure/testnet_samples.csv | Adds sample block heights for witness measurement runs. |
| tools/witnessmeasure/main.go | New CLI tool to fetch witness payloads via RPC and measure size/verify time. |
| tools/statelessdemo/main.go | New demo verifier that polls blocks and validates witness summaries + proofs. |
| tools/statelessdemo/main_test.go | Unit tests for statelessdemo validation helpers. |
| state/factory/workingsetstore_test.go | Adds test coverage for flusher options that skip contract-storage flush. |
| state/factory/workingsetstore_erigon_simulate.go | Extends Erigon simulate store to retain a base store reference. |
| state/factory/workingset.go | Adds BaseState/BasePutState/BaseDelState to bypass Erigon dry-run store. |
| state/factory/statedb.go | Adds skip-contract-storage flush option when stateless validation is enabled. |
| server/itx/server.go | Enables real p2p agent in standalone mode under experimental flag. |
| db/trie/trie.go | Introduces ProofTrie interface (GetProof/VerifyProof). |
| db/trie/mptrie/merklepatriciatrie.go | Implements GetProof and VerifyProof for MPT. |
| db/trie/mptrie/merklepatriciatrie_test.go | Adds tests for proof generation/verification and tamper detection. |
| consensus/consensus.go | Validates blocks before committing in consensus callback. |
| chainservice/stateless_witness.go | Adds RPC client for fetching persisted block witnesses by hash. |
| chainservice/stateless_witness_test.go | Tests for stateless witness RPC client and parsing. |
| chainservice/cs_syncer.go | Adds CS syncer to fetch blocks via gRPC and witnesses via Web3/debug RPC, with local caching. |
| chainservice/cs_syncer_test.go | Tests witness caching behavior and Start() non-blocking behavior. |
| chainservice/builder.go | Wires experimental stateless validation and CS sync into chainservice builder. |
| blockchain/witness/store.go | Adds witness persistence store (bolt DB) + parsing into stateless validation context. |
| blockchain/witness/json.go | Adds JSON witness schema and conversion to EVM witness structures. |
| blockchain/witness/collector.go | Adds runtime witness collector to capture per-action witnesses during block execution. |
| blockchain/config.go | Adds experimental config flags for standalone sync, stateless validation RPC, CS sync, witness DB path. |
| blockchain/blockchain_witness_test.go | Ensures witness store is skipped for CS-sync consumer nodes. |
| blockchain/blockchain.go | Integrates witness collection/persistence, stateless validation option plumbing, and witness retrieval APIs. |
| api/web3server_utils.go | Updates tx decoding to use CodeAt(ctx, …) and extends EVM tracer to capture storage access/witnesses. |
| api/web3server_marshal.go | Adds JSON marshaling for storage access summaries and witness payloads; block-level summarizers. |
| api/web3server.go | Adds new debug RPC methods for block storage tracing and witness retrieval endpoints. |
| api/web3server_test.go | Adds extensive tests for new trace/witness JSON outputs and new debug endpoints. |
| api/mock_apicoreservice.go | Updates mock core service with BlockWitnessByNumber/BlockWitnessByHash methods. |
| api/coreservice.go | Adds block witness getters; adds no-index fallback for action/receipt lookups; wires tracer callbacks into EVM. |
| api/coreservice_test.go | Adds tests for no-index action/receipt lookup and trace call witness capture. |
| action/protocol/execution/evm/context.go | Adds stateless validation context + tracer hooks for storage accesses/witnesses. |
| action/protocol/execution/evm/storage_access_trace.go | Adds storage access tracer and stable ordering utilities. |
| action/protocol/execution/evm/storage_witness.go | Adds contract storage witness types and helpers. |
| action/protocol/execution/evm/storage_witness_test.go | Tests witness building requirements and absence proofs. |
| action/protocol/execution/evm/storage_witness_validate.go | Adds witness proof verification logic. |
| action/protocol/execution/evm/storage_witness_validate_test.go | Tests verification success and tamper rejection. |
| action/protocol/execution/evm/evmstatedbadapter.go | Adds opt-in storage access tracing + witness assembly from cached contracts. |
| action/protocol/execution/evm/evmstatedbadapter_test.go | Tests storage access tracing and reset behavior. |
| action/protocol/execution/evm/evmstatedbadapter_erigon.go | Adds witness assembly for Erigon adapter and stateless contract selection. |
| action/protocol/execution/evm/evm.go | Emits traced accesses/witnesses via tracer context; enables tracing option when tracer is present. |
| action/protocol/execution/evm/evm_test.go | Tests storage tracing opt-in via tracer context. |
| action/protocol/execution/evm/tracer.go | Ensures helper context exists for tracing and makes TraceEnd tolerant of missing VM tracer. |
| action/protocol/execution/evm/contract.go | Adds witness building, pre-state snapshot capture, and stateless contract implementation. |
| action/protocol/execution/evm/contract_adapter.go | Ensures adapter forwards BuildStorageWitness. |
| action/protocol/execution/evm/contract_erigon.go | Declares BuildStorageWitness unsupported for pure erigon contract. |
| action/protocol/execution/evm/contract_stateless_kvstore.go | Adds mirrored KV store to keep digest consistent while using in-memory proof nodes. |
| action/protocol/execution/evm/contract_stateless_test.go | Comprehensive tests for stateless contract behavior and Erigon integration. |
| action/protocol/execution/evm/contract_dryrun_hybrid.go | Adds dry-run hybrid contract to separate execution reads from proof assembly reads. |
| action/protocol/execution/evm/contract_dryrun_hybrid_test.go | Tests dry-run hybrid routing and error propagation. |
| action/protocol/execution/evm/witness_bench_test.go | Adds benchmarks/measurement for witness size and verification cost. |
| Makefile | Adds build target for statelessdemo tool and includes it in build-all. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+921
to
+936
| _, blk, _, err := core.lookupActionByHashNoIndex(h) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| receipt := filterReceipts(blk.Receipts, h) | ||
| if receipt != nil { | ||
| return receipt, nil | ||
| } | ||
| receipts, err := core.dao.GetReceipts(blk.Height()) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| if receipt := filterReceipts(receipts, h); receipt != nil { | ||
| return receipt, nil | ||
| } | ||
| return nil, errors.Wrapf(ErrNotFound, "failed to find receipt for action %x", h) |
Comment on lines
+1271
to
+1276
| func (core *coreService) lookupActionByHashNoIndex(h hash.Hash256) (*action.SealedEnvelope, *block.Block, uint32, error) { | ||
| for height := core.bc.TipHeight(); height >= 1; height-- { | ||
| blk, err := core.dao.GetBlockByHeight(height) | ||
| if err != nil { | ||
| return nil, nil, 0, errors.Wrap(ErrNotFound, err.Error()) | ||
| } |
Comment on lines
+684
to
688
| svCtx, err = witnessClient.blockWitnessByHash(context.Background(), blk.HashBlock()) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } |
Comment on lines
+153
to
+154
| ctx, cancel := context.WithTimeout(context.Background(), maxDuration(s.blocksyncCfg.Interval, 30*time.Second)) | ||
| defer cancel() |
Comment on lines
+64
to
+67
| if err := c.call(ctx, "debug_getBlockWitnessByHash", []any{common.BytesToHash(blockHash[:]).Hex()}, &result); err != nil { | ||
| if strings.Contains(err.Error(), "not exist in DB") { | ||
| return append(json.RawMessage(nil), _emptyBlockWitnessResult...), nil | ||
| } |
Comment on lines
+24
to
+29
| func (s *mirroredTrieKVStore) Start(ctx context.Context) error { | ||
| if err := s.primary.Start(ctx); err != nil { | ||
| return err | ||
| } | ||
| return s.mirror.Start(ctx) | ||
| } |
Comment on lines
+34
to
+39
| func (s *Store) PutRaw(blockHash hash.Hash256, height uint64, raw json.RawMessage) error { | ||
| if err := s.db.Put(byHashNamespace, blockHash[:], raw); err != nil { | ||
| return err | ||
| } | ||
| return s.db.Put(hashByHeightNamespace, byteutil.Uint64ToBytesBigEndian(height), blockHash[:]) | ||
| } |
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Description
Please include a summary of the changes and the related issue. Please also include relevant motivation and context. List any dependencies that are required for this change.
Fixes #(issue)
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
Test Configuration:
Checklist: