aboutsummaryrefslogtreecommitdiffstats
path: root/core/types/transaction_signing.go
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2017-01-05 18:35:23 +0800
committerFelix Lange <fjl@users.noreply.github.com>2017-01-05 18:35:23 +0800
commit08eea0f0e417c5f6ff864ae4633cc3e0a12aa405 (patch)
treef3a76e0c2511e18a874742cf801d35073b62c2f2 /core/types/transaction_signing.go
parent0fac8cba479a7cd90c17307b8795a0f836877c2e (diff)
downloadgo-tangerine-08eea0f0e417c5f6ff864ae4633cc3e0a12aa405.tar
go-tangerine-08eea0f0e417c5f6ff864ae4633cc3e0a12aa405.tar.gz
go-tangerine-08eea0f0e417c5f6ff864ae4633cc3e0a12aa405.tar.bz2
go-tangerine-08eea0f0e417c5f6ff864ae4633cc3e0a12aa405.tar.lz
go-tangerine-08eea0f0e417c5f6ff864ae4633cc3e0a12aa405.tar.xz
go-tangerine-08eea0f0e417c5f6ff864ae4633cc3e0a12aa405.tar.zst
go-tangerine-08eea0f0e417c5f6ff864ae4633cc3e0a12aa405.zip
accounts, core, crypto, internal: use normalised V during signature handling (#3455)
To address increasing complexity in code that handles signatures, this PR discards all notion of "different" signature types at the library level. Both the crypto and accounts package is reduced to only be able to produce plain canonical secp256k1 signatures. This makes the crpyto APIs much cleaner, simpler and harder to abuse.
Diffstat (limited to 'core/types/transaction_signing.go')
-rw-r--r--core/types/transaction_signing.go56
1 files changed, 19 insertions, 37 deletions
diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go
index 7d571643f..8952bd574 100644
--- a/core/types/transaction_signing.go
+++ b/core/types/transaction_signing.go
@@ -53,7 +53,7 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer {
// SignECDSA signs the transaction using the given signer and private key
func SignECDSA(s Signer, tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
h := s.Hash(tx)
- sig, err := crypto.SignEthereum(h[:], prv)
+ sig, err := crypto.Sign(h[:], prv)
if err != nil {
return nil, err
}
@@ -91,11 +91,6 @@ func Sender(signer Signer, tx *Transaction) (common.Address, error) {
return addr, nil
}
-// SignatureValues returns the ECDSA signature values contained in the transaction.
-func SignatureValues(signer Signer, tx *Transaction) (v byte, r *big.Int, s *big.Int) {
- return normaliseV(signer, tx.data.V), new(big.Int).Set(tx.data.R), new(big.Int).Set(tx.data.S)
-}
-
type Signer interface {
// Hash returns the rlp encoded hash for signatures
Hash(tx *Transaction) common.Hash
@@ -143,17 +138,16 @@ func (s EIP155Signer) PublicKey(tx *Transaction) ([]byte, error) {
return nil, ErrInvalidChainId
}
- V := normaliseV(s, tx.data.V)
+ V := byte(new(big.Int).Sub(tx.data.V, s.chainIdMul).Uint64() - 35)
if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, true) {
return nil, ErrInvalidSig
}
-
// encode the signature in uncompressed format
R, S := tx.data.R.Bytes(), tx.data.S.Bytes()
sig := make([]byte, 65)
copy(sig[32-len(R):32], R)
copy(sig[64-len(S):64], S)
- sig[64] = V - 27
+ sig[64] = V
// recover the public key from the signature
hash := s.Hash(tx)
@@ -167,8 +161,8 @@ func (s EIP155Signer) PublicKey(tx *Transaction) ([]byte, error) {
return pub, nil
}
-// WithSignature returns a new transaction with the given signature.
-// This signature needs to be formatted as described in the yellow paper (v+27).
+// WithSignature returns a new transaction with the given signature. This signature
+// needs to be in the [R || S || V] format where V is 0 or 1.
func (s EIP155Signer) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
if len(sig) != 65 {
panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig)))
@@ -179,7 +173,7 @@ func (s EIP155Signer) WithSignature(tx *Transaction, sig []byte) (*Transaction,
cpy.data.S = new(big.Int).SetBytes(sig[32:64])
cpy.data.V = new(big.Int).SetBytes([]byte{sig[64]})
if s.chainId.BitLen() > 0 {
- cpy.data.V = big.NewInt(int64(sig[64] - 27 + 35))
+ cpy.data.V = big.NewInt(int64(sig[64] + 35))
cpy.data.V.Add(cpy.data.V, s.chainIdMul)
}
return cpy, nil
@@ -201,7 +195,7 @@ func (s EIP155Signer) Hash(tx *Transaction) common.Hash {
func (s EIP155Signer) SigECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
h := s.Hash(tx)
- sig, err := crypto.SignEthereum(h[:], prv)
+ sig, err := crypto.Sign(h[:], prv)
if err != nil {
return nil, err
}
@@ -217,8 +211,8 @@ func (s HomesteadSigner) Equal(s2 Signer) bool {
return ok
}
-// WithSignature returns a new transaction with the given snature.
-// This snature needs to be formatted as described in the yellow paper (v+27).
+// WithSignature returns a new transaction with the given signature. This signature
+// needs to be in the [R || S || V] format where V is 0 or 1.
func (hs HomesteadSigner) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
if len(sig) != 65 {
panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig)))
@@ -226,13 +220,13 @@ func (hs HomesteadSigner) WithSignature(tx *Transaction, sig []byte) (*Transacti
cpy := &Transaction{data: tx.data}
cpy.data.R = new(big.Int).SetBytes(sig[:32])
cpy.data.S = new(big.Int).SetBytes(sig[32:64])
- cpy.data.V = new(big.Int).SetBytes([]byte{sig[64]})
+ cpy.data.V = new(big.Int).SetBytes([]byte{sig[64] + 27})
return cpy, nil
}
func (hs HomesteadSigner) SignECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
h := hs.Hash(tx)
- sig, err := crypto.SignEthereum(h[:], prv)
+ sig, err := crypto.Sign(h[:], prv)
if err != nil {
return nil, err
}
@@ -243,7 +237,7 @@ func (hs HomesteadSigner) PublicKey(tx *Transaction) ([]byte, error) {
if tx.data.V.BitLen() > 8 {
return nil, ErrInvalidSig
}
- V := byte(tx.data.V.Uint64())
+ V := byte(tx.data.V.Uint64() - 27)
if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, true) {
return nil, ErrInvalidSig
}
@@ -252,7 +246,7 @@ func (hs HomesteadSigner) PublicKey(tx *Transaction) ([]byte, error) {
sig := make([]byte, 65)
copy(sig[32-len(r):32], r)
copy(sig[64-len(s):64], s)
- sig[64] = V - 27
+ sig[64] = V
// recover the public key from the snature
hash := hs.Hash(tx)
@@ -273,8 +267,8 @@ func (s FrontierSigner) Equal(s2 Signer) bool {
return ok
}
-// WithSignature returns a new transaction with the given snature.
-// This snature needs to be formatted as described in the yellow paper (v+27).
+// WithSignature returns a new transaction with the given signature. This signature
+// needs to be in the [R || S || V] format where V is 0 or 1.
func (fs FrontierSigner) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) {
if len(sig) != 65 {
panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig)))
@@ -282,13 +276,13 @@ func (fs FrontierSigner) WithSignature(tx *Transaction, sig []byte) (*Transactio
cpy := &Transaction{data: tx.data}
cpy.data.R = new(big.Int).SetBytes(sig[:32])
cpy.data.S = new(big.Int).SetBytes(sig[32:64])
- cpy.data.V = new(big.Int).SetBytes([]byte{sig[64]})
+ cpy.data.V = new(big.Int).SetBytes([]byte{sig[64] + 27})
return cpy, nil
}
func (fs FrontierSigner) SignECDSA(tx *Transaction, prv *ecdsa.PrivateKey) (*Transaction, error) {
h := fs.Hash(tx)
- sig, err := crypto.SignEthereum(h[:], prv)
+ sig, err := crypto.Sign(h[:], prv)
if err != nil {
return nil, err
}
@@ -313,7 +307,7 @@ func (fs FrontierSigner) PublicKey(tx *Transaction) ([]byte, error) {
return nil, ErrInvalidSig
}
- V := byte(tx.data.V.Uint64())
+ V := byte(tx.data.V.Uint64() - 27)
if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, false) {
return nil, ErrInvalidSig
}
@@ -322,7 +316,7 @@ func (fs FrontierSigner) PublicKey(tx *Transaction) ([]byte, error) {
sig := make([]byte, 65)
copy(sig[32-len(r):32], r)
copy(sig[64-len(s):64], s)
- sig[64] = V - 27
+ sig[64] = V
// recover the public key from the snature
hash := fs.Hash(tx)
@@ -336,18 +330,6 @@ func (fs FrontierSigner) PublicKey(tx *Transaction) ([]byte, error) {
return pub, nil
}
-// normaliseV returns the Ethereum version of the V parameter
-func normaliseV(s Signer, v *big.Int) byte {
- if s, ok := s.(EIP155Signer); ok {
- stdV := v.BitLen() <= 8 && (v.Uint64() == 27 || v.Uint64() == 28)
- if s.chainId.BitLen() > 0 && !stdV {
- nv := byte((new(big.Int).Sub(v, s.chainIdMul).Uint64()) - 35 + 27)
- return nv
- }
- }
- return byte(v.Uint64())
-}
-
// deriveChainId derives the chain id from the given v parameter
func deriveChainId(v *big.Int) *big.Int {
if v.BitLen() <= 64 {