From f287de9d12d2d86b8fd77759e4a3ef4f1a30582b Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Thu, 19 Dec 2024 10:35:10 +0100 Subject: [PATCH] core, core/types: implement unchained flag in SetCodeAuthorization --- core/blockchain_test.go | 11 ++++---- core/state_transition.go | 6 +---- core/types/gen_authorization.go | 32 +++++++++++----------- core/types/tx_setcode.go | 48 +++++++++++++++++---------------- 4 files changed, 47 insertions(+), 50 deletions(-) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index fc0e3d8446ca4..500e35f4cc8e2 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -4273,15 +4273,14 @@ func TestEIP7702(t *testing.T) { // 1. tx -> addr1 which is delegated to 0xaaaa // 2. addr1:0xaaaa calls into addr2:0xbbbb // 3. addr2:0xbbbb writes to storage - auth1, _ := types.SignSetCode(key1, types.SetCodeAuthorization{ - ChainID: gspec.Config.ChainID.Uint64(), + auth1, _ := types.SignSetCode(key1, gspec.Config.ChainID, types.SetCodeAuthorization{ Address: aa, Nonce: 1, }) - auth2, _ := types.SignSetCode(key2, types.SetCodeAuthorization{ - ChainID: 0, - Address: bb, - Nonce: 0, + auth2, _ := types.SignSetCode(key2, gspec.Config.ChainID, types.SetCodeAuthorization{ + Unchained: true, + Address: bb, + Nonce: 0, }) _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { diff --git a/core/state_transition.go b/core/state_transition.go index 93d72d16b715f..3b655eef1ee59 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -529,16 +529,12 @@ 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) { - // 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() + authority, err = auth.Authority(st.evm.ChainConfig().ChainID) if err != nil { return authority, fmt.Errorf("%w: %v", ErrAuthorizationInvalidSignature, err) } diff --git a/core/types/gen_authorization.go b/core/types/gen_authorization.go index be5467c50d0db..33cfaa38954fd 100644 --- a/core/types/gen_authorization.go +++ b/core/types/gen_authorization.go @@ -16,15 +16,15 @@ var _ = (*authorizationMarshaling)(nil) // MarshalJSON marshals as JSON. func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) { type SetCodeAuthorization struct { - ChainID hexutil.Uint64 `json:"chainId" gencodec:"required"` - Address common.Address `json:"address" gencodec:"required"` - Nonce hexutil.Uint64 `json:"nonce" gencodec:"required"` - V hexutil.Uint64 `json:"yParity" gencodec:"required"` - R hexutil.U256 `json:"r" gencodec:"required"` - S hexutil.U256 `json:"s" gencodec:"required"` + Unchained bool `json:"unchained" gencodec:"required"` + Address common.Address `json:"address" gencodec:"required"` + Nonce hexutil.Uint64 `json:"nonce" gencodec:"required"` + V hexutil.Uint64 `json:"yParity" gencodec:"required"` + R hexutil.U256 `json:"r" gencodec:"required"` + S hexutil.U256 `json:"s" gencodec:"required"` } var enc SetCodeAuthorization - enc.ChainID = hexutil.Uint64(s.ChainID) + enc.Unchained = s.Unchained enc.Address = s.Address enc.Nonce = hexutil.Uint64(s.Nonce) enc.V = hexutil.Uint64(s.V) @@ -36,21 +36,21 @@ func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals from JSON. func (s *SetCodeAuthorization) UnmarshalJSON(input []byte) error { type SetCodeAuthorization struct { - ChainID *hexutil.Uint64 `json:"chainId" gencodec:"required"` - Address *common.Address `json:"address" gencodec:"required"` - Nonce *hexutil.Uint64 `json:"nonce" gencodec:"required"` - V *hexutil.Uint64 `json:"yParity" gencodec:"required"` - R *hexutil.U256 `json:"r" gencodec:"required"` - S *hexutil.U256 `json:"s" gencodec:"required"` + Unchained *bool `json:"unchained" gencodec:"required"` + Address *common.Address `json:"address" gencodec:"required"` + Nonce *hexutil.Uint64 `json:"nonce" gencodec:"required"` + V *hexutil.Uint64 `json:"yParity" gencodec:"required"` + R *hexutil.U256 `json:"r" gencodec:"required"` + S *hexutil.U256 `json:"s" gencodec:"required"` } var dec SetCodeAuthorization if err := json.Unmarshal(input, &dec); err != nil { return err } - if dec.ChainID == nil { - return errors.New("missing required field 'chainId' for SetCodeAuthorization") + if dec.Unchained == nil { + return errors.New("missing required field 'unchained' for SetCodeAuthorization") } - s.ChainID = uint64(*dec.ChainID) + s.Unchained = *dec.Unchained if dec.Address == nil { return errors.New("missing required field 'address' for SetCodeAuthorization") } diff --git a/core/types/tx_setcode.go b/core/types/tx_setcode.go index f14ae3bc9d2f9..6fbe463954c70 100644 --- a/core/types/tx_setcode.go +++ b/core/types/tx_setcode.go @@ -70,52 +70,54 @@ type SetCodeTx struct { // SetCodeAuthorization is an authorization from an account to deploy code at its address. type SetCodeAuthorization struct { - ChainID uint64 `json:"chainId" gencodec:"required"` - Address common.Address `json:"address" gencodec:"required"` - Nonce uint64 `json:"nonce" gencodec:"required"` - V uint8 `json:"yParity" gencodec:"required"` - R uint256.Int `json:"r" gencodec:"required"` - S uint256.Int `json:"s" gencodec:"required"` + Unchained bool `json:"unchained" gencodec:"required"` + Address common.Address `json:"address" gencodec:"required"` + Nonce uint64 `json:"nonce" gencodec:"required"` + V uint8 `json:"yParity" gencodec:"required"` + R uint256.Int `json:"r" gencodec:"required"` + S uint256.Int `json:"s" gencodec:"required"` } // field type overrides for gencodec type authorizationMarshaling struct { - ChainID hexutil.Uint64 - Nonce hexutil.Uint64 - V hexutil.Uint64 - R hexutil.U256 - S hexutil.U256 + Nonce hexutil.Uint64 + V hexutil.Uint64 + R hexutil.U256 + S hexutil.U256 } // SignSetCode creates a signed the SetCode authorization. -func SignSetCode(prv *ecdsa.PrivateKey, auth SetCodeAuthorization) (SetCodeAuthorization, error) { - sighash := auth.sigHash() +func SignSetCode(prv *ecdsa.PrivateKey, chainID *big.Int, auth SetCodeAuthorization) (SetCodeAuthorization, error) { + sighash := auth.sigHash(chainID) sig, err := crypto.Sign(sighash[:], prv) if err != nil { return SetCodeAuthorization{}, err } r, s, _ := decodeSignature(sig) return SetCodeAuthorization{ - ChainID: auth.ChainID, - Address: auth.Address, - Nonce: auth.Nonce, - V: sig[64], - R: *uint256.MustFromBig(r), - S: *uint256.MustFromBig(s), + Unchained: auth.Unchained, + Address: auth.Address, + Nonce: auth.Nonce, + V: sig[64], + R: *uint256.MustFromBig(r), + S: *uint256.MustFromBig(s), }, nil } -func (a *SetCodeAuthorization) sigHash() common.Hash { +func (a *SetCodeAuthorization) sigHash(chainID *big.Int) common.Hash { + if a.Unchained { + chainID = common.Big0 + } return prefixedRlpHash(0x05, []any{ - a.ChainID, + chainID, a.Address, a.Nonce, }) } // Authority recovers the the authorizing account of an authorization. -func (a *SetCodeAuthorization) Authority() (common.Address, error) { - sighash := a.sigHash() +func (a *SetCodeAuthorization) Authority(chainID *big.Int) (common.Address, error) { + sighash := a.sigHash(chainID) if !crypto.ValidateSignatureValues(a.V, a.R.ToBig(), a.S.ToBig(), true) { return common.Address{}, ErrInvalidSig }