1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use keys::{Public, Signature, Message};
use chain::constants::{
SEQUENCE_FINAL, SEQUENCE_LOCKTIME_DISABLE_FLAG,
SEQUENCE_LOCKTIME_MASK, SEQUENCE_LOCKTIME_TYPE_FLAG, LOCKTIME_THRESHOLD
};
use sign::SignatureVersion;
use {Script, TransactionInputSigner, Num};
pub trait SignatureChecker {
fn verify_signature(
&self,
signature: &Signature,
public: &Public,
hash: &Message,
) -> bool;
fn check_signature(
&self,
signature: &Signature,
public: &Public,
script_code: &Script,
sighashtype: u32,
version: SignatureVersion
) -> bool;
fn check_lock_time(&self, lock_time: Num) -> bool;
fn check_sequence(&self, sequence: Num) -> bool;
}
pub struct NoopSignatureChecker;
impl SignatureChecker for NoopSignatureChecker {
fn verify_signature(&self, signature: &Signature, public: &Public, hash: &Message) -> bool {
public.verify(hash, signature).unwrap_or(false)
}
fn check_signature(&self, _: &Signature, _: &Public, _: &Script, _: u32, _: SignatureVersion) -> bool {
false
}
fn check_lock_time(&self, _: Num) -> bool {
false
}
fn check_sequence(&self, _: Num) -> bool {
false
}
}
#[derive(Debug)]
pub struct TransactionSignatureChecker {
pub signer: TransactionInputSigner,
pub input_index: usize,
pub input_amount: u64,
}
impl SignatureChecker for TransactionSignatureChecker {
fn verify_signature(
&self,
signature: &Signature,
public: &Public,
hash: &Message,
) -> bool {
public.verify(hash, signature).unwrap_or(false)
}
fn check_signature(
&self,
signature: &Signature,
public: &Public,
script_code: &Script,
sighashtype: u32,
version: SignatureVersion
) -> bool {
let hash = self.signer.signature_hash(self.input_index, self.input_amount, script_code, version, sighashtype);
self.verify_signature(signature, public, &hash)
}
fn check_lock_time(&self, lock_time: Num) -> bool {
let lock_time_u32: u32 = lock_time.into();
if !(
(self.signer.lock_time < LOCKTIME_THRESHOLD && lock_time_u32 < LOCKTIME_THRESHOLD) ||
(self.signer.lock_time >= LOCKTIME_THRESHOLD && lock_time_u32 >= LOCKTIME_THRESHOLD)
) {
return false;
}
if i64::from(lock_time) > self.signer.lock_time as i64 {
return false;
}
SEQUENCE_FINAL != self.signer.inputs[self.input_index].sequence
}
fn check_sequence(&self, sequence: Num) -> bool {
let to_sequence: i64 = self.signer.inputs[self.input_index].sequence as i64;
if (self.signer.version as u32) < 2 {
return false;
}
if to_sequence & SEQUENCE_LOCKTIME_DISABLE_FLAG as i64 != 0 {
return false;
}
let locktime_mask: u32 = SEQUENCE_LOCKTIME_TYPE_FLAG | SEQUENCE_LOCKTIME_MASK;
let to_sequence_masked: i64 = to_sequence & locktime_mask as i64;
let sequence_masked: i64 = i64::from(sequence) & locktime_mask as i64;
if !(
(to_sequence_masked < SEQUENCE_LOCKTIME_TYPE_FLAG as i64 && sequence_masked < SEQUENCE_LOCKTIME_TYPE_FLAG as i64) ||
(to_sequence_masked >= SEQUENCE_LOCKTIME_TYPE_FLAG as i64 && sequence_masked >= SEQUENCE_LOCKTIME_TYPE_FLAG as i64)
) {
return false;
}
sequence_masked <= to_sequence_masked
}
}