mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-08 07:58:40 +00:00
Merge 350978a0a6 into c5598fe958
This commit is contained in:
commit
2357b7a12a
8 changed files with 100 additions and 53 deletions
|
|
@ -207,20 +207,35 @@ func toWordSize(size uint64) uint64 {
|
|||
// A Message contains the data derived from a single transaction that is relevant to state
|
||||
// processing.
|
||||
type Message struct {
|
||||
To *common.Address
|
||||
From common.Address
|
||||
Nonce uint64
|
||||
Value *big.Int
|
||||
GasLimit uint64
|
||||
GasPrice *big.Int
|
||||
GasFeeCap *big.Int
|
||||
GasTipCap *big.Int
|
||||
Data []byte
|
||||
AccessList types.AccessList
|
||||
BlobGasFeeCap *big.Int
|
||||
BlobHashes []common.Hash
|
||||
To *common.Address
|
||||
From common.Address
|
||||
Nonce uint64
|
||||
Value *big.Int
|
||||
GasLimit uint64
|
||||
GasPrice *big.Int
|
||||
GasFeeCap *big.Int
|
||||
GasTipCap *big.Int
|
||||
Data []byte
|
||||
AccessList types.AccessList
|
||||
BlobGasFeeCap *big.Int
|
||||
BlobHashes []common.Hash
|
||||
|
||||
// When SetCodeAuthorizations is not nil, it represents the full set of
|
||||
// auths included in the actual transaction.
|
||||
//
|
||||
// To avoid recovering the authority addresses during the state transition,
|
||||
// they are precomputed or retrieved from the Transaction cache and placed
|
||||
// into Authorities below. The authority for any given index will match the
|
||||
// corresponding authorization in SetCodeAuthorizations. Nil is used when the
|
||||
// authorization is invalid to maintain indexes between the two lists.
|
||||
SetCodeAuthorizations []types.SetCodeAuthorization
|
||||
|
||||
// Authorities is the list of recovered authority addresses for the
|
||||
// authorization list. Nil is used to represent an invalid authorization. The
|
||||
// indexes between SetCodeAuthorizations and Authorities match so that the
|
||||
// each authority matches the corresponding authorization.
|
||||
Authorities []*common.Address // Recovered authority addresses
|
||||
|
||||
// When SkipNonceChecks is true, the message nonce is not checked against the
|
||||
// account nonce in state.
|
||||
//
|
||||
|
|
@ -249,6 +264,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
|
|||
Data: tx.Data(),
|
||||
AccessList: tx.AccessList(),
|
||||
SetCodeAuthorizations: tx.SetCodeAuthorizations(),
|
||||
Authorities: tx.SetCodeAuthorities(),
|
||||
SkipNonceChecks: false,
|
||||
SkipTransactionChecks: false,
|
||||
BlobHashes: tx.BlobHashes(),
|
||||
|
|
@ -575,9 +591,17 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
|
||||
// Apply EIP-7702 authorizations.
|
||||
if msg.SetCodeAuthorizations != nil {
|
||||
for _, auth := range msg.SetCodeAuthorizations {
|
||||
// Note errors are ignored, we simply skip invalid authorizations here.
|
||||
st.applyAuthorization(&auth)
|
||||
if len(msg.SetCodeAuthorizations) != len(msg.Authorities) {
|
||||
// This is an invariant of Message that cannot be invalidated.
|
||||
panic("Length of authorizations does match authorities")
|
||||
}
|
||||
for i, auth := range msg.SetCodeAuthorizations {
|
||||
addr := msg.Authorities[i]
|
||||
if addr == nil {
|
||||
// Skip invalid authorizations.
|
||||
continue
|
||||
}
|
||||
st.applyAuthorization(&auth, *addr)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -661,20 +685,16 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
}
|
||||
|
||||
// validateAuthorization validates an EIP-7702 authorization against the state.
|
||||
func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorization) (authority common.Address, err error) {
|
||||
func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorization, authority common.Address) error {
|
||||
// Verify chain ID is null or equal to current chain ID.
|
||||
if !auth.ChainID.IsZero() && auth.ChainID.CmpBig(st.evm.ChainConfig().ChainID) != 0 {
|
||||
return authority, ErrAuthorizationWrongChainID
|
||||
return ErrAuthorizationWrongChainID
|
||||
}
|
||||
// Limit nonce to 2^64-1 per EIP-2681.
|
||||
if auth.Nonce+1 < auth.Nonce {
|
||||
return authority, ErrAuthorizationNonceOverflow
|
||||
}
|
||||
// Validate signature values and recover authority.
|
||||
authority, err = auth.Authority()
|
||||
if err != nil {
|
||||
return authority, fmt.Errorf("%w: %v", ErrAuthorizationInvalidSignature, err)
|
||||
return ErrAuthorizationNonceOverflow
|
||||
}
|
||||
|
||||
// Check the authority account
|
||||
// 1) doesn't have code or has exisiting delegation
|
||||
// 2) matches the auth's nonce
|
||||
|
|
@ -683,17 +703,17 @@ func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorizatio
|
|||
st.state.AddAddressToAccessList(authority)
|
||||
code := st.state.GetCode(authority)
|
||||
if _, ok := types.ParseDelegation(code); len(code) != 0 && !ok {
|
||||
return authority, ErrAuthorizationDestinationHasCode
|
||||
return ErrAuthorizationDestinationHasCode
|
||||
}
|
||||
if have := st.state.GetNonce(authority); have != auth.Nonce {
|
||||
return authority, ErrAuthorizationNonceMismatch
|
||||
return ErrAuthorizationNonceMismatch
|
||||
}
|
||||
return authority, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// applyAuthorization applies an EIP-7702 code delegation to the state.
|
||||
func (st *stateTransition) applyAuthorization(auth *types.SetCodeAuthorization) error {
|
||||
authority, err := st.validateAuthorization(auth)
|
||||
func (st *stateTransition) applyAuthorization(auth *types.SetCodeAuthorization, authority common.Address) error {
|
||||
err := st.validateAuthorization(auth, authority)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -632,7 +632,7 @@ func (pool *LegacyPool) validateAuth(tx *types.Transaction) error {
|
|||
}
|
||||
// For symmetry, allow at most one in-flight tx for any authority with a
|
||||
// pending transaction.
|
||||
if auths := tx.SetCodeAuthorities(); len(auths) > 0 {
|
||||
if auths := tx.UniqueSetCodeAuthorities(); len(auths) > 0 {
|
||||
for _, auth := range auths {
|
||||
var count int
|
||||
if pending := pool.pending[auth]; pending != nil {
|
||||
|
|
@ -1759,7 +1759,7 @@ func (t *lookup) TxsBelowTip(threshold *big.Int) types.Transactions {
|
|||
// addAuthorities tracks the supplied tx in relation to each authority it
|
||||
// specifies.
|
||||
func (t *lookup) addAuthorities(tx *types.Transaction) {
|
||||
for _, addr := range tx.SetCodeAuthorities() {
|
||||
for _, addr := range tx.UniqueSetCodeAuthorities() {
|
||||
list, ok := t.auths[addr]
|
||||
if !ok {
|
||||
list = []common.Hash{}
|
||||
|
|
@ -1777,7 +1777,7 @@ func (t *lookup) addAuthorities(tx *types.Transaction) {
|
|||
// authorities.
|
||||
func (t *lookup) removeAuthorities(tx *types.Transaction) {
|
||||
hash := tx.Hash()
|
||||
for _, addr := range tx.SetCodeAuthorities() {
|
||||
for _, addr := range tx.UniqueSetCodeAuthorities() {
|
||||
list := t.auths[addr]
|
||||
// Remove tx from tracker.
|
||||
if i := slices.Index(list, hash); i >= 0 {
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ func validatePoolInternals(pool *LegacyPool) error {
|
|||
}
|
||||
// Ensure all auths in pool are tracked
|
||||
for _, tx := range pool.all.txs {
|
||||
for _, addr := range tx.SetCodeAuthorities() {
|
||||
for _, addr := range tx.UniqueSetCodeAuthorities() {
|
||||
list := pool.all.auths[addr]
|
||||
if i := slices.Index(list, tx.Hash()); i < 0 {
|
||||
return fmt.Errorf("authority not tracked: addr %s, tx %s", addr, tx.Hash())
|
||||
|
|
|
|||
|
|
@ -58,9 +58,10 @@ type Transaction struct {
|
|||
time time.Time // Time first seen locally (spam avoidance)
|
||||
|
||||
// caches
|
||||
hash atomic.Pointer[common.Hash]
|
||||
size atomic.Uint64
|
||||
from atomic.Pointer[sigCache]
|
||||
hash atomic.Pointer[common.Hash]
|
||||
size atomic.Uint64
|
||||
from atomic.Pointer[sigCache]
|
||||
auths atomic.Pointer[authCache]
|
||||
}
|
||||
|
||||
// NewTx creates a new transaction.
|
||||
|
|
@ -539,27 +540,36 @@ func (tx *Transaction) SetCodeAuthorizations() []SetCodeAuthorization {
|
|||
return setcodetx.AuthList
|
||||
}
|
||||
|
||||
// SetCodeAuthorities returns a list of unique authorities from the
|
||||
// authorization list.
|
||||
func (tx *Transaction) SetCodeAuthorities() []common.Address {
|
||||
// SetCodeAuthorities returns a list of authorities from the authorization list.
|
||||
// Nil is used to represent authorizations that fail derivation.
|
||||
func (tx *Transaction) SetCodeAuthorities() []*common.Address {
|
||||
setcodetx, ok := tx.inner.(*SetCodeTx)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if cache := tx.auths.Load(); cache != nil {
|
||||
return *cache
|
||||
}
|
||||
cache := (authCache)(DeriveAuthorities(setcodetx.AuthList))
|
||||
tx.auths.Store(&cache)
|
||||
return cache
|
||||
}
|
||||
|
||||
// UniqueSetCodeAuthorities returns a list of unique authorities from the
|
||||
// authorization list.
|
||||
func (tx *Transaction) UniqueSetCodeAuthorities() []common.Address {
|
||||
var (
|
||||
marks = make(map[common.Address]bool)
|
||||
auths = make([]common.Address, 0, len(setcodetx.AuthList))
|
||||
auths = tx.SetCodeAuthorities()
|
||||
marks = make(map[common.Address]bool)
|
||||
uniques []common.Address
|
||||
)
|
||||
for _, auth := range setcodetx.AuthList {
|
||||
if addr, err := auth.Authority(); err == nil {
|
||||
if marks[addr] {
|
||||
continue
|
||||
}
|
||||
marks[addr] = true
|
||||
auths = append(auths, addr)
|
||||
for _, auth := range auths {
|
||||
if auth != nil && !marks[*auth] {
|
||||
marks[*auth] = true
|
||||
uniques = append(uniques, *auth)
|
||||
}
|
||||
}
|
||||
return auths
|
||||
return uniques
|
||||
}
|
||||
|
||||
// SetTime sets the decoding time of a transaction. This is used by tests to set
|
||||
|
|
|
|||
|
|
@ -66,6 +66,25 @@ type SetCodeTx struct {
|
|||
S *uint256.Int
|
||||
}
|
||||
|
||||
// authCache is an internal helper type used in the Transaction object to cache
|
||||
// authorizations.
|
||||
type authCache []*common.Address
|
||||
|
||||
// DeriveAuthorities returns a list of recovered authorization signers. The
|
||||
// length is always equal to the number of authorizations. Any authorities that
|
||||
// fail to recover are set as nil in the list.
|
||||
func DeriveAuthorities(authList []SetCodeAuthorization) []*common.Address {
|
||||
auths := make([]*common.Address, 0, len(authList))
|
||||
for _, auth := range authList {
|
||||
if addr, err := auth.Authority(); err == nil {
|
||||
auths = append(auths, &addr)
|
||||
} else {
|
||||
auths = append(auths, nil)
|
||||
}
|
||||
}
|
||||
return auths
|
||||
}
|
||||
|
||||
//go:generate go run github.com/fjl/gencodec -type SetCodeAuthorization -field-override authorizationMarshaling -out gen_authorization.go
|
||||
|
||||
// SetCodeAuthorization is an authorization from an account to deploy code at its address.
|
||||
|
|
|
|||
|
|
@ -196,11 +196,7 @@ func (t *prestateTracer) OnTxStart(env *tracing.VMContext, tx *types.Transaction
|
|||
t.lookupAccount(env.Coinbase)
|
||||
|
||||
// Add accounts with authorizations to the prestate before they get applied.
|
||||
for _, auth := range tx.SetCodeAuthorizations() {
|
||||
addr, err := auth.Authority()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, addr := range tx.UniqueSetCodeAuthorities() {
|
||||
t.lookupAccount(addr)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -491,6 +491,7 @@ func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck bool) *c
|
|||
BlobGasFeeCap: (*big.Int)(args.BlobFeeCap),
|
||||
BlobHashes: args.BlobHashes,
|
||||
SetCodeAuthorizations: args.AuthorizationList,
|
||||
Authorities: types.DeriveAuthorities(args.AuthorizationList),
|
||||
SkipNonceChecks: skipNonceCheck,
|
||||
SkipTransactionChecks: true,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -489,6 +489,7 @@ func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Mess
|
|||
BlobHashes: tx.BlobVersionedHashes,
|
||||
BlobGasFeeCap: tx.BlobGasFeeCap,
|
||||
SetCodeAuthorizations: authList,
|
||||
Authorities: types.DeriveAuthorities(authList),
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue