From 21b1f70e19166c4a5bde5d96ae8260c49a87f70d Mon Sep 17 00:00:00 2001 From: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Date: Wed, 4 Jun 2025 09:22:17 +0200 Subject: [PATCH 1/4] implement debug_ExecutionWitness Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> --- core/blockchain.go | 6 +++--- core/stateless/encoding.go | 17 +++++++++-------- core/stateless/witness.go | 4 ++++ eth/api_debug.go | 17 +++++++++++++++++ 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 64345bc1a35..e7e9717951a 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1837,7 +1837,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness } // The traced section of block import. start := time.Now() - res, err := bc.processBlock(parent.Root, block, setHead, makeWitness && len(chain) == 1) + res, err := bc.ProcessBlock(parent.Root, block, setHead, makeWitness && len(chain) == 1) if err != nil { return nil, it.index, err } @@ -1903,9 +1903,9 @@ type blockProcessingResult struct { witness *stateless.Witness } -// processBlock executes and validates the given block. If there was no error +// ProcessBlock executes and validates the given block. If there was no error // it writes the block and associated state to database. -func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool) (_ *blockProcessingResult, blockEndErr error) { +func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool) (_ *blockProcessingResult, blockEndErr error) { var ( err error startTime = time.Now() diff --git a/core/stateless/encoding.go b/core/stateless/encoding.go index 5f4cb0ea3c0..9ce357921aa 100644 --- a/core/stateless/encoding.go +++ b/core/stateless/encoding.go @@ -23,9 +23,9 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) -// toExtWitness converts our internal witness representation to the consensus one. -func (w *Witness) toExtWitness() *extWitness { - ext := &extWitness{ +// ToExtWitness converts our internal witness representation to the consensus one. +func (w *Witness) ToExtWitness() *ExtWitness { + ext := &ExtWitness{ Headers: w.Headers, } ext.Codes = make([][]byte, 0, len(w.Codes)) @@ -40,7 +40,7 @@ func (w *Witness) toExtWitness() *extWitness { } // fromExtWitness converts the consensus witness format into our internal one. -func (w *Witness) fromExtWitness(ext *extWitness) error { +func (w *Witness) fromExtWitness(ext *ExtWitness) error { w.Headers = ext.Headers w.Codes = make(map[string]struct{}, len(ext.Codes)) @@ -56,21 +56,22 @@ func (w *Witness) fromExtWitness(ext *extWitness) error { // EncodeRLP serializes a witness as RLP. func (w *Witness) EncodeRLP(wr io.Writer) error { - return rlp.Encode(wr, w.toExtWitness()) + return rlp.Encode(wr, w.ToExtWitness()) } // DecodeRLP decodes a witness from RLP. func (w *Witness) DecodeRLP(s *rlp.Stream) error { - var ext extWitness + var ext ExtWitness if err := s.Decode(&ext); err != nil { return err } return w.fromExtWitness(&ext) } -// extWitness is a witness RLP encoding for transferring across clients. -type extWitness struct { +// ExtWitness is a witness RLP encoding for transferring across clients. +type ExtWitness struct { Headers []*types.Header Codes [][]byte State [][]byte + Keys [][]byte } diff --git a/core/stateless/witness.go b/core/stateless/witness.go index aecfad1d52f..f1601552ca9 100644 --- a/core/stateless/witness.go +++ b/core/stateless/witness.go @@ -98,6 +98,10 @@ func (w *Witness) AddState(nodes map[string]struct{}) { maps.Copy(w.State, nodes) } +func (w *Witness) AddKey() { + panic("not yet implemented") +} + // Copy deep-copies the witness object. Witness.Block isn't deep-copied as it // is never mutated by Witness func (w *Witness) Copy() *Witness { diff --git a/eth/api_debug.go b/eth/api_debug.go index 188dee11aa5..1cbbd17aacf 100644 --- a/eth/api_debug.go +++ b/eth/api_debug.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/stateless" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/internal/ethapi" @@ -443,3 +444,19 @@ func (api *DebugAPI) GetTrieFlushInterval() (string, error) { } return api.eth.blockchain.GetTrieFlushInterval().String(), nil } + +func (api *DebugAPI) ExecuteWitnessByHash(hash common.Hash) (*stateless.ExtWitness, error) { + bc := api.eth.blockchain + block := bc.GetBlockByHash(hash) + if block != nil { + return &stateless.ExtWitness{}, fmt.Errorf("block hash %x not found", hash) + } + statedb, err := bc.StateAt(block.Header().Root) + if err != nil { + return &stateless.ExtWitness{}, err + } + parent := bc.GetHeader(block.ParentHash(), block.NumberU64()-1) + bc.ProcessBlock(parent.Root, block, false, true) + + return statedb.Witness().ToExtWitness(), nil +} From 9fd692a02db7631f65692c09dc18afcd899211c8 Mon Sep 17 00:00:00 2001 From: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Date: Thu, 10 Jul 2025 13:06:04 +0200 Subject: [PATCH 2/4] fix some issues Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> --- core/blockchain.go | 4 ++++ eth/api_debug.go | 11 +++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index e7e9717951a..1bafd297d0f 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1903,6 +1903,10 @@ type blockProcessingResult struct { witness *stateless.Witness } +func (bpr *blockProcessingResult) Witness() *stateless.Witness { + return bpr.witness +} + // ProcessBlock executes and validates the given block. If there was no error // it writes the block and associated state to database. func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool) (_ *blockProcessingResult, blockEndErr error) { diff --git a/eth/api_debug.go b/eth/api_debug.go index 1cbbd17aacf..450489d3108 100644 --- a/eth/api_debug.go +++ b/eth/api_debug.go @@ -448,15 +448,14 @@ func (api *DebugAPI) GetTrieFlushInterval() (string, error) { func (api *DebugAPI) ExecuteWitnessByHash(hash common.Hash) (*stateless.ExtWitness, error) { bc := api.eth.blockchain block := bc.GetBlockByHash(hash) - if block != nil { + if block == nil { return &stateless.ExtWitness{}, fmt.Errorf("block hash %x not found", hash) } - statedb, err := bc.StateAt(block.Header().Root) + parent := bc.GetHeader(block.ParentHash(), block.NumberU64()-1) + result, err := bc.ProcessBlock(parent.Root, block, false, true) if err != nil { - return &stateless.ExtWitness{}, err + return nil, err } - parent := bc.GetHeader(block.ParentHash(), block.NumberU64()-1) - bc.ProcessBlock(parent.Root, block, false, true) - return statedb.Witness().ToExtWitness(), nil + return result.Witness().ToExtWitness(), nil } From 9a67868f8bf76c48dae1c90f78120a2dad39b8db Mon Sep 17 00:00:00 2001 From: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Date: Tue, 15 Jul 2025 12:12:26 +0200 Subject: [PATCH 3/4] fix some encoding issues Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> --- core/stateless/encoding.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/stateless/encoding.go b/core/stateless/encoding.go index 9ce357921aa..e48583202c8 100644 --- a/core/stateless/encoding.go +++ b/core/stateless/encoding.go @@ -20,6 +20,7 @@ import ( "io" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/rlp" ) @@ -28,11 +29,11 @@ func (w *Witness) ToExtWitness() *ExtWitness { ext := &ExtWitness{ Headers: w.Headers, } - ext.Codes = make([][]byte, 0, len(w.Codes)) + ext.Codes = make([]hexutil.Bytes, 0, len(w.Codes)) for code := range w.Codes { ext.Codes = append(ext.Codes, []byte(code)) } - ext.State = make([][]byte, 0, len(w.State)) + ext.State = make([]hexutil.Bytes, 0, len(w.State)) for node := range w.State { ext.State = append(ext.State, []byte(node)) } @@ -70,8 +71,8 @@ func (w *Witness) DecodeRLP(s *rlp.Stream) error { // ExtWitness is a witness RLP encoding for transferring across clients. type ExtWitness struct { - Headers []*types.Header - Codes [][]byte - State [][]byte - Keys [][]byte + Headers []*types.Header `json:"headers"` + Codes []hexutil.Bytes `json:"codes"` + State []hexutil.Bytes `json:"state"` + Keys []hexutil.Bytes `json:"keys"` } From 59b8f7889a5964de75f659040467b37d4972d7cd Mon Sep 17 00:00:00 2001 From: Guillaume Ballet <3272758+gballet@users.noreply.github.com> Date: Tue, 15 Jul 2025 14:07:06 +0200 Subject: [PATCH 4/4] fix linter issue Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com> --- core/stateless/encoding.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/stateless/encoding.go b/core/stateless/encoding.go index e48583202c8..5c43159e66b 100644 --- a/core/stateless/encoding.go +++ b/core/stateless/encoding.go @@ -19,8 +19,8 @@ package stateless import ( "io" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" )