money-tree 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4fb106149c53cf468220d50f609604835f0771d0
4
- data.tar.gz: ae65887642b07d8bcfdefae06452d4b0a91d0f2a
3
+ metadata.gz: 838719a8f745234b8e08d8726d2e4af5b61d93de
4
+ data.tar.gz: 9391e5eebd7b8b71dfe98ef61f2ff5e3ad0094ad
5
5
  SHA512:
6
- metadata.gz: ea72d026539e19514e95d51a0e2404dfd594b6d524b4debfe491b762d0d1d24f1cc0d3ef0cbd1fb20db29de0403c7d7066d3190f4aca3736853bfd4d6354853a
7
- data.tar.gz: c2e21de52d10e2f9d2917be4a6db7cd5e9c8b6588959963ead0648a6b219b479a1c5f67ac45299f0a31ff380562c6a138a449df656988a0ad1310a77f0762860
6
+ metadata.gz: 73142e1cd77e36e4a4750b0a7f2e4f34f47f9320a27144ea412fd5149073598642624a37d63aca0417136c4acb9bb2e1043ec8d679384fe5a5eb415e8fc033e8
7
+ data.tar.gz: 6e0e848c4b968c004ca66acfd5ff1e917978fd9af63fea16264785d36ab6219ba6ef8a493919607c40789335f87d85f02d6a9c444fae3494f8d70b1e9f5ee55c
data/.simplecov ADDED
@@ -0,0 +1,7 @@
1
+ require 'coveralls'
2
+
3
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
4
+ SimpleCov::Formatter::HTMLFormatter,
5
+ Coveralls::SimpleCov::Formatter
6
+ ]
7
+ SimpleCov.start
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
+ [![Build Status](https://travis-ci.org/wink/money-tree.png)](https://travis-ci.org/wink/money-tree) [![Coverage Status](https://coveralls.io/repos/wink/money-tree/badge.png?branch=master)](https://coveralls.io/r/wink/money-tree?branch=master) [![Gem Version](https://badge.fury.io/rb/money-tree.png)](http://badge.fury.io/rb/money-tree)
1
2
  # MoneyTree
2
3
 
3
- MoneyTree is a Ruby implementation of Bitcoin Wallets. Specifically, it supports [Hierachical Deterministic wallets](http://) according to the protocol specified in [BIP0032](https://en.bitcoin.it/wiki/BIP_0032).
4
+ MoneyTree is a Ruby implementation of Bitcoin Wallets. Specifically, it supports [Hierachical Deterministic wallets](https://en.bitcoin.it/wiki/Deterministic_Wallet) according to the protocol specified in [BIP0032](https://en.bitcoin.it/wiki/BIP_0032).
5
+
6
+ If you find this helpful, please consider a small Bitcoin donation to 1nj2kie1hATcFbAaD7dEY53QaxNgt4KBp
4
7
 
5
8
  ## Installation
6
9
 
@@ -16,9 +19,12 @@ Or install it yourself as:
16
19
 
17
20
  $ gem install money-tree
18
21
 
22
+ ## Prerequisites
23
+ MoneyTree will only work with Ruby 2.0.0 and greater. This is because the version of OpenSSL included with previous versions of Ruby did not include an OpenSSL::PKey::EC::Point#mul (point multiplication) method, which is required in order to calculate a Bitcoin public key from a private key.
24
+
19
25
  ## Usage
20
26
 
21
- TODO: Write usage instructions here
27
+ Documentation coming very soon! For now, please feel free to browse the source and specs.
22
28
 
23
29
  ## Contributing
24
30
 
data/Rakefile CHANGED
@@ -1 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -12,6 +12,7 @@ module MoneyTree
12
12
  class KeyImportFailure < Exception; end
13
13
  class KeyFormatNotFound < Exception; end
14
14
  class InvalidWIFFormat < Exception; end
15
+ class InvalidBase64Format < Exception; end
15
16
 
16
17
  attr_reader :options, :key
17
18
  attr_accessor :ec_key
@@ -76,11 +77,10 @@ module MoneyTree
76
77
  def parse_raw_key
77
78
  result = if raw_key.is_a?(Bignum) then int_to_hex(raw_key)
78
79
  elsif hex_format? then raw_key
80
+ elsif base64_format? then from_base64
79
81
  elsif compressed_wif_format? then from_wif
80
82
  elsif uncompressed_wif_format? then from_wif
81
- elsif base64_format? then from_base64
82
83
  else
83
- raise raw_key.inspect
84
84
  raise KeyFormatNotFound
85
85
  end
86
86
  result.downcase
@@ -94,8 +94,9 @@ module MoneyTree
94
94
  hex.slice(2..last_char)
95
95
  end
96
96
 
97
- def from_base64
98
- decode_base64(raw_key)
97
+ def from_base64(base64_key = raw_key)
98
+ raise InvalidBase64Format unless base64_format?(base64_key)
99
+ decode_base64(base64_key)
99
100
  end
100
101
 
101
102
  def compressed_wif_format?
@@ -106,8 +107,8 @@ module MoneyTree
106
107
  raw_key.length == 51 && raw_key.slice(0) == MoneyTree::NETWORKS[:bitcoin][:uncompressed_wif_char]
107
108
  end
108
109
 
109
- def base64_format?
110
- raw_key.length == 44
110
+ def base64_format?(base64_key = raw_key)
111
+ base64_key.length == 44 && base64_key =~ /^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/
111
112
  end
112
113
 
113
114
  def hex_format?
@@ -16,12 +16,12 @@ module MoneyTree
16
16
  @parent = opts[:parent]
17
17
  end
18
18
 
19
- def is_private?
20
- is_private == true
21
- end
22
-
23
19
  def index_hex(i = index)
24
- i.to_s(16).rjust(8, "0")
20
+ if i < 0
21
+ [i].pack('l>').unpack('H*').first
22
+ else
23
+ i.to_s(16).rjust(8, "0")
24
+ end
25
25
  end
26
26
 
27
27
  def depth_hex(depth)
@@ -94,7 +94,7 @@ module MoneyTree
94
94
  end
95
95
 
96
96
  def to_fingerprint
97
- to_identifier[0..7]
97
+ public_key.to_fingerprint
98
98
  end
99
99
 
100
100
  def to_address
@@ -107,10 +107,11 @@ module MoneyTree
107
107
  child_private_key, child_chain_code = derive_private_key(i)
108
108
  child_private_key = MoneyTree::PrivateKey.new key: child_private_key
109
109
  child_public_key = MoneyTree::PublicKey.new child_private_key
110
+ index = i
110
111
 
111
112
  MoneyTree::Node.new depth: depth+1,
112
113
  index: i,
113
- is_private: i >= 0x80000000,
114
+ is_private: i >= 0x80000000 || i < 0,
114
115
  private_key: child_private_key,
115
116
  public_key: child_public_key,
116
117
  chain_code: child_chain_code,
@@ -194,15 +195,9 @@ module MoneyTree
194
195
  end
195
196
 
196
197
  def generate_seed_until_valid
197
- begin
198
- @seed = generate_seed
199
- @seed_hash = generate_seed_hash(@seed)
200
- raise SeedGeneration::ValidityError unless seed_valid?(@seed_hash)
201
- @seed_generation_attempt = 0
202
- rescue SeedGeneration::Failure
203
- @seed_generation_attempt += 1
204
- @seed_generation_attempt < 10 ? generate_seed_until_valid : raise(SeedGeneration::TooManyAttempts)
205
- end
198
+ @seed = generate_seed
199
+ @seed_hash = generate_seed_hash(@seed)
200
+ raise SeedGeneration::ValidityError unless seed_valid?(@seed_hash)
206
201
  end
207
202
 
208
203
  def generate_seed
@@ -219,10 +214,6 @@ module MoneyTree
219
214
  !master_key.zero? && master_key < MoneyTree::Key::ORDER
220
215
  end
221
216
 
222
- def is_hex?(str)
223
- str =~ /^[0-9A-F]+$/i && str.length % 2 == 0
224
- end
225
-
226
217
  def set_master_keys
227
218
  @private_key = MoneyTree::PrivateKey.new key: left_from_hash(seed_hash)
228
219
  @chain_code = right_from_hash(seed_hash)
@@ -1,4 +1,5 @@
1
1
  require 'openssl'
2
+ require 'base64'
2
3
 
3
4
  module MoneyTree
4
5
  module Support
@@ -58,11 +59,11 @@ module MoneyTree
58
59
  end
59
60
 
60
61
  def encode_base64(hex)
61
- [[hex].pack("H*")].pack("m0")
62
+ Base64.encode64([hex].pack("H*")).chomp
62
63
  end
63
64
 
64
65
  def decode_base64(base64)
65
- base64.unpack("m0").unpack("H*")
66
+ Base64.decode64(base64).unpack("H*")[0]
66
67
  end
67
68
 
68
69
  def hmac_sha512(key, message)
@@ -89,21 +90,21 @@ module MoneyTree
89
90
  hex = '0' + hex unless (hex.length % 2).zero?
90
91
  hex.downcase
91
92
  end
92
-
93
+
93
94
  def int_to_bytes(i)
94
95
  [int_to_hex(i)].pack("H*")
95
96
  end
96
97
 
97
- def bytes_to_hex(i)
98
- i.unpack("H*")[0].downcase
98
+ def bytes_to_hex(bytes)
99
+ bytes.unpack("H*")[0].downcase
99
100
  end
100
101
 
101
- def hex_to_bytes(i)
102
- [i].pack("H*")
102
+ def hex_to_bytes(hex)
103
+ [hex].pack("H*")
103
104
  end
104
105
 
105
- def hex_to_int(i)
106
- bytes_to_int(hex_to_bytes(i))
106
+ def hex_to_int(hex)
107
+ hex.to_i(16)
107
108
  end
108
109
  end
109
110
  end
@@ -1,3 +1,3 @@
1
1
  module MoneyTree
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/money-tree.gemspec CHANGED
@@ -21,5 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "simplecov"
25
+ spec.add_development_dependency "coveralls"
24
26
  spec.add_development_dependency "pry"
25
27
  end
@@ -1,3 +1,4 @@
1
+ require 'spec_helper'
1
2
  require 'money-tree'
2
3
 
3
4
  describe MoneyTree::Address do
@@ -1,3 +1,4 @@
1
+ require 'spec_helper'
1
2
  require 'money-tree'
2
3
 
3
4
  # Test vectors from https://en.bitcoin.it/wiki/BIP_0032_TestVectors
@@ -537,6 +538,34 @@ describe MoneyTree::Master do
537
538
  end
538
539
  end
539
540
  end
540
-
541
+
542
+ describe "negative index" do
543
+ before do
544
+ @master = MoneyTree::Master.new seed_hex: "000102030405060708090a0b0c0d0e0f"
545
+ @node = @master.node_for_path "m/0'/-1"
546
+ end
547
+
548
+ it "has an index of 1" do
549
+ @node.index.should == -1
550
+ end
551
+
552
+ it "is public" do
553
+ @node.is_private.should == true
554
+ end
555
+
556
+ it "has a depth of 2" do
557
+ @node.depth.should == 2
558
+ end
559
+
560
+ it "generates a serialized private key" do
561
+ @node.to_serialized_hex(:private).should == "0488ade4025c1bd648ffffffffeb8291afea1716eb01a1ce7e00d1843072cbd227309df728ba4015f73d5344aa00d9bd1df2ae56b5be763ddd393573497a8075352bda4aad9ea9083e4c0b1081ac"
562
+ @node.to_serialized_address(:private).should == "xprv9wTYmMFvAM7JKr2H3xMXcBNzPsqKgffzsM2XnrvKQLJQo2qRftY4uspJCAqjvPypq6Rgvkpoen8MGGnNBxYdeYR5jt6VFdL8cGp2qKnukbW"
563
+ end
564
+
565
+ it "generates a serialized public_key" do
566
+ @node.to_serialized_hex.should == "0488b21e025c1bd648ffffffffeb8291afea1716eb01a1ce7e00d1843072cbd227309df728ba4015f73d5344aa02bcd68031f49f6c921e24ed8c1774221433de23eb309709f571d5449909405cfc"
567
+ @node.to_serialized_address.should == "xpub6ASuArnozifbYL6k9ytXyKKiwufp68PrEZx8bFKvxfqPfqAaDRrKTg8n3Ren8WFSpAbbWLGTimcfYkUB2JbyYFToRBdKT6pEhmpyVe3AqZ9"
568
+ end
569
+ end
541
570
  end
542
571
  end
@@ -1,3 +1,4 @@
1
+ require 'spec_helper'
1
2
  require 'money-tree'
2
3
 
3
4
  describe MoneyTree::PrivateKey do
@@ -62,4 +63,32 @@ describe MoneyTree::PrivateKey do
62
63
  @key.to_base64.should == 'Xq5Tdftfeg6mUFZjY776KDDvRBvcsZGYrfMY+u6G1ks='
63
64
  end
64
65
  end
66
+
67
+ describe "from_base64(base64_key)" do
68
+ it "parses base64 key" do
69
+ @key = MoneyTree::PrivateKey.new(key: "Xq5Tdftfeg6mUFZjY776KDDvRBvcsZGYrfMY+u6G1ks=")
70
+ @key.to_hex.should == "5eae5375fb5f7a0ea650566363befa2830ef441bdcb19198adf318faee86d64b"
71
+ end
72
+
73
+ it "returns the key from base64 encoding" do
74
+ @key.from_base64("Xq5Tdftfeg6mUFZjY776KDDvRBvcsZGYrfMY+u6G1ks=").should == '5eae5375fb5f7a0ea650566363befa2830ef441bdcb19198adf318faee86d64b'
75
+ end
76
+
77
+ it "raises an error on bad encoding" do
78
+ lambda { @key.from_base64("Xq5Tdftfeg6mUFZjY776KD&%#BbadBADrfMY+u6G1ks=") }.should raise_error(MoneyTree::Key::InvalidBase64Format)
79
+ end
80
+ end
81
+
82
+ describe "valid?(eckey)" do
83
+ it "checks for a valid key" do
84
+ @key.valid?.should be_true
85
+ end
86
+ end
87
+
88
+ describe "parse_raw_key" do
89
+ it "returns error if key is not Bignum, hex, base64, or wif formatted" do
90
+ lambda { @key = MoneyTree::PrivateKey.new(key: "Thisisnotakey") }.should raise_error(MoneyTree::Key::KeyFormatNotFound)
91
+
92
+ end
93
+ end
65
94
  end
@@ -1,3 +1,4 @@
1
+ require 'spec_helper'
1
2
  require 'money-tree'
2
3
 
3
4
  describe MoneyTree::PublicKey do
@@ -26,6 +27,12 @@ describe MoneyTree::PublicKey do
26
27
  end
27
28
  end
28
29
 
30
+ describe "to_fingerprint" do
31
+ it "returns a valid fingerprint" do
32
+ @key.to_fingerprint.should == "1fddf42e"
33
+ end
34
+ end
35
+
29
36
  describe "to_address(compressed: false)" do
30
37
  it "has 34 characters" do
31
38
  @key.to_address(compressed: false).length.should == 34
@@ -1,3 +1,4 @@
1
+ require 'spec_helper'
1
2
  require 'money-tree'
2
3
  include MoneyTree::Support
3
4
 
@@ -23,4 +24,10 @@ describe MoneyTree::Support do
23
24
  hmac_sha512_hex("Jefe", "what do ya want for nothing?").should == "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737"
24
25
  end
25
26
  end
27
+
28
+ describe "hex_to_int" do
29
+ it "converts hex to integer" do
30
+ hex_to_int("abcdef0123456789").should == 12379813738877118345
31
+ end
32
+ end
26
33
  end
@@ -0,0 +1 @@
1
+ require 'simplecov'
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.0.1
4
+ version: 0.0.2
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-09-09 00:00:00.000000000 Z
11
+ date: 2013-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: coveralls
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: pry
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -74,6 +102,8 @@ extensions: []
74
102
  extra_rdoc_files: []
75
103
  files:
76
104
  - .gitignore
105
+ - .simplecov
106
+ - .travis.yml
77
107
  - Gemfile
78
108
  - LICENSE.txt
79
109
  - README.md
@@ -91,6 +121,7 @@ files:
91
121
  - spec/lib/money-tree/private_key_spec.rb
92
122
  - spec/lib/money-tree/public_key_spec.rb
93
123
  - spec/lib/money-tree/support_spec.rb
124
+ - spec/spec_helper.rb
94
125
  homepage: ''
95
126
  licenses:
96
127
  - MIT
@@ -121,3 +152,4 @@ test_files:
121
152
  - spec/lib/money-tree/private_key_spec.rb
122
153
  - spec/lib/money-tree/public_key_spec.rb
123
154
  - spec/lib/money-tree/support_spec.rb
155
+ - spec/spec_helper.rb