@ -29,9 +29,6 @@ import (
var (
ErrInvalidChainId = errors . New ( "invalid chain id for signer" )
errAbstractSigner = errors . New ( "abstract signer" )
abstractSignerAddress = common . HexToAddress ( "ffffffffffffffffffffffffffffffffffffffff" )
)
// sigCache is used to cache the derived sender and contains
@ -62,12 +59,9 @@ func SignTx(tx *Transaction, s Signer, prv *ecdsa.PrivateKey) (*Transaction, err
if err != nil {
return nil , err
}
return s . WithSignature ( tx , sig )
return tx . WithSignature ( s , sig )
}
// Sender derives the sender from the tx using the signer derivation
// functions.
// Sender returns the address derived from the signature (V, R, S) using secp256k1
// elliptic curve and an error if it failed deriving or upon an incorrect
// signature.
@ -86,33 +80,30 @@ func Sender(signer Signer, tx *Transaction) (common.Address, error) {
}
}
pubkey , err := signer . PublicKey ( tx )
addr , err := signer . Sender ( tx )
if err != nil {
return common . Address { } , err
}
var addr common . Address
copy ( addr [ : ] , crypto . Keccak256 ( pubkey [ 1 : ] ) [ 12 : ] )
tx . from . Store ( sigCache { signer : signer , from : addr } )
return addr , nil
}
// Signer encapsulates transaction signature handling. Note that this interface is not a
// stable API and may change at any time to accommodate new protocol rules.
type Signer interface {
// Hash returns the rlp encoded hash for signatures
// Sender returns the sender address of the transaction.
Sender ( tx * Transaction ) ( common . Address , error )
// SignatureValues returns the raw R, S, V values corresponding to the
// given signature.
SignatureValues ( tx * Transaction , sig [ ] byte ) ( r , s , v * big . Int , err error )
// Hash returns the hash to be signed.
Hash ( tx * Transaction ) common . Hash
// PubilcKey returns the public key derived from the signature
PublicKey ( tx * Transaction ) ( [ ] byte , error )
// WithSignature returns a copy of the transaction with the given signature.
// The signature must be encoded in [R || S || V] format where V is 0 or 1.
WithSignature ( tx * Transaction , sig [ ] byte ) ( * Transaction , error )
// Checks for equality on the signers
// Equal returns true if the given signer is the same as the receiver.
Equal ( Signer ) bool
}
// EIP155Transaction implements TransactionInterface using the
// EIP155 rules
// EIP155Transaction implements Signer using the EIP155 rules.
type EIP155Signer struct {
HomesteadSigner
chainId , chainIdMul * big . Int
}
@ -131,55 +122,32 @@ func (s EIP155Signer) Equal(s2 Signer) bool {
return ok && eip155 . chainId . Cmp ( s . chainId ) == 0
}
func ( s EIP155Signer ) PublicKey ( tx * Transaction ) ( [ ] byte , error ) {
// if the transaction is not protected fall back to homestead signer
var big8 = big . NewInt ( 8 )
func ( s EIP155Signer ) Sender ( tx * Transaction ) ( common . Address , error ) {
if ! tx . Protected ( ) {
return ( HomesteadSigner { } ) . PublicKey ( tx )
return HomesteadSigner { } . Sender ( tx )
}
if tx . ChainId ( ) . Cmp ( s . chainId ) != 0 {
return nil , ErrInvalidChainId
}
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
// recover the public key from the signature
hash := s . Hash ( tx )
pub , err := crypto . Ecrecover ( hash [ : ] , sig )
if err != nil {
return nil , err
}
if len ( pub ) == 0 || pub [ 0 ] != 4 {
return nil , errors . New ( "invalid public key" )
return common . Address { } , ErrInvalidChainId
}
return pub , nil
V := new ( big . Int ) . Sub ( tx . data . V , s . chainIdMul )
V . Sub ( V , big8 )
return recoverPlain ( s . Hash ( tx ) , tx . data . R , tx . data . S , V , true )
}
// 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 signature: got %d, want 65" , len ( sig ) ) )
func ( s EIP155Signer ) SignatureValues ( tx * Transaction , sig [ ] byte ) ( R , S , V * big . Int , err error ) {
R , S , V , err = HomesteadSigner { } . SignatureValues ( tx , sig )
if err != nil {
return nil , nil , nil , err
}
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 ] } )
if s . chainId . Sign ( ) != 0 {
cpy . data . V = big . NewInt ( int64 ( sig [ 64 ] + 35 ) )
cpy . data . V . Add ( cpy . data . V , s . chainIdMul )
V = big . NewInt ( int64 ( sig [ 64 ] + 35 ) )
V . Add ( V , s . chainIdMul )
}
return cpy , nil
return R , S , V , nil
}
// Hash returns the hash to be signed by the sender.
@ -205,44 +173,14 @@ func (s HomesteadSigner) Equal(s2 Signer) bool {
return ok
}
// WithSignature returns a new transaction with the given signature . This signature
// SignatureValues returns signature values . 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 ) ) )
}
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 ] + 27 } )
return cpy , nil
func ( hs HomesteadSigner ) SignatureValues ( tx * Transaction , sig [ ] byte ) ( r , s , v * big . Int , err error ) {
return hs . FrontierSigner . SignatureValues ( tx , sig )
}
func ( hs HomesteadSigner ) PublicKey ( tx * Transaction ) ( [ ] byte , error ) {
if tx . data . V . BitLen ( ) > 8 {
return nil , ErrInvalidSig
}
V := byte ( tx . data . V . Uint64 ( ) - 27 )
if ! crypto . ValidateSignatureValues ( V , tx . data . R , tx . data . S , true ) {
return nil , ErrInvalidSig
}
// encode the snature 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
// recover the public key from the snature
hash := hs . Hash ( tx )
pub , err := crypto . Ecrecover ( hash [ : ] , sig )
if err != nil {
return nil , err
}
if len ( pub ) == 0 || pub [ 0 ] != 4 {
return nil , errors . New ( "invalid public key" )
}
return pub , nil
func ( hs HomesteadSigner ) Sender ( tx * Transaction ) ( common . Address , error ) {
return recoverPlain ( hs . Hash ( tx ) , tx . data . R , tx . data . S , tx . data . V , true )
}
type FrontierSigner struct { }
@ -252,20 +190,19 @@ func (s FrontierSigner) Equal(s2 Signer) bool {
return ok
}
// WithSignature returns a new transaction with the given signature . This signature
// SignatureValues returns signature values . This signature
// needs to be in the [R || S || V] format where V is 0 or 1.
func ( fs FrontierSigner ) With Signature( tx * Transaction , sig [ ] byte ) ( * Transaction , error ) {
func ( fs FrontierSigner ) SignatureValues ( tx * Transaction , sig [ ] byte ) ( r , s , v * big . Int , err error ) {
if len ( sig ) != 65 {
panic ( fmt . Sprintf ( "wrong size for snature: got %d, want 65" , len ( sig ) ) )
panic ( fmt . Sprintf ( "wrong size for sig nature: got %d, want 65" , len ( sig ) ) )
}
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 ] + 27 } )
return cpy , nil
r = new ( big . Int ) . SetBytes ( sig [ : 32 ] )
s = new ( big . Int ) . SetBytes ( sig [ 32 : 64 ] )
v = new ( big . Int ) . SetBytes ( [ ] byte { sig [ 64 ] + 27 } )
return r , s , v , nil
}
// Hash returns the hash to be sned by the sender.
// Hash returns the hash to be sig ned by the sender.
// It does not uniquely identify the transaction.
func ( fs FrontierSigner ) Hash ( tx * Transaction ) common . Hash {
return rlpHash ( [ ] interface { } {
@ -278,32 +215,35 @@ func (fs FrontierSigner) Hash(tx *Transaction) common.Hash {
} )
}
func ( fs FrontierSigner ) PublicKey ( tx * Transaction ) ( [ ] byte , error ) {
if tx . data . V . BitLen ( ) > 8 {
return nil , ErrInvalidSig
}
func ( fs FrontierSigner ) Sender ( tx * Transaction ) ( common . Address , error ) {
return recoverPlain ( fs . Hash ( tx ) , tx . data . R , tx . data . S , tx . data . V , false )
}
V := byte ( tx . data . V . Uint64 ( ) - 27 )
if ! crypto . ValidateSignatureValues ( V , tx . data . R , tx . data . S , false ) {
return nil , ErrInvalidSig
func recoverPlain ( sighash common . Hash , R , S , Vb * big . Int , homestead bool ) ( common . Address , error ) {
if Vb . BitLen ( ) > 8 {
return common . Address { } , ErrInvalidSig
}
V := byte ( Vb . Uint64 ( ) - 27 )
if ! crypto . ValidateSignatureValues ( V , R , S , homestead ) {
return common . Address { } , ErrInvalidSig
}
// encode the snature in uncompressed format
r , s := tx . data . R . Bytes ( ) , tx . data . S . Bytes ( )
r , s := R . Bytes ( ) , S . Bytes ( )
sig := make ( [ ] byte , 65 )
copy ( sig [ 32 - len ( r ) : 32 ] , r )
copy ( sig [ 64 - len ( s ) : 64 ] , s )
sig [ 64 ] = V
// recover the public key from the snature
hash := fs . Hash ( tx )
pub , err := crypto . Ecrecover ( hash [ : ] , sig )
pub , err := crypto . Ecrecover ( sighash [ : ] , sig )
if err != nil {
return nil , err
return common . Address { } , err
}
if len ( pub ) == 0 || pub [ 0 ] != 4 {
return nil , errors . New ( "invalid public key" )
return common . Address { } , errors . New ( "invalid public key" )
}
return pub , nil
var addr common . Address
copy ( addr [ : ] , crypto . Keccak256 ( pub [ 1 : ] ) [ 12 : ] )
return addr , nil
}
// deriveChainId derives the chain id from the given v parameter