tapyrus 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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