mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-22 15:59:26 +00:00
core/types/bal: change code change type to list (#33774)
To align with the latest spec of EIP-7928: ``` # CodeChange: [block_access_index, new_code] CodeChange = [BlockAccessIndex, Bytecode] ```
This commit is contained in:
parent
01083736c8
commit
199ac16e07
4 changed files with 61 additions and 54 deletions
|
|
@ -24,13 +24,6 @@ import (
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CodeChange contains the runtime bytecode deployed at an address and the
|
|
||||||
// transaction index where the deployment took place.
|
|
||||||
type CodeChange struct {
|
|
||||||
TxIndex uint16
|
|
||||||
Code []byte `json:"code,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConstructionAccountAccess contains post-block account state for mutations as well as
|
// ConstructionAccountAccess contains post-block account state for mutations as well as
|
||||||
// all storage keys that were read during execution. It is used when building block
|
// all storage keys that were read during execution. It is used when building block
|
||||||
// access list during execution.
|
// access list during execution.
|
||||||
|
|
@ -55,9 +48,9 @@ type ConstructionAccountAccess struct {
|
||||||
// by tx index.
|
// by tx index.
|
||||||
NonceChanges map[uint16]uint64 `json:"nonceChanges,omitempty"`
|
NonceChanges map[uint16]uint64 `json:"nonceChanges,omitempty"`
|
||||||
|
|
||||||
// CodeChange is only set for contract accounts which were deployed in
|
// CodeChange contains the post-state contract code of an account keyed
|
||||||
// the block.
|
// by tx index.
|
||||||
CodeChange *CodeChange `json:"codeChange,omitempty"`
|
CodeChange map[uint16][]byte `json:"codeChange,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConstructionAccountAccess initializes the account access object.
|
// NewConstructionAccountAccess initializes the account access object.
|
||||||
|
|
@ -67,6 +60,7 @@ func NewConstructionAccountAccess() *ConstructionAccountAccess {
|
||||||
StorageReads: make(map[common.Hash]struct{}),
|
StorageReads: make(map[common.Hash]struct{}),
|
||||||
BalanceChanges: make(map[uint16]*uint256.Int),
|
BalanceChanges: make(map[uint16]*uint256.Int),
|
||||||
NonceChanges: make(map[uint16]uint64),
|
NonceChanges: make(map[uint16]uint64),
|
||||||
|
CodeChange: make(map[uint16][]byte),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,10 +114,8 @@ func (b *ConstructionBlockAccessList) CodeChange(address common.Address, txIndex
|
||||||
if _, ok := b.Accounts[address]; !ok {
|
if _, ok := b.Accounts[address]; !ok {
|
||||||
b.Accounts[address] = NewConstructionAccountAccess()
|
b.Accounts[address] = NewConstructionAccountAccess()
|
||||||
}
|
}
|
||||||
b.Accounts[address].CodeChange = &CodeChange{
|
// TODO(rjl493456442) is it essential to deep-copy the code?
|
||||||
TxIndex: txIndex,
|
b.Accounts[address].CodeChange[txIndex] = bytes.Clone(code)
|
||||||
Code: bytes.Clone(code),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NonceChange records tx post-state nonce of any contract-like accounts whose
|
// NonceChange records tx post-state nonce of any contract-like accounts whose
|
||||||
|
|
@ -170,12 +162,11 @@ func (b *ConstructionBlockAccessList) Copy() *ConstructionBlockAccessList {
|
||||||
aaCopy.BalanceChanges = balances
|
aaCopy.BalanceChanges = balances
|
||||||
aaCopy.NonceChanges = maps.Clone(aa.NonceChanges)
|
aaCopy.NonceChanges = maps.Clone(aa.NonceChanges)
|
||||||
|
|
||||||
if aa.CodeChange != nil {
|
codes := make(map[uint16][]byte, len(aa.CodeChange))
|
||||||
aaCopy.CodeChange = &CodeChange{
|
for index, code := range aa.CodeChange {
|
||||||
TxIndex: aa.CodeChange.TxIndex,
|
codes[index] = bytes.Clone(code)
|
||||||
Code: bytes.Clone(aa.CodeChange.Code),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
aaCopy.CodeChange = codes
|
||||||
res.Accounts[addr] = &aaCopy
|
res.Accounts[addr] = &aaCopy
|
||||||
}
|
}
|
||||||
return &res
|
return &res
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,13 @@ func (e *encodingSlotWrites) validate() error {
|
||||||
return errors.New("storage write tx indices not in order")
|
return errors.New("storage write tx indices not in order")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// encodingCodeChange contains the runtime bytecode deployed at an address
|
||||||
|
// and the transaction index where the deployment took place.
|
||||||
|
type encodingCodeChange struct {
|
||||||
|
TxIndex uint16 `ssz-size:"2"`
|
||||||
|
Code []byte `ssz-max:"300000"` // TODO(rjl493456442) shall we put the limit here? The limit will be increased gradually
|
||||||
|
}
|
||||||
|
|
||||||
// AccountAccess is the encoding format of ConstructionAccountAccess.
|
// AccountAccess is the encoding format of ConstructionAccountAccess.
|
||||||
type AccountAccess struct {
|
type AccountAccess struct {
|
||||||
Address [20]byte `ssz-size:"20"` // 20-byte Ethereum address
|
Address [20]byte `ssz-size:"20"` // 20-byte Ethereum address
|
||||||
|
|
@ -126,7 +133,7 @@ type AccountAccess struct {
|
||||||
StorageReads [][32]byte `ssz-max:"300000"` // Read-only storage keys
|
StorageReads [][32]byte `ssz-max:"300000"` // Read-only storage keys
|
||||||
BalanceChanges []encodingBalanceChange `ssz-max:"300000"` // Balance changes ([tx_index -> post_balance])
|
BalanceChanges []encodingBalanceChange `ssz-max:"300000"` // Balance changes ([tx_index -> post_balance])
|
||||||
NonceChanges []encodingAccountNonce `ssz-max:"300000"` // Nonce changes ([tx_index -> new_nonce])
|
NonceChanges []encodingAccountNonce `ssz-max:"300000"` // Nonce changes ([tx_index -> new_nonce])
|
||||||
Code []CodeChange `ssz-max:"1"` // Code changes ([tx_index -> new_code])
|
CodeChanges []encodingCodeChange `ssz-max:"300000"` // Code changes ([tx_index -> new_code])
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate converts the account accesses out of encoding format.
|
// validate converts the account accesses out of encoding format.
|
||||||
|
|
@ -166,9 +173,16 @@ func (e *AccountAccess) validate() error {
|
||||||
return errors.New("nonce changes not in ascending order by tx index")
|
return errors.New("nonce changes not in ascending order by tx index")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert code change
|
// Check the code changes are sorted in order
|
||||||
if len(e.Code) == 1 {
|
if !slices.IsSortedFunc(e.CodeChanges, func(a, b encodingCodeChange) int {
|
||||||
if len(e.Code[0].Code) > params.MaxCodeSize {
|
return cmp.Compare[uint16](a.TxIndex, b.TxIndex)
|
||||||
|
}) {
|
||||||
|
return errors.New("code changes not in ascending order by tx index")
|
||||||
|
}
|
||||||
|
for _, change := range e.CodeChanges {
|
||||||
|
// TODO(rjl493456442): This check should be fork-aware, since the limit may
|
||||||
|
// differ across forks.
|
||||||
|
if len(change.Code) > params.MaxCodeSize {
|
||||||
return errors.New("code change contained oversized code")
|
return errors.New("code change contained oversized code")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -182,6 +196,8 @@ func (e *AccountAccess) Copy() AccountAccess {
|
||||||
StorageReads: slices.Clone(e.StorageReads),
|
StorageReads: slices.Clone(e.StorageReads),
|
||||||
BalanceChanges: slices.Clone(e.BalanceChanges),
|
BalanceChanges: slices.Clone(e.BalanceChanges),
|
||||||
NonceChanges: slices.Clone(e.NonceChanges),
|
NonceChanges: slices.Clone(e.NonceChanges),
|
||||||
|
StorageWrites: make([]encodingSlotWrites, 0, len(e.StorageWrites)),
|
||||||
|
CodeChanges: make([]encodingCodeChange, 0, len(e.CodeChanges)),
|
||||||
}
|
}
|
||||||
for _, storageWrite := range e.StorageWrites {
|
for _, storageWrite := range e.StorageWrites {
|
||||||
res.StorageWrites = append(res.StorageWrites, encodingSlotWrites{
|
res.StorageWrites = append(res.StorageWrites, encodingSlotWrites{
|
||||||
|
|
@ -189,13 +205,11 @@ func (e *AccountAccess) Copy() AccountAccess {
|
||||||
Accesses: slices.Clone(storageWrite.Accesses),
|
Accesses: slices.Clone(storageWrite.Accesses),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if len(e.Code) == 1 {
|
for _, codeChange := range e.CodeChanges {
|
||||||
res.Code = []CodeChange{
|
res.CodeChanges = append(res.CodeChanges, encodingCodeChange{
|
||||||
{
|
TxIndex: codeChange.TxIndex,
|
||||||
e.Code[0].TxIndex,
|
Code: bytes.Clone(codeChange.Code),
|
||||||
bytes.Clone(e.Code[0].Code),
|
})
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
@ -212,11 +226,11 @@ var _ rlp.Encoder = &ConstructionBlockAccessList{}
|
||||||
func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAccess {
|
func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAccess {
|
||||||
res := AccountAccess{
|
res := AccountAccess{
|
||||||
Address: addr,
|
Address: addr,
|
||||||
StorageWrites: make([]encodingSlotWrites, 0),
|
StorageWrites: make([]encodingSlotWrites, 0, len(a.StorageWrites)),
|
||||||
StorageReads: make([][32]byte, 0),
|
StorageReads: make([][32]byte, 0, len(a.StorageReads)),
|
||||||
BalanceChanges: make([]encodingBalanceChange, 0),
|
BalanceChanges: make([]encodingBalanceChange, 0, len(a.BalanceChanges)),
|
||||||
NonceChanges: make([]encodingAccountNonce, 0),
|
NonceChanges: make([]encodingAccountNonce, 0, len(a.NonceChanges)),
|
||||||
Code: nil,
|
CodeChanges: make([]encodingCodeChange, 0, len(a.CodeChange)),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert write slots
|
// Convert write slots
|
||||||
|
|
@ -268,13 +282,13 @@ func (a *ConstructionAccountAccess) toEncodingObj(addr common.Address) AccountAc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert code change
|
// Convert code change
|
||||||
if a.CodeChange != nil {
|
codeIndices := slices.Collect(maps.Keys(a.CodeChange))
|
||||||
res.Code = []CodeChange{
|
slices.SortFunc(codeIndices, cmp.Compare[uint16])
|
||||||
{
|
for _, idx := range codeIndices {
|
||||||
a.CodeChange.TxIndex,
|
res.CodeChanges = append(res.CodeChanges, encodingCodeChange{
|
||||||
bytes.Clone(a.CodeChange.Code),
|
TxIndex: idx,
|
||||||
},
|
Code: a.CodeChange[idx],
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
@ -327,9 +341,9 @@ func (e *BlockAccessList) PrettyPrint() string {
|
||||||
printWithIndent(2, fmt.Sprintf("%d: %d", change.TxIdx, change.Nonce))
|
printWithIndent(2, fmt.Sprintf("%d: %d", change.TxIdx, change.Nonce))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(accountDiff.Code) > 0 {
|
printWithIndent(1, "code changes:")
|
||||||
printWithIndent(1, "code:")
|
for _, change := range accountDiff.CodeChanges {
|
||||||
printWithIndent(2, fmt.Sprintf("%d: %x", accountDiff.Code[0].TxIndex, accountDiff.Code[0].Code))
|
printWithIndent(2, fmt.Sprintf("%d: %x", change.TxIndex, change.Code))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res.String()
|
return res.String()
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ func (obj *BlockAccessList) EncodeRLP(_w io.Writer) error {
|
||||||
}
|
}
|
||||||
w.ListEnd(_tmp15)
|
w.ListEnd(_tmp15)
|
||||||
_tmp18 := w.List()
|
_tmp18 := w.List()
|
||||||
for _, _tmp19 := range _tmp2.Code {
|
for _, _tmp19 := range _tmp2.CodeChanges {
|
||||||
_tmp20 := w.List()
|
_tmp20 := w.List()
|
||||||
w.WriteUint64(uint64(_tmp19.TxIndex))
|
w.WriteUint64(uint64(_tmp19.TxIndex))
|
||||||
w.WriteBytes(_tmp19.Code)
|
w.WriteBytes(_tmp19.Code)
|
||||||
|
|
@ -228,13 +228,13 @@ func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_tmp2.NonceChanges = _tmp17
|
_tmp2.NonceChanges = _tmp17
|
||||||
// Code:
|
// CodeChanges:
|
||||||
var _tmp21 []CodeChange
|
var _tmp21 []encodingCodeChange
|
||||||
if _, err := dec.List(); err != nil {
|
if _, err := dec.List(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for dec.MoreDataInList() {
|
for dec.MoreDataInList() {
|
||||||
var _tmp22 CodeChange
|
var _tmp22 encodingCodeChange
|
||||||
{
|
{
|
||||||
if _, err := dec.List(); err != nil {
|
if _, err := dec.List(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -260,7 +260,7 @@ func (obj *BlockAccessList) DecodeRLP(dec *rlp.Stream) error {
|
||||||
if err := dec.ListEnd(); err != nil {
|
if err := dec.ListEnd(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_tmp2.Code = _tmp21
|
_tmp2.CodeChanges = _tmp21
|
||||||
if err := dec.ListEnd(); err != nil {
|
if err := dec.ListEnd(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,9 +60,8 @@ func makeTestConstructionBAL() *ConstructionBlockAccessList {
|
||||||
1: 2,
|
1: 2,
|
||||||
2: 6,
|
2: 6,
|
||||||
},
|
},
|
||||||
CodeChange: &CodeChange{
|
CodeChange: map[uint16][]byte{
|
||||||
TxIndex: 0,
|
0: common.Hex2Bytes("deadbeef"),
|
||||||
Code: common.Hex2Bytes("deadbeef"),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
common.BytesToAddress([]byte{0xff, 0xff, 0xff}): {
|
common.BytesToAddress([]byte{0xff, 0xff, 0xff}): {
|
||||||
|
|
@ -85,6 +84,9 @@ func makeTestConstructionBAL() *ConstructionBlockAccessList {
|
||||||
NonceChanges: map[uint16]uint64{
|
NonceChanges: map[uint16]uint64{
|
||||||
1: 2,
|
1: 2,
|
||||||
},
|
},
|
||||||
|
CodeChange: map[uint16][]byte{
|
||||||
|
0: common.Hex2Bytes("deadbeef"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +181,7 @@ func makeTestAccountAccess(sort bool) AccountAccess {
|
||||||
StorageReads: storageReads,
|
StorageReads: storageReads,
|
||||||
BalanceChanges: balances,
|
BalanceChanges: balances,
|
||||||
NonceChanges: nonces,
|
NonceChanges: nonces,
|
||||||
Code: []CodeChange{
|
CodeChanges: []encodingCodeChange{
|
||||||
{
|
{
|
||||||
TxIndex: 100,
|
TxIndex: 100,
|
||||||
Code: testrand.Bytes(256),
|
Code: testrand.Bytes(256),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue