include block hashes, contract codes in witness

This commit is contained in:
Jared Wasinger 2023-12-04 14:38:28 +08:00
parent 992c6c5ef7
commit 7bb60f34cb
5 changed files with 55 additions and 14 deletions

View file

@ -1852,7 +1852,6 @@ 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)
} }
fmt.Println("dump block")
statedb.Witness.Block = block statedb.Witness.Block = block
state.DumpWitnessToFile(statedb.Witness) state.DumpWitnessToFile(statedb.Witness)

View file

@ -12,6 +12,8 @@ import (
type Witness struct { type Witness struct {
Block *types.Block Block *types.Block
UsedBlockHashes map[uint64]common.Hash
Codes map[common.Hash]Code
Root common.Hash Root common.Hash
Lists map[common.Hash]map[string][]byte Lists map[common.Hash]map[string][]byte
} }
@ -22,6 +24,10 @@ type EncodeWitness struct {
owners []common.Hash owners []common.Hash
paths [][]string paths [][]string
nodes [][][]byte nodes [][][]byte
blockNums []uint64
blockHashes []common.Hash
codeHashes []common.Hash
codes []Code
} }
func (w *Witness) EncodeRLP() []byte { func (w *Witness) EncodeRLP() []byte {
@ -39,6 +45,16 @@ func (w *Witness) EncodeRLP() []byte {
e.paths = append(e.paths, paths) e.paths = append(e.paths, paths)
e.nodes = append(e.nodes, nodes) 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) res := new(bytes.Buffer)
if err := e.encode(res); err != nil { if err := e.encode(res); err != nil {
panic(err) panic(err)
@ -63,6 +79,18 @@ func (obj *EncodeWitness) encode(_w io.Writer) error {
if err := rlp.Encode(w, obj.nodes); err != nil { if err := rlp.Encode(w, obj.nodes); err != nil {
panic(err) 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) w.ListEnd(_tmp0)
return w.Flush() return w.Flush()
} }

View file

@ -84,7 +84,7 @@ type StateDB struct {
stateObjectsDirty map[common.Address]struct{} // State objects modified in the current execution 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 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 codes map[common.Hash]Code
// DB error. // DB error.
@ -170,6 +170,9 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
accessList: newAccessList(), accessList: newAccessList(),
transientStorage: newTransientStorage(), transientStorage: newTransientStorage(),
hasher: crypto.NewKeccakState(), hasher: crypto.NewKeccakState(),
usedBlockHashes: make(map[uint64]common.Hash),
codes: make(map[common.Hash]Code),
} }
if sdb.snaps != nil { if sdb.snaps != nil {
sdb.snap = sdb.snaps.Snapshot(root) 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 return sdb, nil
} }
func (s *StateDB) MarkUsedBlockHash(hash common.Hash) { func (s *StateDB) MarkUsedBlockHash(hash common.Hash, num uint64) {
s.usedBlockHashes[hash] = struct{}{} s.usedBlockHashes[num] = hash
} }
func (s *StateDB) MarkWitnessCode(hash common.Hash, code Code) { func (s *StateDB) MarkWitnessCode(hash common.Hash, code Code) {
@ -734,6 +737,15 @@ func (s *StateDB) Copy() *StateDB {
// miner to operate trie-backed only. // miner to operate trie-backed only.
snaps: s.snaps, snaps: s.snaps,
snap: s.snap, 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 // Copy the dirty states, logs, and preimages
for addr := range s.journal.dirties { 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) return common.Hash{}, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
} }
w := newWitness(s.originalRoot) w := newWitness(s.originalRoot)
w.Codes = s.codes
w.UsedBlockHashes = s.usedBlockHashes
// Finalize any pending changes and merge everything into the tries // Finalize any pending changes and merge everything into the tries
s.IntermediateRoot(deleteEmptyObjects) s.IntermediateRoot(deleteEmptyObjects)

View file

@ -450,7 +450,7 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
res := interpreter.evm.Context.GetHash(num64).Bytes() res := interpreter.evm.Context.GetHash(num64).Bytes()
var bh common.Hash var bh common.Hash
copy(bh[:], res[:]) copy(bh[:], res[:])
interpreter.evm.StateDB.MarkUsedBlockHash(bh) interpreter.evm.StateDB.MarkUsedBlockHash(bh, num64)
num.SetBytes(res[:]) num.SetBytes(res[:])
} else { } else {
num.Clear() num.Clear()

View file

@ -79,7 +79,7 @@ type StateDB interface {
AddLog(*types.Log) AddLog(*types.Log)
AddPreimage(common.Hash, []byte) AddPreimage(common.Hash, []byte)
MarkUsedBlockHash(common.Hash) MarkUsedBlockHash(common.Hash, uint64)
} }
// CallContext provides a basic interface for the EVM calling conventions. The EVM // CallContext provides a basic interface for the EVM calling conventions. The EVM