From 2999e85732c6764ec92c04a250f05bdb91ea1ad7 Mon Sep 17 00:00:00 2001 From: grujicf <61869071+grujicf@users.noreply.github.com> Date: Wed, 14 Feb 2024 10:39:48 +0100 Subject: [PATCH] [BLADE-97] Refactor tx signer (#113) * Refactoring the tx singer logic * Build fix * Fix tests --- crypto/txsigner.go | 93 +++++----- crypto/txsignerBerlin.go | 157 +++++++++++++++++ crypto/txsignerEIP155.go | 164 ++++++++++++++++++ crypto/txsignerFrontier.go | 126 ++++++++++++++ crypto/txsignerHomestead.go | 97 +++++++++++ crypto/txsignerLondon.go | 163 +++++++++++++++++ crypto/txsignerState.go | 126 ++++++++++++++ crypto/txsigner_eip155.go | 91 ---------- crypto/txsigner_eip155_test.go | 10 +- crypto/txsigner_frontier.go | 74 -------- crypto/txsigner_london_berlin.go | 72 -------- ...berlin_test.go => txsigner_london_test.go} | 7 +- go.mod | 4 +- go.sum | 12 ++ helper/common/common.go | 58 +++---- helper/tests/testing.go | 2 +- server/server.go | 10 +- txpool/txpool_test.go | 16 +- 18 files changed, 950 insertions(+), 332 deletions(-) create mode 100644 crypto/txsignerBerlin.go create mode 100644 crypto/txsignerEIP155.go create mode 100644 crypto/txsignerFrontier.go create mode 100644 crypto/txsignerHomestead.go create mode 100644 crypto/txsignerLondon.go create mode 100644 crypto/txsignerState.go delete mode 100644 crypto/txsigner_eip155.go delete mode 100644 crypto/txsigner_frontier.go delete mode 100644 crypto/txsigner_london_berlin.go rename crypto/{txsigner_london_berlin_test.go => txsigner_london_test.go} (95%) diff --git a/crypto/txsigner.go b/crypto/txsigner.go index 530bca94ad..95b89ad704 100644 --- a/crypto/txsigner.go +++ b/crypto/txsigner.go @@ -3,76 +3,84 @@ package crypto import ( "crypto/ecdsa" "errors" - "fmt" "math/big" "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/helper/keccak" "github.com/0xPolygon/polygon-edge/types" + "github.com/umbracle/fastrlp" ) -// Magic numbers from Ethereum, used in v calculation +// Magic numbers, taken from the Ethereum, used in the calculation of the V value +// Only matters in pre-EIP-2930 (pre-Berlin) transactions var ( - big27 = big.NewInt(27) - big35 = big.NewInt(35) + big27 = big.NewInt(27) // pre-EIP-155 + big35 = big.NewInt(35) // EIP-155 ) -// TxSigner is a utility interface used to recover data from a transaction +// RLP encoding helper +var arenaPool fastrlp.ArenaPool + +// TxSigner is a utility interface used to work with transaction signatures type TxSigner interface { // Hash returns the hash of the transaction - Hash(tx *types.Transaction) types.Hash + Hash(*types.Transaction) types.Hash // Sender returns the sender of the transaction - Sender(tx *types.Transaction) (types.Address, error) + Sender(*types.Transaction) (types.Address, error) - // SignTx signs a transaction - SignTx(tx *types.Transaction, priv *ecdsa.PrivateKey) (*types.Transaction, error) + // SingTx takes the original transaction as input and returns its signed version + SignTx(*types.Transaction, *ecdsa.PrivateKey) (*types.Transaction, error) } -// NewSigner creates a new signer object (EIP155 or FrontierSigner) +// NewSigner creates a new signer based on currently supported forks func NewSigner(forks chain.ForksInTime, chainID uint64) TxSigner { var signer TxSigner - if forks.EIP155 { - signer = NewEIP155Signer(chainID, forks.Homestead) + if forks.London { + signer = NewLondonSigner(chainID) + } else if forks.Berlin { + signer = NewBerlinSigner(chainID) + } else if forks.EIP155 { + signer = NewEIP155Signer(chainID) + } else if forks.Homestead { + signer = NewHomesteadSigner() } else { - signer = NewFrontierSigner(forks.Homestead) - } - - // London signer requires a fallback signer that is defined above. - // This is the reason why the london signer check is separated. - if forks.London || forks.Berlin { - return NewLondonOrBerlinSigner(chainID, forks.Homestead, signer) + signer = NewFrontierSigner() } return signer } -// encodeSignature generates a signature value based on the R, S and V value -func encodeSignature(R, S, V *big.Int, isHomestead bool) ([]byte, error) { - if !ValidateSignatureValues(V, R, S, isHomestead) { - return nil, fmt.Errorf("invalid txn signature") +// encodeSignature generates a signature based on the R, S and parity values +// +// The signature encoding format is as follows: +// (32-bytes R, 32-bytes S, 1-byte parity) +// +// Note: although the signature value V, based on different standards, is calculated and encoded in different ways, +// the encodeSignature function expects parity of Y coordinate as third input and that is what will be encoded +func encodeSignature(r, s, parity *big.Int, isHomestead bool) ([]byte, error) { + if !ValidateSignatureValues(parity, r, s, isHomestead) { + return nil, errors.New("Signature encoding failed: Invalid transaction signature") } - sig := make([]byte, 65) - copy(sig[32-len(R.Bytes()):32], R.Bytes()) - copy(sig[64-len(S.Bytes()):64], S.Bytes()) - sig[64] = byte(V.Int64()) // here is safe to convert it since ValidateSignatureValues will validate the v value + signature := make([]byte, 65) - return sig, nil + copy(signature[32-len(r.Bytes()):32], r.Bytes()) + copy(signature[64-len(s.Bytes()):64], s.Bytes()) + signature[64] = byte(parity.Int64()) + + return signature, nil } -// recoverAddress recovers the sender address from a transaction hash and signature parameters. -// It takes the transaction hash, r, s, v values of the signature, -// and a flag indicating if the transaction is in the Homestead format. -// It returns the recovered address and an error if any. -func recoverAddress(txHash types.Hash, r, s, v *big.Int, isHomestead bool) (types.Address, error) { - sig, err := encodeSignature(r, s, v, isHomestead) +// recoverAddress recovers the sender address from the transaction hash and signature R, S and parity values +func recoverAddress(txHash types.Hash, r, s, parity *big.Int, isHomestead bool) (types.Address, error) { + signature, err := encodeSignature(r, s, parity, isHomestead) if err != nil { return types.ZeroAddress, err } - pub, err := Ecrecover(txHash.Bytes(), sig) + publicKey, err := Ecrecover(txHash.Bytes(), signature) if err != nil { return types.ZeroAddress, err } @@ -81,9 +89,12 @@ func recoverAddress(txHash types.Hash, r, s, v *big.Int, isHomestead bool) (type return types.ZeroAddress, errors.New("invalid public key") } - buf := Keccak256(pub[1:])[12:] + // First byte of the publicKey indicates that it is serialized in uncompressed form (it has the value 0x04), so we ommit that + hash := Keccak256(publicKey[1:]) + + address := hash[12:] - return types.BytesToAddress(buf), nil + return types.BytesToAddress(address), nil } // calcTxHash calculates the transaction hash (keccak256 hash of the RLP value) @@ -98,7 +109,7 @@ func calcTxHash(tx *types.Transaction, chainID uint64) types.Hash { switch tx.Type() { case types.AccessListTx: - a := signerPool.Get() + a := arenaPool.Get() v := a.NewArray() v.Set(a.NewUint(chainID)) @@ -137,12 +148,12 @@ func calcTxHash(tx *types.Transaction, chainID uint64) types.Hash { hash = keccak.PrefixedKeccak256Rlp([]byte{byte(tx.Type())}, nil, v) - signerPool.Put(a) + arenaPool.Put(a) return types.BytesToHash(hash) case types.DynamicFeeTx, types.LegacyTx, types.StateTx: - a := signerPool.Get() + a := arenaPool.Get() isDynamicFeeTx := tx.Type() == types.DynamicFeeTx v := a.NewArray() @@ -207,7 +218,7 @@ func calcTxHash(tx *types.Transaction, chainID uint64) types.Hash { hash = keccak.Keccak256Rlp(nil, v) } - signerPool.Put(a) + arenaPool.Put(a) } return types.BytesToHash(hash) diff --git a/crypto/txsignerBerlin.go b/crypto/txsignerBerlin.go new file mode 100644 index 0000000000..2f1aa6cb5c --- /dev/null +++ b/crypto/txsignerBerlin.go @@ -0,0 +1,157 @@ +package crypto + +import ( + "crypto/ecdsa" + "errors" + "math/big" + + "github.com/0xPolygon/polygon-edge/helper/keccak" + "github.com/0xPolygon/polygon-edge/types" +) + +// BerlinSigner may be used for signing legacy (pre-EIP-155 and EIP-155) and EIP-2930 transactions +type BerlinSigner struct { + EIP155Signer +} + +// NewBerlinSigner returns new BerlinSinger object (constructor) +// +// BerlinSigner accepts the following types of transactions: +// - EIP-2930 access list transactions, +// - EIP-155 replay protected transactions, and +// - pre-EIP-155 legacy transactions +func NewBerlinSigner(chainID uint64) *BerlinSigner { + return &BerlinSigner{ + EIP155Signer: EIP155Signer{ + chainID: chainID, + HomesteadSigner: HomesteadSigner{}, + }, + } +} + +// Hash returns the keccak256 hash of the transaction +// +// The EIP-2930 transaction hash preimage is as follows: +// (0x01 || RLP(chainId, nonce, gasPrice, gas, to, value, input, accessList) +// +// Specification: https://eips.ethereum.org/EIPS/eip-2930#specification +func (signer *BerlinSigner) Hash(tx *types.Transaction) types.Hash { + if tx.Type() != types.AccessListTx { + return signer.EIP155Signer.Hash(tx) + } + + var hash []byte + + RLP := arenaPool.Get() + + // RLP(-, -, -, -, -, -, -, -) + hashPreimage := RLP.NewArray() + + // RLP(chainId, -, -, -, -, -, -, -) + hashPreimage.Set(RLP.NewUint(signer.chainID)) + + // RLP(chainId, nonce, -, -, -, -, -, -) + hashPreimage.Set(RLP.NewUint(tx.Nonce())) + + // RLP(chainId, nonce, gasPrice, -, -, -, -, -) + hashPreimage.Set(RLP.NewBigInt(tx.GasPrice())) + + // RLP(chainId, nonce, gasPrice, gas, -, -, -, -) + hashPreimage.Set(RLP.NewUint(tx.Gas())) + + // Checking whether the transaction is a smart contract deployment + if tx.To() == nil { + + // RLP(chainId, nonce, gasPrice, gas, to, -, -, -) + hashPreimage.Set(RLP.NewNull()) + } else { + + // RLP(chainId, nonce, gasPrice, gas, to, -, -, -) + hashPreimage.Set(RLP.NewCopyBytes((*(tx.To())).Bytes())) + } + + // RLP(chainId, nonce, gasPrice, gas, to, value, -, -) + hashPreimage.Set(RLP.NewBigInt(tx.Value())) + + // RLP(chainId, nonce, gasPrice, gas, to, value, input, -) + hashPreimage.Set(RLP.NewCopyBytes(tx.Input())) + + // Serialization format of the access list: [[{20-bytes address}, [{32-bytes key}, ...]], ...] where `...` denotes zero or more items + accessList := RLP.NewArray() + + if tx.AccessList() != nil { + + // accessTuple contains (address, storageKeys[]) + for _, accessTuple := range tx.AccessList() { + + accessTupleSerFormat := RLP.NewArray() + accessTupleSerFormat.Set(RLP.NewCopyBytes(accessTuple.Address.Bytes())) + + storageKeysSerFormat := RLP.NewArray() + + for _, storageKey := range accessTuple.StorageKeys { + storageKeysSerFormat.Set(RLP.NewCopyBytes(storageKey.Bytes())) + } + + accessTupleSerFormat.Set(storageKeysSerFormat) + accessList.Set(accessTupleSerFormat) + } + } + + // RLP(chainId, nonce, gasPrice, gas, to, value, input, accessList) + hashPreimage.Set(accessList) + + // keccak256(0x01 || RLP(chainId, nonce, gasPrice, gas, to, value, input, accessList) + hash = keccak.PrefixedKeccak256Rlp([]byte{byte(tx.Type())}, nil, hashPreimage) + + arenaPool.Put(RLP) + + return types.BytesToHash(hash) +} + +// Sender returns the sender of the transaction +func (signer *BerlinSigner) Sender(tx *types.Transaction) (types.Address, error) { + if tx.Type() != types.AccessListTx { + return signer.EIP155Signer.Sender(tx) + } + + v, r, s := tx.RawSignatureValues() + + return recoverAddress(signer.Hash(tx), r, s, v, true) +} + +// SingTx takes the original transaction as input and returns its signed version +func (signer *BerlinSigner) SignTx(tx *types.Transaction, privateKey *ecdsa.PrivateKey) (*types.Transaction, error) { + if tx.Type() != types.AccessListTx { + return signer.EIP155Signer.SignTx(tx, privateKey) + } + + tx = tx.Copy() + + h := signer.Hash(tx) + + sig, err := Sign(privateKey, h[:]) + if err != nil { + return nil, err + } + + r := new(big.Int).SetBytes(sig[:32]) + s := new(big.Int).SetBytes(sig[32:64]) + + if s.Cmp(secp256k1NHalf) > 0 { + return nil, errors.New("SignTx method: S must be inclusively lower than secp256k1n/2") + } + + v := new(big.Int).SetBytes(signer.calculateV(sig[64])) + + tx.SetSignatureValues(v, r, s) + + return tx, nil +} + +// Private method calculateV returns the V value for the EIP-2930 transactions +// +// V represents the parity of the Y coordinate +func (e *BerlinSigner) calculateV(parity byte) []byte { + return big.NewInt(int64(parity)).Bytes() +} diff --git a/crypto/txsignerEIP155.go b/crypto/txsignerEIP155.go new file mode 100644 index 0000000000..1b06a6ca25 --- /dev/null +++ b/crypto/txsignerEIP155.go @@ -0,0 +1,164 @@ +package crypto + +import ( + "crypto/ecdsa" + "errors" + "math/big" + + "github.com/0xPolygon/polygon-edge/helper/keccak" + "github.com/0xPolygon/polygon-edge/types" +) + +// EIP155Signer may be used for signing legacy (pre-EIP-155 and EIP-155) transactions +type EIP155Signer struct { + HomesteadSigner + chainID uint64 +} + +// NewEIP155Signer returns new EIP155Signer object (constructor) +// +// EIP155Signer accepts the following types of transactions: +// - EIP-155 replay protected transactions, and +// - pre-EIP-155 legacy transactions +func NewEIP155Signer(chainID uint64) *EIP155Signer { + return &EIP155Signer{ + chainID: chainID, + } +} + +// Hash returns the keccak256 hash of the transaction +// +// The EIP-155 transaction hash preimage is as follows: +// RLP(nonce, gasPrice, gas, to, value, input, chainId, 0, 0) +// +// Specification: https://eips.ethereum.org/EIPS/eip-155#specification +func (signer *EIP155Signer) Hash(tx *types.Transaction) types.Hash { + if tx.ChainID().Cmp(big.NewInt(0)) == 0 { + return signer.HomesteadSigner.Hash(tx) + } + + var hash []byte + + RLP := arenaPool.Get() + + // RLP(-, -, -, -, -, -, -, -, -) + hashPreimage := RLP.NewArray() + + // RLP(nonce, -, -, -, -, -, -, -, -) + hashPreimage.Set(RLP.NewUint(tx.Nonce())) + + // RLP(nonce, gasPrice, -, -, -, -, -, -, -) + hashPreimage.Set(RLP.NewBigInt(tx.GasPrice())) + + // RLP(nonce, gasPrice, gas, -, -, -, -, -, -) + hashPreimage.Set(RLP.NewUint(tx.Gas())) + + // Checking whether the transaction is a smart contract deployment + if tx.To() == nil { + + // RLP(nonce, gasPrice, gas, to, -, -, -, -, -) + hashPreimage.Set(RLP.NewNull()) + } else { + + // RLP(nonce, gasPrice, gas, to, -, -, -, -, -) + hashPreimage.Set(RLP.NewCopyBytes((*(tx.To())).Bytes())) + } + + // RLP(nonce, gasPrice, gas, to, value, -, -, -, -) + hashPreimage.Set(RLP.NewBigInt(tx.Value())) + + // RLP(nonce, gasPrice, gas, to, value, input, -, -, -) + hashPreimage.Set(RLP.NewCopyBytes(tx.Input())) + + // RLP(nonce, gasPrice, gas, to, value, input, chainId, -, -) + hashPreimage.Set(RLP.NewUint(signer.chainID)) + + // RLP(nonce, gasPrice, gas, to, value, input, chainId, 0, -) + hashPreimage.Set(RLP.NewUint(0)) + + // RLP(nonce, gasPrice, gas, to, value, input, chainId, 0, 0) + hashPreimage.Set(RLP.NewUint(0)) + + // keccak256(RLP(nonce, gasPrice, gas, to, value, input)) + hash = keccak.Keccak256Rlp(nil, hashPreimage) + + arenaPool.Put(RLP) + + return types.BytesToHash(hash) +} + +// Sender returns the sender of the transaction +func (signer *EIP155Signer) Sender(tx *types.Transaction) (types.Address, error) { + if tx.ChainID().Cmp(big.NewInt(0)) == 0 { + return signer.HomesteadSigner.Sender(tx) + } + + v, r, s := tx.RawSignatureValues() + + // Reverse the V calculation to find the parity of the Y coordinate + // v = CHAIN_ID * 2 + 35 + {0, 1} -> {0, 1} = v - 35 - CHAIN_ID * 2 + + a := big.NewInt(0) + b := big.NewInt(0) + parity := big.NewInt(0) + + // a = v - 35 + a.Sub(v, big35) + + // b = CHAIN_ID * 2 + b.Mul(big.NewInt(int64(signer.chainID)), big.NewInt(2)) + + // parity = a - b + parity.Sub(a, b) + + return recoverAddress(signer.Hash(tx), r, s, parity, true) +} + +// SingTx takes the original transaction as input and returns its signed version +func (signer *EIP155Signer) SignTx(tx *types.Transaction, privateKey *ecdsa.PrivateKey) (*types.Transaction, error) { + if tx.ChainID().Cmp(big.NewInt(0)) == 0 { + return signer.HomesteadSigner.SignTx(tx, privateKey) + } + + tx = tx.Copy() + + hash := signer.Hash(tx) + + signature, err := Sign(privateKey, hash[:]) + if err != nil { + return nil, err + } + + r := new(big.Int).SetBytes(signature[:32]) + s := new(big.Int).SetBytes(signature[32:64]) + + if s.Cmp(secp256k1NHalf) > 0 { + return nil, errors.New("SignTx method: S must be inclusively lower than secp256k1n/2") + } + + v := new(big.Int).SetBytes(signer.calculateV(signature[64])) + + tx.SetSignatureValues(v, r, s) + + return tx, nil +} + +// Private method calculateV returns the V value for the EIP-155 transactions +// +// V is calculated by the formula: {0, 1} + CHAIN_ID * 2 + 35 where {0, 1} denotes the parity of the Y coordinate +func (signer *EIP155Signer) calculateV(parity byte) []byte { + a := big.NewInt(0) + b := big.NewInt(0) + result := big.NewInt(0) + + // a = {0, 1} + 35 + a.Add(big.NewInt(int64(parity)), big35) + + // b = CHAIN_ID * 2 + b.Mul(big.NewInt(int64(signer.chainID)), big.NewInt(2)) + + // result = a + b + result.Add(a, b) + + return result.Bytes() +} diff --git a/crypto/txsignerFrontier.go b/crypto/txsignerFrontier.go new file mode 100644 index 0000000000..3010d99a11 --- /dev/null +++ b/crypto/txsignerFrontier.go @@ -0,0 +1,126 @@ +package crypto + +import ( + "crypto/ecdsa" + "errors" + "math/big" + + "github.com/0xPolygon/polygon-edge/helper/keccak" + "github.com/0xPolygon/polygon-edge/types" +) + +// FrontierSigner may be used for pre-EIP-155 transactions +type FrontierSigner struct { +} + +// NewFrontierSigner returns new FrontierSigner object (constructor) +// +// FrontierSigner accepts the following types of transactions: +// - pre-EIP-155 transactions +func NewFrontierSigner() *FrontierSigner { + return &FrontierSigner{} +} + +// Hash returns the keccak256 hash of the transaction +// +// The pre-EIP-155 transaction hash preimage is as follows: +// RLP(nonce, gasPrice, gas, to, value, input) +// +// Specification: https://eips.ethereum.org/EIPS/eip-155#specification +func (signer *FrontierSigner) Hash(tx *types.Transaction) types.Hash { + if tx.Type() != types.LegacyTx { + return types.BytesToHash(make([]byte, 0)) + } + + var hash []byte + + RLP := arenaPool.Get() + + // RLP(-, -, -, -, -, -) + hashPreimage := RLP.NewArray() + + // RLP(nonce, -, -, -, -, -) + hashPreimage.Set(RLP.NewUint(tx.Nonce())) + + // RLP(nonce, gasPrice, -, -, -, -) + hashPreimage.Set(RLP.NewBigInt(tx.GasPrice())) + + // RLP(nonce, gasPrice, gas, -, -, -) + hashPreimage.Set(RLP.NewUint(tx.Gas())) + + // Checking whether the transaction is a smart contract deployment + if tx.To() == nil { + + // RLP(nonce, gasPrice, gas, to, -, -) + hashPreimage.Set(RLP.NewNull()) + } else { + + // RLP(nonce, gasPrice, gas, to, -, -) + hashPreimage.Set(RLP.NewCopyBytes((*(tx.To())).Bytes())) + } + + // RLP(nonce, gasPrice, gas, to, value, -) + hashPreimage.Set(RLP.NewBigInt(tx.Value())) + + // RLP(nonce, gasPrice, gas, to, value, input) + hashPreimage.Set(RLP.NewCopyBytes(tx.Input())) + + // keccak256(RLP(nonce, gasPrice, gas, to, value, input)) + hash = keccak.Keccak256Rlp(nil, hashPreimage) + + arenaPool.Put(RLP) + + return types.BytesToHash(hash) +} + +// Sender returns the sender of the transaction +func (signer *FrontierSigner) Sender(tx *types.Transaction) (types.Address, error) { + if tx.Type() != types.LegacyTx { + return types.Address{}, errors.New("Sender method: Unknown transaction type") + } + + v, r, s := tx.RawSignatureValues() + + // Reverse the V calculation to find the parity of the Y coordinate + // v = {0, 1} + 27 -> {0, 1} = v - 27 + + parity := big.NewInt(0).Sub(v, big27) + + return recoverAddress(signer.Hash(tx), r, s, parity, false) +} + +// SingTx takes the original transaction as input and returns its signed version +func (signer *FrontierSigner) SignTx(tx *types.Transaction, privateKey *ecdsa.PrivateKey) (*types.Transaction, error) { + if tx.Type() != types.LegacyTx { + return nil, errors.New("SignTx method: Unknown transaction type") + } + + tx = tx.Copy() + + hash := signer.Hash(tx) + + signature, err := Sign(privateKey, hash[:]) + if err != nil { + return nil, err + } + + r := new(big.Int).SetBytes(signature[:32]) + s := new(big.Int).SetBytes(signature[32:64]) + v := new(big.Int).SetBytes(signer.calculateV(signature[64])) + + tx.SetSignatureValues(v, r, s) + + return tx, nil +} + +// Private method calculateV returns the V value for the pre-EIP-155 transactions +// +// V is calculated by the formula: {0, 1} + 27 where {0, 1} denotes the parity of the Y coordinate +func (signer *FrontierSigner) calculateV(parity byte) []byte { + result := big.NewInt(0) + + // result = {0, 1} + 27 + result.Add(big.NewInt(int64(parity)), big27) + + return result.Bytes() +} diff --git a/crypto/txsignerHomestead.go b/crypto/txsignerHomestead.go new file mode 100644 index 0000000000..9ae89b56d9 --- /dev/null +++ b/crypto/txsignerHomestead.go @@ -0,0 +1,97 @@ +package crypto + +import ( + "crypto/ecdsa" + "errors" + "math/big" + + "github.com/0xPolygon/polygon-edge/types" +) + +// HomesteadSigner may be used for signing pre-EIP155 transactions +type HomesteadSigner struct { + FrontierSigner +} + +// NewHomesteadSigner returns new FrontierSigner object (constructor) +// +// HomesteadSigner accepts the following types of transactions: +// - pre-EIP-155 transactions +func NewHomesteadSigner() *HomesteadSigner { + return &HomesteadSigner{ + FrontierSigner: FrontierSigner{}, + } +} + +// Hash returns the keccak256 hash of the transaction +// +// The pre-EIP-155 transaction hash preimage is as follows: +// RLP(nonce, gasPrice, gas, to, value, input) +// +// Specification: https://eips.ethereum.org/EIPS/eip-155#specification +// +// Note: Since the hash is calculated in the same way as with FrontierSigner, this is just a wrapper method +func (signer *HomesteadSigner) Hash(tx *types.Transaction) types.Hash { + return signer.FrontierSigner.Hash(tx) +} + +// Sender returns the sender of the transaction +func (signer *HomesteadSigner) Sender(tx *types.Transaction) (types.Address, error) { + if tx.Type() != types.LegacyTx { + return types.Address{}, errors.New("Sender method: Unknown transaction type") + } + + v, r, s := tx.RawSignatureValues() + + // Reverse the V calculation to find the parity of the Y coordinate + // v = {0, 1} + 27 -> {0, 1} = v - 27 + + parity := big.NewInt(0).Sub(v, big27) + + // The only difference compared to FrontierSinger.Sender() method is that the `isHomestead` flag is set to true + // `isHomestead` flag denotes that the S value must be inclusively lower than the half of the secp256k1 curve order + return recoverAddress(signer.Hash(tx), r, s, parity, true) +} + +// SingTx takes the original transaction as input and returns its signed version +func (signer *HomesteadSigner) SignTx(tx *types.Transaction, privateKey *ecdsa.PrivateKey) (*types.Transaction, error) { + if tx.Type() != types.LegacyTx { + return nil, errors.New("SignTx method: Unknown transaction type") + } + + tx = tx.Copy() + + hash := signer.Hash(tx) + + signature, err := Sign(privateKey, hash[:]) + if err != nil { + return nil, err + } + + r := new(big.Int).SetBytes(signature[:32]) + s := new(big.Int).SetBytes(signature[32:64]) + + // Homestead hard-fork introduced the rule that the S value must be inclusively lower than the half of the secp256k1 curve order + // Specification: https://eips.ethereum.org/EIPS/eip-2#specification (2) + if s.Cmp(secp256k1NHalf) > 0 { + return nil, errors.New("SignTx method: S must be inclusively lower than secp256k1n/2") + } + + v := new(big.Int).SetBytes(signer.calculateV(signature[64])) + + tx.SetSignatureValues(v, r, s) + + return tx, nil +} + +// Private method calculateV returns the V value for the pre-EIP-155 transactions +// +// V is calculated by the formula: {0, 1} + 27 where {0, 1} denotes the parity of the Y coordinate +func (signer *HomesteadSigner) calculateV(parity byte) []byte { + result := big.NewInt(0) + + // result = {0, 1} + 27 + result.Add(big.NewInt(int64(parity)), big27) + + return result.Bytes() +} diff --git a/crypto/txsignerLondon.go b/crypto/txsignerLondon.go new file mode 100644 index 0000000000..6775551313 --- /dev/null +++ b/crypto/txsignerLondon.go @@ -0,0 +1,163 @@ +package crypto + +import ( + "crypto/ecdsa" + "errors" + "math/big" + + "github.com/0xPolygon/polygon-edge/helper/keccak" + "github.com/0xPolygon/polygon-edge/types" +) + +// LondonSigner may be used for signing legacy (pre-EIP-155 and EIP-155), EIP-2930 and EIP-1559 transactions +type LondonSigner struct { + BerlinSigner +} + +// NewLondonSigner returns new LondonSinger object (constructor) +// +// LondonSigner accepts the following types of transactions: +// - EIP-1559 dynamic fee transactions +// - EIP-2930 access list transactions, +// - EIP-155 replay protected transactions, and +// - pre-EIP-155 legacy transactions +func NewLondonSigner(chainID uint64) *LondonSigner { + return &LondonSigner{ + BerlinSigner: BerlinSigner{ + EIP155Signer: EIP155Signer{ + chainID: chainID, + HomesteadSigner: HomesteadSigner{}, + }, + }, + } +} + +// Hash returns the keccak256 hash of the transaction +// +// The EIP-1559 transaction hash preimage is as follows: +// (0x02 || RLP(chainId, nonce, gasTipCap, gasFeeCap, gas, to, value, input, accessList) +// +// Specification: https://eips.ethereum.org/EIPS/eip-1559#specification +func (signer *LondonSigner) Hash(tx *types.Transaction) types.Hash { + if tx.Type() != types.DynamicFeeTx { + return signer.BerlinSigner.Hash(tx) + } + + var hash []byte + + RLP := arenaPool.Get() + + // RLP(-, -, -, -, -, -, -, -, -) + hashPreimage := RLP.NewArray() + + // RLP(chainId, -, -, -, -, -, -, -, -) + hashPreimage.Set(RLP.NewUint(signer.chainID)) + + // RLP(chainId, nonce, -, -, -, -, -, -, -) + hashPreimage.Set(RLP.NewUint(tx.Nonce())) + + // RLP(chainId, nonce, gasTipCap, -, -, -, -, -, -) + hashPreimage.Set(RLP.NewBigInt(tx.GasTipCap())) + + // RLP(chainId, nonce, gasTipCap, gasFeeCap, -, -, -, -, -) + hashPreimage.Set(RLP.NewBigInt(tx.GasFeeCap())) + + // RLP(chainId, nonce, gasTipCap, gasFeeCap, gas, -, -, -, -) + hashPreimage.Set(RLP.NewUint(tx.Gas())) + + // Checking whether the transaction is a smart contract deployment + if tx.To() == nil { + + // RLP(chainId, nonce, gasTipCap, gasFeeCap, gas, to, -, -, -) + hashPreimage.Set(RLP.NewNull()) + } else { + + // RLP(chainId, nonce, gasTipCap, gasFeeCap, gas, to, -, -, -) + hashPreimage.Set(RLP.NewCopyBytes((*(tx.To())).Bytes())) + } + + // RLP(chainId, nonce, gasTipCap, gasFeeCap, gas, to, value, -, -) + hashPreimage.Set(RLP.NewBigInt(tx.Value())) + + // RLP(chainId, nonce, gasTipCap, gasFeeCap, gas, to, value, input, -) + hashPreimage.Set(RLP.NewCopyBytes(tx.Input())) + + // Serialization format of the access list: [[{20-bytes address}, [{32-bytes key}, ...]], ...] where `...` denotes zero or more items + accessList := RLP.NewArray() + + if tx.AccessList() != nil { + + // accessTuple contains (address, storageKeys[]) + for _, accessTuple := range tx.AccessList() { + + accessTupleSerFormat := RLP.NewArray() + accessTupleSerFormat.Set(RLP.NewCopyBytes(accessTuple.Address.Bytes())) + + storageKeysSerFormat := RLP.NewArray() + + for _, storageKey := range accessTuple.StorageKeys { + storageKeysSerFormat.Set(RLP.NewCopyBytes(storageKey.Bytes())) + } + + accessTupleSerFormat.Set(storageKeysSerFormat) + accessList.Set(accessTupleSerFormat) + } + } + + // RLP(chainId, nonce, gasTipCap, gasFeeCap, gas, to, value, input,accessList) + hashPreimage.Set(accessList) + + // keccak256(0x02 || RLP(chainId, nonce, gasTipCap, gasFeeCap, gas, to, value, input,accessList) + hash = keccak.PrefixedKeccak256Rlp([]byte{byte(tx.Type())}, nil, hashPreimage) + + arenaPool.Put(RLP) + + return types.BytesToHash(hash) +} + +// Sender returns the sender of the transaction +func (signer *LondonSigner) Sender(tx *types.Transaction) (types.Address, error) { + if tx.Type() != types.DynamicFeeTx { + return signer.BerlinSigner.Sender(tx) + } + + v, r, s := tx.RawSignatureValues() + + return recoverAddress(signer.Hash(tx), r, s, v, true) +} + +// SingTx takes the original transaction as input and returns its signed version +func (signer *LondonSigner) SignTx(tx *types.Transaction, privateKey *ecdsa.PrivateKey) (*types.Transaction, error) { + if tx.Type() != types.DynamicFeeTx { + return signer.BerlinSigner.SignTx(tx, privateKey) + } + + tx = tx.Copy() + + h := signer.Hash(tx) + + sig, err := Sign(privateKey, h[:]) + if err != nil { + return nil, err + } + + r := new(big.Int).SetBytes(sig[:32]) + s := new(big.Int).SetBytes(sig[32:64]) + + if s.Cmp(secp256k1NHalf) > 0 { + return nil, errors.New("SignTx method: S must be inclusively lower than secp256k1n/2") + } + + v := new(big.Int).SetBytes(signer.calculateV(sig[64])) + + tx.SetSignatureValues(v, r, s) + + return tx, nil +} + +// Private method calculateV returns the V value for the EIP-1559 transactions +// +// V represents the parity of the Y coordinate +func (e *LondonSigner) calculateV(parity byte) []byte { + return big.NewInt(int64(parity)).Bytes() +} diff --git a/crypto/txsignerState.go b/crypto/txsignerState.go new file mode 100644 index 0000000000..b35262f7c1 --- /dev/null +++ b/crypto/txsignerState.go @@ -0,0 +1,126 @@ +package crypto + +import ( + "crypto/ecdsa" + "errors" + "math/big" + + "github.com/0xPolygon/polygon-edge/helper/keccak" + "github.com/0xPolygon/polygon-edge/types" +) + +// StateSigner may be used for state transactions +type StateSigner struct { +} + +// NewStateSigner returns new StateSigner object (constructor) +// +// FrontierSigner accepts the following types of transactions: +// - state transactions +func NewStateSigner() *StateSigner { + return &StateSigner{} +} + +// Hash returns the keccak256 hash of the transaction +// +// The state transaction hash preimage is as follows: +// RLP(nonce, gasPrice, gas, to, value, input) +// +// Specification: - +func (signer *StateSigner) Hash(tx *types.Transaction) types.Hash { + if tx.Type() != types.StateTx { + return types.BytesToHash(make([]byte, 0)) + } + + var hash []byte + + RLP := arenaPool.Get() + + // RLP(-, -, -, -, -, -) + hashPreimage := RLP.NewArray() + + // RLP(nonce, -, -, -, -, -) + hashPreimage.Set(RLP.NewUint(tx.Nonce())) + + // RLP(nonce, gasPrice, -, -, -, -) + hashPreimage.Set(RLP.NewBigInt(tx.GasPrice())) + + // RLP(nonce, gasPrice, gas, -, -, -) + hashPreimage.Set(RLP.NewUint(tx.Gas())) + + // Checking whether the transaction is a smart contract deployment + if tx.To() == nil { + + // RLP(nonce, gasPrice, gas, to, -, -) + hashPreimage.Set(RLP.NewNull()) + } else { + + // RLP(nonce, gasPrice, gas, to, -, -) + hashPreimage.Set(RLP.NewCopyBytes((*(tx.To())).Bytes())) + } + + // RLP(nonce, gasPrice, gas, to, value, -) + hashPreimage.Set(RLP.NewBigInt(tx.Value())) + + // RLP(nonce, gasPrice, gas, to, value, input) + hashPreimage.Set(RLP.NewCopyBytes(tx.Input())) + + // keccak256(RLP(nonce, gasPrice, gas, to, value, input)) + hash = keccak.Keccak256Rlp(nil, hashPreimage) + + arenaPool.Put(RLP) + + return types.BytesToHash(hash) +} + +// Sender returns the sender of the transaction +func (signer *StateSigner) Sender(tx *types.Transaction) (types.Address, error) { + if tx.Type() != types.StateTx { + return types.Address{}, errors.New("Sender method: Unknown transaction type") + } + + v, r, s := tx.RawSignatureValues() + + // Reverse the V calculation to find the parity of the Y coordinate + // v = {0, 1} + 27 -> {0, 1} = v - 27 + + parity := big.NewInt(0).Sub(v, big27) + + return recoverAddress(signer.Hash(tx), r, s, parity, false) +} + +// SingTx takes the original transaction as input and returns its signed version +func (signer *StateSigner) SignTx(tx *types.Transaction, privateKey *ecdsa.PrivateKey) (*types.Transaction, error) { + if tx.Type() != types.StateTx { + return nil, errors.New("SignTx method: Unknown transaction type") + } + + tx = tx.Copy() + + hash := signer.Hash(tx) + + signature, err := Sign(privateKey, hash[:]) + if err != nil { + return nil, err + } + + r := new(big.Int).SetBytes(signature[:32]) + s := new(big.Int).SetBytes(signature[32:64]) + v := new(big.Int).SetBytes(signer.calculateV(signature[64])) + + tx.SetSignatureValues(v, r, s) + + return tx, nil +} + +// Private method calculateV returns the V value for the pre-EIP-155 transactions +// +// V is calculated by the formula: {0, 1} + 27 where {0, 1} denotes the parity of the Y coordinate +func (signer *StateSigner) calculateV(parity byte) []byte { + result := big.NewInt(0) + + // result = {0, 1} + 27 + result.Add(big.NewInt(int64(parity)), big27) + + return result.Bytes() +} diff --git a/crypto/txsigner_eip155.go b/crypto/txsigner_eip155.go deleted file mode 100644 index 5e330cb977..0000000000 --- a/crypto/txsigner_eip155.go +++ /dev/null @@ -1,91 +0,0 @@ -package crypto - -import ( - "crypto/ecdsa" - "math/big" - "math/bits" - - "github.com/0xPolygon/polygon-edge/types" -) - -type EIP155Signer struct { - chainID uint64 - isHomestead bool -} - -// NewEIP155Signer returns a new EIP155Signer object -func NewEIP155Signer(chainID uint64, isHomestead bool) *EIP155Signer { - return &EIP155Signer{ - chainID: chainID, - isHomestead: isHomestead, - } -} - -// Hash is a wrapper function that calls calcTxHash with the EIP155Signer's chainID -func (e *EIP155Signer) Hash(tx *types.Transaction) types.Hash { - return calcTxHash(tx, e.chainID) -} - -// Sender returns the transaction sender -func (e *EIP155Signer) Sender(tx *types.Transaction) (types.Address, error) { - protected := true - - // Check if v value conforms to an earlier standard (before EIP155) - bigV := big.NewInt(0) - - v, r, s := tx.RawSignatureValues() - if v != nil { - bigV.SetBytes(v.Bytes()) - } - - if vv := bigV.Uint64(); bits.Len(uint(vv)) <= 8 { - protected = vv != 27 && vv != 28 - } - - if !protected { - return (&FrontierSigner{}).Sender(tx) - } - - // Reverse the V calculation to find the original V in the range [0, 1] - // v = CHAIN_ID * 2 + 35 + {0, 1} - mulOperand := big.NewInt(0).Mul(big.NewInt(int64(e.chainID)), big.NewInt(2)) - bigV.Sub(bigV, mulOperand) - bigV.Sub(bigV, big35) - - return recoverAddress(e.Hash(tx), r, s, bigV, e.isHomestead) -} - -// SignTx signs the transaction using the passed in private key -func (e *EIP155Signer) SignTx( - tx *types.Transaction, - privateKey *ecdsa.PrivateKey, -) (*types.Transaction, error) { - tx = tx.Copy() - - h := e.Hash(tx) - - sig, err := Sign(privateKey, h[:]) - if err != nil { - return nil, err - } - - r := new(big.Int).SetBytes(sig[:32]) - s := new(big.Int).SetBytes(sig[32:64]) - v := new(big.Int).SetBytes(e.calculateV(sig[64])) - - tx.SetSignatureValues(v, r, s) - - return tx, nil -} - -// calculateV returns the V value for transaction signatures. Based on EIP155 -func (e *EIP155Signer) calculateV(parity byte) []byte { - reference := big.NewInt(int64(parity)) - reference.Add(reference, big35) - - mulOperand := big.NewInt(0).Mul(big.NewInt(int64(e.chainID)), big.NewInt(2)) - - reference.Add(reference, mulOperand) - - return reference.Bytes() -} diff --git a/crypto/txsigner_eip155_test.go b/crypto/txsigner_eip155_test.go index 86769d6c7d..277c73d2a0 100644 --- a/crypto/txsigner_eip155_test.go +++ b/crypto/txsigner_eip155_test.go @@ -74,11 +74,12 @@ func TestEIP155Signer_Sender(t *testing.T) { To: &toAddress, Value: big.NewInt(1), GasPrice: big.NewInt(0), + ChainID: testCase.chainID, }) signer := NewEIP155Signer( testCase.chainID.Uint64(), - testCase.isHomestead, + //testCase.isHomestead, ) signedTx, signErr := signer.SignTx(txn, key) @@ -110,9 +111,11 @@ func TestEIP155Signer_ChainIDMismatch(t *testing.T) { To: &toAddress, Value: big.NewInt(1), GasPrice: big.NewInt(0), + ChainID: big.NewInt(int64(chainIDTop)), }) - signer := NewEIP155Signer(chainIDTop, true) + //signer := NewEIP155Signer(chainIDTop, true) + signer := NewEIP155Signer(chainIDTop) signedTx, signErr := signer.SignTx(txn, key) if signErr != nil { @@ -120,7 +123,8 @@ func TestEIP155Signer_ChainIDMismatch(t *testing.T) { } for _, chainIDBottom := range chainIDS { - signerBottom := NewEIP155Signer(chainIDBottom, true) + //signerBottom := NewEIP155Signer(chainIDBottom, true) + signerBottom := NewEIP155Signer(chainIDBottom) recoveredSender, recoverErr := signerBottom.Sender(signedTx) if chainIDTop == chainIDBottom { diff --git a/crypto/txsigner_frontier.go b/crypto/txsigner_frontier.go deleted file mode 100644 index 5365e54562..0000000000 --- a/crypto/txsigner_frontier.go +++ /dev/null @@ -1,74 +0,0 @@ -package crypto - -import ( - "crypto/ecdsa" - "math/big" - - "github.com/umbracle/fastrlp" - - "github.com/0xPolygon/polygon-edge/types" -) - -var signerPool fastrlp.ArenaPool - -// FrontierSigner implements tx signer interface -type FrontierSigner struct { - isHomestead bool -} - -// NewFrontierSigner is the constructor of FrontierSigner -func NewFrontierSigner(isHomestead bool) *FrontierSigner { - return &FrontierSigner{ - isHomestead: isHomestead, - } -} - -// Hash is a wrapper function for the calcTxHash, with chainID 0 -func (f *FrontierSigner) Hash(tx *types.Transaction) types.Hash { - return calcTxHash(tx, 0) -} - -// Sender decodes the signature and returns the sender of the transaction -func (f *FrontierSigner) Sender(tx *types.Transaction) (types.Address, error) { - refV := big.NewInt(0) - - v, r, s := tx.RawSignatureValues() - if v != nil { - refV.SetBytes(v.Bytes()) - } - - refV.Sub(refV, big27) - - return recoverAddress(f.Hash(tx), r, s, refV, f.isHomestead) -} - -// SignTx signs the transaction using the passed in private key -func (f *FrontierSigner) SignTx( - tx *types.Transaction, - privateKey *ecdsa.PrivateKey, -) (*types.Transaction, error) { - tx = tx.Copy() - - h := f.Hash(tx) - - sig, err := Sign(privateKey, h[:]) - if err != nil { - return nil, err - } - - r := new(big.Int).SetBytes(sig[:32]) - s := new(big.Int).SetBytes(sig[32:64]) - v := new(big.Int).SetBytes(f.calculateV(sig[64])) - - tx.SetSignatureValues(v, r, s) - - return tx, nil -} - -// calculateV returns the V value for transactions pre EIP155 -func (f *FrontierSigner) calculateV(parity byte) []byte { - reference := big.NewInt(int64(parity)) - reference.Add(reference, big27) - - return reference.Bytes() -} diff --git a/crypto/txsigner_london_berlin.go b/crypto/txsigner_london_berlin.go deleted file mode 100644 index 29f9d21e70..0000000000 --- a/crypto/txsigner_london_berlin.go +++ /dev/null @@ -1,72 +0,0 @@ -package crypto - -import ( - "crypto/ecdsa" - "math/big" - - "github.com/0xPolygon/polygon-edge/types" -) - -// LondonOrBerlinSigner implements signer for london and berlin hard forks -type LondonOrBerlinSigner struct { - chainID uint64 - isHomestead bool - fallbackSigner TxSigner -} - -// NewLondonOrBerlinSigner returns new LondonOrBerlinSigner object that accepts -// - EIP-1559 dynamic fee transactions -// - EIP-2930 access list transactions, -// - EIP-155 replay protected transactions, and -// - legacy Homestead transactions. -func NewLondonOrBerlinSigner(chainID uint64, isHomestead bool, fallbackSigner TxSigner) *LondonOrBerlinSigner { - return &LondonOrBerlinSigner{ - chainID: chainID, - isHomestead: isHomestead, - fallbackSigner: fallbackSigner, - } -} - -// Hash is a wrapper function that calls calcTxHash with the LondonSigner's fields -func (e *LondonOrBerlinSigner) Hash(tx *types.Transaction) types.Hash { - return calcTxHash(tx, e.chainID) -} - -// Sender returns the transaction sender -func (e *LondonOrBerlinSigner) Sender(tx *types.Transaction) (types.Address, error) { - if tx.Type() != types.DynamicFeeTx && tx.Type() != types.AccessListTx { - return e.fallbackSigner.Sender(tx) - } - - v, r, s := tx.RawSignatureValues() - - return recoverAddress(e.Hash(tx), r, s, v, e.isHomestead) -} - -// SignTx signs the transaction using the passed in private key -func (e *LondonOrBerlinSigner) SignTx(tx *types.Transaction, pk *ecdsa.PrivateKey) (*types.Transaction, error) { - if tx.Type() != types.DynamicFeeTx && tx.Type() != types.AccessListTx { - return e.fallbackSigner.SignTx(tx, pk) - } - - tx = tx.Copy() - - h := e.Hash(tx) - - sig, err := Sign(pk, h[:]) - if err != nil { - return nil, err - } - - r := new(big.Int).SetBytes(sig[:32]) - s := new(big.Int).SetBytes(sig[32:64]) - v := new(big.Int).SetBytes(e.calculateV(sig[64])) - tx.SetSignatureValues(v, r, s) - - return tx, nil -} - -// calculateV returns the V value for transaction signatures. Based on EIP155 -func (e *LondonOrBerlinSigner) calculateV(parity byte) []byte { - return big.NewInt(int64(parity)).Bytes() -} diff --git a/crypto/txsigner_london_berlin_test.go b/crypto/txsigner_london_test.go similarity index 95% rename from crypto/txsigner_london_berlin_test.go rename to crypto/txsigner_london_test.go index a8ff06e695..6059a01509 100644 --- a/crypto/txsigner_london_berlin_test.go +++ b/crypto/txsigner_london_test.go @@ -77,17 +77,19 @@ func TestLondonSignerSender(t *testing.T) { To: &recipient, Value: big.NewInt(1), GasPrice: big.NewInt(5), + ChainID: tc.chainID, }) case types.DynamicFeeTx, types.LegacyTx, types.StateTx: txn = types.NewTx(&types.MixedTxn{ To: &recipient, Value: big.NewInt(1), GasPrice: big.NewInt(5), + ChainID: tc.chainID, }) } chainID := tc.chainID.Uint64() - signer := NewLondonOrBerlinSigner(chainID, true, NewEIP155Signer(chainID, true)) + signer := NewLondonSigner(chainID) signedTx, err := signer.SignTx(txn, key) require.NoError(t, err, "unable to sign transaction") @@ -103,7 +105,8 @@ func TestLondonSignerSender(t *testing.T) { func Test_LondonSigner_Sender(t *testing.T) { t.Parallel() - signer := NewLondonOrBerlinSigner(100, true, NewEIP155Signer(100, true)) + signer := NewLondonSigner(100) + to := types.StringToAddress("0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF") r, ok := big.NewInt(0).SetString("102623819621514684481463796449525884981685455700611671612296611353030973716382", 10) diff --git a/go.mod b/go.mod index 14b6bb6fef..2630c14010 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/0xPolygon/polygon-edge -go 1.20 +go 1.21 + +toolchain go1.22.0 require ( cloud.google.com/go/secretmanager v1.11.5 diff --git a/go.sum b/go.sum index 043422033a..598f8a21af 100644 --- a/go.sum +++ b/go.sum @@ -128,6 +128,7 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= @@ -171,6 +172,7 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -190,6 +192,7 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78 github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= +github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-toolsmith/astcopy v1.0.2 h1:YnWf5Rnh1hUudj11kei53kI57quN/VH6Hp1n+erozn0= github.com/go-toolsmith/astcopy v1.0.2/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= @@ -241,6 +244,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -270,6 +274,7 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.5.0 h1:WcmKMm43DR7RdtlkEXQJyo5ws8iTp98CyhCCbOHMvNI= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= @@ -361,11 +366,14 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= @@ -381,6 +389,7 @@ github.com/libp2p/go-libp2p-kbucket v0.6.3/go.mod h1:RCseT7AH6eJWxxk2ol03xtP9pEH github.com/libp2p/go-libp2p-pubsub v0.10.0 h1:wS0S5FlISavMaAbxyQn3dxMOe2eegMfswM471RuHJwA= github.com/libp2p/go-libp2p-pubsub v0.10.0/go.mod h1:1OxbaT/pFRO5h+Dpze8hdHQ63R0ke55XTs6b6NwLLkw= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= @@ -489,6 +498,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= @@ -564,6 +574,7 @@ github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Id github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052/go.mod h1:uvX/8buq8uVeiZiFht+0lqSLBHF+uGV8BrTv8W/SIwk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -693,6 +704,7 @@ go.uber.org/fx v1.20.1 h1:zVwVQGS8zYvhh9Xxcu4w1M6ESyeMzebzj2NbSayZ4Mk= go.uber.org/fx v1.20.1/go.mod h1:iSYNbHf2y55acNCwCXKx7LbWb5WG1Bnue5RDXz1OREg= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= diff --git a/helper/common/common.go b/helper/common/common.go index 3ba8ffe337..257c86f9d3 100644 --- a/helper/common/common.go +++ b/helper/common/common.go @@ -11,9 +11,7 @@ import ( "math/big" "os" "os/signal" - "os/user" "path/filepath" - "strconv" "syscall" "time" @@ -204,34 +202,34 @@ func SaveFileSafe(path string, data []byte, perms fs.FileMode) error { // or the file owner is in the same group as current user // and permissions are set correctly by the owner. func verifyFileOwnerAndPermissions(path string, info fs.FileInfo, expectedPerms fs.FileMode) error { - // get stats - stat, ok := info.Sys().(*syscall.Stat_t) - if stat == nil || !ok { - return fmt.Errorf("failed to get stats of %s", path) - } - - // get current user - currUser, err := user.Current() - if err != nil { - return fmt.Errorf("failed to get current user") - } - - // get user id of the owner - ownerUID := strconv.FormatUint(uint64(stat.Uid), 10) - if currUser.Uid == ownerUID { - return nil - } - - // get group id of the owner - ownerGID := strconv.FormatUint(uint64(stat.Gid), 10) - if currUser.Gid != ownerGID { - return fmt.Errorf("file/directory created by a user from a different group: %s", path) - } - - // check if permissions are set correctly by the owner - if info.Mode() != expectedPerms { - return fmt.Errorf("permissions of the file/directory '%s' are set incorrectly by another user", path) - } + // // get stats + // stat, ok := info.Sys().(*syscall.Stat_t) + // if stat == nil || !ok { + // return fmt.Errorf("failed to get stats of %s", path) + // } + + // // get current user + // currUser, err := user.Current() + // if err != nil { + // return fmt.Errorf("failed to get current user") + // } + + // // get user id of the owner + // ownerUID := strconv.FormatUint(uint64(stat.Uid), 10) + // if currUser.Uid == ownerUID { + // return nil + // } + + // // get group id of the owner + // ownerGID := strconv.FormatUint(uint64(stat.Gid), 10) + // if currUser.Gid != ownerGID { + // return fmt.Errorf("file/directory created by a user from a different group: %s", path) + // } + + // // check if permissions are set correctly by the owner + // if info.Mode() != expectedPerms { + // return fmt.Errorf("permissions of the file/directory '%s' are set incorrectly by another user", path) + // } return nil } diff --git a/helper/tests/testing.go b/helper/tests/testing.go index e7ceb0c8a5..3e6b6ce4ba 100644 --- a/helper/tests/testing.go +++ b/helper/tests/testing.go @@ -236,7 +236,7 @@ type GenerateTxReqParams struct { } func generateTx(params GenerateTxReqParams) (*types.Transaction, error) { - signer := crypto.NewEIP155Signer(100, true) + signer := crypto.NewEIP155Signer(100) signedTx, signErr := signer.SignTx(types.NewTx(&types.MixedTxn{ Nonce: params.Nonce, diff --git a/server/server.go b/server/server.go index fec97b79fd..3af3dd6306 100644 --- a/server/server.go +++ b/server/server.go @@ -282,15 +282,7 @@ func NewServer(config *Config) (*Server, error) { // compute the genesis root state config.Chain.Genesis.StateRoot = genesisRoot - // Use the london signer with eip-155 as a fallback one - var signer crypto.TxSigner = crypto.NewLondonOrBerlinSigner( - uint64(m.config.Chain.Params.ChainID), - config.Chain.Params.Forks.IsActive(chain.Homestead, 0), - crypto.NewEIP155Signer( - uint64(m.config.Chain.Params.ChainID), - config.Chain.Params.Forks.IsActive(chain.Homestead, 0), - ), - ) + var signer crypto.TxSigner = crypto.NewSigner(config.Chain.Params.Forks.At(0), uint64(m.config.Chain.Params.ChainID)) // create storage instance for blockchain var db storage.Storage diff --git a/txpool/txpool_test.go b/txpool/txpool_test.go index 4e1ae0e369..ccf4da8c71 100644 --- a/txpool/txpool_test.go +++ b/txpool/txpool_test.go @@ -111,7 +111,7 @@ type result struct { func TestAddTxErrors(t *testing.T) { t.Parallel() - poolSigner := crypto.NewEIP155Signer(100, true) + poolSigner := crypto.NewEIP155Signer(100) // Generate a private key and address defaultKey, defaultAddr := tests.GenerateKeyAndAddr(t) @@ -581,7 +581,7 @@ func TestAddGossipTx(t *testing.T) { t.Parallel() key, sender := tests.GenerateKeyAndAddr(t) - signer := crypto.NewEIP155Signer(100, true) + signer := crypto.NewEIP155Signer(100) tx := newTx(types.ZeroAddress, 1, 1) t.Run("node is a validator", func(t *testing.T) { @@ -2132,7 +2132,7 @@ func Test_updateAccountSkipsCounts(t *testing.T) { func Test_TxPool_validateTx(t *testing.T) { t.Parallel() - signer := crypto.NewEIP155Signer(100, true) + signer := crypto.NewEIP155Signer(100) // Generate a private key and address defaultKey, defaultAddr := tests.GenerateKeyAndAddr(t) @@ -2377,7 +2377,7 @@ func (e *eoa) signTx(t *testing.T, tx *types.Transaction, signer crypto.TxSigner return signedTx } -var signerEIP155 = crypto.NewEIP155Signer(100, true) +var signerEIP155 = crypto.NewEIP155Signer(100) func TestResetAccounts_Promoted(t *testing.T) { t.Parallel() @@ -3531,7 +3531,7 @@ func TestAddTxsInOrder(t *testing.T) { pool, err := newTestPool() require.NoError(t, err) - signer := crypto.NewEIP155Signer(100, true) + signer := crypto.NewEIP155Signer(100) pool.SetSigner(signer) pool.Start() @@ -3634,7 +3634,7 @@ func TestAddTx_TxReplacement(t *testing.T) { secondAccountNonce = 2 ) - poolSigner := crypto.NewEIP155Signer(100, true) + poolSigner := crypto.NewEIP155Signer(100) firstKey, firstKeyAddr := tests.GenerateKeyAndAddr(t) secondKey, secondKeyAddr := tests.GenerateKeyAndAddr(t) @@ -3748,7 +3748,7 @@ func getDefaultEnabledForks() *chain.Forks { func BenchmarkAddTxTime(b *testing.B) { b.Run("benchmark add one tx", func(b *testing.B) { - signer := crypto.NewEIP155Signer(100, true) + signer := crypto.NewEIP155Signer(100) key, err := crypto.GenerateECDSAKey() if err != nil { @@ -3776,7 +3776,7 @@ func BenchmarkAddTxTime(b *testing.B) { }) b.Run("benchmark fill account", func(b *testing.B) { - signer := crypto.NewEIP155Signer(100, true) + signer := crypto.NewEIP155Signer(100) key, err := crypto.GenerateECDSAKey() if err != nil {