Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gemfile.lock #8

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
110dc2d
Merge branch 'release/v0.8.8' into develop
jvergeldedios Dec 4, 2014
e31957f
clear and free EC_GROUP object
Dec 8, 2014
c648b6b
Group is already removed by EC_KEY_free
wink Dec 8, 2014
ae064cd
ensure subnodes are on same bitcoin network
hudon Dec 9, 2014
01aaa3e
support uncompressed addresses
hudon Dec 10, 2014
7498db5
Merge pull request #4 from Hudon/master
jvergeldedios Dec 10, 2014
47f8fa4
Merge pull request #5 from Hudon/hudon-uncompressed-address
jvergeldedios Dec 10, 2014
42dae7c
Merge branch 'master' into develop
Dec 22, 2014
f40772d
nil'd after freeing
Dec 22, 2014
a80b9e3
Update README.md
thedoctor Jan 2, 2015
3606d6f
force chaincode_hex value to avoid int to bytes conversion error
Jan 17, 2015
d841beb
adding test for child derivation using hex_to_bytes
jvergeldedios Jan 21, 2015
67d5216
version bump
jvergeldedios Jan 21, 2015
ef7f57a
Merge branch 'develop'
Jan 31, 2015
ed318fc
Remove the notion of 'network' entirely
semaj Apr 22, 2015
b9ef187
Networks hash throws error by default
semaj Apr 22, 2015
d72b971
.***_serialized_address -> .***_bip32
semaj Apr 24, 2015
8371ac3
support 'testnet3' as network
thedoctor May 14, 2015
e17fad7
trailing whitespace
thedoctor May 14, 2015
67ec6e1
Merge pull request #8 from GemHQ/remove-network-state
jvergeldedios May 19, 2015
286282e
0.9.0 release
jvergeldedios May 19, 2015
7dc0420
update deprecated calls in specs
Feb 26, 2016
4a2b902
make readme use to/from_bip32
Feb 26, 2016
672ef88
Merge pull request #13 from kholbekj/update-deprications-in-specs
thedoctor Feb 26, 2016
a6b382b
Merge pull request #14 from kholbekj/update-readme
thedoctor Feb 26, 2016
70ac456
[Fix] Descend From StandardError Not Exception
etscrivner May 12, 2017
7ae404b
Update key.rb
drush Aug 17, 2017
1538ccf
Support more libssl library names so this will work on heroku
glitch003 Nov 1, 2017
11cb3ce
Merge pull request #23 from glitch003/master
thedoctor Nov 13, 2017
1ef34a9
Merge pull request #20 from drush/patch-1
thedoctor Nov 13, 2017
8314a73
Merge pull request #17 from etscrivner/use-standard-error-rather-than…
thedoctor Nov 13, 2017
d98b642
adds extra libssl location
hstove Mar 14, 2018
6fcfea7
Merge pull request #28 from numaverse/numa
thedoctor May 24, 2018
2686577
0.10.0 Release
thedoctor May 24, 2018
250ec7c
adds Gemfile.lock manifest file
Sep 6, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Remove the notion of 'network' entirely
Money-Tree, in essence is a key-derivation tool.
The keys it derives are not aware of the 'coin',
or 'version'. So there is now no notion of network
held as state on anything.

Money-Tree derives keys, and in the various forms of serialization
you can specify which type of coin (version bytes) you'd like to use.

Although it may seem tedious, it allows trees to be
coin-agnostic until serialization (and theoretically
the usage of the same key-pairs for different coin
addresses.)
  • Loading branch information
semaj committed Apr 22, 2015

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit ed318fc129e87418fa2cd34251a6b0c002b44678
4 changes: 2 additions & 2 deletions lib/money-tree/address.rb
Original file line number Diff line number Diff line change
@@ -8,8 +8,8 @@ def initialize(opts = {})
@public_key = MoneyTree::PublicKey.new(@private_key, opts)
end

def to_s
public_key.to_s
def to_s(network: :bitcoin)
public_key.to_s(network: network)
end

end
37 changes: 8 additions & 29 deletions lib/money-tree/key.rb
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ class KeyFormatNotFound < Exception; end
class InvalidWIFFormat < Exception; end
class InvalidBase64Format < Exception; end

attr_reader :options, :key, :raw_key, :network, :network_key
attr_reader :options, :key, :raw_key
attr_accessor :ec_key

GROUP_NAME = 'secp256k1'
@@ -39,8 +39,6 @@ class PrivateKey < Key
def initialize(opts = {})
@options = opts
@ec_key = PKey::EC.new GROUP_NAME
@network_key = options[:network] || :bitcoin
@network = MoneyTree::NETWORKS[network_key]
if @options[:key]
@raw_key = @options[:key]
@key = parse_raw_key
@@ -94,22 +92,12 @@ def from_hex(hex = raw_key)

def from_wif(wif = raw_key)
compressed = wif.length == 52
parse_network_from_wif(wif, compressed: compressed)
validate_wif(wif)
hex = decode_base58(wif)
last_char = compressed ? -11 : -9
hex.slice(2..last_char)
end

def parse_network_from_wif(wif, opts = {})
networks = MoneyTree::NETWORKS
chars_key = opts[:compressed] ? :compressed_wif_chars : :uncompressed_wif_chars
@network_key = networks.keys.select do |k|
networks[k][chars_key].include?(wif.slice(0))
end.first
@network = networks[network_key]
end

def from_base64(base64_key = raw_key)
raise InvalidBase64Format unless base64_format?(base64_key)
decode_base64(base64_key)
@@ -141,10 +129,9 @@ def to_hex
int_to_hex @ec_key.private_key, 64
end

def to_wif(opts = {})
opts[:compressed] = true unless opts[:compressed] == false
source = network[:privkey_version] + to_hex
source += network[:privkey_compression_flag] if opts[:compressed]
def to_wif(compressed: true, network: :bitcoin)
source = NETWORKS[network][:privkey_version] + to_hex
source += NETWORKS[network][:privkey_compression_flag] if compressed
hash = sha256(source)
hash = sha256(hash)
checksum = hash.slice(0..7)
@@ -154,7 +141,6 @@ def to_wif(opts = {})

def wif_valid?(wif)
hex = decode_base58(wif)
return false unless hex.slice(0..1) == network[:privkey_version]
checksum = hex.chars.to_a.pop(8).join
source = hex.slice(0..-9)
hash = sha256(source)
@@ -171,8 +157,8 @@ def to_base64
encode_base64(to_hex)
end

def to_s
to_wif
def to_s(network: :bitcoin)
to_wif(network: network)
end

end
@@ -183,24 +169,17 @@ class PublicKey < Key
def initialize(p_key, opts = {})
@options = opts
@options[:compressed] = true if @options[:compressed].nil?

if p_key.is_a?(PrivateKey)
@private_key = p_key
@network_key = private_key.network_key
@network = MoneyTree::NETWORKS[network_key]
@point = @private_key.calculate_public_key(@options)
@group = @point.group
@key = @raw_key = to_hex
else
@network_key = @options[:network] || :bitcoin
@network = MoneyTree::NETWORKS[network_key]
@raw_key = p_key
@group = PKey::EC::Group.new GROUP_NAME
@key = parse_raw_key
end

@options[:network] = @network_key # remember for deep clone

raise ArgumentError, "Must initialize with a MoneyTree::PrivateKey or a public key value" if @key.nil?
end

@@ -267,9 +246,9 @@ def to_ripemd160
ripemd160 hash
end

def to_address
def to_address(network: :bitcoin)
hash = to_ripemd160
address = network[:address_version] + hash
address = NETWORKS[network][:address_version] + hash
to_serialized_base58 address
end
alias :to_s :to_address
80 changes: 33 additions & 47 deletions lib/money-tree/node.rb
Original file line number Diff line number Diff line change
@@ -3,57 +3,48 @@ class Node
include Support
extend Support
attr_reader :private_key, :public_key, :chain_code,
:is_private, :depth, :index, :parent, :network, :network_key
:is_private, :depth, :index, :parent

class PublicDerivationFailure < Exception; end
class InvalidKeyForIndex < Exception; end
class ImportError < Exception; end
class PrivatePublicMismatch < Exception; end

def initialize(opts = {})
@network_key = opts.delete(:network) || :bitcoin
@network = MoneyTree::NETWORKS[network_key]
opts.each { |k, v| instance_variable_set "@#{k}", v }
end
def self.from_serialized_address(address)

def self.from_wif(address, has_version: true)
hex = from_serialized_base58 address
version = from_version_hex hex.slice!(0..7)
hex.slice!(0..7) if has_version
self.new({
depth: hex.slice!(0..1).to_i(16),
parent_fingerprint: hex.slice!(0..7),
index: hex.slice!(0..7).to_i(16),
chain_code: hex.slice!(0..63).to_i(16)
}.merge(key_options(hex, version)))
}.merge(parse_out_key(hex)))
end

def self.key_options(hex, version)
k_opts = { network: version[:network] }
if version[:private_key] && hex.slice(0..1) == '00'
private_key = MoneyTree::PrivateKey.new({ key: hex.slice(2..-1) }.merge(k_opts))
k_opts.merge private_key: private_key, public_key: MoneyTree::PublicKey.new(private_key)

def self.from_serialized_address(address)
puts "Node.from_serialized_address is DEPRECATED.\n
Please use .from_wif instead."
from_wif(address)
end

def self.parse_out_key(hex)
if hex.slice(0..1) == '00'
private_key = MoneyTree::PrivateKey.new(key: hex.slice(2..-1))
{
private_key: private_key,
public_key: MoneyTree::PublicKey.new(private_key)
}
elsif %w(02 03).include? hex.slice(0..1)
k_opts.merge public_key: MoneyTree::PublicKey.new(hex, k_opts)
{ public_key: MoneyTree::PublicKey.new(hex) }
else
raise ImportError, 'Public or private key data does not match version type'
end
end

def self.from_version_hex(hex)
case hex
when MoneyTree::NETWORKS[:bitcoin][:extended_privkey_version]
{ private_key: true, network: :bitcoin }
when MoneyTree::NETWORKS[:bitcoin][:extended_pubkey_version]
{ private_key: false, network: :bitcoin }
when MoneyTree::NETWORKS[:bitcoin_testnet][:extended_privkey_version]
{ private_key: true, network: :bitcoin_testnet }
when MoneyTree::NETWORKS[:bitcoin_testnet][:extended_pubkey_version]
{ private_key: false, network: :bitcoin_testnet }
else
raise ImportError, 'invalid version bytes'
end
end


def is_private?
index >= 0x80000000 || index < 0
end
@@ -114,20 +105,20 @@ def right_from_hash(hash)
bytes_to_int hash.bytes.to_a[32..-1]
end

def to_serialized_hex(type = :public)
def to_serialized_hex(type = :public, network: :bitcoin)
raise PrivatePublicMismatch if type.to_sym == :private && private_key.nil?
version_key = type.to_sym == :private ? :extended_privkey_version : :extended_pubkey_version
hex = network[version_key] # version (4 bytes)
hex = NETWORKS[network][version_key] # version (4 bytes)
hex += depth_hex(depth) # depth (1 byte)
hex += parent_fingerprint # fingerprint of key (4 bytes)
hex += index_hex(index) # child number i (4 bytes)
hex += chain_code_hex
hex += type.to_sym == :private ? "00#{private_key.to_hex}" : public_key.compressed.to_hex
end

def to_serialized_address(type = :public)
def to_serialized_address(type = :public, network: :bitcoin)
raise PrivatePublicMismatch if type.to_sym == :private && private_key.nil?
to_serialized_base58 to_serialized_hex(type)
to_serialized_base58 to_serialized_hex(type, network: network)
end

def to_identifier(compressed=true)
@@ -147,28 +138,27 @@ def parent_fingerprint
end
end

def to_address(compressed=true)
address = network[:address_version] + to_identifier(compressed)
def to_address(compressed=true, network: :bitcoin)
address = NETWORKS[network][:address_version] + to_identifier(compressed)
to_serialized_base58 address
end

def subnode(i = 0, opts = {})
if private_key.nil?
child_public_key, child_chain_code = derive_public_key(i)
child_public_key = MoneyTree::PublicKey.new child_public_key, network: network_key
child_public_key = MoneyTree::PublicKey.new child_public_key
else
child_private_key, child_chain_code = derive_private_key(i)
child_private_key = MoneyTree::PrivateKey.new key: child_private_key, network: network_key
child_private_key = MoneyTree::PrivateKey.new key: child_private_key
child_public_key = MoneyTree::PublicKey.new child_private_key
end

MoneyTree::Node.new network: network_key,
depth: depth+1,
MoneyTree::Node.new( depth: depth+1,
index: i,
private_key: private_key.nil? ? nil : child_private_key,
public_key: child_public_key,
chain_code: child_chain_code,
parent: self
parent: self)
end

# path: a path of subkeys denoted by numbers and slashes. Use
@@ -246,8 +236,6 @@ def initialize(opts = {})
@depth = 0
@index = 0
opts[:seed] = [opts[:seed_hex]].pack("H*") if opts[:seed_hex]
@network_key = opts[:network] || :bitcoin
@network = MoneyTree::NETWORKS[network_key]
if opts[:seed]
@seed = opts[:seed]
@seed_hash = generate_seed_hash(@seed)
@@ -258,14 +246,12 @@ def initialize(opts = {})
@chain_code = opts[:chain_code]
if opts[:private_key]
@private_key = opts[:private_key]
@network_key = @private_key.network_key
@network = MoneyTree::NETWORKS[network_key]
@public_key = MoneyTree::PublicKey.new @private_key
else opts[:public_key]
@public_key = if opts[:public_key].is_a?(MoneyTree::PublicKey)
opts[:public_key]
else
MoneyTree::PublicKey.new(opts[:public_key], network: network_key)
MoneyTree::PublicKey.new(opts[:public_key])
end
end
else
@@ -295,7 +281,7 @@ def seed_valid?(seed_hash)
end

def set_seeded_keys
@private_key = MoneyTree::PrivateKey.new key: left_from_hash(seed_hash), network: network_key
@private_key = MoneyTree::PrivateKey.new key: left_from_hash(seed_hash)
@chain_code = right_from_hash(seed_hash)
@public_key = MoneyTree::PublicKey.new @private_key
end
2 changes: 1 addition & 1 deletion spec/lib/money-tree/address_spec.rb
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@
end

it "returns a testnet address" do
expect(%w(m n)).to include(@address.to_s[0])
expect(%w(m n)).to include(@address.to_s(network: :bitcoin_testnet)[0])
end
end
end
28 changes: 14 additions & 14 deletions spec/lib/money-tree/node_spec.rb
Original file line number Diff line number Diff line change
@@ -24,49 +24,49 @@
end

it "generates testnet address" do
expect(%w(m n)).to include(@master.to_address[0])
expect(%w(m n)).to include(@master.to_address(network: :bitcoin_testnet)[0])
end

it "generates testnet compressed wif" do
expect(@master.private_key.to_wif[0]).to eql('c')
expect(@master.private_key.to_wif(network: :bitcoin_testnet)[0]).to eql('c')
end

it "generates testnet uncompressed wif" do
expect(@master.private_key.to_wif(compressed: false)[0]).to eql('9')
expect(@master.private_key.to_wif(compressed: false, network: :bitcoin_testnet)[0]).to eql('9')
end

it "generates testnet serialized private address" do
expect(@master.to_serialized_address(:private).slice(0, 4)).to eql("tprv")
expect(@master.to_serialized_address(:private, network: :bitcoin_testnet).slice(0, 4)).to eql("tprv")
end

it "generates testnet serialized public address" do
expect(@master.to_serialized_address.slice(0, 4)).to eql("tpub")
expect(@master.to_serialized_address(network: :bitcoin_testnet).slice(0, 4)).to eql("tpub")
end

it "imports from testnet serialized private address" do
node = MoneyTree::Node.from_serialized_address 'tprv8ZgxMBicQKsPcuN7bfUZqq78UEYapr3Tzmc9NcDXw8BnBJ47dZYr6SusnfYj7vbAYP9CP8ZiD5aVBTUo1yU5QP56mepKVvuEbu8KZQXMKNE'
expect(node.to_serialized_address(:private)).to eql('tprv8ZgxMBicQKsPcuN7bfUZqq78UEYapr3Tzmc9NcDXw8BnBJ47dZYr6SusnfYj7vbAYP9CP8ZiD5aVBTUo1yU5QP56mepKVvuEbu8KZQXMKNE')
expect(node.to_serialized_address(:private, network: :bitcoin_testnet)).to eql('tprv8ZgxMBicQKsPcuN7bfUZqq78UEYapr3Tzmc9NcDXw8BnBJ47dZYr6SusnfYj7vbAYP9CP8ZiD5aVBTUo1yU5QP56mepKVvuEbu8KZQXMKNE')
end

it "imports from testnet serialized public address" do
node = MoneyTree::Node.from_serialized_address 'tpubD6NzVbkrYhZ4YA8aUE9bBZTSyHJibBqwDny5urfwDdJc4W8od3y3Ebzy6CqsYn9CCC5P5VQ7CeZYpnT1kX3RPVPysU2rFRvYSj8BCoYYNqT'
expect(%w(m n)).to include(node.public_key.to_s[0])
expect(node.to_serialized_address).to eql('tpubD6NzVbkrYhZ4YA8aUE9bBZTSyHJibBqwDny5urfwDdJc4W8od3y3Ebzy6CqsYn9CCC5P5VQ7CeZYpnT1kX3RPVPysU2rFRvYSj8BCoYYNqT')
expect(%w(m n)).to include(node.public_key.to_s(network: :bitcoin_testnet)[0])
expect(node.to_serialized_address(network: :bitcoin_testnet)).to eql('tpubD6NzVbkrYhZ4YA8aUE9bBZTSyHJibBqwDny5urfwDdJc4W8od3y3Ebzy6CqsYn9CCC5P5VQ7CeZYpnT1kX3RPVPysU2rFRvYSj8BCoYYNqT')
end

it "generates testnet subnodes from serialized private address" do
node = MoneyTree::Node.from_serialized_address 'tprv8ZgxMBicQKsPcuN7bfUZqq78UEYapr3Tzmc9NcDXw8BnBJ47dZYr6SusnfYj7vbAYP9CP8ZiD5aVBTUo1yU5QP56mepKVvuEbu8KZQXMKNE'
subnode = node.node_for_path('1/1/1')
expect(%w(m n)).to include(subnode.public_key.to_s[0])
expect(subnode.to_serialized_address(:private).slice(0,4)).to eql('tprv')
expect(subnode.to_serialized_address.slice(0,4)).to eql('tpub')
expect(%w(m n)).to include(subnode.public_key.to_s(network: :bitcoin_testnet)[0])
expect(subnode.to_serialized_address(:private, network: :bitcoin_testnet).slice(0,4)).to eql('tprv')
expect(subnode.to_serialized_address(network: :bitcoin_testnet).slice(0,4)).to eql('tpub')
end

it "generates testnet subnodes from serialized public address" do
node = MoneyTree::Node.from_serialized_address 'tpubD6NzVbkrYhZ4YA8aUE9bBZTSyHJibBqwDny5urfwDdJc4W8od3y3Ebzy6CqsYn9CCC5P5VQ7CeZYpnT1kX3RPVPysU2rFRvYSj8BCoYYNqT'
subnode = node.node_for_path('1/1/1')
expect(%w(m n)).to include(subnode.public_key.to_s[0])
expect(subnode.to_serialized_address.slice(0,4)).to eql('tpub')
expect(%w(m n)).to include(subnode.public_key.to_s(network: :bitcoin_testnet)[0])
expect(subnode.to_serialized_address(network: :bitcoin_testnet).slice(0,4)).to eql('tpub')
end
end

@@ -799,7 +799,7 @@
it "correctly derives from a node with a chain code represented in 31 bytes" do
@node = MoneyTree::Node.from_serialized_address "tpubD6NzVbkrYhZ4WM42MZZmUZ7LjxyjBf5bGjEeLf9nJnMZqocGJWu94drvpqWsE9jE7k3h22v6gjpPGnqgBrqwGsRYwDXVRfQ2M9dfHbXP5zA"
@subnode = @node.node_for_path('m/1')
expect(@subnode.to_serialized_address).to eql("tpubDA7bCxb3Nrcz2ChXyPqXxbG4q5oiAZUHR7wD3LAiXukuxmT65weWw84XYmjhkJTkJEM6LhNWioWTpKEkQp7j2fgVccj3PPc271xHDeMsaTY")
expect(@subnode.to_serialized_address(network: :bitcoin_testnet)).to eql("tpubDA7bCxb3Nrcz2ChXyPqXxbG4q5oiAZUHR7wD3LAiXukuxmT65weWw84XYmjhkJTkJEM6LhNWioWTpKEkQp7j2fgVccj3PPc271xHDeMsaTY")
end
end
end
4 changes: 2 additions & 2 deletions spec/lib/money-tree/private_key_spec.rb
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@
end

it "is valid" do
expect(@key.to_wif(compressed: false)).to eql('5JXz5ZyFk31oHVTQxqce7yitCmTAPxBqeGQ4b7H3Aj3L45wUhoa' )
expect(@key.to_wif(compressed: false)).to eql('5JXz5ZyFk31oHVTQxqce7yitCmTAPxBqeGQ4b7H3Aj3L45wUhoa')
end
end

@@ -104,7 +104,7 @@

describe "to_wif" do
it "returns same wif" do
expect(@key.to_wif).to eql('cRhes8SBnsF6WizphaRKQKZZfDniDa9Bxcw31yKeEC1KDExhxFgD')
expect(@key.to_wif(network: :bitcoin_testnet)).to eql('cRhes8SBnsF6WizphaRKQKZZfDniDa9Bxcw31yKeEC1KDExhxFgD')
end
end
end
Loading