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 }