mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +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 is returned if the sender of a transaction is a contract.
|
||||||
ErrSenderNoEOA = errors.New("sender not an eoa")
|
ErrSenderNoEOA = errors.New("sender not an eoa")
|
||||||
|
|
||||||
|
// -- EIP-4844 errors --
|
||||||
|
|
||||||
// ErrBlobFeeCapTooLow is returned if the transaction fee cap is less than the
|
// ErrBlobFeeCapTooLow is returned if the transaction fee cap is less than the
|
||||||
// blob gas fee of the block.
|
// blob gas fee of the block.
|
||||||
ErrBlobFeeCapTooLow = errors.New("max fee per blob gas less than block blob gas fee")
|
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 is returned if a blob transaction has no explicit to field.
|
||||||
ErrBlobTxCreate = errors.New("blob transaction of type create")
|
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 is returned if a set code transaction has an empty auth list.
|
||||||
ErrEmptyAuthList = errors.New("set code transaction with empty auth list")
|
ErrEmptyAuthList = errors.New("set code transaction with empty auth list")
|
||||||
|
|
||||||
// ErrAuthSignatureVeryHigh is returned if a set code transaction has a
|
// ErrAuthSignatureVeryHigh is returned if a set code transaction has a
|
||||||
// signature with R or S larger than 2^256-1.
|
// 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")
|
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)
|
st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check authorizations list validity.
|
// Apply EIP-7702 authorizations.
|
||||||
if msg.AuthList != nil {
|
if msg.AuthList != nil {
|
||||||
for _, auth := range msg.AuthList {
|
for _, auth := range msg.AuthList {
|
||||||
// Verify chain ID is 0 or equal to current chain ID.
|
// Note errors are ignored, we simply skip invalid authorizations here.
|
||||||
if auth.ChainID != 0 && st.evm.ChainConfig().ChainID.Uint64() != auth.ChainID {
|
err := st.applyAuthorization(msg, &auth)
|
||||||
continue
|
fmt.Println("err:", err)
|
||||||
}
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -565,6 +525,65 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
||||||
}, nil
|
}, 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 {
|
func (st *stateTransition) refundGas(refundQuotient uint64) uint64 {
|
||||||
// Apply refund counter, capped to a refund quotient
|
// Apply refund counter, capped to a refund quotient
|
||||||
refund := st.gasUsed() / refundQuotient
|
refund := st.gasUsed() / refundQuotient
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue