money-tree 0.10.0 → 0.11.1

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
  SHA256:
3
- metadata.gz: e6b1fd18c035198917d9939d44f6bcbbe4ae69ef168af5de52ab32f5778662b1
4
- data.tar.gz: 31ef2d35cd3d2f10cf40d7fe44787a38857c1c79173494f97d0d296f7828bfba
3
+ metadata.gz: a817c56d0f39bc09f84b1dd02d9e828a9b3fd4d93500d7f6e9cd4ead322c7355
4
+ data.tar.gz: 1e8de14764b5ddf911769e537b99eb4b9f3ce2e91e6dff9ffc2cef923214d156
5
5
  SHA512:
6
- metadata.gz: 03c0b6c55c8f290f10989870d559904a644a68f441cc0ae6498d9cde12bc4853f63babc6ce68d5ad1dfbfb3f6a67b0b4b400053fdddacb62faa9d01adc43f765
7
- data.tar.gz: 8c37b6e7386c60be7ac9797a248039b88ff39b0f46438a07c46aa363b8c8fa30160cdeb0f6d5d54f92fc0b512f437e6a73488cc12e355c25b04fb9dcb7af5d33
6
+ metadata.gz: d2d89e5ffa65f7781a7ff35c830da95614b22e743a24ce5662f4f952dd18685ba9b5a18078fb5bc0a45c1527bb66e32473a5d8453a0a87026e7d5625dbd940d0
7
+ data.tar.gz: 1355fe75f77593dec9c191e9c1d91f4a1f5205fe8e6f01600298311a17c070f25002c8ed0889166125b5879ce9b03675e476f2cf64b5a6f03e19b01886a4506f
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: Spec
3
+
4
+ on:
5
+ pull_request:
6
+ branches:
7
+ - master
8
+ push:
9
+ branches:
10
+ - master
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ${{ matrix.os }}
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ os: [ubuntu-latest, macos-latest]
19
+ ruby: ['2.7', '3.0']
20
+ steps:
21
+ - uses: actions/checkout@v2
22
+ - uses: ruby/setup-ruby@v1
23
+ with:
24
+ ruby-version: ${{ matrix.ruby }}
25
+ bundler-cache: false
26
+ - name: Install Dependencies
27
+ run: |
28
+ bundle install
29
+ - name: Run Tests
30
+ run: |
31
+ bundle exec rspec
32
+ env:
33
+ COVERAGE: true
data/Gemfile CHANGED
@@ -1,4 +1,16 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in money-tree.gemspec
4
- gemspec
3
+ gem "openssl", "~> 3.0"
4
+ gem "bech32", "~> 1.2"
5
+
6
+ group :test, :development do
7
+ gem "bundler", "~> 2.2"
8
+ gem "codecov", "~> 0.6"
9
+ gem "pry", "~> 0.14"
10
+ gem "rake", "~> 13.0"
11
+ gem "rdoc", "~> 6.3"
12
+ gem "rspec", "~> 3.10"
13
+ gem "rufo", "~> 0.13"
14
+ gem "simplecov", "~> 0.21"
15
+ gem "yard", "~> 0.9"
16
+ end
data/README.md CHANGED
@@ -1,13 +1,23 @@
1
- [![Build Status](https://travis-ci.org/GemHQ/money-tree.png)](https://travis-ci.org/GemHQ/money-tree) [![Coverage Status](https://img.shields.io/coveralls/GemHQ/money-tree.svg)](https://coveralls.io/r/GemHQ/money-tree?branch=master) [![Code Climate](https://codeclimate.com/github/GemHQ/money-tree.png)](https://codeclimate.com/github/GemHQ/money-tree) [![Gem Version](https://badge.fury.io/rb/money-tree.png)](http://badge.fury.io/rb/money-tree)
2
1
  # MoneyTree
2
+
3
+ [![GitHub release (latest by date)](https://img.shields.io/github/v/release/GemHQ/money-tree)](https://github.com/GemHQ/money-tree/releases)
4
+ [![Gem](https://img.shields.io/gem/v/money-tree)](https://rubygems.org/gems/money-tree)
5
+ [![Gem](https://img.shields.io/gem/dt/money-tree)](https://rubygems.org/gems/money-tree)
6
+ [![GitHub top language](https://img.shields.io/github/languages/top/GemHQ/money-tree?color=red)](https://github.com/GemHQ/money-tree/pulse)
7
+
8
+ [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/GemHQ/money-tree/Spec)](https://github.com/GemHQ/money-tree/actions)
9
+ [![Code Coverage](https://codecov.io/gh/GemHQ/money-tree/branch/master/graph/badge.svg?token=PF4BL36Z9q)](https://codecov.io/gh/GemHQ/money-tree)
10
+ [![Code Climate](https://codeclimate.com/github/GemHQ/money-tree.png)](https://codeclimate.com/github/GemHQ/money-tree)
11
+ [![GitHub](https://img.shields.io/github/license/GemHQ/money-tree)](LICENSE)
12
+
3
13
  ### RSpec tested. Big Brother removed.
4
14
 
5
15
  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://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki).
6
16
 
7
17
  ___
8
- If you find this helpful, please consider a small Bitcoin donation to 1nj2kie1hATcFbAaD7dEY53QaxNgt4KBp
18
+ If you find this helpful, please consider a small Bitcoin donation to `1nj2kie1hATcFbAaD7dEY53QaxNgt4KBp`.
9
19
 
10
- ![Donate BTC](https://raw.github.com/wink/money-tree/master/donation_btc_qr_code.gif)
20
+ ![Donate BTC](./.github/donation_btc_qr_code.gif)
11
21
  ___
12
22
 
13
23
  ## Why would I want an HD Wallet?
@@ -163,7 +173,7 @@ Because we need multiple pieces of info to reconstruct nodes in a tree, when we'
163
173
  "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
164
174
  ```
165
175
 
166
- In addition to the key and the chain code, this encoding also includes info about the depth and index of the key, along with a fingerprint of its parent key (which I presume is for quickly sorting a big pile of keys into a tree).
176
+ In addition to the key and the chain code, this encoding also includes info about the depth and index of the key, along with a fingerprint of its parent key (which I presume is for quickly sorting a big pile of keys into a tree).
167
177
 
168
178
  These are the addresses that you should use to represent each node in the tree structure, however these are NOT the bitcoin addresses you should pass around for receiving money. These are more for storing inside a wallet file so that you can reconstruct the tree.
169
179
 
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
- require 'rspec/core/rake_task'
2
+ require "rspec/core/rake_task"
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task :default => :spec
@@ -0,0 +1 @@
1
+ cc59abeb70c300eb32c0562dea582de4d26da71cb3fac9937fb3b88fd7092177c98ccbdf6eba7517c3dbc14b33f15e95bf799a02adfec5c12583cb9179c68bb7
@@ -1 +1 @@
1
- ce3c7dc0fe6817aee65f990c7a97f89fd36c94380ac804c7579554d665a934df99d4e72ee9b2e467efcc76799a20c4d1de4c950bbba3512d42260c38a46e54b9
1
+ ce3c7dc0fe6817aee65f990c7a97f89fd36c94380ac804c7579554d665a934df99d4e72ee9b2e467efcc76799a20c4d1de4c950bbba3512d42260c38a46e54b9
@@ -1,16 +1,26 @@
1
1
  module MoneyTree
2
2
  class Address
3
- attr_reader :private_key, :public_key
4
-
3
+ attr_reader :private_key
4
+ attr_reader :public_key
5
+
5
6
  def initialize(opts = {})
6
7
  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
+ @private_key = PrivateKey.new({ key: private_key }.merge(opts))
9
+ @public_key = PublicKey.new(@private_key, opts)
9
10
  end
10
-
11
+
11
12
  def to_s(network: :bitcoin)
12
- public_key.to_s(network: network)
13
+ @public_key.to_s(network: network)
13
14
  end
14
15
 
16
+ def to_bech32(network: :bitcoin)
17
+ hrp = NETWORKS[network][:human_readable_part]
18
+ witprog = @public_key.to_ripemd160
19
+ Support.to_serialized_bech32(hrp, witprog)
20
+ end
21
+
22
+ def to_p2wpkh_p2sh(network: :bitcoin)
23
+ @public_key.to_p2wpkh_p2sh(network: network)
24
+ end
15
25
  end
16
26
  end
@@ -1,12 +1,11 @@
1
1
  # encoding ascii-8bit
2
2
 
3
- require 'openssl'
3
+ require "openssl"
4
4
 
5
5
  module MoneyTree
6
6
  class Key
7
- include OpenSSL
8
7
  include Support
9
- extend Support
8
+
10
9
  class KeyInvalid < StandardError; end
11
10
  class KeyGenerationFailure < StandardError; end
12
11
  class KeyImportFailure < StandardError; end
@@ -14,10 +13,13 @@ module MoneyTree
14
13
  class InvalidWIFFormat < StandardError; end
15
14
  class InvalidBase64Format < StandardError; end
16
15
 
17
- attr_reader :options, :key, :raw_key
16
+ attr_reader :options
17
+ attr_reader :key
18
+ attr_reader :raw_key
19
+
18
20
  attr_accessor :ec_key
19
21
 
20
- GROUP_NAME = 'secp256k1'
22
+ GROUP_NAME = "secp256k1"
21
23
  ORDER = "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".to_i(16)
22
24
 
23
25
  def valid?(eckey = nil)
@@ -35,7 +37,6 @@ module MoneyTree
35
37
  end
36
38
 
37
39
  class PrivateKey < Key
38
-
39
40
  def initialize(opts = {})
40
41
  @options = opts
41
42
  @ec_key = PKey::EC.new GROUP_NAME
@@ -70,14 +71,9 @@ module MoneyTree
70
71
  end
71
72
 
72
73
  def parse_raw_key
73
- result = if raw_key.is_a?(Integer) then from_integer
74
- elsif hex_format? then from_hex
75
- elsif base64_format? then from_base64
76
- elsif compressed_wif_format? then from_wif
77
- elsif uncompressed_wif_format? then from_wif
78
- else
79
- raise KeyFormatNotFound
80
- end
74
+ result = if raw_key.is_a?(Integer) then from_integer elsif hex_format? then from_hex elsif base64_format? then from_base64 elsif compressed_wif_format? then from_wif elsif uncompressed_wif_format? then from_wif else
75
+ raise KeyFormatNotFound
76
+ end
81
77
  result.downcase
82
78
  end
83
79
 
@@ -113,7 +109,7 @@ module MoneyTree
113
109
 
114
110
  def wif_format?(compression)
115
111
  length = compression == :compressed ? 52 : 51
116
- wif_prefixes = MoneyTree::NETWORKS.map {|k, v| v["#{compression}_wif_chars".to_sym]}.flatten
112
+ wif_prefixes = MoneyTree::NETWORKS.map { |k, v| v["#{compression}_wif_chars".to_sym] }.flatten
117
113
  raw_key.length == length && wif_prefixes.include?(raw_key.slice(0))
118
114
  end
119
115
 
@@ -160,7 +156,6 @@ module MoneyTree
160
156
  def to_s(network: :bitcoin)
161
157
  to_wif(network: network)
162
158
  end
163
-
164
159
  end
165
160
 
166
161
  class PublicKey < Key
@@ -209,19 +204,19 @@ module MoneyTree
209
204
  self.compression = opts[:compressed] ? :compressed : :uncompressed
210
205
  bn = BN.new int_to_hex(int), 16
211
206
  @point = PKey::EC::Point.new group, bn
212
- raise KeyInvalid, 'point is not on the curve' unless @point.on_curve?
207
+ raise KeyInvalid, "point is not on the curve" unless @point.on_curve?
213
208
  end
214
209
 
215
210
  def parse_raw_key
216
211
  result = if raw_key.is_a?(Integer)
217
- set_point raw_key
218
- elsif hex_format?
219
- set_point hex_to_int(raw_key), compressed: false
220
- elsif compressed_hex_format?
221
- set_point hex_to_int(raw_key), compressed: true
222
- else
223
- raise KeyFormatNotFound
224
- end
212
+ set_point raw_key
213
+ elsif hex_format?
214
+ set_point hex_to_int(raw_key), compressed: false
215
+ elsif compressed_hex_format?
216
+ set_point hex_to_int(raw_key), compressed: true
217
+ else
218
+ raise KeyFormatNotFound
219
+ end
225
220
  to_hex
226
221
  end
227
222
 
@@ -251,8 +246,20 @@ module MoneyTree
251
246
  address = NETWORKS[network][:address_version] + hash
252
247
  to_serialized_base58 address
253
248
  end
249
+
254
250
  alias :to_s :to_address
255
251
 
252
+ def to_p2wpkh_p2sh(network: :bitcoin)
253
+ prefix = [NETWORKS[network][:p2sh_version]].pack("H*")
254
+ convert_p2wpkh_p2sh(to_hex, prefix)
255
+ end
256
+
257
+ def to_bech32_address(network: :bitcoin)
258
+ hrp = NETWORKS[network][:human_readable_part]
259
+ witprog = to_ripemd160
260
+ to_serialized_bech32(hrp, witprog)
261
+ end
262
+
256
263
  def to_fingerprint
257
264
  hash = to_ripemd160
258
265
  hash.slice(0..7)
@@ -1,33 +1,34 @@
1
1
  module MoneyTree
2
- NETWORKS =
3
- begin
2
+ NETWORKS = begin
4
3
  hsh = Hash.new do |_, key|
5
4
  raise "#{key} is not a valid network!"
6
5
  end.merge(
7
6
  bitcoin: {
8
- address_version: '00',
9
- p2sh_version: '05',
10
- p2sh_char: '3',
11
- privkey_version: '80',
12
- privkey_compression_flag: '01',
7
+ address_version: "00",
8
+ p2sh_version: "05",
9
+ p2sh_char: "3",
10
+ privkey_version: "80",
11
+ privkey_compression_flag: "01",
13
12
  extended_privkey_version: "0488ade4",
14
13
  extended_pubkey_version: "0488b21e",
15
14
  compressed_wif_chars: %w(K L),
16
15
  uncompressed_wif_chars: %w(5),
17
- protocol_version: 70001
16
+ protocol_version: 70001,
17
+ human_readable_part: "bc",
18
18
  },
19
19
  bitcoin_testnet: {
20
- address_version: '6f',
21
- p2sh_version: 'c4',
22
- p2sh_char: '2',
23
- privkey_version: 'ef',
24
- privkey_compression_flag: '01',
20
+ address_version: "6f",
21
+ p2sh_version: "c4",
22
+ p2sh_char: "2",
23
+ privkey_version: "ef",
24
+ privkey_compression_flag: "01",
25
25
  extended_privkey_version: "04358394",
26
26
  extended_pubkey_version: "043587cf",
27
27
  compressed_wif_chars: %w(c),
28
28
  uncompressed_wif_chars: %w(9),
29
- protocol_version: 70001
30
- }
29
+ protocol_version: 70001,
30
+ human_readable_part: "tb",
31
+ },
31
32
  )
32
33
  hsh[:testnet3] = hsh[:bitcoin_testnet]
33
34
  hsh
@@ -2,8 +2,14 @@ module MoneyTree
2
2
  class Node
3
3
  include Support
4
4
  extend Support
5
- attr_reader :private_key, :public_key, :chain_code,
6
- :is_private, :depth, :index, :parent
5
+
6
+ attr_reader :private_key
7
+ attr_reader :public_key
8
+ attr_reader :chain_code
9
+ attr_reader :is_private
10
+ attr_reader :depth
11
+ attr_reader :index
12
+ attr_reader :parent
7
13
 
8
14
  class PublicDerivationFailure < StandardError; end
9
15
  class InvalidKeyForIndex < StandardError; end
@@ -21,26 +27,21 @@ module MoneyTree
21
27
  depth: hex.slice!(0..1).to_i(16),
22
28
  parent_fingerprint: hex.slice!(0..7),
23
29
  index: hex.slice!(0..7).to_i(16),
24
- chain_code: hex.slice!(0..63).to_i(16)
30
+ chain_code: hex.slice!(0..63).to_i(16),
25
31
  }.merge(parse_out_key(hex)))
26
32
  end
27
33
 
28
- def self.from_serialized_address(address)
29
- puts 'Node.from_serialized_address is DEPRECATED. Please use .from_bip32 instead.'
30
- from_bip32(address)
31
- end
32
-
33
34
  def self.parse_out_key(hex)
34
- if hex.slice(0..1) == '00'
35
+ if hex.slice(0..1) == "00"
35
36
  private_key = MoneyTree::PrivateKey.new(key: hex.slice(2..-1))
36
37
  {
37
38
  private_key: private_key,
38
- public_key: MoneyTree::PublicKey.new(private_key)
39
+ public_key: MoneyTree::PublicKey.new(private_key),
39
40
  }
40
41
  elsif %w(02 03).include? hex.slice(0..1)
41
42
  { public_key: MoneyTree::PublicKey.new(hex) }
42
43
  else
43
- raise ImportError, 'Public or private key data does not match version type'
44
+ raise ImportError, "Public or private key data does not match version type"
44
45
  end
45
46
  end
46
47
 
@@ -50,7 +51,7 @@ module MoneyTree
50
51
 
51
52
  def index_hex(i = index)
52
53
  if i < 0
53
- [i].pack('l>').unpack('H*').first
54
+ [i].pack("l>").unpack("H*").first
54
55
  else
55
56
  i.to_s(16).rjust(8, "0")
56
57
  end
@@ -69,16 +70,16 @@ module MoneyTree
69
70
  end
70
71
 
71
72
  def i_as_bytes(i)
72
- [i].pack('N')
73
+ [i].pack("N")
73
74
  end
74
75
 
75
76
  def derive_private_key(i = 0)
76
77
  message = i >= 0x80000000 || i < 0 ? private_derivation_message(i) : public_derivation_message(i)
77
78
  hash = hmac_sha512 hex_to_bytes(chain_code_hex), message
78
79
  left_int = left_from_hash(hash)
79
- raise InvalidKeyForIndex, 'greater than or equal to order' if left_int >= MoneyTree::Key::ORDER # very low probability
80
+ raise InvalidKeyForIndex, "greater than or equal to order" if left_int >= MoneyTree::Key::ORDER # very low probability
80
81
  child_private_key = (left_int + private_key.to_i) % MoneyTree::Key::ORDER
81
- raise InvalidKeyForIndex, 'equal to zero' if child_private_key == 0 # very low probability
82
+ raise InvalidKeyForIndex, "equal to zero" if child_private_key == 0 # very low probability
82
83
  child_chain_code = right_from_hash(hash)
83
84
  return child_private_key, child_chain_code
84
85
  end
@@ -88,10 +89,15 @@ module MoneyTree
88
89
  message = public_derivation_message(i)
89
90
  hash = hmac_sha512 hex_to_bytes(chain_code_hex), message
90
91
  left_int = left_from_hash(hash)
91
- raise InvalidKeyForIndex, 'greater than or equal to order' if left_int >= MoneyTree::Key::ORDER # very low probability
92
+ raise InvalidKeyForIndex, "greater than or equal to order" if left_int >= MoneyTree::Key::ORDER # very low probability
92
93
  factor = BN.new left_int.to_s
93
- child_public_key = public_key.uncompressed.group.generator.mul(factor).add(public_key.uncompressed.point).to_bn.to_i
94
- raise InvalidKeyForIndex, 'at infinity' if child_public_key == 1/0.0 # very low probability
94
+
95
+ gen_point = public_key.uncompressed.group.generator.mul(factor)
96
+
97
+ sum_point_hex = MoneyTree::OpenSSLExtensions.add(gen_point, public_key.uncompressed.point)
98
+ child_public_key = OpenSSL::PKey::EC::Point.new(public_key.group, OpenSSL::BN.new(sum_point_hex, 16)).to_bn.to_i
99
+
100
+ raise InvalidKeyForIndex, "at infinity" if child_public_key == 1 / 0.0 # very low probability
95
101
  child_chain_code = right_from_hash(hash)
96
102
  return child_public_key, child_chain_code
97
103
  end
@@ -120,12 +126,7 @@ module MoneyTree
120
126
  to_serialized_base58 to_serialized_hex(type, network: network)
121
127
  end
122
128
 
123
- def to_serialized_address(type = :public, network: :bitcoin)
124
- puts 'Node.to_serialized_address is DEPRECATED. Please use .to_bip32.'
125
- to_bip32(type, network: network)
126
- end
127
-
128
- def to_identifier(compressed=true)
129
+ def to_identifier(compressed = true)
129
130
  key = compressed ? public_key.compressed : public_key.uncompressed
130
131
  key.to_ripemd160
131
132
  end
@@ -138,15 +139,25 @@ module MoneyTree
138
139
  if @parent_fingerprint
139
140
  @parent_fingerprint
140
141
  else
141
- depth.zero? ? '00000000' : parent.to_fingerprint
142
+ depth.zero? ? "00000000" : parent.to_fingerprint
142
143
  end
143
144
  end
144
145
 
145
- def to_address(compressed=true, network: :bitcoin)
146
+ def to_address(compressed = true, network: :bitcoin)
146
147
  address = NETWORKS[network][:address_version] + to_identifier(compressed)
147
148
  to_serialized_base58 address
148
149
  end
149
150
 
151
+ def to_p2wpkh_p2sh(network: :bitcoin)
152
+ public_key.to_p2wpkh_p2sh(network: network)
153
+ end
154
+
155
+ def to_bech32_address(network: :bitcoin)
156
+ hrp = NETWORKS[network][:human_readable_part]
157
+ witprog = to_identifier
158
+ to_serialized_bech32(hrp, witprog)
159
+ end
160
+
150
161
  def subnode(i = 0, opts = {})
151
162
  if private_key.nil?
152
163
  child_public_key, child_chain_code = derive_public_key(i)
@@ -157,7 +168,7 @@ module MoneyTree
157
168
  child_public_key = MoneyTree::PublicKey.new child_private_key
158
169
  end
159
170
 
160
- MoneyTree::Node.new( depth: depth+1,
171
+ MoneyTree::Node.new(depth: depth + 1,
161
172
  index: i,
162
173
  private_key: private_key.nil? ? nil : child_private_key,
163
174
  public_key: child_public_key,
@@ -177,9 +188,9 @@ module MoneyTree
177
188
  #
178
189
  # You should choose either the p or the negative number convention for private key derivation.
179
190
  def node_for_path(path)
180
- force_public = path[-4..-1] == '.pub'
191
+ force_public = path[-4..-1] == ".pub"
181
192
  path = path[0..-5] if force_public
182
- parts = path.split('/')
193
+ parts = path.split("/")
183
194
  nodes = []
184
195
  parts.each_with_index do |part, depth|
185
196
  if part =~ /m/i
@@ -190,7 +201,7 @@ module MoneyTree
190
201
  nodes << node.subnode(i)
191
202
  end
192
203
  end
193
- if force_public or parts.first == 'M'
204
+ if force_public or parts.first == "M"
194
205
  node = nodes.last
195
206
  node.strip_private_info!
196
207
  node
@@ -204,12 +215,12 @@ module MoneyTree
204
215
  i = path_part.to_i
205
216
 
206
217
  i = if i < 0
207
- i
208
- elsif is_prime
209
- i | 0x80000000
210
- else
211
- i & 0x7fffffff
212
- end
218
+ i
219
+ elsif is_prime
220
+ i | 0x80000000
221
+ else
222
+ i & 0x7fffffff
223
+ end
213
224
  end
214
225
 
215
226
  def strip_private_info!
@@ -246,7 +257,7 @@ module MoneyTree
246
257
  raise SeedGeneration::ImportError unless seed_valid?(@seed_hash)
247
258
  set_seeded_keys
248
259
  elsif opts[:private_key] || opts[:public_key]
249
- raise ImportError, 'chain code required' unless opts[:chain_code]
260
+ raise ImportError, "chain code required" unless opts[:chain_code]
250
261
  @chain_code = opts[:chain_code]
251
262
  if opts[:private_key]
252
263
  @private_key = opts[:private_key]
@@ -256,8 +267,7 @@ module MoneyTree
256
267
  opts[:public_key]
257
268
  else
258
269
  MoneyTree::PublicKey.new(opts[:public_key])
259
- end
260
- end
270
+ end end
261
271
  else
262
272
  generate_seed
263
273
  set_seeded_keys