diff --git a/.gitignore b/.gitignore index 8a9256e..23d3f5e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ **/*.rs.bk Cargo.lock **/*~ +/parity-ethereum +/_build +/ebin diff --git a/Cargo.toml b/Cargo.toml index 0ea0fc1..c9f873f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/Makefile.linux b/Makefile similarity index 56% rename from Makefile.linux rename to Makefile index 792be51..7e3b2dd 100644 --- a/Makefile.linux +++ b/Makefile @@ -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 diff --git a/rebar.config b/rebar.config index c461d22..864cf39 100644 --- a/rebar.config +++ b/rebar.config @@ -1,24 +1,16 @@ - -{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, - {git, "https://github.com/aeternity/ecrecover-prebuilt.git", - {ref, "93569ca272e59682366cdf3c7ed2ee991540701a"}}}} + {git, "https://github.com/aeternity/ecrecover-prebuilt.git", + {ref, "93569ca272e59682366cdf3c7ed2ee991540701a"}}}} ]}. {plugins, [{rebar_ecrecoverprebuilt_dep, - {git, "https://github.com/aeternity/rebar3-ecrecover-prebuilt-plugin.git", - {ref, "f982da061c5f2e0ffbf1ad58ac25b3b32e182b01"}}} + {git, "https://github.com/aeternity/rebar3-ecrecover-prebuilt-plugin.git", + {ref, "f982da061c5f2e0ffbf1ad58ac25b3b32e182b01"}}} ]}. -%%{profiles, [{test, [{deps, [{meck, "0.8.12"}]}]}]}. - {dialyzer, [{warnings, [unknown]}, {plt_apps, all_deps}, {base_plt_apps, [erts, kernel, stdlib, crypto]} diff --git a/rebar.lock b/rebar.lock new file mode 100644 index 0000000..c3eef02 --- /dev/null +++ b/rebar.lock @@ -0,0 +1,5 @@ +[{<<"ecrecoverprebuilt">>, + {ecrecoverprebuilt_app_with_priv_from_git, + {git,"https://github.com/aeternity/ecrecover-prebuilt.git", + {ref,"93569ca272e59682366cdf3c7ed2ee991540701a"}}}, + 0}]. diff --git a/src/ecrecover.erl b/src/ecrecover.erl index c703c55..558e87a 100644 --- a/src/ecrecover.erl +++ b/src/ecrecover.erl @@ -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 = <>, + 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). diff --git a/src/ecrecover_util.erl b/src/ecrecover_util.erl new file mode 100644 index 0000000..6d154b7 --- /dev/null +++ b/src/ecrecover_util.erl @@ -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) -> + <> = 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]). diff --git a/src/lib.rs b/src/lib.rs index 359697d..9ec33b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,9 +37,9 @@ pub fn nif_ecrecover<'a>(env: Env<'a>, args: &[Term<'a>]) -> Result, 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)) }