tapyrus 0.2.7 → 0.2.8

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