money-tree 0.8.4 → 0.8.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/money-tree/address.rb +4 -3
- data/lib/money-tree/key.rb +43 -13
- data/lib/money-tree/networks.rb +8 -6
- data/lib/money-tree/node.rb +27 -16
- data/lib/money-tree/version.rb +1 -1
- data/spec/lib/money-tree/address_spec.rb +10 -0
- data/spec/lib/money-tree/node_spec.rb +53 -1
- data/spec/lib/money-tree/private_key_spec.rb +12 -0
- data/spec/lib/money-tree/public_key_spec.rb +23 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed8522c0f961d7b6556cc9067455f12d65bcfd0f
|
4
|
+
data.tar.gz: 02857ab85d9b22a1a96c71f6d47c957a9310eb23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9d8647c31dccee3b9c34ad46e533bbd0cd37c8407402caa1356e8282b3e3e422637b69ebbee42a840c64948ccca8e9d5479fb0a260fa7d8508790210f9317ae
|
7
|
+
data.tar.gz: 22fbe674fbb0919ced227c8d3bd5f9f554b76726fca29442b2dd545c810f05e9dd5b97fa1f2f2ceaedaeb06e8b58f7b2c6bcb8f8e6d57e4d1103cc3c250369ac
|
data/lib/money-tree/address.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module MoneyTree
|
2
2
|
class Address
|
3
|
-
|
3
|
+
attr_reader :private_key, :public_key
|
4
4
|
|
5
5
|
def initialize(opts = {})
|
6
|
-
|
7
|
-
@
|
6
|
+
private_key = opts.delete(:private_key)
|
7
|
+
@private_key = MoneyTree::PrivateKey.new({ key: private_key }.merge(opts))
|
8
|
+
@public_key = MoneyTree::PublicKey.new(@private_key, opts)
|
8
9
|
end
|
9
10
|
|
10
11
|
def to_s
|
data/lib/money-tree/key.rb
CHANGED
@@ -15,7 +15,7 @@ module MoneyTree
|
|
15
15
|
class InvalidWIFFormat < Exception; end
|
16
16
|
class InvalidBase64Format < Exception; end
|
17
17
|
|
18
|
-
attr_reader :options, :key, :raw_key
|
18
|
+
attr_reader :options, :key, :raw_key, :network, :network_key
|
19
19
|
attr_accessor :ec_key
|
20
20
|
|
21
21
|
GROUP_NAME = 'secp256k1'
|
@@ -40,6 +40,8 @@ module MoneyTree
|
|
40
40
|
def initialize(opts = {})
|
41
41
|
@options = opts
|
42
42
|
@ec_key = PKey::EC.new GROUP_NAME
|
43
|
+
@network_key = options[:network] || :bitcoin
|
44
|
+
@network = MoneyTree::NETWORKS[network_key]
|
43
45
|
if @options[:key]
|
44
46
|
@raw_key = @options[:key]
|
45
47
|
@key = parse_raw_key
|
@@ -71,8 +73,8 @@ module MoneyTree
|
|
71
73
|
end
|
72
74
|
|
73
75
|
def parse_raw_key
|
74
|
-
result = if raw_key.is_a?(Bignum) then
|
75
|
-
elsif hex_format? then
|
76
|
+
result = if raw_key.is_a?(Bignum) then from_bignum
|
77
|
+
elsif hex_format? then from_hex
|
76
78
|
elsif base64_format? then from_base64
|
77
79
|
elsif compressed_wif_format? then from_wif
|
78
80
|
elsif uncompressed_wif_format? then from_wif
|
@@ -81,28 +83,52 @@ module MoneyTree
|
|
81
83
|
end
|
82
84
|
result.downcase
|
83
85
|
end
|
86
|
+
|
87
|
+
def from_bignum(bignum = raw_key)
|
88
|
+
int_to_hex(bignum)
|
89
|
+
end
|
90
|
+
|
91
|
+
def from_hex(hex = raw_key)
|
92
|
+
hex
|
93
|
+
end
|
84
94
|
|
85
95
|
def from_wif(wif = raw_key)
|
86
96
|
compressed = wif.length == 52
|
97
|
+
parse_network_from_wif(wif, compressed: compressed)
|
87
98
|
validate_wif(wif)
|
88
99
|
hex = decode_base58(wif)
|
89
100
|
last_char = compressed ? -11 : -9
|
90
101
|
hex.slice(2..last_char)
|
91
102
|
end
|
103
|
+
|
104
|
+
def parse_network_from_wif(wif, opts = {})
|
105
|
+
networks = MoneyTree::NETWORKS
|
106
|
+
chars_key = opts[:compressed] ? :compressed_wif_chars : :uncompressed_wif_chars
|
107
|
+
@network_key = networks.keys.select do |k|
|
108
|
+
networks[k][chars_key].include?(wif.slice(0))
|
109
|
+
end.first
|
110
|
+
@network = networks[network_key]
|
111
|
+
end
|
92
112
|
|
93
113
|
def from_base64(base64_key = raw_key)
|
94
114
|
raise InvalidBase64Format unless base64_format?(base64_key)
|
95
115
|
decode_base64(base64_key)
|
96
116
|
end
|
97
|
-
|
117
|
+
|
98
118
|
def compressed_wif_format?
|
99
|
-
|
119
|
+
wif_format?(:compressed)
|
100
120
|
end
|
101
121
|
|
102
122
|
def uncompressed_wif_format?
|
103
|
-
|
123
|
+
wif_format?(:uncompressed)
|
104
124
|
end
|
105
|
-
|
125
|
+
|
126
|
+
def wif_format?(compression)
|
127
|
+
length = compression == :compressed ? 52 : 51
|
128
|
+
wif_prefixes = MoneyTree::NETWORKS.map {|k, v| v["#{compression}_wif_chars".to_sym]}.flatten
|
129
|
+
raw_key.length == length && wif_prefixes.include?(raw_key.slice(0))
|
130
|
+
end
|
131
|
+
|
106
132
|
def base64_format?(base64_key = raw_key)
|
107
133
|
base64_key.length == 44 && base64_key =~ /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/
|
108
134
|
end
|
@@ -117,8 +143,8 @@ module MoneyTree
|
|
117
143
|
|
118
144
|
def to_wif(opts = {})
|
119
145
|
opts[:compressed] = true unless opts[:compressed] == false
|
120
|
-
source =
|
121
|
-
source +=
|
146
|
+
source = network[:privkey_version] + to_hex
|
147
|
+
source += network[:privkey_compression_flag] if opts[:compressed]
|
122
148
|
hash = sha256(source)
|
123
149
|
hash = sha256(hash)
|
124
150
|
checksum = hash.slice(0..7)
|
@@ -128,7 +154,7 @@ module MoneyTree
|
|
128
154
|
|
129
155
|
def wif_valid?(wif)
|
130
156
|
hex = decode_base58(wif)
|
131
|
-
return false unless hex.slice(0..1) ==
|
157
|
+
return false unless hex.slice(0..1) == network[:privkey_version]
|
132
158
|
checksum = hex.chars.to_a.pop(8).join
|
133
159
|
source = hex.slice(0..-9)
|
134
160
|
hash = sha256(source)
|
@@ -160,10 +186,14 @@ module MoneyTree
|
|
160
186
|
|
161
187
|
if p_key.is_a?(PrivateKey)
|
162
188
|
@private_key = p_key
|
189
|
+
@network_key = private_key.network_key
|
190
|
+
@network = MoneyTree::NETWORKS[network_key]
|
163
191
|
@point = @private_key.calculate_public_key(@options)
|
164
192
|
@group = @point.group
|
165
193
|
@key = @raw_key = to_hex
|
166
194
|
else
|
195
|
+
@network_key = @options[:network] || :bitcoin
|
196
|
+
@network = MoneyTree::NETWORKS[network_key]
|
167
197
|
@raw_key = p_key
|
168
198
|
@group = PKey::EC::Group.new GROUP_NAME
|
169
199
|
@key = parse_raw_key
|
@@ -180,13 +210,13 @@ module MoneyTree
|
|
180
210
|
end
|
181
211
|
|
182
212
|
def compressed
|
183
|
-
compressed_key = self.class.new raw_key # deep clone
|
213
|
+
compressed_key = self.class.new raw_key, options # deep clone
|
184
214
|
compressed_key.set_point to_i, compressed: true
|
185
215
|
compressed_key
|
186
216
|
end
|
187
217
|
|
188
218
|
def uncompressed
|
189
|
-
uncompressed_key = self.class.new raw_key # deep clone
|
219
|
+
uncompressed_key = self.class.new raw_key, options # deep clone
|
190
220
|
uncompressed_key.set_point to_i, compressed: false
|
191
221
|
uncompressed_key
|
192
222
|
end
|
@@ -236,7 +266,7 @@ module MoneyTree
|
|
236
266
|
|
237
267
|
def to_address
|
238
268
|
hash = to_ripemd160
|
239
|
-
address =
|
269
|
+
address = network[:address_version] + hash
|
240
270
|
to_serialized_base58 address
|
241
271
|
end
|
242
272
|
alias :to_s :to_address
|
data/lib/money-tree/networks.rb
CHANGED
@@ -3,24 +3,26 @@ module MoneyTree
|
|
3
3
|
bitcoin: {
|
4
4
|
address_version: '00',
|
5
5
|
p2sh_version: '05',
|
6
|
+
p2sh_char: '3',
|
6
7
|
privkey_version: '80',
|
7
8
|
privkey_compression_flag: '01',
|
8
9
|
extended_privkey_version: "0488ade4",
|
9
10
|
extended_pubkey_version: "0488b21e",
|
10
11
|
compressed_wif_chars: %w(K L),
|
11
|
-
|
12
|
+
uncompressed_wif_chars: %w(5),
|
12
13
|
protocol_version: 70001
|
13
14
|
},
|
14
15
|
bitcoin_testnet: {
|
15
16
|
address_version: '6f',
|
16
|
-
p2sh_version: '
|
17
|
-
|
17
|
+
p2sh_version: 'c4',
|
18
|
+
p2sh_char: '2',
|
19
|
+
privkey_version: 'ef',
|
18
20
|
privkey_compression_flag: '01',
|
19
21
|
extended_privkey_version: "04358394",
|
20
22
|
extended_pubkey_version: "043587cf",
|
21
|
-
compressed_wif_chars: %w(
|
22
|
-
|
23
|
+
compressed_wif_chars: %w(c),
|
24
|
+
uncompressed_wif_chars: %w(9),
|
23
25
|
protocol_version: 70001
|
24
26
|
}
|
25
27
|
}
|
26
|
-
end
|
28
|
+
end
|
data/lib/money-tree/node.rb
CHANGED
@@ -2,7 +2,7 @@ module MoneyTree
|
|
2
2
|
class Node
|
3
3
|
include Support
|
4
4
|
extend Support
|
5
|
-
attr_reader :private_key, :public_key, :chain_code, :is_private, :depth, :index, :parent, :
|
5
|
+
attr_reader :private_key, :public_key, :chain_code, :is_private, :depth, :index, :parent, :network, :network_key
|
6
6
|
|
7
7
|
class PublicDerivationFailure < Exception; end
|
8
8
|
class InvalidKeyForIndex < Exception; end
|
@@ -10,6 +10,8 @@ module MoneyTree
|
|
10
10
|
class PrivatePublicMismatch < Exception; end
|
11
11
|
|
12
12
|
def initialize(opts = {})
|
13
|
+
@network_key = opts.delete(:network) || :bitcoin
|
14
|
+
@network = MoneyTree::NETWORKS[network_key]
|
13
15
|
opts.each { |k, v| instance_variable_set "@#{k}", v }
|
14
16
|
end
|
15
17
|
|
@@ -17,7 +19,6 @@ module MoneyTree
|
|
17
19
|
hex = from_serialized_base58 address
|
18
20
|
version = from_version_hex hex.slice!(0..7)
|
19
21
|
self.new({
|
20
|
-
is_test: version[:test],
|
21
22
|
depth: hex.slice!(0..1).to_i(16),
|
22
23
|
fingerprint: hex.slice!(0..7),
|
23
24
|
index: hex.slice!(0..7).to_i(16),
|
@@ -26,11 +27,12 @@ module MoneyTree
|
|
26
27
|
end
|
27
28
|
|
28
29
|
def self.key_options(hex, version)
|
30
|
+
k_opts = { network: version[:network] }
|
29
31
|
if version[:private_key] && hex.slice(0..1) == '00'
|
30
|
-
private_key = MoneyTree::PrivateKey.new key: hex.slice(2..-1)
|
31
|
-
|
32
|
+
private_key = MoneyTree::PrivateKey.new({ key: hex.slice(2..-1) }.merge(k_opts))
|
33
|
+
k_opts.merge private_key: private_key, public_key: MoneyTree::PublicKey.new(private_key)
|
32
34
|
elsif %w(02 03).include? hex.slice(0..1)
|
33
|
-
|
35
|
+
k_opts.merge public_key: MoneyTree::PublicKey.new(hex, k_opts)
|
34
36
|
else
|
35
37
|
raise ImportError, 'Public or private key data does not match version type'
|
36
38
|
end
|
@@ -39,13 +41,13 @@ module MoneyTree
|
|
39
41
|
def self.from_version_hex(hex)
|
40
42
|
case hex
|
41
43
|
when MoneyTree::NETWORKS[:bitcoin][:extended_privkey_version]
|
42
|
-
{ private_key: true,
|
44
|
+
{ private_key: true, network: :bitcoin }
|
43
45
|
when MoneyTree::NETWORKS[:bitcoin][:extended_pubkey_version]
|
44
|
-
{ private_key: false,
|
46
|
+
{ private_key: false, network: :bitcoin }
|
45
47
|
when MoneyTree::NETWORKS[:bitcoin_testnet][:extended_privkey_version]
|
46
|
-
{ private_key: true,
|
48
|
+
{ private_key: true, network: :bitcoin_testnet }
|
47
49
|
when MoneyTree::NETWORKS[:bitcoin_testnet][:extended_pubkey_version]
|
48
|
-
{ private_key: false,
|
50
|
+
{ private_key: false, network: :bitcoin_testnet }
|
49
51
|
else
|
50
52
|
raise ImportError, 'invalid version bytes'
|
51
53
|
end
|
@@ -114,7 +116,7 @@ module MoneyTree
|
|
114
116
|
def to_serialized_hex(type = :public)
|
115
117
|
raise PrivatePublicMismatch if type.to_sym == :private && private_key.nil?
|
116
118
|
version_key = type.to_sym == :private ? :extended_privkey_version : :extended_pubkey_version
|
117
|
-
hex =
|
119
|
+
hex = network[version_key] # version (4 bytes)
|
118
120
|
hex += depth_hex(depth) # depth (1 byte)
|
119
121
|
hex += depth.zero? ? '00000000' : parent.to_fingerprint# fingerprint of key (4 bytes)
|
120
122
|
hex += index_hex(index) # child number i (4 bytes)
|
@@ -136,21 +138,22 @@ module MoneyTree
|
|
136
138
|
end
|
137
139
|
|
138
140
|
def to_address
|
139
|
-
address =
|
141
|
+
address = network[:address_version] + to_identifier
|
140
142
|
to_serialized_base58 address
|
141
143
|
end
|
142
144
|
|
143
145
|
def subnode(i = 0, opts = {})
|
144
146
|
if private_key.nil?
|
145
147
|
child_public_key, child_chain_code = derive_public_key(i)
|
146
|
-
child_public_key = MoneyTree::PublicKey.new child_public_key
|
148
|
+
child_public_key = MoneyTree::PublicKey.new child_public_key, network: network_key
|
147
149
|
else
|
148
150
|
child_private_key, child_chain_code = derive_private_key(i)
|
149
|
-
child_private_key = MoneyTree::PrivateKey.new key: child_private_key
|
151
|
+
child_private_key = MoneyTree::PrivateKey.new key: child_private_key, network: network_key
|
150
152
|
child_public_key = MoneyTree::PublicKey.new child_private_key
|
151
153
|
end
|
152
154
|
|
153
|
-
MoneyTree::Node.new
|
155
|
+
MoneyTree::Node.new network: network_key,
|
156
|
+
depth: depth+1,
|
154
157
|
index: i,
|
155
158
|
private_key: private_key.nil? ? nil : child_private_key,
|
156
159
|
public_key: child_public_key,
|
@@ -233,6 +236,8 @@ module MoneyTree
|
|
233
236
|
@depth = 0
|
234
237
|
@index = 0
|
235
238
|
opts[:seed] = [opts[:seed_hex]].pack("H*") if opts[:seed_hex]
|
239
|
+
@network_key = opts[:network] || :bitcoin
|
240
|
+
@network = MoneyTree::NETWORKS[network_key]
|
236
241
|
if opts[:seed]
|
237
242
|
@seed = opts[:seed]
|
238
243
|
@seed_hash = generate_seed_hash(@seed)
|
@@ -243,9 +248,15 @@ module MoneyTree
|
|
243
248
|
@chain_code = opts[:chain_code]
|
244
249
|
if opts[:private_key]
|
245
250
|
@private_key = opts[:private_key]
|
251
|
+
@network_key = @private_key.network_key
|
252
|
+
@network = MoneyTree::NETWORKS[network_key]
|
246
253
|
@public_key = MoneyTree::PublicKey.new @private_key
|
247
254
|
else opts[:public_key]
|
248
|
-
@public_key = opts[:public_key].is_a?(MoneyTree::PublicKey)
|
255
|
+
@public_key = if opts[:public_key].is_a?(MoneyTree::PublicKey)
|
256
|
+
opts[:public_key]
|
257
|
+
else
|
258
|
+
MoneyTree::PublicKey.new(opts[:public_key], network: network_key)
|
259
|
+
end
|
249
260
|
end
|
250
261
|
else
|
251
262
|
generate_seed
|
@@ -274,7 +285,7 @@ module MoneyTree
|
|
274
285
|
end
|
275
286
|
|
276
287
|
def set_seeded_keys
|
277
|
-
@private_key = MoneyTree::PrivateKey.new key: left_from_hash(seed_hash)
|
288
|
+
@private_key = MoneyTree::PrivateKey.new key: left_from_hash(seed_hash), network: network_key
|
278
289
|
@chain_code = right_from_hash(seed_hash)
|
279
290
|
@public_key = MoneyTree::PublicKey.new @private_key
|
280
291
|
end
|
data/lib/money-tree/version.rb
CHANGED
@@ -49,4 +49,14 @@ describe MoneyTree::Address do
|
|
49
49
|
@address.private_key.to_s.should == "KzPkwAXJ4wtXHnbamTaJqoMrzwCUUJaqhUxnqYhnZvZH6KhgmDPK"
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
53
|
+
context "testnet3" do
|
54
|
+
before do
|
55
|
+
@address = MoneyTree::Address.new network: :bitcoin_testnet
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns a testnet address" do
|
59
|
+
%w(m n).should include(@address.to_s[0])
|
60
|
+
end
|
61
|
+
end
|
52
62
|
end
|
@@ -12,7 +12,59 @@ describe MoneyTree::Master do
|
|
12
12
|
@master.seed.bytesize.should == 32
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
|
+
context "testnet" do
|
17
|
+
before do
|
18
|
+
@master = MoneyTree::Master.new network: :bitcoin_testnet
|
19
|
+
end
|
20
|
+
|
21
|
+
it "generates testnet address" do
|
22
|
+
%w(m n).should include(@master.to_address[0])
|
23
|
+
end
|
24
|
+
|
25
|
+
it "generates testnet compressed wif" do
|
26
|
+
@master.private_key.to_wif[0].should == 'c'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "generates testnet uncompressed wif" do
|
30
|
+
@master.private_key.to_wif(compressed: false)[0].should == '9'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "generates testnet serialized private address" do
|
34
|
+
@master.to_serialized_address(:private).slice(0, 4).should == "tprv"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "generates testnet serialized public address" do
|
38
|
+
@master.to_serialized_address.slice(0, 4).should == "tpub"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "imports from testnet serialized private address" do
|
42
|
+
node = MoneyTree::Node.from_serialized_address 'tprv8ZgxMBicQKsPcuN7bfUZqq78UEYapr3Tzmc9NcDXw8BnBJ47dZYr6SusnfYj7vbAYP9CP8ZiD5aVBTUo1yU5QP56mepKVvuEbu8KZQXMKNE'
|
43
|
+
node.to_serialized_address(:private).should == 'tprv8ZgxMBicQKsPcuN7bfUZqq78UEYapr3Tzmc9NcDXw8BnBJ47dZYr6SusnfYj7vbAYP9CP8ZiD5aVBTUo1yU5QP56mepKVvuEbu8KZQXMKNE'
|
44
|
+
end
|
45
|
+
|
46
|
+
it "imports from testnet serialized public address" do
|
47
|
+
node = MoneyTree::Node.from_serialized_address 'tpubD6NzVbkrYhZ4YA8aUE9bBZTSyHJibBqwDny5urfwDdJc4W8od3y3Ebzy6CqsYn9CCC5P5VQ7CeZYpnT1kX3RPVPysU2rFRvYSj8BCoYYNqT'
|
48
|
+
%w(m n).should include(node.public_key.to_s[0])
|
49
|
+
node.to_serialized_address.should == 'tpubD6NzVbkrYhZ4YA8aUE9bBZTSyHJibBqwDny5urfwDdJc4W8od3y3Ebzy6CqsYn9CCC5P5VQ7CeZYpnT1kX3RPVPysU2rFRvYSj8BCoYYNqT'
|
50
|
+
end
|
51
|
+
|
52
|
+
it "generates testnet subnodes from serialized private address" do
|
53
|
+
node = MoneyTree::Node.from_serialized_address 'tprv8ZgxMBicQKsPcuN7bfUZqq78UEYapr3Tzmc9NcDXw8BnBJ47dZYr6SusnfYj7vbAYP9CP8ZiD5aVBTUo1yU5QP56mepKVvuEbu8KZQXMKNE'
|
54
|
+
subnode = node.node_for_path('1/1/1')
|
55
|
+
%w(m n).should include(subnode.public_key.to_s[0])
|
56
|
+
subnode.to_serialized_address(:private).slice(0,4).should == 'tprv'
|
57
|
+
subnode.to_serialized_address.slice(0,4).should == 'tpub'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "generates testnet subnodes from serialized public address" do
|
61
|
+
node = MoneyTree::Node.from_serialized_address 'tpubD6NzVbkrYhZ4YA8aUE9bBZTSyHJibBqwDny5urfwDdJc4W8od3y3Ebzy6CqsYn9CCC5P5VQ7CeZYpnT1kX3RPVPysU2rFRvYSj8BCoYYNqT'
|
62
|
+
subnode = node.node_for_path('1/1/1')
|
63
|
+
%w(m n).should include(subnode.public_key.to_s[0])
|
64
|
+
subnode.to_serialized_address.slice(0,4).should == 'tpub'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
16
68
|
describe "Test vector 1" do
|
17
69
|
describe "from a seed" do
|
18
70
|
before do
|
@@ -91,4 +91,16 @@ describe MoneyTree::PrivateKey do
|
|
91
91
|
|
92
92
|
end
|
93
93
|
end
|
94
|
+
|
95
|
+
context "testnet" do
|
96
|
+
before do
|
97
|
+
@key = MoneyTree::PrivateKey.new key: 'cRhes8SBnsF6WizphaRKQKZZfDniDa9Bxcw31yKeEC1KDExhxFgD'
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "to_wif" do
|
101
|
+
it "returns same wif" do
|
102
|
+
@key.to_wif.should == 'cRhes8SBnsF6WizphaRKQKZZfDniDa9Bxcw31yKeEC1KDExhxFgD'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
94
106
|
end
|
@@ -157,4 +157,27 @@ describe MoneyTree::PublicKey do
|
|
157
157
|
before_str.should == after_str
|
158
158
|
end
|
159
159
|
end
|
160
|
+
|
161
|
+
context "testnet" do
|
162
|
+
context 'with private key' do
|
163
|
+
before do
|
164
|
+
@private_key = MoneyTree::PrivateKey.new network: :bitcoin_testnet
|
165
|
+
@key = MoneyTree::PublicKey.new(@private_key)
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should have an address starting with m or n" do
|
169
|
+
%w(m n).should include(@key.to_s[0])
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'without private key' do
|
174
|
+
before do
|
175
|
+
@key = MoneyTree::PublicKey.new('0297b033ba894611345a0e777861237ef1632370fbd58ebe644eb9f3714e8fe2bc', network: :bitcoin_testnet)
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should have an address starting with m or n" do
|
179
|
+
%w(m n).should include(@key.to_s[0])
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
160
183
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: money-tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Micah Winkelspecht
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-12-
|
11
|
+
date: 2013-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|