btcruby 1.0.9 → 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 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