tapyrus 0.2.3 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- 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 +7 -30
- 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 +20 -2
- data/lib/tapyrus/script/multisig.rb +13 -12
- data/lib/tapyrus/script/script.rb +104 -67
- 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 +17 -18
- 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 +20 -7
- 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 -16
- metadata +20 -31
- data/.travis.yml +0 -12
@@ -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
|