github.com/amazechain/amc@v0.1.3/internal/avm/types/transaction_signing.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The AmazeChain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package types
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"errors"
    22  	"fmt"
    23  	"github.com/amazechain/amc/common/crypto"
    24  	"github.com/amazechain/amc/internal/avm/common"
    25  	"github.com/amazechain/amc/params"
    26  	"github.com/holiman/uint256"
    27  	"math/big"
    28  )
    29  
    30  var (
    31  	ErrInvalidSig           = errors.New("invalid transaction v, r, s values")
    32  	ErrUnexpectedProtection = errors.New("transaction type does not supported EIP-155 protected signatures")
    33  	ErrInvalidTxType        = errors.New("transaction type not valid in this context")
    34  	ErrTxTypeNotSupported   = errors.New("transaction type not supported")
    35  	ErrGasFeeCapTooLow      = errors.New("fee cap less than base fee")
    36  	errShortTypedTx         = errors.New("typed transaction too short")
    37  	ErrInvalidChainId       = errors.New("invalid chain id for signer")
    38  )
    39  
    40  // sigCache is used to cache the derived sender and contains
    41  // the signer used to derive it.
    42  type sigCache struct {
    43  	signer Signer
    44  	from   common.Address
    45  }
    46  
    47  // MakeSigner returns a Signer based on the given chain blockchain and block number.
    48  func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
    49  	var signer Signer
    50  	switch {
    51  	case config.IsLondon(blockNumber.Uint64()):
    52  		signer = NewLondonSigner(config.ChainID)
    53  	case config.IsBerlin(blockNumber.Uint64()):
    54  		signer = NewEIP2930Signer(config.ChainID)
    55  	//case config.IsEIP155(blockNumber):
    56  	//	signer = NewEIP155Signer(config.ChainID)
    57  	case config.IsHomestead(blockNumber.Uint64()):
    58  		signer = HomesteadSigner{}
    59  	default:
    60  		signer = FrontierSigner{}
    61  	}
    62  	return signer
    63  }
    64  
    65  // LatestSigner returns the 'most permissive' Signer available for the given chain
    66  // configuration. Specifically, this enables support of EIP-155 replay protection and
    67  // EIP-2930 access list transactions when their respective forks are scheduled to occur at
    68  // any block number in the chain blockchain.
    69  //
    70  // Use this in transaction-handling code where the current block number is unknown. If you
    71  // have the current block number available, use MakeSigner instead.
    72  func LatestSigner(config *params.ChainConfig) Signer {
    73  	if config.ChainID != nil {
    74  		if config.LondonBlock != nil {
    75  			return NewLondonSigner(config.ChainID)
    76  		}
    77  		if config.BerlinBlock != nil {
    78  			return NewEIP2930Signer(config.ChainID)
    79  		}
    80  		//if config.EIP155Block != nil {
    81  		//	return NewEIP155Signer(config.ChainID)
    82  		//}
    83  	}
    84  	return HomesteadSigner{}
    85  }
    86  
    87  // LatestSignerForChainID returns the 'most permissive' Signer available. Specifically,
    88  // this enables support for EIP-155 replay protection and all implemented EIP-2718
    89  // transaction types if chainID is non-nil.
    90  //
    91  // Use this in transaction-handling code where the current block number and fork
    92  // configuration are unknown. If you have a ChainConfig, use LatestSigner instead.
    93  // If you have a ChainConfig and know the current block number, use MakeSigner instead.
    94  func LatestSignerForChainID(chainID *big.Int) Signer {
    95  	if chainID == nil {
    96  		return HomesteadSigner{}
    97  	}
    98  	return NewLondonSigner(chainID)
    99  }
   100  
   101  // SignTx signs the transaction using the given signer and private key.
   102  func SignTx(tx *Transaction, s Signer, prv *ecdsa.PrivateKey) (*Transaction, error) {
   103  	h := s.Hash(tx)
   104  	sig, err := crypto.Sign(h[:], prv)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	return tx.WithSignature(s, sig)
   109  }
   110  
   111  // SignNewTx creates a transaction and signs it.
   112  func SignNewTx(prv *ecdsa.PrivateKey, s Signer, txdata TxData) (*Transaction, error) {
   113  	tx := NewTx(txdata)
   114  	h := s.Hash(tx)
   115  	sig, err := crypto.Sign(h[:], prv)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	return tx.WithSignature(s, sig)
   120  }
   121  
   122  // MustSignNewTx creates a transaction and signs it.
   123  // This panics if the transaction cannot be signed.
   124  func MustSignNewTx(prv *ecdsa.PrivateKey, s Signer, txdata TxData) *Transaction {
   125  	tx, err := SignNewTx(prv, s, txdata)
   126  	if err != nil {
   127  		panic(err)
   128  	}
   129  	return tx
   130  }
   131  
   132  // Sender returns the address derived from the signature (V, R, S) using secp256k1
   133  // elliptic curve and an error if it failed deriving or upon an incorrect
   134  // signature.
   135  //
   136  // Sender may cache the address, allowing it to be used regardless of
   137  // signing method. The cache is invalidated if the cached signer does
   138  // not match the signer used in the current call.
   139  func Sender(signer Signer, tx *Transaction) (common.Address, error) {
   140  	if sc := tx.from.Load(); sc != nil {
   141  		sigCache := sc.(sigCache)
   142  		// If the signer used to derive from in a previous
   143  		// call is not the same as used current, invalidate
   144  		// the cache.
   145  		if sigCache.signer.Equal(signer) {
   146  			return sigCache.from, nil
   147  		}
   148  	}
   149  
   150  	addr, err := signer.Sender(tx)
   151  	if err != nil {
   152  		return common.Address{}, err
   153  	}
   154  	tx.from.Store(sigCache{signer: signer, from: addr})
   155  	return addr, nil
   156  }
   157  
   158  // Signer encapsulates transaction signature handling. The name of this type is slightly
   159  // misleading because Signers don't actually sign, they're just for validating and
   160  // processing of signatures.
   161  //
   162  // Note that this interface is not a stable API and may change at any time to accommodate
   163  // new protocol rules.
   164  type Signer interface {
   165  	// Sender returns the sender address of the transaction.
   166  	Sender(tx *Transaction) (common.Address, error)
   167  
   168  	// SignatureValues returns the raw R, S, V values corresponding to the
   169  	// given signature.
   170  	SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error)
   171  	ChainID() *big.Int
   172  
   173  	// Hash returns 'signature hash', i.e. the transaction hash that is signed by the
   174  	// private key. This hash does not uniquely identify the transaction.
   175  	Hash(tx *Transaction) common.Hash
   176  
   177  	// Equal returns true if the given signer is the same as the receiver.
   178  	Equal(Signer) bool
   179  }
   180  
   181  type londonSigner struct{ eip2930Signer }
   182  
   183  // NewLondonSigner returns a signer that accepts
   184  // - EIP-1559 dynamic fee transactions
   185  // - EIP-2930 access list transactions,
   186  // - EIP-155 replay protected transactions, and
   187  // - legacy Homestead transactions.
   188  func NewLondonSigner(chainId *big.Int) Signer {
   189  	return londonSigner{eip2930Signer{NewEIP155Signer(chainId)}}
   190  }
   191  
   192  func (s londonSigner) Sender(tx *Transaction) (common.Address, error) {
   193  	if tx.Type() != DynamicFeeTxType {
   194  		return s.eip2930Signer.Sender(tx)
   195  	}
   196  	V, R, S := tx.RawSignatureValues()
   197  	// DynamicFee txs are defined to use 0 and 1 as their recovery
   198  	// id, add 27 to become equivalent to unprotected Homestead signatures.
   199  	V = new(big.Int).Add(V, big.NewInt(27))
   200  	if tx.ChainId().Cmp(s.chainId) != 0 {
   201  		return common.Address{}, ErrInvalidChainId
   202  	}
   203  	return recoverPlain(s.Hash(tx), R, S, V, true)
   204  }
   205  
   206  func (s londonSigner) Equal(s2 Signer) bool {
   207  	x, ok := s2.(londonSigner)
   208  	return ok && x.chainId.Cmp(s.chainId) == 0
   209  }
   210  
   211  func (s londonSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) {
   212  	txdata, ok := tx.inner.(*DynamicFeeTx)
   213  	if !ok {
   214  		return s.eip2930Signer.SignatureValues(tx, sig)
   215  	}
   216  	// Check that chain ID of tx matches the signer. We also accept ID zero here,
   217  	// because it indicates that the chain ID was not specified in the tx.
   218  	if txdata.ChainID.Sign() != 0 && txdata.ChainID.Cmp(s.chainId) != 0 {
   219  		return nil, nil, nil, ErrInvalidChainId
   220  	}
   221  	R, S, _ = decodeSignature(sig)
   222  	V = big.NewInt(int64(sig[64]))
   223  	return R, S, V, nil
   224  }
   225  
   226  // Hash returns the hash to be signed by the sender.
   227  // It does not uniquely identify the transaction.
   228  func (s londonSigner) Hash(tx *Transaction) common.Hash {
   229  	if tx.Type() != DynamicFeeTxType {
   230  		return s.eip2930Signer.Hash(tx)
   231  	}
   232  	return prefixedRlpHash(
   233  		tx.Type(),
   234  		[]interface{}{
   235  			s.chainId,
   236  			tx.Nonce(),
   237  			tx.GasTipCap(),
   238  			tx.GasFeeCap(),
   239  			tx.Gas(),
   240  			tx.To(),
   241  			tx.Value(),
   242  			tx.Data(),
   243  			tx.AccessList(),
   244  		})
   245  }
   246  
   247  type eip2930Signer struct{ EIP155Signer }
   248  
   249  // NewEIP2930Signer returns a signer that accepts EIP-2930 access list transactions,
   250  // EIP-155 replay protected transactions, and legacy Homestead transactions.
   251  func NewEIP2930Signer(chainId *big.Int) Signer {
   252  	return eip2930Signer{NewEIP155Signer(chainId)}
   253  }
   254  
   255  func (s eip2930Signer) ChainID() *big.Int {
   256  	return s.chainId
   257  }
   258  
   259  func (s eip2930Signer) Equal(s2 Signer) bool {
   260  	x, ok := s2.(eip2930Signer)
   261  	return ok && x.chainId.Cmp(s.chainId) == 0
   262  }
   263  
   264  func (s eip2930Signer) Sender(tx *Transaction) (common.Address, error) {
   265  	V, R, S := tx.RawSignatureValues()
   266  	switch tx.Type() {
   267  	case LegacyTxType:
   268  		if !tx.Protected() {
   269  			return HomesteadSigner{}.Sender(tx)
   270  		}
   271  		V = new(big.Int).Sub(V, s.chainIdMul)
   272  		V.Sub(V, big8)
   273  	case AccessListTxType:
   274  		// AL txs are defined to use 0 and 1 as their recovery
   275  		// id, add 27 to become equivalent to unprotected Homestead signatures.
   276  		V = new(big.Int).Add(V, big.NewInt(27))
   277  	default:
   278  		return common.Address{}, ErrTxTypeNotSupported
   279  	}
   280  	if tx.ChainId().Cmp(s.chainId) != 0 {
   281  		return common.Address{}, ErrInvalidChainId
   282  	}
   283  	return recoverPlain(s.Hash(tx), R, S, V, true)
   284  }
   285  
   286  func (s eip2930Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) {
   287  	switch txdata := tx.inner.(type) {
   288  	case *LegacyTx:
   289  		return s.EIP155Signer.SignatureValues(tx, sig)
   290  	case *AccessListTx:
   291  		// Check that chain ID of tx matches the signer. We also accept ID zero here,
   292  		// because it indicates that the chain ID was not specified in the tx.
   293  		if txdata.ChainID.Sign() != 0 && txdata.ChainID.Cmp(s.chainId) != 0 {
   294  			return nil, nil, nil, ErrInvalidChainId
   295  		}
   296  		R, S, _ = decodeSignature(sig)
   297  		V = big.NewInt(int64(sig[64]))
   298  	default:
   299  		return nil, nil, nil, ErrTxTypeNotSupported
   300  	}
   301  	return R, S, V, nil
   302  }
   303  
   304  // Hash returns the hash to be signed by the sender.
   305  // It does not uniquely identify the transaction.
   306  func (s eip2930Signer) Hash(tx *Transaction) common.Hash {
   307  	switch tx.Type() {
   308  	case LegacyTxType:
   309  		return rlpHash([]interface{}{
   310  			tx.Nonce(),
   311  			tx.GasPrice(),
   312  			tx.Gas(),
   313  			tx.To(),
   314  			tx.Value(),
   315  			tx.Data(),
   316  			s.chainId, uint(0), uint(0),
   317  		})
   318  	case AccessListTxType:
   319  		return prefixedRlpHash(
   320  			tx.Type(),
   321  			[]interface{}{
   322  				s.chainId,
   323  				tx.Nonce(),
   324  				tx.GasPrice(),
   325  				tx.Gas(),
   326  				tx.To(),
   327  				tx.Value(),
   328  				tx.Data(),
   329  				tx.AccessList(),
   330  			})
   331  	default:
   332  		// This _should_ not happen, but in case someone sends in a bad
   333  		// json struct via RPC, it's probably more prudent to return an
   334  		// empty hash instead of killing the node with a panic
   335  		//panic("Unsupported transaction type: %d", tx.typ)
   336  		return common.Hash{}
   337  	}
   338  }
   339  
   340  // EIP155Signer implements Signer using the EIP-155 rules. This accepts transactions which
   341  // are replay-protected as well as unprotected homestead transactions.
   342  type EIP155Signer struct {
   343  	chainId, chainIdMul *big.Int
   344  }
   345  
   346  func NewEIP155Signer(chainId *big.Int) EIP155Signer {
   347  	if chainId == nil {
   348  		chainId = new(big.Int)
   349  	}
   350  	return EIP155Signer{
   351  		chainId:    chainId,
   352  		chainIdMul: new(big.Int).Mul(chainId, big.NewInt(2)),
   353  	}
   354  }
   355  
   356  func (s EIP155Signer) ChainID() *big.Int {
   357  	return s.chainId
   358  }
   359  
   360  func (s EIP155Signer) Equal(s2 Signer) bool {
   361  	eip155, ok := s2.(EIP155Signer)
   362  	return ok && eip155.chainId.Cmp(s.chainId) == 0
   363  }
   364  
   365  var big8 = big.NewInt(8)
   366  
   367  func (s EIP155Signer) Sender(tx *Transaction) (common.Address, error) {
   368  	if tx.Type() != LegacyTxType {
   369  		return common.Address{}, ErrTxTypeNotSupported
   370  	}
   371  	if !tx.Protected() {
   372  		return HomesteadSigner{}.Sender(tx)
   373  	}
   374  	if tx.ChainId().Cmp(s.chainId) != 0 {
   375  		return common.Address{}, ErrInvalidChainId
   376  	}
   377  	V, R, S := tx.RawSignatureValues()
   378  	V = new(big.Int).Sub(V, s.chainIdMul)
   379  	V.Sub(V, big8)
   380  	return recoverPlain(s.Hash(tx), R, S, V, true)
   381  }
   382  
   383  // SignatureValues returns signature values. This signature
   384  // needs to be in the [R || S || V] format where V is 0 or 1.
   385  func (s EIP155Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) {
   386  	if tx.Type() != LegacyTxType {
   387  		return nil, nil, nil, ErrTxTypeNotSupported
   388  	}
   389  	R, S, V = decodeSignature(sig)
   390  	if s.chainId.Sign() != 0 {
   391  		V = big.NewInt(int64(sig[64] + 35))
   392  		V.Add(V, s.chainIdMul)
   393  	}
   394  	return R, S, V, nil
   395  }
   396  
   397  // Hash returns the hash to be signed by the sender.
   398  // It does not uniquely identify the transaction.
   399  func (s EIP155Signer) Hash(tx *Transaction) common.Hash {
   400  	return rlpHash([]interface{}{
   401  		tx.Nonce(),
   402  		tx.GasPrice(),
   403  		tx.Gas(),
   404  		tx.To(),
   405  		tx.Value(),
   406  		tx.Data(),
   407  		s.chainId, uint(0), uint(0),
   408  	})
   409  }
   410  
   411  // HomesteadTransaction implements TransactionInterface using the
   412  // homestead rules.
   413  type HomesteadSigner struct{ FrontierSigner }
   414  
   415  func (s HomesteadSigner) ChainID() *big.Int {
   416  	return nil
   417  }
   418  
   419  func (s HomesteadSigner) Equal(s2 Signer) bool {
   420  	_, ok := s2.(HomesteadSigner)
   421  	return ok
   422  }
   423  
   424  // SignatureValues returns signature values. This signature
   425  // needs to be in the [R || S || V] format where V is 0 or 1.
   426  func (hs HomesteadSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) {
   427  	return hs.FrontierSigner.SignatureValues(tx, sig)
   428  }
   429  
   430  func (hs HomesteadSigner) Sender(tx *Transaction) (common.Address, error) {
   431  	if tx.Type() != LegacyTxType {
   432  		return common.Address{}, ErrTxTypeNotSupported
   433  	}
   434  	v, r, s := tx.RawSignatureValues()
   435  	return recoverPlain(hs.Hash(tx), r, s, v, true)
   436  }
   437  
   438  type FrontierSigner struct{}
   439  
   440  func (s FrontierSigner) ChainID() *big.Int {
   441  	return nil
   442  }
   443  
   444  func (s FrontierSigner) Equal(s2 Signer) bool {
   445  	_, ok := s2.(FrontierSigner)
   446  	return ok
   447  }
   448  
   449  func (fs FrontierSigner) Sender(tx *Transaction) (common.Address, error) {
   450  	if tx.Type() != LegacyTxType {
   451  		return common.Address{}, ErrTxTypeNotSupported
   452  	}
   453  	v, r, s := tx.RawSignatureValues()
   454  	return recoverPlain(fs.Hash(tx), r, s, v, false)
   455  }
   456  
   457  // SignatureValues returns signature values. This signature
   458  // needs to be in the [R || S || V] format where V is 0 or 1.
   459  func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) {
   460  	if tx.Type() != LegacyTxType {
   461  		return nil, nil, nil, ErrTxTypeNotSupported
   462  	}
   463  	r, s, v = decodeSignature(sig)
   464  	return r, s, v, nil
   465  }
   466  
   467  // Hash returns the hash to be signed by the sender.
   468  // It does not uniquely identify the transaction.
   469  func (fs FrontierSigner) Hash(tx *Transaction) common.Hash {
   470  	return rlpHash([]interface{}{
   471  		tx.Nonce(),
   472  		tx.GasPrice(),
   473  		tx.Gas(),
   474  		tx.To(),
   475  		tx.Value(),
   476  		tx.Data(),
   477  	})
   478  }
   479  
   480  func decodeSignature(sig []byte) (r, s, v *big.Int) {
   481  	if len(sig) != crypto.SignatureLength {
   482  		panic(fmt.Sprintf("wrong size for signature: got %d, want %d", len(sig), crypto.SignatureLength))
   483  	}
   484  	r = new(big.Int).SetBytes(sig[:32])
   485  	s = new(big.Int).SetBytes(sig[32:64])
   486  	v = new(big.Int).SetBytes([]byte{sig[64] + 27})
   487  	return r, s, v
   488  }
   489  
   490  func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (common.Address, error) {
   491  	if Vb.BitLen() > 8 {
   492  		return common.Address{}, ErrInvalidSig
   493  	}
   494  	V := byte(Vb.Uint64() - 27)
   495  	ir, _ := uint256.FromBig(R)
   496  	is, _ := uint256.FromBig(S)
   497  	if !crypto.ValidateSignatureValues(V, ir, is, homestead) {
   498  		return common.Address{}, ErrInvalidSig
   499  	}
   500  	// encode the signature in uncompressed format
   501  	r, s := R.Bytes(), S.Bytes()
   502  	sig := make([]byte, crypto.SignatureLength)
   503  	copy(sig[32-len(r):32], r)
   504  	copy(sig[64-len(s):64], s)
   505  	sig[64] = V
   506  	// recover the public key from the signature
   507  	pub, err := crypto.Ecrecover(sighash[:], sig)
   508  	if err != nil {
   509  		return common.Address{}, err
   510  	}
   511  	if len(pub) == 0 || pub[0] != 4 {
   512  		return common.Address{}, errors.New("invalid public key")
   513  	}
   514  	var addr common.Address
   515  	copy(addr[:], crypto.Keccak256(pub[1:])[12:])
   516  	return addr, nil
   517  }
   518  
   519  // deriveChainId derives the chain id from the given v parameter
   520  func deriveChainId(v *big.Int) *big.Int {
   521  	if v.BitLen() <= 64 {
   522  		v := v.Uint64()
   523  		if v == 27 || v == 28 {
   524  			return new(big.Int)
   525  		}
   526  		return new(big.Int).SetUint64((v - 35) / 2)
   527  	}
   528  	v = new(big.Int).Sub(v, big.NewInt(35))
   529  	return v.Div(v, big.NewInt(2))
   530  }