From 7bb60f34cb911bbe96e0fd810bbbbdb6951d593c Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Mon, 4 Dec 2023 14:38:28 +0800 Subject: [PATCH] include block hashes, contract codes in witness --- core/blockchain.go | 1 - core/state/state_witness.go | 44 ++++++++++++++++++++++++++++++------- core/state/statedb.go | 20 ++++++++++++++--- core/vm/instructions.go | 2 +- core/vm/interface.go | 2 +- 5 files changed, 55 insertions(+), 14 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 42855179e0..e959d081cd 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1852,7 +1852,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error) } else { status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false) } - fmt.Println("dump block") statedb.Witness.Block = block state.DumpWitnessToFile(statedb.Witness) diff --git a/core/state/state_witness.go b/core/state/state_witness.go index f83fd8e22f..656ea709ba 100644 --- a/core/state/state_witness.go +++ b/core/state/state_witness.go @@ -11,17 +11,23 @@ import ( ) type Witness struct { - Block *types.Block - Root common.Hash - Lists map[common.Hash]map[string][]byte + Block *types.Block + UsedBlockHashes map[uint64]common.Hash + Codes map[common.Hash]Code + Root common.Hash + Lists map[common.Hash]map[string][]byte } type EncodeWitness struct { - block *types.Block - root common.Hash - owners []common.Hash - paths [][]string - nodes [][][]byte + block *types.Block + root common.Hash + owners []common.Hash + paths [][]string + nodes [][][]byte + blockNums []uint64 + blockHashes []common.Hash + codeHashes []common.Hash + codes []Code } func (w *Witness) EncodeRLP() []byte { @@ -39,6 +45,16 @@ func (w *Witness) EncodeRLP() []byte { e.paths = append(e.paths, paths) e.nodes = append(e.nodes, nodes) } + + for codeHash, code := range w.Codes { + e.codeHashes = append(e.codeHashes, codeHash) + e.codes = append(e.codes, code) + } + + for blockNum, blockHash := range w.UsedBlockHashes { + e.blockNums = append(e.blockNums, blockNum) + e.blockHashes = append(e.blockHashes, blockHash) + } res := new(bytes.Buffer) if err := e.encode(res); err != nil { panic(err) @@ -63,6 +79,18 @@ func (obj *EncodeWitness) encode(_w io.Writer) error { if err := rlp.Encode(w, obj.nodes); err != nil { panic(err) } + if err := rlp.Encode(w, obj.blockNums); err != nil { + panic(err) + } + if err := rlp.Encode(w, obj.blockHashes); err != nil { + panic(err) + } + if err := rlp.Encode(w, obj.codeHashes); err != nil { + panic(err) + } + if err := rlp.Encode(w, obj.codes); err != nil { + panic(err) + } w.ListEnd(_tmp0) return w.Flush() } diff --git a/core/state/statedb.go b/core/state/statedb.go index c3db1091c0..884bf8209c 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -84,7 +84,7 @@ type StateDB struct { stateObjectsDirty map[common.Address]struct{} // State objects modified in the current execution stateObjectsDestruct map[common.Address]*types.StateAccount // State objects destructed in the block along with its previous value - usedBlockHashes map[common.Hash]struct{} + usedBlockHashes map[uint64]common.Hash codes map[common.Hash]Code // DB error. @@ -170,6 +170,9 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) accessList: newAccessList(), transientStorage: newTransientStorage(), hasher: crypto.NewKeccakState(), + + usedBlockHashes: make(map[uint64]common.Hash), + codes: make(map[common.Hash]Code), } if sdb.snaps != nil { sdb.snap = sdb.snaps.Snapshot(root) @@ -177,8 +180,8 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) return sdb, nil } -func (s *StateDB) MarkUsedBlockHash(hash common.Hash) { - s.usedBlockHashes[hash] = struct{}{} +func (s *StateDB) MarkUsedBlockHash(hash common.Hash, num uint64) { + s.usedBlockHashes[num] = hash } func (s *StateDB) MarkWitnessCode(hash common.Hash, code Code) { @@ -734,6 +737,15 @@ func (s *StateDB) Copy() *StateDB { // miner to operate trie-backed only. snaps: s.snaps, snap: s.snap, + + codes: make(map[common.Hash]Code), + usedBlockHashes: make(map[uint64]common.Hash), + } + for codeHash, code := range s.codes { + state.codes[codeHash] = code + } + for num, bh := range s.usedBlockHashes { + state.usedBlockHashes[num] = bh } // Copy the dirty states, logs, and preimages for addr := range s.journal.dirties { @@ -1203,6 +1215,8 @@ func (s *StateDB) Commit(block uint64, deleteEmptyObjects bool) (common.Hash, er return common.Hash{}, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr) } w := newWitness(s.originalRoot) + w.Codes = s.codes + w.UsedBlockHashes = s.usedBlockHashes // Finalize any pending changes and merge everything into the tries s.IntermediateRoot(deleteEmptyObjects) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 39ee73e276..c5eb31c759 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -450,7 +450,7 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ( res := interpreter.evm.Context.GetHash(num64).Bytes() var bh common.Hash copy(bh[:], res[:]) - interpreter.evm.StateDB.MarkUsedBlockHash(bh) + interpreter.evm.StateDB.MarkUsedBlockHash(bh, num64) num.SetBytes(res[:]) } else { num.Clear() diff --git a/core/vm/interface.go b/core/vm/interface.go index fee005e608..ee735cbc99 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -79,7 +79,7 @@ type StateDB interface { AddLog(*types.Log) AddPreimage(common.Hash, []byte) - MarkUsedBlockHash(common.Hash) + MarkUsedBlockHash(common.Hash, uint64) } // CallContext provides a basic interface for the EVM calling conventions. The EVM