From e6e6b94b5b1178418ccce49f0b4d9f6043687618 Mon Sep 17 00:00:00 2001 From: John Newby Date: Mon, 5 Aug 2019 15:05:14 +0200 Subject: [PATCH] NIF goodness! --- Cargo.toml | 1 + src/lib.rs | 24 ++++++++---------------- src/nifecrecover.erl | 39 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 562c9a5..f60a5d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +base64 = "0.10.1" c_vec = "1.3.3" ethcore-builtin = { path = "../parity-ethereum/ethcore/builtin" } lazy_static = "1.3.0" diff --git a/src/lib.rs b/src/lib.rs index 0d297de..8460313 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,8 @@ use crate::ethcore_builtin::Implementation; use c_vec::{CVec}; use parity_bytes::BytesRef; use rustler::*; +use rustler::types::atom::ok; +use std::io::Write; use std::ptr::copy_nonoverlapping; const INPUT_LENGTH: usize = 512; @@ -27,37 +29,27 @@ mod atoms { rustler_export_nifs!( "nifecrecover", [ - ("ecrecover", 2, nif_ecrecover), + ("ecrecover", 1, nif_ecrecover), ], Some(on_load) ); -struct EcrecoverResource { } #[no_mangle] fn on_load(env: Env, _load_info: Term) -> bool { - println!("on_load"); - rustler::resource_struct_init!(EcrecoverResource, env); true } -pub fn nif_ecrecover<'a>(env: Env<'a>, args: &[Term<'a>]) -> Result, Error> { - let input: String = args[0].decode()?; - let mut output: String = args[1].decode()?; +pub fn nif_ecrecover<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult> { + let input: Binary = args[0].decode()?; let mut byte_ref = Vec::new(); let ecrecover = EcRecover { }; - let result = match ecrecover.execute(input.as_bytes(), + let result = match ecrecover.execute(input.as_slice(), &mut BytesRef::Flexible(&mut byte_ref)) { - Ok(x) => x, + Ok(_) => (), Err(e) => return Err(rustler::Error::Atom("ecrecover failed")), }; - match String::from_utf8(byte_ref) { - Ok(x) => { - output.push_str(&x); - Ok((atoms::ok(), true).encode(env)) - }, - Err(x) => Err(rustler::Error::Atom("Invalid UTF-8")), - } + Ok(byte_ref.as_slice().encode(env)) } /** diff --git a/src/nifecrecover.erl b/src/nifecrecover.erl index c2444ad..5b3765d 100644 --- a/src/nifecrecover.erl +++ b/src/nifecrecover.erl @@ -1,17 +1,29 @@ -module(nifecrecover). %% API --export([ecrecover/2]). +-export([ecrecover/1, + ecrecover_hex/1, + bin_to_hexstr/1, + hexstr_to_bin/1, + time_taken_to_execute/1 +]). %% Native library support -export([load/0]). -on_load(load/0). -ecrecover(_Input, _Output) -> +ecrecover(_Input) -> not_loaded(?LINE). +ecrecover_hex(Input) -> + Decoded = hexstr_to_bin(Input), + {ok, PubKey} = ecrecover(Decoded), + Encoded = bin_to_hexstr(PubKey), + Encoded. + + load() -> - ok = erlang:load_nif("/home/newby/projects/ethereum/ecrecover/target/debug/libecrecover", 0). + ok = erlang:load_nif("/home/newby/projects/ethereum/ecrecover/target/release/libecrecover", 0). not_loaded(Line) -> erlang:nif_error({error, {not_loaded, [{module, ?MODULE}, {line, Line}]}}). @@ -25,3 +37,24 @@ priv()-> Path -> Path end. + +%% +time_taken_to_execute(F) -> Start = os:timestamp(), + F(), + io:format("total time taken ~f seconds~n", [timer:now_diff(os:timestamp(), Start) / 1000000]). + +%% +bin_to_hexstr(Bin) -> + lists:flatten([io_lib:format("~2.16.0B", [X]) || + X <- binary_to_list(Bin)]). + +hexstr_to_bin(S) -> + hexstr_to_bin(S, []). +hexstr_to_bin([], Acc) -> + list_to_binary(lists:reverse(Acc)); +hexstr_to_bin([X,Y|T], Acc) -> + {ok, [V], []} = io_lib:fread("~16u", [X,Y]), + hexstr_to_bin(T, [V | Acc]); +hexstr_to_bin([X|T], Acc) -> + {ok, [V], []} = io_lib:fread("~16u", lists:flatten([X,"0"])), + hexstr_to_bin(T, [V | Acc]).