mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-03-11 05:39:03 +00:00
more documentation
This commit is contained in:
parent
2e84d09c1c
commit
c2c132d6a0
9 changed files with 123 additions and 157 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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{
|
||||
|
|
|
|||
Loading…
Reference in a new issue