money-tree 0.0.1 → 0.0.2

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