tapyrus 0.2.7 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +37 -0
- data/.prettierignore +3 -0
- data/.prettierrc.yaml +3 -0
- data/CODE_OF_CONDUCT.md +7 -7
- data/README.md +14 -17
- data/Rakefile +3 -3
- data/lib/openassets.rb +0 -2
- data/lib/openassets/marker_output.rb +0 -4
- data/lib/openassets/payload.rb +4 -10
- data/lib/schnorr.rb +2 -3
- data/lib/schnorr/signature.rb +3 -6
- data/lib/tapyrus.rb +6 -22
- data/lib/tapyrus/base58.rb +7 -6
- data/lib/tapyrus/block.rb +1 -2
- data/lib/tapyrus/block_header.rb +15 -9
- data/lib/tapyrus/bloom_filter.rb +5 -3
- data/lib/tapyrus/chain_params.rb +1 -4
- data/lib/tapyrus/chainparams/dev.yml +3 -2
- data/lib/tapyrus/chainparams/prod.yml +3 -2
- data/lib/tapyrus/constants.rb +29 -23
- data/lib/tapyrus/errors.rb +1 -3
- data/lib/tapyrus/ext.rb +1 -1
- data/lib/tapyrus/ext/ecdsa.rb +4 -4
- data/lib/tapyrus/ext/json_parser.rb +1 -4
- data/lib/tapyrus/ext_key.rb +38 -34
- data/lib/tapyrus/key.rb +31 -35
- data/lib/tapyrus/key_path.rb +15 -12
- data/lib/tapyrus/logger.rb +20 -16
- data/lib/tapyrus/merkle_tree.rb +19 -20
- data/lib/tapyrus/message.rb +14 -16
- data/lib/tapyrus/message/addr.rb +1 -7
- data/lib/tapyrus/message/base.rb +0 -3
- data/lib/tapyrus/message/block.rb +2 -9
- data/lib/tapyrus/message/block_transaction_request.rb +3 -6
- data/lib/tapyrus/message/block_transactions.rb +2 -6
- data/lib/tapyrus/message/block_txn.rb +0 -4
- data/lib/tapyrus/message/cmpct_block.rb +1 -7
- data/lib/tapyrus/message/error.rb +1 -4
- data/lib/tapyrus/message/fee_filter.rb +1 -4
- data/lib/tapyrus/message/filter_add.rb +0 -4
- data/lib/tapyrus/message/filter_clear.rb +0 -4
- data/lib/tapyrus/message/filter_load.rb +2 -5
- data/lib/tapyrus/message/get_addr.rb +0 -4
- data/lib/tapyrus/message/get_block_txn.rb +0 -4
- data/lib/tapyrus/message/get_blocks.rb +0 -3
- data/lib/tapyrus/message/get_data.rb +1 -4
- data/lib/tapyrus/message/get_headers.rb +1 -3
- data/lib/tapyrus/message/header_and_short_ids.rb +3 -9
- data/lib/tapyrus/message/headers.rb +0 -4
- data/lib/tapyrus/message/headers_parser.rb +3 -8
- data/lib/tapyrus/message/inv.rb +1 -4
- data/lib/tapyrus/message/inventories_parser.rb +2 -7
- data/lib/tapyrus/message/inventory.rb +12 -5
- data/lib/tapyrus/message/mem_pool.rb +0 -4
- data/lib/tapyrus/message/merkle_block.rb +4 -9
- data/lib/tapyrus/message/network_addr.rb +7 -6
- data/lib/tapyrus/message/not_found.rb +0 -3
- data/lib/tapyrus/message/ping.rb +0 -3
- data/lib/tapyrus/message/pong.rb +0 -3
- data/lib/tapyrus/message/prefilled_tx.rb +0 -4
- data/lib/tapyrus/message/reject.rb +0 -3
- data/lib/tapyrus/message/send_cmpct.rb +1 -3
- data/lib/tapyrus/message/send_headers.rb +0 -3
- data/lib/tapyrus/message/tx.rb +0 -4
- data/lib/tapyrus/message/ver_ack.rb +1 -5
- data/lib/tapyrus/message/version.rb +2 -5
- data/lib/tapyrus/mnemonic.rb +17 -15
- data/lib/tapyrus/network.rb +0 -2
- data/lib/tapyrus/network/connection.rb +0 -3
- data/lib/tapyrus/network/message_handler.rb +61 -60
- data/lib/tapyrus/network/peer.rb +13 -12
- data/lib/tapyrus/network/peer_discovery.rb +3 -5
- data/lib/tapyrus/network/pool.rb +12 -12
- data/lib/tapyrus/node.rb +1 -1
- data/lib/tapyrus/node/cli.rb +12 -14
- data/lib/tapyrus/node/configuration.rb +1 -3
- data/lib/tapyrus/node/spv.rb +2 -3
- data/lib/tapyrus/opcodes.rb +9 -7
- data/lib/tapyrus/out_point.rb +5 -5
- data/lib/tapyrus/rpc/http_server.rb +21 -22
- data/lib/tapyrus/rpc/request_handler.rb +42 -44
- data/lib/tapyrus/rpc/tapyrus_core_client.rb +53 -25
- data/lib/tapyrus/script/color.rb +10 -0
- data/lib/tapyrus/script/multisig.rb +13 -12
- data/lib/tapyrus/script/script.rb +72 -71
- data/lib/tapyrus/script/script_error.rb +1 -4
- data/lib/tapyrus/script/script_interpreter.rb +439 -399
- data/lib/tapyrus/script/tx_checker.rb +20 -10
- data/lib/tapyrus/secp256k1.rb +0 -4
- data/lib/tapyrus/secp256k1/native.rb +14 -15
- data/lib/tapyrus/secp256k1/rfc6979.rb +7 -4
- data/lib/tapyrus/secp256k1/ruby.rb +10 -12
- data/lib/tapyrus/slip39.rb +20 -5
- data/lib/tapyrus/slip39/share.rb +41 -29
- data/lib/tapyrus/slip39/sss.rb +101 -57
- data/lib/tapyrus/store.rb +1 -3
- data/lib/tapyrus/store/chain_entry.rb +0 -4
- data/lib/tapyrus/store/db.rb +0 -2
- data/lib/tapyrus/store/db/level_db.rb +5 -9
- data/lib/tapyrus/store/spv_chain.rb +11 -17
- data/lib/tapyrus/tx.rb +45 -37
- data/lib/tapyrus/tx_builder.rb +158 -0
- data/lib/tapyrus/tx_in.rb +1 -6
- data/lib/tapyrus/tx_out.rb +2 -7
- data/lib/tapyrus/util.rb +7 -9
- data/lib/tapyrus/validation.rb +12 -11
- data/lib/tapyrus/version.rb +1 -1
- data/lib/tapyrus/wallet/account.rb +22 -18
- data/lib/tapyrus/wallet/base.rb +12 -9
- data/lib/tapyrus/wallet/db.rb +6 -9
- data/lib/tapyrus/wallet/master_key.rb +2 -4
- data/tapyrusrb.gemspec +13 -14
- metadata +21 -4
- data/.travis.yml +0 -14
@@ -1,8 +1,6 @@
|
|
1
1
|
module Tapyrus
|
2
|
-
|
3
2
|
# tapyrus script error
|
4
3
|
class ScriptError < Exception
|
5
|
-
|
6
4
|
attr_accessor :code
|
7
5
|
attr_accessor :extra_msg
|
8
6
|
|
@@ -100,6 +98,5 @@ module Tapyrus
|
|
100
98
|
def self.name_to_code(name)
|
101
99
|
NAME_MAP[name]
|
102
100
|
end
|
103
|
-
|
104
101
|
end
|
105
|
-
end
|
102
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
module Tapyrus
|
2
|
-
|
3
2
|
class ScriptInterpreter
|
4
|
-
|
5
3
|
include Tapyrus::Opcodes
|
6
4
|
|
7
5
|
attr_reader :stack
|
@@ -11,8 +9,23 @@ module Tapyrus
|
|
11
9
|
attr_reader :checker
|
12
10
|
attr_reader :require_minimal
|
13
11
|
|
14
|
-
DISABLE_OPCODES = [
|
15
|
-
|
12
|
+
DISABLE_OPCODES = [
|
13
|
+
OP_CAT,
|
14
|
+
OP_SUBSTR,
|
15
|
+
OP_LEFT,
|
16
|
+
OP_RIGHT,
|
17
|
+
OP_INVERT,
|
18
|
+
OP_AND,
|
19
|
+
OP_OR,
|
20
|
+
OP_XOR,
|
21
|
+
OP_2MUL,
|
22
|
+
OP_2DIV,
|
23
|
+
OP_DIV,
|
24
|
+
OP_MUL,
|
25
|
+
OP_MOD,
|
26
|
+
OP_LSHIFT,
|
27
|
+
OP_RSHIFT
|
28
|
+
]
|
16
29
|
|
17
30
|
# syntax sugar for simple evaluation for script.
|
18
31
|
# @param [Tapyrus::Script] script_sig a scriptSig.
|
@@ -34,7 +47,6 @@ module Tapyrus
|
|
34
47
|
# @param [Tapyrus::Script] script_pubkey a script pubkey (locking script)
|
35
48
|
# @return [Boolean] result
|
36
49
|
def verify_script(script_sig, script_pubkey)
|
37
|
-
|
38
50
|
return set_error(SCRIPT_ERR_SIG_PUSHONLY) if flag?(SCRIPT_VERIFY_SIGPUSHONLY) && !script_sig.push_only?
|
39
51
|
|
40
52
|
stack_copy = nil
|
@@ -97,9 +109,7 @@ module Tapyrus
|
|
97
109
|
opcode = c.opcode
|
98
110
|
|
99
111
|
if need_exec && c.pushdata?
|
100
|
-
if require_minimal && !minimal_push?(c.pushed_data, opcode)
|
101
|
-
return set_error(SCRIPT_ERR_MINIMALDATA)
|
102
|
-
end
|
112
|
+
return set_error(SCRIPT_ERR_MINIMALDATA) if require_minimal && !minimal_push?(c.pushed_data, opcode)
|
103
113
|
return set_error(SCRIPT_ERR_BAD_OPCODE) unless verify_pushdata_length(c)
|
104
114
|
stack << c.pushed_data.bth
|
105
115
|
else
|
@@ -107,385 +117,415 @@ module Tapyrus
|
|
107
117
|
return set_error(SCRIPT_ERR_OP_COUNT)
|
108
118
|
end
|
109
119
|
return set_error(SCRIPT_ERR_DISABLED_OPCODE) if DISABLE_OPCODES.include?(opcode)
|
110
|
-
|
120
|
+
if opcode == OP_CODESEPARATOR && sig_version == :base && flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE)
|
121
|
+
return set_error(SCRIPT_ERR_OP_CODESEPARATOR)
|
122
|
+
end
|
111
123
|
next unless (need_exec || (OP_IF <= opcode && opcode <= OP_ENDIF))
|
112
124
|
small_int = Opcodes.opcode_to_small_int(opcode)
|
113
125
|
if small_int && opcode != OP_0
|
114
126
|
push_int(small_int)
|
115
127
|
else
|
116
128
|
case opcode
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
end
|
129
|
+
when OP_0
|
130
|
+
stack << ''
|
131
|
+
when OP_DEPTH
|
132
|
+
push_int(stack.size)
|
133
|
+
when OP_EQUAL, OP_EQUALVERIFY
|
134
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
135
|
+
a, b = pop_string(2)
|
136
|
+
result = a == b
|
137
|
+
push_int(result ? 1 : 0)
|
138
|
+
if opcode == OP_EQUALVERIFY
|
139
|
+
if result
|
140
|
+
stack.pop
|
141
|
+
else
|
142
|
+
return set_error(SCRIPT_ERR_EQUALVERIFY)
|
132
143
|
end
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
144
|
+
end
|
145
|
+
when OP_0NOTEQUAL
|
146
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
147
|
+
push_int(pop_int == 0 ? 0 : 1)
|
148
|
+
when OP_ADD
|
149
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
150
|
+
a, b = pop_int(2)
|
151
|
+
push_int(a + b)
|
152
|
+
when OP_1ADD
|
153
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
154
|
+
push_int(pop_int + 1)
|
155
|
+
when OP_SUB
|
156
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
157
|
+
a, b = pop_int(2)
|
158
|
+
push_int(a - b)
|
159
|
+
when OP_1SUB
|
160
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
161
|
+
push_int(pop_int - 1)
|
162
|
+
when OP_IF, OP_NOTIF
|
163
|
+
result = false
|
164
|
+
if need_exec
|
165
|
+
return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if stack.size < 1
|
166
|
+
value = pop_string.htb
|
167
|
+
if flag?(SCRIPT_VERIFY_MINIMALIF)
|
168
|
+
if value.bytesize > 1 || (value.bytesize == 1 && value[0].unpack('C').first != 1)
|
169
|
+
return set_error(SCRIPT_ERR_MINIMALIF)
|
159
170
|
end
|
160
|
-
result = cast_to_bool(value)
|
161
|
-
result = !result if opcode == OP_NOTIF
|
162
171
|
end
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
172
|
+
result = cast_to_bool(value)
|
173
|
+
result = !result if opcode == OP_NOTIF
|
174
|
+
end
|
175
|
+
flow_stack << result
|
176
|
+
when OP_ELSE
|
177
|
+
return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.size < 1
|
178
|
+
flow_stack << !flow_stack.pop
|
179
|
+
when OP_ENDIF
|
180
|
+
return set_error(SCRIPT_ERR_UNBALANCED_CONDITIONAL) if flow_stack.empty?
|
181
|
+
flow_stack.pop
|
182
|
+
when OP_NOP
|
183
|
+
when OP_NOP1, OP_NOP4..OP_NOP10
|
184
|
+
if flag?(SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
|
185
|
+
return set_error(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS)
|
186
|
+
end
|
187
|
+
when OP_CHECKLOCKTIMEVERIFY
|
188
|
+
next unless flag?(SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
|
189
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
190
|
+
|
191
|
+
# Note that elsewhere numeric opcodes are limited to operands in the range -2**31+1 to 2**31-1,
|
192
|
+
# however it is legal for opcodes to produce results exceeding that range.
|
193
|
+
# This limitation is implemented by CScriptNum's default 4-byte limit.
|
194
|
+
# If we kept to that limit we'd have a year 2038 problem,
|
195
|
+
# even though the nLockTime field in transactions themselves is uint32 which only becomes meaningless after the year 2106.
|
196
|
+
# Thus as a special case we tell CScriptNum to accept up to 5-byte bignums,
|
197
|
+
# which are good until 2**39-1, well beyond the 2**32-1 limit of the nLockTime field itself.
|
198
|
+
locktime = cast_to_int(stack.last, 5)
|
199
|
+
return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if locktime < 0
|
200
|
+
return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME) unless checker.check_locktime(locktime)
|
201
|
+
when OP_CHECKSEQUENCEVERIFY
|
202
|
+
next unless flag?(SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
|
203
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
204
|
+
|
205
|
+
# nSequence, like nLockTime, is a 32-bit unsigned integer field.
|
206
|
+
# See the comment in CHECKLOCKTIMEVERIFY regarding 5-byte numeric operands.
|
207
|
+
sequence = cast_to_int(stack.last, 5)
|
208
|
+
|
209
|
+
# In the rare event that the argument may be < 0 due to some arithmetic being done first,
|
210
|
+
# you can always use 0 MAX CHECKSEQUENCEVERIFY.
|
211
|
+
return set_error(SCRIPT_ERR_NEGATIVE_LOCKTIME) if sequence < 0
|
212
|
+
|
213
|
+
# To provide for future soft-fork extensibility,
|
214
|
+
# if the operand has the disabled lock-time flag set, CHECKSEQUENCEVERIFY behaves as a NOP.
|
215
|
+
next if (sequence & Tapyrus::TxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0
|
216
|
+
|
217
|
+
# Compare the specified sequence number with the input.
|
218
|
+
return set_error(SCRIPT_ERR_UNSATISFIED_LOCKTIME) unless checker.check_sequence(sequence)
|
219
|
+
when OP_DUP
|
220
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
221
|
+
stack << stack.last
|
222
|
+
when OP_2DUP
|
223
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
224
|
+
2.times { stack << stack[-2] }
|
225
|
+
when OP_3DUP
|
226
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
227
|
+
3.times { stack << stack[-3] }
|
228
|
+
when OP_IFDUP
|
229
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
230
|
+
stack << stack.last if cast_to_bool(stack.last)
|
231
|
+
when OP_RIPEMD160
|
232
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
233
|
+
stack << Digest::RMD160.hexdigest(pop_string.htb)
|
234
|
+
when OP_SHA1
|
235
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
236
|
+
stack << Digest::SHA1.hexdigest(pop_string.htb)
|
237
|
+
when OP_SHA256
|
238
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
239
|
+
stack << Digest::SHA256.hexdigest(pop_string.htb)
|
240
|
+
when OP_HASH160
|
241
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
242
|
+
stack << Tapyrus.hash160(pop_string)
|
243
|
+
when OP_HASH256
|
244
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
245
|
+
stack << Tapyrus.double_sha256(pop_string.htb).bth
|
246
|
+
when OP_VERIFY
|
247
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
248
|
+
return set_error(SCRIPT_ERR_VERIFY) unless pop_bool
|
249
|
+
when OP_TOALTSTACK
|
250
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
251
|
+
alt_stack << stack.pop
|
252
|
+
when OP_FROMALTSTACK
|
253
|
+
return set_error(SCRIPT_ERR_INVALID_ALTSTACK_OPERATION) if alt_stack.size < 1
|
254
|
+
stack << alt_stack.pop
|
255
|
+
when OP_DROP
|
256
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
257
|
+
stack.pop
|
258
|
+
when OP_2DROP
|
259
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
260
|
+
2.times { stack.pop }
|
261
|
+
when OP_NIP
|
262
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
263
|
+
stack.delete_at(-2)
|
264
|
+
when OP_OVER
|
265
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
266
|
+
stack << stack[-2]
|
267
|
+
when OP_2OVER
|
268
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
|
269
|
+
2.times { stack << stack[-4] }
|
270
|
+
when OP_PICK, OP_ROLL
|
271
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
272
|
+
pos = pop_int
|
273
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if pos < 0 || pos >= stack.size
|
274
|
+
stack << stack[-pos - 1]
|
275
|
+
stack.delete_at(-pos - 2) if opcode == OP_ROLL
|
276
|
+
when OP_ROT
|
277
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
278
|
+
stack << stack[-3]
|
279
|
+
stack.delete_at(-4)
|
280
|
+
when OP_2ROT
|
281
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 6
|
282
|
+
2.times { stack << stack[-6] }
|
283
|
+
2.times { stack.delete_at(-7) }
|
284
|
+
when OP_SWAP
|
285
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
286
|
+
tmp = stack.last
|
287
|
+
stack[-1] = stack[-2]
|
288
|
+
stack[-2] = tmp
|
289
|
+
when OP_2SWAP
|
290
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
|
291
|
+
2.times { stack << stack[-4] }
|
292
|
+
2.times { stack.delete_at(-5) }
|
293
|
+
when OP_TUCK
|
294
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
295
|
+
stack.insert(-3, stack.last)
|
296
|
+
when OP_ABS
|
297
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
298
|
+
v = pop_int
|
299
|
+
push_int(v.abs)
|
300
|
+
when OP_BOOLAND
|
301
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
302
|
+
a, b = pop_int(2)
|
303
|
+
push_int((!a.zero? && !b.zero?) ? 1 : 0)
|
304
|
+
when OP_BOOLOR
|
305
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
306
|
+
a, b = pop_int(2)
|
307
|
+
push_int((!a.zero? || !b.zero?) ? 1 : 0)
|
308
|
+
when OP_NUMEQUAL, OP_NUMEQUALVERIFY
|
309
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
310
|
+
a, b = pop_int(2)
|
311
|
+
result = a == b
|
312
|
+
push_int(result ? 1 : 0)
|
313
|
+
if opcode == OP_NUMEQUALVERIFY
|
314
|
+
if result
|
315
|
+
stack.pop
|
316
|
+
else
|
317
|
+
return set_error(SCRIPT_ERR_NUMEQUALVERIFY)
|
205
318
|
end
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
when OP_2OVER
|
255
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
|
256
|
-
2.times { stack << stack[-4]}
|
257
|
-
when OP_PICK, OP_ROLL
|
258
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
259
|
-
pos = pop_int
|
260
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if pos < 0 || pos >= stack.size
|
261
|
-
stack << stack[-pos - 1]
|
262
|
-
stack.delete_at(-pos - 2) if opcode == OP_ROLL
|
263
|
-
when OP_ROT
|
264
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
265
|
-
stack << stack[-3]
|
266
|
-
stack.delete_at(-4)
|
267
|
-
when OP_2ROT
|
268
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 6
|
269
|
-
2.times { stack << stack[-6] }
|
270
|
-
2.times { stack.delete_at(-7) }
|
271
|
-
when OP_SWAP
|
272
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
273
|
-
tmp = stack.last
|
274
|
-
stack[-1] = stack[-2]
|
275
|
-
stack[-2] = tmp
|
276
|
-
when OP_2SWAP
|
277
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 4
|
278
|
-
2.times {stack << stack[-4]}
|
279
|
-
2.times {stack.delete_at(-5)}
|
280
|
-
when OP_TUCK
|
281
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
282
|
-
stack.insert(-3, stack.last)
|
283
|
-
when OP_ABS
|
284
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
285
|
-
v = pop_int
|
286
|
-
push_int(v.abs)
|
287
|
-
when OP_BOOLAND
|
288
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
289
|
-
a, b = pop_int(2)
|
290
|
-
push_int((!a.zero? && !b.zero?) ? 1 : 0)
|
291
|
-
when OP_BOOLOR
|
292
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
293
|
-
a, b = pop_int(2)
|
294
|
-
push_int((!a.zero? || !b.zero?) ? 1 : 0)
|
295
|
-
when OP_NUMEQUAL, OP_NUMEQUALVERIFY
|
296
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
297
|
-
a, b = pop_int(2)
|
298
|
-
result = a == b
|
299
|
-
push_int(result ? 1 : 0)
|
300
|
-
if opcode == OP_NUMEQUALVERIFY
|
301
|
-
if result
|
302
|
-
stack.pop
|
303
|
-
else
|
304
|
-
return set_error(SCRIPT_ERR_NUMEQUALVERIFY)
|
305
|
-
end
|
319
|
+
end
|
320
|
+
when OP_LESSTHAN, OP_LESSTHANOREQUAL
|
321
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
322
|
+
a, b = pop_int(2)
|
323
|
+
push_int(a < b ? 1 : 0) if opcode == OP_LESSTHAN
|
324
|
+
push_int(a <= b ? 1 : 0) if opcode == OP_LESSTHANOREQUAL
|
325
|
+
when OP_GREATERTHAN, OP_GREATERTHANOREQUAL
|
326
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
327
|
+
a, b = pop_int(2)
|
328
|
+
push_int(a > b ? 1 : 0) if opcode == OP_GREATERTHAN
|
329
|
+
push_int(a >= b ? 1 : 0) if opcode == OP_GREATERTHANOREQUAL
|
330
|
+
when OP_MIN
|
331
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
332
|
+
push_int(pop_int(2).min)
|
333
|
+
when OP_MAX
|
334
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
335
|
+
push_int(pop_int(2).max)
|
336
|
+
when OP_WITHIN
|
337
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
338
|
+
x, a, b = pop_int(3)
|
339
|
+
push_int((a <= x && x < b) ? 1 : 0)
|
340
|
+
when OP_NOT
|
341
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
342
|
+
push_int(pop_int == 0 ? 1 : 0)
|
343
|
+
when OP_SIZE
|
344
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
345
|
+
item = stack.last
|
346
|
+
item = Tapyrus::Script.encode_number(item) if item.is_a?(Numeric)
|
347
|
+
size = item.htb.bytesize
|
348
|
+
push_int(size)
|
349
|
+
when OP_NEGATE
|
350
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
351
|
+
push_int(-pop_int)
|
352
|
+
when OP_NUMNOTEQUAL
|
353
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
354
|
+
a, b = pop_int(2)
|
355
|
+
push_int(a == b ? 0 : 1)
|
356
|
+
when OP_CODESEPARATOR
|
357
|
+
last_code_separator_index = index + 1
|
358
|
+
when OP_CHECKSIG, OP_CHECKSIGVERIFY
|
359
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
360
|
+
sig, pubkey = pop_string(2)
|
361
|
+
|
362
|
+
subscript = script.subscript(last_code_separator_index..-1)
|
363
|
+
if sig_version == :base
|
364
|
+
tmp = subscript.find_and_delete(Script.new << sig)
|
365
|
+
if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
|
366
|
+
return set_error(SCRIPT_ERR_SIG_FINDANDDELETE)
|
306
367
|
end
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
item = Tapyrus::Script.encode_number(item) if item.is_a?(Numeric)
|
334
|
-
size = item.htb.bytesize
|
335
|
-
push_int(size)
|
336
|
-
when OP_NEGATE
|
337
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
338
|
-
push_int(-pop_int)
|
339
|
-
when OP_NUMNOTEQUAL
|
340
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
341
|
-
a, b = pop_int(2)
|
342
|
-
push_int(a == b ? 0 : 1)
|
343
|
-
when OP_CODESEPARATOR
|
344
|
-
last_code_separator_index = index + 1
|
345
|
-
when OP_CHECKSIG, OP_CHECKSIGVERIFY
|
346
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 2
|
347
|
-
sig, pubkey = pop_string(2)
|
348
|
-
|
349
|
-
subscript = script.subscript(last_code_separator_index..-1)
|
350
|
-
if sig_version == :base
|
351
|
-
tmp = subscript.find_and_delete(Script.new << sig)
|
352
|
-
return set_error(SCRIPT_ERR_SIG_FINDANDDELETE) if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
|
353
|
-
subscript = tmp
|
368
|
+
subscript = tmp
|
369
|
+
end
|
370
|
+
if (
|
371
|
+
if sig.htb.bytesize == Tapyrus::Key::COMPACT_SIGNATURE_SIZE
|
372
|
+
!check_schnorr_signature_encoding(sig)
|
373
|
+
else
|
374
|
+
!check_ecdsa_signature_encoding(sig)
|
375
|
+
end
|
376
|
+
) || !check_pubkey_encoding(pubkey)
|
377
|
+
return false
|
378
|
+
end
|
379
|
+
|
380
|
+
success = checker.check_sig(sig, pubkey, subscript, sig_version)
|
381
|
+
|
382
|
+
# https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki#NULLFAIL
|
383
|
+
if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
|
384
|
+
return set_error(SCRIPT_ERR_SIG_NULLFAIL)
|
385
|
+
end
|
386
|
+
|
387
|
+
push_int(success ? 1 : 0)
|
388
|
+
|
389
|
+
if opcode == OP_CHECKSIGVERIFY
|
390
|
+
if success
|
391
|
+
stack.pop
|
392
|
+
else
|
393
|
+
return set_error(SCRIPT_ERR_CHECKSIGVERIFY)
|
354
394
|
end
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
return set_error(
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < (sig_count)
|
407
|
-
|
408
|
-
sigs = pop_string(sig_count)
|
409
|
-
sigs = [sigs] if sigs.is_a?(String)
|
410
|
-
|
411
|
-
subscript = script.subscript(last_code_separator_index..-1)
|
412
|
-
|
413
|
-
if sig_version == :base
|
414
|
-
sigs.each do |sig|
|
415
|
-
tmp = subscript.find_and_delete(Script.new << sig)
|
416
|
-
return set_error(SCRIPT_ERR_SIG_FINDANDDELETE) if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
|
417
|
-
subscript = tmp
|
395
|
+
end
|
396
|
+
when OP_CHECKDATASIG, OP_CHECKDATASIGVERIFY
|
397
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 3
|
398
|
+
sig, msg, pubkey = pop_string(3)
|
399
|
+
|
400
|
+
# check signature encoding without hashtype byte
|
401
|
+
if (
|
402
|
+
sig.htb.bytesize != (Tapyrus::Key::COMPACT_SIGNATURE_SIZE - 1) &&
|
403
|
+
!check_ecdsa_signature_encoding(sig, true)
|
404
|
+
) || !check_pubkey_encoding(pubkey)
|
405
|
+
return false
|
406
|
+
end
|
407
|
+
digest = Tapyrus.sha256(msg)
|
408
|
+
success = checker.verify_sig(sig, pubkey, digest)
|
409
|
+
if !success && flag?(SCRIPT_VERIFY_NULLFAIL) && sig.bytesize > 0
|
410
|
+
return set_error(SCRIPT_ERR_SIG_NULLFAIL)
|
411
|
+
end
|
412
|
+
push_int(success ? 1 : 0)
|
413
|
+
if opcode == OP_CHECKDATASIGVERIFY
|
414
|
+
stack.pop if success
|
415
|
+
return set_error(SCRIPT_ERR_CHECKDATASIGVERIFY) unless success
|
416
|
+
end
|
417
|
+
when OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY
|
418
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
419
|
+
pubkey_count = pop_int
|
420
|
+
return set_error(SCRIPT_ERR_PUBKEY_COUNT) unless (0..MAX_PUBKEYS_PER_MULTISIG).include?(pubkey_count)
|
421
|
+
|
422
|
+
op_count += pubkey_count
|
423
|
+
return set_error(SCRIPT_ERR_OP_COUNT) if op_count > MAX_OPS_PER_SCRIPT
|
424
|
+
|
425
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < pubkey_count
|
426
|
+
|
427
|
+
pubkeys = pop_string(pubkey_count)
|
428
|
+
pubkeys = [pubkeys] if pubkeys.is_a?(String)
|
429
|
+
|
430
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
431
|
+
|
432
|
+
sig_count = pop_int
|
433
|
+
return set_error(SCRIPT_ERR_SIG_COUNT) if sig_count < 0 || sig_count > pubkey_count
|
434
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < (sig_count)
|
435
|
+
|
436
|
+
sigs = pop_string(sig_count)
|
437
|
+
sigs = [sigs] if sigs.is_a?(String)
|
438
|
+
|
439
|
+
subscript = script.subscript(last_code_separator_index..-1)
|
440
|
+
|
441
|
+
if sig_version == :base
|
442
|
+
sigs.each do |sig|
|
443
|
+
tmp = subscript.find_and_delete(Script.new << sig)
|
444
|
+
if flag?(SCRIPT_VERIFY_CONST_SCRIPTCODE) && tmp != subscript
|
445
|
+
return set_error(SCRIPT_ERR_SIG_FINDANDDELETE)
|
418
446
|
end
|
447
|
+
subscript = tmp
|
419
448
|
end
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
449
|
+
end
|
450
|
+
|
451
|
+
success = true
|
452
|
+
current_sig_scheme = nil
|
453
|
+
while success && sig_count > 0
|
454
|
+
sig = sigs.pop
|
455
|
+
pubkey = pubkeys.pop
|
456
|
+
sig_scheme = sig.htb.bytesize == Tapyrus::Key::COMPACT_SIGNATURE_SIZE ? :schnorr : :ecdsa
|
457
|
+
current_sig_scheme = sig_scheme if current_sig_scheme.nil?
|
458
|
+
|
459
|
+
if (
|
460
|
+
if sig_scheme == :schnorr
|
461
|
+
!check_schnorr_signature_encoding(sig)
|
462
|
+
else
|
463
|
+
!check_ecdsa_signature_encoding(sig)
|
464
|
+
end
|
465
|
+
) || !check_pubkey_encoding(pubkey)
|
466
|
+
return false
|
467
|
+
end # error already set.
|
468
|
+
|
469
|
+
return set_error(SCRIPT_ERR_MIXED_SCHEME_MULTISIG) unless sig_scheme == current_sig_scheme
|
470
|
+
|
471
|
+
ok = checker.check_sig(sig, pubkey, subscript, sig_version)
|
472
|
+
if ok
|
473
|
+
sig_count -= 1
|
474
|
+
else
|
475
|
+
sigs << sig
|
441
476
|
end
|
442
|
-
|
443
|
-
if
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
477
|
+
pubkey_count -= 1
|
478
|
+
success = false if sig_count > pubkey_count
|
479
|
+
end
|
480
|
+
|
481
|
+
if !success && flag?(SCRIPT_VERIFY_NULLFAIL)
|
482
|
+
sigs.each do |sig|
|
483
|
+
# If the operation failed, we require that all signatures must be empty vector
|
484
|
+
return set_error(SCRIPT_ERR_SIG_NULLFAIL) if sig.bytesize > 0
|
448
485
|
end
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
486
|
+
end
|
487
|
+
|
488
|
+
# A bug causes CHECKMULTISIG to consume one extra argument whose contents were not checked in any way.
|
489
|
+
# Unfortunately this is a potential source of mutability,
|
490
|
+
# so optionally verify it is exactly equal to zero prior to removing it from the stack.
|
491
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
492
|
+
return set_error(SCRIPT_ERR_SIG_NULLDUMMY) if stack[-1].size > 0
|
493
|
+
|
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)
|
465
502
|
end
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
503
|
+
end
|
504
|
+
when OP_RETURN
|
505
|
+
return set_error(SCRIPT_ERR_OP_RETURN)
|
506
|
+
when OP_COLOR
|
507
|
+
# Color id is not permitted in p2sh redeem script
|
508
|
+
return set_error(SCRIPT_ERR_OP_COLOR_UNEXPECTED) if is_redeem_script
|
471
509
|
|
472
|
-
|
473
|
-
|
510
|
+
# if Color id is already initialized this must be an extra
|
511
|
+
if color_id && color_id.type != Tapyrus::Color::TokenTypes::NONE
|
512
|
+
return set_error(SCRIPT_ERR_OP_COLOR_MULTIPLE)
|
513
|
+
end
|
474
514
|
|
475
|
-
|
476
|
-
|
515
|
+
# color id is not allowed inside OP_IF
|
516
|
+
return set_error(SCRIPT_ERR_OP_COLOR_IN_BRANCH) unless flow_stack.empty?
|
477
517
|
|
478
|
-
|
479
|
-
|
518
|
+
# pop one stack element and verify that it exists
|
519
|
+
return set_error(SCRIPT_ERR_INVALID_STACK_OPERATION) if stack.size < 1
|
480
520
|
|
481
|
-
|
521
|
+
color_id = Tapyrus::Color::ColorIdentifier.parse_from_payload(stack.last.htb)
|
482
522
|
|
483
|
-
|
484
|
-
|
523
|
+
# check ColorIdentifier is valid
|
524
|
+
return set_error(SCRIPT_ERR_OP_COLOR_ID_INVALID) unless color_id.valid?
|
485
525
|
|
486
|
-
|
487
|
-
|
488
|
-
|
526
|
+
stack.pop
|
527
|
+
else
|
528
|
+
return set_error(SCRIPT_ERR_BAD_OPCODE)
|
489
529
|
end
|
490
530
|
end
|
491
531
|
end
|
@@ -513,7 +553,7 @@ module Tapyrus
|
|
513
553
|
|
514
554
|
# pop the item with the int value for the number specified by +count+ from the stack.
|
515
555
|
def pop_int(count = 1)
|
516
|
-
i = stack.pop(count).map{ |s| cast_to_int(s) }
|
556
|
+
i = stack.pop(count).map { |s| cast_to_int(s) }
|
517
557
|
count == 1 ? i.first : i
|
518
558
|
end
|
519
559
|
|
@@ -536,14 +576,17 @@ module Tapyrus
|
|
536
576
|
|
537
577
|
# pop the item with the string(hex) value for the number specified by +count+ from the stack.
|
538
578
|
def pop_string(count = 1)
|
539
|
-
s =
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
579
|
+
s =
|
580
|
+
stack
|
581
|
+
.pop(count)
|
582
|
+
.map do |s|
|
583
|
+
case s
|
584
|
+
when Numeric
|
585
|
+
Script.encode_number(s)
|
586
|
+
else
|
587
|
+
s
|
588
|
+
end
|
589
|
+
end
|
547
590
|
count == 1 ? s.first : s
|
548
591
|
end
|
549
592
|
|
@@ -555,15 +598,13 @@ module Tapyrus
|
|
555
598
|
# see https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L36-L49
|
556
599
|
def cast_to_bool(v)
|
557
600
|
case v
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
else
|
566
|
-
false
|
601
|
+
when Numeric
|
602
|
+
return v != 0
|
603
|
+
when String
|
604
|
+
v.each_byte.with_index { |b, i| return !(i == (v.bytesize - 1) && b == 0x80) unless b == 0 }
|
605
|
+
false
|
606
|
+
else
|
607
|
+
false
|
567
608
|
end
|
568
609
|
end
|
569
610
|
|
@@ -616,7 +657,7 @@ module Tapyrus
|
|
616
657
|
return opcode == data.bytesize
|
617
658
|
elsif data.bytesize <= 255
|
618
659
|
return opcode == OP_PUSHDATA1
|
619
|
-
elsif data.bytesize <=
|
660
|
+
elsif data.bytesize <= 65_535
|
620
661
|
return opcode == OP_PUSHDATA2
|
621
662
|
end
|
622
663
|
true
|
@@ -626,22 +667,21 @@ module Tapyrus
|
|
626
667
|
buf = StringIO.new(chunk)
|
627
668
|
opcode = buf.read(1).ord
|
628
669
|
offset = 1
|
629
|
-
len =
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
670
|
+
len =
|
671
|
+
case opcode
|
672
|
+
when OP_PUSHDATA1
|
673
|
+
offset += 1
|
674
|
+
buf.read(1).unpack('C').first
|
675
|
+
when OP_PUSHDATA2
|
676
|
+
offset += 2
|
677
|
+
buf.read(2).unpack('v').first
|
678
|
+
when OP_PUSHDATA4
|
679
|
+
offset += 4
|
680
|
+
buf.read(4).unpack('V').first
|
681
|
+
else
|
682
|
+
opcode
|
683
|
+
end
|
642
684
|
chunk.bytesize == len + offset
|
643
685
|
end
|
644
|
-
|
645
686
|
end
|
646
|
-
|
647
|
-
end
|
687
|
+
end
|