mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-24 08:49:29 +00:00
core, internal/ethapi: skip EIP-7702 auth signature validation in simulation mode
When eth_estimateGas or eth_call is invoked with an authorizationList containing unsigned (zero-signature) entries, the signature recovery fails and the authorization is silently skipped. This means the sender's account never receives the delegated code, producing an incorrect gas estimate. Fix this by falling back to msg.From as the authority when signature recovery fails in simulation mode (SkipTransactionChecks). Also skip authorization nonce validation when SkipNonceChecks is set, consistent with the existing sender nonce skip behaviour. Fixes #31617
This commit is contained in:
parent
c3467dd8b5
commit
a27bd32d26
2 changed files with 29 additions and 2 deletions
|
|
@ -607,7 +607,15 @@ func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorizatio
|
|||
// Validate signature values and recover authority.
|
||||
authority, err = auth.Authority()
|
||||
if err != nil {
|
||||
return authority, fmt.Errorf("%w: %v", ErrAuthorizationInvalidSignature, err)
|
||||
// In simulation mode (e.g. eth_estimateGas, eth_call), allow
|
||||
// authorizations with invalid signatures by assuming the
|
||||
// transaction sender is the authority. This lets callers estimate
|
||||
// gas for EIP-7702 transactions before signing the authorization.
|
||||
if st.msg.SkipTransactionChecks {
|
||||
authority = st.msg.From
|
||||
} else {
|
||||
return authority, fmt.Errorf("%w: %v", ErrAuthorizationInvalidSignature, err)
|
||||
}
|
||||
}
|
||||
// Check the authority account
|
||||
// 1) doesn't have code or has exisiting delegation
|
||||
|
|
@ -619,7 +627,9 @@ func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorizatio
|
|||
if _, ok := types.ParseDelegation(code); len(code) != 0 && !ok {
|
||||
return authority, ErrAuthorizationDestinationHasCode
|
||||
}
|
||||
if have := st.state.GetNonce(authority); have != auth.Nonce {
|
||||
// Skip nonce validation in simulation mode, consistent with the
|
||||
// top-level SkipNonceChecks behaviour for the sender account.
|
||||
if have := st.state.GetNonce(authority); have != auth.Nonce && !st.msg.SkipNonceChecks {
|
||||
return authority, ErrAuthorizationNonceMismatch
|
||||
}
|
||||
return authority, nil
|
||||
|
|
|
|||
|
|
@ -972,6 +972,23 @@ func TestEstimateGas(t *testing.T) {
|
|||
},
|
||||
expectErr: core.ErrSetCodeTxCreate,
|
||||
},
|
||||
// EstimateGas with unsigned (zero-signature) EIP-7702 authorization
|
||||
// should succeed, using the sender as the authority. This allows
|
||||
// callers to estimate gas before signing the authorization.
|
||||
{
|
||||
blockNumber: rpc.LatestBlockNumber,
|
||||
call: TransactionArgs{
|
||||
From: &accounts[0].addr,
|
||||
To: &accounts[1].addr,
|
||||
Value: (*hexutil.Big)(big.NewInt(0)),
|
||||
AuthorizationList: []types.SetCodeAuthorization{{
|
||||
ChainID: *uint256.NewInt(0),
|
||||
Address: accounts[0].addr,
|
||||
Nonce: uint64(genBlocks + 1),
|
||||
}},
|
||||
},
|
||||
want: 46000,
|
||||
},
|
||||
}
|
||||
for i, tc := range testSuite {
|
||||
result, err := api.EstimateGas(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides)
|
||||
|
|
|
|||
Loading…
Reference in a new issue