From a2f3444bbcf0d2599893b44f8ae674d732683ac9 Mon Sep 17 00:00:00 2001 From: Vinod Damle Date: Wed, 10 Aug 2022 18:08:03 -0400 Subject: [PATCH 1/2] Add Signer interface to support multiple Signers In addition to the existing secp256k1 local signer, we can allow any provider/api that has signature generation capability to implement the Signer interface and use firefly-signer's transaction signing Signed-off-by: Vinod Damle --- pkg/ethsigner/transaction.go | 8 ++++---- pkg/secp256k1/keypair.go | 2 +- pkg/secp256k1/signer.go | 5 +++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pkg/ethsigner/transaction.go b/pkg/ethsigner/transaction.go index eee6e7f..b6dbd02 100644 --- a/pkg/ethsigner/transaction.go +++ b/pkg/ethsigner/transaction.go @@ -96,7 +96,7 @@ func (t *Transaction) Build1559(chainID int64) rlp.List { // - If either of the new EIP-1559 fields are set, use EIP-1559 // - By default use EIP-155 signing // Never picks legacy-legacy (non EIP-155), or EIP-2930 -func (t *Transaction) Sign(signer *secp256k1.KeyPair, chainID int64) ([]byte, error) { +func (t *Transaction) Sign(signer secp256k1.Signer, chainID int64) ([]byte, error) { if t.MaxPriorityFeePerGas.BigInt().Sign() > 0 || t.MaxFeePerGas.BigInt().Sign() > 0 { return t.SignEIP1559(signer, chainID) } @@ -124,7 +124,7 @@ func (t *Transaction) SignaturePayloadLegacyOriginal() *TransactionSignaturePayl } // SignLegacyOriginal uses legacy transaction structure, with legacy V value (27/28) -func (t *Transaction) SignLegacyOriginal(signer *secp256k1.KeyPair) ([]byte, error) { +func (t *Transaction) SignLegacyOriginal(signer secp256k1.Signer) ([]byte, error) { signatureData := t.SignaturePayloadLegacyOriginal() sig, err := signer.Sign(signatureData.data) if err != nil { @@ -148,7 +148,7 @@ func (t *Transaction) SignaturePayloadLegacyEIP155(chainID int64) *TransactionSi } // SignLegacyEIP155 uses legacy transaction structure, with EIP-155 signing V value (2*ChainID + 35 + Y-parity) -func (t *Transaction) SignLegacyEIP155(signer *secp256k1.KeyPair, chainID int64) ([]byte, error) { +func (t *Transaction) SignLegacyEIP155(signer secp256k1.Signer, chainID int64) ([]byte, error) { signaturePayload := t.SignaturePayloadLegacyEIP155(chainID) @@ -178,7 +178,7 @@ func (t *Transaction) SignaturePayloadEIP1559(chainID int64) *TransactionSignatu } // SignEIP1559 uses EIP-1559 transaction structure (with EIP-2718 transaction type byte), with EIP-2930 V value (0 / 1 - direct parity-Y) -func (t *Transaction) SignEIP1559(signer *secp256k1.KeyPair, chainID int64) ([]byte, error) { +func (t *Transaction) SignEIP1559(signer secp256k1.Signer, chainID int64) ([]byte, error) { signaturePayload := t.SignaturePayloadEIP1559(chainID) sig, err := signer.Sign(signaturePayload.data) diff --git a/pkg/secp256k1/keypair.go b/pkg/secp256k1/keypair.go index 8839038..2099ed5 100644 --- a/pkg/secp256k1/keypair.go +++ b/pkg/secp256k1/keypair.go @@ -35,7 +35,7 @@ func (k *KeyPair) PrivateKeyBytes() []byte { } func (k *KeyPair) PublicKeyBytes() []byte { - // Remove the "04" Suffix byte when computing the address. This byte indicates that it is an uncompressed public key. + // Remove the "04" Prefix byte when computing the address. This byte indicates that it is an uncompressed public key. return k.PublicKey.SerializeUncompressed()[1:] } diff --git a/pkg/secp256k1/signer.go b/pkg/secp256k1/signer.go index 1d93602..998560e 100644 --- a/pkg/secp256k1/signer.go +++ b/pkg/secp256k1/signer.go @@ -31,6 +31,11 @@ type SignatureData struct { S *big.Int } +// Signer is the low level common interface that can be implemented by any module which provides signature capability +type Signer interface { + Sign(message []byte) (*SignatureData, error) +} + // getVNormalized returns the original 27/28 parity func (s *SignatureData) getVNormalized(chainID int64) (byte, error) { v := s.V.Int64() From c996220c00961dcc7ac51609fd1d9be6a6fc203e Mon Sep 17 00:00:00 2001 From: Vinod Damle Date: Wed, 10 Aug 2022 18:25:17 -0400 Subject: [PATCH 2/2] Check for invalid signer Signed-off-by: Vinod Damle --- pkg/ethsigner/transaction.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkg/ethsigner/transaction.go b/pkg/ethsigner/transaction.go index b6dbd02..8394033 100644 --- a/pkg/ethsigner/transaction.go +++ b/pkg/ethsigner/transaction.go @@ -18,6 +18,7 @@ package ethsigner import ( "encoding/json" + "fmt" "math/big" "github.com/hyperledger/firefly-signer/pkg/ethtypes" @@ -97,6 +98,9 @@ func (t *Transaction) Build1559(chainID int64) rlp.List { // - By default use EIP-155 signing // Never picks legacy-legacy (non EIP-155), or EIP-2930 func (t *Transaction) Sign(signer secp256k1.Signer, chainID int64) ([]byte, error) { + if signer == nil { + return nil, fmt.Errorf("invalid signer") + } if t.MaxPriorityFeePerGas.BigInt().Sign() > 0 || t.MaxFeePerGas.BigInt().Sign() > 0 { return t.SignEIP1559(signer, chainID) } @@ -125,6 +129,9 @@ func (t *Transaction) SignaturePayloadLegacyOriginal() *TransactionSignaturePayl // SignLegacyOriginal uses legacy transaction structure, with legacy V value (27/28) func (t *Transaction) SignLegacyOriginal(signer secp256k1.Signer) ([]byte, error) { + if signer == nil { + return nil, fmt.Errorf("invalid signer") + } signatureData := t.SignaturePayloadLegacyOriginal() sig, err := signer.Sign(signatureData.data) if err != nil { @@ -149,6 +156,9 @@ func (t *Transaction) SignaturePayloadLegacyEIP155(chainID int64) *TransactionSi // SignLegacyEIP155 uses legacy transaction structure, with EIP-155 signing V value (2*ChainID + 35 + Y-parity) func (t *Transaction) SignLegacyEIP155(signer secp256k1.Signer, chainID int64) ([]byte, error) { + if signer == nil { + return nil, fmt.Errorf("invalid signer") + } signaturePayload := t.SignaturePayloadLegacyEIP155(chainID) @@ -179,6 +189,9 @@ func (t *Transaction) SignaturePayloadEIP1559(chainID int64) *TransactionSignatu // SignEIP1559 uses EIP-1559 transaction structure (with EIP-2718 transaction type byte), with EIP-2930 V value (0 / 1 - direct parity-Y) func (t *Transaction) SignEIP1559(signer secp256k1.Signer, chainID int64) ([]byte, error) { + if signer == nil { + return nil, fmt.Errorf("invalid signer") + } signaturePayload := t.SignaturePayloadEIP1559(chainID) sig, err := signer.Sign(signaturePayload.data)