tapyrus 0.2.6 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +37 -0
  3. data/.prettierignore +3 -0
  4. data/.prettierrc.yaml +3 -0
  5. data/.ruby-version +1 -1
  6. data/CODE_OF_CONDUCT.md +7 -7
  7. data/README.md +14 -17
  8. data/Rakefile +3 -3
  9. data/lib/openassets/marker_output.rb +0 -4
  10. data/lib/openassets/payload.rb +4 -10
  11. data/lib/openassets.rb +0 -2
  12. data/lib/schnorr/sign_to_contract.rb +51 -0
  13. data/lib/schnorr/signature.rb +3 -6
  14. data/lib/schnorr.rb +14 -9
  15. data/lib/tapyrus/base58.rb +7 -6
  16. data/lib/tapyrus/bip175.rb +67 -0
  17. data/lib/tapyrus/block.rb +1 -2
  18. data/lib/tapyrus/block_header.rb +15 -9
  19. data/lib/tapyrus/bloom_filter.rb +5 -3
  20. data/lib/tapyrus/chain_params.rb +1 -4
  21. data/lib/tapyrus/chainparams/dev.yml +3 -2
  22. data/lib/tapyrus/chainparams/prod.yml +3 -2
  23. data/lib/tapyrus/constants.rb +29 -23
  24. data/lib/tapyrus/errors.rb +1 -3
  25. data/lib/tapyrus/ext/ecdsa.rb +4 -4
  26. data/lib/tapyrus/ext/json_parser.rb +1 -4
  27. data/lib/tapyrus/ext.rb +1 -1
  28. data/lib/tapyrus/ext_key.rb +44 -32
  29. data/lib/tapyrus/key.rb +31 -35
  30. data/lib/tapyrus/key_path.rb +15 -12
  31. data/lib/tapyrus/logger.rb +20 -16
  32. data/lib/tapyrus/merkle_tree.rb +22 -20
  33. data/lib/tapyrus/message/addr.rb +1 -7
  34. data/lib/tapyrus/message/base.rb +0 -3
  35. data/lib/tapyrus/message/block.rb +2 -9
  36. data/lib/tapyrus/message/block_transaction_request.rb +3 -6
  37. data/lib/tapyrus/message/block_transactions.rb +2 -6
  38. data/lib/tapyrus/message/block_txn.rb +0 -4
  39. data/lib/tapyrus/message/cmpct_block.rb +1 -7
  40. data/lib/tapyrus/message/error.rb +1 -4
  41. data/lib/tapyrus/message/fee_filter.rb +1 -4
  42. data/lib/tapyrus/message/filter_add.rb +0 -4
  43. data/lib/tapyrus/message/filter_clear.rb +0 -4
  44. data/lib/tapyrus/message/filter_load.rb +2 -5
  45. data/lib/tapyrus/message/get_addr.rb +0 -4
  46. data/lib/tapyrus/message/get_block_txn.rb +0 -4
  47. data/lib/tapyrus/message/get_blocks.rb +0 -3
  48. data/lib/tapyrus/message/get_data.rb +1 -4
  49. data/lib/tapyrus/message/get_headers.rb +1 -3
  50. data/lib/tapyrus/message/header_and_short_ids.rb +3 -9
  51. data/lib/tapyrus/message/headers.rb +0 -4
  52. data/lib/tapyrus/message/headers_parser.rb +3 -8
  53. data/lib/tapyrus/message/inv.rb +1 -4
  54. data/lib/tapyrus/message/inventories_parser.rb +2 -7
  55. data/lib/tapyrus/message/inventory.rb +12 -5
  56. data/lib/tapyrus/message/mem_pool.rb +0 -4
  57. data/lib/tapyrus/message/merkle_block.rb +4 -9
  58. data/lib/tapyrus/message/network_addr.rb +7 -6
  59. data/lib/tapyrus/message/not_found.rb +0 -3
  60. data/lib/tapyrus/message/ping.rb +0 -3
  61. data/lib/tapyrus/message/pong.rb +0 -3
  62. data/lib/tapyrus/message/prefilled_tx.rb +0 -4
  63. data/lib/tapyrus/message/reject.rb +0 -3
  64. data/lib/tapyrus/message/send_cmpct.rb +1 -3
  65. data/lib/tapyrus/message/send_headers.rb +0 -3
  66. data/lib/tapyrus/message/tx.rb +0 -4
  67. data/lib/tapyrus/message/ver_ack.rb +1 -5
  68. data/lib/tapyrus/message/version.rb +2 -5
  69. data/lib/tapyrus/message.rb +14 -16
  70. data/lib/tapyrus/mnemonic.rb +17 -15
  71. data/lib/tapyrus/network/connection.rb +0 -3
  72. data/lib/tapyrus/network/message_handler.rb +61 -60
  73. data/lib/tapyrus/network/peer.rb +13 -12
  74. data/lib/tapyrus/network/peer_discovery.rb +10 -9
  75. data/lib/tapyrus/network/pool.rb +12 -12
  76. data/lib/tapyrus/network.rb +0 -2
  77. data/lib/tapyrus/node/cli.rb +12 -14
  78. data/lib/tapyrus/node/configuration.rb +1 -3
  79. data/lib/tapyrus/node/spv.rb +2 -3
  80. data/lib/tapyrus/node.rb +1 -1
  81. data/lib/tapyrus/opcodes.rb +9 -7
  82. data/lib/tapyrus/out_point.rb +5 -5
  83. data/lib/tapyrus/rpc/http_server.rb +21 -22
  84. data/lib/tapyrus/rpc/request_handler.rb +42 -44
  85. data/lib/tapyrus/rpc/tapyrus_core_client.rb +67 -25
  86. data/lib/tapyrus/rpc.rb +1 -0
  87. data/lib/tapyrus/script/color.rb +10 -0
  88. data/lib/tapyrus/script/multisig.rb +13 -12
  89. data/lib/tapyrus/script/script.rb +99 -88
  90. data/lib/tapyrus/script/script_error.rb +1 -4
  91. data/lib/tapyrus/script/script_interpreter.rb +439 -399
  92. data/lib/tapyrus/script/tx_checker.rb +20 -10
  93. data/lib/tapyrus/secp256k1/native.rb +14 -15
  94. data/lib/tapyrus/secp256k1/rfc6979.rb +7 -4
  95. data/lib/tapyrus/secp256k1/ruby.rb +10 -12
  96. data/lib/tapyrus/secp256k1.rb +0 -4
  97. data/lib/tapyrus/slip39/share.rb +41 -29
  98. data/lib/tapyrus/slip39/sss.rb +107 -57
  99. data/lib/tapyrus/slip39.rb +20 -5
  100. data/lib/tapyrus/store/chain_entry.rb +0 -4
  101. data/lib/tapyrus/store/db/level_db.rb +5 -9
  102. data/lib/tapyrus/store/db.rb +0 -2
  103. data/lib/tapyrus/store/spv_chain.rb +11 -17
  104. data/lib/tapyrus/store.rb +1 -3
  105. data/lib/tapyrus/tx.rb +45 -37
  106. data/lib/tapyrus/tx_builder.rb +158 -0
  107. data/lib/tapyrus/tx_in.rb +1 -6
  108. data/lib/tapyrus/tx_out.rb +2 -7
  109. data/lib/tapyrus/util.rb +20 -7
  110. data/lib/tapyrus/validation.rb +12 -11
  111. data/lib/tapyrus/version.rb +1 -1
  112. data/lib/tapyrus/wallet/account.rb +22 -18
  113. data/lib/tapyrus/wallet/base.rb +12 -9
  114. data/lib/tapyrus/wallet/db.rb +6 -9
  115. data/lib/tapyrus/wallet/master_key.rb +2 -4
  116. data/lib/tapyrus.rb +8 -30
  117. data/tapyrusrb.gemspec +13 -14
  118. metadata +26 -7
  119. data/.travis.yml +0 -14
@@ -3,6 +3,40 @@ require 'json/pure'
3
3
 
4
4
  module Tapyrus
5
5
  module RPC
6
+ # Throw when happened anything http's error with connect to server.
7
+ #
8
+ # Almost case this exception happened from 401 Unauthorized or 500 Internal Server Error.
9
+ # And also, throw by cause of other http's errors.
10
+ #
11
+ # You can pull RPC error message when happened 500 Internal Server Error, like below:
12
+ #
13
+ # rescue Tapyrus::RPC::Error => ex
14
+ # if ex.message.response_code == 500
15
+ # puts ex.message[:rpc_error]
16
+ # end
17
+ # end
18
+ class Error < StandardError
19
+ attr_reader :response_code, :response_msg, :rpc_error
20
+
21
+ def initialize(response_code, response_msg, rpc_error)
22
+ @response_code = response_code
23
+ @response_msg = response_msg
24
+ @rpc_error = rpc_error
25
+ end
26
+
27
+ def message
28
+ @message ||=
29
+ begin
30
+ m = { response_code: response_code, response_msg: response_msg }
31
+ m.merge!(rpc_error: rpc_error) if rpc_error
32
+ m
33
+ end
34
+ end
35
+
36
+ def to_s
37
+ message.to_s
38
+ end
39
+ end
6
40
 
7
41
  # Client implementation for RPC to Tapyrus Core.
8
42
  #
@@ -16,25 +50,21 @@ module Tapyrus
16
50
  # client.getblockchaininfo
17
51
  #
18
52
  class TapyrusCoreClient
19
-
20
53
  attr_reader :config
21
54
 
22
55
  # @param [Hash] config a configuration required to connect to Bitcoin Core.
23
56
  def initialize(config)
24
57
  @config = config
25
58
 
26
- commands = request(:help).split("\n").inject([]) do |memo_ary, line|
27
- if !line.empty? && !line.start_with?('==')
28
- memo_ary << line.split(' ').first.to_sym
29
- end
30
- memo_ary
31
- end
32
- TapyrusCoreClient.class_eval do
33
- commands.each do |command|
34
- define_method(command) do |*params|
35
- request(command, *params)
59
+ commands =
60
+ request(:help)
61
+ .split("\n")
62
+ .inject([]) do |memo_ary, line|
63
+ memo_ary << line.split(' ').first.to_sym if !line.empty? && !line.start_with?('==')
64
+ memo_ary
36
65
  end
37
- end
66
+ TapyrusCoreClient.class_eval do
67
+ commands.each { |command| define_method(command) { |*params| request(command, *params) } }
38
68
  end
39
69
  end
40
70
 
@@ -42,33 +72,45 @@ module Tapyrus
42
72
 
43
73
  def server_url
44
74
  url = "#{config[:schema]}://#{config[:user]}:#{config[:password]}@#{config[:host]}:#{config[:port]}"
45
- if !config[:wallet].nil? && !config[:wallet].empty?
46
- url += "/wallet/#{config[:wallet]}"
47
- end
75
+ url += "/wallet/#{config[:wallet]}" if !config[:wallet].nil? && !config[:wallet].empty?
48
76
  url
49
77
  end
50
78
 
51
79
  def request(command, *params)
52
- data = {
53
- :method => command,
54
- :params => params,
55
- :id => 'jsonrpc'
56
- }
80
+ data = { method: command, params: params, id: 'jsonrpc' }
57
81
  uri = URI.parse(server_url)
58
82
  http = Net::HTTP.new(uri.hostname, uri.port)
59
- http.use_ssl = uri.scheme === "https"
83
+ http.use_ssl = uri.scheme === 'https'
60
84
  request = Net::HTTP::Post.new(uri.path.empty? ? '/' : uri.path)
61
85
  request.basic_auth(uri.user, uri.password)
62
86
  request.content_type = 'application/json'
63
87
  request.body = data.to_json
64
88
  response = http.request(request)
65
- body = response.body
66
- response = Tapyrus::Ext::JsonParser.new(body.gsub(/\\u([\da-fA-F]{4})/) { [$1].pack('H*').unpack('n*').pack('U*').encode('ISO-8859-1').force_encoding('UTF-8') }).parse
67
- raise response['error'].to_json if response['error']
89
+ raise error!(response) unless response.is_a? Net::HTTPOK
90
+ response = Tapyrus::RPC.response_body2json(response.body)
68
91
  response['result']
69
92
  end
70
93
 
94
+ def error!(response)
95
+ rpc_error =
96
+ begin
97
+ Tapyrus::RPC.response_body2json(response.body)['error']
98
+ rescue JSON::ParserError => _
99
+ # if RPC server don't send error message.
100
+ end
101
+
102
+ raise Error.new(response.code, response.msg, rpc_error)
103
+ end
104
+ end
105
+
106
+ def response_body2json(body)
107
+ Tapyrus::Ext::JsonParser.new(
108
+ body.gsub(/\\u([\da-fA-F]{4})/) do
109
+ [$1].pack('H*').unpack('n*').pack('U*').encode('ISO-8859-1').force_encoding('UTF-8')
110
+ end
111
+ ).parse
71
112
  end
72
113
 
114
+ module_function :response_body2json
73
115
  end
74
- end
116
+ end
data/lib/tapyrus/rpc.rb CHANGED
@@ -3,5 +3,6 @@ module Tapyrus
3
3
  autoload :HttpServer, 'tapyrus/rpc/http_server'
4
4
  autoload :RequestHandler, 'tapyrus/rpc/request_handler'
5
5
  autoload :TapyrusCoreClient, 'tapyrus/rpc/tapyrus_core_client'
6
+ autoload :Error, 'tapyrus/rpc/tapyrus_core_client'
6
7
  end
7
8
  end
@@ -24,6 +24,11 @@ module Tapyrus
24
24
  new(TokenTypes::NFT, Tapyrus.sha256(out_point.to_payload))
25
25
  end
26
26
 
27
+ # Return ColorIdentifier for native token(i.e TPC)
28
+ def self.default
29
+ new(TokenTypes::NONE, '0000000000000000000000000000000000000000000000000000000000000000'.htb)
30
+ end
31
+
27
32
  def to_payload
28
33
  [type, payload].pack('Ca*')
29
34
  end
@@ -51,6 +56,11 @@ module Tapyrus
51
56
  to_payload.eql?(other.to_payload)
52
57
  end
53
58
 
59
+ # Return true if the coin is native token(i.e TPC), otherwise false
60
+ def default?
61
+ self == ColorIdentifier.default
62
+ end
63
+
54
64
  private
55
65
 
56
66
  def initialize(type, payload)
@@ -1,11 +1,10 @@
1
1
  module Tapyrus
2
-
3
2
  # utility for multisig
4
3
  module Multisig
5
4
  include Tapyrus::Opcodes
6
5
 
7
6
  def self.prefix
8
- [OP_0].pack("C*")
7
+ [OP_0].pack('C*')
9
8
  end
10
9
 
11
10
  # generate input script sig spending a multisig output script.
@@ -23,7 +22,7 @@ module Tapyrus
23
22
  # multiple parties. Signatures must be in the same order as the
24
23
  # pubkeys in the output script being redeemed.
25
24
  def self.add_sig_to_multisig_script_sig(sig_to_add, script_sig, hash_type = SIGHASH_TYPE[:all])
26
- signature = sig_to_add + [hash_type].pack("C*")
25
+ signature = sig_to_add + [hash_type].pack('C*')
27
26
  offset = script_sig.empty? ? 0 : 1
28
27
  script_sig.insert(offset, Tapyrus::Script.pack_pushdata(signature))
29
28
  end
@@ -49,17 +48,19 @@ module Tapyrus
49
48
  pubkeys = redeem_script.get_multisig_pubkeys
50
49
 
51
50
  # find the pubkey for each signature by trying to verify it
52
- sigs = Hash[script.chunks[1...-1].map.with_index do |sig, idx|
53
- sig = sig.pushed_data
54
- pubkey = pubkeys.map do |key|
55
- Tapyrus::Key.new(pubkey: key.bth).verify(sig, sig_hash) ? key : nil
56
- end.compact.first
57
- raise "Key for signature ##{idx} not found in redeem script!" unless pubkey
58
- [pubkey, sig]
59
- end]
51
+ sigs =
52
+ Hash[
53
+ script.chunks[1...-1].map.with_index do |sig, idx|
54
+ sig = sig.pushed_data
55
+ pubkey =
56
+ pubkeys.map { |key| Tapyrus::Key.new(pubkey: key.bth).verify(sig, sig_hash) ? key : nil }.compact.first
57
+ raise "Key for signature ##{idx} not found in redeem script!" unless pubkey
58
+ [pubkey, sig]
59
+ end
60
+ ]
60
61
 
61
62
  prefix + pubkeys.map { |k| sigs[k] ? Tapyrus::Script.pack_pushdata(sigs[k]) : nil }.join +
62
63
  Tapyrus::Script.pack_pushdata(script.chunks[-1].pushed_data)
63
64
  end
64
65
  end
65
- end
66
+ end
@@ -2,7 +2,6 @@
2
2
  # https://github.com/lian/bitcoin-ruby/blob/master/COPYING
3
3
 
4
4
  module Tapyrus
5
-
6
5
  # tapyrus script
7
6
  class Script
8
7
  include Tapyrus::HexConverter
@@ -82,14 +81,12 @@ module Tapyrus
82
81
  def remove_color
83
82
  raise RuntimeError, 'Only cp2pkh and cp2sh can remove color' unless cp2pkh? or cp2sh?
84
83
 
85
- Tapyrus::Script.new.tap do |s|
86
- s.chunks = self.chunks[2..-1]
87
- end
84
+ Tapyrus::Script.new.tap { |s| s.chunks = self.chunks[2..-1] }
88
85
  end
89
86
 
90
87
  def get_multisig_pubkeys
91
88
  num = Tapyrus::Opcodes.opcode_to_small_int(chunks[-2].bth.to_i(16))
92
- (1..num).map{ |i| chunks[i].pushed_data }
89
+ (1..num).map { |i| chunks[i].pushed_data }
93
90
  end
94
91
 
95
92
  # generate m of n multisig script
@@ -104,14 +101,16 @@ module Tapyrus
104
101
  # generate script from string.
105
102
  def self.from_string(string)
106
103
  script = new
107
- string.split(' ').each do |v|
108
- opcode = Opcodes.name_to_opcode(v)
109
- if opcode
110
- script << (v =~ /^\d/ && Opcodes.small_int_to_opcode(v.ord) ? v.ord : opcode)
111
- else
112
- script << (v =~ /^[0-9]+$/ ? v.to_i : v)
104
+ string
105
+ .split(' ')
106
+ .each do |v|
107
+ opcode = Opcodes.name_to_opcode(v)
108
+ if opcode
109
+ script << (v =~ /^\d/ && Opcodes.small_int_to_opcode(v.ord) ? v.ord : opcode)
110
+ else
111
+ script << (v =~ /^[0-9]+$/ ? v.to_i : v)
112
+ end
113
113
  end
114
- end
115
114
  script
116
115
  end
117
116
 
@@ -130,6 +129,12 @@ module Tapyrus
130
129
  Tapyrus::Script.to_p2pkh(hex)
131
130
  when Tapyrus.chain_params.p2sh_version
132
131
  Tapyrus::Script.to_p2sh(hex)
132
+ when Tapyrus.chain_params.cp2pkh_version
133
+ color = Tapyrus::Color::ColorIdentifier.parse_from_payload(hex[0..65].htb)
134
+ Tapyrus::Script.to_cp2pkh(color, hex[66..-1])
135
+ when Tapyrus.chain_params.cp2sh_version
136
+ color = Tapyrus::Color::ColorIdentifier.parse_from_payload(hex[0..65].htb)
137
+ Tapyrus::Script.to_cp2sh(color, hex[66..-1])
133
138
  else
134
139
  throw e
135
140
  end
@@ -144,19 +149,20 @@ module Tapyrus
144
149
  if opcode.pushdata?
145
150
  pushcode = opcode.ord
146
151
  packed_size = nil
147
- len = case pushcode
148
- when OP_PUSHDATA1
149
- packed_size = buf.read(1)
150
- packed_size.unpack('C').first
151
- when OP_PUSHDATA2
152
- packed_size = buf.read(2)
153
- packed_size.unpack('v').first
154
- when OP_PUSHDATA4
155
- packed_size = buf.read(4)
156
- packed_size.unpack('V').first
157
- else
158
- pushcode if pushcode < OP_PUSHDATA1
159
- end
152
+ len =
153
+ case pushcode
154
+ when OP_PUSHDATA1
155
+ packed_size = buf.read(1)
156
+ packed_size.unpack('C').first
157
+ when OP_PUSHDATA2
158
+ packed_size = buf.read(2)
159
+ packed_size.unpack('v').first
160
+ when OP_PUSHDATA4
161
+ packed_size = buf.read(4)
162
+ packed_size.unpack('V').first
163
+ else
164
+ pushcode if pushcode < OP_PUSHDATA1
165
+ end
160
166
  if len
161
167
  s.chunks << [len].pack('C') if buf.eof?
162
168
  unless buf.eof?
@@ -188,7 +194,7 @@ module Tapyrus
188
194
  return [p2sh_addr] if p2sh?
189
195
  return [cp2pkh_addr] if cp2pkh?
190
196
  return [cp2sh_addr] if cp2sh?
191
- return get_multisig_pubkeys.map{|pubkey| Tapyrus::Key.new(pubkey: pubkey.bth).to_p2pkh} if multisig?
197
+ return get_multisig_pubkeys.map { |pubkey| Tapyrus::Key.new(pubkey: pubkey.bth).to_p2pkh } if multisig?
192
198
  []
193
199
  end
194
200
 
@@ -200,8 +206,8 @@ module Tapyrus
200
206
  # whether this script is a P2PKH format script.
201
207
  def p2pkh?
202
208
  return false unless chunks.size == 5
203
- [OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG] ==
204
- (chunks[0..1]+ chunks[3..4]).map(&:ord) && chunks[2].bytesize == 21
209
+ [OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG] == (chunks[0..1] + chunks[3..4]).map(&:ord) &&
210
+ chunks[2].bytesize == 21
205
211
  end
206
212
 
207
213
  def p2sh?
@@ -222,8 +228,7 @@ module Tapyrus
222
228
  end
223
229
 
224
230
  def standard_op_return?
225
- op_return? && size <= MAX_OP_RETURN_RELAY &&
226
- (chunks.size == 1 || chunks[1].opcode <= OP_16)
231
+ op_return? && size <= MAX_OP_RETURN_RELAY && (chunks.size == 1 || chunks[1].opcode <= OP_16)
227
232
  end
228
233
 
229
234
  # Return whether this script is a CP2PKH format script or not.
@@ -233,8 +238,8 @@ module Tapyrus
233
238
  return false unless chunks[0].bytesize == 34
234
239
  return false unless Tapyrus::Color::ColorIdentifier.parse_from_payload(chunks[0].pushed_data)&.valid?
235
240
  return false unless chunks[1].ord == OP_COLOR
236
- [OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG] ==
237
- (chunks[2..3]+ chunks[5..6]).map(&:ord) && chunks[4].bytesize == 21
241
+ [OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG] == (chunks[2..3] + chunks[5..6]).map(&:ord) &&
242
+ chunks[4].bytesize == 21
238
243
  end
239
244
 
240
245
  # Return whether this script is a CP2SH format script or not.
@@ -246,7 +251,7 @@ module Tapyrus
246
251
  return false unless chunks[1].ord == OP_COLOR
247
252
  OP_HASH160 == chunks[2].ord && OP_EQUAL == chunks[4].ord && chunks[3].bytesize == 21
248
253
  end
249
-
254
+
250
255
  # Return whether this script represents colored coin.
251
256
  # @return [Boolean] true if this script is colored, otherwise false.
252
257
  def colored?
@@ -269,24 +274,25 @@ module Tapyrus
269
274
 
270
275
  # whether data push only script which dose not include other opcode
271
276
  def push_only?
272
- chunks.each do |c|
273
- return false if !c.opcode.nil? && c.opcode > OP_16
274
- end
277
+ chunks.each { |c| return false if !c.opcode.nil? && c.opcode > OP_16 }
275
278
  true
276
279
  end
277
280
 
278
281
  # get public keys in the stack.
279
282
  # @return[Array[String]] an array of the pubkeys with hex format.
280
283
  def get_pubkeys
281
- chunks.select{|c|c.pushdata? && [33, 65].include?(c.pushed_data.bytesize) && [2, 3, 4, 6, 7].include?(c.pushed_data[0].bth.to_i(16))}.map{|c|c.pushed_data.bth}
284
+ chunks
285
+ .select do |c|
286
+ c.pushdata? && [33, 65].include?(c.pushed_data.bytesize) &&
287
+ [2, 3, 4, 6, 7].include?(c.pushed_data[0].bth.to_i(16))
288
+ end
289
+ .map { |c| c.pushed_data.bth }
282
290
  end
283
291
 
284
292
  # returns the self payload. ScriptInterpreter does not use this.
285
293
  def to_script_code(skip_separator_index = 0)
286
294
  payload = to_payload
287
- if skip_separator_index > 0
288
- payload = subscript_codeseparator(skip_separator_index)
289
- end
295
+ payload = subscript_codeseparator(skip_separator_index) if skip_separator_index > 0
290
296
  Tapyrus.pack_var_string(payload)
291
297
  end
292
298
 
@@ -297,7 +303,7 @@ module Tapyrus
297
303
  elsif obj.is_a?(String)
298
304
  append_data(obj)
299
305
  elsif obj.is_a?(Array)
300
- obj.each { |o| self.<< o}
306
+ obj.each { |o| self.<< o }
301
307
  self
302
308
  end
303
309
  end
@@ -333,41 +339,44 @@ module Tapyrus
333
339
 
334
340
  # Check the item is in the chunk of the script.
335
341
  def include?(item)
336
- chunk_item = if item.is_a?(Integer)
337
- item.chr
338
- elsif item.is_a?(String)
339
- data = Encoding::ASCII_8BIT == item.encoding ? item : item.htb
340
- Tapyrus::Script.pack_pushdata(data)
341
- end
342
+ chunk_item =
343
+ if item.is_a?(Integer)
344
+ item.chr
345
+ elsif item.is_a?(String)
346
+ data = Encoding::ASCII_8BIT == item.encoding ? item : item.htb
347
+ Tapyrus::Script.pack_pushdata(data)
348
+ end
342
349
  return false unless chunk_item
343
350
  chunks.include?(chunk_item)
344
351
  end
345
352
 
346
353
  def to_s
347
- chunks.map { |c|
348
- case c
349
- when Integer
350
- opcode_to_name(c)
351
- when String
352
- return c if c.empty?
353
- if c.pushdata?
354
- v = Opcodes.opcode_to_small_int(c.ord)
355
- if v
356
- v
357
- else
358
- data = c.pushed_data
359
- if data.bytesize <= 4
360
- Script.decode_number(data.bth) # for scriptnum
354
+ chunks
355
+ .map do |c|
356
+ case c
357
+ when Integer
358
+ opcode_to_name(c)
359
+ when String
360
+ return c if c.empty?
361
+ if c.pushdata?
362
+ v = Opcodes.opcode_to_small_int(c.ord)
363
+ if v
364
+ v
361
365
  else
362
- data.bth
366
+ data = c.pushed_data
367
+ if data.bytesize <= 4
368
+ Script.decode_number(data.bth) # for scriptnum
369
+ else
370
+ data.bth
371
+ end
363
372
  end
373
+ else
374
+ opcode = Opcodes.opcode_to_name(c.ord)
375
+ opcode ? opcode : 'OP_UNKNOWN [error]'
364
376
  end
365
- else
366
- opcode = Opcodes.opcode_to_name(c.ord)
367
- opcode ? opcode : 'OP_UNKNOWN [error]'
368
377
  end
369
378
  end
370
- }.join(' ')
379
+ .join(' ')
371
380
  end
372
381
 
373
382
  # generate sha-256 hash for payload
@@ -425,17 +434,18 @@ module Tapyrus
425
434
  # binary +data+ convert pushdata which contains data length and append PUSHDATA opcode if necessary.
426
435
  def self.pack_pushdata(data)
427
436
  size = data.bytesize
428
- header = if size < OP_PUSHDATA1
429
- [size].pack('C')
430
- elsif size < 0xff
431
- [OP_PUSHDATA1, size].pack('CC')
432
- elsif size < 0xffff
433
- [OP_PUSHDATA2, size].pack('Cv')
434
- elsif size < 0xffffffff
435
- [OP_PUSHDATA4, size].pack('CV')
436
- else
437
- raise ArgumentError, 'data size is too big.'
438
- end
437
+ header =
438
+ if size < OP_PUSHDATA1
439
+ [size].pack('C')
440
+ elsif size < 0xff
441
+ [OP_PUSHDATA1, size].pack('CC')
442
+ elsif size < 0xffff
443
+ [OP_PUSHDATA2, size].pack('Cv')
444
+ elsif size < 0xffffffff
445
+ [OP_PUSHDATA4, size].pack('CV')
446
+ else
447
+ raise ArgumentError, 'data size is too big.'
448
+ end
439
449
  header + data
440
450
  end
441
451
 
@@ -459,8 +469,12 @@ module Tapyrus
459
469
  if chunk == sub_chunk
460
470
  buf << chunk
461
471
  i += 1
462
- (i = 0; buf.clear) if i == subscript.chunks.size # matched the whole subscript
463
- else # matched the part of head
472
+ (
473
+ i = 0
474
+ buf.clear
475
+ ) if i == subscript.chunks.size # matched the whole subscript
476
+ else
477
+ # matched the part of head
464
478
  i = 0
465
479
  tmp = chunk.dup
466
480
  tmp.slice!(sub_chunk)
@@ -482,7 +496,7 @@ module Tapyrus
482
496
 
483
497
  # remove all occurences of opcode. Typically it's OP_CODESEPARATOR.
484
498
  def delete_opcode(opcode)
485
- @chunks = chunks.select{|chunk| chunk.ord != opcode}
499
+ @chunks = chunks.select { |chunk| chunk.ord != opcode }
486
500
  self
487
501
  end
488
502
 
@@ -490,12 +504,10 @@ module Tapyrus
490
504
  def subscript_codeseparator(separator_index)
491
505
  buf = []
492
506
  process_separator_index = 0
493
- chunks.each{|chunk|
507
+ chunks.each do |chunk|
494
508
  buf << chunk if process_separator_index == separator_index
495
- if chunk.ord == OP_CODESEPARATOR && process_separator_index < separator_index
496
- process_separator_index += 1
497
- end
498
- }
509
+ process_separator_index += 1 if chunk.ord == OP_CODESEPARATOR && process_separator_index < separator_index
510
+ end
499
511
  buf.join
500
512
  end
501
513
 
@@ -512,10 +524,10 @@ module Tapyrus
512
524
  end
513
525
 
514
526
  def to_h
515
- h = {asm: to_s, hex: to_hex, type: type}
527
+ h = { asm: to_s, hex: to_hex, type: type }
516
528
  addrs = addresses
517
529
  unless addrs.empty?
518
- h[:req_sigs] = multisig? ? Tapyrus::Opcodes.opcode_to_small_int(chunks[0].bth.to_i(16)) :addrs.size
530
+ h[:req_sigs] = multisig? ? Tapyrus::Opcodes.opcode_to_small_int(chunks[0].bth.to_i(16)) : addrs.size
519
531
  h[:addresses] = addrs
520
532
  end
521
533
  h
@@ -562,5 +574,4 @@ module Tapyrus
562
574
  Tapyrus.encode_base58_address(color_id + hash160, Tapyrus.chain_params.cp2sh_version)
563
575
  end
564
576
  end
565
-
566
577
  end
@@ -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