tapyrus 0.2.4 → 0.2.9
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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +37 -0
- data/.prettierignore +3 -0
- data/.prettierrc.yaml +3 -0
- data/CODE_OF_CONDUCT.md +7 -7
- data/README.md +14 -17
- data/Rakefile +3 -3
- data/lib/openassets.rb +0 -2
- data/lib/openassets/marker_output.rb +0 -4
- data/lib/openassets/payload.rb +4 -10
- data/lib/schnorr.rb +14 -9
- data/lib/schnorr/sign_to_contract.rb +51 -0
- data/lib/schnorr/signature.rb +3 -6
- data/lib/tapyrus.rb +8 -30
- data/lib/tapyrus/base58.rb +7 -6
- data/lib/tapyrus/bip175.rb +67 -0
- data/lib/tapyrus/block.rb +1 -2
- data/lib/tapyrus/block_header.rb +15 -9
- data/lib/tapyrus/bloom_filter.rb +5 -3
- data/lib/tapyrus/chain_params.rb +1 -4
- data/lib/tapyrus/chainparams/dev.yml +3 -2
- data/lib/tapyrus/chainparams/prod.yml +3 -2
- data/lib/tapyrus/constants.rb +29 -23
- data/lib/tapyrus/errors.rb +1 -3
- data/lib/tapyrus/ext.rb +1 -1
- data/lib/tapyrus/ext/ecdsa.rb +4 -4
- data/lib/tapyrus/ext/json_parser.rb +1 -4
- data/lib/tapyrus/ext_key.rb +44 -32
- data/lib/tapyrus/key.rb +31 -35
- data/lib/tapyrus/key_path.rb +15 -12
- data/lib/tapyrus/logger.rb +20 -16
- data/lib/tapyrus/merkle_tree.rb +19 -20
- data/lib/tapyrus/message.rb +14 -16
- data/lib/tapyrus/message/addr.rb +1 -7
- data/lib/tapyrus/message/base.rb +0 -3
- data/lib/tapyrus/message/block.rb +2 -9
- data/lib/tapyrus/message/block_transaction_request.rb +3 -6
- data/lib/tapyrus/message/block_transactions.rb +2 -6
- data/lib/tapyrus/message/block_txn.rb +0 -4
- data/lib/tapyrus/message/cmpct_block.rb +1 -7
- data/lib/tapyrus/message/error.rb +1 -4
- data/lib/tapyrus/message/fee_filter.rb +1 -4
- data/lib/tapyrus/message/filter_add.rb +0 -4
- data/lib/tapyrus/message/filter_clear.rb +0 -4
- data/lib/tapyrus/message/filter_load.rb +2 -5
- data/lib/tapyrus/message/get_addr.rb +0 -4
- data/lib/tapyrus/message/get_block_txn.rb +0 -4
- data/lib/tapyrus/message/get_blocks.rb +0 -3
- data/lib/tapyrus/message/get_data.rb +1 -4
- data/lib/tapyrus/message/get_headers.rb +1 -3
- data/lib/tapyrus/message/header_and_short_ids.rb +3 -9
- data/lib/tapyrus/message/headers.rb +0 -4
- data/lib/tapyrus/message/headers_parser.rb +3 -8
- data/lib/tapyrus/message/inv.rb +1 -4
- data/lib/tapyrus/message/inventories_parser.rb +2 -7
- data/lib/tapyrus/message/inventory.rb +12 -5
- data/lib/tapyrus/message/mem_pool.rb +0 -4
- data/lib/tapyrus/message/merkle_block.rb +4 -9
- data/lib/tapyrus/message/network_addr.rb +7 -6
- data/lib/tapyrus/message/not_found.rb +0 -3
- data/lib/tapyrus/message/ping.rb +0 -3
- data/lib/tapyrus/message/pong.rb +0 -3
- data/lib/tapyrus/message/prefilled_tx.rb +0 -4
- data/lib/tapyrus/message/reject.rb +0 -3
- data/lib/tapyrus/message/send_cmpct.rb +1 -3
- data/lib/tapyrus/message/send_headers.rb +0 -3
- data/lib/tapyrus/message/tx.rb +0 -4
- data/lib/tapyrus/message/ver_ack.rb +1 -5
- data/lib/tapyrus/message/version.rb +2 -5
- data/lib/tapyrus/mnemonic.rb +17 -15
- data/lib/tapyrus/network.rb +0 -2
- data/lib/tapyrus/network/connection.rb +0 -3
- data/lib/tapyrus/network/message_handler.rb +61 -60
- data/lib/tapyrus/network/peer.rb +13 -12
- data/lib/tapyrus/network/peer_discovery.rb +3 -5
- data/lib/tapyrus/network/pool.rb +12 -12
- data/lib/tapyrus/node.rb +1 -1
- data/lib/tapyrus/node/cli.rb +12 -14
- data/lib/tapyrus/node/configuration.rb +1 -3
- data/lib/tapyrus/node/spv.rb +2 -3
- data/lib/tapyrus/opcodes.rb +9 -7
- data/lib/tapyrus/out_point.rb +5 -5
- data/lib/tapyrus/rpc.rb +1 -0
- data/lib/tapyrus/rpc/http_server.rb +21 -22
- data/lib/tapyrus/rpc/request_handler.rb +42 -44
- data/lib/tapyrus/rpc/tapyrus_core_client.rb +67 -25
- data/lib/tapyrus/script/color.rb +20 -2
- data/lib/tapyrus/script/multisig.rb +13 -12
- data/lib/tapyrus/script/script.rb +104 -67
- data/lib/tapyrus/script/script_error.rb +1 -4
- data/lib/tapyrus/script/script_interpreter.rb +439 -399
- data/lib/tapyrus/script/tx_checker.rb +20 -10
- data/lib/tapyrus/secp256k1.rb +0 -4
- data/lib/tapyrus/secp256k1/native.rb +14 -15
- data/lib/tapyrus/secp256k1/rfc6979.rb +7 -4
- data/lib/tapyrus/secp256k1/ruby.rb +10 -12
- data/lib/tapyrus/slip39.rb +20 -5
- data/lib/tapyrus/slip39/share.rb +41 -29
- data/lib/tapyrus/slip39/sss.rb +101 -57
- data/lib/tapyrus/store.rb +1 -3
- data/lib/tapyrus/store/chain_entry.rb +0 -4
- data/lib/tapyrus/store/db.rb +0 -2
- data/lib/tapyrus/store/db/level_db.rb +5 -9
- data/lib/tapyrus/store/spv_chain.rb +11 -17
- data/lib/tapyrus/tx.rb +45 -37
- data/lib/tapyrus/tx_builder.rb +158 -0
- data/lib/tapyrus/tx_in.rb +1 -6
- data/lib/tapyrus/tx_out.rb +2 -7
- data/lib/tapyrus/util.rb +20 -7
- data/lib/tapyrus/validation.rb +12 -11
- data/lib/tapyrus/version.rb +1 -1
- data/lib/tapyrus/wallet/account.rb +22 -18
- data/lib/tapyrus/wallet/base.rb +12 -9
- data/lib/tapyrus/wallet/db.rb +6 -9
- data/lib/tapyrus/wallet/master_key.rb +2 -4
- data/tapyrusrb.gemspec +13 -16
- metadata +22 -31
- data/.travis.yml +0 -12
data/lib/tapyrus/node/spv.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
module Tapyrus
|
2
2
|
module Node
|
3
|
-
|
4
3
|
# SPV class
|
5
4
|
class SPV
|
6
|
-
|
7
5
|
attr_reader :chain
|
8
6
|
attr_reader :pool
|
9
7
|
attr_reader :logger
|
@@ -20,6 +18,7 @@ module Tapyrus
|
|
20
18
|
@logger = Tapyrus::Logger.create(:debug)
|
21
19
|
@running = false
|
22
20
|
@wallet = Tapyrus::Wallet::Base.current_wallet
|
21
|
+
|
23
22
|
# TODO : optimize bloom filter parameters
|
24
23
|
setup_filter
|
25
24
|
end
|
@@ -72,7 +71,7 @@ module Tapyrus
|
|
72
71
|
|
73
72
|
def setup_filter
|
74
73
|
@bloom = Tapyrus::BloomFilter.create_filter(512, 0.01)
|
75
|
-
wallet.watch_targets.each{|t|bloom.add(t.htb)} if wallet
|
74
|
+
wallet.watch_targets.each { |t| bloom.add(t.htb) } if wallet
|
76
75
|
end
|
77
76
|
end
|
78
77
|
end
|
data/lib/tapyrus/opcodes.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Tapyrus
|
2
|
-
|
3
2
|
# https://bitcoin.org/en/developer-reference#opcodes
|
4
3
|
module Opcodes
|
5
|
-
|
6
4
|
module_function
|
7
5
|
|
8
6
|
# https://en.bitcoin.it/wiki/Script#Constants
|
@@ -111,7 +109,7 @@ module Tapyrus
|
|
111
109
|
OP_HASH256 = 0xaa
|
112
110
|
OP_CODESEPARATOR = 0xab
|
113
111
|
OP_CHECKSIG = 0xac
|
114
|
-
OP_CHECKSIGVERIFY= 0xad
|
112
|
+
OP_CHECKSIGVERIFY = 0xad
|
115
113
|
OP_CHECKMULTISIG = 0xae
|
116
114
|
OP_CHECKMULTISIGVERIFY = 0xaf
|
117
115
|
|
@@ -124,7 +122,7 @@ module Tapyrus
|
|
124
122
|
OP_VER = 0x62
|
125
123
|
OP_VERIF = 0x65
|
126
124
|
OP_VERNOTIF = 0x66
|
127
|
-
OP_RESERVED1= 0x89
|
125
|
+
OP_RESERVED1 = 0x89
|
128
126
|
OP_RESERVED2 = 0x8a
|
129
127
|
|
130
128
|
OP_NOP1 = 0xb0
|
@@ -147,7 +145,12 @@ module Tapyrus
|
|
147
145
|
OP_COLOR = 0xbc
|
148
146
|
|
149
147
|
DUPLICATE_KEY = [:OP_NOP2, :OP_NOP3]
|
150
|
-
OPCODES_MAP =
|
148
|
+
OPCODES_MAP =
|
149
|
+
Hash[
|
150
|
+
*(constants.grep(/^OP_/) - [:OP_NOP2, :OP_NOP3, :OP_CHECKLOCKTIMEVERIFY, :OP_CHECKSEQUENCEVERIFY]).map do |c|
|
151
|
+
[const_get(c), c.to_s]
|
152
|
+
end.flatten
|
153
|
+
]
|
151
154
|
NAME_MAP = Hash[*constants.grep(/^OP_/).map { |c| [c.to_s, const_get(c)] }.flatten]
|
152
155
|
|
153
156
|
def opcode_to_name(opcode)
|
@@ -178,6 +181,5 @@ module Tapyrus
|
|
178
181
|
return opcode - (OP_1 - 1) if opcode >= OP_1 && opcode <= OP_16
|
179
182
|
nil
|
180
183
|
end
|
181
|
-
|
182
184
|
end
|
183
|
-
end
|
185
|
+
end
|
data/lib/tapyrus/out_point.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
module Tapyrus
|
2
|
-
|
3
2
|
# outpoint class
|
4
3
|
class OutPoint
|
5
|
-
|
6
4
|
COINBASE_HASH = '0000000000000000000000000000000000000000000000000000000000000000'
|
7
|
-
COINBASE_INDEX =
|
5
|
+
COINBASE_INDEX = 4_294_967_295
|
8
6
|
|
9
7
|
attr_reader :tx_hash
|
10
8
|
attr_reader :index
|
@@ -34,11 +32,13 @@ module Tapyrus
|
|
34
32
|
index >= 0 && (!coinbase? && tx_hash != COINBASE_HASH)
|
35
33
|
end
|
36
34
|
|
35
|
+
def ==(other)
|
36
|
+
to_payload == other&.to_payload
|
37
|
+
end
|
38
|
+
|
37
39
|
# convert hash to txid
|
38
40
|
def txid
|
39
41
|
tx_hash.rhex
|
40
42
|
end
|
41
|
-
|
42
43
|
end
|
43
|
-
|
44
44
|
end
|
data/lib/tapyrus/rpc.rb
CHANGED
@@ -3,7 +3,6 @@ require 'json'
|
|
3
3
|
|
4
4
|
module Tapyrus
|
5
5
|
module RPC
|
6
|
-
|
7
6
|
# Tapyrusrb RPC server.
|
8
7
|
class HttpServer < EM::Connection
|
9
8
|
include EM::HttpServer
|
@@ -28,27 +27,29 @@ module Tapyrus
|
|
28
27
|
|
29
28
|
# process http request.
|
30
29
|
def process_http_request
|
31
|
-
operation =
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
e
|
30
|
+
operation =
|
31
|
+
proc do
|
32
|
+
command, args = parse_json_params
|
33
|
+
logger.debug("process http request. command = #{command}")
|
34
|
+
begin
|
35
|
+
send(command, *args).to_json
|
36
|
+
rescue Exception => e
|
37
|
+
e
|
38
|
+
end
|
38
39
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
40
|
+
callback =
|
41
|
+
proc do |result|
|
42
|
+
response = EM::DelegatedHttpResponse.new(self)
|
43
|
+
if result.is_a?(Exception)
|
44
|
+
response.status = 500
|
45
|
+
response.content = result.message
|
46
|
+
else
|
47
|
+
response.status = 200
|
48
|
+
response.content = result
|
49
|
+
end
|
50
|
+
response.content_type 'application/json'
|
51
|
+
response.send_response
|
48
52
|
end
|
49
|
-
response.content_type 'application/json'
|
50
|
-
response.send_response
|
51
|
-
}
|
52
53
|
EM.defer(operation, callback)
|
53
54
|
end
|
54
55
|
|
@@ -58,8 +59,6 @@ module Tapyrus
|
|
58
59
|
params = JSON.parse(@http_post_content)
|
59
60
|
[params['method'], params['params']]
|
60
61
|
end
|
61
|
-
|
62
62
|
end
|
63
|
-
|
64
63
|
end
|
65
64
|
end
|
@@ -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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
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,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 =
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
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 ===
|
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
|
-
|
66
|
-
response = Tapyrus::
|
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/script/color.rb
CHANGED
@@ -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
|
@@ -43,6 +48,19 @@ module Tapyrus
|
|
43
48
|
true
|
44
49
|
end
|
45
50
|
|
51
|
+
def hash
|
52
|
+
to_payload.hash
|
53
|
+
end
|
54
|
+
|
55
|
+
def eql?(other)
|
56
|
+
to_payload.eql?(other.to_payload)
|
57
|
+
end
|
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
|
+
|
46
64
|
private
|
47
65
|
|
48
66
|
def initialize(type, payload)
|
@@ -53,11 +71,11 @@ module Tapyrus
|
|
53
71
|
|
54
72
|
module ColoredOutput
|
55
73
|
def colored?
|
56
|
-
script_pubkey.
|
74
|
+
script_pubkey.colored?
|
57
75
|
end
|
58
76
|
|
59
77
|
def color_id
|
60
|
-
@color_id ||=
|
78
|
+
@color_id ||= script_pubkey.color_id
|
61
79
|
end
|
62
80
|
|
63
81
|
def reissuable?
|