tapyrus 0.2.6 → 0.2.10

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