Improve API to be more Erlang-ish

This commit is contained in:
Tino Breddin 2019-08-15 09:28:29 +02:00
parent f69e1947c7
commit 231415aa99
8 changed files with 72 additions and 62 deletions

3
.gitignore vendored
View File

@ -2,3 +2,6 @@
**/*.rs.bk
Cargo.lock
**/*~
/parity-ethereum
/_build
/ebin

View File

@ -9,7 +9,7 @@ edition = "2018"
[dependencies]
base64 = "0.10.1"
c_vec = "1.3.3"
ethcore-builtin = { path = "../parity-ethereum/ethcore/builtin" }
ethcore-builtin = { path = "parity-ethereum/ethcore/builtin" }
lazy_static = "1.3.0"
libc = "0.2.60"
parity-bytes = "0.1.0"

View File

@ -1,8 +1,11 @@
all: priv/ecrecover.so
priv/ecrecover.so: src/lib.rs
priv/ecrecover.so: src/lib.rs parity-ethereum/
cargo build --release
cp target/release/libecrecover.so priv/ecrecover.so
clean:
rm -f src/ecrecover.so target/release/libecrecover.so
parity-ethereum/:
git clone https://github.com/johnsnewby/parity-ethereum.git

View File

@ -1,10 +1,4 @@
{erl_opts, [{parse_transform, lager_transform}, {lager_extra_sinks, [ecrecover]}]}.
{deps, [
{lager, {git, "https://github.com/erlang-lager/lager.git",
{ref, "69b4ada"}}}, % tag: 3.6.7
%% ecrecover prebuilt libraries
{ecrecoverprebuilt,
{ecrecoverprebuilt_app_with_priv_from_git,
@ -17,8 +11,6 @@
{ref, "f982da061c5f2e0ffbf1ad58ac25b3b32e182b01"}}}
]}.
%%{profiles, [{test, [{deps, [{meck, "0.8.12"}]}]}]}.
{dialyzer, [{warnings, [unknown]},
{plt_apps, all_deps},
{base_plt_apps, [erts, kernel, stdlib, crypto]}

5
rebar.lock Normal file
View File

@ -0,0 +1,5 @@
[{<<"ecrecoverprebuilt">>,
{ecrecoverprebuilt_app_with_priv_from_git,
{git,"https://github.com/aeternity/ecrecover-prebuilt.git",
{ref,"93569ca272e59682366cdf3c7ed2ee991540701a"}}},
0}].

View File

@ -1,44 +1,41 @@
-module(ecrecover).
%% API
-export([ecrecover/1,
ecrecover_hex/1,
bin_to_hexstr/1,
hexstr_to_bin/1,
time_taken_to_execute/1
]).
-export([recover/2]).
%% Native library support
%% NIF
-export([load/0]).
-on_load(load/0).
ecrecover(_Input) ->
not_loaded(?LINE).
ecrecover_hex(Input) ->
Decoded = hexstr_to_bin(Input),
{ok, PubKey} = ecrecover(Decoded),
Encoded = bin_to_hexstr(PubKey),
Encoded.
%%=============================================================================
%% NIF API
load() ->
Dir = case code:priv_dir(ecrecoverprebuilt) of
{error, bad_name} ->
filename:join(
filename:dirname(
filename:dirname(
code:which(?MODULE))), "priv");
D -> D
end,
SoName = filename:join(Dir, atom_to_list(?MODULE)),
SoName = filename:join(priv(), atom_to_list(?MODULE)),
ok = erlang:load_nif(SoName, 0).
not_loaded(Line) ->
erlang:nif_error({error, {not_loaded, [{module, ?MODULE}, {line, Line}]}}).
%%=============================================================================
%% External API
recover(<<_:32/binary>> = Hash, <<_:65/binary>> = Sig) ->
Input = <<Hash/binary, 0:(8*31), Sig/binary>>,
case recover_(Input) of
{ok, []} ->
<<0:256>>;
{ok, Res} ->
erlang:list_to_binary(Res);
_Err ->
<<0:256>>
end.
%%=============================================================================
%% Internal Functions
priv()->
case code:priv_dir(?MODULE) of
case code:priv_dir(ecrecoverprebuilt) of
{error, _} ->
EbinDir = filename:dirname(code:which(?MODULE)),
AppPath = filename:dirname(EbinDir),
@ -47,23 +44,5 @@ priv()->
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]).
recover_(_Input) ->
not_loaded(?LINE).

28
src/ecrecover_util.erl Normal file
View File

@ -0,0 +1,28 @@
-module(ecrecover_util).
-export([ recover_from_hex/1
, bin_to_hex/1
, hex_to_bin/1
]).
%%=============================================================================
%% External API
recover_from_hex(Input) ->
<<Hash:32/binary, _:31/binary, Sig:65/binary>> = hex_to_bin(Input),
PubKey = ecrecover:recover(Hash, Sig),
bin_to_hex(PubKey).
bin_to_hex(Bin) ->
lists:flatten([io_lib:format("~2.16.0B", [X]) || X <- binary_to_list(Bin)]).
hex_to_bin(S) ->
hex_to_bin(S, []).
hex_to_bin([], Acc) ->
list_to_binary(lists:reverse(Acc));
hex_to_bin([X,Y|T], Acc) ->
{ok, [V], []} = io_lib:fread("~16u", [X,Y]),
hex_to_bin(T, [V | Acc]);
hex_to_bin([X|T], Acc) ->
{ok, [V], []} = io_lib:fread("~16u", lists:flatten([X,"0"])),
hex_to_bin(T, [V | Acc]).

View File

@ -37,9 +37,9 @@ pub fn nif_ecrecover<'a>(env: Env<'a>, args: &[Term<'a>]) -> Result<Term<'a>, Er
let mut byte_ref = Vec::new();
let ecrecover = EcRecover { };
let _result = match ecrecover.execute(input.as_slice(),
&mut BytesRef::Flexible(&mut byte_ref)) {
&mut BytesRef::Fixed(&mut byte_ref)) {
Ok(_) => (),
Err(_e) => return Err(rustler::Error::Atom("ecrecover failed")),
Err(_e) => return Err(rustler::Error::Atom("ecrecover_failed")),
};
Ok((atoms::ok(), byte_ref.as_slice()).encode(env))
}