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.
Files changed (115) 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/CODE_OF_CONDUCT.md +7 -7
  6. data/README.md +14 -17
  7. data/Rakefile +3 -3
  8. data/lib/openassets.rb +0 -2
  9. data/lib/openassets/marker_output.rb +0 -4
  10. data/lib/openassets/payload.rb +4 -10
  11. data/lib/schnorr.rb +2 -3
  12. data/lib/schnorr/signature.rb +3 -6
  13. data/lib/tapyrus.rb +6 -22
  14. data/lib/tapyrus/base58.rb +7 -6
  15. data/lib/tapyrus/block.rb +1 -2
  16. data/lib/tapyrus/block_header.rb +15 -9
  17. data/lib/tapyrus/bloom_filter.rb +5 -3
  18. data/lib/tapyrus/chain_params.rb +1 -4
  19. data/lib/tapyrus/chainparams/dev.yml +3 -2
  20. data/lib/tapyrus/chainparams/prod.yml +3 -2
  21. data/lib/tapyrus/constants.rb +29 -23
  22. data/lib/tapyrus/errors.rb +1 -3
  23. data/lib/tapyrus/ext.rb +1 -1
  24. data/lib/tapyrus/ext/ecdsa.rb +4 -4
  25. data/lib/tapyrus/ext/json_parser.rb +1 -4
  26. data/lib/tapyrus/ext_key.rb +38 -34
  27. data/lib/tapyrus/key.rb +31 -35
  28. data/lib/tapyrus/key_path.rb +15 -12
  29. data/lib/tapyrus/logger.rb +20 -16
  30. data/lib/tapyrus/merkle_tree.rb +19 -20
  31. data/lib/tapyrus/message.rb +14 -16
  32. data/lib/tapyrus/message/addr.rb +1 -7
  33. data/lib/tapyrus/message/base.rb +0 -3
  34. data/lib/tapyrus/message/block.rb +2 -9
  35. data/lib/tapyrus/message/block_transaction_request.rb +3 -6
  36. data/lib/tapyrus/message/block_transactions.rb +2 -6
  37. data/lib/tapyrus/message/block_txn.rb +0 -4
  38. data/lib/tapyrus/message/cmpct_block.rb +1 -7
  39. data/lib/tapyrus/message/error.rb +1 -4
  40. data/lib/tapyrus/message/fee_filter.rb +1 -4
  41. data/lib/tapyrus/message/filter_add.rb +0 -4
  42. data/lib/tapyrus/message/filter_clear.rb +0 -4
  43. data/lib/tapyrus/message/filter_load.rb +2 -5
  44. data/lib/tapyrus/message/get_addr.rb +0 -4
  45. data/lib/tapyrus/message/get_block_txn.rb +0 -4
  46. data/lib/tapyrus/message/get_blocks.rb +0 -3
  47. data/lib/tapyrus/message/get_data.rb +1 -4
  48. data/lib/tapyrus/message/get_headers.rb +1 -3
  49. data/lib/tapyrus/message/header_and_short_ids.rb +3 -9
  50. data/lib/tapyrus/message/headers.rb +0 -4
  51. data/lib/tapyrus/message/headers_parser.rb +3 -8
  52. data/lib/tapyrus/message/inv.rb +1 -4
  53. data/lib/tapyrus/message/inventories_parser.rb +2 -7
  54. data/lib/tapyrus/message/inventory.rb +12 -5
  55. data/lib/tapyrus/message/mem_pool.rb +0 -4
  56. data/lib/tapyrus/message/merkle_block.rb +4 -9
  57. data/lib/tapyrus/message/network_addr.rb +7 -6
  58. data/lib/tapyrus/message/not_found.rb +0 -3
  59. data/lib/tapyrus/message/ping.rb +0 -3
  60. data/lib/tapyrus/message/pong.rb +0 -3
  61. data/lib/tapyrus/message/prefilled_tx.rb +0 -4
  62. data/lib/tapyrus/message/reject.rb +0 -3
  63. data/lib/tapyrus/message/send_cmpct.rb +1 -3
  64. data/lib/tapyrus/message/send_headers.rb +0 -3
  65. data/lib/tapyrus/message/tx.rb +0 -4
  66. data/lib/tapyrus/message/ver_ack.rb +1 -5
  67. data/lib/tapyrus/message/version.rb +2 -5
  68. data/lib/tapyrus/mnemonic.rb +17 -15
  69. data/lib/tapyrus/network.rb +0 -2
  70. data/lib/tapyrus/network/connection.rb +0 -3
  71. data/lib/tapyrus/network/message_handler.rb +61 -60
  72. data/lib/tapyrus/network/peer.rb +13 -12
  73. data/lib/tapyrus/network/peer_discovery.rb +3 -5
  74. data/lib/tapyrus/network/pool.rb +12 -12
  75. data/lib/tapyrus/node.rb +1 -1
  76. data/lib/tapyrus/node/cli.rb +12 -14
  77. data/lib/tapyrus/node/configuration.rb +1 -3
  78. data/lib/tapyrus/node/spv.rb +2 -3
  79. data/lib/tapyrus/opcodes.rb +9 -7
  80. data/lib/tapyrus/out_point.rb +5 -5
  81. data/lib/tapyrus/rpc/http_server.rb +21 -22
  82. data/lib/tapyrus/rpc/request_handler.rb +42 -44
  83. data/lib/tapyrus/rpc/tapyrus_core_client.rb +53 -25
  84. data/lib/tapyrus/script/color.rb +10 -0
  85. data/lib/tapyrus/script/multisig.rb +13 -12
  86. data/lib/tapyrus/script/script.rb +72 -71
  87. data/lib/tapyrus/script/script_error.rb +1 -4
  88. data/lib/tapyrus/script/script_interpreter.rb +439 -399
  89. data/lib/tapyrus/script/tx_checker.rb +20 -10
  90. data/lib/tapyrus/secp256k1.rb +0 -4
  91. data/lib/tapyrus/secp256k1/native.rb +14 -15
  92. data/lib/tapyrus/secp256k1/rfc6979.rb +7 -4
  93. data/lib/tapyrus/secp256k1/ruby.rb +10 -12
  94. data/lib/tapyrus/slip39.rb +20 -5
  95. data/lib/tapyrus/slip39/share.rb +41 -29
  96. data/lib/tapyrus/slip39/sss.rb +101 -57
  97. data/lib/tapyrus/store.rb +1 -3
  98. data/lib/tapyrus/store/chain_entry.rb +0 -4
  99. data/lib/tapyrus/store/db.rb +0 -2
  100. data/lib/tapyrus/store/db/level_db.rb +5 -9
  101. data/lib/tapyrus/store/spv_chain.rb +11 -17
  102. data/lib/tapyrus/tx.rb +45 -37
  103. data/lib/tapyrus/tx_builder.rb +158 -0
  104. data/lib/tapyrus/tx_in.rb +1 -6
  105. data/lib/tapyrus/tx_out.rb +2 -7
  106. data/lib/tapyrus/util.rb +7 -9
  107. data/lib/tapyrus/validation.rb +12 -11
  108. data/lib/tapyrus/version.rb +1 -1
  109. data/lib/tapyrus/wallet/account.rb +22 -18
  110. data/lib/tapyrus/wallet/base.rb +12 -9
  111. data/lib/tapyrus/wallet/db.rb +6 -9
  112. data/lib/tapyrus/wallet/master_key.rb +2 -4
  113. data/tapyrusrb.gemspec +13 -14
  114. metadata +21 -4
  115. data/.travis.yml +0 -14
@@ -1,9 +1,7 @@
1
1
  module Tapyrus
2
2
  module RPC
3
-
4
3
  # RPC server's request handler.
5
4
  module RequestHandler
6
-
7
5
  # Returns an object containing various state info regarding blockchain processing.
8
6
  def getblockchaininfo
9
7
  h = {}
@@ -28,19 +26,19 @@ module Tapyrus
28
26
  raise ArgumentError.new('Block not found') unless entry
29
27
  if verbose
30
28
  {
31
- hash: block_id,
32
- height: entry.height,
33
- features: entry.header.features,
34
- featuresHex: entry.header.features.to_even_length_hex.ljust(8, '0'),
35
- merkleroot: entry.header.merkle_root.rhex,
36
- immutablemerkleroot: entry.header.im_merkle_root.rhex,
37
- time: entry.header.time,
38
- mediantime: node.chain.mtp(block_hash),
39
- xfield_type: entry.header.x_field_type,
40
- xfield: entry.header.x_field,
41
- proof: entry.header.proof,
42
- previousblockhash: entry.prev_hash.rhex,
43
- nextblockhash: node.chain.next_hash(block_hash).rhex
29
+ hash: block_id,
30
+ height: entry.height,
31
+ features: entry.header.features,
32
+ featuresHex: entry.header.features.to_even_length_hex.ljust(8, '0'),
33
+ merkleroot: entry.header.merkle_root.rhex,
34
+ immutablemerkleroot: entry.header.im_merkle_root.rhex,
35
+ time: entry.header.time,
36
+ mediantime: node.chain.mtp(block_hash),
37
+ xfield_type: entry.header.x_field_type,
38
+ xfield: entry.header.x_field,
39
+ proof: entry.header.proof,
40
+ previousblockhash: entry.prev_hash.rhex,
41
+ nextblockhash: node.chain.next_hash(block_hash).rhex
44
42
  }
45
43
  else
46
44
  entry.header.to_hex
@@ -49,34 +47,38 @@ module Tapyrus
49
47
 
50
48
  # Returns connected peer information.
51
49
  def getpeerinfo
52
- node.pool.peers.map do |peer|
53
- local_addr = "#{peer.remote_version.remote_addr.ip}:18333"
54
- {
55
- id: peer.id,
56
- addr: "#{peer.host}:#{peer.port}",
57
- addrlocal: local_addr,
58
- services: peer.remote_version.services.to_even_length_hex.rjust(16, '0'),
59
- relaytxes: peer.remote_version.relay,
60
- lastsend: peer.last_send,
61
- lastrecv: peer.last_recv,
62
- bytessent: peer.bytes_sent,
63
- bytesrecv: peer.bytes_recv,
64
- conntime: peer.conn_time,
65
- pingtime: peer.ping_time,
66
- minping: peer.min_ping,
67
- version: peer.remote_version.version,
68
- subver: peer.remote_version.user_agent,
69
- inbound: !peer.outbound?,
70
- startingheight: peer.remote_version.start_height,
71
- best_hash: peer.best_hash,
72
- best_height: peer.best_height
73
- }
74
- end
50
+ node
51
+ .pool
52
+ .peers
53
+ .map do |peer|
54
+ local_addr = "#{peer.remote_version.remote_addr.ip}:18333"
55
+ {
56
+ id: peer.id,
57
+ addr: "#{peer.host}:#{peer.port}",
58
+ addrlocal: local_addr,
59
+ services: peer.remote_version.services.to_even_length_hex.rjust(16, '0'),
60
+ relaytxes: peer.remote_version.relay,
61
+ lastsend: peer.last_send,
62
+ lastrecv: peer.last_recv,
63
+ bytessent: peer.bytes_sent,
64
+ bytesrecv: peer.bytes_recv,
65
+ conntime: peer.conn_time,
66
+ pingtime: peer.ping_time,
67
+ minping: peer.min_ping,
68
+ version: peer.remote_version.version,
69
+ subver: peer.remote_version.user_agent,
70
+ inbound: !peer.outbound?,
71
+ startingheight: peer.remote_version.start_height,
72
+ best_hash: peer.best_hash,
73
+ best_height: peer.best_height
74
+ }
75
+ end
75
76
  end
76
77
 
77
78
  # broadcast transaction
78
79
  def sendrawtransaction(hex_tx)
79
80
  tx = Tapyrus::Tx.parse_from_payload(hex_tx.htb)
81
+
80
82
  # TODO check wether tx is valid
81
83
  node.broadcast(tx)
82
84
  tx.txid
@@ -110,7 +112,7 @@ module Tapyrus
110
112
  def createwallet(wallet_id = 1, wallet_path_prefix = Tapyrus::Wallet::Base.default_path_prefix)
111
113
  wallet = Tapyrus::Wallet::Base.create(wallet_id, wallet_path_prefix)
112
114
  node.wallet = wallet unless node.wallet
113
- {wallet_id: wallet.wallet_id, mnemonic: wallet.master_key.mnemonic}
115
+ { wallet_id: wallet.wallet_id, mnemonic: wallet.master_key.mnemonic }
114
116
  end
115
117
 
116
118
  # get wallet list.
@@ -127,9 +129,7 @@ module Tapyrus
127
129
  def listaccounts
128
130
  return {} unless node.wallet
129
131
  accounts = {}
130
- node.wallet.accounts.each do |a|
131
- accounts[a.name] = node.wallet.get_balance(a)
132
- end
132
+ node.wallet.accounts.each { |a| accounts[a.name] = node.wallet.get_balance(a) }
133
133
  accounts
134
134
  end
135
135
 
@@ -144,8 +144,6 @@ module Tapyrus
144
144
  def getnewaddress(account_name)
145
145
  node.wallet.generate_new_address(account_name)
146
146
  end
147
-
148
147
  end
149
-
150
148
  end
151
149
  end
@@ -3,6 +3,37 @@ 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 :message
20
+
21
+ def initialize(response)
22
+ raise ArgumentError, 'Must set response as cause.' unless response
23
+
24
+ # set message from response body or status code.
25
+ @message = { response_code: response&.code, response_msg: response&.msg }
26
+ begin
27
+ @message.merge!({ rpc_error: Tapyrus::RPC.response_body2json(response.body)['error'] })
28
+ rescue JSON::ParserError => _
29
+ # if RPC server don't send error message.
30
+ end
31
+ end
32
+
33
+ def to_s
34
+ @message.to_s
35
+ end
36
+ end
6
37
 
7
38
  # Client implementation for RPC to Tapyrus Core.
8
39
  #
@@ -16,25 +47,21 @@ module Tapyrus
16
47
  # client.getblockchaininfo
17
48
  #
18
49
  class TapyrusCoreClient
19
-
20
50
  attr_reader :config
21
51
 
22
52
  # @param [Hash] config a configuration required to connect to Bitcoin Core.
23
53
  def initialize(config)
24
54
  @config = config
25
55
 
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)
56
+ commands =
57
+ request(:help)
58
+ .split("\n")
59
+ .inject([]) do |memo_ary, line|
60
+ memo_ary << line.split(' ').first.to_sym if !line.empty? && !line.start_with?('==')
61
+ memo_ary
36
62
  end
37
- end
63
+ TapyrusCoreClient.class_eval do
64
+ commands.each { |command| define_method(command) { |*params| request(command, *params) } }
38
65
  end
39
66
  end
40
67
 
@@ -42,33 +69,34 @@ module Tapyrus
42
69
 
43
70
  def server_url
44
71
  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
72
+ url += "/wallet/#{config[:wallet]}" if !config[:wallet].nil? && !config[:wallet].empty?
48
73
  url
49
74
  end
50
75
 
51
76
  def request(command, *params)
52
- data = {
53
- :method => command,
54
- :params => params,
55
- :id => 'jsonrpc'
56
- }
77
+ data = { method: command, params: params, id: 'jsonrpc' }
57
78
  uri = URI.parse(server_url)
58
79
  http = Net::HTTP.new(uri.hostname, uri.port)
59
- http.use_ssl = uri.scheme === "https"
80
+ http.use_ssl = uri.scheme === 'https'
60
81
  request = Net::HTTP::Post.new(uri.path.empty? ? '/' : uri.path)
61
82
  request.basic_auth(uri.user, uri.password)
62
83
  request.content_type = 'application/json'
63
84
  request.body = data.to_json
64
85
  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']
86
+ raise Error.new(response) unless response.is_a? Net::HTTPOK
87
+ response = Tapyrus::RPC.response_body2json(response.body)
68
88
  response['result']
69
89
  end
90
+ end
70
91
 
92
+ def response_body2json(body)
93
+ Tapyrus::Ext::JsonParser.new(
94
+ body.gsub(/\\u([\da-fA-F]{4})/) do
95
+ [$1].pack('H*').unpack('n*').pack('U*').encode('ISO-8859-1').force_encoding('UTF-8')
96
+ end
97
+ ).parse
71
98
  end
72
99
 
100
+ module_function :response_body2json
73
101
  end
74
- end
102
+ 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
 
@@ -150,19 +149,20 @@ module Tapyrus
150
149
  if opcode.pushdata?
151
150
  pushcode = opcode.ord
152
151
  packed_size = nil
153
- len = 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
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
166
166
  if len
167
167
  s.chunks << [len].pack('C') if buf.eof?
168
168
  unless buf.eof?
@@ -194,7 +194,7 @@ module Tapyrus
194
194
  return [p2sh_addr] if p2sh?
195
195
  return [cp2pkh_addr] if cp2pkh?
196
196
  return [cp2sh_addr] if cp2sh?
197
- 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?
198
198
  []
199
199
  end
200
200
 
@@ -206,8 +206,8 @@ module Tapyrus
206
206
  # whether this script is a P2PKH format script.
207
207
  def p2pkh?
208
208
  return false unless chunks.size == 5
209
- [OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG] ==
210
- (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
211
211
  end
212
212
 
213
213
  def p2sh?
@@ -228,8 +228,7 @@ module Tapyrus
228
228
  end
229
229
 
230
230
  def standard_op_return?
231
- op_return? && size <= MAX_OP_RETURN_RELAY &&
232
- (chunks.size == 1 || chunks[1].opcode <= OP_16)
231
+ op_return? && size <= MAX_OP_RETURN_RELAY && (chunks.size == 1 || chunks[1].opcode <= OP_16)
233
232
  end
234
233
 
235
234
  # Return whether this script is a CP2PKH format script or not.
@@ -239,8 +238,8 @@ module Tapyrus
239
238
  return false unless chunks[0].bytesize == 34
240
239
  return false unless Tapyrus::Color::ColorIdentifier.parse_from_payload(chunks[0].pushed_data)&.valid?
241
240
  return false unless chunks[1].ord == OP_COLOR
242
- [OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG] ==
243
- (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
244
243
  end
245
244
 
246
245
  # Return whether this script is a CP2SH format script or not.
@@ -252,7 +251,7 @@ module Tapyrus
252
251
  return false unless chunks[1].ord == OP_COLOR
253
252
  OP_HASH160 == chunks[2].ord && OP_EQUAL == chunks[4].ord && chunks[3].bytesize == 21
254
253
  end
255
-
254
+
256
255
  # Return whether this script represents colored coin.
257
256
  # @return [Boolean] true if this script is colored, otherwise false.
258
257
  def colored?
@@ -275,24 +274,23 @@ module Tapyrus
275
274
 
276
275
  # whether data push only script which dose not include other opcode
277
276
  def push_only?
278
- chunks.each do |c|
279
- return false if !c.opcode.nil? && c.opcode > OP_16
280
- end
277
+ chunks.each { |c| return false if !c.opcode.nil? && c.opcode > OP_16 }
281
278
  true
282
279
  end
283
280
 
284
281
  # get public keys in the stack.
285
282
  # @return[Array[String]] an array of the pubkeys with hex format.
286
283
  def get_pubkeys
287
- 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.select do |c|
285
+ c.pushdata? && [33, 65].include?(c.pushed_data.bytesize) &&
286
+ [2, 3, 4, 6, 7].include?(c.pushed_data[0].bth.to_i(16))
287
+ end.map { |c| c.pushed_data.bth }
288
288
  end
289
289
 
290
290
  # returns the self payload. ScriptInterpreter does not use this.
291
291
  def to_script_code(skip_separator_index = 0)
292
292
  payload = to_payload
293
- if skip_separator_index > 0
294
- payload = subscript_codeseparator(skip_separator_index)
295
- end
293
+ payload = subscript_codeseparator(skip_separator_index) if skip_separator_index > 0
296
294
  Tapyrus.pack_var_string(payload)
297
295
  end
298
296
 
@@ -303,7 +301,7 @@ module Tapyrus
303
301
  elsif obj.is_a?(String)
304
302
  append_data(obj)
305
303
  elsif obj.is_a?(Array)
306
- obj.each { |o| self.<< o}
304
+ obj.each { |o| self.<< o }
307
305
  self
308
306
  end
309
307
  end
@@ -339,18 +337,19 @@ module Tapyrus
339
337
 
340
338
  # Check the item is in the chunk of the script.
341
339
  def include?(item)
342
- chunk_item = if item.is_a?(Integer)
343
- item.chr
344
- elsif item.is_a?(String)
345
- data = Encoding::ASCII_8BIT == item.encoding ? item : item.htb
346
- Tapyrus::Script.pack_pushdata(data)
347
- end
340
+ chunk_item =
341
+ if item.is_a?(Integer)
342
+ item.chr
343
+ elsif item.is_a?(String)
344
+ data = Encoding::ASCII_8BIT == item.encoding ? item : item.htb
345
+ Tapyrus::Script.pack_pushdata(data)
346
+ end
348
347
  return false unless chunk_item
349
348
  chunks.include?(chunk_item)
350
349
  end
351
350
 
352
351
  def to_s
353
- chunks.map { |c|
352
+ chunks.map do |c|
354
353
  case c
355
354
  when Integer
356
355
  opcode_to_name(c)
@@ -373,7 +372,7 @@ module Tapyrus
373
372
  opcode ? opcode : 'OP_UNKNOWN [error]'
374
373
  end
375
374
  end
376
- }.join(' ')
375
+ end.join(' ')
377
376
  end
378
377
 
379
378
  # generate sha-256 hash for payload
@@ -431,17 +430,18 @@ module Tapyrus
431
430
  # binary +data+ convert pushdata which contains data length and append PUSHDATA opcode if necessary.
432
431
  def self.pack_pushdata(data)
433
432
  size = data.bytesize
434
- header = if size < OP_PUSHDATA1
435
- [size].pack('C')
436
- elsif size < 0xff
437
- [OP_PUSHDATA1, size].pack('CC')
438
- elsif size < 0xffff
439
- [OP_PUSHDATA2, size].pack('Cv')
440
- elsif size < 0xffffffff
441
- [OP_PUSHDATA4, size].pack('CV')
442
- else
443
- raise ArgumentError, 'data size is too big.'
444
- end
433
+ header =
434
+ if size < OP_PUSHDATA1
435
+ [size].pack('C')
436
+ elsif size < 0xff
437
+ [OP_PUSHDATA1, size].pack('CC')
438
+ elsif size < 0xffff
439
+ [OP_PUSHDATA2, size].pack('Cv')
440
+ elsif size < 0xffffffff
441
+ [OP_PUSHDATA4, size].pack('CV')
442
+ else
443
+ raise ArgumentError, 'data size is too big.'
444
+ end
445
445
  header + data
446
446
  end
447
447
 
@@ -465,8 +465,12 @@ module Tapyrus
465
465
  if chunk == sub_chunk
466
466
  buf << chunk
467
467
  i += 1
468
- (i = 0; buf.clear) if i == subscript.chunks.size # matched the whole subscript
469
- else # matched the part of head
468
+ (
469
+ i = 0
470
+ buf.clear
471
+ ) if i == subscript.chunks.size # matched the whole subscript
472
+ else
473
+ # matched the part of head
470
474
  i = 0
471
475
  tmp = chunk.dup
472
476
  tmp.slice!(sub_chunk)
@@ -488,7 +492,7 @@ module Tapyrus
488
492
 
489
493
  # remove all occurences of opcode. Typically it's OP_CODESEPARATOR.
490
494
  def delete_opcode(opcode)
491
- @chunks = chunks.select{|chunk| chunk.ord != opcode}
495
+ @chunks = chunks.select { |chunk| chunk.ord != opcode }
492
496
  self
493
497
  end
494
498
 
@@ -496,12 +500,10 @@ module Tapyrus
496
500
  def subscript_codeseparator(separator_index)
497
501
  buf = []
498
502
  process_separator_index = 0
499
- chunks.each{|chunk|
503
+ chunks.each do |chunk|
500
504
  buf << chunk if process_separator_index == separator_index
501
- if chunk.ord == OP_CODESEPARATOR && process_separator_index < separator_index
502
- process_separator_index += 1
503
- end
504
- }
505
+ process_separator_index += 1 if chunk.ord == OP_CODESEPARATOR && process_separator_index < separator_index
506
+ end
505
507
  buf.join
506
508
  end
507
509
 
@@ -518,10 +520,10 @@ module Tapyrus
518
520
  end
519
521
 
520
522
  def to_h
521
- h = {asm: to_s, hex: to_hex, type: type}
523
+ h = { asm: to_s, hex: to_hex, type: type }
522
524
  addrs = addresses
523
525
  unless addrs.empty?
524
- h[:req_sigs] = multisig? ? Tapyrus::Opcodes.opcode_to_small_int(chunks[0].bth.to_i(16)) :addrs.size
526
+ h[:req_sigs] = multisig? ? Tapyrus::Opcodes.opcode_to_small_int(chunks[0].bth.to_i(16)) : addrs.size
525
527
  h[:addresses] = addrs
526
528
  end
527
529
  h
@@ -568,5 +570,4 @@ module Tapyrus
568
570
  Tapyrus.encode_base58_address(color_id + hash160, Tapyrus.chain_params.cp2sh_version)
569
571
  end
570
572
  end
571
-
572
573
  end