Skip to content

Commit

Permalink
core, core/types: implement unchained flag in SetCodeAuthorization
Browse files Browse the repository at this point in the history
  • Loading branch information
fjl committed Dec 19, 2024
1 parent f1e6372 commit f287de9
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 50 deletions.
11 changes: 5 additions & 6 deletions core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 1 addition & 5 deletions core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
32 changes: 16 additions & 16 deletions core/types/gen_authorization.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 25 additions & 23 deletions core/types/tx_setcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit f287de9

Please sign in to comment.