btcruby 1.0.9 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 439c2a6b804d58bfcb7255211aeea92a5f986f29
4
- data.tar.gz: 559235e43429aa8fba5ce4e709042bd20423fe12
3
+ metadata.gz: 64ee5200a38763d90afb6404bd5b5a5f527f144e
4
+ data.tar.gz: ebcc849873a50338a4d226bdd111bd6988928689
5
5
  SHA512:
6
- metadata.gz: 0dc6aa566dc06fc01355faa49043655781567a46852d7d02dc100bc621bb0440017b69599eeb37f702cd1e4bb827cc5a1034e9bf939b340889a0aca5e859f183
7
- data.tar.gz: e08ac7f8e1a52a2f257f1f68b51db79e9c0b77209a5809bd4595e508ecece588e2c65f4fb18698e53e367920d640964cb7bb6456abbcec9e430a462f6ed82abc
6
+ metadata.gz: 04c8322fc7e1ef83c2f8b4a03d54ec0741776955e95fe92210abcdc80c81fbf999899713d15389fd0875ec5983f770c4e30dcd5372ecbbeafebd5668b2ad8f50
7
+ data.tar.gz: 730d0a4c98735df953eaa01835055df65a1b24296bb17d06848ecbfd3aad2d3baa7b54f4379fcc47d7ec669fe6a896525eec1794e7d0e3d9610603c9613c2fb4
@@ -2,6 +2,13 @@
2
2
  BTCRuby Release Notes
3
3
  =====================
4
4
 
5
+ 1.1 (July 29, 2015)
6
+ --------------------
7
+
8
+ * Added full script interpreter as in Bitcoin Core 0.11.
9
+ * Added array encoding/decoding support to `BTC::WireFormat`.
10
+
11
+
5
12
  1.0.9 (July 20, 2015)
6
13
  --------------------
7
14
 
@@ -27,9 +27,18 @@ require_relative 'btcruby/transaction.rb'
27
27
  require_relative 'btcruby/transaction_input.rb'
28
28
  require_relative 'btcruby/transaction_output.rb'
29
29
  require_relative 'btcruby/transaction_outpoint.rb'
30
- require_relative 'btcruby/script.rb'
31
- require_relative 'btcruby/opcode.rb'
32
- require_relative 'btcruby/signature_hashtype.rb'
30
+
31
+ require_relative 'btcruby/script/script_error.rb'
32
+ require_relative 'btcruby/script/script_flags.rb'
33
+ require_relative 'btcruby/script/script_number.rb'
34
+ require_relative 'btcruby/script/script.rb'
35
+ require_relative 'btcruby/script/script_interpreter.rb'
36
+ require_relative 'btcruby/script/opcode.rb'
37
+ require_relative 'btcruby/script/signature_hashtype.rb'
38
+ require_relative 'btcruby/script/signature_checker.rb'
39
+ require_relative 'btcruby/script/test_signature_checker.rb'
40
+ require_relative 'btcruby/script/transaction_signature_checker.rb'
41
+
33
42
  require_relative 'btcruby/transaction_builder.rb'
34
43
  require_relative 'btcruby/proof_of_work.rb'
35
44
  require_relative 'btcruby/block_header.rb'
@@ -17,7 +17,7 @@ module BTC
17
17
  if outpoint || amount
18
18
  raise ArgumentError, "Outpoint is missing" if !outpoint
19
19
  raise ArgumentError, "Amount is missing" if !amount || amount < 0
20
- data = outpoint.transaction_hash + WireFormat.encode_uint32le(outpoint.index) + WireFormat.encode_uint64le(amount)
20
+ data = outpoint.transaction_hash + WireFormat.encode_uint32be(outpoint.index) + WireFormat.encode_uint64le(amount)
21
21
  super(hash: BTC.hash160(data), network: network)
22
22
  else
23
23
  super(string: string, hash: hash, network: network, _raw_data: _raw_data)
@@ -0,0 +1,139 @@
1
+ module BTC
2
+ SCRIPT_ERR_OK = 0
3
+ SCRIPT_ERR_UNKNOWN_ERROR = 1
4
+ SCRIPT_ERR_EVAL_FALSE = 2
5
+ SCRIPT_ERR_OP_RETURN = 3
6
+
7
+ # Max sizes
8
+ SCRIPT_ERR_SCRIPT_SIZE = 4
9
+ SCRIPT_ERR_PUSH_SIZE = 5
10
+ SCRIPT_ERR_OP_COUNT = 6
11
+ SCRIPT_ERR_STACK_SIZE = 7
12
+ SCRIPT_ERR_SIG_COUNT = 8
13
+ SCRIPT_ERR_PUBKEY_COUNT = 9
14
+
15
+ # Failed verify operations
16
+ SCRIPT_ERR_VERIFY = 10
17
+ SCRIPT_ERR_EQUALVERIFY = 11
18
+ SCRIPT_ERR_CHECKMULTISIGVERIFY = 12
19
+ SCRIPT_ERR_CHECKSIGVERIFY = 13
20
+ SCRIPT_ERR_NUMEQUALVERIFY = 14
21
+
22
+ # Logical/Format/Canonical errors
23
+ SCRIPT_ERR_BAD_OPCODE = 15
24
+ SCRIPT_ERR_DISABLED_OPCODE = 16
25
+ SCRIPT_ERR_INVALID_STACK_OPERATION = 17
26
+ SCRIPT_ERR_INVALID_ALTSTACK_OPERATION = 18
27
+ SCRIPT_ERR_UNBALANCED_CONDITIONAL = 19
28
+
29
+ # OP_CHECKLOCKTIMEVERIFY
30
+ SCRIPT_ERR_NEGATIVE_LOCKTIME = 20
31
+ SCRIPT_ERR_UNSATISFIED_LOCKTIME = 21
32
+
33
+ # BIP62
34
+ SCRIPT_ERR_SIG_HASHTYPE = 22
35
+ SCRIPT_ERR_SIG_DER = 23
36
+ SCRIPT_ERR_MINIMALDATA = 24
37
+ SCRIPT_ERR_SIG_PUSHONLY = 25
38
+ SCRIPT_ERR_SIG_HIGH_S = 26
39
+ SCRIPT_ERR_SIG_NULLDUMMY = 27
40
+ SCRIPT_ERR_PUBKEYTYPE = 28
41
+ SCRIPT_ERR_CLEANSTACK = 29
42
+
43
+ # softfork safeness
44
+ SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS = 30
45
+
46
+ class ScriptError
47
+ attr_reader :code
48
+ attr_reader :message
49
+ attr_reader :description
50
+
51
+ def initialize(code, message = nil)
52
+ @code = code
53
+ @message = message
54
+ end
55
+
56
+ def code_name
57
+ self.class.constants.find{|n| self.class.const_get(n) == @code }
58
+ end
59
+
60
+ def inspect
61
+ "#<#{self.class}:#{code} #{description} (#{code_name})>"
62
+ end
63
+
64
+ def description
65
+ builtin_description + (@message ? ". #{@message}." : "")
66
+ end
67
+
68
+ def builtin_description
69
+ case @code
70
+ when SCRIPT_ERR_OK
71
+ return "No error"
72
+ when SCRIPT_ERR_EVAL_FALSE
73
+ return "Script evaluated without error but finished with a false/empty top stack element"
74
+ when SCRIPT_ERR_VERIFY
75
+ return "Script failed an OP_VERIFY operation"
76
+ when SCRIPT_ERR_EQUALVERIFY
77
+ return "Script failed an OP_EQUALVERIFY operation"
78
+ when SCRIPT_ERR_CHECKMULTISIGVERIFY
79
+ return "Script failed an OP_CHECKMULTISIGVERIFY operation"
80
+ when SCRIPT_ERR_CHECKSIGVERIFY
81
+ return "Script failed an OP_CHECKSIGVERIFY operation"
82
+ when SCRIPT_ERR_NUMEQUALVERIFY
83
+ return "Script failed an OP_NUMEQUALVERIFY operation"
84
+ when SCRIPT_ERR_SCRIPT_SIZE
85
+ return "Script is too big"
86
+ when SCRIPT_ERR_PUSH_SIZE
87
+ return "Push value size limit exceeded"
88
+ when SCRIPT_ERR_OP_COUNT
89
+ return "Operation limit exceeded"
90
+ when SCRIPT_ERR_STACK_SIZE
91
+ return "Stack size limit exceeded"
92
+ when SCRIPT_ERR_SIG_COUNT
93
+ return "Signature count negative or greater than pubkey count"
94
+ when SCRIPT_ERR_PUBKEY_COUNT
95
+ return "Pubkey count negative or limit exceeded"
96
+ when SCRIPT_ERR_BAD_OPCODE
97
+ return "Opcode missing or not understood"
98
+ when SCRIPT_ERR_DISABLED_OPCODE
99
+ return "Attempted to use a disabled opcode"
100
+ when SCRIPT_ERR_INVALID_STACK_OPERATION
101
+ return "Operation not valid with the current stack size"
102
+ when SCRIPT_ERR_INVALID_ALTSTACK_OPERATION
103
+ return "Operation not valid with the current altstack size"
104
+ when SCRIPT_ERR_OP_RETURN
105
+ return "OP_RETURN was encountered"
106
+ when SCRIPT_ERR_UNBALANCED_CONDITIONAL
107
+ return "Invalid OP_IF construction"
108
+ when SCRIPT_ERR_NEGATIVE_LOCKTIME
109
+ return "Negative locktime"
110
+ when SCRIPT_ERR_UNSATISFIED_LOCKTIME
111
+ return "Locktime requirement not satisfied"
112
+ when SCRIPT_ERR_SIG_HASHTYPE
113
+ return "Signature hash type missing or not understood"
114
+ when SCRIPT_ERR_SIG_DER
115
+ return "Non-canonical DER signature"
116
+ when SCRIPT_ERR_MINIMALDATA
117
+ return "Data push larger than necessary"
118
+ when SCRIPT_ERR_SIG_PUSHONLY
119
+ return "Only non-push operators allowed in signatures"
120
+ when SCRIPT_ERR_SIG_HIGH_S
121
+ return "Non-canonical signature: S value is unnecessarily high"
122
+ when SCRIPT_ERR_SIG_NULLDUMMY
123
+ return "Dummy CHECKMULTISIG argument must be zero"
124
+ when SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS
125
+ return "NOPx reserved for soft-fork upgrades"
126
+ when SCRIPT_ERR_PUBKEYTYPE
127
+ return "Public key is neither compressed or uncompressed"
128
+ when SCRIPT_ERR_UNKNOWN_ERROR
129
+ when SCRIPT_ERR_ERROR_COUNT
130
+ end
131
+ "unknown error"
132
+ end
133
+ end
134
+ end
135
+
136
+ if $0 == __FILE__
137
+ puts BTC::ScriptError.new(BTC::ScriptError::SCRIPT_ERR_SIG_HIGH_S).inspect
138
+ end
139
+
@@ -0,0 +1,55 @@
1
+ module BTC
2
+ module ScriptFlags
3
+ SCRIPT_VERIFY_NONE = 0
4
+
5
+ # Evaluate P2SH subscripts (softfork safe, BIP16).
6
+ SCRIPT_VERIFY_P2SH = (1 << 0)
7
+
8
+ # Passing a non-strict-DER signature or one with undefined hashtype to a checksig operation causes script failure.
9
+ # Evaluating a pubkey that is not (0x04 + 64 bytes) or (0x02 or 0x03 + 32 bytes) by checksig causes script failure.
10
+ # (softfork safe, but not used or intended as a consensus rule).
11
+ SCRIPT_VERIFY_STRICTENC = (1 << 1)
12
+
13
+ # Passing a non-strict-DER signature to a checksig operation causes script failure (softfork safe, BIP62 rule 1)
14
+ SCRIPT_VERIFY_DERSIG = (1 << 2)
15
+
16
+ # Passing a non-strict-DER signature or one with S > order/2 to a checksig operation causes script failure
17
+ # (softfork safe, BIP62 rule 5).
18
+ SCRIPT_VERIFY_LOW_S = (1 << 3)
19
+
20
+ # verify dummy stack item consumed by CHECKMULTISIG is of zero-length (softfork safe, BIP62 rule 7).
21
+ SCRIPT_VERIFY_NULLDUMMY = (1 << 4)
22
+
23
+ # Using a non-push operator in the scriptSig causes script failure (softfork safe, BIP62 rule 2).
24
+ SCRIPT_VERIFY_SIGPUSHONLY = (1 << 5)
25
+
26
+ # Require minimal encodings for all push operations (OP_0... OP_16, OP_1NEGATE where possible, direct
27
+ # pushes up to 75 bytes, OP_PUSHDATA up to 255 bytes, OP_PUSHDATA2 for anything larger). Evaluating
28
+ # any other push causes the script to fail (BIP62 rule 3).
29
+ # In addition, whenever a stack element is interpreted as a number, it must be of minimal length (BIP62 rule 4).
30
+ # (softfork safe)
31
+ SCRIPT_VERIFY_MINIMALDATA = (1 << 6)
32
+
33
+ # Discourage use of NOPs reserved for upgrades (NOP1-10)
34
+ #
35
+ # Provided so that nodes can avoid accepting or mining transactions
36
+ # containing executed NOP's whose meaning may change after a soft-fork,
37
+ # thus rendering the script invalid; with this flag set executing
38
+ # discouraged NOPs fails the script. This verification flag will never be
39
+ # a mandatory flag applied to scripts in a block. NOPs that are not
40
+ # executed, e.g. within an unexecuted IF ENDIF block, are *not* rejected.
41
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1 << 7)
42
+
43
+ # Require that only a single stack element remains after evaluation. This changes the success criterion from
44
+ # "At least one stack element must remain, and when interpreted as a boolean, it must be true" to
45
+ # "Exactly one stack element must remain, and when interpreted as a boolean, it must be true".
46
+ # (softfork safe, BIP62 rule 6)
47
+ # Note: CLEANSTACK should never be used without P2SH.
48
+ SCRIPT_VERIFY_CLEANSTACK = (1 << 8)
49
+
50
+ # Verify CHECKLOCKTIMEVERIFY
51
+ #
52
+ # See BIP65 for details.
53
+ SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1 << 9)
54
+ end
55
+ end
@@ -0,0 +1,886 @@
1
+ if $0 == __FILE__
2
+ require 'btcruby'
3
+ require_relative 'script_flags.rb'
4
+ require_relative 'script_number.rb'
5
+ end
6
+
7
+ module BTC
8
+
9
+ MAX_STACK_SIZE = 1000
10
+
11
+ # Script is a stack machine (like Forth) that evaluates a predicate
12
+ # returning a bool indicating valid or not. There are no loops.
13
+ class ScriptInterpreter
14
+ include ScriptFlags
15
+
16
+ attr_accessor :flags
17
+ attr_accessor :signature_checker
18
+ attr_accessor :stack
19
+ attr_accessor :altstack
20
+ attr_accessor :error # ScriptError instance
21
+
22
+ # Instantiates interpreter with validation flags and an optional checker
23
+ # (required if the scripts use signature-checking opcodes).
24
+ # Checker can be transaction checker or block checker
25
+ def initialize(flags: SCRIPT_VERIFY_NONE,
26
+ signature_checker: nil,
27
+ raise_on_failure: false,
28
+ max_pushdata_size: MAX_SCRIPT_ELEMENT_SIZE,
29
+ max_op_count: MAX_OPS_PER_SCRIPT,
30
+ max_stack_size: MAX_STACK_SIZE,
31
+ integer_max_size: 4,
32
+ locktime_max_size: 5)
33
+ @flags = flags
34
+ @signature_checker = signature_checker
35
+ @raise_on_failure = raise_on_failure
36
+ @max_pushdata_size = max_pushdata_size
37
+ @max_op_count = max_op_count
38
+ @max_stack_size = max_stack_size
39
+ @integer_max_size = integer_max_size
40
+ @locktime_max_size = locktime_max_size
41
+
42
+ @stack = []
43
+ @altstack = []
44
+ end
45
+
46
+ # Returns true if succeeded or false in case of failure.
47
+ # If fails, sets the error attribute.
48
+ def verify_script(signature_script: nil, output_script: nil)
49
+
50
+ if flag?(SCRIPT_VERIFY_SIGPUSHONLY) && !signature_script.data_only?
51
+ return set_error(SCRIPT_ERR_SIG_PUSHONLY)
52
+ end
53
+
54
+ if !run_script(signature_script)
55
+ # error is set in run_script
56
+ return false
57
+ end
58
+
59
+ stack_copy = if flag?(SCRIPT_VERIFY_P2SH)
60
+ @stack.dup
61
+ end
62
+
63
+ if !run_script(output_script)
64
+ # error is set in run_script
65
+ return false
66
+ end
67
+
68
+ if @stack.empty?
69
+ return set_error(SCRIPT_ERR_EVAL_FALSE)
70
+ end
71
+
72
+ if cast_to_bool(@stack.last) == false
73
+ return set_error(SCRIPT_ERR_EVAL_FALSE)
74
+ end
75
+
76
+ # Additional validation for pay-to-script-hash (P2SH) transactions:
77
+ if flag?(SCRIPT_VERIFY_P2SH) && output_script.p2sh?
78
+
79
+ # scriptSig must be literals-only or validation fails
80
+ if !signature_script.data_only?
81
+ return set_error(SCRIPT_ERR_SIG_PUSHONLY)
82
+ end
83
+
84
+ # Restore stack.
85
+ @stack = stack_copy
86
+
87
+ # stack cannot be empty here, because if it was the
88
+ # P2SH HASH <> EQUAL scriptPubKey would be evaluated with
89
+ # an empty stack and the EvalScript above would return false.
90
+ raise "Stack cannot be empty" if @stack.empty?
91
+
92
+ serialized_redeem_script = stack_pop
93
+ begin
94
+ redeem_script = BTC::Script.new(data: serialized_redeem_script)
95
+ rescue => e
96
+ return set_error(SCRIPT_ERR_BAD_OPCODE, "Failed to parse serialized redeem script for P2SH. #{e.message}")
97
+ end
98
+
99
+ if !run_script(redeem_script)
100
+ # error is set in run_script
101
+ return false
102
+ end
103
+
104
+ if @stack.empty?
105
+ return set_error(SCRIPT_ERR_EVAL_FALSE)
106
+ end
107
+
108
+ if cast_to_bool(@stack.last) == false
109
+ return set_error(SCRIPT_ERR_EVAL_FALSE)
110
+ end
111
+ end
112
+
113
+ # The CLEANSTACK check is only performed after potential P2SH evaluation,
114
+ # as the non-P2SH evaluation of a P2SH script will obviously not result in
115
+ # a clean stack (the P2SH inputs remain).
116
+ if flag?(SCRIPT_VERIFY_CLEANSTACK)
117
+ # Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK
118
+ # would be possible, which is not a softfork (and P2SH should be one).
119
+ if !flag?(SCRIPT_VERIFY_P2SH)
120
+ raise ArgumentError, "CLEANSTACK without P2SH is disallowed"
121
+ end
122
+ if @stack.size != 1
123
+ return set_error(SCRIPT_ERR_CLEANSTACK, "Stack must be clean (should contain one item 'true')")
124
+ end
125
+ end
126
+
127
+ return true
128
+ end
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+ # Returns true if succeeded or false in case of failure.
139
+ # If fails, sets the error attribute.
140
+ # Used internally in `verify_script` and also in unit tests.
141
+ def run_script(script)
142
+
143
+ number_zero = ScriptNumber.new(integer: 0)
144
+ number_one = ScriptNumber.new(integer: 1)
145
+ zero_value = "".b
146
+ false_value = "".b
147
+ true_value = "\x01".b
148
+
149
+ opcount = 0
150
+ require_minimal = flag?(SCRIPT_VERIFY_MINIMALDATA)
151
+ condition_flags = []
152
+ index_after_codeseparator = 0
153
+ script.chunks.each_with_index do |chunk, chunk_index|
154
+
155
+ opcode = chunk.opcode
156
+ should_execute = !condition_flags.include?(false)
157
+
158
+ if chunk.pushdata? && chunk.pushdata.bytesize > @max_pushdata_size
159
+ return set_error(SCRIPT_ERR_PUSH_SIZE)
160
+ end
161
+
162
+ # Note how OP_RESERVED does not count towards the opcode limit.
163
+ if opcode > OP_16
164
+ if (opcount += 1) > @max_op_count
165
+ return set_error(SCRIPT_ERR_OP_COUNT)
166
+ end
167
+ end
168
+
169
+ if opcode == OP_CAT ||
170
+ opcode == OP_SUBSTR ||
171
+ opcode == OP_LEFT ||
172
+ opcode == OP_RIGHT ||
173
+ opcode == OP_INVERT ||
174
+ opcode == OP_AND ||
175
+ opcode == OP_OR ||
176
+ opcode == OP_XOR ||
177
+ opcode == OP_2MUL ||
178
+ opcode == OP_2DIV ||
179
+ opcode == OP_MUL ||
180
+ opcode == OP_DIV ||
181
+ opcode == OP_MOD ||
182
+ opcode == OP_LSHIFT ||
183
+ opcode == OP_RSHIFT
184
+
185
+ return set_error(SCRIPT_ERR_DISABLED_OPCODE)
186
+ end
187
+
188
+ if should_execute && 0 <= opcode && opcode <= OP_PUSHDATA4
189
+ # Pushdata (including OP_0).
190
+ if require_minimal && !chunk.canonical?
191
+ return set_error(SCRIPT_ERR_MINIMALDATA)
192
+ end
193
+ stack_push(chunk.pushdata)
194
+ elsif should_execute || (OP_IF <= opcode && opcode <= OP_ENDIF)
195
+
196
+ case opcode
197
+ when OP_1NEGATE, OP_1..OP_16
198
+ # ( -- value)
199
+ num = ScriptNumber.new(integer: opcode - (OP_1 - 1))
200
+ stack_push(num.data)
201
+ # The result of these opcodes should always be the minimal way to push the data
202
+ # they push, so no need for a CheckMinimalPush here.
203
+
204
+
205
+ # Control Operators
206
+ # -----------------
207
+
208
+ when OP_NOP
209
+ # nothing
210
+
211
+ when OP_CHECKLOCKTIMEVERIFY
212
+ if !flag?(SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
213
+ # not enabled; treat as a NOP2
214
+ if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
215
+ return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS)
216
+ end
217
+ break
218
+ end
219
+
220
+ if @stack.size < 1
221
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
222
+ end
223
+
224
+ # Note that elsewhere numeric opcodes are limited to
225
+ # operands in the range -2**31+1 to 2**31-1, however it is
226
+ # legal for opcodes to produce results exceeding that
227
+ # range. This limitation is implemented by CScriptNum's
228
+ # default 4-byte limit.
229
+ #
230
+ # If we kept to that limit we'd have a year 2038 problem,
231
+ # even though the nLockTime field in transactions
232
+ # themselves is uint32 which only becomes meaningless
233
+ # after the year 2106.
234
+ #
235
+ # Thus as a special case we tell CScriptNum to accept up
236
+ # to 5-byte bignums, which are good until 2**39-1, well
237
+ # beyond the 2**32-1 limit of the nLockTime field itself.
238
+ locktime = cast_to_number(@stack.last, max_size: @locktime_max_size)
239
+
240
+ # In the rare event that the argument may be < 0 due to
241
+ # some arithmetic being done first, you can always use
242
+ # 0 MAX CHECKLOCKTIMEVERIFY.
243
+ if locktime < 0
244
+ return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME)
245
+ end
246
+
247
+ # Actually compare the specified lock time with the transaction.
248
+ if !signature_checker.check_lock_time(locktime)
249
+ return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME)
250
+ end
251
+
252
+ when OP_NOP1..OP_NOP10
253
+ if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
254
+ return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS)
255
+ end
256
+
257
+ when OP_IF, OP_NOTIF
258
+ # <expression> if [statements] [else [statements]] endif
259
+ flag = false
260
+ if should_execute
261
+ if @stack.size < 1
262
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL)
263
+ end
264
+ flag = cast_to_bool(@stack.last)
265
+ if opcode == OP_NOTIF
266
+ flag = !flag
267
+ end
268
+ stack_pop
269
+ end
270
+ condition_flags.push(flag)
271
+
272
+ when OP_ELSE
273
+ if condition_flags.empty?
274
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL)
275
+ end
276
+ condition_flags[-1] = !condition_flags.last
277
+
278
+ when OP_ENDIF
279
+ if condition_flags.empty?
280
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL)
281
+ end
282
+ condition_flags.pop
283
+
284
+ when OP_VERIFY
285
+ # (true -- ) or
286
+ # (false -- false) and return
287
+ if @stack.size < 1
288
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
289
+ end
290
+ flag = cast_to_bool(@stack.last)
291
+ if flag
292
+ stack_pop
293
+ else
294
+ return set_error(SCRIPT_ERR_VERIFY)
295
+ end
296
+
297
+ when OP_RETURN
298
+ return set_error(SCRIPT_ERR_OP_RETURN)
299
+
300
+
301
+ # Stack Operations
302
+ # ----------------
303
+
304
+ when OP_TOALTSTACK
305
+ if @stack.size < 1
306
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
307
+ end
308
+ @altstack.push(stack_pop)
309
+
310
+ when OP_FROMALTSTACK
311
+ if @altstack.size < 1
312
+ return set_error(SCRIPT_ERR_INVALID_ALTSTACK_OPERATION)
313
+ end
314
+ stack_push(@altstack.pop)
315
+
316
+ when OP_2DROP
317
+ # (x1 x2 -- )
318
+ if @stack.size < 2
319
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
320
+ end
321
+ stack_pop
322
+ stack_pop
323
+
324
+ when OP_2DUP
325
+ # (x1 x2 -- x1 x2 x1 x2)
326
+ if @stack.size < 2
327
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
328
+ end
329
+ a = @stack[-2]
330
+ b = @stack[-1]
331
+ stack_push(a)
332
+ stack_push(b)
333
+
334
+ when OP_3DUP
335
+ # (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
336
+ if @stack.size < 3
337
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
338
+ end
339
+ a = @stack[-3]
340
+ b = @stack[-2]
341
+ c = @stack[-1]
342
+ stack_push(a)
343
+ stack_push(b)
344
+ stack_push(c)
345
+
346
+ when OP_2OVER
347
+ # (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
348
+ if @stack.size < 4
349
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
350
+ end
351
+ a = @stack[-4]
352
+ b = @stack[-3]
353
+ stack_push(a)
354
+ stack_push(b)
355
+
356
+ when OP_2ROT
357
+ # (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
358
+ if @stack.size < 6
359
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
360
+ end
361
+ a = @stack[-6]
362
+ b = @stack[-5]
363
+ @stack[-6...-4] = []
364
+ stack_push(a)
365
+ stack_push(b)
366
+
367
+ when OP_2SWAP
368
+ # (x1 x2 x3 x4 -- x3 x4 x1 x2)
369
+ if @stack.size < 4
370
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
371
+ end
372
+ x1x2 = @stack[-4...-2]
373
+ @stack[-4...-2] = []
374
+ @stack += x1x2
375
+
376
+ when OP_IFDUP
377
+ # (x - 0 | x x)
378
+ if @stack.size < 1
379
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
380
+ end
381
+ item = @stack.last
382
+ if cast_to_bool(item)
383
+ stack_push(item)
384
+ end
385
+
386
+ when OP_DEPTH
387
+ # -- stacksize
388
+ sn = ScriptNumber.new(integer: @stack.size)
389
+ stack_push(sn.data)
390
+
391
+ when OP_DROP
392
+ # (x -- )
393
+ if @stack.size < 1
394
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
395
+ end
396
+ stack_pop
397
+
398
+ when OP_DUP
399
+ # (x -- x x)
400
+ if @stack.size < 1
401
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
402
+ end
403
+ stack_push(@stack.last)
404
+
405
+ when OP_NIP
406
+ # (x1 x2 -- x2)
407
+ if @stack.size < 2
408
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
409
+ end
410
+ @stack.delete_at(-2)
411
+
412
+ when OP_OVER
413
+ # (x1 x2 -- x1 x2 x1)
414
+ if @stack.size < 2
415
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
416
+ end
417
+ stack_push(@stack[-2])
418
+
419
+ when OP_PICK, OP_ROLL
420
+ # (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
421
+ # (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
422
+ if @stack.size < 2
423
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
424
+ end
425
+ n = cast_to_number(@stack.last).to_i
426
+ stack_pop
427
+ if n < 0 || n >= @stack.size
428
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
429
+ end
430
+ item = @stack[-n-1]
431
+ if opcode == OP_ROLL
432
+ @stack.delete_at(-n-1)
433
+ end
434
+ stack_push(item)
435
+
436
+ when OP_ROT
437
+ # (x1 x2 x3 -- x2 x3 x1)
438
+ # x2 x1 x3 after first swap
439
+ # x2 x3 x1 after second swap
440
+ if @stack.size < 3
441
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
442
+ end
443
+ x1 = @stack[-3]
444
+ @stack.delete_at(-3)
445
+ stack_push(x1)
446
+
447
+ when OP_SWAP
448
+ # (x1 x2 -- x2 x1)
449
+ if @stack.size < 2
450
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
451
+ end
452
+ x1 = @stack[-2]
453
+ @stack.delete_at(-2)
454
+ stack_push(x1)
455
+
456
+ when OP_TUCK
457
+ # (x1 x2 -- x2 x1 x2)
458
+ if @stack.size < 2
459
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
460
+ end
461
+ item = @stack[-1]
462
+ @stack.insert(-3, item) # -1 inserts in the end, -2 before the last item.
463
+
464
+ when OP_SIZE
465
+ # (in -- in size)
466
+ if @stack.size < 1
467
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
468
+ end
469
+ sn = ScriptNumber.new(integer: @stack.last.size)
470
+ stack_push(sn.data)
471
+
472
+
473
+ # Bitwise Logic
474
+ # -------------
475
+
476
+ when OP_EQUAL, OP_EQUALVERIFY
477
+ # there is no OP_NOTEQUAL, use OP_NUMNOTEQUAL instead
478
+ # (x1 x2 - bool)
479
+ if @stack.size < 2
480
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
481
+ end
482
+ a = @stack[-2]
483
+ b = @stack[-1]
484
+ equal = (a == b)
485
+ # OP_NOTEQUAL is disabled because it would be too easy to say
486
+ # something like n != 1 and have some wiseguy pass in 1 with extra
487
+ # zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
488
+ # if opcode == OP_NOTEQUAL
489
+ # equal = !equal
490
+ # end
491
+ stack_pop
492
+ stack_pop
493
+ stack_push(equal ? true_value : false_value)
494
+ if opcode == OP_EQUALVERIFY
495
+ if equal
496
+ stack_pop
497
+ else
498
+ return set_error(SCRIPT_ERR_EQUALVERIFY)
499
+ end
500
+ end
501
+
502
+
503
+ # Numeric
504
+ # -------
505
+
506
+ when OP_1ADD,
507
+ OP_1SUB,
508
+ OP_NEGATE,
509
+ OP_ABS,
510
+ OP_NOT,
511
+ OP_0NOTEQUAL
512
+ # (in -- out)
513
+ if @stack.size < 1
514
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
515
+ end
516
+
517
+ bn = cast_to_number(@stack.last)
518
+ case opcode
519
+ when OP_1ADD
520
+ bn += 1
521
+ when OP_1SUB
522
+ bn -= 1
523
+ when OP_NEGATE
524
+ bn = -bn
525
+ when OP_ABS
526
+ bn = -bn if bn < 0
527
+ when OP_NOT
528
+ bn = ScriptNumber.new(boolean: (bn == 0))
529
+ when OP_0NOTEQUAL
530
+ bn = ScriptNumber.new(boolean: (bn != 0))
531
+ else
532
+ raise "invalid opcode"
533
+ end
534
+ stack_pop
535
+ stack_push(bn.data);
536
+
537
+
538
+ when OP_ADD, OP_SUB, OP_BOOLAND..OP_MAX
539
+ # (x1 x2 -- out)
540
+ if @stack.size < 2
541
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
542
+ end
543
+
544
+ bn1 = cast_to_number(@stack[-2])
545
+ bn2 = cast_to_number(@stack[-1])
546
+ bn = ScriptNumber.new(integer: 0)
547
+
548
+ case opcode
549
+ when OP_ADD
550
+ bn = bn1 + bn2
551
+ when OP_SUB
552
+ bn = bn1 - bn2
553
+ when OP_BOOLAND
554
+ bn = ScriptNumber.new(boolean: ((bn1 != 0) && (bn2 != 0)))
555
+ when OP_BOOLOR
556
+ bn = ScriptNumber.new(boolean: ((bn1 != 0) || (bn2 != 0)))
557
+ when OP_NUMEQUAL, OP_NUMEQUALVERIFY
558
+ bn = ScriptNumber.new(boolean: (bn1 == bn2))
559
+ when OP_NUMNOTEQUAL
560
+ bn = ScriptNumber.new(boolean: (bn1 != bn2))
561
+ when OP_LESSTHAN
562
+ bn = ScriptNumber.new(boolean: (bn1 < bn2))
563
+ when OP_GREATERTHAN
564
+ bn = ScriptNumber.new(boolean: (bn1 > bn2))
565
+ when OP_LESSTHANOREQUAL
566
+ bn = ScriptNumber.new(boolean: (bn1 <= bn2))
567
+ when OP_GREATERTHANOREQUAL
568
+ bn = ScriptNumber.new(boolean: (bn1 >= bn2))
569
+ when OP_MIN
570
+ bn = ScriptNumber.new(boolean: (bn1 < bn2 ? bn1 : bn2))
571
+ when OP_MAX
572
+ bn = ScriptNumber.new(boolean: (bn1 > bn2 ? bn1 : bn2))
573
+ else
574
+ raise "Invalid opcode"
575
+ end
576
+ stack_pop
577
+ stack_pop
578
+ stack_push(bn.data)
579
+
580
+ if opcode == OP_NUMEQUALVERIFY
581
+ if cast_to_bool(@stack[-1])
582
+ stack_pop
583
+ else
584
+ return set_error(SCRIPT_ERR_NUMEQUALVERIFY)
585
+ end
586
+ end
587
+
588
+ when OP_WITHIN
589
+ # (x min max -- out)
590
+ if @stack.size < 3
591
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
592
+ end
593
+ bn1 = cast_to_number(@stack[-3])
594
+ bn2 = cast_to_number(@stack[-2])
595
+ bn3 = cast_to_number(@stack[-1])
596
+ flag = ((bn2 <= bn1) && (bn1 < bn3))
597
+ stack_pop
598
+ stack_pop
599
+ stack_pop
600
+ stack_push(flag ? true_value : false_value)
601
+
602
+ # Crypto
603
+ # ------
604
+
605
+ when OP_RIPEMD160..OP_HASH256
606
+ # (in -- hash)
607
+ if @stack.size < 1
608
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
609
+ end
610
+ item = @stack[-1]
611
+ hash = case opcode
612
+ when OP_RIPEMD160
613
+ BTC.ripemd160(item)
614
+ when OP_SHA1
615
+ BTC.sha1(item)
616
+ when OP_SHA256
617
+ BTC.sha256(item)
618
+ when OP_HASH160
619
+ BTC.hash160(item)
620
+ when OP_HASH256
621
+ BTC.hash256(item)
622
+ end
623
+ stack_pop
624
+ stack_push(hash)
625
+
626
+ when OP_CODESEPARATOR
627
+ # Hash starts after the code separator
628
+ index_after_codeseparator = chunk_index + 1
629
+
630
+ when OP_CHECKSIG, OP_CHECKSIGVERIFY
631
+ # (sig pubkey -- bool)
632
+ if @stack.size < 2
633
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
634
+ end
635
+
636
+ sig = @stack[-2]
637
+ pubkey = @stack[-1]
638
+
639
+ # Subset of script starting at the most recent codeseparator
640
+ subscript = script.subscript(index_after_codeseparator..-1)
641
+
642
+ # Drop the signature, since there's no way for a signature to sign itself
643
+ # Consensus-critical code: must replace sig with minimal encoding.
644
+ subscript = subscript.find_and_delete(BTC::Script.new << sig)
645
+
646
+ if !check_signature_encoding(sig) || !check_pubkey_encoding(pubkey)
647
+ # error is set already
648
+ return false
649
+ end
650
+
651
+ success = signature_checker.check_signature(
652
+ script_signature: sig,
653
+ public_key: pubkey,
654
+ script: subscript
655
+ )
656
+
657
+ stack_pop
658
+ stack_pop
659
+ stack_push(success ? true_value : false_value)
660
+
661
+ if opcode == OP_CHECKSIGVERIFY
662
+ if success
663
+ stack_pop
664
+ else
665
+ return set_error(SCRIPT_ERR_CHECKSIGVERIFY)
666
+ end
667
+ end
668
+
669
+
670
+ when OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
671
+ # ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
672
+
673
+ i = 1
674
+ if @stack.size < i
675
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
676
+ end
677
+
678
+ keys_count = cast_to_number(@stack[-i]).to_i
679
+ if keys_count < 0 || keys_count > 20
680
+ return set_error(SCRIPT_ERR_PUBKEY_COUNT)
681
+ end
682
+ opcount += keys_count
683
+ if opcount > @max_op_count
684
+ return set_error(SCRIPT_ERR_OP_COUNT)
685
+ end
686
+ ikey = (i+=1)
687
+ i += keys_count
688
+ if @stack.size < i
689
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
690
+ end
691
+
692
+ sigs_count = cast_to_number(@stack[-i]).to_i
693
+ if sigs_count < 0 || sigs_count > keys_count
694
+ return set_error(SCRIPT_ERR_SIG_COUNT)
695
+ end
696
+
697
+ isig = (i+=1)
698
+ i += sigs_count
699
+
700
+ if @stack.size < i
701
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
702
+ end
703
+
704
+ # Subset of script starting at the most recent codeseparator
705
+
706
+ # Subset of script starting at the most recent codeseparator
707
+ subscript = script.subscript(index_after_codeseparator..-1)
708
+
709
+ # Drop the signatures, since there's no way for a signature to sign itself
710
+ # Consensus-critical code: must replace sig with minimal encoding.
711
+ sigs_count.times do |k|
712
+ sig = @stack[-isig-k]
713
+ subscript = subscript.find_and_delete(BTC::Script.new << sig)
714
+ end
715
+
716
+ success = true
717
+ while success && sigs_count > 0
718
+ sig = @stack[-isig]
719
+ pubkey = @stack[-ikey]
720
+ # Note how this makes the exact order of pubkey/signature evaluation
721
+ # distinguishable by CHECKMULTISIG NOT if the STRICTENC flag is set.
722
+ # See the script_(in)valid tests for details.
723
+ if !check_signature_encoding(sig) || !check_pubkey_encoding(pubkey)
724
+ # error is set already
725
+ return false
726
+ end
727
+
728
+ # Check signature
729
+ ok = signature_checker.check_signature(
730
+ script_signature: sig,
731
+ public_key: pubkey,
732
+ script: subscript
733
+ )
734
+ if ok
735
+ isig += 1
736
+ sigs_count -= 1
737
+ end
738
+ ikey += 1
739
+ keys_count -= 1
740
+
741
+ # If there are more signatures left than keys left,
742
+ # then too many signatures have failed. Exit early,
743
+ # without checking any further signatures.
744
+ if sigs_count > keys_count
745
+ success = false
746
+ end
747
+ end
748
+
749
+ # Clean up stack of actual arguments
750
+ while (i-=1) > 0 # Bitcoin Core: while (i-- > 1)
751
+ stack_pop
752
+ end
753
+
754
+ # A bug causes CHECKMULTISIG to consume one extra argument
755
+ # whose contents were not checked in any way.
756
+ #
757
+ # Unfortunately this is a potential source of mutability,
758
+ # so optionally verify it is exactly equal to zero prior
759
+ # to removing it from the stack.
760
+ if @stack.size < 1
761
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION)
762
+ end
763
+
764
+ if flag?(SCRIPT_VERIFY_NULLDUMMY) && @stack[-1].size > 0
765
+ return set_error(SCRIPT_ERR_SIG_NULLDUMMY)
766
+ end
767
+ stack_pop
768
+ stack_push(success ? true_value : false_value)
769
+ if opcode == OP_CHECKMULTISIGVERIFY
770
+ if success
771
+ stack_pop
772
+ else
773
+ return set_error(SCRIPT_ERR_CHECKMULTISIGVERIFY)
774
+ end
775
+ end
776
+
777
+ else # unknown opcode
778
+ return set_error(SCRIPT_ERR_BAD_OPCODE)
779
+
780
+ end # case opcode
781
+ end # within IF scope
782
+
783
+ # Size limits
784
+ if @stack.size + @altstack.size > @max_stack_size
785
+ return set_error(SCRIPT_ERR_STACK_SIZE)
786
+ end
787
+
788
+ end # each chunk
789
+
790
+ if !condition_flags.empty?
791
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL)
792
+ end
793
+
794
+ return true
795
+ end # run_script
796
+
797
+
798
+ def stack_pop
799
+ r = @stack.pop
800
+ #puts "POPPED FROM STACK: #{@stack.map{|s|s.to_hex}.join(' ')}"
801
+ r
802
+ end
803
+
804
+ def stack_push(x)
805
+ @stack.push(x)
806
+ #puts "PUSHED TO STACK: #{@stack.map{|s|s.to_hex}.join(' ')}"
807
+ end
808
+
809
+ def check_signature_encoding(sig)
810
+ # Empty signature. Not strictly DER encoded, but allowed to provide a
811
+ # compact way to provide an invalid signature for use with CHECK(MULTI)SIG
812
+ if sig.size == 0
813
+ return true
814
+ end
815
+ if flag?(SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC) && !valid_signature_encoding(sig)
816
+ return set_error(SCRIPT_ERR_SIG_DER)
817
+ elsif flag?(SCRIPT_VERIFY_LOW_S) && !low_der_signature(sig)
818
+ return set_error(SCRIPT_ERR_SIG_HIGH_S)
819
+ elsif flag?(SCRIPT_VERIFY_STRICTENC) && !defined_hashtype_signature(sig)
820
+ return set_error(SCRIPT_ERR_SIG_HASHTYPE)
821
+ end
822
+ return true
823
+ end
824
+
825
+ def check_pubkey_encoding(pubkey)
826
+ if flag?(SCRIPT_VERIFY_STRICTENC) && !compressed_or_uncompressed_pubkey(pubkey)
827
+ return set_error(SCRIPT_ERR_PUBKEYTYPE)
828
+ end
829
+ return true
830
+ end
831
+
832
+ def valid_signature_encoding(sig)
833
+ BTC::Key.validate_script_signature(sig, verify_lower_s: false, verify_hashtype: false)
834
+ end
835
+
836
+ def low_der_signature(sig)
837
+ BTC::Key.validate_script_signature(sig, verify_lower_s: true, verify_hashtype: false)
838
+ end
839
+
840
+ def defined_hashtype_signature(sig)
841
+ BTC::Key.validate_script_signature(sig, verify_lower_s: false, verify_hashtype: true)
842
+ end
843
+
844
+ def compressed_or_uncompressed_pubkey(pubkey)
845
+ BTC::Key.validate_public_key(pubkey)
846
+ end
847
+
848
+ # If multiple flags are provided, returns true if any of them are present
849
+ def flag?(flags)
850
+ (@flags & flags) != 0
851
+ end
852
+
853
+ def cast_to_number(data,
854
+ require_minimal: flag?(SCRIPT_VERIFY_MINIMALDATA),
855
+ max_size: @integer_max_size)
856
+ ScriptNumber.new(data: data, require_minimal: require_minimal, max_size: max_size)
857
+ end
858
+
859
+ def cast_to_bool(data)
860
+ data.bytes.each_with_index do |byte, i|
861
+ if byte != 0
862
+ # Can be negative zero
863
+ if byte == 0x80 && i == (data.bytesize - 1)
864
+ return false
865
+ end
866
+ return true
867
+ end
868
+ end
869
+ return false
870
+ end
871
+
872
+ def set_error(code, message = nil)
873
+ error = ScriptError.new(code, message)
874
+ raise "#{error.description} (#{code.inspect})" if @raise_on_failure
875
+ @error = error
876
+ false
877
+ end
878
+
879
+
880
+ end
881
+ end
882
+
883
+ if $0 == __FILE__
884
+ require 'btcruby'
885
+
886
+ end