mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 09:53:48 +00:00
core: track validation error for authorizations
It's not strictly necessary, but can be nice for debugging.
This commit is contained in:
parent
bb182a6429
commit
0926de326e
2 changed files with 74 additions and 44 deletions
|
|
@ -103,6 +103,8 @@ var (
|
|||
// ErrSenderNoEOA is returned if the sender of a transaction is a contract.
|
||||
ErrSenderNoEOA = errors.New("sender not an eoa")
|
||||
|
||||
// -- EIP-4844 errors --
|
||||
|
||||
// ErrBlobFeeCapTooLow is returned if the transaction fee cap is less than the
|
||||
// blob gas fee of the block.
|
||||
ErrBlobFeeCapTooLow = errors.New("max fee per blob gas less than block blob gas fee")
|
||||
|
|
@ -113,10 +115,19 @@ var (
|
|||
// ErrBlobTxCreate is returned if a blob transaction has no explicit to field.
|
||||
ErrBlobTxCreate = errors.New("blob transaction of type create")
|
||||
|
||||
// -- EIP-7702 errors --
|
||||
|
||||
// ErrEmptyAuthList is returned if a set code transaction has an empty auth list.
|
||||
ErrEmptyAuthList = errors.New("set code transaction with empty auth list")
|
||||
|
||||
// ErrAuthSignatureVeryHigh is returned if a set code transaction has a
|
||||
// signature with R or S larger than 2^256-1.
|
||||
ErrAuthSignatureVeryHigh = errors.New("set code transaction has authorization with R or S value greater than 2^256 - 1")
|
||||
|
||||
// EIP-7702 state transition errors:
|
||||
ErrAuthorizationWrongChainID = errors.New("EIP-7702 authorization chain ID mismatch")
|
||||
ErrAuthorizationNonceOverflow = errors.New("EIP-7702 authorization nonce > 64 bit")
|
||||
ErrAuthorizationInvalidSignature = errors.New("EIP-7702 authorization has invalid signature")
|
||||
ErrAuthorizationDestinationHasCode = errors.New("EIP-7702 authorization destination is a contract")
|
||||
ErrAuthorizationNonceMismatch = errors.New("EIP-7702 authorization nonce does not match current account nonce")
|
||||
)
|
||||
|
|
|
|||
|
|
@ -466,52 +466,12 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1)
|
||||
}
|
||||
|
||||
// Check authorizations list validity.
|
||||
// Apply EIP-7702 authorizations.
|
||||
if msg.AuthList != nil {
|
||||
for _, auth := range msg.AuthList {
|
||||
// Verify chain ID is 0 or equal to current chain ID.
|
||||
if auth.ChainID != 0 && st.evm.ChainConfig().ChainID.Uint64() != auth.ChainID {
|
||||
continue
|
||||
}
|
||||
// Limit nonce to 2^64-1 per EIP-2681.
|
||||
if auth.Nonce+1 < auth.Nonce {
|
||||
continue
|
||||
}
|
||||
// Validate signature values and recover authority.
|
||||
authority, err := auth.Authority()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// Check the authority account 1) doesn't have code or has exisiting
|
||||
// delegation 2) matches the auth's nonce
|
||||
st.state.AddAddressToAccessList(authority)
|
||||
code := st.state.GetCode(authority)
|
||||
if _, ok := types.ParseDelegation(code); len(code) != 0 && !ok {
|
||||
continue
|
||||
}
|
||||
if have := st.state.GetNonce(authority); have != auth.Nonce {
|
||||
continue
|
||||
}
|
||||
// If the account already exists in state, refund the new account cost
|
||||
// charged in the intrinsic calculation.
|
||||
if exists := st.state.Exist(authority); exists {
|
||||
st.state.AddRefund(params.CallNewAccountGas - params.TxAuthTupleGas)
|
||||
}
|
||||
st.state.SetNonce(authority, auth.Nonce+1)
|
||||
delegation := types.AddressToDelegation(auth.Address)
|
||||
if auth.Address == (common.Address{}) {
|
||||
// If the delegation is for the zero address, completely clear all
|
||||
// delegations from the account.
|
||||
delegation = []byte{}
|
||||
}
|
||||
st.state.SetCode(authority, delegation)
|
||||
|
||||
// Usually the transaction destination and delegation target are added to
|
||||
// the access list in statedb.Prepare(..), however if the delegation is in
|
||||
// the same transaction we need add here as Prepare already happened.
|
||||
if *msg.To == authority {
|
||||
st.state.AddAddressToAccessList(auth.Address)
|
||||
}
|
||||
// Note errors are ignored, we simply skip invalid authorizations here.
|
||||
err := st.applyAuthorization(msg, &auth)
|
||||
fmt.Println("err:", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -565,6 +525,65 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// validateAuthorization validates an EIP-7702 authorization against the state.
|
||||
func (st *stateTransition) validateAuthorization(auth *types.Authorization) (authority common.Address, err error) {
|
||||
// Verify chain ID is 0 or equal to current chain ID.
|
||||
if auth.ChainID != 0 && st.evm.ChainConfig().ChainID.Uint64() != auth.ChainID {
|
||||
return authority, 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)
|
||||
}
|
||||
// Check the authority account 1) doesn't have code or has exisiting
|
||||
// delegation 2) matches the auth's nonce
|
||||
st.state.AddAddressToAccessList(authority)
|
||||
code := st.state.GetCode(authority)
|
||||
if _, ok := types.ParseDelegation(code); len(code) != 0 && !ok {
|
||||
return authority, ErrAuthorizationDestinationHasCode
|
||||
}
|
||||
if have := st.state.GetNonce(authority); have != auth.Nonce {
|
||||
return authority, ErrAuthorizationNonceMismatch
|
||||
}
|
||||
return authority, nil
|
||||
}
|
||||
|
||||
// applyAuthorization applies an EIP-7702 code delegation to the state.
|
||||
func (st *stateTransition) applyAuthorization(msg *Message, auth *types.Authorization) error {
|
||||
authority, err := st.validateAuthorization(auth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the account already exists in state, refund the new account cost
|
||||
// charged in the intrinsic calculation.
|
||||
if exists := st.state.Exist(authority); exists {
|
||||
st.state.AddRefund(params.CallNewAccountGas - params.TxAuthTupleGas)
|
||||
}
|
||||
st.state.SetNonce(authority, auth.Nonce+1)
|
||||
delegation := types.AddressToDelegation(auth.Address)
|
||||
if auth.Address == (common.Address{}) {
|
||||
// If the delegation is for the zero address, completely clear all
|
||||
// delegations from the account.
|
||||
delegation = []byte{}
|
||||
}
|
||||
st.state.SetCode(authority, delegation)
|
||||
|
||||
// Usually the transaction destination and delegation target are added to
|
||||
// the access list in statedb.Prepare(..), however if the delegation is in
|
||||
// the same transaction we need add here as Prepare already happened.
|
||||
if *msg.To == authority {
|
||||
st.state.AddAddressToAccessList(auth.Address)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *stateTransition) refundGas(refundQuotient uint64) uint64 {
|
||||
// Apply refund counter, capped to a refund quotient
|
||||
refund := st.gasUsed() / refundQuotient
|
||||
|
|
|
|||
Loading…
Reference in a new issue