1#[cfg(feature = "c-secp256k1")]
2use secp256k1::{Message, Error, RecoverableSignature, RecoveryId, SECP256K1};
3#[cfg(feature = "c-secp256k1")]
4use secp256k1::key::SecretKey;
5#[cfg(feature = "rust-secp256k1")]
6use secp256k1::{self, Message, Error, Signature, RecoveryId, SecretKey, PublicKey};
7
8use rlp::{self, Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp};
9use bigint::{Address, Gas, H256, U256};
10use sha3::{Digest, Keccak256};
11use address::FromKey;
12use std::str::FromStr;
13use super::{TransactionAction, RlpHash};
14
15pub trait SignaturePatch {
17 fn chain_id() -> Option<u64>;
18}
19
20pub struct GlobalSignaturePatch;
22impl SignaturePatch for GlobalSignaturePatch {
23 fn chain_id() -> Option<u64> { None }
24}
25
26pub struct ClassicSignaturePatch;
28impl SignaturePatch for ClassicSignaturePatch {
29 fn chain_id() -> Option<u64> { Some(61) }
30}
31
32pub trait ValidationPatch {
34 fn require_low_s() -> bool;
35}
36
37pub struct FrontierValidationPatch;
39impl ValidationPatch for FrontierValidationPatch {
40 fn require_low_s() -> bool { false }
41}
42
43pub struct HomesteadValidationPatch;
45impl ValidationPatch for HomesteadValidationPatch {
46 fn require_low_s() -> bool { true }
47}
48
49#[derive(Clone, Debug, PartialEq, Eq)]
50pub struct TransactionSignature {
51 pub v: u64,
52 pub r: H256,
53 pub s: H256,
54}
55
56impl TransactionSignature {
57 pub fn standard_v(&self) -> u8 {
58 let v = self.v;
59 if v == 27 || v == 28 || v > 36 {
60 ((v - 1) % 2) as u8
61 } else {
62 4
63 }
64 }
65
66 pub fn is_low_s(&self) -> bool {
67 self.s <= H256::from_str("0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0").unwrap()
68 }
69
70 pub fn is_valid(&self) -> bool {
71 self.standard_v() <= 1 &&
72 self.r < H256::from_str("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141").unwrap() &&
73 self.r >= H256::from(1) &&
74 self.s < H256::from_str("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141").unwrap() &&
75 self.s >= H256::from(1)
76 }
77
78 pub fn chain_id(&self) -> Option<u64> {
79 if self.v > 36 {
80 Some((self.v - 35) / 2)
81 } else {
82 None
83 }
84 }
85
86 #[cfg(feature = "c-secp256k1")]
87 pub fn to_recoverable_signature(&self) -> Result<RecoverableSignature, Error> {
88 let mut sig = [0u8; 64];
89 sig[0..32].copy_from_slice(&self.r);
90 sig[32..64].copy_from_slice(&self.s);
91
92 RecoverableSignature::from_compact(&SECP256K1, &sig, RecoveryId::from_i32(self.standard_v() as i32)?)
93 }
94
95 #[cfg(feature = "rust-secp256k1")]
96 pub fn to_recoverable_signature(&self) -> Result<(Signature, RecoveryId), Error> {
97 let mut sig = [0u8; 64];
98 sig[0..32].copy_from_slice(&self.r);
99 sig[32..64].copy_from_slice(&self.s);
100
101 Ok((Signature::parse(&sig), RecoveryId::parse(self.standard_v() as u8)?))
102 }
103}
104
105pub struct UnsignedTransaction {
106 pub nonce: U256,
107 pub gas_price: Gas,
108 pub gas_limit: Gas,
109 pub action: TransactionAction,
110 pub value: U256,
111 pub input: Vec<u8>,
112}
113
114impl UnsignedTransaction {
115 fn signing_rlp_append(&self, s: &mut RlpStream, chain_id: Option<u64>) {
116 s.begin_list(if chain_id.is_some() { 9 } else { 6 });
117 s.append(&self.nonce);
118 s.append(&self.gas_price);
119 s.append(&self.gas_limit);
120 s.append(&self.action);
121 s.append(&self.value);
122 s.append(&self.input);
123
124 if let Some(chain_id) = chain_id {
125 s.append(&chain_id);
126 s.append(&0u8);
127 s.append(&0u8);
128 }
129 }
130
131 fn signing_hash(&self, chain_id: Option<u64>) -> H256 {
132 let mut stream = RlpStream::new();
133 self.signing_rlp_append(&mut stream, chain_id);
134 H256::from(Keccak256::digest(&stream.drain()).as_slice())
135 }
136
137 pub fn sign<P: SignaturePatch>(self, key: &SecretKey) -> Transaction {
138 let hash = self.signing_hash(P::chain_id());
139 let msg = {
141 #[cfg(feature = "c-secp256k1")]
142 { Message::from_slice(&hash).unwrap() }
143 #[cfg(feature = "rust-secp256k1")]
144 { let mut a = [0u8; 32];
145 for i in 0..32 {
146 a[i] = hash[i];
147 }
148 Message::parse(&a)
149 }
150 };
151
152 let s = {
154 #[cfg(feature = "c-secp256k1")]
155 { SECP256K1.sign_recoverable(&msg, key).unwrap() }
156 #[cfg(feature = "rust-secp256k1")]
157 { secp256k1::sign(&msg, key).unwrap() }
158 };
159 let (rid, sig) = {
160 #[cfg(feature = "c-secp256k1")]
161 { s.serialize_compact(&SECP256K1) }
162 #[cfg(feature = "rust-secp256k1")]
163 { (s.1, s.0.serialize()) }
164 };
165
166 let sig = TransactionSignature {
167 v: ({
168 #[cfg(feature = "c-secp256k1")]
169 { rid.to_i32() }
170 #[cfg(feature = "rust-secp256k1")]
171 { let v: i32 = rid.into(); v }
172 } + if let Some(n) = P::chain_id() { (35 + n * 2) as i32 } else { 27 }) as u64,
173 r: H256::from(&sig[0..32]),
174 s: H256::from(&sig[32..64]),
175 };
176
177 Transaction {
178 nonce: self.nonce,
179 gas_price: self.gas_price,
180 gas_limit: self.gas_limit,
181 action: self.action,
182 value: self.value,
183 input: self.input,
184 signature: sig,
185 }
186 }
187
188 pub fn sign_global(self, key: &SecretKey) -> Transaction {
189 self.sign::<GlobalSignaturePatch>(key)
190 }
191}
192
193impl From<Transaction> for UnsignedTransaction {
194 fn from(val: Transaction) -> UnsignedTransaction {
195 UnsignedTransaction {
196 nonce: val.nonce,
197 gas_price: val.gas_price,
198 gas_limit: val.gas_limit,
199 action: val.action,
200 value: val.value,
201 input: val.input,
202 }
203 }
204}
205
206#[derive(Clone, Debug, PartialEq, Eq)]
207pub struct Transaction {
208 pub nonce: U256,
209 pub gas_price: Gas,
210 pub gas_limit: Gas,
211 pub action: TransactionAction,
212 pub value: U256,
213 pub signature: TransactionSignature,
214 pub input: Vec<u8>, }
216
217impl Transaction {
218 pub fn caller(&self) -> Result<Address, Error> {
219 let unsigned = UnsignedTransaction::from((*self).clone());
220 let hash = unsigned.signing_hash(self.signature.chain_id());
221 let sig = self.signature.to_recoverable_signature()?;
222 let public_key = {
223 #[cfg(feature = "c-secp256k1")]
224 { SECP256K1.recover(&Message::from_slice(&hash).unwrap(), &sig)? }
225 #[cfg(feature = "rust-secp256k1")]
226 { let mut a = [0u8; 32];
227 for i in 0..32 {
228 a[i] = hash[i];
229 }
230 secp256k1::recover(&Message::parse(&a), &sig.0, &sig.1)?
231 }
232 };
233
234 Ok(Address::from_public_key(&public_key))
235 }
236
237 pub fn address(&self) -> Result<Address, Error> {
238 Ok(self.action.address(self.caller()?, self.nonce))
239 }
240
241 pub fn is_basic_valid<P: SignaturePatch, Q: ValidationPatch>(&self) -> bool {
242 if !self.signature.is_valid() {
243 return false;
244 }
245
246 if self.signature.chain_id().is_some() && self.signature.chain_id() != P::chain_id() {
247 return false;
248 }
249
250 if self.caller().is_err() {
251 return false;
252 }
253
254 if Q::require_low_s() && !self.signature.is_low_s() {
255 return false;
256 }
257
258 return true;
259 }
260}
261
262impl Encodable for Transaction {
263 fn rlp_append(&self, s: &mut RlpStream) {
264 s.begin_list(9);
265 s.append(&self.nonce);
266 s.append(&self.gas_price);
267 s.append(&self.gas_limit);
268 s.append(&self.action);
269 s.append(&self.value);
270 s.append(&self.input);
271 s.append(&self.signature.v);
272 s.append(&self.signature.r);
273 s.append(&self.signature.s);
274 }
275}
276
277impl Decodable for Transaction {
278 fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
279 Ok(Self {
280 nonce: rlp.val_at(0)?,
281 gas_price: rlp.val_at(1)?,
282 gas_limit: rlp.val_at(2)?,
283 action: rlp.val_at(3)?,
284 value: rlp.val_at(4)?,
285 input: rlp.val_at(5)?,
286 signature: TransactionSignature {
287 v: rlp.val_at(6)?,
288 r: rlp.val_at(7)?,
289 s: rlp.val_at(8)?,
290 },
291 })
292 }
293}
294
295impl RlpHash for Transaction {
296 fn rlp_hash(&self) -> H256 {
297 H256::from(Keccak256::digest(&rlp::encode(self)).as_slice())
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use secp256k1::SECP256K1;
304 use secp256k1::key::SecretKey;
305 use bigint::{Address, Gas, U256};
306 use address::FromKey;
307 use rand::os::OsRng;
308 use super::{UnsignedTransaction, TransactionAction, ClassicSignaturePatch,
309 HomesteadValidationPatch};
310
311 #[test]
312 pub fn should_recover_address() {
313 let mut rng = OsRng::new().unwrap();
314 let secret_key = SecretKey::new(&SECP256K1, &mut rng);
315 let address = Address::from_secret_key(&secret_key);
316
317 let unsigned = UnsignedTransaction {
318 nonce: U256::zero(),
319 gas_price: Gas::zero(),
320 gas_limit: Gas::zero(),
321 action: TransactionAction::Create,
322 value: U256::zero(),
323 input: Vec::new()
324 };
325 let signed = unsigned.sign::<ClassicSignaturePatch>(&secret_key);
326
327 assert_eq!(signed.signature.chain_id(), Some(61));
328 assert!(signed.is_basic_valid::<ClassicSignaturePatch, HomesteadValidationPatch>());
329 assert_eq!(signed.caller(), address);
330 }
331}