Skip to content

Commit

Permalink
initial library config
Browse files Browse the repository at this point in the history
  • Loading branch information
izelnakri committed Aug 29, 2017
1 parent c34c67e commit 84da5d8
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 7 deletions.
32 changes: 28 additions & 4 deletions lib/eth.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require IEx
# elliptic curve cryptography library for Ethereum
# elliptic curve cryptography library for signing transactions in Ethereum
defmodule ETH do
@moduledoc """
Documentation for Eth.
Expand All @@ -15,13 +15,17 @@ defmodule ETH do
"""

def get_private_key do
:crypto.strong_rand_bytes(32)
end

def private_key_to_address(<< private_key :: binary-size(32) >>) do
private_key
|> private_key_to_public_key()
|> get_public_key()
|> public_key_to_address()
end

def private_key_to_public_key(<< private_key :: binary-size(32) >>) do
def get_public_key(<< private_key :: binary-size(32) >>) do
{public_key, ^private_key} = :crypto.generate_key(:ecdh, :secp256k1, private_key)
public_key
end
Expand All @@ -31,6 +35,24 @@ defmodule ETH do
address
end

def sign_transaction(
source_wallet, value, target_wallet, options \\ [gas_price: 100, gas_limit: 1000, data: "", chain_id: 3]
) do
gas_price = options.gas_price |> Hexate.encode
gas_limit = options.gas_limit |> Hexate.encode
data = data |> Hexate.encode

Ethereumex.HttpClient.eth_get_transaction_count([first[:eth_address]]) |> elem(1) |> Map.get("result")

# NOTE: calc nonce
%{
to: target_wallet[:eth_address], value: Hexate.encode(value), gas_price: gas_price,
gas_limit: gas_limit, data: data, chain_id: 3
}
# get nonce and make a transaction map -> sign_transaction -> send it to client
end


def sign_transaction(transaction, private_key) do # must have chain_id
hash = hash_transaction(transaction)
decoded_private_key = Base.decode16!(private_key, case: :lower)
Expand All @@ -49,7 +71,8 @@ defmodule ETH do
def adjust_v_for_chain_id(transaction) do
if transaction.chain_id > 0 do
current_v_bytes = Base.decode16!(transaction.v, case: :lower) |> :binary.decode_unsigned
transaction |> Map.merge(%{v: encode16(<< current_v_bytes + (transaction.chain_id * 2 + 8) >>) })
target_v_bytes = current_v_bytes + (transaction.chain_id * 2 + 8)
transaction |> Map.merge(%{v: encode16(<< target_v_bytes >>) })
else
transaction
end
Expand All @@ -62,6 +85,7 @@ defmodule ETH do

# must have [nonce, gasPrice, gasLimit, to, value, data] # and chainId inside the transaction?
def hash_transaction(transaction) do
# NOTE: if transaction is decoded no need to encode
# EIP155 spec:
# when computing the hash of a transaction for purposes of signing or recovering,
# instead of hashing only the first six elements (ie. nonce, gasprice, startgas, to, value, data),
Expand Down
32 changes: 32 additions & 0 deletions lib/eth/wallet.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule ETH.Wallet do
def create(private_key \\ :crypto.strong_rand_bytes(32)) do # pattern match on the base16 version as well
{public_key, _} = :crypto.generate_key(:ecdh, :secp256k1, private_key)
<< 4 :: size(8), key :: binary-size(64) >> = public_key
<< _ :: binary-size(12), address :: binary-size(20) >> = keccak256(key)

%{private_key: Base.encode16(private_key), public_key: Base.encode16(public_key),
eth_address: "0x#{Base.encode16(address)}"}
end

# def get_public_key(<< private_key :: binary-size(32) >>) do
# {public_key, ^private_key} = :crypto.generate_key(:ecdh, :secp256k1, private_key)
# public_key
# end
#
# def private_key_to_address(<< private_key :: binary-size(32) >>) do
# private_key
# |> get_public_key()
# |> public_key_to_address()
# end
#
# def public_key_to_address(<< 4 :: size(8), key :: binary-size(64) >>) do
# << _ :: binary-size(12), address :: binary-size(20) >> = keccak256(key)
# address
# end

def balance do
# Ethereumex
end

defp keccak256(data), do: :keccakf1600.hash(:sha3_256, data)
end
25 changes: 23 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ defmodule Eth.Mixfile do
version: "0.1.0",
elixir: "~> 1.5",
start_permanent: Mix.env == :prod,
deps: deps()
deps: deps(),
package: package
]
end

Expand All @@ -24,7 +25,27 @@ defmodule Eth.Mixfile do
{:libsecp256k1, [github: "mbrix/libsecp256k1", manager: :rebar]},
{:keccakf1600, git: "https://github.com/jur0/erlang-keccakf1600", branch: "original-keccak"},
{:ex_rlp, "~> 0.2.1"},
{:hexate, "~> 0.6.1"}
{:hexate, "~> 0.6.1"},
{:ethereumex, "~> 0.1.0"}
]
end

defp description do
"""
Ethereum utilities for Elixir.
"""
end

def package do
[
name: :eth,
files: ["lib", "mix.exs", "README*", "LICENSE*"],
maintainers: ["Izel Nakri"],
licenses: ["MIT License"],
links: %{
"GitHub" => "https://github.com/izelnakri/eth",
"Docs" => "https://hexdocs.pm/eth/ETH.html"
}
]
end
end
2 changes: 1 addition & 1 deletion test/eth_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ defmodule ETHTest do
assert ETH.secp256k1_signature(hash, private_key)[:signature] |> Base.encode16(case: :lower) == target_signature
end

test "hash_transaction\2 works" do
test "hash_transaction/2 works" do
result = ETH.hash_transaction(@first_example_transaction) |> Base.encode16(case: :lower)
target_digest = "df2a7cb6d05278504959987a144c116dbd11cbdc50d6482c5bae84a7f41e2113"
assert result == target_digest
Expand Down

0 comments on commit 84da5d8

Please sign in to comment.