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
@@ -0,0 +1,158 @@
|
|
1
|
+
module Tapyrus
|
2
|
+
#
|
3
|
+
# Transaction Builder class.
|
4
|
+
#
|
5
|
+
# TxBuilder makes it easy to build transactions without having to deal with TxOut/TxIn/Script directly.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
#
|
9
|
+
# txb = Tapyrus::TxBuilder.new
|
10
|
+
# utxo1 = {
|
11
|
+
# script_pubkey: Tapyrus::Script.parse_from_addr('mgCuyNQ1pUbKqL57tJQZX3hhUCaZcuX3RQ'),
|
12
|
+
# txid: 'e1fb3255ead43dccd3ae0ac2c4f81b32260ca52749936a739669918bbb895411',
|
13
|
+
# index: 0,
|
14
|
+
# value: 3_000
|
15
|
+
# }
|
16
|
+
# color_id = Tapyrus::Color::ColorIdentifier.nft(...)
|
17
|
+
# utxo2 = {
|
18
|
+
# script_pubkey: Tapyrus::Script.parse_from_addr('mu9QMUcB9UCHbQjZJLAuyysQhM9tmFQbPx'),
|
19
|
+
# color_id: color_id,
|
20
|
+
# txid: 'e1fb3255ead43dccd3ae0ac2c4f81b32260ca52749936a739669918bbb895411',
|
21
|
+
# index: 1,
|
22
|
+
# value: 3_000
|
23
|
+
# }
|
24
|
+
#
|
25
|
+
# tx = txb
|
26
|
+
# .add_utxo(utxo1)
|
27
|
+
# .add_utxo(utxo2)
|
28
|
+
# .data("0102030405060a0b0c")
|
29
|
+
# .reissuable(utxo1[:script_pubkey],'n4jKJN5UMLsAejL1M5CTzQ8npeWoLBLCAH', 10_000)
|
30
|
+
# .pay('n4jKJN5UMLsAejL1M5CTzQ8npeWoLBLCAH', 1_000)
|
31
|
+
# .build
|
32
|
+
#
|
33
|
+
class TxBuilder
|
34
|
+
def initialize
|
35
|
+
@utxos = []
|
36
|
+
@incomings = {}
|
37
|
+
@outgoings = {}
|
38
|
+
@outputs = []
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add utxo for transaction input
|
42
|
+
# @param utxo [Hash] a hash whose fields are `txid`, `index`, `script_pubkey`, `value`, and `color_id` (color_id is optional)
|
43
|
+
def add_utxo(utxo)
|
44
|
+
@utxos << utxo
|
45
|
+
color_id = utxo[:color_id] || Tapyrus::Color::ColorIdentifier.default
|
46
|
+
@incomings[color_id] ||= 0
|
47
|
+
@incomings[color_id] += utxo[:value]
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
# Issue reissuable token
|
52
|
+
# @param script_pubkey [Tapyrus::Script] the script pubkey in the issue input.
|
53
|
+
# @param address [String] p2pkh or p2sh address.
|
54
|
+
# @param value [Integer] issued amount.
|
55
|
+
def reissuable(script_pubkey, address, value)
|
56
|
+
color_id = Tapyrus::Color::ColorIdentifier.reissuable(script_pubkey)
|
57
|
+
pay(address, value, color_id)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Issue non reissuable token
|
61
|
+
# @param out_point [Tapyrus::OutPoint] the out point at issue input.
|
62
|
+
# @param address [String] p2pkh or p2sh address.
|
63
|
+
# @param value [Integer] issued amount.
|
64
|
+
def non_reissuable(out_point, address, value)
|
65
|
+
color_id = Tapyrus::Color::ColorIdentifier.non_reissuable(out_point)
|
66
|
+
pay(address, value, color_id)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Issue NFT
|
70
|
+
# @param out_point [Tapyrus::OutPoint] the out point at issue input.
|
71
|
+
# @param address [String] p2pkh or p2sh address.
|
72
|
+
# @param value [Integer] issued amount.
|
73
|
+
def nft(out_point, address)
|
74
|
+
color_id = Tapyrus::Color::ColorIdentifier.nft(out_point)
|
75
|
+
pay(address, 1, color_id)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Create payment output.
|
79
|
+
# @param address [String] tapyrus address with Base58 format
|
80
|
+
# @param value [Integer] issued or transferred amount
|
81
|
+
# @param color_id [Tapyrus::Color::ColorIdentifier] color id
|
82
|
+
def pay(address, value, color_id = Tapyrus::Color::ColorIdentifier.default)
|
83
|
+
script_pubkey = Tapyrus::Script.parse_from_addr(address)
|
84
|
+
|
85
|
+
unless color_id.default?
|
86
|
+
raise ArgumentError, 'invalid address' if !script_pubkey.p2pkh? && !script_pubkey.p2sh?
|
87
|
+
script_pubkey = script_pubkey.add_color(color_id)
|
88
|
+
end
|
89
|
+
|
90
|
+
@outgoings[color_id] ||= 0
|
91
|
+
@outgoings[color_id] += value
|
92
|
+
@outputs << Tapyrus::TxOut.new(script_pubkey: script_pubkey, value: value)
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
# Create data output
|
97
|
+
# @param contents [[String]] array of hex string
|
98
|
+
def data(*contents)
|
99
|
+
payload = contents.join
|
100
|
+
script = Tapyrus::Script.new << Tapyrus::Script::OP_RETURN << payload
|
101
|
+
@outputs << Tapyrus::TxOut.new(script_pubkey: script)
|
102
|
+
self
|
103
|
+
end
|
104
|
+
|
105
|
+
# Set transaction fee.
|
106
|
+
# @param fee [Integer] transaction fee
|
107
|
+
def fee(fee)
|
108
|
+
@fee = fee
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
# Set address for change.
|
113
|
+
# If set, #build method add output for change which has the specified address
|
114
|
+
# If not set, transaction built by #build method has no output for change.
|
115
|
+
# @param address [String] p2pkh or p2sh address.
|
116
|
+
def change_address(address)
|
117
|
+
script_pubkey = Tapyrus::Script.parse_from_addr(address)
|
118
|
+
raise ArgumentError, 'invalid address' if !script_pubkey.p2pkh? && !script_pubkey.p2sh?
|
119
|
+
@change_script_pubkey = script_pubkey
|
120
|
+
self
|
121
|
+
end
|
122
|
+
|
123
|
+
# Build transaction
|
124
|
+
def build
|
125
|
+
tx = Tapyrus::Tx.new
|
126
|
+
expand_input(tx)
|
127
|
+
@outputs.each { |output| tx.outputs << output }
|
128
|
+
add_change(tx) if @change_script_pubkey
|
129
|
+
tx
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def add_change(tx)
|
135
|
+
@incomings.each do |color_id, in_amount|
|
136
|
+
out_amount = @outgoings[color_id] || 0
|
137
|
+
change, script_pubkey =
|
138
|
+
if color_id.default?
|
139
|
+
[in_amount - out_amount - estimated_fee, @change_script_pubkey]
|
140
|
+
else
|
141
|
+
[in_amount - out_amount, @change_script_pubkey.add_color(color_id)]
|
142
|
+
end
|
143
|
+
tx.outputs << Tapyrus::TxOut.new(script_pubkey: script_pubkey, value: change) if change > 0
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def expand_input(tx)
|
148
|
+
@utxos.each do |utxo|
|
149
|
+
tx.inputs << Tapyrus::TxIn.new(out_point: Tapyrus::OutPoint.from_txid(utxo[:txid], utxo[:index]))
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Return transaction fee
|
154
|
+
def estimated_fee
|
155
|
+
@fee
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
data/lib/tapyrus/tx_in.rb
CHANGED
@@ -2,10 +2,8 @@
|
|
2
2
|
# https://github.com/lian/bitcoin-ruby/blob/master/COPYING
|
3
3
|
|
4
4
|
module Tapyrus
|
5
|
-
|
6
5
|
# transaction input
|
7
6
|
class TxIn
|
8
|
-
|
9
7
|
attr_accessor :out_point
|
10
8
|
attr_accessor :script_sig
|
11
9
|
attr_accessor :sequence
|
@@ -58,11 +56,10 @@ module Tapyrus
|
|
58
56
|
p
|
59
57
|
end
|
60
58
|
|
61
|
-
|
62
59
|
def to_h
|
63
60
|
sig = script_sig.to_h
|
64
61
|
sig.delete(:type)
|
65
|
-
h = {txid: out_point.txid, vout: out_point.index,
|
62
|
+
h = { txid: out_point.txid, vout: out_point.index, script_sig: sig }
|
66
63
|
h[:sequence] = sequence
|
67
64
|
h
|
68
65
|
end
|
@@ -76,7 +73,5 @@ module Tapyrus
|
|
76
73
|
return nil unless out_point
|
77
74
|
out_point.tx_hash
|
78
75
|
end
|
79
|
-
|
80
76
|
end
|
81
|
-
|
82
77
|
end
|
data/lib/tapyrus/tx_out.rb
CHANGED
@@ -2,10 +2,8 @@
|
|
2
2
|
# https://github.com/lian/bitcoin-ruby/blob/master/COPYING
|
3
3
|
|
4
4
|
module Tapyrus
|
5
|
-
|
6
5
|
# transaction output
|
7
6
|
class TxOut
|
8
|
-
|
9
7
|
include OpenAssets::MarkerOutput
|
10
8
|
include Tapyrus::Color::ColoredOutput
|
11
9
|
|
@@ -39,7 +37,7 @@ module Tapyrus
|
|
39
37
|
end
|
40
38
|
|
41
39
|
def to_h
|
42
|
-
{value: value_to_btc, script_pubkey: script_pubkey.to_h}
|
40
|
+
{ value: value_to_btc, script_pubkey: script_pubkey.to_h }
|
43
41
|
end
|
44
42
|
|
45
43
|
def ==(other)
|
@@ -65,11 +63,8 @@ module Tapyrus
|
|
65
63
|
n_size = size
|
66
64
|
n_size += (32 + 4 + 1 + 107 + 4)
|
67
65
|
fee = n_size * Tapyrus.chain_params.dust_relay_fee / 1000
|
68
|
-
if fee == 0 && n_size != 0
|
69
|
-
fee = Tapyrus.chain_params.dust_relay_fee > 0 ? 1 : -1
|
70
|
-
end
|
66
|
+
fee = Tapyrus.chain_params.dust_relay_fee > 0 ? 1 : -1 if fee == 0 && n_size != 0
|
71
67
|
fee
|
72
68
|
end
|
73
69
|
end
|
74
|
-
|
75
70
|
end
|
data/lib/tapyrus/util.rb
CHANGED
@@ -2,12 +2,10 @@
|
|
2
2
|
# https://github.com/lian/bitcoin-ruby/blob/master/COPYING
|
3
3
|
|
4
4
|
module Tapyrus
|
5
|
-
|
6
5
|
# tapyrus utility.
|
7
6
|
# following methods can be used as follows.
|
8
7
|
# Tapyrus.pack_var_int(5)
|
9
8
|
module Util
|
10
|
-
|
11
9
|
def pack_var_string(payload)
|
12
10
|
pack_var_int(payload.bytesize) + payload
|
13
11
|
end
|
@@ -18,7 +16,7 @@ module Tapyrus
|
|
18
16
|
end
|
19
17
|
|
20
18
|
def pack_var_int(i)
|
21
|
-
if i <
|
19
|
+
if i < 0xfd
|
22
20
|
[i].pack('C')
|
23
21
|
elsif i <= 0xffff
|
24
22
|
[0xfd, i].pack('Cv')
|
@@ -111,7 +109,14 @@ module Tapyrus
|
|
111
109
|
def decode_base58_address(addr)
|
112
110
|
hex = Base58.decode(addr)
|
113
111
|
if hex.size == 50 && calc_checksum(hex[0...-8]) == hex[-8..-1]
|
114
|
-
|
112
|
+
unless [Tapyrus.chain_params.address_version, Tapyrus.chain_params.p2sh_version].include?(hex[0..1])
|
113
|
+
raise 'Invalid version bytes.'
|
114
|
+
end
|
115
|
+
[hex[2...-8], hex[0..1]]
|
116
|
+
elsif hex.size == 116 && calc_checksum(hex[0...-8]) == hex[-8..-1]
|
117
|
+
unless [Tapyrus.chain_params.cp2pkh_version, Tapyrus.chain_params.cp2sh_version].include?(hex[0..1])
|
118
|
+
raise 'Invalid version bytes.'
|
119
|
+
end
|
115
120
|
[hex[2...-8], hex[0..1]]
|
116
121
|
else
|
117
122
|
raise 'Invalid address.'
|
@@ -128,14 +133,22 @@ module Tapyrus
|
|
128
133
|
OpenSSL::HMAC.digest(DIGEST_NAME_SHA256, key, data)
|
129
134
|
end
|
130
135
|
|
136
|
+
# check whether +addr+ is valid address.
|
137
|
+
# @param [String] addr an address
|
138
|
+
# @return [Boolean] if valid address return true, otherwise false.
|
139
|
+
def valid_address?(addr)
|
140
|
+
begin
|
141
|
+
Tapyrus::Script.parse_from_addr(addr)
|
142
|
+
true
|
143
|
+
rescue Exception => e
|
144
|
+
false
|
145
|
+
end
|
146
|
+
end
|
131
147
|
end
|
132
148
|
|
133
149
|
module HexConverter
|
134
|
-
|
135
150
|
def to_hex
|
136
151
|
to_payload.bth
|
137
152
|
end
|
138
|
-
|
139
153
|
end
|
140
|
-
|
141
154
|
end
|
data/lib/tapyrus/validation.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module Tapyrus
|
2
|
-
|
3
2
|
class Validation
|
4
|
-
|
5
3
|
# check transaction validation
|
6
4
|
def check_tx(tx, state)
|
7
5
|
# Basic checks that don't depend on any context
|
@@ -16,14 +14,20 @@ module Tapyrus
|
|
16
14
|
# Check for negative or overflow output values
|
17
15
|
amount = 0
|
18
16
|
tx.outputs.each do |o|
|
19
|
-
|
20
|
-
|
17
|
+
if o.value < 0
|
18
|
+
return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-negative')
|
19
|
+
end
|
20
|
+
if MAX_MONEY < o.value
|
21
|
+
return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-toolarge')
|
22
|
+
end
|
21
23
|
amount += o.value
|
22
|
-
|
24
|
+
if MAX_MONEY < amount
|
25
|
+
return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-vout-toolarge')
|
26
|
+
end
|
23
27
|
end
|
24
28
|
|
25
29
|
# Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
|
26
|
-
out_points = tx.inputs.map{|i|i.out_point.to_payload}
|
30
|
+
out_points = tx.inputs.map { |i| i.out_point.to_payload }
|
27
31
|
unless out_points.size == out_points.uniq.size
|
28
32
|
return state.DoS(100, reject_code: Message::Reject::CODE_INVALID, reject_reason: 'bad-txns-inputs-duplicate')
|
29
33
|
end
|
@@ -46,7 +50,6 @@ module Tapyrus
|
|
46
50
|
def check_block_header(header, state)
|
47
51
|
header.block_hash
|
48
52
|
header.bits
|
49
|
-
|
50
53
|
end
|
51
54
|
|
52
55
|
def check_block(block, state)
|
@@ -63,12 +66,10 @@ module Tapyrus
|
|
63
66
|
|
64
67
|
# check sigop count
|
65
68
|
end
|
66
|
-
|
67
69
|
end
|
68
70
|
|
69
71
|
class ValidationState
|
70
|
-
|
71
|
-
MODE = {valid: 0, invlid: 1, error: 2}
|
72
|
+
MODE = { valid: 0, invlid: 1, error: 2 }
|
72
73
|
|
73
74
|
attr_accessor :mode
|
74
75
|
attr_accessor :n_dos
|
@@ -107,4 +108,4 @@ module Tapyrus
|
|
107
108
|
mode == MODE[:error]
|
108
109
|
end
|
109
110
|
end
|
110
|
-
end
|
111
|
+
end
|
data/lib/tapyrus/version.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
module Tapyrus
|
2
2
|
module Wallet
|
3
|
-
|
4
3
|
# the account in BIP-44
|
5
4
|
class Account
|
6
5
|
include Tapyrus::HexConverter
|
7
6
|
|
8
|
-
PURPOSE_TYPE = {legacy: 44, nested_witness: 49, native_segwit: 84}
|
7
|
+
PURPOSE_TYPE = { legacy: 44, nested_witness: 49, native_segwit: 84 }
|
9
8
|
|
10
9
|
attr_reader :purpose # either 44 or 49 or 84
|
11
10
|
attr_reader :index # BIP-44 index
|
@@ -86,26 +85,26 @@ module Tapyrus
|
|
86
85
|
# get the list of derived keys for receive key.
|
87
86
|
# @return [Array[Tapyrus::ExtPubkey]]
|
88
87
|
def derived_receive_keys
|
89
|
-
(receive_depth + 1).times.map{|i|derive_key(0,i)}
|
88
|
+
(receive_depth + 1).times.map { |i| derive_key(0, i) }
|
90
89
|
end
|
91
90
|
|
92
91
|
# get the list of derived keys for change key.
|
93
92
|
# @return [Array[Tapyrus::ExtPubkey]]
|
94
93
|
def derived_change_keys
|
95
|
-
(change_depth + 1).times.map{|i|derive_key(1,i)}
|
94
|
+
(change_depth + 1).times.map { |i| derive_key(1, i) }
|
96
95
|
end
|
97
96
|
|
98
97
|
# get account type label.
|
99
98
|
def type
|
100
99
|
case purpose
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
100
|
+
when PURPOSE_TYPE[:legacy]
|
101
|
+
'pubkeyhash'
|
102
|
+
when PURPOSE_TYPE[:nested_witness]
|
103
|
+
'p2wpkh-p2sh'
|
104
|
+
when PURPOSE_TYPE[:native_segwit]
|
105
|
+
'p2wpkh'
|
106
|
+
else
|
107
|
+
'unknown'
|
109
108
|
end
|
110
109
|
end
|
111
110
|
|
@@ -126,10 +125,17 @@ module Tapyrus
|
|
126
125
|
|
127
126
|
def to_h
|
128
127
|
{
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
128
|
+
name: name,
|
129
|
+
type: type,
|
130
|
+
index: index,
|
131
|
+
receive_depth: receive_depth,
|
132
|
+
change_depth: change_depth,
|
133
|
+
look_ahead: lookahead,
|
134
|
+
receive_address: derive_key(0, receive_depth).addr,
|
135
|
+
change_address: derive_key(1, change_depth).addr,
|
136
|
+
account_key: account_key.to_base58,
|
137
|
+
path: path,
|
138
|
+
watch_only: watch_only
|
133
139
|
}
|
134
140
|
end
|
135
141
|
|
@@ -145,8 +151,6 @@ module Tapyrus
|
|
145
151
|
version_bytes = Tapyrus::ExtPubkey.version_from_purpose(purpose + Tapyrus::HARDENED_THRESHOLD)
|
146
152
|
raise 'The purpose and the account key do not match.' unless account_key.version == version_bytes
|
147
153
|
end
|
148
|
-
|
149
154
|
end
|
150
|
-
|
151
155
|
end
|
152
156
|
end
|
data/lib/tapyrus/wallet/base.rb
CHANGED
@@ -2,9 +2,7 @@ require 'leveldb-native'
|
|
2
2
|
|
3
3
|
module Tapyrus
|
4
4
|
module Wallet
|
5
|
-
|
6
5
|
class Base
|
7
|
-
|
8
6
|
attr_accessor :wallet_id
|
9
7
|
attr_reader :db
|
10
8
|
attr_reader :path
|
@@ -24,6 +22,7 @@ module Tapyrus
|
|
24
22
|
def self.create(wallet_id = 1, path_prefix = default_path_prefix)
|
25
23
|
raise ArgumentError, "wallet_id : #{wallet_id} already exist." if self.exist?(wallet_id, path_prefix)
|
26
24
|
w = self.new(wallet_id, path_prefix)
|
25
|
+
|
27
26
|
# generate seed
|
28
27
|
raise RuntimeError, 'the seed already exist.' if w.db.registered_master?
|
29
28
|
master = Tapyrus::Wallet::MasterKey.generate
|
@@ -122,14 +121,20 @@ module Tapyrus
|
|
122
121
|
|
123
122
|
# decrypt wallet
|
124
123
|
# @param [String] passphrase the wallet passphrase
|
125
|
-
def decrypt(passphrase)
|
126
|
-
|
127
|
-
end
|
124
|
+
def decrypt(passphrase); end
|
128
125
|
|
129
126
|
# wallet information
|
130
127
|
def to_h
|
131
128
|
a = accounts.map(&:to_h)
|
132
|
-
{
|
129
|
+
{
|
130
|
+
wallet_id: wallet_id,
|
131
|
+
version: version,
|
132
|
+
account_depth: a.size,
|
133
|
+
accounts: a,
|
134
|
+
master: {
|
135
|
+
encrypted: master_key.encrypted
|
136
|
+
}
|
137
|
+
}
|
133
138
|
end
|
134
139
|
|
135
140
|
# get data elements tobe monitored with Bloom Filter.
|
@@ -153,10 +158,8 @@ module Tapyrus
|
|
153
158
|
|
154
159
|
# find account using +account_name+
|
155
160
|
def find_account(account_name, purpose = nil)
|
156
|
-
accounts(purpose).find{|a| a.name == account_name}
|
161
|
+
accounts(purpose).find { |a| a.name == account_name }
|
157
162
|
end
|
158
|
-
|
159
163
|
end
|
160
|
-
|
161
164
|
end
|
162
165
|
end
|