mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-03-18 00:50:39 +00:00
a bunch of changes. mostly bal persistence and removing bal from block body object. wip...
This commit is contained in:
parent
7036b1cb39
commit
3435849244
18 changed files with 158 additions and 84 deletions
|
|
@ -307,11 +307,7 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
|||
|
||||
var blockAccessListHash *common.Hash
|
||||
body := types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}
|
||||
if data.BlockAccessList != nil {
|
||||
body.AccessList = data.BlockAccessList
|
||||
balHash := data.BlockAccessList.Hash()
|
||||
blockAccessListHash = &balHash
|
||||
}
|
||||
|
||||
header := &types.Header{
|
||||
ParentHash: data.ParentHash,
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
|
|
@ -336,7 +332,16 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
|||
BlockAccessListHash: blockAccessListHash,
|
||||
SlotNumber: data.SlotNumber,
|
||||
}
|
||||
|
||||
if data.BlockAccessList != nil {
|
||||
balHash := data.BlockAccessList.Hash()
|
||||
header.BlockAccessListHash = &balHash
|
||||
block := types.NewBlockWithHeader(header).WithBody(body).WithAccessList(data.BlockAccessList)
|
||||
return block, nil
|
||||
}
|
||||
|
||||
return types.NewBlockWithHeader(header).WithBody(body), nil
|
||||
|
||||
}
|
||||
|
||||
// BlockToExecutableData constructs the ExecutableData structure by filling the
|
||||
|
|
@ -360,6 +365,10 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
|
|||
Withdrawals: block.Withdrawals(),
|
||||
BlobGasUsed: block.BlobGasUsed(),
|
||||
ExcessBlobGas: block.ExcessBlobGas(),
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
BlockAccessList: block.AccessList(),
|
||||
>>>>>>> 959ade7689 (a bunch of changes. mostly bal persistence and removing bal from block body object. wip...)
|
||||
SlotNumber: block.SlotNumber(),
|
||||
BlockAccessList: block.Body().AccessList,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@
|
|||
# https://github.com/ethereum/execution-spec-tests/releases/download/v5.1.0
|
||||
a3192784375acec7eaec492799d5c5d0c47a2909a3cc40178898e4ecd20cc416 fixtures_develop.tar.gz
|
||||
|
||||
# version:spec-tests-bal v3.0.1
|
||||
# version:spec-tests-bal v5.0.0
|
||||
# https://github.com/ethereum/execution-spec-tests/releases
|
||||
# https://github.com/ethereum/execution-spec-tests/releases/download/bal%40v3.0.1
|
||||
57d0f109f0557ec33d6ecd6cbd77b55415a658aefe583c4035157e1021ae512a fixtures_bal.tar.gz
|
||||
# https://github.com/ethereum/execution-spec-tests/releases/download/bal%40v5.0.0
|
||||
17aecf8334da7f5d1025635c763a4be0dfbcdb0e659cc70a36e6a81bd3af06f2 fixtures_bal.tar.gz
|
||||
|
||||
# version:golang 1.25.1
|
||||
# https://go.dev/dl/
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package beacon
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -357,9 +358,9 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
|
|||
|
||||
// FinalizeAndAssemble implements consensus.Engine, setting the final state and
|
||||
// assembling the block.
|
||||
func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalization func()) (*types.Block, error) {
|
||||
func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalizeAccessList func() *bal.BlockAccessList) (*types.Block, error) {
|
||||
if !beacon.IsPoSHeader(header) {
|
||||
return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts, onFinalization)
|
||||
return beacon.ethone.FinalizeAndAssemble(chain, header, state, body, receipts, nil)
|
||||
}
|
||||
shanghai := chain.Config().IsShanghai(header.Number, header.Time)
|
||||
if shanghai {
|
||||
|
|
@ -379,12 +380,15 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
|
|||
// Assign the final state root to header.
|
||||
header.Root = state.IntermediateRoot(true)
|
||||
|
||||
if onFinalization != nil {
|
||||
onFinalization()
|
||||
}
|
||||
|
||||
// Assemble the final block.
|
||||
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)), nil
|
||||
if onFinalizeAccessList != nil {
|
||||
al := onFinalizeAccessList()
|
||||
alHash := al.Hash()
|
||||
header.BlockAccessListHash = &alHash
|
||||
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)).WithAccessList(al), nil
|
||||
} else {
|
||||
return types.NewBlock(header, body, receipts, trie.NewStackTrie(nil)), nil
|
||||
}
|
||||
}
|
||||
|
||||
// Seal generates a new sealing request for the given input block and pushes
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||
"io"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
|
|
@ -581,7 +582,7 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
|
|||
|
||||
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
|
||||
// nor block rewards given, and returns the final block.
|
||||
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalize func()) (*types.Block, error) {
|
||||
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalizeAccessList func() *bal.BlockAccessList) (*types.Block, error) {
|
||||
if len(body.Withdrawals) > 0 {
|
||||
return nil, errors.New("clique does not support withdrawals")
|
||||
}
|
||||
|
|
@ -591,10 +592,9 @@ func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
|
|||
// Assign the final state root to header.
|
||||
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
|
||||
|
||||
if onFinalize != nil {
|
||||
onFinalize()
|
||||
if onFinalizeAccessList != nil {
|
||||
panic("access list embedding not enabled for clique consensus")
|
||||
}
|
||||
|
||||
// Assemble and return the final block for sealing.
|
||||
return types.NewBlock(header, &types.Body{Transactions: body.Transactions}, receipts, trie.NewStackTrie(nil)), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package consensus
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
|
@ -92,7 +93,7 @@ type Engine interface {
|
|||
//
|
||||
// Note: The block header and state database might be updated to reflect any
|
||||
// consensus rules that happen at finalization (e.g. block rewards).
|
||||
FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalization func()) (*types.Block, error)
|
||||
FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalizeAccessList func() *bal.BlockAccessList) (*types.Block, error)
|
||||
|
||||
// Seal generates a new sealing request for the given input block and pushes
|
||||
// the result into the given channel.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package ethash
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
|
|
@ -513,7 +514,7 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.
|
|||
|
||||
// FinalizeAndAssemble implements consensus.Engine, accumulating the block and
|
||||
// uncle rewards, setting the final state and assembling the block.
|
||||
func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalize func()) (*types.Block, error) {
|
||||
func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, onFinalizeAccessList func() *bal.BlockAccessList) (*types.Block, error) {
|
||||
if len(body.Withdrawals) > 0 {
|
||||
return nil, errors.New("ethash does not support withdrawals")
|
||||
}
|
||||
|
|
@ -523,8 +524,8 @@ func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
|
|||
// Assign the final state root to header.
|
||||
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
|
||||
|
||||
if onFinalize != nil {
|
||||
onFinalize()
|
||||
if onFinalizeAccessList != nil {
|
||||
panic("access list embedding not supported for ethash consenus")
|
||||
}
|
||||
// Header seems complete, assemble into a block and return
|
||||
return types.NewBlock(header, &types.Body{Transactions: body.Transactions, Uncles: body.Uncles}, receipts, trie.NewStackTrie(nil)), nil
|
||||
|
|
|
|||
|
|
@ -116,10 +116,10 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
|||
// TODO: verify that this check isn't also done elsewhere
|
||||
return fmt.Errorf("block access list hash not set in header")
|
||||
}
|
||||
if block.Body().AccessList != nil {
|
||||
if *block.Header().BlockAccessListHash != block.Body().AccessList.Hash() {
|
||||
return fmt.Errorf("access list hash mismatch. local: %x. remote: %x\n", block.Body().AccessList.Hash(), *block.Header().BlockAccessListHash)
|
||||
} else if err := block.Body().AccessList.Validate(len(block.Transactions())); err != nil {
|
||||
if block.AccessList() != nil {
|
||||
if *block.Header().BlockAccessListHash != block.AccessList().Hash() {
|
||||
return fmt.Errorf("access list hash mismatch. local: %x. remote: %x\n", block.AccessList().Hash(), *block.Header().BlockAccessListHash)
|
||||
} else if err := block.AccessList().Validate(len(block.Transactions())); err != nil {
|
||||
return fmt.Errorf("invalid block access list: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
@ -133,7 +133,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
|||
}
|
||||
} else {
|
||||
// if experimental.bal is not enabled, block headers cannot have access list hash and bodies cannot have access lists.
|
||||
if block.Body().AccessList != nil {
|
||||
if block.AccessList() != nil {
|
||||
return fmt.Errorf("access list not allowed in block body if not in amsterdam or experimental.bal is set")
|
||||
} else if block.Header().BlockAccessListHash != nil {
|
||||
return fmt.Errorf("access list hash in block header not allowed when experimental.bal is set")
|
||||
|
|
|
|||
|
|
@ -2201,7 +2201,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
|||
}
|
||||
// TODO: need to check that the block is also postcancun if it contained an access list?
|
||||
// this should be checked during decoding (?)
|
||||
blockHasAccessList := block.Body().AccessList != nil
|
||||
blockHasAccessList := block.AccessList() != nil
|
||||
// only construct and embed BALs in the block if:
|
||||
// * it has been enabled for testing purposes (preAmsterdam/postCancun blocks with experimental.bal)
|
||||
// * we are after Amsterdam and the block was provided with bal omitted
|
||||
|
|
@ -2276,7 +2276,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
|||
// Disable tracing for prefetcher executions.
|
||||
vmCfg := bc.cfg.VmConfig
|
||||
vmCfg.Tracer = nil
|
||||
if block.Body().AccessList == nil {
|
||||
if block.AccessList() == nil {
|
||||
// only use the state prefetcher for non-BAL blocks.
|
||||
bc.prefetcher.Prefetch(block, throwaway, vmCfg, &interrupt)
|
||||
}
|
||||
|
|
@ -2369,13 +2369,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
|||
return nil, err
|
||||
|
||||
}
|
||||
// very ugly... deepcopy the block body before setting the block access
|
||||
// list on it to prevent mutating the block instance passed by the caller.
|
||||
existingBody := block.Body()
|
||||
block = block.WithBody(*existingBody)
|
||||
existingBody = block.Body()
|
||||
existingBody.AccessList = balTracer.AccessList().ToEncodingObj()
|
||||
block = block.WithBody(*existingBody)
|
||||
block = block.WithAccessList(balTracer.AccessList().ToEncodingObj())
|
||||
} else if enableBALFork {
|
||||
|
||||
computedAccessList := balTracer.AccessList().ToEncodingObj()
|
||||
|
|
@ -2387,16 +2381,12 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
|||
bc.reportBadBlock(block, res, err)
|
||||
return nil, err
|
||||
}
|
||||
if block.Body().AccessList == nil {
|
||||
// very ugly... deep copy the block body before setting the block access
|
||||
// list on it to prevent mutating the block instance passed by the caller.
|
||||
existingBody := block.Body()
|
||||
block = block.WithBody(*existingBody)
|
||||
existingBody = block.Body()
|
||||
existingBody.AccessList = computedAccessList
|
||||
block = block.WithBody(*existingBody)
|
||||
} else if block.Body().AccessList.Hash() != computedAccessListHash {
|
||||
err := fmt.Errorf("block access list hash mismatch (remote=%x computed=%x)", block.Body().AccessList.Hash(), computedAccessListHash)
|
||||
if block.AccessList() == nil {
|
||||
// attach the computed access list to the block so it gets persisted
|
||||
// when the block is written to disk
|
||||
block = block.WithAccessList(computedAccessList)
|
||||
} else if block.AccessList().Hash() != computedAccessListHash {
|
||||
err := fmt.Errorf("block access list hash mismatch (remote=%x computed=%x)", block.AccessList().Hash(), computedAccessListHash)
|
||||
bc.reportBadBlock(block, res, err)
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||
"math/big"
|
||||
"slices"
|
||||
|
||||
|
|
@ -421,6 +422,17 @@ func WriteBodyRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp
|
|||
}
|
||||
}
|
||||
|
||||
func WriteAccessListRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, rlp rlp.RawValue) {
|
||||
if err := db.Put(accessListKey(number, hash), rlp); err != nil {
|
||||
log.Crit("failed to store block access list", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
func ReadAccessListRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||
data, _ := db.Get(accessListKey(number, hash))
|
||||
return data
|
||||
}
|
||||
|
||||
// HasBody verifies the existence of a block body corresponding to the hash.
|
||||
func HasBody(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
||||
if isCanon(db, number, hash) {
|
||||
|
|
@ -455,6 +467,25 @@ func WriteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64, body *t
|
|||
WriteBodyRLP(db, hash, number, data)
|
||||
}
|
||||
|
||||
func ReadAccessList(db ethdb.Reader, hash common.Hash, number uint64) (al *bal.BlockAccessList) {
|
||||
data := ReadAccessListRLP(db, hash, number)
|
||||
if data != nil {
|
||||
err := rlp.DecodeBytes(data, al)
|
||||
if err != nil {
|
||||
log.Crit("failed to RLP decode access list", "err", err)
|
||||
}
|
||||
}
|
||||
return al
|
||||
}
|
||||
|
||||
func WriteAccessList(db ethdb.KeyValueWriter, hash common.Hash, number uint64, al *bal.BlockAccessList) {
|
||||
data, err := rlp.EncodeToBytes(al)
|
||||
if err != nil {
|
||||
log.Crit("failed to RLP encode block access list", "err", err)
|
||||
}
|
||||
WriteAccessListRLP(db, hash, number, data)
|
||||
}
|
||||
|
||||
// DeleteBody removes all block body data associated with a hash.
|
||||
func DeleteBody(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||
if err := db.Delete(blockBodyKey(number, hash)); err != nil {
|
||||
|
|
@ -659,13 +690,26 @@ func ReadBlock(db ethdb.Reader, hash common.Hash, number uint64) *types.Block {
|
|||
if body == nil {
|
||||
return nil
|
||||
}
|
||||
return types.NewBlockWithHeader(header).WithBody(*body)
|
||||
|
||||
block := types.NewBlockWithHeader(header).WithBody(*body)
|
||||
|
||||
// TODO: only read the access list if the bal hash is set in the header.
|
||||
// I do it here regardless in order to support --experimental.bal which
|
||||
// doesn't expect bal hash to be set in header in order to be compatible
|
||||
// with importing mainnet blocks augmented with BALs
|
||||
accessList := ReadAccessList(db, hash, number)
|
||||
if accessList != nil {
|
||||
block = block.WithAccessList(accessList)
|
||||
}
|
||||
|
||||
return block
|
||||
}
|
||||
|
||||
// WriteBlock serializes a block into the database, header and body separately.
|
||||
func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) {
|
||||
WriteBody(db, block.Hash(), block.NumberU64(), block.Body())
|
||||
WriteHeader(db, block.Header())
|
||||
panic("TODO write access list if it exists")
|
||||
}
|
||||
|
||||
// WriteAncientBlocks writes entire block data into ancient store and returns the total written size.
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ var (
|
|||
headerNumberPrefix = []byte("H") // headerNumberPrefix + hash -> num (uint64 big endian)
|
||||
|
||||
blockBodyPrefix = []byte("b") // blockBodyPrefix + num (uint64 big endian) + hash -> block body
|
||||
accessListPrefix = []byte("z")
|
||||
blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts
|
||||
|
||||
txLookupPrefix = []byte("l") // txLookupPrefix + hash -> transaction/receipt lookup metadata
|
||||
|
|
@ -209,6 +210,11 @@ func blockBodyKey(number uint64, hash common.Hash) []byte {
|
|||
return append(append(blockBodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
|
||||
}
|
||||
|
||||
// accessListKey = accessListPrefix + num (uint64 big endian) + hash
|
||||
func accessListKey(number uint64, hash common.Hash) []byte {
|
||||
return append(append(accessListPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
|
||||
}
|
||||
|
||||
// blockReceiptsKey = blockReceiptsPrefix + num (uint64 big endian) + hash
|
||||
func blockReceiptsKey(number uint64, hash common.Hash) []byte {
|
||||
return append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ type BALReader struct {
|
|||
// NewBALReader constructs a new reader from an access list. db is expected to have been instantiated with a reader.
|
||||
func NewBALReader(block *types.Block, reader Reader) *BALReader {
|
||||
r := &BALReader{accesses: make(map[common.Address]*bal.AccountAccess), block: block}
|
||||
for _, acctDiff := range *block.Body().AccessList {
|
||||
for _, acctDiff := range *block.AccessList() {
|
||||
r.accesses[acctDiff.Address] = &acctDiff
|
||||
}
|
||||
r.prestateReader.schedule(reader, r.ModifiedAccounts())
|
||||
|
|
|
|||
|
|
@ -462,6 +462,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
if t := st.evm.Config.Tracer; t != nil && t.OnGasChange != nil {
|
||||
t.OnGasChange(st.gasRemaining, st.gasRemaining-gas, tracing.GasChangeTxIntrinsicGas)
|
||||
}
|
||||
fmt.Printf("gas used %d\n", gas)
|
||||
st.gasRemaining -= gas
|
||||
|
||||
if rules.IsEIP4762 {
|
||||
|
|
@ -568,8 +569,10 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
}
|
||||
}
|
||||
|
||||
fmt.Printf("2 used gas is %d, %d\n", st.gasUsed(), peakGasUsed)
|
||||
|
||||
return &ExecutionResult{
|
||||
UsedGas: st.gasUsed(),
|
||||
UsedGas: peakGasUsed,
|
||||
MaxUsedGas: peakGasUsed,
|
||||
Err: vmerr,
|
||||
ReturnData: ret,
|
||||
|
|
|
|||
|
|
@ -93,7 +93,8 @@ func makeTestConstructionBAL() *AccessListBuilder {
|
|||
// TestBALEncoding tests that a populated access list can be encoded/decoded correctly.
|
||||
func TestBALEncoding(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
bal := makeTestConstructionBAL()
|
||||
balBuilder := makeTestConstructionBAL()
|
||||
bal := balBuilder.FinalizedAccesses
|
||||
err := bal.EncodeRLP(&buf)
|
||||
if err != nil {
|
||||
t.Fatalf("encoding failed: %v\n", err)
|
||||
|
|
@ -136,7 +137,7 @@ func makeTestAccountAccess(sort bool) AccountAccess {
|
|||
}
|
||||
if sort {
|
||||
slices.SortFunc(storageWrites, func(a, b encodingSlotWrites) int {
|
||||
return bytes.Compare(a.Slot[:], b.Slot[:])
|
||||
return bytes.Compare(a.Slot.inner.Bytes(), b.Slot.inner.Bytes())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +174,7 @@ func makeTestAccountAccess(sort bool) AccountAccess {
|
|||
})
|
||||
}
|
||||
|
||||
var encodedStorageReads []EncodedStorage
|
||||
var encodedStorageReads []*EncodedStorage
|
||||
for _, slot := range storageReads {
|
||||
encodedStorageReads = append(encodedStorageReads, newEncodedStorageFromHash(slot))
|
||||
}
|
||||
|
|
@ -220,7 +221,7 @@ func TestBlockAccessListCopy(t *testing.T) {
|
|||
// Make sure the mutations on copy won't affect the origin
|
||||
for _, aa := range cpyCpy {
|
||||
for i := 0; i < len(aa.StorageReads); i++ {
|
||||
aa.StorageReads[i] = testrand.Bytes(32)
|
||||
aa.StorageReads[i] = &EncodedStorage{new(uint256.Int).SetBytes(testrand.Bytes(32))}
|
||||
}
|
||||
}
|
||||
if !reflect.DeepEqual(list, cpy) {
|
||||
|
|
@ -230,8 +231,9 @@ func TestBlockAccessListCopy(t *testing.T) {
|
|||
|
||||
func TestBlockAccessListValidation(t *testing.T) {
|
||||
// Validate the block access list after RLP decoding
|
||||
testBALMaxIndex := 8
|
||||
enc := makeTestBAL(true)
|
||||
if err := enc.Validate(); err != nil {
|
||||
if err := enc.Validate(testBALMaxIndex); err != nil {
|
||||
t.Fatalf("Unexpected validation error: %v", err)
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
|
|
@ -243,14 +245,14 @@ func TestBlockAccessListValidation(t *testing.T) {
|
|||
if err := dec.DecodeRLP(rlp.NewStream(bytes.NewReader(buf.Bytes()), 0)); err != nil {
|
||||
t.Fatalf("Unexpected RLP-decode error: %v", err)
|
||||
}
|
||||
if err := dec.Validate(); err != nil {
|
||||
if err := dec.Validate(testBALMaxIndex); err != nil {
|
||||
t.Fatalf("Unexpected validation error: %v", err)
|
||||
}
|
||||
|
||||
// Validate the derived block access list
|
||||
cBAL := makeTestConstructionBAL()
|
||||
cBAL := makeTestConstructionBAL().FinalizedAccesses
|
||||
listB := cBAL.ToEncodingObj()
|
||||
if err := listB.Validate(); err != nil {
|
||||
if err := listB.Validate(testBALMaxIndex); err != nil {
|
||||
t.Fatalf("Unexpected validation error: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,8 +182,7 @@ func (h *Header) EmptyReceipts() bool {
|
|||
type Body struct {
|
||||
Transactions []*Transaction
|
||||
Uncles []*Header
|
||||
Withdrawals []*Withdrawal `rlp:"optional"`
|
||||
AccessList *bal.BlockAccessList `rlp:"optional,nil"`
|
||||
Withdrawals []*Withdrawal `rlp:"optional"`
|
||||
}
|
||||
|
||||
// Block represents an Ethereum block.
|
||||
|
|
@ -287,15 +286,17 @@ func NewBlock(header *Header, body *Body, receipts []*Receipt, hasher ListHasher
|
|||
b.withdrawals = slices.Clone(withdrawals)
|
||||
}
|
||||
|
||||
if body.AccessList != nil {
|
||||
balHash := body.AccessList.Hash()
|
||||
b.header.BlockAccessListHash = &balHash
|
||||
b.accessList = body.AccessList
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func NewBlockWithAccessList(header *Header, body *Body, receipts []*Receipt, accessList *bal.BlockAccessList, hasher ListHasher) *Block {
|
||||
block := NewBlock(header, body, receipts, hasher)
|
||||
block.accessList = accessList
|
||||
balHash := accessList.Hash()
|
||||
block.header.BlockAccessListHash = &balHash
|
||||
return block
|
||||
}
|
||||
|
||||
// CopyHeader creates a deep copy of a block header.
|
||||
func CopyHeader(h *Header) *Header {
|
||||
cpy := *h
|
||||
|
|
@ -367,15 +368,16 @@ func (b *Block) EncodeRLP(w io.Writer) error {
|
|||
// Body returns the non-header content of the block.
|
||||
// Note the returned data is not an independent copy.
|
||||
func (b *Block) Body() *Body {
|
||||
return &Body{b.transactions, b.uncles, b.withdrawals, b.accessList}
|
||||
return &Body{b.transactions, b.uncles, b.withdrawals}
|
||||
}
|
||||
|
||||
// Accessors for body data. These do not return a copy because the content
|
||||
// of the body slices does not affect the cached hash/size in block.
|
||||
|
||||
func (b *Block) Uncles() []*Header { return b.uncles }
|
||||
func (b *Block) Transactions() Transactions { return b.transactions }
|
||||
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals }
|
||||
func (b *Block) Uncles() []*Header { return b.uncles }
|
||||
func (b *Block) Transactions() Transactions { return b.transactions }
|
||||
func (b *Block) Withdrawals() Withdrawals { return b.withdrawals }
|
||||
func (b *Block) AccessList() *bal.BlockAccessList { return b.accessList }
|
||||
|
||||
func (b *Block) Transaction(hash common.Hash) *Transaction {
|
||||
for _, transaction := range b.transactions {
|
||||
|
|
@ -522,16 +524,30 @@ func (b *Block) WithBody(body Body) *Block {
|
|||
uncles: make([]*Header, len(body.Uncles)),
|
||||
withdrawals: slices.Clone(body.Withdrawals),
|
||||
}
|
||||
if body.AccessList != nil {
|
||||
balCopy := body.AccessList.Copy()
|
||||
block.accessList = &balCopy
|
||||
}
|
||||
for i := range body.Uncles {
|
||||
block.uncles[i] = CopyHeader(body.Uncles[i])
|
||||
}
|
||||
return block
|
||||
}
|
||||
|
||||
// WithAccessList returns a copy of the block with the access list embedded.
|
||||
// It does not set the access list hash in the header of the returned block.
|
||||
// TODO: ^ when support for --experimental.bal is removed, this function should set the access list hash in the header
|
||||
func (b *Block) WithAccessList(accessList *bal.BlockAccessList) *Block {
|
||||
alCopy := accessList.Copy()
|
||||
block := &Block{
|
||||
header: b.header,
|
||||
transactions: slices.Clone(b.transactions),
|
||||
uncles: make([]*Header, len(b.uncles)),
|
||||
withdrawals: slices.Clone(b.withdrawals),
|
||||
accessList: &alCopy,
|
||||
}
|
||||
for i := range b.uncles {
|
||||
block.uncles[i] = CopyHeader(b.uncles[i])
|
||||
}
|
||||
return block
|
||||
}
|
||||
|
||||
// Hash returns the keccak256 hash of b's header.
|
||||
// The hash is computed on the first call and cached thereafter.
|
||||
func (b *Block) Hash() common.Hash {
|
||||
|
|
|
|||
|
|
@ -514,8 +514,8 @@ func (b *EthAPIBackend) BlockAccessListByNumberOrHash(number rpc.BlockNumberOrHa
|
|||
if block == nil {
|
||||
return nil, fmt.Errorf("block not found")
|
||||
}
|
||||
if block.Body().AccessList == nil {
|
||||
if block.AccessList() == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return block.Body().AccessList.StringableRepresentation(), nil
|
||||
return block.AccessList().StringableRepresentation(), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,6 @@ func (f *fetchResult) body() types.Body {
|
|||
Transactions: f.Transactions,
|
||||
Uncles: f.Uncles,
|
||||
Withdrawals: f.Withdrawals,
|
||||
AccessList: f.AccessList,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -970,8 +970,8 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *param
|
|||
if block.Withdrawals() != nil {
|
||||
fields["withdrawals"] = block.Withdrawals()
|
||||
}
|
||||
if block.Body().AccessList != nil {
|
||||
fields["accessList"] = block.Body().AccessList
|
||||
if block.AccessList() != nil {
|
||||
fields["accessList"] = block.AccessList()
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"github.com/ethereum/go-ethereum/core/tracing"
|
||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
|
@ -147,9 +148,6 @@ func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPay
|
|||
}
|
||||
}
|
||||
body := types.Body{Transactions: work.txs, Withdrawals: genParam.withdrawals}
|
||||
if work.alTracer != nil {
|
||||
body.AccessList = work.alTracer.AccessList().ToEncodingObj()
|
||||
}
|
||||
|
||||
allLogs := make([]*types.Log, 0)
|
||||
for _, r := range work.receipts {
|
||||
|
|
@ -184,11 +182,12 @@ func (miner *Miner) generateWork(genParam *generateParams, witness bool) *newPay
|
|||
// I considered trying to instantiate the beacon consensus engine with a tracer.
|
||||
// however, the BAL tracer instance is used once per block, while the engine object
|
||||
// lives for the entire time the client is running.
|
||||
onBlockFinalization := func() {
|
||||
onBlockFinalization := func() *bal.BlockAccessList {
|
||||
if miner.chainConfig.IsAmsterdam(work.header.Number, work.header.Time) {
|
||||
work.alTracer.OnBlockFinalization()
|
||||
body.AccessList = work.alTracer.AccessList().ToEncodingObj()
|
||||
return work.alTracer.AccessList().ToEncodingObj()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
block, err := miner.engine.FinalizeAndAssemble(miner.chain, work.header, work.state, &body, work.receipts, onBlockFinalization)
|
||||
|
|
|
|||
Loading…
Reference in a new issue