@@ -29,9 +29,6 @@ import (
29
29
30
30
var (
31
31
ErrInvalidChainId = errors .New ("invalid chain id for signer" )
32
-
33
- errAbstractSigner = errors .New ("abstract signer" )
34
- abstractSignerAddress = common .HexToAddress ("ffffffffffffffffffffffffffffffffffffffff" )
35
32
)
36
33
37
34
// 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
62
59
if err != nil {
63
60
return nil , err
64
61
}
65
- return s .WithSignature (tx , sig )
62
+ return tx .WithSignature (s , sig )
66
63
}
67
64
68
- // Sender derives the sender from the tx using the signer derivation
69
- // functions.
70
-
71
65
// Sender returns the address derived from the signature (V, R, S) using secp256k1
72
66
// elliptic curve and an error if it failed deriving or upon an incorrect
73
67
// signature.
@@ -86,33 +80,30 @@ func Sender(signer Signer, tx *Transaction) (common.Address, error) {
86
80
}
87
81
}
88
82
89
- pubkey , err := signer .PublicKey (tx )
83
+ addr , err := signer .Sender (tx )
90
84
if err != nil {
91
85
return common.Address {}, err
92
86
}
93
- var addr common.Address
94
- copy (addr [:], crypto .Keccak256 (pubkey [1 :])[12 :])
95
87
tx .from .Store (sigCache {signer : signer , from : addr })
96
88
return addr , nil
97
89
}
98
90
91
+ // Signer encapsulates transaction signature handling. Note that this interface is not a
92
+ // stable API and may change at any time to accommodate new protocol rules.
99
93
type Signer interface {
100
- // Hash returns the rlp encoded hash for signatures
94
+ // Sender returns the sender address of the transaction.
95
+ Sender (tx * Transaction ) (common.Address , error )
96
+ // SignatureValues returns the raw R, S, V values corresponding to the
97
+ // given signature.
98
+ SignatureValues (tx * Transaction , sig []byte ) (r , s , v * big.Int , err error )
99
+ // Hash returns the hash to be signed.
101
100
Hash (tx * Transaction ) common.Hash
102
- // PubilcKey returns the public key derived from the signature
103
- PublicKey (tx * Transaction ) ([]byte , error )
104
- // WithSignature returns a copy of the transaction with the given signature.
105
- // The signature must be encoded in [R || S || V] format where V is 0 or 1.
106
- WithSignature (tx * Transaction , sig []byte ) (* Transaction , error )
107
- // Checks for equality on the signers
101
+ // Equal returns true if the given signer is the same as the receiver.
108
102
Equal (Signer ) bool
109
103
}
110
104
111
- // EIP155Transaction implements TransactionInterface using the
112
- // EIP155 rules
105
+ // EIP155Transaction implements Signer using the EIP155 rules.
113
106
type EIP155Signer struct {
114
- HomesteadSigner
115
-
116
107
chainId , chainIdMul * big.Int
117
108
}
118
109
@@ -131,55 +122,32 @@ func (s EIP155Signer) Equal(s2 Signer) bool {
131
122
return ok && eip155 .chainId .Cmp (s .chainId ) == 0
132
123
}
133
124
134
- func (s EIP155Signer ) PublicKey (tx * Transaction ) ([]byte , error ) {
135
- // if the transaction is not protected fall back to homestead signer
125
+ var big8 = big .NewInt (8 )
126
+
127
+ func (s EIP155Signer ) Sender (tx * Transaction ) (common.Address , error ) {
136
128
if ! tx .Protected () {
137
- return ( HomesteadSigner {}). PublicKey (tx )
129
+ return HomesteadSigner {}. Sender (tx )
138
130
}
139
-
140
131
if tx .ChainId ().Cmp (s .chainId ) != 0 {
141
- return nil , ErrInvalidChainId
142
- }
143
-
144
- V := byte (new (big.Int ).Sub (tx .data .V , s .chainIdMul ).Uint64 () - 35 )
145
- if ! crypto .ValidateSignatureValues (V , tx .data .R , tx .data .S , true ) {
146
- return nil , ErrInvalidSig
147
- }
148
- // encode the signature in uncompressed format
149
- R , S := tx .data .R .Bytes (), tx .data .S .Bytes ()
150
- sig := make ([]byte , 65 )
151
- copy (sig [32 - len (R ):32 ], R )
152
- copy (sig [64 - len (S ):64 ], S )
153
- sig [64 ] = V
154
-
155
- // recover the public key from the signature
156
- hash := s .Hash (tx )
157
- pub , err := crypto .Ecrecover (hash [:], sig )
158
- if err != nil {
159
- return nil , err
160
- }
161
- if len (pub ) == 0 || pub [0 ] != 4 {
162
- return nil , errors .New ("invalid public key" )
132
+ return common.Address {}, ErrInvalidChainId
163
133
}
164
- return pub , nil
134
+ V := new (big.Int ).Sub (tx .data .V , s .chainIdMul )
135
+ V .Sub (V , big8 )
136
+ return recoverPlain (s .Hash (tx ), tx .data .R , tx .data .S , V , true )
165
137
}
166
138
167
139
// WithSignature returns a new transaction with the given signature. This signature
168
140
// needs to be in the [R || S || V] format where V is 0 or 1.
169
- func (s EIP155Signer ) WithSignature (tx * Transaction , sig []byte ) (* Transaction , error ) {
170
- if len (sig ) != 65 {
171
- panic (fmt .Sprintf ("wrong size for signature: got %d, want 65" , len (sig )))
141
+ func (s EIP155Signer ) SignatureValues (tx * Transaction , sig []byte ) (R , S , V * big.Int , err error ) {
142
+ R , S , V , err = HomesteadSigner {}.SignatureValues (tx , sig )
143
+ if err != nil {
144
+ return nil , nil , nil , err
172
145
}
173
-
174
- cpy := & Transaction {data : tx .data }
175
- cpy .data .R = new (big.Int ).SetBytes (sig [:32 ])
176
- cpy .data .S = new (big.Int ).SetBytes (sig [32 :64 ])
177
- cpy .data .V = new (big.Int ).SetBytes ([]byte {sig [64 ]})
178
146
if s .chainId .Sign () != 0 {
179
- cpy . data . V = big .NewInt (int64 (sig [64 ] + 35 ))
180
- cpy . data . V .Add (cpy . data . V , s .chainIdMul )
147
+ V = big .NewInt (int64 (sig [64 ] + 35 ))
148
+ V .Add (V , s .chainIdMul )
181
149
}
182
- return cpy , nil
150
+ return R , S , V , nil
183
151
}
184
152
185
153
// Hash returns the hash to be signed by the sender.
@@ -205,44 +173,14 @@ func (s HomesteadSigner) Equal(s2 Signer) bool {
205
173
return ok
206
174
}
207
175
208
- // WithSignature returns a new transaction with the given signature. This signature
176
+ // SignatureValues returns signature values . This signature
209
177
// needs to be in the [R || S || V] format where V is 0 or 1.
210
- func (hs HomesteadSigner ) WithSignature (tx * Transaction , sig []byte ) (* Transaction , error ) {
211
- if len (sig ) != 65 {
212
- panic (fmt .Sprintf ("wrong size for snature: got %d, want 65" , len (sig )))
213
- }
214
- cpy := & Transaction {data : tx .data }
215
- cpy .data .R = new (big.Int ).SetBytes (sig [:32 ])
216
- cpy .data .S = new (big.Int ).SetBytes (sig [32 :64 ])
217
- cpy .data .V = new (big.Int ).SetBytes ([]byte {sig [64 ] + 27 })
218
- return cpy , nil
178
+ func (hs HomesteadSigner ) SignatureValues (tx * Transaction , sig []byte ) (r , s , v * big.Int , err error ) {
179
+ return hs .FrontierSigner .SignatureValues (tx , sig )
219
180
}
220
181
221
- func (hs HomesteadSigner ) PublicKey (tx * Transaction ) ([]byte , error ) {
222
- if tx .data .V .BitLen () > 8 {
223
- return nil , ErrInvalidSig
224
- }
225
- V := byte (tx .data .V .Uint64 () - 27 )
226
- if ! crypto .ValidateSignatureValues (V , tx .data .R , tx .data .S , true ) {
227
- return nil , ErrInvalidSig
228
- }
229
- // encode the snature in uncompressed format
230
- r , s := tx .data .R .Bytes (), tx .data .S .Bytes ()
231
- sig := make ([]byte , 65 )
232
- copy (sig [32 - len (r ):32 ], r )
233
- copy (sig [64 - len (s ):64 ], s )
234
- sig [64 ] = V
235
-
236
- // recover the public key from the snature
237
- hash := hs .Hash (tx )
238
- pub , err := crypto .Ecrecover (hash [:], sig )
239
- if err != nil {
240
- return nil , err
241
- }
242
- if len (pub ) == 0 || pub [0 ] != 4 {
243
- return nil , errors .New ("invalid public key" )
244
- }
245
- return pub , nil
182
+ func (hs HomesteadSigner ) Sender (tx * Transaction ) (common.Address , error ) {
183
+ return recoverPlain (hs .Hash (tx ), tx .data .R , tx .data .S , tx .data .V , true )
246
184
}
247
185
248
186
type FrontierSigner struct {}
@@ -252,20 +190,19 @@ func (s FrontierSigner) Equal(s2 Signer) bool {
252
190
return ok
253
191
}
254
192
255
- // WithSignature returns a new transaction with the given signature. This signature
193
+ // SignatureValues returns signature values . This signature
256
194
// needs to be in the [R || S || V] format where V is 0 or 1.
257
- func (fs FrontierSigner ) WithSignature (tx * Transaction , sig []byte ) (* Transaction , error ) {
195
+ func (fs FrontierSigner ) SignatureValues (tx * Transaction , sig []byte ) (r , s , v * big. Int , err error ) {
258
196
if len (sig ) != 65 {
259
- panic (fmt .Sprintf ("wrong size for snature : got %d, want 65" , len (sig )))
197
+ panic (fmt .Sprintf ("wrong size for signature : got %d, want 65" , len (sig )))
260
198
}
261
- cpy := & Transaction {data : tx .data }
262
- cpy .data .R = new (big.Int ).SetBytes (sig [:32 ])
263
- cpy .data .S = new (big.Int ).SetBytes (sig [32 :64 ])
264
- cpy .data .V = new (big.Int ).SetBytes ([]byte {sig [64 ] + 27 })
265
- return cpy , nil
199
+ r = new (big.Int ).SetBytes (sig [:32 ])
200
+ s = new (big.Int ).SetBytes (sig [32 :64 ])
201
+ v = new (big.Int ).SetBytes ([]byte {sig [64 ] + 27 })
202
+ return r , s , v , nil
266
203
}
267
204
268
- // Hash returns the hash to be sned by the sender.
205
+ // Hash returns the hash to be signed by the sender.
269
206
// It does not uniquely identify the transaction.
270
207
func (fs FrontierSigner ) Hash (tx * Transaction ) common.Hash {
271
208
return rlpHash ([]interface {}{
@@ -278,32 +215,35 @@ func (fs FrontierSigner) Hash(tx *Transaction) common.Hash {
278
215
})
279
216
}
280
217
281
- func (fs FrontierSigner ) PublicKey (tx * Transaction ) ([]byte , error ) {
282
- if tx .data .V .BitLen () > 8 {
283
- return nil , ErrInvalidSig
284
- }
218
+ func (fs FrontierSigner ) Sender (tx * Transaction ) (common.Address , error ) {
219
+ return recoverPlain (fs .Hash (tx ), tx .data .R , tx .data .S , tx .data .V , false )
220
+ }
285
221
286
- V := byte (tx .data .V .Uint64 () - 27 )
287
- if ! crypto .ValidateSignatureValues (V , tx .data .R , tx .data .S , false ) {
288
- return nil , ErrInvalidSig
222
+ func recoverPlain (sighash common.Hash , R , S , Vb * big.Int , homestead bool ) (common.Address , error ) {
223
+ if Vb .BitLen () > 8 {
224
+ return common.Address {}, ErrInvalidSig
225
+ }
226
+ V := byte (Vb .Uint64 () - 27 )
227
+ if ! crypto .ValidateSignatureValues (V , R , S , homestead ) {
228
+ return common.Address {}, ErrInvalidSig
289
229
}
290
230
// encode the snature in uncompressed format
291
- r , s := tx . data . R .Bytes (), tx . data . S .Bytes ()
231
+ r , s := R .Bytes (), S .Bytes ()
292
232
sig := make ([]byte , 65 )
293
233
copy (sig [32 - len (r ):32 ], r )
294
234
copy (sig [64 - len (s ):64 ], s )
295
235
sig [64 ] = V
296
-
297
236
// recover the public key from the snature
298
- hash := fs .Hash (tx )
299
- pub , err := crypto .Ecrecover (hash [:], sig )
237
+ pub , err := crypto .Ecrecover (sighash [:], sig )
300
238
if err != nil {
301
- return nil , err
239
+ return common. Address {} , err
302
240
}
303
241
if len (pub ) == 0 || pub [0 ] != 4 {
304
- return nil , errors .New ("invalid public key" )
242
+ return common. Address {} , errors .New ("invalid public key" )
305
243
}
306
- return pub , nil
244
+ var addr common.Address
245
+ copy (addr [:], crypto .Keccak256 (pub [1 :])[12 :])
246
+ return addr , nil
307
247
}
308
248
309
249
// deriveChainId derives the chain id from the given v parameter
0 commit comments