mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 09:53:48 +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,13 +4273,12 @@ 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,
|
||||
auth2, _ := types.SignSetCode(key2, gspec.Config.ChainID, types.SetCodeAuthorization{
|
||||
Unchained: true,
|
||||
Address: bb,
|
||||
Nonce: 0,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ var _ = (*authorizationMarshaling)(nil)
|
|||
// MarshalJSON marshals as JSON.
|
||||
func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) {
|
||||
type SetCodeAuthorization struct {
|
||||
ChainID hexutil.Uint64 `json:"chainId" 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"`
|
||||
|
|
@ -24,7 +24,7 @@ func (s SetCodeAuthorization) MarshalJSON() ([]byte, error) {
|
|||
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,7 +36,7 @@ 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"`
|
||||
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"`
|
||||
|
|
@ -47,10 +47,10 @@ func (s *SetCodeAuthorization) UnmarshalJSON(input []byte) error {
|
|||
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")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ 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"`
|
||||
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"`
|
||||
|
|
@ -80,7 +80,6 @@ type SetCodeAuthorization struct {
|
|||
|
||||
// field type overrides for gencodec
|
||||
type authorizationMarshaling struct {
|
||||
ChainID hexutil.Uint64
|
||||
Nonce hexutil.Uint64
|
||||
V hexutil.Uint64
|
||||
R hexutil.U256
|
||||
|
|
@ -88,15 +87,15 @@ type authorizationMarshaling struct {
|
|||
}
|
||||
|
||||
// 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,
|
||||
Unchained: auth.Unchained,
|
||||
Address: auth.Address,
|
||||
Nonce: auth.Nonce,
|
||||
V: sig[64],
|
||||
|
|
@ -105,17 +104,25 @@ func SignSetCode(prv *ecdsa.PrivateKey, auth SetCodeAuthorization) (SetCodeAutho
|
|||
}, 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) {
|
||||
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) {
|
||||
return common.Address{}, ErrInvalidSig
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue