mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
consensus/beacon, core/{state,types}: add verkle witness builder
This commit is contained in:
parent
ea3b5095f4
commit
08cc404362
7 changed files with 228 additions and 112 deletions
|
|
@ -34,6 +34,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
|||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||
}
|
||||
var enc ExecutableData
|
||||
enc.ParentHash = e.ParentHash
|
||||
|
|
@ -58,6 +59,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
|
|||
enc.Withdrawals = e.Withdrawals
|
||||
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
|
||||
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
|
||||
enc.ExecutionWitness = e.ExecutionWitness
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +83,7 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
|||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
|
||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||
}
|
||||
var dec ExecutableData
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -154,5 +157,8 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
|
|||
if dec.ExcessBlobGas != nil {
|
||||
e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
|
||||
}
|
||||
if dec.ExecutionWitness != nil {
|
||||
e.ExecutionWitness = dec.ExecutionWitness
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ type ExecutableData struct {
|
|||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||
BlobGasUsed *uint64 `json:"blobGasUsed"`
|
||||
ExcessBlobGas *uint64 `json:"excessBlobGas"`
|
||||
ExecutionWitness *types.ExecutionWitness `json:"executionWitness,omitempty"`
|
||||
}
|
||||
|
||||
// JSON type overrides for executableData.
|
||||
|
|
@ -250,6 +251,7 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
|||
ExcessBlobGas: data.ExcessBlobGas,
|
||||
BlobGasUsed: data.BlobGasUsed,
|
||||
ParentBeaconRoot: beaconRoot,
|
||||
ExecutionWitness: params.ExecutionWitness,
|
||||
}
|
||||
block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals})
|
||||
if block.Hash() != data.BlockHash {
|
||||
|
|
@ -279,6 +281,7 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
|||
Withdrawals: block.Withdrawals(),
|
||||
BlobGasUsed: block.BlobGasUsed(),
|
||||
ExcessBlobGas: block.ExcessBlobGas(),
|
||||
ExecutionWitness: block.ExecutionWitness(),
|
||||
}
|
||||
bundle := BlobsBundleV1{
|
||||
Commitments: make([]hexutil.Bytes, 0),
|
||||
|
|
|
|||
|
|
@ -386,9 +386,37 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
|
|||
|
||||
// Assign the final state root to header.
|
||||
header.Root = state.IntermediateRoot(true)
|
||||
|
||||
// Assemble and return the final block.
|
||||
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)), nil
|
||||
|
||||
block := types.NewBlock(header, body, receipts, trie.NewStackTrie(nil))
|
||||
|
||||
if chain.Config().IsVerkle(header.Number, header.Time) {
|
||||
keys := state.AccessEvents().Keys()
|
||||
|
||||
// Open the pre-tree to prove the pre-state against
|
||||
parent := chain.GetHeaderByNumber(header.Number.Uint64() - 1)
|
||||
if parent == nil {
|
||||
return nil, fmt.Errorf("nil parent header for block %d", header.Number)
|
||||
}
|
||||
|
||||
preTrie, err := state.Database().OpenTrie(parent.Root)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening pre-state tree root: %w", err)
|
||||
}
|
||||
|
||||
vtrpre, okpre := preTrie.(*trie.VerkleTrie)
|
||||
vtrpost, okpost := state.GetTrie().(*trie.VerkleTrie)
|
||||
if okpre && okpost {
|
||||
if len(keys) > 0 {
|
||||
p, k, err := trie.ProveAndSerialize(vtrpre, vtrpost, keys, vtrpre.FlatdbNodeResolver)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error generating verkle proof for block %d: %w", header.Number, err)
|
||||
}
|
||||
block.SetVerkleProof(p, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
return block, nil
|
||||
}
|
||||
|
||||
// Seal generates a new sealing request for the given input block and pushes
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ type StateDB struct {
|
|||
|
||||
// Per-transaction access list
|
||||
accessList *accessList
|
||||
accessEvents *AccessEvents
|
||||
|
||||
// Transient storage
|
||||
transientStorage transientStorage
|
||||
|
|
@ -184,6 +185,9 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error)
|
|||
transientStorage: newTransientStorage(),
|
||||
hasher: crypto.NewKeccakState(),
|
||||
}
|
||||
if db.TrieDB().IsVerkle() {
|
||||
sdb.accessEvents = sdb.NewAccessEvents()
|
||||
}
|
||||
if sdb.snaps != nil {
|
||||
sdb.snap = sdb.snaps.Snapshot(root)
|
||||
}
|
||||
|
|
@ -1452,3 +1456,18 @@ func (s *StateDB) PointCache() *utils.PointCache {
|
|||
func (s *StateDB) Witness() *stateless.Witness {
|
||||
return s.witness
|
||||
}
|
||||
|
||||
func (s *StateDB) NewAccessEvents() *AccessEvents {
|
||||
return &AccessEvents{
|
||||
branches: make(map[branchAccessKey]mode),
|
||||
chunks: make(map[chunkAccessKey]mode),
|
||||
pointCache: utils.NewPointCache(100),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StateDB) AccessEvents() *AccessEvents {
|
||||
if s.accessEvents == nil {
|
||||
s.accessEvents = s.NewAccessEvents()
|
||||
}
|
||||
return s.accessEvents
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-verkle"
|
||||
)
|
||||
|
||||
// A BlockNonce is a 64-bit hash which proves (combined with the
|
||||
|
|
@ -59,6 +60,18 @@ func (n *BlockNonce) UnmarshalText(input []byte) error {
|
|||
return hexutil.UnmarshalFixedText("BlockNonce", input, n[:])
|
||||
}
|
||||
|
||||
type ExecutionWitness struct {
|
||||
StateDiff verkle.StateDiff `json:"stateDiff"`
|
||||
VerkleProof *verkle.VerkleProof `json:"verkleProof"`
|
||||
}
|
||||
|
||||
func (ew *ExecutionWitness) Copy() *ExecutionWitness {
|
||||
return &ExecutionWitness{
|
||||
StateDiff: ew.StateDiff.Copy(),
|
||||
VerkleProof: ew.VerkleProof.Copy(),
|
||||
}
|
||||
}
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type Header -field-override headerMarshaling -out gen_header_json.go
|
||||
//go:generate go run ../../rlp/rlpgen -type Header -out gen_header_rlp.go
|
||||
|
||||
|
|
@ -94,6 +107,8 @@ type Header struct {
|
|||
|
||||
// ParentBeaconRoot was added by EIP-4788 and is ignored in legacy headers.
|
||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
|
||||
ExecutionWitness *ExecutionWitness `json:"executionWitness,omitempty" rlp:"-"`
|
||||
}
|
||||
|
||||
// field type overrides for gencodec
|
||||
|
|
@ -302,6 +317,9 @@ func CopyHeader(h *Header) *Header {
|
|||
cpy.ParentBeaconRoot = new(common.Hash)
|
||||
*cpy.ParentBeaconRoot = *h.ParentBeaconRoot
|
||||
}
|
||||
if h.ExecutionWitness != nil {
|
||||
cpy.ExecutionWitness = h.ExecutionWitness.Copy()
|
||||
}
|
||||
return &cpy
|
||||
}
|
||||
|
||||
|
|
@ -401,6 +419,8 @@ func (b *Block) BlobGasUsed() *uint64 {
|
|||
return blobGasUsed
|
||||
}
|
||||
|
||||
func (b *Block) ExecutionWitness() *ExecutionWitness { return b.header.ExecutionWitness }
|
||||
|
||||
// Size returns the true RLP encoded storage size of the block, either by encoding
|
||||
// and returning it, or returning a previously cached value.
|
||||
func (b *Block) Size() uint64 {
|
||||
|
|
@ -477,6 +497,18 @@ func (b *Block) Hash() common.Hash {
|
|||
return h
|
||||
}
|
||||
|
||||
func (b *Block) SetVerkleProof(vp *verkle.VerkleProof, statediff verkle.StateDiff) {
|
||||
b.header.ExecutionWitness = &ExecutionWitness{statediff, vp}
|
||||
if statediff == nil {
|
||||
b.header.ExecutionWitness.StateDiff = []verkle.StemStateDiff{}
|
||||
}
|
||||
if vp == nil {
|
||||
b.header.ExecutionWitness.VerkleProof = &verkle.VerkleProof{
|
||||
IPAProof: &verkle.IPAProof{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Blocks []*Block
|
||||
|
||||
// HeaderParentHashFromRLP returns the parentHash of an RLP-encoded
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
|||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
ExecutionWitness *ExecutionWitness `json:"executionWitness,omitempty" rlp:"-"`
|
||||
Hash common.Hash `json:"hash"`
|
||||
}
|
||||
var enc Header
|
||||
|
|
@ -59,6 +60,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
|||
enc.BlobGasUsed = (*hexutil.Uint64)(h.BlobGasUsed)
|
||||
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
|
||||
enc.ParentBeaconRoot = h.ParentBeaconRoot
|
||||
enc.ExecutionWitness = h.ExecutionWitness
|
||||
enc.Hash = h.Hash()
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
|
@ -86,6 +88,7 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
|||
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||
ExecutionWitness *ExecutionWitness `json:"executionWitness,omitempty" rlp:"-"`
|
||||
}
|
||||
var dec Header
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
|
|
@ -163,5 +166,8 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
|||
if dec.ParentBeaconRoot != nil {
|
||||
h.ParentBeaconRoot = dec.ParentBeaconRoot
|
||||
}
|
||||
if dec.ExecutionWitness != nil {
|
||||
h.ExecutionWitness = dec.ExecutionWitness
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ func NewVerkleTrie(root common.Hash, db database.Database, cache *utils.PointCac
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (trie *VerkleTrie) FlatdbNodeResolver(path []byte) ([]byte, error) {
|
||||
return trie.reader.node(path, common.Hash{})
|
||||
}
|
||||
|
||||
// GetKey returns the sha3 preimage of a hashed key that was previously used
|
||||
// to store a value.
|
||||
func (t *VerkleTrie) GetKey(key []byte) []byte {
|
||||
|
|
@ -303,6 +307,24 @@ func (t *VerkleTrie) IsVerkle() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func ProveAndSerialize(pretrie, posttrie *VerkleTrie, keys [][]byte, resolver verkle.NodeResolverFn) (*verkle.VerkleProof, verkle.StateDiff, error) {
|
||||
var postroot verkle.VerkleNode
|
||||
if posttrie != nil {
|
||||
postroot = posttrie.root
|
||||
}
|
||||
proof, _, _, _, err := verkle.MakeVerkleMultiProof(pretrie.root, postroot, keys, resolver)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
p, kvps, err := verkle.SerializeProof(proof)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return p, kvps, nil
|
||||
}
|
||||
|
||||
// ChunkedCode represents a sequence of 32-bytes chunks of code (31 bytes of which
|
||||
// are actual code, and 1 byte is the pushdata offset).
|
||||
type ChunkedCode []byte
|
||||
|
|
|
|||
Loading…
Reference in a new issue