optionally enable block witness recording/dumping via 'debug_setWitnessRecording'. only collect witnesses in statedb if explicitly enabled

This commit is contained in:
Jared Wasinger 2023-12-19 18:51:23 +08:00
parent 64e53367d8
commit 2d0ee010f2
5 changed files with 69 additions and 16 deletions

View file

@ -258,6 +258,8 @@ type BlockChain struct {
processor Processor // Block transaction processor interface processor Processor // Block transaction processor interface
forker *ForkChoice forker *ForkChoice
vmConfig vm.Config vmConfig vm.Config
witnessRecordingPath atomic.Pointer[string]
} }
// NewBlockChain returns a fully initialised block chain using information // 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 { if parent == nil {
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1) 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 { if err != nil {
return it.index, err return it.index, err
} }
@ -1852,8 +1862,16 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
} else { } else {
status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false) 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) //state.DumpBlockWithWitnessToFile(statedb.GetWitness(), block)
followupInterrupt.Store(true) followupInterrupt.Store(true)
@ -2594,3 +2612,11 @@ func (bc *BlockChain) SetTrieFlushInterval(interval time.Duration) {
func (bc *BlockChain) GetTrieFlushInterval() time.Duration { func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
return time.Duration(bc.flushInterval.Load()) 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)
}
}

View file

@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"os" "os"
"path/filepath"
) )
type Witness struct { 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() 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 { if err != nil {
panic("shite2") return err
}
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 nil
} }

View file

@ -139,7 +139,17 @@ type StateDB struct {
// Testing hooks // Testing hooks
onCommit func(states *triestate.Set) // Hook invoked when commit is performed 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. // 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 storageTrieNodesDeleted int
nodes = trienode.NewMergedNodeSet() nodes = trienode.NewMergedNodeSet()
codeWriter = s.db.DiskDB().NewBatch() codeWriter = s.db.DiskDB().NewBatch()
root common.Hash
set *trienode.NodeSet
) )
// Handle all state deletions first // Handle all state deletions first
incomplete, err := s.handleDestruction(nodes) incomplete, err := s.handleDestruction(nodes)
@ -1247,9 +1259,14 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er
if metrics.EnabledExpensive { if metrics.EnabledExpensive {
start = time.Now() start = time.Now()
} }
//root, set, err := s.trie.Commit(true)
root, set, accessList, err := s.trie.CommitAndObtainAccessList(true) if s.recordWitness {
s.witness.addAccessList(common.Hash{}, accessList) 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 { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }

View file

@ -443,3 +443,8 @@ func (api *DebugAPI) GetTrieFlushInterval() (string, error) {
} }
return api.eth.blockchain.GetTrieFlushInterval().String(), nil return api.eth.blockchain.GetTrieFlushInterval().String(), nil
} }
func (api *DebugAPI) SetWitnessRecording(path string, enabled bool) error {
api.eth.blockchain.SetWitnessRecording(path, enabled)
return nil
}

View file

@ -501,6 +501,11 @@ web3._extend({
call: 'debug_getTrieFlushInterval', call: 'debug_getTrieFlushInterval',
params: 0 params: 0
}), }),
new web3._extend.Method({
name: 'setWitnessRecording',
call: 'debug_setWitnessRecording',
params: 2
}),
], ],
properties: [] properties: []
}); });