Skip to content

Commit

Permalink
Merge pull request #7 from hexanova/rustler_init
Browse files Browse the repository at this point in the history
  • Loading branch information
ShreyanJain9 authored Feb 4, 2024
2 parents c10ed89 + 0aacb61 commit 96ba73c
Show file tree
Hide file tree
Showing 13 changed files with 924 additions and 5 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2024 ɴᴏᴠᴀ
Copyright (c) 2024 @hexanova

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
759 changes: 759 additions & 0 deletions lib/hexpds/cid.ex

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion lib/hexpds/didgenerator.ex
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
defmodule Hexpds.DidGenerator do
require Logger
alias :crypto, as: Crypto
alias Hexpds.K256, as: K256
alias Bitcoinex, as: Bitcoin
alias Bitcoin.Secp256k1, as: Secp256k1

def generate_private_key(), do: Crypto.strong_rand_bytes(32)

@spec get_public_key(binary()) :: binary() | {:error, String.t()}
def get_public_key(privkey) when is_binary(privkey) and byte_size(privkey) == 32 do
case ExSecp256k1.create_public_key(privkey) do
case(K256.create_public_key(privkey)) do
{:ok, pubkey} -> pubkey
_ -> raise "Error generating public key"
end
Expand Down
4 changes: 4 additions & 0 deletions lib/hexpds/k256.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
defmodule Hexpds.K256 do
use Rustler, otp_app: :hexpds, crate: "hexpds_k256"
def create_public_key(private_key), do: :erlang.nif_error(:nif_not_loaded)
end
64 changes: 64 additions & 0 deletions lib/hexpds/recordconverter.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
defmodule RecordConverter do
alias Hexpds.CID, as: CID

# Converts a record to a JSON-compatible format.
def record_to_json(record) do
cond do
is_list(record) ->
Enum.map(record, &record_to_json/1)

is_map(record) ->
Enum.reduce(record, %{}, fn {k, v}, acc ->
Map.put(acc, k, record_to_json(v))
end)

# Assuming CID module exists with an encode function
record.__struct__ == CID ->
%{"$link" => CID.encode(record, "base32")}

is_binary(record) ->
raise ArgumentError, "can't represent bytes as JSON"

true ->
record
end
end

# Enumerates CIDs within a record.
def enumerate_record_cids(record) do
cond do
is_list(record) ->
Enum.flat_map(record, &enumerate_record_cids/1)

is_map(record) ->
Enum.flat_map(record, fn {_k, v} -> enumerate_record_cids(v) end)

record.__struct__ == CID ->
[record]

true ->
[]
end
end

# Converts JSON data to a record format.
def json_to_record(data) do
cond do
is_list(data) ->
Enum.map(data, &json_to_record/1)

is_map(data) ->
if Kernel.map_size(data) == 1 and Map.has_key?(data, "$link") do
# Assuming CID module exists with a decode function
CID.decode(data["$link"])
else
Enum.reduce(data, %{}, fn {k, v}, acc ->
Map.put(acc, k, json_to_record(v))
end)
end

true ->
data
end
end
end
3 changes: 3 additions & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ defmodule Hexpds.MixProject do
{:bitcoinex, "~> 0.1.7"},
{:ex_secp256k1, "~> 0.7.2"},
{:multibase, "~> 0.0.1"},
{:ex_multihash, "~> 2.0.0"},
{:rustler, "~> 0.30.0"},
{:toml, "~> 0.7.0"}
]
end
end
6 changes: 3 additions & 3 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
"ex_doc": {:hex, :ex_doc, "0.28.6", "2bbd7a143d3014fc26de9056793e97600ae8978af2ced82c2575f130b7c0d7d7", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "bca1441614654710ba37a0e173079273d619f9160cbcc8cd04e6bd59f1ad0e29"},
"ex_multihash": {:hex, :ex_multihash, "1.0.0", "1833995f1871ad006a2e060b9dec0fc172e0e30796031f0a4cf11fcb5e626124", [:mix], [{:monad, "~> 1.0.4", [hex: :monad, repo: "hexpm", optional: false]}], "hexpm", "d31d4794bfbf7ea8a06e095fb8753466cd8532ad4f4c0c6ea60077c77818fbaa"},
"ex_multihash": {:hex, :ex_multihash, "2.0.0", "7fb36f842a2ec1c6bbba550f28fcd16d3c62981781b9466c9c1975c43d7db43c", [:mix], [], "hexpm", "66a08a86a1ba00d95736c595d7975696e5691308cdf7770c50b0f84a2a1172b0"},
"ex_secp256k1": {:hex, :ex_secp256k1, "0.7.2", "33398c172813b90fab9ab75c12b98d16cfab472c6dcbde832b13c45ce1c01947", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.6", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "f3b1bf56e6992e28b9d86e3bf741a4aca3e641052eb47d13ae4f5f4d4944bdaf"},
"expo": {:hex, :expo, "0.5.1", "249e826a897cac48f591deba863b26c16682b43711dd15ee86b92f25eafd96d9", [:mix], [], "hexpm", "68a4233b0658a3d12ee00d27d37d856b1ba48607e7ce20fd376958d0ba6ce92b"},
"gettext": {:hex, :gettext, "0.24.0", "6f4d90ac5f3111673cbefc4ebee96fe5f37a114861ab8c7b7d5b30a1108ce6d8", [:mix], [{:expo, "~> 0.5.1", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "bdf75cdfcbe9e4622dd18e034b227d77dd17f0f133853a1c73b97b3d6c770e8b"},
Expand All @@ -30,10 +30,10 @@
"nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"},
"parallel_stream": {:hex, :parallel_stream, "1.1.0", "f52f73eb344bc22de335992377413138405796e0d0ad99d995d9977ac29f1ca9", [:mix], [], "hexpm", "684fd19191aedfaf387bbabbeb8ff3c752f0220c8112eb907d797f4592d6e871"},
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
"rustler": {:hex, :rustler, "0.30.0", "cefc49922132b072853fa9b0ca4dc2ffcb452f68fb73b779042b02d545e097fb", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "9ef1abb6a7dda35c47cfc649e6a5a61663af6cf842a55814a554a84607dee389"},
"rustler_precompiled": {:hex, :rustler_precompiled, "0.7.1", "ecadf02cc59a0eccbaed6c1937303a5827fbcf60010c541595e6d3747d3d0f9f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "b9e4657b99a1483ea31502e1d58c464bedebe9028808eda45c3a429af4550c66"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"timex": {:hex, :timex, "3.7.11", "bb95cb4eb1d06e27346325de506bcc6c30f9c6dea40d1ebe390b262fad1862d1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.20", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.1", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "8b9024f7efbabaf9bd7aa04f65cf8dcd7c9818ca5737677c7b76acbc6a94d1aa"},
"tzdata": {:hex, :tzdata, "1.1.1", "20c8043476dfda8504952d00adac41c6eda23912278add38edc140ae0c5bcc46", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a69cec8352eafcd2e198dea28a34113b60fdc6cb57eb5ad65c10292a6ba89787"},
"toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
"varint": {:hex, :varint, "1.4.0", "b7405c8a99db7b95d4341fa9cb15e7c3af6c8dda43e21bbe1c4a9cdff50b6502", [:mix], [], "hexpm", "0fd461901b7120c03467530dff3c58fa3475328fd75ba72c7d3cbf13bce6b0d2"},
"zbase32": {:hex, :zbase32, "2.0.0", "5a61d5ee8f39092d4a243da2a42b5b4339ef226d9b182603f63d5a3f16d192ee", [:mix], [], "hexpm", "798f81895658f9773e1dcf30ba3c118547f482502c5e1e19e72752f9a6f23e44"},
Expand Down
5 changes: 5 additions & 0 deletions native/hexpds_k256/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[target.'cfg(target_os = "macos")']
rustflags = [
"-C", "link-arg=-undefined",
"-C", "link-arg=dynamic_lookup",
]
14 changes: 14 additions & 0 deletions native/hexpds_k256/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
17 changes: 17 additions & 0 deletions native/hexpds_k256/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "hexpds_k256"
version = "0.1.0"
authors = [ "NetWatchInc" ]
edition = "2021"

[lib]
name = "hexpds_k256"
path = "src/lib.rs"
crate-type = ["cdylib"]

[dependencies]
atoms = "2.2.3"
elliptic-curve = "0.13.8"
hex = "0.4.3"
k256 = "0.10.1"
rustler = "0.30.0"
20 changes: 20 additions & 0 deletions native/hexpds_k256/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# NIF for Elixir.Hexpds.k256

## To build the NIF module:

- Your NIF will now build along with your project.

## To load the NIF:

```elixir
defmodule Hexpds.K256 do
use Rustler, otp_app: :hexpds, crate: "hexpds_k256"

# When your NIF is loaded, it will override this function.
def create_public_key(private_key), do: :erlang.nif_error(:nif_not_loaded)
end
```

## Examples

[This](https://github.com/rusterlium/NifIo) is a complete example of a NIF written in Rust.
32 changes: 32 additions & 0 deletions native/hexpds_k256/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use rustler::{Encoder, Env, Term};
use k256::{elliptic_curve::sec1::ToEncodedPoint, SecretKey};
use hex;

mod atoms {
rustler::atoms! {
ok,
error,
}
}

#[rustler::nif]
fn create_public_key(env: Env, private_key: String) -> Term {
let private_key_bytes = match hex::decode(&private_key) {
Ok(bytes) => bytes,
Err(e) => return (atoms::error(), format!("Failed to decode hex string: {}", e)).encode(env),
};

let secret_key = match SecretKey::from_be_bytes(&private_key_bytes) {
Ok(key) => key,
Err(e) => return (atoms::error(), format!("Failed to create secret key: {}", e)).encode(env),
};

let public_key = secret_key.public_key();

let public_key_hex = hex::encode(public_key.to_encoded_point(false).as_bytes());

(atoms::ok(), public_key_hex).encode(env)
}

rustler::init!("Elixir.Hexpds.K256", [create_public_key]);

Binary file added priv/native/libhexpds_k256.so
Binary file not shown.

0 comments on commit 96ba73c

Please sign in to comment.