use Bytes to simplify the Witness's operation logic

This commit is contained in:
maskpp 2025-09-18 18:21:52 +08:00
parent 8a171dce1f
commit a0b180c68a
3 changed files with 19 additions and 49 deletions

View file

@ -44,9 +44,7 @@ func (w *Witness) MakeHashDB() ethdb.Database {
rawdb.WriteHeader(memdb, header) rawdb.WriteHeader(memdb, header)
} }
// Inject all the bytecodes into the ephemeral database // Inject all the bytecodes into the ephemeral database
for code := range w.Codes { for _, blob := range w.Codes {
blob := []byte(code)
hasher.Reset() hasher.Reset()
hasher.Write(blob) hasher.Write(blob)
hasher.Read(hash) hasher.Read(hash)
@ -54,9 +52,7 @@ func (w *Witness) MakeHashDB() ethdb.Database {
rawdb.WriteCode(memdb, common.BytesToHash(hash), blob) rawdb.WriteCode(memdb, common.BytesToHash(hash), blob)
} }
// Inject all the MPT trie nodes into the ephemeral database // Inject all the MPT trie nodes into the ephemeral database
for node := range w.State { for _, blob := range w.State {
blob := []byte(node)
hasher.Reset() hasher.Reset()
hasher.Write(blob) hasher.Write(blob)
hasher.Read(hash) hasher.Read(hash)

View file

@ -18,6 +18,7 @@ package stateless
import ( import (
"io" "io"
"slices"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@ -26,47 +27,21 @@ import (
// ToExtWitness converts our internal witness representation to the consensus one. // ToExtWitness converts our internal witness representation to the consensus one.
func (w *Witness) ToExtWitness() *ExtWitness { func (w *Witness) ToExtWitness() *ExtWitness {
ext := &ExtWitness{ return &ExtWitness{
Headers: w.Headers, Headers: slices.Clone(w.Headers),
Codes: slices.Clone(w.Codes),
State: slices.Clone(w.State),
} }
ext.Codes = make([]hexutil.Bytes, 0, len(w.Codes))
for code := range w.Codes {
ext.Codes = append(ext.Codes, []byte(code))
}
ext.State = make([]hexutil.Bytes, 0, len(w.State))
for node := range w.State {
ext.State = append(ext.State, []byte(node))
}
return ext
}
// fromExtWitness converts the consensus witness format into our internal one.
func (w *Witness) fromExtWitness(ext *ExtWitness) error {
w.Headers = ext.Headers
w.Codes = make(map[string]struct{}, len(ext.Codes))
for _, code := range ext.Codes {
w.Codes[string(code)] = struct{}{}
}
w.State = make(map[string]struct{}, len(ext.State))
for _, node := range ext.State {
w.State[string(node)] = struct{}{}
}
return nil
} }
// EncodeRLP serializes a witness as RLP. // EncodeRLP serializes a witness as RLP.
func (w *Witness) EncodeRLP(wr io.Writer) error { func (w *Witness) EncodeRLP(wr io.Writer) error {
return rlp.Encode(wr, w.ToExtWitness()) return rlp.Encode(wr, w)
} }
// DecodeRLP decodes a witness from RLP. // DecodeRLP decodes a witness from RLP.
func (w *Witness) DecodeRLP(s *rlp.Stream) error { func (w *Witness) DecodeRLP(s *rlp.Stream) error {
var ext ExtWitness return s.Decode(&w)
if err := s.Decode(&ext); err != nil {
return err
}
return w.fromExtWitness(&ext)
} }
// ExtWitness is a witness RLP encoding for transferring across clients. // ExtWitness is a witness RLP encoding for transferring across clients.
@ -74,5 +49,4 @@ type ExtWitness struct {
Headers []*types.Header `json:"headers"` Headers []*types.Header `json:"headers"`
Codes []hexutil.Bytes `json:"codes"` Codes []hexutil.Bytes `json:"codes"`
State []hexutil.Bytes `json:"state"` State []hexutil.Bytes `json:"state"`
Keys []hexutil.Bytes `json:"keys"`
} }

View file

@ -18,11 +18,11 @@ package stateless
import ( import (
"errors" "errors"
"maps"
"slices" "slices"
"sync" "sync"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
) )
@ -38,9 +38,9 @@ type HeaderReader interface {
type Witness struct { type Witness struct {
context *types.Header // Header to which this witness belongs to, with rootHash and receiptHash zeroed out context *types.Header // Header to which this witness belongs to, with rootHash and receiptHash zeroed out
Headers []*types.Header // Past headers in reverse order (0=parent, 1=parent's-parent, etc). First *must* be set. Headers []*types.Header `json:"headers"` // Past headers in reverse order (0=parent, 1=parent's-parent, etc). First *must* be set.
Codes map[string]struct{} // Set of bytecodes ran or accessed Codes []hexutil.Bytes `json:"codes"` // Set of bytecodes ran or accessed
State map[string]struct{} // Set of MPT state trie nodes (account and storage together) State []hexutil.Bytes `json:"state"` // Set of MPT state trie nodes (account and storage together)
chain HeaderReader // Chain reader to convert block hash ops to header proofs chain HeaderReader // Chain reader to convert block hash ops to header proofs
lock sync.Mutex // Lock to allow concurrent state insertions lock sync.Mutex // Lock to allow concurrent state insertions
@ -62,8 +62,8 @@ func NewWitness(context *types.Header, chain HeaderReader) (*Witness, error) {
return &Witness{ return &Witness{
context: context, context: context,
Headers: headers, Headers: headers,
Codes: make(map[string]struct{}), Codes: []hexutil.Bytes{},
State: make(map[string]struct{}), State: []hexutil.Bytes{},
chain: chain, chain: chain,
}, nil }, nil
} }
@ -84,7 +84,7 @@ func (w *Witness) AddCode(code []byte) {
if len(code) == 0 { if len(code) == 0 {
return return
} }
w.Codes[string(code)] = struct{}{} w.Codes = append(w.Codes, code)
} }
// AddState inserts a batch of MPT trie nodes into the witness. // AddState inserts a batch of MPT trie nodes into the witness.
@ -96,7 +96,7 @@ func (w *Witness) AddState(nodes map[string][]byte) {
defer w.lock.Unlock() defer w.lock.Unlock()
for _, value := range nodes { for _, value := range nodes {
w.State[string(value)] = struct{}{} w.State = append(w.State, value)
} }
} }
@ -109,8 +109,8 @@ func (w *Witness) AddKey() {
func (w *Witness) Copy() *Witness { func (w *Witness) Copy() *Witness {
cpy := &Witness{ cpy := &Witness{
Headers: slices.Clone(w.Headers), Headers: slices.Clone(w.Headers),
Codes: maps.Clone(w.Codes), Codes: slices.Clone(w.Codes),
State: maps.Clone(w.State), State: slices.Clone(w.State),
chain: w.chain, chain: w.chain,
} }
if w.context != nil { if w.context != nil {