diff --git a/core/blockchain.go b/core/blockchain.go index f58df07e44..90e87b6bbb 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -258,6 +258,8 @@ type BlockChain struct { processor Processor // Block transaction processor interface forker *ForkChoice vmConfig vm.Config + + witnessRecordingPath atomic.Pointer[string] } // NewBlockChain returns a fully initialised block chain using information @@ -1779,7 +1781,15 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) if parent == nil { parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1) } - statedb, err := state.New(parent.Root, bc.stateCache, bc.snaps) + + var statedb *state.StateDB + var err error + recordBlockwitness := bc.witnessRecordingPath.Load() != nil + if recordBlockwitness { + statedb, err = state.NewWithWitnessRecording(parent.Root, bc.stateCache, bc.snaps) + } else { + statedb, err = state.New(parent.Root, bc.stateCache, bc.snaps) + } if err != nil { return it.index, err } @@ -1852,8 +1862,16 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) } else { status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false) } - statedb.GetWitness().SetBlock(block) - log.Info(fmt.Sprintf("block %d summary:\n%s", block.NumberU64(), statedb.GetWitness().Summary())) + + if witnessRecordingPath := bc.witnessRecordingPath.Load(); witnessRecordingPath != nil { + witness := statedb.GetWitness() + witness.SetBlock(block) + if err := state.DumpBlockWitnessToFile(witness, *witnessRecordingPath); err != nil { + log.Error("could not dump block witness to file", "err", err) + } else { + log.Info(fmt.Sprintf("block %d summary:\n%s", block.NumberU64(), statedb.GetWitness().Summary())) + } + } //state.DumpBlockWithWitnessToFile(statedb.GetWitness(), block) followupInterrupt.Store(true) @@ -2594,3 +2612,11 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) { func (bc *BlockChain) GetTrieFlushInterval() time.Duration { return time.Duration(bc.flushInterval.Load()) } + +func (bc *BlockChain) SetWitnessRecording(path string, enabled bool) { + if enabled { + bc.witnessRecordingPath.Store(&path) + } else { + bc.witnessRecordingPath.Store(nil) + } +} diff --git a/core/state/state_witness.go b/core/state/state_witness.go index 21018e2c3a..56ed645692 100644 --- a/core/state/state_witness.go +++ b/core/state/state_witness.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" "os" + "path/filepath" ) type Witness struct { @@ -260,16 +261,15 @@ func NewWitness() *Witness { } } -func DumpBlockWithWitnessToFile(w *Witness, b *types.Block) { +func DumpBlockWitnessToFile(w *Witness, path string) error { enc := w.EncodeRLP() - path, _ := os.Getwd() //"/datadrive/" - err := os.MkdirAll(fmt.Sprintf("%s/block-dump", path), 0755) + + blockHash := w.block.Hash() + outputFName := fmt.Sprintf("%d-%x.rlp", w.block.NumberU64(), blockHash[0:8]) + path = filepath.Join(path, outputFName) + err := os.WriteFile(path, enc, 0644) if err != nil { - panic("shite2") - } - outputFName := fmt.Sprintf("%d-%x.rlp", b.NumberU64(), b.Hash()) - err = os.WriteFile(path+"/block-dump/"+outputFName, enc, 0644) - if err != nil { - panic("shite 3") + return err } + return nil } diff --git a/core/state/statedb.go b/core/state/statedb.go index 66aaad395b..6474e2474d 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -139,7 +139,17 @@ type StateDB struct { // Testing hooks onCommit func(states *triestate.Set) // Hook invoked when commit is performed - witness *Witness + recordWitness bool + witness *Witness +} + +func NewWithWitnessRecording(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) { + sdb, err := New(root, db, snaps) + if err != nil { + return nil, err + } + sdb.recordWitness = true + return sdb, nil } // New creates a new state from a given trie. @@ -1202,6 +1212,8 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er storageTrieNodesDeleted int nodes = trienode.NewMergedNodeSet() codeWriter = s.db.DiskDB().NewBatch() + root common.Hash + set *trienode.NodeSet ) // Handle all state deletions first incomplete, err := s.handleDestruction(nodes) @@ -1247,9 +1259,14 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er if metrics.EnabledExpensive { start = time.Now() } - //root, set, err := s.trie.Commit(true) - root, set, accessList, err := s.trie.CommitAndObtainAccessList(true) - s.witness.addAccessList(common.Hash{}, accessList) + + if s.recordWitness { + var accessList map[string][]byte + root, set, accessList, err = s.trie.CommitAndObtainAccessList(true) + s.witness.addAccessList(common.Hash{}, accessList) + } else { + root, set, err = s.trie.Commit(true) + } if err != nil { return common.Hash{}, err } diff --git a/eth/api_debug.go b/eth/api_debug.go index dc9f568146..7c78cc985d 100644 --- a/eth/api_debug.go +++ b/eth/api_debug.go @@ -443,3 +443,8 @@ func (api *DebugAPI) GetTrieFlushInterval() (string, error) { } return api.eth.blockchain.GetTrieFlushInterval().String(), nil } + +func (api *DebugAPI) SetWitnessRecording(path string, enabled bool) error { + api.eth.blockchain.SetWitnessRecording(path, enabled) + return nil +} diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index b86b5909d2..829fad95a5 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -501,6 +501,11 @@ web3._extend({ call: 'debug_getTrieFlushInterval', params: 0 }), + new web3._extend.Method({ + name: 'setWitnessRecording', + call: 'debug_setWitnessRecording', + params: 2 + }), ], properties: [] });