mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-22 07:49:26 +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
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if chain.Config().IsAmsterdam(header.Number, header.Time) && header.BlockAccessListHash == nil {
|
||||||
if chain.Config().IsAmsterdam(header.Number, header.Time) {
|
return fmt.Errorf("block access list hash must be set post-Amsterdam")
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@ func latestBlobConfig(cfg *params.ChainConfig, time uint64) *BlobConfig {
|
||||||
bc *params.BlobConfig
|
bc *params.BlobConfig
|
||||||
)
|
)
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
case cfg.IsBPO5(london, time) && s.BPO5 != nil:
|
case cfg.IsBPO5(london, time) && s.BPO5 != nil:
|
||||||
bc = s.BPO5
|
bc = s.BPO5
|
||||||
case cfg.IsBPO4(london, time) && s.BPO4 != nil:
|
case cfg.IsBPO4(london, time) && s.BPO4 != nil:
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,11 @@ type accountPrestate struct {
|
||||||
code []byte
|
code []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockAccessListTracer constructs an EIP-7928 block access list from the
|
// BlockAccessListTracer is a tracer which gathers state accesses/mutations
|
||||||
// execution of a block
|
// from the execution of a block. It is used for constructing and verifying
|
||||||
|
// EIP-7928 block access lists.
|
||||||
type BlockAccessListTracer struct {
|
type BlockAccessListTracer struct {
|
||||||
// this is a set of access lists for each call scope. the overall block access lists
|
builder *bal.BlockAccessListBuilder
|
||||||
// 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
|
|
||||||
|
|
||||||
// the access list index that changes are currently being recorded into
|
// the access list index that changes are currently being recorded into
|
||||||
balIdx uint16
|
balIdx uint16
|
||||||
|
|
@ -32,7 +28,7 @@ type BlockAccessListTracer struct {
|
||||||
// NewBlockAccessListTracer returns an BlockAccessListTracer and a set of hooks
|
// NewBlockAccessListTracer returns an BlockAccessListTracer and a set of hooks
|
||||||
func NewBlockAccessListTracer() (*BlockAccessListTracer, *tracing.Hooks) {
|
func NewBlockAccessListTracer() (*BlockAccessListTracer, *tracing.Hooks) {
|
||||||
balTracer := &BlockAccessListTracer{
|
balTracer := &BlockAccessListTracer{
|
||||||
accessList: bal.NewConstructionBlockAccessList(),
|
builder: bal.NewConstructionBlockAccessList(),
|
||||||
}
|
}
|
||||||
hooks := &tracing.Hooks{
|
hooks := &tracing.Hooks{
|
||||||
OnBlockFinalization: balTracer.OnBlockFinalization,
|
OnBlockFinalization: balTracer.OnBlockFinalization,
|
||||||
|
|
@ -58,62 +54,62 @@ func NewBlockAccessListTracer() (*BlockAccessListTracer, *tracing.Hooks) {
|
||||||
// AccessList returns the constructed access list.
|
// AccessList returns the constructed access list.
|
||||||
// It is assumed that this is only called after all the block state changes
|
// It is assumed that this is only called after all the block state changes
|
||||||
// have been executed and the block has been finalized.
|
// have been executed and the block has been finalized.
|
||||||
func (a *BlockAccessListTracer) AccessList() *bal.ConstructionBlockAccessList {
|
func (a *BlockAccessListTracer) AccessList() *bal.BlockAccessListBuilder {
|
||||||
return a.accessList
|
return a.builder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *BlockAccessListTracer) OnPreTxExecutionDone() {
|
func (a *BlockAccessListTracer) OnPreTxExecutionDone() {
|
||||||
a.accessList.FinalisePendingChanges(0)
|
a.builder.FinalisePendingChanges(0)
|
||||||
a.balIdx++
|
a.balIdx++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *BlockAccessListTracer) TxEndHook(receipt *types.Receipt, err error) {
|
func (a *BlockAccessListTracer) TxEndHook(receipt *types.Receipt, err error) {
|
||||||
a.accessList.FinalisePendingChanges(a.balIdx)
|
a.builder.FinalisePendingChanges(a.balIdx)
|
||||||
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) {
|
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) {
|
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) {
|
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.
|
// 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.
|
// probably the tracer shouldn't invoke code change if the code didn't actually change tho.
|
||||||
if prevCodeHash != codeHash {
|
if prevCodeHash != codeHash {
|
||||||
a.accessList.CodeChange(addr, prevCode, code)
|
a.builder.CodeChange(addr, prevCode, code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *BlockAccessListTracer) OnSelfDestruct(addr common.Address) {
|
func (a *BlockAccessListTracer) OnSelfDestruct(addr common.Address) {
|
||||||
a.accessList.SelfDestruct(addr)
|
a.builder.SelfDestruct(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *BlockAccessListTracer) OnBlockFinalization() {
|
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) {
|
func (a *BlockAccessListTracer) OnBalanceChange(addr common.Address, prevBalance, newBalance *big.Int, _ tracing.BalanceChangeReason) {
|
||||||
newU256 := new(uint256.Int).SetBytes(newBalance.Bytes())
|
newU256 := new(uint256.Int).SetBytes(newBalance.Bytes())
|
||||||
prevU256 := new(uint256.Int).SetBytes(prevBalance.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) {
|
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) {
|
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) {
|
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) {
|
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 v.config.IsAmsterdam(block.Number(), block.Time()) {
|
||||||
if block.Body().AccessList == nil {
|
if block.Body().AccessList == nil {
|
||||||
return fmt.Errorf("access list not present in block body")
|
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() {
|
} 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)
|
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 {
|
} else if err := block.Body().AccessList.Validate(); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ func (p *ParallelStateProcessor) prepareExecResult(block *types.Block, allStateR
|
||||||
postTxState.Finalise(true)
|
postTxState.Finalise(true)
|
||||||
|
|
||||||
balTracer.OnBlockFinalization()
|
balTracer.OnBlockFinalization()
|
||||||
diff, stateReads := balTracer.accessList.FinalizedIdxChanges()
|
diff, stateReads := balTracer.builder.FinalizedIdxChanges()
|
||||||
allStateReads.Merge(stateReads)
|
allStateReads.Merge(stateReads)
|
||||||
|
|
||||||
balIdx := len(block.Transactions()) + 1
|
balIdx := len(block.Transactions()) + 1
|
||||||
|
|
@ -278,7 +278,7 @@ func (p *ParallelStateProcessor) execTx(block *types.Block, tx *types.Transactio
|
||||||
return &txExecResult{err: err}
|
return &txExecResult{err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
diff, accesses := balTracer.accessList.FinalizedIdxChanges()
|
diff, accesses := balTracer.builder.FinalizedIdxChanges()
|
||||||
if err := db.BlockAccessList().ValidateStateDiff(txIdx+1, diff); err != nil {
|
if err := db.BlockAccessList().ValidateStateDiff(txIdx+1, diff); err != nil {
|
||||||
return &txExecResult{err: err}
|
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
|
// TODO: weird that I have to manually call finalize here
|
||||||
balTracer.OnPreTxExecutionDone()
|
balTracer.OnPreTxExecutionDone()
|
||||||
|
|
||||||
diff, stateReads := balTracer.accessList.FinalizedIdxChanges()
|
diff, stateReads := balTracer.builder.FinalizedIdxChanges()
|
||||||
if err := statedb.BlockAccessList().ValidateStateDiff(0, diff); err != nil {
|
if err := statedb.BlockAccessList().ValidateStateDiff(0, diff); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ func (p *prestateResolver) account(addr common.Address) *types.StateAccount {
|
||||||
return res.(*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
|
var acct *types.StateAccount
|
||||||
if a == nil {
|
if a == nil {
|
||||||
acct = &types.StateAccount{
|
acct = &types.StateAccount{
|
||||||
|
|
@ -104,7 +104,7 @@ func (r *BALReader) initObjFromDiff(db *StateDB, addr common.Address, a *types.S
|
||||||
return obj
|
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
|
var acct *types.StateAccount
|
||||||
if a == nil {
|
if a == nil {
|
||||||
acct = &types.StateAccount{
|
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.
|
// changesAt returns all state changes at the given index.
|
||||||
func (r *BALReader) changesAt(idx int) *bal.StateDiff {
|
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 {
|
for addr, _ := range r.accesses {
|
||||||
accountChanges := r.accountChangesAt(addr, idx)
|
accountChanges := r.accountChangesAt(addr, idx)
|
||||||
if accountChanges != nil {
|
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,
|
// accountChangesAt returns the state changes of an account at a given index,
|
||||||
// or nil if there are no changes.
|
// 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]
|
acct, exist := r.accesses[addr]
|
||||||
if !exist {
|
if !exist {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var res bal.AccountState
|
var res bal.AccountMutations
|
||||||
|
|
||||||
for i := len(acct.BalanceChanges) - 1; i >= 0; i-- {
|
for i := len(acct.BalanceChanges) - 1; i >= 0; i-- {
|
||||||
if acct.BalanceChanges[i].TxIdx == uint16(idx) {
|
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.
|
// 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]
|
diff, exist := r.accesses[addr]
|
||||||
if !exist {
|
if !exist {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var res bal.AccountState
|
var res bal.AccountMutations
|
||||||
|
|
||||||
for i := 0; i < len(diff.BalanceChanges) && diff.BalanceChanges[i].TxIdx <= uint16(idx); i++ {
|
for i := 0; i < len(diff.BalanceChanges) && diff.BalanceChanges[i].TxIdx <= uint16(idx); i++ {
|
||||||
res.Balance = diff.BalanceChanges[i].Balance
|
res.Balance = diff.BalanceChanges[i].Balance
|
||||||
|
|
|
||||||
|
|
@ -28,21 +28,21 @@ import (
|
||||||
// idxAccessListBuilder is responsible for producing the state accesses and
|
// idxAccessListBuilder is responsible for producing the state accesses and
|
||||||
// reads recorded within the scope of a single index in the access list.
|
// reads recorded within the scope of a single index in the access list.
|
||||||
type idxAccessListBuilder struct {
|
type idxAccessListBuilder struct {
|
||||||
// stores the tx-prestate values of any account/storage values which were modified
|
// stores the previous values of any account data that was modified in the
|
||||||
//
|
// current index.
|
||||||
// TODO: it's a bit unfortunate that the prestate.StorageWrites is reused here to
|
prestates map[common.Address]*partialAccountState
|
||||||
// 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
|
|
||||||
|
|
||||||
|
// 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
|
accessesStack []map[common.Address]*constructionAccountAccess
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAccessListBuilder() *idxAccessListBuilder {
|
func newAccessListBuilder() *idxAccessListBuilder {
|
||||||
return &idxAccessListBuilder{
|
return &idxAccessListBuilder{
|
||||||
make(map[common.Address]*AccountState),
|
make(map[common.Address]*partialAccountState),
|
||||||
[]map[common.Address]*constructionAccountAccess{
|
[]map[common.Address]*constructionAccountAccess{
|
||||||
make(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) {
|
func (c *idxAccessListBuilder) storageWrite(address common.Address, key, prevVal, newVal common.Hash) {
|
||||||
if _, ok := c.prestates[address]; !ok {
|
if _, ok := c.prestates[address]; !ok {
|
||||||
c.prestates[address] = &AccountState{}
|
c.prestates[address] = &AccountMutations{}
|
||||||
}
|
}
|
||||||
if c.prestates[address].StorageWrites == nil {
|
if c.prestates[address].StorageWrites == nil {
|
||||||
c.prestates[address].StorageWrites = make(map[common.Hash]common.Hash)
|
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) {
|
func (c *idxAccessListBuilder) balanceChange(address common.Address, prev, cur *uint256.Int) {
|
||||||
if _, ok := c.prestates[address]; !ok {
|
if _, ok := c.prestates[address]; !ok {
|
||||||
c.prestates[address] = &AccountState{}
|
c.prestates[address] = &AccountMutations{}
|
||||||
}
|
}
|
||||||
if c.prestates[address].Balance == nil {
|
if c.prestates[address].Balance == nil {
|
||||||
c.prestates[address].Balance = prev
|
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 {
|
if _, ok := c.prestates[address]; !ok {
|
||||||
c.prestates[address] = &AccountState{}
|
c.prestates[address] = &AccountMutations{}
|
||||||
}
|
}
|
||||||
if c.prestates[address].Code == nil {
|
if c.prestates[address].Code == nil {
|
||||||
c.prestates[address].Code = prev
|
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) {
|
func (c *idxAccessListBuilder) nonceChange(address common.Address, prev, cur uint64) {
|
||||||
if _, ok := c.prestates[address]; !ok {
|
if _, ok := c.prestates[address]; !ok {
|
||||||
c.prestates[address] = &AccountState{}
|
c.prestates[address] = &AccountMutations{}
|
||||||
}
|
}
|
||||||
if c.prestates[address].Nonce == nil {
|
if c.prestates[address].Nonce == nil {
|
||||||
c.prestates[address].Nonce = &prev
|
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
|
// state which was accessed. The idxAccessListBuilder instance should be discarded
|
||||||
// after calling finalise.
|
// after calling finalise.
|
||||||
func (a *idxAccessListBuilder) finalise() (*StateDiff, StateAccesses) {
|
func (a *idxAccessListBuilder) finalise() (*StateDiff, StateAccesses) {
|
||||||
diff := &StateDiff{make(map[common.Address]*AccountState)}
|
diff := &StateDiff{make(map[common.Address]*AccountMutations)}
|
||||||
stateAccesses := make(StateAccesses)
|
stateAccesses := make(StateAccesses)
|
||||||
|
|
||||||
for addr, access := range a.accessesStack[0] {
|
for addr, access := range a.accessesStack[0] {
|
||||||
|
|
@ -224,7 +224,7 @@ func (a *idxAccessListBuilder) finalise() (*StateDiff, StateAccesses) {
|
||||||
}
|
}
|
||||||
|
|
||||||
stateAccesses[addr] = access.storageReads
|
stateAccesses[addr] = access.storageReads
|
||||||
diff.Mutations[addr] = &AccountState{
|
diff.Mutations[addr] = &AccountMutations{
|
||||||
Balance: access.balance,
|
Balance: access.balance,
|
||||||
Nonce: access.nonce,
|
Nonce: access.nonce,
|
||||||
Code: access.code,
|
Code: access.code,
|
||||||
|
|
@ -235,15 +235,15 @@ func (a *idxAccessListBuilder) finalise() (*StateDiff, StateAccesses) {
|
||||||
return diff, stateAccesses
|
return diff, stateAccesses
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConstructionBlockAccessList) FinalisePendingChanges(idx uint16) {
|
func (c *BlockAccessListBuilder) FinalisePendingChanges(idx uint16) {
|
||||||
diff, accesses := c.nonFinalizedAccessList.finalise()
|
diff, accesses := c.idxBuilder.finalise()
|
||||||
c.nonFinalizedAccessList = newAccessListBuilder()
|
c.idxBuilder = newAccessListBuilder()
|
||||||
|
|
||||||
for addr, stateDiff := range diff.Mutations {
|
for addr, stateDiff := range diff.Mutations {
|
||||||
acctChanges, ok := c.Accounts[addr]
|
acctChanges, ok := c.FinalizedAccesses[addr]
|
||||||
if !ok {
|
if !ok {
|
||||||
acctChanges = &ConstructionAccountAccesses{}
|
acctChanges = &ConstructionAccountAccesses{}
|
||||||
c.Accounts[addr] = acctChanges
|
c.FinalizedAccesses[addr] = acctChanges
|
||||||
}
|
}
|
||||||
|
|
||||||
if stateDiff.Nonce != nil {
|
if stateDiff.Nonce != nil {
|
||||||
|
|
@ -286,10 +286,10 @@ func (c *ConstructionBlockAccessList) FinalisePendingChanges(idx uint16) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for addr, stateAccesses := range accesses {
|
for addr, stateAccesses := range accesses {
|
||||||
acctAccess, ok := c.Accounts[addr]
|
acctAccess, ok := c.FinalizedAccesses[addr]
|
||||||
if !ok {
|
if !ok {
|
||||||
acctAccess = &ConstructionAccountAccesses{}
|
acctAccess = &ConstructionAccountAccesses{}
|
||||||
c.Accounts[addr] = acctAccess
|
c.FinalizedAccesses[addr] = acctAccess
|
||||||
}
|
}
|
||||||
|
|
||||||
for key := range stateAccesses {
|
for key := range stateAccesses {
|
||||||
|
|
@ -308,39 +308,39 @@ func (c *ConstructionBlockAccessList) FinalisePendingChanges(idx uint16) {
|
||||||
c.lastFinalizedAccesses = accesses
|
c.lastFinalizedAccesses = accesses
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConstructionBlockAccessList) StorageRead(address common.Address, key common.Hash) {
|
func (c *BlockAccessListBuilder) StorageRead(address common.Address, key common.Hash) {
|
||||||
c.nonFinalizedAccessList.storageRead(address, key)
|
c.idxBuilder.storageRead(address, key)
|
||||||
}
|
}
|
||||||
func (c *ConstructionBlockAccessList) AccountRead(address common.Address) {
|
func (c *BlockAccessListBuilder) AccountRead(address common.Address) {
|
||||||
c.nonFinalizedAccessList.accountRead(address)
|
c.idxBuilder.accountRead(address)
|
||||||
}
|
}
|
||||||
func (c *ConstructionBlockAccessList) StorageWrite(address common.Address, key, prevVal, newVal common.Hash) {
|
func (c *BlockAccessListBuilder) StorageWrite(address common.Address, key, prevVal, newVal common.Hash) {
|
||||||
c.nonFinalizedAccessList.storageWrite(address, key, prevVal, newVal)
|
c.idxBuilder.storageWrite(address, key, prevVal, newVal)
|
||||||
}
|
}
|
||||||
func (c *ConstructionBlockAccessList) BalanceChange(address common.Address, prev, cur *uint256.Int) {
|
func (c *BlockAccessListBuilder) BalanceChange(address common.Address, prev, cur *uint256.Int) {
|
||||||
c.nonFinalizedAccessList.balanceChange(address, prev, cur)
|
c.idxBuilder.balanceChange(address, prev, cur)
|
||||||
}
|
}
|
||||||
func (c *ConstructionBlockAccessList) NonceChange(address common.Address, prev, cur uint64) {
|
func (c *BlockAccessListBuilder) NonceChange(address common.Address, prev, cur uint64) {
|
||||||
c.nonFinalizedAccessList.nonceChange(address, prev, cur)
|
c.idxBuilder.nonceChange(address, prev, cur)
|
||||||
}
|
}
|
||||||
func (c *ConstructionBlockAccessList) CodeChange(address common.Address, prev, cur []byte) {
|
func (c *BlockAccessListBuilder) CodeChange(address common.Address, prev, cur []byte) {
|
||||||
c.nonFinalizedAccessList.codeChange(address, prev, cur)
|
c.idxBuilder.codeChange(address, prev, cur)
|
||||||
}
|
}
|
||||||
func (c *ConstructionBlockAccessList) SelfDestruct(address common.Address) {
|
func (c *BlockAccessListBuilder) SelfDestruct(address common.Address) {
|
||||||
c.nonFinalizedAccessList.selfDestruct(address)
|
c.idxBuilder.selfDestruct(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConstructionBlockAccessList) EnterScope() {
|
func (c *BlockAccessListBuilder) EnterScope() {
|
||||||
c.nonFinalizedAccessList.enterScope()
|
c.idxBuilder.enterScope()
|
||||||
}
|
}
|
||||||
func (c *ConstructionBlockAccessList) ExitScope(reverted bool) {
|
func (c *BlockAccessListBuilder) ExitScope(reverted bool) {
|
||||||
c.nonFinalizedAccessList.exitScope(reverted)
|
c.idxBuilder.exitScope(reverted)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: the BalReader Validation method should accept the computed values as
|
// TODO: the BalReader Validation method should accept the computed values as
|
||||||
// a index/StateDiff/StateAccesses trio.
|
// a index/StateDiff/StateAccesses trio.
|
||||||
|
|
||||||
// BAL tracer maintains a ConstructionBlockAccessList.
|
// BAL tracer maintains a BlockAccessListBuilder.
|
||||||
// For each BAL index, it instantiates an idxAccessListBuilder and
|
// For each BAL index, it instantiates an idxAccessListBuilder and
|
||||||
// appends the result to the access list where appropriate
|
// appends the result to the access list where appropriate
|
||||||
|
|
||||||
|
|
@ -505,31 +505,19 @@ func (c *constructionAccountAccess) NonceChange(cur uint64) {
|
||||||
c.nonce = &cur
|
c.nonce = &cur
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConstructionAccountAccesses initializes the account access object.
|
// BlockAccessListBuilder is used to build an EIP-7928 block access list
|
||||||
func NewConstructionAccountAccesses() *ConstructionAccountAccesses {
|
type BlockAccessListBuilder struct {
|
||||||
return &ConstructionAccountAccesses{
|
FinalizedAccesses map[common.Address]*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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConstructionBlockAccessList contains post-block modified state and some state accessed
|
idxBuilder *idxAccessListBuilder
|
||||||
// in execution (account addresses and storage keys).
|
|
||||||
type ConstructionBlockAccessList struct {
|
|
||||||
Accounts map[common.Address]*ConstructionAccountAccesses
|
|
||||||
|
|
||||||
nonFinalizedAccessList *idxAccessListBuilder
|
|
||||||
|
|
||||||
lastFinalizedMutations *StateDiff
|
lastFinalizedMutations *StateDiff
|
||||||
lastFinalizedAccesses StateAccesses
|
lastFinalizedAccesses StateAccesses
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConstructionBlockAccessList instantiates an empty access list.
|
// NewConstructionBlockAccessList instantiates an empty access list.
|
||||||
func NewConstructionBlockAccessList() *ConstructionBlockAccessList {
|
func NewConstructionBlockAccessList() *BlockAccessListBuilder {
|
||||||
return &ConstructionBlockAccessList{
|
return &BlockAccessListBuilder{
|
||||||
make(map[common.Address]*ConstructionAccountAccesses),
|
make(map[common.Address]*ConstructionAccountAccesses),
|
||||||
newAccessListBuilder(),
|
newAccessListBuilder(),
|
||||||
nil,
|
nil,
|
||||||
|
|
@ -538,9 +526,9 @@ func NewConstructionBlockAccessList() *ConstructionBlockAccessList {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a deep copy of the access list.
|
// Copy returns a deep copy of the access list.
|
||||||
func (c *ConstructionBlockAccessList) Copy() *ConstructionBlockAccessList {
|
func (c *BlockAccessListBuilder) Copy() *BlockAccessListBuilder {
|
||||||
res := NewConstructionBlockAccessList()
|
res := NewConstructionBlockAccessList()
|
||||||
for addr, aa := range c.Accounts {
|
for addr, aa := range c.FinalizedAccesses {
|
||||||
var aaCopy ConstructionAccountAccesses
|
var aaCopy ConstructionAccountAccesses
|
||||||
|
|
||||||
slotWrites := make(map[common.Hash]map[uint16]common.Hash, len(aa.StorageWrites))
|
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),
|
Code: bytes.Clone(codeChange.Code),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.Accounts[addr] = &aaCopy
|
res.FinalizedAccesses[addr] = &aaCopy
|
||||||
}
|
}
|
||||||
return res
|
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
|
return c.lastFinalizedMutations, c.lastFinalizedAccesses
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StateDiff contains state mutations occuring over one or more access list
|
||||||
|
// index.
|
||||||
type StateDiff struct {
|
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{}
|
type StateAccesses map[common.Address]map[common.Hash]struct{}
|
||||||
|
|
||||||
|
// Merge combines adds the accesses from other into s.
|
||||||
func (s *StateAccesses) Merge(other StateAccesses) {
|
func (s *StateAccesses) Merge(other StateAccesses) {
|
||||||
for addr, accesses := range other {
|
for addr, accesses := range other {
|
||||||
if _, ok := (*s)[addr]; !ok {
|
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"`
|
Balance *uint256.Int `json:"Balance,omitempty"`
|
||||||
Nonce *uint64 `json:"Nonce,omitempty"`
|
Nonce *uint64 `json:"Nonce,omitempty"`
|
||||||
Code ContractCode `json:"Code,omitempty"`
|
Code ContractCode `json:"Code,omitempty"`
|
||||||
StorageWrites map[common.Hash]common.Hash `json:"StorageWrites,omitempty"`
|
StorageWrites map[common.Hash]common.Hash `json:"StorageWrites,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AccountState) Empty() bool {
|
// String returns a human-readable JSON representation of the account mutations.
|
||||||
return a.Balance == nil && a.Nonce == nil && a.Code == nil && len(a.StorageWrites) == 0
|
func (a *AccountMutations) String() string {
|
||||||
}
|
|
||||||
|
|
||||||
func (a *AccountState) String() string {
|
|
||||||
var res bytes.Buffer
|
var res bytes.Buffer
|
||||||
enc := json.NewEncoder(&res)
|
enc := json.NewEncoder(&res)
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
|
|
@ -609,39 +610,8 @@ func (a *AccountState) String() string {
|
||||||
return res.String()
|
return res.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge the changes of a future AccountState into the caller, resulting in the
|
// Eq returns whether the calling instance is equal to the provided one.
|
||||||
// combined state changes through next.
|
func (a *AccountMutations) Eq(other *AccountMutations) bool {
|
||||||
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 {
|
|
||||||
if a.Balance != nil || other.Balance != nil {
|
if a.Balance != nil || other.Balance != nil {
|
||||||
if a.Balance == nil || other.Balance == nil {
|
if a.Balance == nil || other.Balance == nil {
|
||||||
return false
|
return false
|
||||||
|
|
@ -678,8 +648,14 @@ func (a *AccountState) Eq(other *AccountState) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AccountState) Copy() *AccountState {
|
// Copy returns a deep-copy of the instance.
|
||||||
res := NewEmptyAccountState()
|
func (a *AccountMutations) Copy() *AccountMutations {
|
||||||
|
res := &AccountMutations{
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
}
|
||||||
if a.Nonce != nil {
|
if a.Nonce != nil {
|
||||||
res.Nonce = new(uint64)
|
res.Nonce = new(uint64)
|
||||||
*res.Nonce = *a.Nonce
|
*res.Nonce = *a.Nonce
|
||||||
|
|
@ -696,6 +672,7 @@ func (a *AccountState) Copy() *AccountState {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the state diff as a formatted JSON string.
|
||||||
func (s *StateDiff) String() string {
|
func (s *StateDiff) String() string {
|
||||||
var res bytes.Buffer
|
var res bytes.Buffer
|
||||||
enc := json.NewEncoder(&res)
|
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 {
|
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 {
|
for addr, accountDiff := range s.Mutations {
|
||||||
cpy := accountDiff.Copy()
|
cpy := accountDiff.Copy()
|
||||||
res.Mutations[addr] = cpy
|
res.Mutations[addr] = cpy
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ import (
|
||||||
// These are objects used as input for the access list encoding. They mirror
|
// These are objects used as input for the access list encoding. They mirror
|
||||||
// the spec format.
|
// the spec format.
|
||||||
|
|
||||||
// BlockAccessList is the encoding format of ConstructionBlockAccessList.
|
// BlockAccessList is the encoding format of BlockAccessListBuilder.
|
||||||
type BlockAccessList []AccountAccess
|
type BlockAccessList []AccountAccess
|
||||||
|
|
||||||
func (e BlockAccessList) EncodeRLP(_w io.Writer) error {
|
func (e BlockAccessList) EncodeRLP(_w io.Writer) error {
|
||||||
|
|
@ -245,11 +245,11 @@ func (e *AccountAccess) Copy() AccountAccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeRLP returns the RLP-encoded access list
|
// 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)
|
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
|
// toEncodingObj creates an instance of the ConstructionAccountAccesses of the type that is
|
||||||
// used as input for the encoding.
|
// 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
|
// ToEncodingObj returns an instance of the access list expressed as the type
|
||||||
// which is used as input for the encoding/decoding.
|
// which is used as input for the encoding/decoding.
|
||||||
func (c *ConstructionBlockAccessList) ToEncodingObj() *BlockAccessList {
|
func (c *BlockAccessListBuilder) ToEncodingObj() *BlockAccessList {
|
||||||
var addresses []common.Address
|
var addresses []common.Address
|
||||||
for addr := range c.Accounts {
|
for addr := range c.FinalizedAccesses {
|
||||||
addresses = append(addresses, addr)
|
addresses = append(addresses, addr)
|
||||||
}
|
}
|
||||||
slices.SortFunc(addresses, common.Address.Cmp)
|
slices.SortFunc(addresses, common.Address.Cmp)
|
||||||
|
|
||||||
var res BlockAccessList
|
var res BlockAccessList
|
||||||
for _, addr := range addresses {
|
for _, addr := range addresses {
|
||||||
res = append(res, c.Accounts[addr].toEncodingObj(addr))
|
res = append(res, c.FinalizedAccesses[addr].toEncodingObj(addr))
|
||||||
}
|
}
|
||||||
return &res
|
return &res
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,8 @@ func equalBALs(a *BlockAccessList, b *BlockAccessList) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeTestConstructionBAL() *ConstructionBlockAccessList {
|
func makeTestConstructionBAL() *BlockAccessListBuilder {
|
||||||
return &ConstructionBlockAccessList{
|
return &BlockAccessListBuilder{
|
||||||
map[common.Address]*ConstructionAccountAccesses{
|
map[common.Address]*ConstructionAccountAccesses{
|
||||||
common.BytesToAddress([]byte{0xff, 0xff}): {
|
common.BytesToAddress([]byte{0xff, 0xff}): {
|
||||||
StorageWrites: map[common.Hash]map[uint16]common.Hash{
|
StorageWrites: map[common.Hash]map[uint16]common.Hash{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue