more documentation

This commit is contained in:
Jared Wasinger 2025-10-10 20:02:43 +08:00
parent 2e84d09c1c
commit c2c132d6a0
9 changed files with 123 additions and 157 deletions

View file

@ -272,13 +272,8 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
return err
}
}
if chain.Config().IsAmsterdam(header.Number, header.Time) {
if header.BlockAccessListHash == nil {
// TODO: (self study). figure out if any of the header checks here overlap with the
// other location that I validate the block access list hash.
return fmt.Errorf("block access list hash must be set in header post-Amsterdam")
}
if chain.Config().IsAmsterdam(header.Number, header.Time) && header.BlockAccessListHash == nil {
return fmt.Errorf("block access list hash must be set post-Amsterdam")
}
return nil
}

View file

@ -63,7 +63,6 @@ func latestBlobConfig(cfg *params.ChainConfig, time uint64) *BlobConfig {
bc *params.BlobConfig
)
switch {
case cfg.IsBPO5(london, time) && s.BPO5 != nil:
bc = s.BPO5
case cfg.IsBPO4(london, time) && s.BPO4 != nil:

View file

@ -15,15 +15,11 @@ type accountPrestate struct {
code []byte
}
// BlockAccessListTracer constructs an EIP-7928 block access list from the
// execution of a block
// BlockAccessListTracer is a tracer which gathers state accesses/mutations
// from the execution of a block. It is used for constructing and verifying
// EIP-7928 block access lists.
type BlockAccessListTracer struct {
// this is a set of access lists for each call scope. the overall block access lists
// is accrued at index 0, while the access lists of various nested execution
// scopes are in the proceeding indices.
// When an execution scope terminates in a non-reverting fashion, the changes are
// merged into the access list of the parent scope.
accessList *bal.ConstructionBlockAccessList
builder *bal.BlockAccessListBuilder
// the access list index that changes are currently being recorded into
balIdx uint16
@ -32,7 +28,7 @@ type BlockAccessListTracer struct {
// NewBlockAccessListTracer returns an BlockAccessListTracer and a set of hooks
func NewBlockAccessListTracer() (*BlockAccessListTracer, *tracing.Hooks) {
balTracer := &BlockAccessListTracer{
accessList: bal.NewConstructionBlockAccessList(),
builder: bal.NewConstructionBlockAccessList(),
}
hooks := &tracing.Hooks{
OnBlockFinalization: balTracer.OnBlockFinalization,
@ -58,62 +54,62 @@ func NewBlockAccessListTracer() (*BlockAccessListTracer, *tracing.Hooks) {
// AccessList returns the constructed access list.
// It is assumed that this is only called after all the block state changes
// have been executed and the block has been finalized.
func (a *BlockAccessListTracer) AccessList() *bal.ConstructionBlockAccessList {
return a.accessList
func (a *BlockAccessListTracer) AccessList() *bal.BlockAccessListBuilder {
return a.builder
}
func (a *BlockAccessListTracer) OnPreTxExecutionDone() {
a.accessList.FinalisePendingChanges(0)
a.builder.FinalisePendingChanges(0)
a.balIdx++
}
func (a *BlockAccessListTracer) TxEndHook(receipt *types.Receipt, err error) {
a.accessList.FinalisePendingChanges(a.balIdx)
a.builder.FinalisePendingChanges(a.balIdx)
a.balIdx++
}
func (a *BlockAccessListTracer) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
a.accessList.EnterScope()
a.builder.EnterScope()
}
func (a *BlockAccessListTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
a.accessList.ExitScope(reverted)
a.builder.ExitScope(reverted)
}
func (a *BlockAccessListTracer) OnCodeChange(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte, reason tracing.CodeChangeReason) {
// TODO: if we don't have this equality check, some tests fail. should be investigated.
// probably the tracer shouldn't invoke code change if the code didn't actually change tho.
if prevCodeHash != codeHash {
a.accessList.CodeChange(addr, prevCode, code)
a.builder.CodeChange(addr, prevCode, code)
}
}
func (a *BlockAccessListTracer) OnSelfDestruct(addr common.Address) {
a.accessList.SelfDestruct(addr)
a.builder.SelfDestruct(addr)
}
func (a *BlockAccessListTracer) OnBlockFinalization() {
a.accessList.FinalisePendingChanges(a.balIdx)
a.builder.FinalisePendingChanges(a.balIdx)
}
func (a *BlockAccessListTracer) OnBalanceChange(addr common.Address, prevBalance, newBalance *big.Int, _ tracing.BalanceChangeReason) {
newU256 := new(uint256.Int).SetBytes(newBalance.Bytes())
prevU256 := new(uint256.Int).SetBytes(prevBalance.Bytes())
a.accessList.BalanceChange(addr, prevU256, newU256)
a.builder.BalanceChange(addr, prevU256, newU256)
}
func (a *BlockAccessListTracer) OnNonceChange(addr common.Address, prev uint64, new uint64, reason tracing.NonceChangeReason) {
a.accessList.NonceChange(addr, prev, new)
a.builder.NonceChange(addr, prev, new)
}
func (a *BlockAccessListTracer) OnStorageRead(addr common.Address, key common.Hash) {
a.accessList.StorageRead(addr, key)
a.builder.StorageRead(addr, key)
}
func (a *BlockAccessListTracer) OnAcountRead(addr common.Address) {
a.accessList.AccountRead(addr)
a.builder.AccountRead(addr)
}
func (a *BlockAccessListTracer) OnStorageChange(addr common.Address, slot common.Hash, prev common.Hash, new common.Hash) {
a.accessList.StorageWrite(addr, slot, prev, new)
a.builder.StorageWrite(addr, slot, prev, new)
}

View file

@ -114,8 +114,6 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
if v.config.IsAmsterdam(block.Number(), block.Time()) {
if block.Body().AccessList == nil {
return fmt.Errorf("access list not present in block body")
} else if block.Header().BlockAccessListHash == nil {
return fmt.Errorf("access list hash not present in block header")
} else 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(); err != nil {

View file

@ -125,7 +125,7 @@ func (p *ParallelStateProcessor) prepareExecResult(block *types.Block, allStateR
postTxState.Finalise(true)
balTracer.OnBlockFinalization()
diff, stateReads := balTracer.accessList.FinalizedIdxChanges()
diff, stateReads := balTracer.builder.FinalizedIdxChanges()
allStateReads.Merge(stateReads)
balIdx := len(block.Transactions()) + 1
@ -278,7 +278,7 @@ func (p *ParallelStateProcessor) execTx(block *types.Block, tx *types.Transactio
return &txExecResult{err: err}
}
diff, accesses := balTracer.accessList.FinalizedIdxChanges()
diff, accesses := balTracer.builder.FinalizedIdxChanges()
if err := db.BlockAccessList().ValidateStateDiff(txIdx+1, diff); err != nil {
return &txExecResult{err: err}
}
@ -335,7 +335,7 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
// TODO: weird that I have to manually call finalize here
balTracer.OnPreTxExecutionDone()
diff, stateReads := balTracer.accessList.FinalizedIdxChanges()
diff, stateReads := balTracer.builder.FinalizedIdxChanges()
if err := statedb.BlockAccessList().ValidateStateDiff(0, diff); err != nil {
return nil, err
}

View file

@ -67,7 +67,7 @@ func (p *prestateResolver) account(addr common.Address) *types.StateAccount {
return res.(*types.StateAccount)
}
func (r *BALReader) initObjFromDiff(db *StateDB, addr common.Address, a *types.StateAccount, diff *bal.AccountState) *stateObject {
func (r *BALReader) initObjFromDiff(db *StateDB, addr common.Address, a *types.StateAccount, diff *bal.AccountMutations) *stateObject {
var acct *types.StateAccount
if a == nil {
acct = &types.StateAccount{
@ -104,7 +104,7 @@ func (r *BALReader) initObjFromDiff(db *StateDB, addr common.Address, a *types.S
return obj
}
func (s *BALReader) initMutatedObjFromDiff(db *StateDB, addr common.Address, a *types.StateAccount, diff *bal.AccountState) *stateObject {
func (s *BALReader) initMutatedObjFromDiff(db *StateDB, addr common.Address, a *types.StateAccount, diff *bal.AccountMutations) *stateObject {
var acct *types.StateAccount
if a == nil {
acct = &types.StateAccount{
@ -231,7 +231,7 @@ func (r *BALReader) StateRoot(prestate *StateDB) (root common.Hash, prestateLoad
// changesAt returns all state changes at the given index.
func (r *BALReader) changesAt(idx int) *bal.StateDiff {
res := &bal.StateDiff{make(map[common.Address]*bal.AccountState)}
res := &bal.StateDiff{make(map[common.Address]*bal.AccountMutations)}
for addr, _ := range r.accesses {
accountChanges := r.accountChangesAt(addr, idx)
if accountChanges != nil {
@ -243,13 +243,13 @@ func (r *BALReader) changesAt(idx int) *bal.StateDiff {
// accountChangesAt returns the state changes of an account at a given index,
// or nil if there are no changes.
func (r *BALReader) accountChangesAt(addr common.Address, idx int) *bal.AccountState {
func (r *BALReader) accountChangesAt(addr common.Address, idx int) *bal.AccountMutations {
acct, exist := r.accesses[addr]
if !exist {
return nil
}
var res bal.AccountState
var res bal.AccountMutations
for i := len(acct.BalanceChanges) - 1; i >= 0; i-- {
if acct.BalanceChanges[i].TxIdx == uint16(idx) {
@ -321,13 +321,13 @@ func (r *BALReader) readAccount(db *StateDB, addr common.Address, idx int) *stat
}
// readAccountDiff returns the accumulated state changes of an account up through idx.
func (r *BALReader) readAccountDiff(addr common.Address, idx int) *bal.AccountState {
func (r *BALReader) readAccountDiff(addr common.Address, idx int) *bal.AccountMutations {
diff, exist := r.accesses[addr]
if !exist {
return nil
}
var res bal.AccountState
var res bal.AccountMutations
for i := 0; i < len(diff.BalanceChanges) && diff.BalanceChanges[i].TxIdx <= uint16(idx); i++ {
res.Balance = diff.BalanceChanges[i].Balance

View file

@ -28,21 +28,21 @@ import (
// idxAccessListBuilder is responsible for producing the state accesses and
// reads recorded within the scope of a single index in the access list.
type idxAccessListBuilder struct {
// stores the tx-prestate values of any account/storage values which were modified
//
// TODO: it's a bit unfortunate that the prestate.StorageWrites is reused here to
// represent the prestate values of keys which were written and it would be nice to
// somehow make it clear that the field can contain both the mutated values or the
// prestate depending on the context (or find a cleaner solution entirely, instead
// of reusing the field here)
prestates map[common.Address]*AccountState
// stores the previous values of any account data that was modified in the
// current index.
prestates map[common.Address]*partialAccountState
// a stack which maintains a set of state mutations/reads for each EVM
// execution frame.
//
// <boilerplate for description about how the execution stack mechanics work when call frames end with/without erring/reverting>
// TODO: how does this construction handle EVM errors which terminate execution of a transaction entirely.
accessesStack []map[common.Address]*constructionAccountAccess
}
func newAccessListBuilder() *idxAccessListBuilder {
return &idxAccessListBuilder{
make(map[common.Address]*AccountState),
make(map[common.Address]*partialAccountState),
[]map[common.Address]*constructionAccountAccess{
make(map[common.Address]*constructionAccountAccess),
},
@ -65,7 +65,7 @@ func (c *idxAccessListBuilder) accountRead(address common.Address) {
func (c *idxAccessListBuilder) storageWrite(address common.Address, key, prevVal, newVal common.Hash) {
if _, ok := c.prestates[address]; !ok {
c.prestates[address] = &AccountState{}
c.prestates[address] = &AccountMutations{}
}
if c.prestates[address].StorageWrites == nil {
c.prestates[address].StorageWrites = make(map[common.Hash]common.Hash)
@ -83,7 +83,7 @@ func (c *idxAccessListBuilder) storageWrite(address common.Address, key, prevVal
func (c *idxAccessListBuilder) balanceChange(address common.Address, prev, cur *uint256.Int) {
if _, ok := c.prestates[address]; !ok {
c.prestates[address] = &AccountState{}
c.prestates[address] = &AccountMutations{}
}
if c.prestates[address].Balance == nil {
c.prestates[address].Balance = prev
@ -104,7 +104,7 @@ func (c *idxAccessListBuilder) codeChange(address common.Address, prev, cur []by
}
if _, ok := c.prestates[address]; !ok {
c.prestates[address] = &AccountState{}
c.prestates[address] = &AccountMutations{}
}
if c.prestates[address].Code == nil {
c.prestates[address].Code = prev
@ -145,7 +145,7 @@ func (c *idxAccessListBuilder) selfDestruct(address common.Address) {
func (c *idxAccessListBuilder) nonceChange(address common.Address, prev, cur uint64) {
if _, ok := c.prestates[address]; !ok {
c.prestates[address] = &AccountState{}
c.prestates[address] = &AccountMutations{}
}
if c.prestates[address].Nonce == nil {
c.prestates[address].Nonce = &prev
@ -186,7 +186,7 @@ func (c *idxAccessListBuilder) exitScope(reverted bool) {
// state which was accessed. The idxAccessListBuilder instance should be discarded
// after calling finalise.
func (a *idxAccessListBuilder) finalise() (*StateDiff, StateAccesses) {
diff := &StateDiff{make(map[common.Address]*AccountState)}
diff := &StateDiff{make(map[common.Address]*AccountMutations)}
stateAccesses := make(StateAccesses)
for addr, access := range a.accessesStack[0] {
@ -224,7 +224,7 @@ func (a *idxAccessListBuilder) finalise() (*StateDiff, StateAccesses) {
}
stateAccesses[addr] = access.storageReads
diff.Mutations[addr] = &AccountState{
diff.Mutations[addr] = &AccountMutations{
Balance: access.balance,
Nonce: access.nonce,
Code: access.code,
@ -235,15 +235,15 @@ func (a *idxAccessListBuilder) finalise() (*StateDiff, StateAccesses) {
return diff, stateAccesses
}
func (c *ConstructionBlockAccessList) FinalisePendingChanges(idx uint16) {
diff, accesses := c.nonFinalizedAccessList.finalise()
c.nonFinalizedAccessList = newAccessListBuilder()
func (c *BlockAccessListBuilder) FinalisePendingChanges(idx uint16) {
diff, accesses := c.idxBuilder.finalise()
c.idxBuilder = newAccessListBuilder()
for addr, stateDiff := range diff.Mutations {
acctChanges, ok := c.Accounts[addr]
acctChanges, ok := c.FinalizedAccesses[addr]
if !ok {
acctChanges = &ConstructionAccountAccesses{}
c.Accounts[addr] = acctChanges
c.FinalizedAccesses[addr] = acctChanges
}
if stateDiff.Nonce != nil {
@ -286,10 +286,10 @@ func (c *ConstructionBlockAccessList) FinalisePendingChanges(idx uint16) {
}
}
for addr, stateAccesses := range accesses {
acctAccess, ok := c.Accounts[addr]
acctAccess, ok := c.FinalizedAccesses[addr]
if !ok {
acctAccess = &ConstructionAccountAccesses{}
c.Accounts[addr] = acctAccess
c.FinalizedAccesses[addr] = acctAccess
}
for key := range stateAccesses {
@ -308,39 +308,39 @@ func (c *ConstructionBlockAccessList) FinalisePendingChanges(idx uint16) {
c.lastFinalizedAccesses = accesses
}
func (c *ConstructionBlockAccessList) StorageRead(address common.Address, key common.Hash) {
c.nonFinalizedAccessList.storageRead(address, key)
func (c *BlockAccessListBuilder) StorageRead(address common.Address, key common.Hash) {
c.idxBuilder.storageRead(address, key)
}
func (c *ConstructionBlockAccessList) AccountRead(address common.Address) {
c.nonFinalizedAccessList.accountRead(address)
func (c *BlockAccessListBuilder) AccountRead(address common.Address) {
c.idxBuilder.accountRead(address)
}
func (c *ConstructionBlockAccessList) StorageWrite(address common.Address, key, prevVal, newVal common.Hash) {
c.nonFinalizedAccessList.storageWrite(address, key, prevVal, newVal)
func (c *BlockAccessListBuilder) StorageWrite(address common.Address, key, prevVal, newVal common.Hash) {
c.idxBuilder.storageWrite(address, key, prevVal, newVal)
}
func (c *ConstructionBlockAccessList) BalanceChange(address common.Address, prev, cur *uint256.Int) {
c.nonFinalizedAccessList.balanceChange(address, prev, cur)
func (c *BlockAccessListBuilder) BalanceChange(address common.Address, prev, cur *uint256.Int) {
c.idxBuilder.balanceChange(address, prev, cur)
}
func (c *ConstructionBlockAccessList) NonceChange(address common.Address, prev, cur uint64) {
c.nonFinalizedAccessList.nonceChange(address, prev, cur)
func (c *BlockAccessListBuilder) NonceChange(address common.Address, prev, cur uint64) {
c.idxBuilder.nonceChange(address, prev, cur)
}
func (c *ConstructionBlockAccessList) CodeChange(address common.Address, prev, cur []byte) {
c.nonFinalizedAccessList.codeChange(address, prev, cur)
func (c *BlockAccessListBuilder) CodeChange(address common.Address, prev, cur []byte) {
c.idxBuilder.codeChange(address, prev, cur)
}
func (c *ConstructionBlockAccessList) SelfDestruct(address common.Address) {
c.nonFinalizedAccessList.selfDestruct(address)
func (c *BlockAccessListBuilder) SelfDestruct(address common.Address) {
c.idxBuilder.selfDestruct(address)
}
func (c *ConstructionBlockAccessList) EnterScope() {
c.nonFinalizedAccessList.enterScope()
func (c *BlockAccessListBuilder) EnterScope() {
c.idxBuilder.enterScope()
}
func (c *ConstructionBlockAccessList) ExitScope(reverted bool) {
c.nonFinalizedAccessList.exitScope(reverted)
func (c *BlockAccessListBuilder) ExitScope(reverted bool) {
c.idxBuilder.exitScope(reverted)
}
// TODO: the BalReader Validation method should accept the computed values as
// a index/StateDiff/StateAccesses trio.
// BAL tracer maintains a ConstructionBlockAccessList.
// BAL tracer maintains a BlockAccessListBuilder.
// For each BAL index, it instantiates an idxAccessListBuilder and
// appends the result to the access list where appropriate
@ -505,31 +505,19 @@ func (c *constructionAccountAccess) NonceChange(cur uint64) {
c.nonce = &cur
}
// NewConstructionAccountAccesses initializes the account access object.
func NewConstructionAccountAccesses() *ConstructionAccountAccesses {
return &ConstructionAccountAccesses{
StorageWrites: make(map[common.Hash]map[uint16]common.Hash),
StorageReads: make(map[common.Hash]struct{}),
BalanceChanges: make(map[uint16]*uint256.Int),
NonceChanges: make(map[uint16]uint64),
CodeChanges: make(map[uint16]CodeChange),
}
}
// BlockAccessListBuilder is used to build an EIP-7928 block access list
type BlockAccessListBuilder struct {
FinalizedAccesses map[common.Address]*ConstructionAccountAccesses
// ConstructionBlockAccessList contains post-block modified state and some state accessed
// in execution (account addresses and storage keys).
type ConstructionBlockAccessList struct {
Accounts map[common.Address]*ConstructionAccountAccesses
nonFinalizedAccessList *idxAccessListBuilder
idxBuilder *idxAccessListBuilder
lastFinalizedMutations *StateDiff
lastFinalizedAccesses StateAccesses
}
// NewConstructionBlockAccessList instantiates an empty access list.
func NewConstructionBlockAccessList() *ConstructionBlockAccessList {
return &ConstructionBlockAccessList{
func NewConstructionBlockAccessList() *BlockAccessListBuilder {
return &BlockAccessListBuilder{
make(map[common.Address]*ConstructionAccountAccesses),
newAccessListBuilder(),
nil,
@ -538,9 +526,9 @@ func NewConstructionBlockAccessList() *ConstructionBlockAccessList {
}
// Copy returns a deep copy of the access list.
func (c *ConstructionBlockAccessList) Copy() *ConstructionBlockAccessList {
func (c *BlockAccessListBuilder) Copy() *BlockAccessListBuilder {
res := NewConstructionBlockAccessList()
for addr, aa := range c.Accounts {
for addr, aa := range c.FinalizedAccesses {
var aaCopy ConstructionAccountAccesses
slotWrites := make(map[common.Hash]map[uint16]common.Hash, len(aa.StorageWrites))
@ -564,21 +552,28 @@ func (c *ConstructionBlockAccessList) Copy() *ConstructionBlockAccessList {
Code: bytes.Clone(codeChange.Code),
}
}
res.Accounts[addr] = &aaCopy
res.FinalizedAccesses[addr] = &aaCopy
}
return res
}
func (c *ConstructionBlockAccessList) FinalizedIdxChanges() (*StateDiff, StateAccesses) {
// FinalizedIdxChanges returns the state mutations and accesses recorded in the latest
// access list index that was finalized.
func (c *BlockAccessListBuilder) FinalizedIdxChanges() (*StateDiff, StateAccesses) {
return c.lastFinalizedMutations, c.lastFinalizedAccesses
}
// StateDiff contains state mutations occuring over one or more access list
// index.
type StateDiff struct {
Mutations map[common.Address]*AccountState `json:"Mutations,omitempty"`
Mutations map[common.Address]*AccountMutations `json:"Mutations,omitempty"`
}
// StateAccesses contains a set of accounts/storage that were accessed during the
// execution of one or more access list indices.
type StateAccesses map[common.Address]map[common.Hash]struct{}
// Merge combines adds the accesses from other into s.
func (s *StateAccesses) Merge(other StateAccesses) {
for addr, accesses := range other {
if _, ok := (*s)[addr]; !ok {
@ -590,18 +585,24 @@ func (s *StateAccesses) Merge(other StateAccesses) {
}
}
type AccountState struct {
type partialAccountState struct {
balance *uint256.Int `json:"Balance,omitempty"`
nonce *uint64 `json:"Nonce,omitempty"`
code ContractCode `json:"Code,omitempty"`
storage map[common.Hash]common.Hash `json:"StorageWrites,omitempty"`
}
// AccountMutations contains mutations that were made to an account across
// one or more access list indices.
type AccountMutations struct {
Balance *uint256.Int `json:"Balance,omitempty"`
Nonce *uint64 `json:"Nonce,omitempty"`
Code ContractCode `json:"Code,omitempty"`
StorageWrites map[common.Hash]common.Hash `json:"StorageWrites,omitempty"`
}
func (a *AccountState) Empty() bool {
return a.Balance == nil && a.Nonce == nil && a.Code == nil && len(a.StorageWrites) == 0
}
func (a *AccountState) String() string {
// String returns a human-readable JSON representation of the account mutations.
func (a *AccountMutations) String() string {
var res bytes.Buffer
enc := json.NewEncoder(&res)
enc.SetIndent("", " ")
@ -609,39 +610,8 @@ func (a *AccountState) String() string {
return res.String()
}
// Merge the changes of a future AccountState into the caller, resulting in the
// combined state changes through next.
func (a *AccountState) Merge(next *AccountState) {
if next.Balance != nil {
a.Balance = next.Balance
}
if next.Nonce != nil {
a.Nonce = next.Nonce
}
if next.Code != nil {
a.Code = next.Code
}
if next.StorageWrites != nil {
if a.StorageWrites == nil {
a.StorageWrites = maps.Clone(next.StorageWrites)
} else {
for key, val := range next.StorageWrites {
a.StorageWrites[key] = val
}
}
}
}
func NewEmptyAccountState() *AccountState {
return &AccountState{
nil,
nil,
nil,
nil,
}
}
func (a *AccountState) Eq(other *AccountState) bool {
// Eq returns whether the calling instance is equal to the provided one.
func (a *AccountMutations) Eq(other *AccountMutations) bool {
if a.Balance != nil || other.Balance != nil {
if a.Balance == nil || other.Balance == nil {
return false
@ -678,8 +648,14 @@ func (a *AccountState) Eq(other *AccountState) bool {
return true
}
func (a *AccountState) Copy() *AccountState {
res := NewEmptyAccountState()
// Copy returns a deep-copy of the instance.
func (a *AccountMutations) Copy() *AccountMutations {
res := &AccountMutations{
nil,
nil,
nil,
nil,
}
if a.Nonce != nil {
res.Nonce = new(uint64)
*res.Nonce = *a.Nonce
@ -696,6 +672,7 @@ func (a *AccountState) Copy() *AccountState {
return res
}
// String returns the state diff as a formatted JSON string.
func (s *StateDiff) String() string {
var res bytes.Buffer
enc := json.NewEncoder(&res)
@ -733,8 +710,9 @@ func (s *StateDiff) Merge(next *StateDiff) {
}
}
// Copy returns a deep copy of the StateDiff
func (s *StateDiff) Copy() *StateDiff {
res := &StateDiff{make(map[common.Address]*AccountState)}
res := &StateDiff{make(map[common.Address]*AccountMutations)}
for addr, accountDiff := range s.Mutations {
cpy := accountDiff.Copy()
res.Mutations[addr] = cpy

View file

@ -38,7 +38,7 @@ import (
// These are objects used as input for the access list encoding. They mirror
// the spec format.
// BlockAccessList is the encoding format of ConstructionBlockAccessList.
// BlockAccessList is the encoding format of BlockAccessListBuilder.
type BlockAccessList []AccountAccess
func (e BlockAccessList) EncodeRLP(_w io.Writer) error {
@ -245,11 +245,11 @@ func (e *AccountAccess) Copy() AccountAccess {
}
// EncodeRLP returns the RLP-encoded access list
func (c *ConstructionBlockAccessList) EncodeRLP(wr io.Writer) error {
func (c *BlockAccessListBuilder) EncodeRLP(wr io.Writer) error {
return c.ToEncodingObj().EncodeRLP(wr)
}
var _ rlp.Encoder = &ConstructionBlockAccessList{}
var _ rlp.Encoder = &BlockAccessListBuilder{}
// toEncodingObj creates an instance of the ConstructionAccountAccesses of the type that is
// used as input for the encoding.
@ -325,16 +325,16 @@ func (a *ConstructionAccountAccesses) toEncodingObj(addr common.Address) Account
// ToEncodingObj returns an instance of the access list expressed as the type
// which is used as input for the encoding/decoding.
func (c *ConstructionBlockAccessList) ToEncodingObj() *BlockAccessList {
func (c *BlockAccessListBuilder) ToEncodingObj() *BlockAccessList {
var addresses []common.Address
for addr := range c.Accounts {
for addr := range c.FinalizedAccesses {
addresses = append(addresses, addr)
}
slices.SortFunc(addresses, common.Address.Cmp)
var res BlockAccessList
for _, addr := range addresses {
res = append(res, c.Accounts[addr].toEncodingObj(addr))
res = append(res, c.FinalizedAccesses[addr].toEncodingObj(addr))
}
return &res
}

View file

@ -36,8 +36,8 @@ func equalBALs(a *BlockAccessList, b *BlockAccessList) bool {
return true
}
func makeTestConstructionBAL() *ConstructionBlockAccessList {
return &ConstructionBlockAccessList{
func makeTestConstructionBAL() *BlockAccessListBuilder {
return &BlockAccessListBuilder{
map[common.Address]*ConstructionAccountAccesses{
common.BytesToAddress([]byte{0xff, 0xff}): {
StorageWrites: map[common.Hash]map[uint16]common.Hash{