bitcoinrb 0.0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bitcoinrb.gemspec +1 -0
- data/lib/bitcoin/connection.rb +7 -5
- data/lib/bitcoin/constants.rb +157 -0
- data/lib/bitcoin/key.rb +15 -3
- data/lib/bitcoin/message/base.rb +0 -12
- data/lib/bitcoin/message/handler.rb +27 -14
- data/lib/bitcoin/message/version.rb +1 -1
- data/lib/bitcoin/message.rb +10 -1
- data/lib/bitcoin/opcodes.rb +2 -2
- data/lib/bitcoin/out_point.rb +5 -1
- data/lib/bitcoin/script/script.rb +117 -38
- data/lib/bitcoin/script/script_error.rb +0 -61
- data/lib/bitcoin/script/script_interpreter.rb +164 -154
- data/lib/bitcoin/script/tx_checker.rb +48 -12
- data/lib/bitcoin/secp256k1/native.rb +139 -5
- data/lib/bitcoin/secp256k1/ruby.rb +2 -13
- data/lib/bitcoin/tx.rb +115 -18
- data/lib/bitcoin/tx_in.rb +23 -4
- data/lib/bitcoin/tx_out.rb +1 -1
- data/lib/bitcoin/validation.rb +93 -0
- data/lib/bitcoin/version.rb +1 -1
- data/lib/bitcoin.rb +31 -2
- metadata +19 -3
@@ -1,29 +1,9 @@
|
|
1
1
|
module Bitcoin
|
2
2
|
|
3
|
-
SCRIPT_VERIFY_NONE = 0
|
4
|
-
SCRIPT_VERIFY_P2SH = (1 << 0)
|
5
|
-
SCRIPT_VERIFY_STRICTENC = (1 << 1)
|
6
|
-
SCRIPT_VERIFY_DERSIG = (1 << 2)
|
7
|
-
SCRIPT_VERIFY_LOW_S = (1 << 3)
|
8
|
-
SCRIPT_VERIFY_NULLDUMMY = (1 << 4)
|
9
|
-
SCRIPT_VERIFY_SIGPUSHONLY = (1 << 5)
|
10
|
-
SCRIPT_VERIFY_MINIMALDATA = (1 << 6)
|
11
|
-
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1 << 7)
|
12
|
-
SCRIPT_VERIFY_CLEANSTACK = (1 << 8)
|
13
|
-
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1 << 9) # Verify CHECKLOCKTIMEVERIFY (BIP-65)
|
14
|
-
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1 << 10) # support CHECKSEQUENCEVERIFY opcode (BIP-112)
|
15
|
-
SCRIPT_VERIFY_WITNESS = (1 << 11) # Support segregated witness
|
16
|
-
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM = (1 << 12) # Making v1-v16 witness program non-standard
|
17
|
-
SCRIPT_VERIFY_MINIMALIF = (1 << 13) # Segwit script only: Require the argument of OP_IF/NOTIF to be exactly 0x01 or empty vector
|
18
|
-
SCRIPT_VERIFY_NULLFAIL = (1 << 14) # Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed
|
19
|
-
SCRIPT_VERIFY_WITNESS_PUBKEYTYPE = (1 << 15) # Public keys in segregated witness scripts must be compressed
|
20
|
-
|
21
3
|
class ScriptInterpreter
|
22
4
|
|
23
5
|
include Bitcoin::Opcodes
|
24
6
|
|
25
|
-
SIG_VERSION = {base: 0, witness_v0: 1}
|
26
|
-
|
27
7
|
attr_reader :stack
|
28
8
|
attr_reader :debug
|
29
9
|
attr_reader :flags
|
@@ -46,25 +26,25 @@ module Bitcoin
|
|
46
26
|
# @param [Bitcoin::Script] script_pubkey a script pubkey (locking script)
|
47
27
|
# @param [Bitcoin::ScriptWitness] witness a witness script
|
48
28
|
# @return [Boolean] result
|
49
|
-
def
|
29
|
+
def verify_script(script_sig, script_pubkey, witness = ScriptWitness.new)
|
50
30
|
|
51
|
-
return set_error(
|
31
|
+
return set_error(SCRIPT_ERR_SIG_PUSHONLY) if flag?(SCRIPT_VERIFY_SIGPUSHONLY) && !script_sig.push_only?
|
52
32
|
|
53
33
|
stack_copy = nil
|
54
34
|
had_witness = false
|
55
35
|
|
56
|
-
return false unless eval_script(script_sig,
|
36
|
+
return false unless eval_script(script_sig, :base)
|
57
37
|
|
58
38
|
stack_copy = stack.dup if flag?(SCRIPT_VERIFY_P2SH)
|
59
39
|
|
60
|
-
return false unless eval_script(script_pubkey,
|
40
|
+
return false unless eval_script(script_pubkey, :base)
|
61
41
|
|
62
|
-
return set_error(
|
42
|
+
return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last.htb)
|
63
43
|
|
64
44
|
# Bare witness programs
|
65
45
|
if flag?(SCRIPT_VERIFY_WITNESS) && script_pubkey.witness_program?
|
66
46
|
had_witness = true
|
67
|
-
return set_error(
|
47
|
+
return set_error(SCRIPT_ERR_WITNESS_MALLEATED) unless script_sig.size == 0
|
68
48
|
version, program = script_pubkey.witness_data
|
69
49
|
stack_copy = stack.dup
|
70
50
|
return false unless verify_witness_program(witness, version, program)
|
@@ -72,23 +52,23 @@ module Bitcoin
|
|
72
52
|
|
73
53
|
# Additional validation for spend-to-script-hash transactions
|
74
54
|
if flag?(SCRIPT_VERIFY_P2SH) && script_pubkey.p2sh?
|
75
|
-
return set_error(
|
55
|
+
return set_error(SCRIPT_ERR_SIG_PUSHONLY) unless script_sig.push_only?
|
76
56
|
tmp = stack
|
77
57
|
@stack = stack_copy
|
78
58
|
raise 'stack cannot be empty.' if stack.empty?
|
79
59
|
begin
|
80
60
|
redeem_script = Bitcoin::Script.parse_from_payload(stack.pop.htb)
|
81
61
|
rescue Exception => e
|
82
|
-
return set_error(
|
62
|
+
return set_error(SCRIPT_ERR_BAD_OPCODE, "Failed to parse serialized redeem script for P2SH. #{e.message}")
|
83
63
|
end
|
84
|
-
return false unless eval_script(redeem_script,
|
85
|
-
return set_error(
|
64
|
+
return false unless eval_script(redeem_script, :base)
|
65
|
+
return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last)
|
86
66
|
|
87
67
|
# P2SH witness program
|
88
68
|
if flag?(SCRIPT_VERIFY_WITNESS) && redeem_script.witness_program?
|
89
69
|
had_witness = true
|
90
70
|
# The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we reintroduce malleability.
|
91
|
-
return set_error(
|
71
|
+
return set_error(SCRIPT_ERR_WITNESS_MALLEATED_P2SH) unless script_sig == (Bitcoin::Script.new << redeem_script.to_payload.bth)
|
92
72
|
|
93
73
|
version, program = redeem_script.witness_data
|
94
74
|
return false unless verify_witness_program(witness, version, program)
|
@@ -102,12 +82,12 @@ module Bitcoin
|
|
102
82
|
# Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK would be possible,
|
103
83
|
# which is not a softfork (and P2SH should be one).
|
104
84
|
raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
|
105
|
-
return set_error(
|
85
|
+
return set_error(SCRIPT_ERR_CLEANSTACK) unless stack.size == 1
|
106
86
|
end
|
107
87
|
|
108
88
|
if flag?(SCRIPT_VERIFY_WITNESS)
|
109
89
|
raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
|
110
|
-
return set_error(
|
90
|
+
return set_error(SCRIPT_ERR_WITNESS_UNEXPECTED) if !had_witness && !witness.empty?
|
111
91
|
end
|
112
92
|
|
113
93
|
true
|
@@ -118,44 +98,40 @@ module Bitcoin
|
|
118
98
|
false
|
119
99
|
end
|
120
100
|
|
121
|
-
def verify_sig
|
122
|
-
|
123
|
-
end
|
124
|
-
|
125
101
|
def verify_witness_program(witness, version, program)
|
126
102
|
if version == 0
|
127
103
|
if program.bytesize == 32
|
128
|
-
return set_error(
|
104
|
+
return set_error(SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY) if witness.stack.size == 0
|
129
105
|
script_pubkey = Bitcoin::Script.parse_from_payload(witness.stack.last)
|
130
|
-
@stack = witness.stack[0..-2]
|
106
|
+
@stack = witness.stack[0..-2].map{|w|w.bth}
|
131
107
|
script_hash = Bitcoin.sha256(script_pubkey.to_payload)
|
132
|
-
return set_error(
|
108
|
+
return set_error(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH) unless script_hash == program
|
133
109
|
elsif program.bytesize == 20
|
134
|
-
return set_error(
|
110
|
+
return set_error(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH) unless witness.stack.size == 2
|
135
111
|
script_pubkey = Bitcoin::Script.to_p2pkh(program.bth)
|
136
112
|
@stack = witness.stack.map{|w|w.bth}
|
137
113
|
else
|
138
|
-
return set_error(
|
114
|
+
return set_error(SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH)
|
139
115
|
end
|
140
116
|
elsif flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
|
141
|
-
return set_error(
|
117
|
+
return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
|
142
118
|
else
|
143
119
|
return true # Higher version witness scripts return true for future softfork compatibility
|
144
120
|
end
|
145
121
|
|
146
122
|
stack.each do |s| # Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
|
147
|
-
return set_error(
|
123
|
+
return set_error(SCRIPT_ERR_PUSH_SIZE) if s.htb.bytesize > MAX_SCRIPT_ELEMENT_SIZE
|
148
124
|
end
|
149
125
|
|
150
|
-
return false unless eval_script(script_pubkey,
|
126
|
+
return false unless eval_script(script_pubkey, :witness_v0)
|
151
127
|
|
152
|
-
return set_error(
|
153
|
-
return set_error(
|
128
|
+
return set_error(SCRIPT_ERR_EVAL_FALSE) unless stack.size == 1
|
129
|
+
return set_error(SCRIPT_ERR_EVAL_FALSE) unless cast_to_bool(stack.last)
|
154
130
|
true
|
155
131
|
end
|
156
132
|
|
157
133
|
def eval_script(script, sig_version)
|
158
|
-
return set_error(
|
134
|
+
return set_error(SCRIPT_ERR_SCRIPT_SIZE) if script.size > MAX_SCRIPT_SIZE
|
159
135
|
begin
|
160
136
|
flow_stack = []
|
161
137
|
alt_stack = []
|
@@ -165,21 +141,21 @@ module Bitcoin
|
|
165
141
|
script.chunks.each_with_index do |c, index|
|
166
142
|
need_exec = !flow_stack.include?(false)
|
167
143
|
|
168
|
-
return set_error(
|
144
|
+
return set_error(SCRIPT_ERR_PUSH_SIZE) if c.pushdata? && c.pushed_data.bytesize > MAX_SCRIPT_ELEMENT_SIZE
|
169
145
|
|
170
146
|
opcode = c.opcode
|
171
147
|
|
172
148
|
if need_exec && c.pushdata?
|
173
149
|
if require_minimal && !minimal_push?(c.pushed_data, opcode)
|
174
|
-
return set_error(
|
150
|
+
return set_error(SCRIPT_ERR_MINIMALDATA)
|
175
151
|
end
|
176
|
-
return set_error(
|
152
|
+
return set_error(SCRIPT_ERR_BAD_OPCODE) unless verify_pushdata_length(c)
|
177
153
|
stack << c.pushed_data.bth
|
178
154
|
else
|
179
|
-
if opcode > OP_16 && (op_count += 1) >
|
180
|
-
return set_error(
|
155
|
+
if opcode > OP_16 && (op_count += 1) > MAX_OPS_PER_SCRIPT
|
156
|
+
return set_error(SCRIPT_ERR_OP_COUNT)
|
181
157
|
end
|
182
|
-
return set_error(
|
158
|
+
return set_error(SCRIPT_ERR_DISABLED_OPCODE) if DISABLE_OPCODES.include?(opcode)
|
183
159
|
next unless (need_exec || (OP_IF <= opcode && opcode <= OP_ENDIF))
|
184
160
|
small_int = Opcodes.opcode_to_small_int(opcode)
|
185
161
|
if small_int && opcode != OP_0
|
@@ -191,7 +167,7 @@ module Bitcoin
|
|
191
167
|
when OP_DEPTH
|
192
168
|
push_int(stack.size)
|
193
169
|
when OP_EQUAL, OP_EQUALVERIFY
|
194
|
-
return set_error(
|
170
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
195
171
|
a, b = pop_string(2)
|
196
172
|
result = a == b
|
197
173
|
push_int(result ? 1 : 0)
|
@@ -199,150 +175,181 @@ module Bitcoin
|
|
199
175
|
if result
|
200
176
|
stack.pop
|
201
177
|
else
|
202
|
-
return set_error(
|
178
|
+
return set_error(SCRIPT_ERR_EQUALVERIFY)
|
203
179
|
end
|
204
180
|
end
|
205
181
|
when OP_0NOTEQUAL
|
206
|
-
return set_error(
|
182
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
207
183
|
push_int(pop_int == 0 ? 0 : 1)
|
208
184
|
when OP_ADD
|
209
|
-
return set_error(
|
185
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
210
186
|
a, b = pop_int(2)
|
211
187
|
push_int(a + b)
|
212
188
|
when OP_1ADD
|
213
|
-
return set_error(
|
189
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
214
190
|
push_int(pop_int + 1)
|
215
191
|
when OP_SUB
|
216
|
-
return set_error(
|
192
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
217
193
|
a, b = pop_int(2)
|
218
194
|
push_int(a - b)
|
219
195
|
when OP_1SUB
|
220
|
-
return set_error(
|
196
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
221
197
|
push_int(pop_int - 1)
|
222
198
|
when OP_IF, OP_NOTIF
|
223
199
|
result = false
|
224
200
|
if need_exec
|
225
|
-
return set_error(
|
226
|
-
|
201
|
+
return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if stack.size < 1
|
202
|
+
value = pop_string.htb
|
203
|
+
if sig_version == :witness_v0 && flag?(SCRIPT_VERIFY_MINIMALIF)
|
204
|
+
if value.bytesize > 1 || (value.bytesize == 1 && value[0].unpack('C').first != 1)
|
205
|
+
return set_error(SCRIPT_ERR_MINIMALIF)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
result = cast_to_bool(value)
|
227
209
|
result = !result if opcode == OP_NOTIF
|
228
210
|
end
|
229
211
|
flow_stack << result
|
230
212
|
when OP_ELSE
|
231
|
-
return set_error(
|
213
|
+
return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.size < 1
|
232
214
|
flow_stack << !flow_stack.pop
|
233
215
|
when OP_ENDIF
|
234
|
-
return set_error(
|
216
|
+
return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.empty?
|
235
217
|
flow_stack.pop
|
236
218
|
when OP_NOP
|
237
219
|
when OP_NOP1, OP_NOP4..OP_NOP10
|
238
|
-
return set_error(
|
220
|
+
return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS) if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
|
239
221
|
when OP_CHECKLOCKTIMEVERIFY
|
240
222
|
unless flag?(SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
|
241
|
-
return set_error(
|
223
|
+
return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS) if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
|
242
224
|
next
|
243
225
|
end
|
244
|
-
return set_error(
|
245
|
-
|
246
|
-
|
247
|
-
|
226
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
227
|
+
# Note that elsewhere numeric opcodes are limited to operands in the range -2**31+1 to 2**31-1,
|
228
|
+
# however it is legal for opcodes to produce results exceeding that range.
|
229
|
+
# This limitation is implemented by CScriptNum's default 4-byte limit.
|
230
|
+
# If we kept to that limit we'd have a year 2038 problem,
|
231
|
+
# even though the nLockTime field in transactions themselves is uint32 which only becomes meaningless after the year 2106.
|
232
|
+
# Thus as a special case we tell CScriptNum to accept up to 5-byte bignums,
|
233
|
+
# which are good until 2**39-1, well beyond the 2**32-1 limit of the nLockTime field itself.
|
234
|
+
locktime = cast_to_int(stack.last, 5)
|
235
|
+
return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if locktime < 0
|
236
|
+
return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME) unless checker.check_locktime(locktime)
|
248
237
|
when OP_CHECKSEQUENCEVERIFY
|
249
238
|
unless flag?(SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
|
250
|
-
|
239
|
+
if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
|
240
|
+
return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS)
|
241
|
+
end
|
251
242
|
next
|
252
243
|
end
|
253
|
-
return set_error(
|
254
|
-
|
244
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
245
|
+
|
246
|
+
# nSequence, like nLockTime, is a 32-bit unsigned integer field.
|
247
|
+
# See the comment in CHECKLOCKTIMEVERIFY regarding 5-byte numeric operands.
|
248
|
+
sequence = cast_to_int(stack.last, 5)
|
249
|
+
|
250
|
+
# In the rare event that the argument may be < 0 due to some arithmetic being done first,
|
251
|
+
# you can always use 0 MAX CHECKSEQUENCEVERIFY.
|
252
|
+
return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if sequence < 0
|
253
|
+
|
254
|
+
# To provide for future soft-fork extensibility,
|
255
|
+
# if the operand has the disabled lock-time flag set, CHECKSEQUENCEVERIFY behaves as a NOP.
|
256
|
+
next if (sequence & Bitcoin::TxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0
|
257
|
+
|
258
|
+
# Compare the specified sequence number with the input.
|
259
|
+
unless checker.check_sequence(sequence)
|
260
|
+
return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME)
|
261
|
+
end
|
255
262
|
when OP_DUP
|
256
|
-
return set_error(
|
263
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
257
264
|
stack << stack.last
|
258
265
|
when OP_2DUP
|
259
|
-
return set_error(
|
266
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
260
267
|
2.times { stack << stack[-2] }
|
261
268
|
when OP_3DUP
|
262
|
-
return set_error(
|
269
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
263
270
|
3.times { stack << stack[-3] }
|
264
271
|
when OP_IFDUP
|
265
|
-
return set_error(
|
272
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
266
273
|
stack << stack.last if cast_to_bool(stack.last)
|
267
274
|
when OP_RIPEMD160
|
268
|
-
return set_error(
|
275
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
269
276
|
stack << Digest::RMD160.hexdigest(pop_string.htb)
|
270
277
|
when OP_SHA1
|
271
|
-
return set_error(
|
278
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
272
279
|
stack << Digest::SHA1.hexdigest(pop_string.htb)
|
273
280
|
when OP_SHA256
|
274
|
-
return set_error(
|
281
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
275
282
|
stack << Digest::SHA256.hexdigest(pop_string.htb)
|
276
283
|
when OP_HASH160
|
277
|
-
return set_error(
|
284
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
278
285
|
stack << Bitcoin.hash160(pop_string)
|
279
286
|
when OP_HASH256
|
280
|
-
return set_error(
|
287
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
281
288
|
stack << Bitcoin.double_sha256(pop_string.htb).bth
|
282
289
|
when OP_VERIFY
|
283
|
-
return set_error(
|
284
|
-
return set_error(
|
290
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
291
|
+
return set_error(SCRIPT_ERR_VERIFY) unless pop_bool
|
285
292
|
when OP_TOALTSTACK
|
286
|
-
return set_error(
|
293
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
287
294
|
alt_stack << stack.pop
|
288
295
|
when OP_FROMALTSTACK
|
289
|
-
return set_error(
|
296
|
+
return set_error(SCRIPT_ERR_INVALID_ALTSTACK_OPERATION) if alt_stack.size < 1
|
290
297
|
stack << alt_stack.pop
|
291
298
|
when OP_DROP
|
292
|
-
return set_error(
|
299
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
293
300
|
stack.pop
|
294
301
|
when OP_2DROP
|
295
|
-
return set_error(
|
302
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
296
303
|
2.times { stack.pop }
|
297
304
|
when OP_NIP
|
298
|
-
return set_error(
|
305
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
299
306
|
stack.delete_at(-2)
|
300
307
|
when OP_OVER
|
301
|
-
return set_error(
|
308
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
302
309
|
stack << stack[-2]
|
303
310
|
when OP_2OVER
|
304
|
-
return set_error(
|
311
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
|
305
312
|
2.times { stack << stack[-4]}
|
306
313
|
when OP_PICK, OP_ROLL
|
307
|
-
return set_error(
|
314
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
308
315
|
pos = pop_int
|
309
|
-
return set_error(
|
316
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if pos < 0 || pos >= stack.size
|
310
317
|
stack << stack[-pos - 1]
|
311
318
|
stack.delete_at(-pos - 2) if opcode == OP_ROLL
|
312
319
|
when OP_ROT
|
313
|
-
return set_error(
|
320
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
314
321
|
stack << stack[-3]
|
315
322
|
stack.delete_at(-4)
|
316
323
|
when OP_2ROT
|
317
|
-
return set_error(
|
324
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 6
|
318
325
|
2.times { stack << stack[-6] }
|
319
326
|
2.times { stack.delete_at(-7) }
|
320
327
|
when OP_SWAP
|
321
|
-
return set_error(
|
328
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
322
329
|
tmp = stack.last
|
323
330
|
stack[-1] = stack[-2]
|
324
331
|
stack[-2] = tmp
|
325
332
|
when OP_2SWAP
|
326
|
-
return set_error(
|
333
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
|
327
334
|
2.times {stack << stack[-4]}
|
328
335
|
2.times {stack.delete_at(-5)}
|
329
336
|
when OP_TUCK
|
330
|
-
return set_error(
|
337
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
331
338
|
stack.insert(-3, stack.last)
|
332
339
|
when OP_ABS
|
333
|
-
return set_error(
|
340
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
334
341
|
v = pop_int
|
335
342
|
push_int(v.abs)
|
336
343
|
when OP_BOOLAND
|
337
|
-
return set_error(
|
344
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
338
345
|
a, b = pop_int(2)
|
339
346
|
push_int((!a.zero? && !b.zero?) ? 1 : 0)
|
340
347
|
when OP_BOOLOR
|
341
|
-
return set_error(
|
348
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
342
349
|
a, b = pop_int(2)
|
343
350
|
push_int((!a.zero? || !b.zero?) ? 1 : 0)
|
344
351
|
when OP_NUMEQUAL, OP_NUMEQUALVERIFY
|
345
|
-
return set_error(
|
352
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
346
353
|
a, b = pop_int(2)
|
347
354
|
result = a == b
|
348
355
|
push_int(result ? 1 : 0)
|
@@ -350,53 +357,53 @@ module Bitcoin
|
|
350
357
|
if result
|
351
358
|
stack.pop
|
352
359
|
else
|
353
|
-
return set_error(
|
360
|
+
return set_error(SCRIPT_ERR_NUMEQUALVERIFY)
|
354
361
|
end
|
355
362
|
end
|
356
363
|
when OP_LESSTHAN, OP_LESSTHANOREQUAL
|
357
|
-
return set_error(
|
364
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
358
365
|
a, b = pop_int(2)
|
359
366
|
push_int(a < b ? 1 : 0) if opcode == OP_LESSTHAN
|
360
367
|
push_int(a <= b ? 1 : 0) if opcode == OP_LESSTHANOREQUAL
|
361
368
|
when OP_GREATERTHAN, OP_GREATERTHANOREQUAL
|
362
|
-
return set_error(
|
369
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
363
370
|
a, b = pop_int(2)
|
364
371
|
push_int(a > b ? 1 : 0) if opcode == OP_GREATERTHAN
|
365
372
|
push_int(a >= b ? 1 : 0) if opcode == OP_GREATERTHANOREQUAL
|
366
373
|
when OP_MIN
|
367
|
-
return set_error(
|
374
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
368
375
|
push_int(pop_int(2).min)
|
369
376
|
when OP_MAX
|
370
|
-
return set_error(
|
377
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
371
378
|
push_int(pop_int(2).max)
|
372
379
|
when OP_WITHIN
|
373
|
-
return set_error(
|
380
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
374
381
|
x, a, b = pop_int(3)
|
375
382
|
push_int((a <= x && x < b) ? 1 : 0)
|
376
383
|
when OP_NOT
|
377
|
-
return set_error(
|
384
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
378
385
|
push_int(pop_int == 0 ? 1 : 0)
|
379
386
|
when OP_SIZE
|
380
|
-
return set_error(
|
387
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
381
388
|
item = stack.last
|
382
389
|
item = Bitcoin::Script.encode_number(item) if item.is_a?(Numeric)
|
383
390
|
size = item.htb.bytesize
|
384
391
|
push_int(size)
|
385
392
|
when OP_NEGATE
|
386
|
-
return set_error(
|
393
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
387
394
|
push_int(-pop_int)
|
388
395
|
when OP_NUMNOTEQUAL
|
389
|
-
return set_error(
|
396
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
390
397
|
a, b = pop_int(2)
|
391
398
|
push_int(a == b ? 0 : 1)
|
392
399
|
when OP_CODESEPARATOR
|
393
400
|
last_code_separator_index = index + 1
|
394
401
|
when OP_CHECKSIG, OP_CHECKSIGVERIFY
|
395
|
-
return set_error(
|
402
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
396
403
|
sig, pubkey = pop_string(2)
|
397
404
|
|
398
405
|
subscript = script.subscript(last_code_separator_index..-1)
|
399
|
-
if sig_version ==
|
406
|
+
if sig_version == :base
|
400
407
|
subscript = subscript.find_and_delete(Script.new << sig)
|
401
408
|
end
|
402
409
|
|
@@ -406,7 +413,7 @@ module Bitcoin
|
|
406
413
|
|
407
414
|
# https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki#NULLFAIL
|
408
415
|
if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
|
409
|
-
return set_error(
|
416
|
+
return set_error(SCRIPT_ERR_SIG_NULLFAIL)
|
410
417
|
end
|
411
418
|
|
412
419
|
push_int(success ? 1 : 0)
|
@@ -419,32 +426,32 @@ module Bitcoin
|
|
419
426
|
end
|
420
427
|
end
|
421
428
|
when OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
|
422
|
-
return set_error(
|
429
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
423
430
|
pubkey_count = pop_int
|
424
|
-
unless (0..
|
425
|
-
return set_error(
|
431
|
+
unless (0..MAX_PUBKEYS_PER_MULTISIG).include?(pubkey_count)
|
432
|
+
return set_error(SCRIPT_ERR_PUBKEY_COUNT)
|
426
433
|
end
|
427
434
|
|
428
435
|
op_count += pubkey_count
|
429
|
-
return set_error(
|
436
|
+
return set_error(SCRIPT_ERR_OP_COUNT) if op_count > MAX_OPS_PER_SCRIPT
|
430
437
|
|
431
|
-
return set_error(
|
438
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < pubkey_count
|
432
439
|
|
433
440
|
pubkeys = pop_string(pubkey_count)
|
434
441
|
pubkeys = [pubkeys] if pubkeys.is_a?(String)
|
435
442
|
|
436
|
-
return set_error(
|
443
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
437
444
|
|
438
445
|
sig_count = pop_int
|
439
|
-
return set_error(
|
440
|
-
return set_error(
|
446
|
+
return set_error(SCRIPT_ERR_SIG_COUNT) if sig_count < 0 || sig_count > pubkey_count
|
447
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < (sig_count)
|
441
448
|
|
442
449
|
sigs = pop_string(sig_count)
|
443
450
|
sigs = [sigs] if sigs.is_a?(String)
|
444
451
|
|
445
452
|
subscript = script.subscript(last_code_separator_index..-1)
|
446
453
|
|
447
|
-
if sig_version ==
|
454
|
+
if sig_version == :base
|
448
455
|
sigs.each do |sig|
|
449
456
|
subscript = subscript.find_and_delete(Script.new << sig)
|
450
457
|
end
|
@@ -468,16 +475,16 @@ module Bitcoin
|
|
468
475
|
if !success && flag?(SCRIPT_VERIFY_NULLFAIL)
|
469
476
|
sigs.each do |sig|
|
470
477
|
# If the operation failed, we require that all signatures must be empty vector
|
471
|
-
return set_error(
|
478
|
+
return set_error(SCRIPT_ERR_SIG_NULLFAIL) if sig.bytesize > 0
|
472
479
|
end
|
473
480
|
end
|
474
481
|
|
475
482
|
# A bug causes CHECKMULTISIG to consume one extra argument whose contents were not checked in any way.
|
476
483
|
# Unfortunately this is a potential source of mutability,
|
477
484
|
# so optionally verify it is exactly equal to zero prior to removing it from the stack.
|
478
|
-
return set_error(
|
485
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
479
486
|
if flag?(SCRIPT_VERIFY_NULLDUMMY) && stack[-1].size > 0
|
480
|
-
return set_error(
|
487
|
+
return set_error(SCRIPT_ERR_SIG_NULLDUMMY)
|
481
488
|
end
|
482
489
|
stack.pop
|
483
490
|
|
@@ -486,29 +493,29 @@ module Bitcoin
|
|
486
493
|
if success
|
487
494
|
stack.pop
|
488
495
|
else
|
489
|
-
return set_error(
|
496
|
+
return set_error(SCRIPT_ERR_CHECKMULTISIGVERIFY)
|
490
497
|
end
|
491
498
|
end
|
492
499
|
when OP_RETURN
|
493
|
-
return set_error(
|
500
|
+
return set_error(SCRIPT_ERR_OP_RETURN)
|
494
501
|
else
|
495
|
-
return set_error(
|
502
|
+
return set_error(SCRIPT_ERR_BAD_OPCODE)
|
496
503
|
end
|
497
504
|
end
|
498
505
|
end
|
499
506
|
|
500
507
|
# max stack size check
|
501
|
-
return set_error(
|
508
|
+
return set_error(SCRIPT_ERR_STACK_SIZE) if stack.size + alt_stack.size > MAX_STACK_SIZE
|
502
509
|
end
|
503
510
|
rescue Exception => e
|
504
511
|
puts e
|
505
512
|
puts e.backtrace
|
506
|
-
return set_error(
|
513
|
+
return set_error(SCRIPT_ERR_UNKNOWN_ERROR, e.message)
|
507
514
|
end
|
508
515
|
|
509
|
-
return set_error(
|
516
|
+
return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) unless flow_stack.empty?
|
510
517
|
|
511
|
-
set_error(
|
518
|
+
set_error(SCRIPT_ERR_OK)
|
512
519
|
true
|
513
520
|
end
|
514
521
|
|
@@ -526,17 +533,20 @@ module Bitcoin
|
|
526
533
|
|
527
534
|
# pop the item with the int value for the number specified by +count+ from the stack.
|
528
535
|
def pop_int(count = 1)
|
529
|
-
i = stack.pop(count).map
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
+
i = stack.pop(count).map{ |s| cast_to_int(s) }
|
537
|
+
count == 1 ? i.first : i
|
538
|
+
end
|
539
|
+
|
540
|
+
# cast item to int value.
|
541
|
+
def cast_to_int(s, max_num_size = DEFAULT_MAX_NUM_SIZE)
|
542
|
+
data = s.htb
|
543
|
+
raise '"script number overflow"' if data.bytesize > max_num_size
|
544
|
+
if require_minimal && data.bytesize > 0
|
545
|
+
if data.bytes[-1] & 0x7f == 0 && (data.bytesize <= 1 || data.bytes[data.bytesize - 2] & 0x80 == 0)
|
546
|
+
raise 'non-minimally encoded script number'
|
536
547
|
end
|
537
|
-
Script.decode_number(s)
|
538
548
|
end
|
539
|
-
|
549
|
+
Script.decode_number(s)
|
540
550
|
end
|
541
551
|
|
542
552
|
# push +i+ into stack as encoded by Script#encode_number
|
@@ -569,7 +579,7 @@ module Bitcoin
|
|
569
579
|
return v != 0
|
570
580
|
when String
|
571
581
|
v.each_byte.with_index do |b, i|
|
572
|
-
return !(i == (v.bytesize - 1) && b == 0x80)
|
582
|
+
return !(i == (v.bytesize - 1) && b == 0x80) unless b == 0
|
573
583
|
end
|
574
584
|
false
|
575
585
|
else
|
@@ -580,11 +590,11 @@ module Bitcoin
|
|
580
590
|
def check_signature_encoding(sig)
|
581
591
|
return true if sig.size.zero?
|
582
592
|
if (flag?(SCRIPT_VERIFY_DERSIG) || flag?(SCRIPT_VERIFY_LOW_S) || flag?(SCRIPT_VERIFY_STRICTENC)) && !valid_signature_encoding?(sig)
|
583
|
-
return set_error(
|
593
|
+
return set_error(SCRIPT_ERR_SIG_DER)
|
584
594
|
elsif flag?(SCRIPT_VERIFY_LOW_S) && !low_der_signature?(sig)
|
585
595
|
return false
|
586
596
|
elsif flag?(SCRIPT_VERIFY_STRICTENC) && !defined_hashtype_signature?(sig)
|
587
|
-
return set_error(
|
597
|
+
return set_error(SCRIPT_ERR_SIG_HASHTYPE)
|
588
598
|
end
|
589
599
|
true
|
590
600
|
end
|
@@ -626,8 +636,8 @@ module Bitcoin
|
|
626
636
|
end
|
627
637
|
|
628
638
|
def low_der_signature?(sig)
|
629
|
-
return set_error(
|
630
|
-
return set_error(
|
639
|
+
return set_error(SCRIPT_ERR_SIG_DER) unless valid_signature_encoding?(sig)
|
640
|
+
return set_error(SCRIPT_ERR_SIG_HIGH_S) unless Key.low_signature?(sig.htb)
|
631
641
|
true
|
632
642
|
end
|
633
643
|
|
@@ -635,19 +645,19 @@ module Bitcoin
|
|
635
645
|
sig = signature.htb
|
636
646
|
return false if sig.empty?
|
637
647
|
s = sig.unpack('C*')
|
638
|
-
hash_type = s[-1] & (~(
|
639
|
-
return false if hash_type <
|
648
|
+
hash_type = s[-1] & (~(SIGHASH_TYPE[:anyonecanpay]))
|
649
|
+
return false if hash_type < SIGHASH_TYPE[:all] || hash_type > SIGHASH_TYPE[:single]
|
640
650
|
true
|
641
651
|
end
|
642
652
|
|
643
653
|
def check_pubkey_encoding(pubkey, sig_version)
|
644
654
|
if flag?(SCRIPT_VERIFY_STRICTENC) && !Key.compress_or_uncompress_pubkey?(pubkey)
|
645
|
-
return set_error(
|
655
|
+
return set_error(SCRIPT_ERR_PUBKEYTYPE)
|
646
656
|
end
|
647
657
|
# Only compressed keys are accepted in segwit
|
648
658
|
if flag?(SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) &&
|
649
|
-
sig_version ==
|
650
|
-
return set_error(
|
659
|
+
sig_version == :witness_v0 && !Key.compress_pubkey?(pubkey)
|
660
|
+
return set_error(SCRIPT_ERR_WITNESS_PUBKEYTYPE)
|
651
661
|
end
|
652
662
|
true
|
653
663
|
end
|