Giter VIP home page Giter VIP logo

ex_wallet's Introduction

ex_wallet

Build Status

The intent of this repository is described in the following articles:

Prerequisites

Firstly, make sure you have libtool (not the native one), automake and autogen installed.

To do that, use brew:

brew install libtool automake autogen

Then, install and compile all the dependencies and the entire project:

mix do deps.get, deps.compile, compile

Usage

There are a couple of modules you can use.

KeyPair

generate/0

This is the very first function you should use to generate private and public keys.

iex(1)> {public_key, private_key} = ExWallet.KeyPair.generate()
{<<4, 151, 165, 182, 104, 33, 82, 87, 33, 86, 124, 244, 253, 92, 60, 183, 7,
   154, 180, 180, 47, 244, 111, 19, 40, 17, 182, 113, 123, 223, 121, 66, 61,
   163, 59, 23, 46, 179, 183, 212, 84, 206, 146, 133, 78, 224, 18, 82, 2, ...>>,
 <<228, 41, 150, 11, 220, 240, 14, 161, 45, 136, 250, 107, 22, 147, 157, 134,
   144, 53, 111, 189, 59, 72, 238, 135, 208, 136, 238, 60, 106, 160, 64, 138>>}

to_public_key/1

You can use the following function if you have a private key and you want to derive a public one.

iex(2)> ExWallet.KeyPair.to_public_key(private_key)
<<4, 151, 165, 182, 104, 33, 82, 87, 33, 86, 124, 244, 253, 92, 60, 183, 7, 154,
  180, 180, 47, 244, 111, 19, 40, 17, 182, 113, 123, 223, 121, 66, 61, 163, 59,
  23, 46, 179, 183, 212, 84, 206, 146, 133, 78, 224, 18, 82, 2, 70, ...>>

Signature

generate/2

When you have a message to sign, you can do that with your private key.

iex(3)> signature = ExWallet.Signature.generate(private_key, "message")
<<48, 68, 2, 32, 83, 249, 55, 184, 125, 161, 204, 82, 253, 84, 35, 212, 65, 85,
  253, 107, 75, 142, 48, 105, 32, 132, 73, 176, 16, 183, 163, 210, 106, 22, 137,
  167, 2, 32, 118, 205, 247, 213, 157, 88, 249, 140, 83, 85, 180, 122, ...>>

verify/3

Later on, any user will be able to verify it with your public key.

iex(4)> ExWallet.Signature.verify(public_key, signature, "message")
true

Base58

encode

This is a regular Base58 encoding according to its alphabet:

iex(6)> ExWallet.Base58.Encode.call("1")
"r"
iex(7)> ExWallet.Base58.Encode.call("0")
"q"
iex(8)> ExWallet.Base58.Encode.call("a")
"2g"
iex(9)> ExWallet.Base58.Encode.call("k")
"2r"

Address

calculate/1

You are able to calculate a Bitcoin Address using your private key:

iex(10)> ExWallet.Address.calculate(private_key)
"112NcehZWxu8WMTRXYLmKG9xiW1bP6gVyB"

Mnemonic.Advanced

generate/1

You can generate a random mnemonic words for the given entropy length (256 is the default).

iex(11)> ExWallet.Mnemonic.Advanced.generate()
"quote plunge gloom vital rookie kick tiger drastic prize lab brass present play man cinnamon perfect manual deer turkey inspire exit story multiply today"

iex(12)> mnemonic = ExWallet.Mnemonic.Advanced.generate(128)
"actor quantum tunnel fish speak model attack type hint crisp boss zone"

from_entropy/1

However, if you already have some random entropy, you can derive a mnemonic from it:

iex(13)> entropy = "00000000000000000000000000000000"
"00000000000000000000000000000000"
iex(14)> ExWallet.Mnemonic.Advanced.from_entropy(entropy)
<<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"

to_entropy/1

And, once you have your mnemonic words, you can turn them back into the corresponding sequence of bytes:

iex(14)> ExWallet.Mnemonic.Advanced.to_entropy(mnemonic)
<<2, 181, 235, 170, 43, 221, 13, 29, 3, 159, 94, 107, 198, 116, 104, 255>>

Mnemonic.Simple

It has identical interface as Advanced above, and, as you can guess, provides a simpler implementation for the the same functionality.

Seed

generate/2

From the generated mnemonic, you can create a seed which can be later used to derive your keys in HD wallet. To do that, just call:

iex(15)> seed = ExWallet.Seed.generate(mnemonic)
"9941f6b337ae0e6501c43fcae4631c07505212220120e5837a309c4b6e0f1d8a6941bef743602ee61ae09adf72ba94bd31d3b05c5d1f00fdf7d005fdc86f5575"

You can provide an optional passphrase to your seed:

iex(16)> ExWallet.Seed.generate(mnemonic, "password")
"78cf455898d8647080e0b6ba92b39c6bea1f115994c5945bca8dc8dffa2d9a428b2aef255cfeaefd381bdd5fb8aef6dae1793a169abeba481cc9ec9ded664514"

Notice that, even with the same mnemonic, the generated seed is different with the given password.

Extended

master/1

Creates a master private key and a chain code from the given seed.

iex(17)> %{chain_code: chain_code, key: key} = master_key = ExWallet.Extended.master(seed)
%ExWallet.Extended.Private{
  chain_code: <<211, 95, 0, 172, 81, 118, 33, 225, 4, 161, 30, 58, 63, 94, 148,
    207, 233, 247, 216, 42, 155, 95, 136, 65, 219, 158, 48, 71, 187, 75, 232,
    121>>,
  child_number: 0,
  depth: 0,
  fingerprint: <<0, 0, 0, 0>>,
  key: <<113, 135, 206, 171, 176, 125, 48, 119, 134, 96, 129, 16, 126, 146, 98,
    237, 172, 203, 221, 191, 23, 95, 121, 216, 88, 45, 252, 56, 220, 233, 143,
    120>>,
  network: :main,
  version_number: <<4, 136, 173, 228>>
}

serialize/3

Serializes the given key into the Base58 representation.

iex(18)> ExWallet.Extended.serialize(master_key)
"xprv9s21ZrQH143K3NAHGAnTnNnTgQC3Q2A9H45DxCqSBuvvpNtGqLcrwLQjd4omvTpD5pxjjuuuZJ9gHAVYf3gzq7TZEBRtrFpKwQq8PS6BUMh"

iex(19)> public_key = ExWallet.Extended.Private.to_public(master_key)
%ExWallet.Extended.Public{
  chain_code: <<188, 182, 132, 50, 118, 131, 197, 34, 46, 13, 92, 95, 242, 248,
    215, 104, 225, 149, 48, 203, 148, 210, 52, 226, 208, 13, 198, 75, 143, 9,
    29, 143>>,
  child_number: 0,
  depth: 0,
  fingerprint: <<0, 0, 0, 0>>,
  key: <<4, 247, 150, 148, 155, 170, 119, 220, 101, 153, 86, 20, 227, 168, 248,
    43, 64, 59, 11, 94, 219, 157, 20, 157, 101, 31, 50, 79, 111, 94, 173, 51,
    33, 89, 98, 132, 154, 25, 144, 94, 26, 241, 42, 204, 179, ...>>,
  network: :main,
  version_number: <<4, 136, 178, 30>>
}

iex(20)> ExWallet.Extended.serialize(public_key)
"xpub661MyMwAqRbcGRQXcXXrXAEVzprK3Qfa7FSeufon5EQn9D7T6z5puQUbiWrt6DfpUCghfoeMWSzCi9kKK3KRowuyFkPULbkTXHo7DK2MkYY"

Extended.Public

new/6

Creates a new extended public key struct with the given params.

iex(21)> ExWallet.Extended.Public.new(:main, key, chain_code)
%ExWallet.Extended.Public{
  chain_code: <<230, 125, 124, 99, 28, 250, 75, 124, 12, 51, 140, 0, 243, 64,
    111, 227, 169, 73, 152, 111, 175, 136, 252, 11, 126, 58, 46, 143, 146, 72,
    238, 242>>,
  child_number: 0,
  depth: 0,
  fingerprint: <<0, 0, 0, 0>>,
  key: <<133, 188, 193, 183, 218, 206, 89, 125, 148, 36, 247, 59, 231, 52, 107,
    71, 134, 107, 46, 72, 225, 30, 196, 236, 87, 27, 236, 28, 233, 13, 8, 162>>,
  network: :main,
  version_number: <<4, 136, 178, 30>>
}

Extended.Private

new/6

Creates a new extended private key struct with the given params.

iex(22)> ExWallet.Extended.Private.new(:test, key, chain_code)
%ExWallet.Extended.Private{
  chain_code: <<230, 125, 124, 99, 28, 250, 75, 124, 12, 51, 140, 0, 243, 64,
    111, 227, 169, 73, 152, 111, 175, 136, 252, 11, 126, 58, 46, 143, 146, 72,
    238, 242>>,
  child_number: 0,
  depth: 0,
  fingerprint: <<0, 0, 0, 0>>,
  key: <<133, 188, 193, 183, 218, 206, 89, 125, 148, 36, 247, 59, 231, 52, 107,
    71, 134, 107, 46, 72, 225, 30, 196, 236, 87, 27, 236, 28, 233, 13, 8, 162>>,
  network: :test,
  version_number: <<4, 53, 131, 148>>
}

to_public/1

Converts the given private key to the public one.

iex(23)> ExWallet.Extended.Private.to_public(master_key)
%ExWallet.Extended.Public{
  chain_code: <<62, 176, 6, 204, 0, 11, 94, 35, 226, 58, 8, 90, 254, 250, 246,
    78, 10, 142, 239, 51, 121, 32, 52, 180, 247, 81, 228, 255, 142, 206, 136,
    153>>,
  child_number: 0,
  depth: 0,
  fingerprint: <<0, 0, 0, 0>>,
  key: <<4, 125, 212, 138, 26, 23, 188, 118, 35, 158, 3, 16, 49, 129, 62, 87,
    19, 126, 178, 175, 55, 101, 120, 166, 214, 80, 72, 167, 217, 11, 47, 5, 117,
    46, 78, 130, 206, 21, 46, 111, 131, 191, 126, 222, 185, ...>>,
  network: :main,
  version_number: <<4, 136, 178, 30>>
}

Extended.Children

derive/2

Derives public or private child key from the given master key based on the specific chain.

Private to Private Hardened:

iex(23)> ExWallet.Extended.Children.derive(master_key, "m/0'/1")
%ExWallet.Extended.Private{
  chain_code: <<9, 195, 92, 71, 136, 21, 39, 116, 10, 68, 125, 72, 219, 217,
    173, 226, 21, 132, 198, 64, 219, 89, 58, 111, 108, 78, 195, 13, 240, 106,
    161, 84>>,
  child_number: 1,
  depth: 2,
  fingerprint: <<86, 241, 214, 41>>,
  key: <<210, 55, 243, 180, 11, 7, 41, 12, 126, 193, 186, 225, 51, 193, 74, 255,
    88, 44, 30, 77, 117, 36, 223, 72, 160, 233, 194, 92, 106, 131, 168, 40>>,
  network: :main,
  version_number: <<4, 136, 173, 228>>
}

Private to Public Hardened:

iex(24)> ExWallet.Extended.Children.derive(master_key, "M/0'")
%ExWallet.Extended.Public{
  chain_code: <<56, 236, 184, 130, 50, 173, 70, 194, 18, 255, 38, 105, 176, 162,
    77, 93, 194, 215, 84, 161, 108, 241, 107, 203, 87, 145, 57, 209, 181, 119,
    21, 62>>,
  child_number: 2147483648,
  depth: 1,
  fingerprint: <<236, 39, 144, 106>>,
  key: <<4, 112, 255, 93, 55, 8, 241, 185, 89, 51, 71, 173, 187, 222, 172, 218,
    46, 215, 108, 57, 223, 20, 123, 177, 187, 144, 210, 106, 233, 106, 106, 117,
    108, 231, 244, 224, 90, 87, 255, 197, 207, 112, 90, 255, 217, ...>>,
  network: :main,
  version_number: <<4, 136, 178, 30>>
}

Public to Public:

iex(25)> master_key |> ExWallet.Extended.Private.to_public() |> ExWallet.Extended.Children.derive("M/100")
%ExWallet.Extended.Public{
  chain_code: <<59, 227, 171, 8, 162, 89, 114, 70, 199, 64, 150, 220, 184, 44,
    92, 230, 114, 174, 24, 146, 230, 21, 42, 20, 27, 150, 11, 52, 24, 182, 84,
    56>>,
  child_number: 100,
  depth: 1,
  fingerprint: <<236, 39, 144, 106>>,
  key: <<4, 240, 125, 84, 166, 82, 126, 184, 67, 34, 134, 229, 193, 205, 246,
    115, 56, 157, 67, 98, 125, 90, 129, 50, 104, 81, 213, 118, 238, 191, 138,
    206, 45, 106, 39, 238, 137, 130, 61, 150, 160, 248, 43, 57, 61, ...>>,
  network: :main,
  version_number: <<4, 136, 178, 30>>
}

Public to Public Hardened:

iex(26)> master_key |> ExWallet.Extended.to_public_key() |> ExWallet.Extended.Children.derive("m/0'")
** (RuntimeError) Cannot derive Public Hardened Child!
    (ex_wallet) lib/ex_wallet/extended/children.ex:72: ExWallet.Extended.Children.derive_key/2
    (ex_wallet) lib/ex_wallet/extended/children.ex:45: ExWallet.Extended.Children.derive_pathlist/3

ex_wallet's People

Contributors

kamillelonek avatar unnawut avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ex_wallet's Issues

won't build

fails to build for me..

Makefile.am: installing 'build-aux/depcomp'
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking how to print strings... printf
checking for style of include used by make... GNU
checking for gcc... cc
checking whether the C compiler works... no
configure: error: in /home/brad/working/elixir/bitcoin/ex_wallet/deps/libsecp256k1/c_src/secp256k1': configure: error: C compiler cannot create executables See config.log' for more details
ERROR: Command [compile] failed!
** (Mix) Could not compile dependency :libsecp256k1, "/home/brad/.mix/rebar compile skip_deps=true deps_dir="/home/brad/working/elixir/bitcoin/ex_wallet/_build/dev/lib"" command failed. You can recompile this dependency with "mix deps.compile libsecp256k1", update it with "mix deps.update libsecp256k1" or clean it with "mix deps.clean libsecp256k1"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.