cs_mwc_bch/script/
checker.rs

1use messages::Tx;
2use secp256k1::{Message, PublicKey, Secp256k1, Signature};
3use transaction::sighash::{sighash, SigHashCache, SIGHASH_FORKID};
4use util::{Amount, Error, Result};
5
6/// Locktimes greater than or equal to this are interpreted as timestamps. Less then, block heights.
7const LOCKTIME_THRESHOLD: i32 = 500000000;
8
9/// Disables the relative lock time for the sequence field
10const SEQUENCE_LOCKTIME_DISABLE_FLAG: u32 = 1 << 31;
11/// When set, sequence uses time. When unset, it uses block height.
12const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = 1 << 22;
13
14/// Checks that external values are correct in the script
15pub trait Checker {
16    /// Checks that a signature and public key validate within a script
17    ///
18    /// Script should already have all signatures removed if they existed.
19    fn check_sig(&mut self, sig: &[u8], pubkey: &[u8], script: &[u8]) -> Result<bool>;
20
21    /// Checks that the lock time is valid according to BIP 65
22    fn check_locktime(&self, locktime: i32) -> Result<bool>;
23
24    /// Checks that the relative lock time enforced by the sequence is valid according to BIP 112
25    fn check_sequence(&self, sequence: i32) -> Result<bool>;
26}
27
28/// Script checker that fails all transaction checks
29pub struct TransactionlessChecker {}
30
31impl Checker for TransactionlessChecker {
32    fn check_sig(&mut self, _sig: &[u8], _pubkey: &[u8], _script: &[u8]) -> Result<bool> {
33        Err(Error::IllegalState("Illegal transaction check".to_string()))
34    }
35
36    fn check_locktime(&self, _locktime: i32) -> Result<bool> {
37        Err(Error::IllegalState("Illegal transaction check".to_string()))
38    }
39
40    fn check_sequence(&self, _sequence: i32) -> Result<bool> {
41        Err(Error::IllegalState("Illegal transaction check".to_string()))
42    }
43}
44
45/// Checks that external values in a script are correct for a specific transaction spend
46pub struct TransactionChecker<'a> {
47    /// Spending transaction
48    pub tx: &'a Tx,
49    /// Cache for intermediate sighash values
50    pub sig_hash_cache: &'a mut SigHashCache,
51    /// Spending input for the script
52    pub input: usize,
53    /// Amount being spent
54    pub amount: Amount,
55    /// True if the signature must have SIGHASH_FORKID present, false if not
56    pub require_sighash_forkid: bool,
57}
58
59impl<'a> Checker for TransactionChecker<'a> {
60    fn check_sig(&mut self, sig: &[u8], pubkey: &[u8], script: &[u8]) -> Result<bool> {
61        if sig.len() < 1 {
62            return Err(Error::ScriptError("Signature too short".to_string()));
63        }
64        let sighash_type = sig[sig.len() - 1];
65        if self.require_sighash_forkid && sighash_type & SIGHASH_FORKID == 0 {
66            return Err(Error::ScriptError("SIGHASH_FORKID not present".to_string()));
67        }
68        let sig_hash = sighash(
69            self.tx,
70            self.input,
71            script,
72            self.amount,
73            sighash_type,
74            self.sig_hash_cache,
75        )?;
76        let der_sig = &sig[0..sig.len() - 1];
77        let secp = Secp256k1::verification_only();
78        let mut signature = Signature::from_der(der_sig)?;
79        // OpenSSL-generated signatures may not be normalized, but libsecp256kq requires them to be
80        signature.normalize_s();
81        let message = Message::from_slice(&sig_hash.0)?;
82        let public_key = PublicKey::from_slice(&pubkey)?;
83        Ok(secp.verify(&message, &signature, &public_key).is_ok())
84    }
85
86    fn check_locktime(&self, locktime: i32) -> Result<bool> {
87        if locktime < 0 {
88            return Err(Error::ScriptError("locktime negative".to_string()));
89        }
90        if (locktime >= LOCKTIME_THRESHOLD && (self.tx.lock_time as i32) < LOCKTIME_THRESHOLD)
91            || (locktime < LOCKTIME_THRESHOLD && (self.tx.lock_time as i32) >= LOCKTIME_THRESHOLD)
92        {
93            return Err(Error::ScriptError("locktime types different".to_string()));
94        }
95        if locktime > self.tx.lock_time as i32 {
96            return Err(Error::ScriptError("locktime greater than tx".to_string()));
97        }
98        if self.tx.inputs[self.input].sequence == 0xffffffff {
99            return Err(Error::ScriptError("sequence is 0xffffffff".to_string()));
100        }
101        Ok(true)
102    }
103
104    fn check_sequence(&self, sequence: i32) -> Result<bool> {
105        if sequence < 0 {
106            return Err(Error::ScriptError("sequence negative".to_string()));
107        }
108        let sequence = sequence as u32;
109        if sequence & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
110            return Ok(true);
111        }
112        if self.tx.version < 2 {
113            return Err(Error::ScriptError("tx version less than 2".to_string()));
114        }
115        if self.tx.inputs[self.input].sequence & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
116            let msg = "tx sequence disable flag set".to_string();
117            return Err(Error::ScriptError(msg));
118        }
119        let sequence_masked = sequence & 0x0000ffff;
120        let tx_sequence_masked = self.tx.inputs[self.input].sequence & 0x0000ffff;
121        if (sequence_masked < SEQUENCE_LOCKTIME_TYPE_FLAG
122            && tx_sequence_masked >= SEQUENCE_LOCKTIME_TYPE_FLAG)
123            || (sequence_masked >= SEQUENCE_LOCKTIME_TYPE_FLAG
124                && sequence_masked < SEQUENCE_LOCKTIME_TYPE_FLAG)
125        {
126            let msg = "sequence types different".to_string();
127            return Err(Error::ScriptError(msg));
128        }
129        if sequence_masked > tx_sequence_masked {
130            let msg = "sequence greater than tx".to_string();
131            return Err(Error::ScriptError(msg));
132        }
133        Ok(true)
134    }
135}
136
137#[cfg(test)]
138mod tests {
139    use super::*;
140    use messages::{OutPoint, TxIn, TxOut};
141    use script::op_codes::*;
142    use script::Script;
143    use secp256k1::{PublicKey, Secp256k1, SecretKey};
144    use transaction::generate_signature;
145    use transaction::sighash::{
146        SIGHASH_ALL, SIGHASH_ANYONECANPAY, SIGHASH_FORKID, SIGHASH_NONE, SIGHASH_SINGLE,
147    };
148    use util::{hash160, Hash256};
149
150    #[test]
151    fn standard_p2pkh() {
152        standard_p2pkh_test(SIGHASH_ALL);
153        standard_p2pkh_test(SIGHASH_ALL | SIGHASH_FORKID);
154    }
155
156    fn standard_p2pkh_test(sighash_type: u8) {
157        let secp = Secp256k1::new();
158        let private_key = [1; 32];
159        let secret_key = SecretKey::from_slice(&private_key).unwrap();
160        let pk = PublicKey::from_secret_key(&secp, &secret_key).serialize();
161        let pkh = hash160(&pk);
162
163        let mut pk_script = Script::new();
164        pk_script.append(OP_DUP);
165        pk_script.append(OP_HASH160);
166        pk_script.append_data(&pkh.0);
167        pk_script.append(OP_EQUALVERIFY);
168        pk_script.append(OP_CHECKSIG);
169
170        let tx_1 = Tx {
171            version: 1,
172            inputs: vec![],
173            outputs: vec![TxOut {
174                amount: Amount(10),
175                pk_script,
176            }],
177            lock_time: 0,
178        };
179
180        let mut tx_2 = Tx {
181            version: 1,
182            inputs: vec![TxIn {
183                prev_output: OutPoint {
184                    hash: tx_1.hash(),
185                    index: 0,
186                },
187                sig_script: Script(vec![]),
188                sequence: 0xffffffff,
189            }],
190            outputs: vec![],
191            lock_time: 0,
192        };
193
194        let mut cache = SigHashCache::new();
195        let pk_script = &tx_1.outputs[0].pk_script.0;
196        let sig_hash = sighash(&tx_2, 0, pk_script, Amount(10), sighash_type, &mut cache).unwrap();
197        let sig = generate_signature(&private_key, &sig_hash, sighash_type).unwrap();
198
199        let mut sig_script = Script::new();
200        sig_script.append_data(&sig);
201        sig_script.append_data(&pk);
202        tx_2.inputs[0].sig_script = sig_script;
203
204        let mut cache = SigHashCache::new();
205        let mut c = TransactionChecker {
206            tx: &tx_2,
207            sig_hash_cache: &mut cache,
208            input: 0,
209            amount: Amount(10),
210            require_sighash_forkid: false,
211        };
212
213        let mut script = Script::new();
214        script.append_slice(&tx_2.inputs[0].sig_script.0);
215        script.append(OP_CODESEPARATOR);
216        script.append_slice(&tx_1.outputs[0].pk_script.0);
217        assert!(script.eval(&mut c).is_ok());
218    }
219
220    #[test]
221    fn multisig() {
222        multisig_test(SIGHASH_ALL);
223        multisig_test(SIGHASH_ALL | SIGHASH_FORKID);
224    }
225
226    fn multisig_test(sighash_type: u8) {
227        let secp = Secp256k1::new();
228        let private_key1 = [1; 32];
229        let private_key2 = [2; 32];
230        let private_key3 = [3; 32];
231        let secret_key1 = SecretKey::from_slice(&private_key1).unwrap();
232        let secret_key2 = SecretKey::from_slice(&private_key2).unwrap();
233        let secret_key3 = SecretKey::from_slice(&private_key3).unwrap();
234        let pk1 = PublicKey::from_secret_key(&secp, &secret_key1).serialize();
235        let pk2 = PublicKey::from_secret_key(&secp, &secret_key2).serialize();
236        let pk3 = PublicKey::from_secret_key(&secp, &secret_key3).serialize();
237
238        let mut pk_script = Script::new();
239        pk_script.append(OP_2);
240        pk_script.append_data(&pk1);
241        pk_script.append_data(&pk2);
242        pk_script.append_data(&pk3);
243        pk_script.append(OP_3);
244        pk_script.append(OP_CHECKMULTISIG);
245
246        let tx_1 = Tx {
247            version: 1,
248            inputs: vec![],
249            outputs: vec![TxOut {
250                amount: Amount(10),
251                pk_script,
252            }],
253            lock_time: 0,
254        };
255
256        let mut tx_2 = Tx {
257            version: 1,
258            inputs: vec![TxIn {
259                prev_output: OutPoint {
260                    hash: tx_1.hash(),
261                    index: 0,
262                },
263                sig_script: Script(vec![]),
264                sequence: 0xffffffff,
265            }],
266            outputs: vec![],
267            lock_time: 0,
268        };
269
270        let mut cache = SigHashCache::new();
271        let pk_script = &tx_1.outputs[0].pk_script.0;
272        let sig_hash = sighash(&tx_2, 0, pk_script, Amount(10), sighash_type, &mut cache).unwrap();
273        let sig1 = generate_signature(&private_key1, &sig_hash, sighash_type).unwrap();
274        let sig3 = generate_signature(&private_key3, &sig_hash, sighash_type).unwrap();
275
276        let mut sig_script = Script::new();
277        sig_script.append(OP_0);
278        sig_script.append_data(&sig1);
279        sig_script.append_data(&sig3);
280        tx_2.inputs[0].sig_script = sig_script;
281
282        let mut cache = SigHashCache::new();
283        let mut c = TransactionChecker {
284            tx: &tx_2,
285            sig_hash_cache: &mut cache,
286            input: 0,
287            amount: Amount(10),
288            require_sighash_forkid: false,
289        };
290
291        let mut script = Script::new();
292        script.append_slice(&tx_2.inputs[0].sig_script.0);
293        script.append(OP_CODESEPARATOR);
294        script.append_slice(&tx_1.outputs[0].pk_script.0);
295        assert!(script.eval(&mut c).is_ok());
296    }
297
298    #[test]
299    fn blank_check() {
300        blank_check_test(SIGHASH_NONE | SIGHASH_ANYONECANPAY);
301        blank_check_test(SIGHASH_NONE | SIGHASH_ANYONECANPAY | SIGHASH_FORKID);
302    }
303
304    fn blank_check_test(sighash_type: u8) {
305        let secp = Secp256k1::new();
306
307        let private_key1 = [1; 32];
308        let secret_key1 = SecretKey::from_slice(&private_key1).unwrap();
309        let pk1 = PublicKey::from_secret_key(&secp, &secret_key1).serialize();
310        let pkh1 = hash160(&pk1);
311
312        let private_key2 = [2; 32];
313        let secret_key2 = SecretKey::from_slice(&private_key2).unwrap();
314        let pk2 = PublicKey::from_secret_key(&secp, &secret_key2).serialize();
315        let pkh2 = hash160(&pk2);
316
317        let mut pk_script1 = Script::new();
318        pk_script1.append(OP_DUP);
319        pk_script1.append(OP_HASH160);
320        pk_script1.append_data(&pkh1.0);
321        pk_script1.append(OP_EQUALVERIFY);
322        pk_script1.append(OP_CHECKSIG);
323
324        let mut pk_script2 = Script::new();
325        pk_script2.append(OP_DUP);
326        pk_script2.append(OP_HASH160);
327        pk_script2.append_data(&pkh2.0);
328        pk_script2.append(OP_EQUALVERIFY);
329        pk_script2.append(OP_CHECKSIG);
330
331        let tx_1 = Tx {
332            version: 1,
333            inputs: vec![],
334            outputs: vec![
335                TxOut {
336                    amount: Amount(10),
337                    pk_script: pk_script1,
338                },
339                TxOut {
340                    amount: Amount(20),
341                    pk_script: pk_script2,
342                },
343            ],
344            lock_time: 0,
345        };
346
347        let mut tx_2 = Tx {
348            version: 1,
349            inputs: vec![TxIn {
350                prev_output: OutPoint {
351                    hash: tx_1.hash(),
352                    index: 0,
353                },
354                sig_script: Script(vec![]),
355                sequence: 0xffffffff,
356            }],
357            outputs: vec![],
358            lock_time: 0,
359        };
360
361        // Sign the first input
362
363        let mut cache = SigHashCache::new();
364        let pk_script = &tx_1.outputs[0].pk_script.0;
365        let sig_hash1 = sighash(&tx_2, 0, pk_script, Amount(10), sighash_type, &mut cache).unwrap();
366        let sig1 = generate_signature(&private_key1, &sig_hash1, sighash_type).unwrap();
367
368        let mut sig_script1 = Script::new();
369        sig_script1.append_data(&sig1);
370        sig_script1.append_data(&pk1);
371        tx_2.inputs[0].sig_script = sig_script1;
372
373        // Add another input and sign that separately
374
375        tx_2.inputs.push(TxIn {
376            prev_output: OutPoint {
377                hash: tx_1.hash(),
378                index: 1,
379            },
380            sig_script: Script(vec![]),
381            sequence: 0xffffffff,
382        });
383
384        let mut cache = SigHashCache::new();
385        let pk_script = &tx_1.outputs[1].pk_script.0;
386
387        let sig_hash2 = sighash(&tx_2, 1, pk_script, Amount(20), sighash_type, &mut cache).unwrap();
388        let sig2 = generate_signature(&private_key2, &sig_hash2, sighash_type).unwrap();
389
390        let mut sig_script2 = Script::new();
391        sig_script2.append_data(&sig2);
392        sig_script2.append_data(&pk2);
393        tx_2.inputs[1].sig_script = sig_script2;
394
395        let mut cache = SigHashCache::new();
396        let mut c1 = TransactionChecker {
397            tx: &tx_2,
398            sig_hash_cache: &mut cache,
399            input: 0,
400            amount: Amount(10),
401            require_sighash_forkid: false,
402        };
403
404        let mut script1 = Script::new();
405        script1.append_slice(&tx_2.inputs[0].sig_script.0);
406        script1.append(OP_CODESEPARATOR);
407        script1.append_slice(&tx_1.outputs[0].pk_script.0);
408        assert!(script1.eval(&mut c1).is_ok());
409
410        let mut cache = SigHashCache::new();
411        let mut c2 = TransactionChecker {
412            tx: &tx_2,
413            sig_hash_cache: &mut cache,
414            input: 1,
415            amount: Amount(20),
416            require_sighash_forkid: false,
417        };
418
419        let mut script2 = Script::new();
420        script2.append_slice(&tx_2.inputs[1].sig_script.0);
421        script2.append(OP_CODESEPARATOR);
422        script2.append_slice(&tx_1.outputs[1].pk_script.0);
423        assert!(script2.eval(&mut c2).is_ok());
424    }
425
426    #[test]
427    fn batch() {
428        batch_test(SIGHASH_SINGLE | SIGHASH_ANYONECANPAY);
429        batch_test(SIGHASH_SINGLE | SIGHASH_ANYONECANPAY | SIGHASH_FORKID);
430    }
431
432    fn batch_test(sighash_type: u8) {
433        let secp = Secp256k1::new();
434
435        let private_key1 = [1; 32];
436        let secret_key1 = SecretKey::from_slice(&private_key1).unwrap();
437        let pk1 = PublicKey::from_secret_key(&secp, &secret_key1).serialize();
438        let pkh1 = hash160(&pk1);
439
440        let private_key2 = [2; 32];
441        let secret_key2 = SecretKey::from_slice(&private_key2).unwrap();
442        let pk2 = PublicKey::from_secret_key(&secp, &secret_key2).serialize();
443        let pkh2 = hash160(&pk2);
444
445        let mut pk_script1 = Script::new();
446        pk_script1.append(OP_DUP);
447        pk_script1.append(OP_HASH160);
448        pk_script1.append_data(&pkh1.0);
449        pk_script1.append(OP_EQUALVERIFY);
450        pk_script1.append(OP_CHECKSIG);
451
452        let mut pk_script2 = Script::new();
453        pk_script2.append(OP_DUP);
454        pk_script2.append(OP_HASH160);
455        pk_script2.append_data(&pkh2.0);
456        pk_script2.append(OP_EQUALVERIFY);
457        pk_script2.append(OP_CHECKSIG);
458
459        let tx_1 = Tx {
460            version: 1,
461            inputs: vec![],
462            outputs: vec![
463                TxOut {
464                    amount: Amount(10),
465                    pk_script: pk_script1.clone(),
466                },
467                TxOut {
468                    amount: Amount(20),
469                    pk_script: pk_script2.clone(),
470                },
471            ],
472            lock_time: 0,
473        };
474
475        let mut tx_2 = Tx {
476            version: 1,
477            inputs: vec![TxIn {
478                prev_output: OutPoint {
479                    hash: tx_1.hash(),
480                    index: 0,
481                },
482                sig_script: Script(vec![]),
483                sequence: 0xffffffff,
484            }],
485            outputs: vec![TxOut {
486                amount: Amount(10),
487                pk_script: pk_script1.clone(),
488            }],
489            lock_time: 0,
490        };
491
492        // Sign the first input and output
493
494        let mut cache = SigHashCache::new();
495        let pk_script = &tx_1.outputs[0].pk_script.0;
496        let sig_hash1 = sighash(&tx_2, 0, pk_script, Amount(10), sighash_type, &mut cache).unwrap();
497        let sig1 = generate_signature(&private_key1, &sig_hash1, sighash_type).unwrap();
498
499        let mut sig_script1 = Script::new();
500        sig_script1.append_data(&sig1);
501        sig_script1.append_data(&pk1);
502        tx_2.inputs[0].sig_script = sig_script1;
503
504        // Add another input and output and sign that separately
505
506        tx_2.inputs.push(TxIn {
507            prev_output: OutPoint {
508                hash: tx_1.hash(),
509                index: 1,
510            },
511            sig_script: Script(vec![]),
512            sequence: 0xffffffff,
513        });
514        tx_2.outputs.push(TxOut {
515            amount: Amount(20),
516            pk_script: pk_script2.clone(),
517        });
518
519        let mut cache = SigHashCache::new();
520        let sig_hash2 = sighash(
521            &tx_2,
522            1,
523            &tx_1.outputs[1].pk_script.0,
524            Amount(20),
525            sighash_type,
526            &mut cache,
527        )
528        .unwrap();
529        let sig2 = generate_signature(&private_key2, &sig_hash2, sighash_type).unwrap();
530
531        let mut sig_script2 = Script::new();
532        sig_script2.append_data(&sig2);
533        sig_script2.append_data(&pk2);
534        tx_2.inputs[1].sig_script = sig_script2;
535
536        let mut cache = SigHashCache::new();
537        let mut c1 = TransactionChecker {
538            tx: &tx_2,
539            sig_hash_cache: &mut cache,
540            input: 0,
541            amount: Amount(10),
542            require_sighash_forkid: false,
543        };
544
545        let mut script1 = Script::new();
546        script1.append_slice(&tx_2.inputs[0].sig_script.0);
547        script1.append(OP_CODESEPARATOR);
548        script1.append_slice(&tx_1.outputs[0].pk_script.0);
549        assert!(script1.eval(&mut c1).is_ok());
550
551        let mut cache = SigHashCache::new();
552        let mut c2 = TransactionChecker {
553            tx: &tx_2,
554            sig_hash_cache: &mut cache,
555            input: 1,
556            amount: Amount(20),
557            require_sighash_forkid: false,
558        };
559
560        let mut script2 = Script::new();
561        script2.append_slice(&tx_2.inputs[1].sig_script.0);
562        script2.append(OP_CODESEPARATOR);
563        script2.append_slice(&tx_1.outputs[1].pk_script.0);
564        assert!(script2.eval(&mut c2).is_ok());
565    }
566
567    #[test]
568    fn check_locktime() {
569        let mut pk_script = Script::new();
570        pk_script.append_num(500).unwrap();
571        pk_script.append(OP_CHECKLOCKTIMEVERIFY);
572        pk_script.append(OP_1);
573        let mut tx = Tx {
574            version: 1,
575            inputs: vec![TxIn {
576                prev_output: OutPoint {
577                    hash: Hash256([0; 32]),
578                    index: 0,
579                },
580                sig_script: Script(vec![]),
581                sequence: 0,
582            }],
583            outputs: vec![],
584            lock_time: 499,
585        };
586        {
587            let mut cache = SigHashCache::new();
588            let mut c = TransactionChecker {
589                tx: &tx,
590                sig_hash_cache: &mut cache,
591                input: 0,
592                amount: Amount(0),
593                require_sighash_forkid: false,
594            };
595            assert!(pk_script.eval(&mut c).is_err());
596        }
597        {
598            tx.lock_time = 500;
599            let mut cache = SigHashCache::new();
600            let mut c = TransactionChecker {
601                tx: &tx,
602                sig_hash_cache: &mut cache,
603                input: 0,
604                amount: Amount(0),
605                require_sighash_forkid: false,
606            };
607            assert!(pk_script.eval(&mut c).is_ok());
608        }
609    }
610
611    #[test]
612    fn check_sequence() {
613        let mut pk_script = Script::new();
614        pk_script
615            .append_num(500 | SEQUENCE_LOCKTIME_TYPE_FLAG as i32)
616            .unwrap();
617        pk_script.append(OP_CHECKSEQUENCEVERIFY);
618        pk_script.append(OP_1);
619        let mut tx = Tx {
620            version: 2,
621            inputs: vec![TxIn {
622                prev_output: OutPoint {
623                    hash: Hash256([0; 32]),
624                    index: 0,
625                },
626                sig_script: Script(vec![]),
627                sequence: 499 | SEQUENCE_LOCKTIME_TYPE_FLAG,
628            }],
629            outputs: vec![],
630            lock_time: 0,
631        };
632        {
633            let mut cache = SigHashCache::new();
634            let mut c = TransactionChecker {
635                tx: &tx,
636                sig_hash_cache: &mut cache,
637                input: 0,
638                amount: Amount(0),
639                require_sighash_forkid: false,
640            };
641            assert!(pk_script.eval(&mut c).is_err());
642        }
643        {
644            tx.inputs[0].sequence = 500 | SEQUENCE_LOCKTIME_TYPE_FLAG;
645            let mut cache = SigHashCache::new();
646            let mut c = TransactionChecker {
647                tx: &tx,
648                sig_hash_cache: &mut cache,
649                input: 0,
650                amount: Amount(0),
651                require_sighash_forkid: false,
652            };
653            assert!(pk_script.eval(&mut c).is_ok());
654        }
655    }
656}