mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 01:43:47 +00:00
core, core/types: implement unchained flag in SetCodeAuthorization
This commit is contained in:
parent
f1e6372eea
commit
979f7c9776
4 changed files with 52 additions and 50 deletions
|
|
@ -4273,15 +4273,14 @@ func TestEIP7702(t *testing.T) {
|
||||||
// 1. tx -> addr1 which is delegated to 0xaaaa
|
// 1. tx -> addr1 which is delegated to 0xaaaa
|
||||||
// 2. addr1:0xaaaa calls into addr2:0xbbbb
|
// 2. addr1:0xaaaa calls into addr2:0xbbbb
|
||||||
// 3. addr2:0xbbbb writes to storage
|
// 3. addr2:0xbbbb writes to storage
|
||||||
auth1, _ := types.SignSetCode(key1, types.SetCodeAuthorization{
|
auth1, _ := types.SignSetCode(key1, gspec.Config.ChainID, types.SetCodeAuthorization{
|
||||||
ChainID: gspec.Config.ChainID.Uint64(),
|
|
||||||
Address: aa,
|
Address: aa,
|
||||||
Nonce: 1,
|
Nonce: 1,
|
||||||
})
|
})
|
||||||
auth2, _ := types.SignSetCode(key2, types.SetCodeAuthorization{
|
auth2, _ := types.SignSetCode(key2, gspec.Config.ChainID, types.SetCodeAuthorization{
|
||||||
ChainID: 0,
|
Unchained: true,
|
||||||
Address: bb,
|
Address: bb,
|
||||||
Nonce: 0,
|
Nonce: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
|
_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
|
||||||
|
|
|
||||||
|
|
@ -529,16 +529,12 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
||||||
|
|
||||||
// validateAuthorization validates an EIP-7702 authorization against the state.
|
// validateAuthorization validates an EIP-7702 authorization against the state.
|
||||||
func (st *stateTransition) validateAuthorization(auth *types.SetCodeAuthorization) (authority common.Address, err error) {
|
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.
|
// Limit nonce to 2^64-1 per EIP-2681.
|
||||||
if auth.Nonce+1 < auth.Nonce {
|
if auth.Nonce+1 < auth.Nonce {
|
||||||
return authority, ErrAuthorizationNonceOverflow
|
return authority, ErrAuthorizationNonceOverflow
|
||||||
}
|
}
|
||||||
// Validate signature values and recover authority.
|
// Validate signature values and recover authority.
|
||||||
authority, err = auth.Authority()
|
authority, err = auth.Authority(st.evm.ChainConfig().ChainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return authority, fmt.Errorf("%w: %v", ErrAuthorizationInvalidSignature, err)
|
return authority, fmt.Errorf("%w: %v", ErrAuthorizationInvalidSignature, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,15 @@ var _ = (*authorizationMarshaling)(nil)
|
||||||
// MarshalJSON marshals as JSON.
|
// MarshalJSON marshals as JSON.
|
||||||
func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) {
|
func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) {
|
||||||
type SetCodeAuthorization struct {
|
type SetCodeAuthorization struct {
|
||||||
ChainID hexutil.Uint64 `json:"chainId" gencodec:"required"`
|
Unchained bool `json:"unchained" gencodec:"required"`
|
||||||
Address common.Address `json:"address" gencodec:"required"`
|
Address common.Address `json:"address" gencodec:"required"`
|
||||||
Nonce hexutil.Uint64 `json:"nonce" gencodec:"required"`
|
Nonce hexutil.Uint64 `json:"nonce" gencodec:"required"`
|
||||||
V hexutil.Uint64 `json:"yParity" gencodec:"required"`
|
V hexutil.Uint64 `json:"yParity" gencodec:"required"`
|
||||||
R hexutil.U256 `json:"r" gencodec:"required"`
|
R hexutil.U256 `json:"r" gencodec:"required"`
|
||||||
S hexutil.U256 `json:"s" gencodec:"required"`
|
S hexutil.U256 `json:"s" gencodec:"required"`
|
||||||
}
|
}
|
||||||
var enc SetCodeAuthorization
|
var enc SetCodeAuthorization
|
||||||
enc.ChainID = hexutil.Uint64(s.ChainID)
|
enc.Unchained = s.Unchained
|
||||||
enc.Address = s.Address
|
enc.Address = s.Address
|
||||||
enc.Nonce = hexutil.Uint64(s.Nonce)
|
enc.Nonce = hexutil.Uint64(s.Nonce)
|
||||||
enc.V = hexutil.Uint64(s.V)
|
enc.V = hexutil.Uint64(s.V)
|
||||||
|
|
@ -36,21 +36,21 @@ func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) {
|
||||||
// UnmarshalJSON unmarshals from JSON.
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
func (s *SetCodeAuthorization) UnmarshalJSON(input []byte) error {
|
func (s *SetCodeAuthorization) UnmarshalJSON(input []byte) error {
|
||||||
type SetCodeAuthorization struct {
|
type SetCodeAuthorization struct {
|
||||||
ChainID *hexutil.Uint64 `json:"chainId" gencodec:"required"`
|
Unchained *bool `json:"unchained" gencodec:"required"`
|
||||||
Address *common.Address `json:"address" gencodec:"required"`
|
Address *common.Address `json:"address" gencodec:"required"`
|
||||||
Nonce *hexutil.Uint64 `json:"nonce" gencodec:"required"`
|
Nonce *hexutil.Uint64 `json:"nonce" gencodec:"required"`
|
||||||
V *hexutil.Uint64 `json:"yParity" gencodec:"required"`
|
V *hexutil.Uint64 `json:"yParity" gencodec:"required"`
|
||||||
R *hexutil.U256 `json:"r" gencodec:"required"`
|
R *hexutil.U256 `json:"r" gencodec:"required"`
|
||||||
S *hexutil.U256 `json:"s" gencodec:"required"`
|
S *hexutil.U256 `json:"s" gencodec:"required"`
|
||||||
}
|
}
|
||||||
var dec SetCodeAuthorization
|
var dec SetCodeAuthorization
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if dec.ChainID == nil {
|
if dec.Unchained == nil {
|
||||||
return errors.New("missing required field 'chainId' for SetCodeAuthorization")
|
return errors.New("missing required field 'unchained' for SetCodeAuthorization")
|
||||||
}
|
}
|
||||||
s.ChainID = uint64(*dec.ChainID)
|
s.Unchained = *dec.Unchained
|
||||||
if dec.Address == nil {
|
if dec.Address == nil {
|
||||||
return errors.New("missing required field 'address' for SetCodeAuthorization")
|
return errors.New("missing required field 'address' for SetCodeAuthorization")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,52 +70,59 @@ type SetCodeTx struct {
|
||||||
|
|
||||||
// SetCodeAuthorization is an authorization from an account to deploy code at its address.
|
// SetCodeAuthorization is an authorization from an account to deploy code at its address.
|
||||||
type SetCodeAuthorization struct {
|
type SetCodeAuthorization struct {
|
||||||
ChainID uint64 `json:"chainId" gencodec:"required"`
|
Unchained bool `json:"unchained" gencodec:"required"`
|
||||||
Address common.Address `json:"address" gencodec:"required"`
|
Address common.Address `json:"address" gencodec:"required"`
|
||||||
Nonce uint64 `json:"nonce" gencodec:"required"`
|
Nonce uint64 `json:"nonce" gencodec:"required"`
|
||||||
V uint8 `json:"yParity" gencodec:"required"`
|
V uint8 `json:"yParity" gencodec:"required"`
|
||||||
R uint256.Int `json:"r" gencodec:"required"`
|
R uint256.Int `json:"r" gencodec:"required"`
|
||||||
S uint256.Int `json:"s" gencodec:"required"`
|
S uint256.Int `json:"s" gencodec:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// field type overrides for gencodec
|
// field type overrides for gencodec
|
||||||
type authorizationMarshaling struct {
|
type authorizationMarshaling struct {
|
||||||
ChainID hexutil.Uint64
|
Nonce hexutil.Uint64
|
||||||
Nonce hexutil.Uint64
|
V hexutil.Uint64
|
||||||
V hexutil.Uint64
|
R hexutil.U256
|
||||||
R hexutil.U256
|
S hexutil.U256
|
||||||
S hexutil.U256
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignSetCode creates a signed the SetCode authorization.
|
// SignSetCode creates a signed the SetCode authorization.
|
||||||
func SignSetCode(prv *ecdsa.PrivateKey, auth SetCodeAuthorization) (SetCodeAuthorization, error) {
|
func SignSetCode(prv *ecdsa.PrivateKey, chainID *big.Int, auth SetCodeAuthorization) (SetCodeAuthorization, error) {
|
||||||
sighash := auth.sigHash()
|
sighash := auth.sigHash(chainID)
|
||||||
sig, err := crypto.Sign(sighash[:], prv)
|
sig, err := crypto.Sign(sighash[:], prv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return SetCodeAuthorization{}, err
|
return SetCodeAuthorization{}, err
|
||||||
}
|
}
|
||||||
r, s, _ := decodeSignature(sig)
|
r, s, _ := decodeSignature(sig)
|
||||||
return SetCodeAuthorization{
|
return SetCodeAuthorization{
|
||||||
ChainID: auth.ChainID,
|
Unchained: auth.Unchained,
|
||||||
Address: auth.Address,
|
Address: auth.Address,
|
||||||
Nonce: auth.Nonce,
|
Nonce: auth.Nonce,
|
||||||
V: sig[64],
|
V: sig[64],
|
||||||
R: *uint256.MustFromBig(r),
|
R: *uint256.MustFromBig(r),
|
||||||
S: *uint256.MustFromBig(s),
|
S: *uint256.MustFromBig(s),
|
||||||
}, nil
|
}, 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{
|
return prefixedRlpHash(0x05, []any{
|
||||||
a.ChainID,
|
chainID,
|
||||||
a.Address,
|
a.Address,
|
||||||
a.Nonce,
|
a.Nonce,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authority recovers the the authorizing account of an authorization.
|
// Authority recovers the the authorizing account of an authorization.
|
||||||
func (a *SetCodeAuthorization) Authority() (common.Address, error) {
|
func (a *SetCodeAuthorization) Authority(chainID *big.Int) (common.Address, error) {
|
||||||
sighash := a.sigHash()
|
if chainID == nil {
|
||||||
|
// This sanity check is important, since a missing chainID would just end up
|
||||||
|
// being encoded into the signature hash, leading to an incorrectly derived address.
|
||||||
|
panic("missing chainID")
|
||||||
|
}
|
||||||
|
sighash := a.sigHash(chainID)
|
||||||
if !crypto.ValidateSignatureValues(a.V, a.R.ToBig(), a.S.ToBig(), true) {
|
if !crypto.ValidateSignatureValues(a.V, a.R.ToBig(), a.S.ToBig(), true) {
|
||||||
return common.Address{}, ErrInvalidSig
|
return common.Address{}, ErrInvalidSig
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue