17
17
# in the yellow paper it is specified that s should be smaller than secpk1n (eq.205)
18
18
secpk1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337
19
19
20
+ # EIP155 parameters
21
+ v_offset = 27
22
+ v_zero = v_offset
23
+ v_one = v_zero + 1
24
+ chain_id = 1
25
+ eip155_v_offset = 35
26
+ eip155_v_zero = eip155_v_offset + 2 * chain_id
27
+ eip155_v_one = eip155_v_zero + 1
20
28
21
29
class Transaction (rlp .Serializable ):
22
30
@@ -70,27 +78,16 @@ def __init__(self, nonce, gasprice, startgas, to, value, data, v=0, r=0, s=0):
70
78
71
79
@property
72
80
def sender (self ):
73
-
74
81
if not self ._sender :
75
- # Determine sender
76
82
if self .v :
77
- if self . r >= N or self .s >= N or self .v not in ( 27 , 28 , 37 , 38 ) \
78
- or self .r == 0 or self .s == 0 :
83
+ v = self .decode_v ( self .v )
84
+ if self . r >= N or self . s >= N or v > 1 or self .r == 0 or self .s == 0 :
79
85
raise InvalidTransaction ("Invalid signature values!" )
80
- log .debug ('reco< 27 or self.v > 28 \v ering sender' )
81
- if self .v in (27 , 28 ):
82
- rlpdata = rlp .encode (self , UnsignedTransaction )
83
- rawhash = utils .sha3 (rlpdata )
84
- v = self .v
85
- elif self .v in (37 , 38 ):
86
- rlpdata = rlp .encode (rlp .infer_sedes (self ).serialize (self )[:- 3 ] + ['\x01 ' , '' , '' ])
87
- rawhash = utils .sha3 (rlpdata )
88
- v = self .v - 10
89
- pub = ecrecover_to_pub (rawhash , v , self .r , self .s )
86
+ rawhash = utils .sha3 (self .signing_data ('verify' ))
87
+ pub = ecrecover_to_pub (rawhash , v + 27 , self .r , self .s )
90
88
if pub == b"\x00 " * 64 :
91
89
raise InvalidTransaction ("Invalid signature (zero privkey cannot sign)" )
92
90
self ._sender = utils .sha3 (pub )[- 20 :]
93
- assert self .sender == self ._sender
94
91
else :
95
92
self ._sender = 0
96
93
return self ._sender
@@ -112,7 +109,8 @@ def sign(self, key):
112
109
# we need a binary key
113
110
key = encode_privkey (key , 'bin' )
114
111
115
- self .v , self .r , self .s = ecsign (rawhash , key )
112
+ v , self .r , self .s = ecsign (rawhash , key )
113
+ self .v = self .encode_v (v )
116
114
117
115
self .sender = utils .privtoaddr (key )
118
116
return self
@@ -185,6 +183,57 @@ def check_low_s_homestead(self):
185
183
if self .s > N // 2 or self .s == 0 :
186
184
raise InvalidTransaction ("Invalid signature S value!" )
187
185
186
+ def encode_v (self , v ):
187
+ return v + v_zero
188
+
189
+ def decode_v (self , v ):
190
+ if not v :
191
+ return
192
+ if v in (v_zero , v_one ):
193
+ return v - v_zero
194
+ else :
195
+ raise InvalidTransaction ("invalid signature" )
196
+
197
+ def signing_data (self , mode ):
198
+ if mode == 'verify' :
199
+ if self .v in (v_zero , v_one ):
200
+ return rlp .encode (self , sedes = UnsignedTransaction )
201
+ elif mode == 'sign' :
202
+ return rlp .encode (self , sedes = UnsignedTransaction )
203
+ else :
204
+ raise ValueError ("invalid mode" )
205
+
206
+
207
+ class EIP155Transaction (Transaction ):
208
+
209
+ def decode_chain_id (self , v ):
210
+ if v < eip155_v_offset + 2 :
211
+ raise InvalidTransaction ("invalid chain id" )
212
+ return (v - eip155_v_offset ) / 2
213
+
214
+ def decode_v (self , v ):
215
+ if not v :
216
+ return
217
+ if v in (eip155_v_zero , eip155_v_one ):
218
+ return v - eip155_v_zero
219
+ else :
220
+ return super (EIP155Transaction , self ).decode_v (v )
221
+
222
+ def signing_data (self , mode ):
223
+ if mode == 'verify' :
224
+ if self .v >= eip155_v_zero :
225
+ v = big_endian_int .serialize (self .decode_chain_id (self .v ))
226
+ return rlp .encode (rlp .infer_sedes (self ).serialize (self )[:- 3 ] + [v , '' , '' ])
227
+ else :
228
+ return super (EIP155Transaction , self ).signing_data (mode )
229
+ elif mode == 'sign' :
230
+ if self .v > 0 and self .r == 0 and self .s == 0 :
231
+ return rlp .encode (self , sedes = Transaction )
232
+ else :
233
+ return super (EIP155Transaction , self ).signing_data (mode )
234
+ else :
235
+ raise ValueError ("invalid mode" )
236
+
188
237
189
238
UnsignedTransaction = Transaction .exclude (['v' , 'r' , 's' ])
190
239
0 commit comments