tapyrus 0.1.0

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.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +12 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +6 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +100 -0
  11. data/Rakefile +6 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/exe/tapyrusrb-cli +5 -0
  15. data/exe/tapyrusrbd +41 -0
  16. data/lib/openassets/marker_output.rb +20 -0
  17. data/lib/openassets/payload.rb +54 -0
  18. data/lib/openassets/util.rb +28 -0
  19. data/lib/openassets.rb +9 -0
  20. data/lib/tapyrus/base58.rb +38 -0
  21. data/lib/tapyrus/block.rb +77 -0
  22. data/lib/tapyrus/block_header.rb +88 -0
  23. data/lib/tapyrus/bloom_filter.rb +78 -0
  24. data/lib/tapyrus/chain_params.rb +90 -0
  25. data/lib/tapyrus/chainparams/mainnet.yml +41 -0
  26. data/lib/tapyrus/chainparams/regtest.yml +38 -0
  27. data/lib/tapyrus/chainparams/testnet.yml +41 -0
  28. data/lib/tapyrus/constants.rb +195 -0
  29. data/lib/tapyrus/descriptor.rb +147 -0
  30. data/lib/tapyrus/ext_key.rb +337 -0
  31. data/lib/tapyrus/key.rb +296 -0
  32. data/lib/tapyrus/key_path.rb +26 -0
  33. data/lib/tapyrus/logger.rb +42 -0
  34. data/lib/tapyrus/merkle_tree.rb +149 -0
  35. data/lib/tapyrus/message/addr.rb +35 -0
  36. data/lib/tapyrus/message/base.rb +28 -0
  37. data/lib/tapyrus/message/block.rb +46 -0
  38. data/lib/tapyrus/message/block_transaction_request.rb +45 -0
  39. data/lib/tapyrus/message/block_transactions.rb +31 -0
  40. data/lib/tapyrus/message/block_txn.rb +27 -0
  41. data/lib/tapyrus/message/cmpct_block.rb +42 -0
  42. data/lib/tapyrus/message/error.rb +10 -0
  43. data/lib/tapyrus/message/fee_filter.rb +27 -0
  44. data/lib/tapyrus/message/filter_add.rb +28 -0
  45. data/lib/tapyrus/message/filter_clear.rb +17 -0
  46. data/lib/tapyrus/message/filter_load.rb +39 -0
  47. data/lib/tapyrus/message/get_addr.rb +17 -0
  48. data/lib/tapyrus/message/get_block_txn.rb +27 -0
  49. data/lib/tapyrus/message/get_blocks.rb +29 -0
  50. data/lib/tapyrus/message/get_data.rb +21 -0
  51. data/lib/tapyrus/message/get_headers.rb +28 -0
  52. data/lib/tapyrus/message/header_and_short_ids.rb +57 -0
  53. data/lib/tapyrus/message/headers.rb +35 -0
  54. data/lib/tapyrus/message/headers_parser.rb +24 -0
  55. data/lib/tapyrus/message/inv.rb +21 -0
  56. data/lib/tapyrus/message/inventories_parser.rb +23 -0
  57. data/lib/tapyrus/message/inventory.rb +51 -0
  58. data/lib/tapyrus/message/mem_pool.rb +17 -0
  59. data/lib/tapyrus/message/merkle_block.rb +42 -0
  60. data/lib/tapyrus/message/network_addr.rb +63 -0
  61. data/lib/tapyrus/message/not_found.rb +21 -0
  62. data/lib/tapyrus/message/ping.rb +30 -0
  63. data/lib/tapyrus/message/pong.rb +26 -0
  64. data/lib/tapyrus/message/prefilled_tx.rb +29 -0
  65. data/lib/tapyrus/message/reject.rb +46 -0
  66. data/lib/tapyrus/message/send_cmpct.rb +43 -0
  67. data/lib/tapyrus/message/send_headers.rb +16 -0
  68. data/lib/tapyrus/message/tx.rb +30 -0
  69. data/lib/tapyrus/message/ver_ack.rb +17 -0
  70. data/lib/tapyrus/message/version.rb +69 -0
  71. data/lib/tapyrus/message.rb +70 -0
  72. data/lib/tapyrus/mnemonic/wordlist/chinese_simplified.txt +2048 -0
  73. data/lib/tapyrus/mnemonic/wordlist/chinese_traditional.txt +2048 -0
  74. data/lib/tapyrus/mnemonic/wordlist/english.txt +2048 -0
  75. data/lib/tapyrus/mnemonic/wordlist/french.txt +2048 -0
  76. data/lib/tapyrus/mnemonic/wordlist/italian.txt +2048 -0
  77. data/lib/tapyrus/mnemonic/wordlist/japanese.txt +2048 -0
  78. data/lib/tapyrus/mnemonic/wordlist/spanish.txt +2048 -0
  79. data/lib/tapyrus/mnemonic.rb +77 -0
  80. data/lib/tapyrus/network/connection.rb +73 -0
  81. data/lib/tapyrus/network/message_handler.rb +241 -0
  82. data/lib/tapyrus/network/peer.rb +223 -0
  83. data/lib/tapyrus/network/peer_discovery.rb +42 -0
  84. data/lib/tapyrus/network/pool.rb +135 -0
  85. data/lib/tapyrus/network.rb +13 -0
  86. data/lib/tapyrus/node/cli.rb +112 -0
  87. data/lib/tapyrus/node/configuration.rb +38 -0
  88. data/lib/tapyrus/node/spv.rb +79 -0
  89. data/lib/tapyrus/node.rb +7 -0
  90. data/lib/tapyrus/opcodes.rb +178 -0
  91. data/lib/tapyrus/out_point.rb +44 -0
  92. data/lib/tapyrus/rpc/http_server.rb +65 -0
  93. data/lib/tapyrus/rpc/request_handler.rb +150 -0
  94. data/lib/tapyrus/rpc/tapyrus_core_client.rb +72 -0
  95. data/lib/tapyrus/rpc.rb +7 -0
  96. data/lib/tapyrus/script/multisig.rb +92 -0
  97. data/lib/tapyrus/script/script.rb +551 -0
  98. data/lib/tapyrus/script/script_error.rb +111 -0
  99. data/lib/tapyrus/script/script_interpreter.rb +668 -0
  100. data/lib/tapyrus/script/tx_checker.rb +81 -0
  101. data/lib/tapyrus/script_witness.rb +38 -0
  102. data/lib/tapyrus/secp256k1/native.rb +174 -0
  103. data/lib/tapyrus/secp256k1/ruby.rb +123 -0
  104. data/lib/tapyrus/secp256k1.rb +12 -0
  105. data/lib/tapyrus/slip39/share.rb +122 -0
  106. data/lib/tapyrus/slip39/sss.rb +245 -0
  107. data/lib/tapyrus/slip39/wordlist/english.txt +1024 -0
  108. data/lib/tapyrus/slip39.rb +93 -0
  109. data/lib/tapyrus/store/chain_entry.rb +67 -0
  110. data/lib/tapyrus/store/db/level_db.rb +98 -0
  111. data/lib/tapyrus/store/db.rb +9 -0
  112. data/lib/tapyrus/store/spv_chain.rb +101 -0
  113. data/lib/tapyrus/store.rb +9 -0
  114. data/lib/tapyrus/tx.rb +347 -0
  115. data/lib/tapyrus/tx_in.rb +89 -0
  116. data/lib/tapyrus/tx_out.rb +74 -0
  117. data/lib/tapyrus/util.rb +133 -0
  118. data/lib/tapyrus/validation.rb +115 -0
  119. data/lib/tapyrus/version.rb +3 -0
  120. data/lib/tapyrus/wallet/account.rb +151 -0
  121. data/lib/tapyrus/wallet/base.rb +162 -0
  122. data/lib/tapyrus/wallet/db.rb +81 -0
  123. data/lib/tapyrus/wallet/master_key.rb +110 -0
  124. data/lib/tapyrus/wallet.rb +8 -0
  125. data/lib/tapyrus.rb +219 -0
  126. data/tapyrusrb.conf.sample +0 -0
  127. data/tapyrusrb.gemspec +47 -0
  128. metadata +451 -0
@@ -0,0 +1,668 @@
1
+ module Tapyrus
2
+
3
+ class ScriptInterpreter
4
+
5
+ include Tapyrus::Opcodes
6
+
7
+ attr_reader :stack
8
+ attr_reader :debug
9
+ attr_reader :flags
10
+ attr_accessor :error
11
+ attr_reader :checker
12
+ attr_reader :require_minimal
13
+
14
+ DISABLE_OPCODES = [OP_CAT, OP_SUBSTR, OP_LEFT, OP_RIGHT, OP_INVERT, OP_AND, OP_OR, OP_XOR, OP_2MUL, OP_2DIV, OP_DIV, OP_MUL, OP_MOD, OP_LSHIFT, OP_RSHIFT]
15
+
16
+
17
+ # syntax sugar for simple evaluation for script.
18
+ # @param [Tapyrus::Script] script_sig a scriptSig.
19
+ # @param [Tapyrus::Script] script_pubkey a scriptPubkey.
20
+ def self.eval(script_sig, script_pubkey)
21
+ self.new.verify_script(script_sig, script_pubkey)
22
+ end
23
+
24
+ # initialize runner
25
+ def initialize(flags: SCRIPT_VERIFY_NONE, checker: TxChecker.new)
26
+ @stack, @debug = [], []
27
+ @flags = flags
28
+ @checker = checker
29
+ @require_minimal = flag?(SCRIPT_VERIFY_MINIMALDATA)
30
+ end
31
+
32
+ # eval script
33
+ # @param [Tapyrus::Script] script_sig a signature script (unlock script which data push only)
34
+ # @param [Tapyrus::Script] script_pubkey a script pubkey (locking script)
35
+ # @param [Tapyrus::ScriptWitness] witness a witness script
36
+ # @return [Boolean] result
37
+ def verify_script(script_sig, script_pubkey, witness = ScriptWitness.new)
38
+
39
+ return set_error(SCRIPT_ERR_SIG_PUSHONLY) if flag?(SCRIPT_VERIFY_SIGPUSHONLY) && !script_sig.push_only?
40
+
41
+ stack_copy = nil
42
+ had_witness = false
43
+
44
+ return false unless eval_script(script_sig, :base)
45
+
46
+ stack_copy = stack.dup if flag?(SCRIPT_VERIFY_P2SH)
47
+
48
+ return false unless eval_script(script_pubkey, :base)
49
+
50
+ return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last.htb)
51
+
52
+ # Bare witness programs
53
+ if flag?(SCRIPT_VERIFY_WITNESS) && script_pubkey.witness_program?
54
+ had_witness = true
55
+ return set_error(SCRIPT_ERR_WITNESS_MALLEATED) unless script_sig.size == 0
56
+ version, program = script_pubkey.witness_data
57
+ stack_copy = stack.dup
58
+ return false unless verify_witness_program(witness, version, program)
59
+ end
60
+
61
+ # Additional validation for spend-to-script-hash transactions
62
+ if flag?(SCRIPT_VERIFY_P2SH) && script_pubkey.p2sh?
63
+ return set_error(SCRIPT_ERR_SIG_PUSHONLY) unless script_sig.push_only?
64
+ tmp = stack
65
+ @stack = stack_copy
66
+ raise 'stack cannot be empty.' if stack.empty?
67
+ begin
68
+ redeem_script = Tapyrus::Script.parse_from_payload(stack.pop.htb)
69
+ rescue Exception => e
70
+ return set_error(SCRIPT_ERR_BAD_OPCODE, "Failed to parse serialized redeem script for P2SH. #{e.message}")
71
+ end
72
+ return false unless eval_script(redeem_script, :base)
73
+ return set_error(SCRIPT_ERR_EVAL_FALSE) if stack.empty? || !cast_to_bool(stack.last)
74
+
75
+ # P2SH witness program
76
+ if flag?(SCRIPT_VERIFY_WITNESS) && redeem_script.witness_program?
77
+ had_witness = true
78
+ # The scriptSig must be _exactly_ a single push of the redeemScript. Otherwise we reintroduce malleability.
79
+ return set_error(SCRIPT_ERR_WITNESS_MALLEATED_P2SH) unless script_sig == (Tapyrus::Script.new << redeem_script.to_payload.bth)
80
+
81
+ version, program = redeem_script.witness_data
82
+ return false unless verify_witness_program(witness, version, program)
83
+ end
84
+ end
85
+
86
+ # The CLEANSTACK check is only performed after potential P2SH evaluation,
87
+ # as the non-P2SH evaluation of a P2SH script will obviously not result in a clean stack (the P2SH inputs remain).
88
+ # The same holds for witness evaluation.
89
+ if flag?(SCRIPT_VERIFY_CLEANSTACK)
90
+ # Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK would be possible,
91
+ # which is not a softfork (and P2SH should be one).
92
+ raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
93
+ return set_error(SCRIPT_ERR_CLEANSTACK) unless stack.size == 1
94
+ end
95
+
96
+ if flag?(SCRIPT_VERIFY_WITNESS)
97
+ raise 'assert' unless flag?(SCRIPT_VERIFY_P2SH)
98
+ return set_error(SCRIPT_ERR_WITNESS_UNEXPECTED) if !had_witness && !witness.empty?
99
+ end
100
+
101
+ true
102
+ end
103
+
104
+ def set_error(err_code, extra_message = nil)
105
+ @error = ScriptError.new(err_code, extra_message)
106
+ false
107
+ end
108
+
109
+ def verify_witness_program(witness, version, program)
110
+ if version == 0
111
+ if program.bytesize == 32
112
+ return set_error(SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY) if witness.stack.size == 0
113
+ script_pubkey = Tapyrus::Script.parse_from_payload(witness.stack.last)
114
+ @stack = witness.stack[0..-2].map{|w|w.bth}
115
+ script_hash = Tapyrus.sha256(script_pubkey.to_payload)
116
+ return set_error(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH) unless script_hash == program
117
+ elsif program.bytesize == 20
118
+ return set_error(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH) unless witness.stack.size == 2
119
+ script_pubkey = Tapyrus::Script.to_p2pkh(program.bth)
120
+ @stack = witness.stack.map{|w|w.bth}
121
+ else
122
+ return set_error(SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH)
123
+ end
124
+ elsif flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
125
+ return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
126
+ else
127
+ return true # Higher version witness scripts return true for future softfork compatibility
128
+ end
129
+
130
+ stack.each do |s| # Disallow stack item size > MAX_SCRIPT_ELEMENT_SIZE in witness stack
131
+ return set_error(SCRIPT_ERR_PUSH_SIZE) if s.htb.bytesize > MAX_SCRIPT_ELEMENT_SIZE
132
+ end
133
+
134
+ return false unless eval_script(script_pubkey, :witness_v0)
135
+
136
+ return set_error(SCRIPT_ERR_EVAL_FALSE) unless stack.size == 1
137
+ return set_error(SCRIPT_ERR_EVAL_FALSE) unless cast_to_bool(stack.last)
138
+ true
139
+ end
140
+
141
+ def eval_script(script, sig_version)
142
+ return set_error(SCRIPT_ERR_SCRIPT_SIZE) if script.size > MAX_SCRIPT_SIZE
143
+ begin
144
+ flow_stack = []
145
+ alt_stack = []
146
+ last_code_separator_index = 0
147
+ op_count = 0
148
+
149
+ script.chunks.each_with_index do |c, index|
150
+ need_exec = !flow_stack.include?(false)
151
+
152
+ return set_error(SCRIPT_ERR_PUSH_SIZE) if c.pushdata? && c.pushed_data.bytesize > MAX_SCRIPT_ELEMENT_SIZE
153
+
154
+ opcode = c.opcode
155
+
156
+ if need_exec && c.pushdata?
157
+ if require_minimal && !minimal_push?(c.pushed_data, opcode)
158
+ return set_error(SCRIPT_ERR_MINIMALDATA)
159
+ end
160
+ return set_error(SCRIPT_ERR_BAD_OPCODE) unless verify_pushdata_length(c)
161
+ stack << c.pushed_data.bth
162
+ else
163
+ if opcode > OP_16 && (op_count += 1) > MAX_OPS_PER_SCRIPT
164
+ return set_error(SCRIPT_ERR_OP_COUNT)
165
+ end
166
+ return set_error(SCRIPT_ERR_DISABLED_OPCODE) if DISABLE_OPCODES.include?(opcode)
167
+ return set_error(SCRIPT_ERR_OP_CODESEPARATOR) if opcode == OP_CODESEPARATOR && sig_version == :base && flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE)
168
+ next unless (need_exec || (OP_IF <= opcode && opcode <= OP_ENDIF))
169
+ small_int = Opcodes.opcode_to_small_int(opcode)
170
+ if small_int && opcode != OP_0
171
+ push_int(small_int)
172
+ else
173
+ case opcode
174
+ when OP_0
175
+ stack << ''
176
+ when OP_DEPTH
177
+ push_int(stack.size)
178
+ when OP_EQUAL, OP_EQUALVERIFY
179
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
180
+ a, b = pop_string(2)
181
+ result = a == b
182
+ push_int(result ? 1 : 0)
183
+ if opcode == OP_EQUALVERIFY
184
+ if result
185
+ stack.pop
186
+ else
187
+ return set_error(SCRIPT_ERR_EQUALVERIFY)
188
+ end
189
+ end
190
+ when OP_0NOTEQUAL
191
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
192
+ push_int(pop_int == 0 ? 0 : 1)
193
+ when OP_ADD
194
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
195
+ a, b = pop_int(2)
196
+ push_int(a + b)
197
+ when OP_1ADD
198
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
199
+ push_int(pop_int + 1)
200
+ when OP_SUB
201
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
202
+ a, b = pop_int(2)
203
+ push_int(a - b)
204
+ when OP_1SUB
205
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
206
+ push_int(pop_int - 1)
207
+ when OP_IF, OP_NOTIF
208
+ result = false
209
+ if need_exec
210
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if stack.size < 1
211
+ value = pop_string.htb
212
+ if sig_version == :witness_v0 && flag?(SCRIPT_VERIFY_MINIMALIF)
213
+ if value.bytesize > 1 || (value.bytesize == 1 && value[0].unpack('C').first != 1)
214
+ return set_error(SCRIPT_ERR_MINIMALIF)
215
+ end
216
+ end
217
+ result = cast_to_bool(value)
218
+ result = !result if opcode == OP_NOTIF
219
+ end
220
+ flow_stack << result
221
+ when OP_ELSE
222
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.size < 1
223
+ flow_stack << !flow_stack.pop
224
+ when OP_ENDIF
225
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.empty?
226
+ flow_stack.pop
227
+ when OP_NOP
228
+ when OP_NOP1, OP_NOP4..OP_NOP10
229
+ return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS) if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
230
+ when OP_CHECKLOCKTIMEVERIFY
231
+ next unless flag?(SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
232
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
233
+ # Note that elsewhere numeric opcodes are limited to operands in the range -2**31+1 to 2**31-1,
234
+ # however it is legal for opcodes to produce results exceeding that range.
235
+ # This limitation is implemented by CScriptNum's default 4-byte limit.
236
+ # If we kept to that limit we'd have a year 2038 problem,
237
+ # even though the nLockTime field in transactions themselves is uint32 which only becomes meaningless after the year 2106.
238
+ # Thus as a special case we tell CScriptNum to accept up to 5-byte bignums,
239
+ # which are good until 2**39-1, well beyond the 2**32-1 limit of the nLockTime field itself.
240
+ locktime = cast_to_int(stack.last, 5)
241
+ return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if locktime < 0
242
+ return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME) unless checker.check_locktime(locktime)
243
+ when OP_CHECKSEQUENCEVERIFY
244
+ next unless flag?(SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
245
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
246
+
247
+ # nSequence, like nLockTime, is a 32-bit unsigned integer field.
248
+ # See the comment in CHECKLOCKTIMEVERIFY regarding 5-byte numeric operands.
249
+ sequence = cast_to_int(stack.last, 5)
250
+
251
+ # In the rare event that the argument may be < 0 due to some arithmetic being done first,
252
+ # you can always use 0 MAX CHECKSEQUENCEVERIFY.
253
+ return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if sequence < 0
254
+
255
+ # To provide for future soft-fork extensibility,
256
+ # if the operand has the disabled lock-time flag set, CHECKSEQUENCEVERIFY behaves as a NOP.
257
+ next if (sequence & Tapyrus::TxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0
258
+
259
+ # Compare the specified sequence number with the input.
260
+ unless checker.check_sequence(sequence)
261
+ return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME)
262
+ end
263
+ when OP_DUP
264
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
265
+ stack << stack.last
266
+ when OP_2DUP
267
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
268
+ 2.times { stack << stack[-2] }
269
+ when OP_3DUP
270
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
271
+ 3.times { stack << stack[-3] }
272
+ when OP_IFDUP
273
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
274
+ stack << stack.last if cast_to_bool(stack.last)
275
+ when OP_RIPEMD160
276
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
277
+ stack << Digest::RMD160.hexdigest(pop_string.htb)
278
+ when OP_SHA1
279
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
280
+ stack << Digest::SHA1.hexdigest(pop_string.htb)
281
+ when OP_SHA256
282
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
283
+ stack << Digest::SHA256.hexdigest(pop_string.htb)
284
+ when OP_HASH160
285
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
286
+ stack << Tapyrus.hash160(pop_string)
287
+ when OP_HASH256
288
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
289
+ stack << Tapyrus.double_sha256(pop_string.htb).bth
290
+ when OP_VERIFY
291
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
292
+ return set_error(SCRIPT_ERR_VERIFY) unless pop_bool
293
+ when OP_TOALTSTACK
294
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
295
+ alt_stack << stack.pop
296
+ when OP_FROMALTSTACK
297
+ return set_error(SCRIPT_ERR_INVALID_ALTSTACK_OPERATION) if alt_stack.size < 1
298
+ stack << alt_stack.pop
299
+ when OP_DROP
300
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
301
+ stack.pop
302
+ when OP_2DROP
303
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
304
+ 2.times { stack.pop }
305
+ when OP_NIP
306
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
307
+ stack.delete_at(-2)
308
+ when OP_OVER
309
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
310
+ stack << stack[-2]
311
+ when OP_2OVER
312
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
313
+ 2.times { stack << stack[-4]}
314
+ when OP_PICK, OP_ROLL
315
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
316
+ pos = pop_int
317
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if pos < 0 || pos >= stack.size
318
+ stack << stack[-pos - 1]
319
+ stack.delete_at(-pos - 2) if opcode == OP_ROLL
320
+ when OP_ROT
321
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
322
+ stack << stack[-3]
323
+ stack.delete_at(-4)
324
+ when OP_2ROT
325
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 6
326
+ 2.times { stack << stack[-6] }
327
+ 2.times { stack.delete_at(-7) }
328
+ when OP_SWAP
329
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
330
+ tmp = stack.last
331
+ stack[-1] = stack[-2]
332
+ stack[-2] = tmp
333
+ when OP_2SWAP
334
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
335
+ 2.times {stack << stack[-4]}
336
+ 2.times {stack.delete_at(-5)}
337
+ when OP_TUCK
338
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
339
+ stack.insert(-3, stack.last)
340
+ when OP_ABS
341
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
342
+ v = pop_int
343
+ push_int(v.abs)
344
+ when OP_BOOLAND
345
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
346
+ a, b = pop_int(2)
347
+ push_int((!a.zero? && !b.zero?) ? 1 : 0)
348
+ when OP_BOOLOR
349
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
350
+ a, b = pop_int(2)
351
+ push_int((!a.zero? || !b.zero?) ? 1 : 0)
352
+ when OP_NUMEQUAL, OP_NUMEQUALVERIFY
353
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
354
+ a, b = pop_int(2)
355
+ result = a == b
356
+ push_int(result ? 1 : 0)
357
+ if opcode == OP_NUMEQUALVERIFY
358
+ if result
359
+ stack.pop
360
+ else
361
+ return set_error(SCRIPT_ERR_NUMEQUALVERIFY)
362
+ end
363
+ end
364
+ when OP_LESSTHAN, OP_LESSTHANOREQUAL
365
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
366
+ a, b = pop_int(2)
367
+ push_int(a < b ? 1 : 0) if opcode == OP_LESSTHAN
368
+ push_int(a <= b ? 1 : 0) if opcode == OP_LESSTHANOREQUAL
369
+ when OP_GREATERTHAN, OP_GREATERTHANOREQUAL
370
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
371
+ a, b = pop_int(2)
372
+ push_int(a > b ? 1 : 0) if opcode == OP_GREATERTHAN
373
+ push_int(a >= b ? 1 : 0) if opcode == OP_GREATERTHANOREQUAL
374
+ when OP_MIN
375
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
376
+ push_int(pop_int(2).min)
377
+ when OP_MAX
378
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
379
+ push_int(pop_int(2).max)
380
+ when OP_WITHIN
381
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
382
+ x, a, b = pop_int(3)
383
+ push_int((a <= x && x < b) ? 1 : 0)
384
+ when OP_NOT
385
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
386
+ push_int(pop_int == 0 ? 1 : 0)
387
+ when OP_SIZE
388
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
389
+ item = stack.last
390
+ item = Tapyrus::Script.encode_number(item) if item.is_a?(Numeric)
391
+ size = item.htb.bytesize
392
+ push_int(size)
393
+ when OP_NEGATE
394
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
395
+ push_int(-pop_int)
396
+ when OP_NUMNOTEQUAL
397
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
398
+ a, b = pop_int(2)
399
+ push_int(a == b ? 0 : 1)
400
+ when OP_CODESEPARATOR
401
+ last_code_separator_index = index + 1
402
+ when OP_CHECKSIG, OP_CHECKSIGVERIFY
403
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
404
+ sig, pubkey = pop_string(2)
405
+
406
+ subscript = script.subscript(last_code_separator_index..-1)
407
+ if sig_version == :base
408
+ tmp = subscript.find_and_delete(Script.new << sig)
409
+ return set_error(SCRIPT_ERR_SIG_FINDANDDELETE) if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
410
+ subscript = tmp
411
+ end
412
+
413
+ return false if !check_pubkey_encoding(pubkey, sig_version) || !check_signature_encoding(sig) # error already set.
414
+
415
+ success = checker.check_sig(sig, pubkey, subscript, sig_version)
416
+
417
+ # https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki#NULLFAIL
418
+ if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
419
+ return set_error(SCRIPT_ERR_SIG_NULLFAIL)
420
+ end
421
+
422
+ push_int(success ? 1 : 0)
423
+
424
+ if opcode == OP_CHECKSIGVERIFY
425
+ if success
426
+ stack.pop
427
+ else
428
+ return set_error(SCRIPT_ERR_CHECKSIGVERIFY)
429
+ end
430
+ end
431
+ when OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
432
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
433
+ pubkey_count = pop_int
434
+ unless (0..MAX_PUBKEYS_PER_MULTISIG).include?(pubkey_count)
435
+ return set_error(SCRIPT_ERR_PUBKEY_COUNT)
436
+ end
437
+
438
+ op_count += pubkey_count
439
+ return set_error(SCRIPT_ERR_OP_COUNT) if op_count > MAX_OPS_PER_SCRIPT
440
+
441
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < pubkey_count
442
+
443
+ pubkeys = pop_string(pubkey_count)
444
+ pubkeys = [pubkeys] if pubkeys.is_a?(String)
445
+
446
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
447
+
448
+ sig_count = pop_int
449
+ return set_error(SCRIPT_ERR_SIG_COUNT) if sig_count < 0 || sig_count > pubkey_count
450
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < (sig_count)
451
+
452
+ sigs = pop_string(sig_count)
453
+ sigs = [sigs] if sigs.is_a?(String)
454
+
455
+ subscript = script.subscript(last_code_separator_index..-1)
456
+
457
+ if sig_version == :base
458
+ sigs.each do |sig|
459
+ tmp = subscript.find_and_delete(Script.new << sig)
460
+ return set_error(SCRIPT_ERR_SIG_FINDANDDELETE) if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
461
+ subscript = tmp
462
+ end
463
+ end
464
+
465
+ success = true
466
+ while success && sig_count > 0
467
+ sig = sigs.pop
468
+ pubkey = pubkeys.pop
469
+ return false if !check_pubkey_encoding(pubkey, sig_version) || !check_signature_encoding(sig) # error already set.
470
+ ok = checker.check_sig(sig, pubkey, subscript, sig_version)
471
+ if ok
472
+ sig_count -= 1
473
+ else
474
+ sigs << sig
475
+ end
476
+ pubkey_count -= 1
477
+ success = false if sig_count > pubkey_count
478
+ end
479
+
480
+ if !success && flag?(SCRIPT_VERIFY_NULLFAIL)
481
+ sigs.each do |sig|
482
+ # If the operation failed, we require that all signatures must be empty vector
483
+ return set_error(SCRIPT_ERR_SIG_NULLFAIL) if sig.bytesize > 0
484
+ end
485
+ end
486
+
487
+ # A bug causes CHECKMULTISIG to consume one extra argument whose contents were not checked in any way.
488
+ # Unfortunately this is a potential source of mutability,
489
+ # so optionally verify it is exactly equal to zero prior to removing it from the stack.
490
+ return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
491
+ if flag?(SCRIPT_VERIFY_NULLDUMMY) && stack[-1].size > 0
492
+ return set_error(SCRIPT_ERR_SIG_NULLDUMMY)
493
+ end
494
+ stack.pop
495
+
496
+ push_int(success ? 1 : 0)
497
+ if opcode == OP_CHECKMULTISIGVERIFY
498
+ if success
499
+ stack.pop
500
+ else
501
+ return set_error(SCRIPT_ERR_CHECKMULTISIGVERIFY)
502
+ end
503
+ end
504
+ when OP_RETURN
505
+ return set_error(SCRIPT_ERR_OP_RETURN)
506
+ else
507
+ return set_error(SCRIPT_ERR_BAD_OPCODE)
508
+ end
509
+ end
510
+ end
511
+
512
+ # max stack size check
513
+ return set_error(SCRIPT_ERR_STACK_SIZE) if stack.size + alt_stack.size > MAX_STACK_SIZE
514
+ end
515
+ rescue Exception => e
516
+ puts e
517
+ puts e.backtrace
518
+ return set_error(SCRIPT_ERR_UNKNOWN_ERROR, e.message)
519
+ end
520
+
521
+ return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) unless flow_stack.empty?
522
+
523
+ set_error(SCRIPT_ERR_OK)
524
+ true
525
+ end
526
+
527
+ private
528
+
529
+ def flag?(flag)
530
+ (flags & flag) != 0
531
+ end
532
+
533
+ # pop the item with the int value for the number specified by +count+ from the stack.
534
+ def pop_int(count = 1)
535
+ i = stack.pop(count).map{ |s| cast_to_int(s) }
536
+ count == 1 ? i.first : i
537
+ end
538
+
539
+ # cast item to int value.
540
+ def cast_to_int(s, max_num_size = DEFAULT_MAX_NUM_SIZE)
541
+ data = s.htb
542
+ raise '"script number overflow"' if data.bytesize > max_num_size
543
+ if require_minimal && data.bytesize > 0
544
+ if data.bytes[-1] & 0x7f == 0 && (data.bytesize <= 1 || data.bytes[data.bytesize - 2] & 0x80 == 0)
545
+ raise 'non-minimally encoded script number'
546
+ end
547
+ end
548
+ Script.decode_number(s)
549
+ end
550
+
551
+ # push +i+ into stack as encoded by Script#encode_number
552
+ def push_int(i)
553
+ stack << Script.encode_number(i)
554
+ end
555
+
556
+ # pop the item with the string(hex) value for the number specified by +count+ from the stack.
557
+ def pop_string(count = 1)
558
+ s = stack.pop(count).map do |s|
559
+ case s
560
+ when Numeric
561
+ Script.encode_number(s)
562
+ else
563
+ s
564
+ end
565
+ end
566
+ count == 1 ? s.first : s
567
+ end
568
+
569
+ # pop the item with the boolean value from the stack.
570
+ def pop_bool
571
+ cast_to_bool(pop_string.htb)
572
+ end
573
+
574
+ # see https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L36-L49
575
+ def cast_to_bool(v)
576
+ case v
577
+ when Numeric
578
+ return v != 0
579
+ when String
580
+ v.each_byte.with_index do |b, i|
581
+ return !(i == (v.bytesize - 1) && b == 0x80) unless b == 0
582
+ end
583
+ false
584
+ else
585
+ false
586
+ end
587
+ end
588
+
589
+ def check_signature_encoding(sig)
590
+ return true if sig.size.zero?
591
+ if (flag?(SCRIPT_VERIFY_DERSIG) || flag?(SCRIPT_VERIFY_LOW_S) || flag?(SCRIPT_VERIFY_STRICTENC)) && !Key.valid_signature_encoding?(sig.htb)
592
+ return set_error(SCRIPT_ERR_SIG_DER)
593
+ elsif flag?(SCRIPT_VERIFY_LOW_S) && !low_der_signature?(sig)
594
+ return false
595
+ elsif flag?(SCRIPT_VERIFY_STRICTENC) && !defined_hashtype_signature?(sig)
596
+ return set_error(SCRIPT_ERR_SIG_HASHTYPE)
597
+ end
598
+ true
599
+ end
600
+
601
+ def low_der_signature?(sig)
602
+ return set_error(SCRIPT_ERR_SIG_DER) unless Key.valid_signature_encoding?(sig.htb)
603
+ return set_error(SCRIPT_ERR_SIG_HIGH_S) unless Key.low_signature?(sig.htb)
604
+ true
605
+ end
606
+
607
+ def defined_hashtype_signature?(signature)
608
+ sig = signature.htb
609
+ return false if sig.empty?
610
+ s = sig.unpack('C*')
611
+ hash_type = s[-1] & (~(SIGHASH_TYPE[:anyonecanpay]))
612
+ hash_type &= (~(Tapyrus::SIGHASH_FORK_ID)) if Tapyrus.chain_params.fork_chain? # for fork coin.
613
+ return false if hash_type < SIGHASH_TYPE[:all] || hash_type > SIGHASH_TYPE[:single]
614
+ true
615
+ end
616
+
617
+ def check_pubkey_encoding(pubkey, sig_version)
618
+ if flag?(SCRIPT_VERIFY_STRICTENC) && !Key.compress_or_uncompress_pubkey?(pubkey)
619
+ return set_error(SCRIPT_ERR_PUBKEYTYPE)
620
+ end
621
+ # Only compressed keys are accepted in segwit
622
+ if flag?(SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) &&
623
+ sig_version == :witness_v0 && !Key.compress_pubkey?(pubkey)
624
+ return set_error(SCRIPT_ERR_WITNESS_PUBKEYTYPE)
625
+ end
626
+ true
627
+ end
628
+
629
+ def minimal_push?(data, opcode)
630
+ if data.bytesize.zero?
631
+ return opcode == OP_0
632
+ elsif data.bytesize == 1 && data.bytes[0] >= 1 && data.bytes[0] <= 16
633
+ return opcode == OP_1 + (data.bytes[0] - 1)
634
+ elsif data.bytesize == 1 && data.bytes[0] == 0x81
635
+ return opcode == OP_1NEGATE
636
+ elsif data.bytesize <= 75
637
+ return opcode == data.bytesize
638
+ elsif data.bytesize <= 255
639
+ return opcode == OP_PUSHDATA1
640
+ elsif data.bytesize <= 65535
641
+ return opcode == OP_PUSHDATA2
642
+ end
643
+ true
644
+ end
645
+
646
+ def verify_pushdata_length(chunk)
647
+ buf = StringIO.new(chunk)
648
+ opcode = buf.read(1).ord
649
+ offset = 1
650
+ len = case opcode
651
+ when OP_PUSHDATA1
652
+ offset += 1
653
+ buf.read(1).unpack('C').first
654
+ when OP_PUSHDATA2
655
+ offset += 2
656
+ buf.read(2).unpack('v').first
657
+ when OP_PUSHDATA4
658
+ offset += 4
659
+ buf.read(4).unpack('V').first
660
+ else
661
+ opcode
662
+ end
663
+ chunk.bytesize == len + offset
664
+ end
665
+
666
+ end
667
+
668
+ end