Switched to C based nif
This commit is contained in:
@@ -4,8 +4,7 @@
|
||||
{registered, []},
|
||||
{applications,
|
||||
[kernel,
|
||||
stdlib,
|
||||
ecrecoverprebuilt
|
||||
stdlib
|
||||
]},
|
||||
{env,[]},
|
||||
{modules, []},
|
||||
|
||||
+26
-37
@@ -1,7 +1,9 @@
|
||||
-module(ecrecover).
|
||||
|
||||
%% https://github.com/mbrix/libsecp256k1
|
||||
|
||||
%% API
|
||||
-export([recover/2]).
|
||||
-export([recover/2, recover/3]).
|
||||
|
||||
%% NIF
|
||||
-export([load/0]).
|
||||
@@ -9,16 +11,17 @@
|
||||
|
||||
%%=============================================================================
|
||||
%% NIF API
|
||||
%% GoodMsg1 = <<71,23,50,133,168,215,52,30,94,151,47,198,119,40,99,132,248,2,248,239,66,165,236,95,3,187,250,37,76,176,31,173>>.
|
||||
%% GoodSig1_v = <<27,101,10,207,157,63,95,10,44,121,151,118,161,37,67,85,213,244,6,23,98,162,55,57,106,153,160,224,227,252,43,205,103,41,81,74,13,172,178,230,35,172,74,189,21,124,177,129,99,255,148,34,128,219,77,92,170,214,109,223,148,27,161,46,3>>.
|
||||
%% ecrecover:recover(<<71,23,50,133,168,215,52,30,94,151,47,198,119,40,99,132,248,2,248,239,66,165,236,95,3,187,250,37,76,176,31,173>>, <<27,101,10,207,157,63,95,10,44,121,151,118,161,37,67,85,213,244,6,23,98,162,55,57,106,153,160,224,227,252,43,205,103,41,81,74,13,172,178,230,35,172,74,189,21,124,177,129,99,255,148,34,128,219,77,92,170,214,109,223,148,27,161,46,3>>).
|
||||
%%
|
||||
|
||||
load() ->
|
||||
% Prefer locally built NIF (good for testing and exotic platforms) over
|
||||
% prebuilt binaries.
|
||||
case load_local_nif() of
|
||||
ok ->
|
||||
ok;
|
||||
{error, _} ->
|
||||
load_prebuilt_nif()
|
||||
end.
|
||||
EbinDir = filename:dirname(code:which(?MODULE)),
|
||||
AppDir = filename:dirname(EbinDir),
|
||||
PrivDir = filename:join(AppDir, "priv"),
|
||||
SoName = filename:join(PrivDir, atom_to_list(?MODULE)),
|
||||
erlang:load_nif(SoName, 0).
|
||||
|
||||
not_loaded(Line) ->
|
||||
erlang:nif_error({error, {not_loaded, [{module, ?MODULE}, {line, Line}]}}).
|
||||
@@ -26,36 +29,22 @@ not_loaded(Line) ->
|
||||
%%=============================================================================
|
||||
%% External API
|
||||
|
||||
-spec recover(<<_:(32*8)>>, <<_:(65*8)>>) -> <<_:(32*8)>>.
|
||||
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 ->
|
||||
recover(Hash, <<V, Sig:64/binary>>) when V == 27; V == 28 ->
|
||||
RecId = V - 27,
|
||||
case recover(Hash, Sig, RecId) of
|
||||
{ok, <<4, XY:64/binary>>} ->
|
||||
<<_:12/bytes, ShortPub:20/bytes>> = keccak256(XY),
|
||||
<<0:96, ShortPub/binary>>;
|
||||
{error, _} ->
|
||||
<<0:256>>
|
||||
end.
|
||||
end.
|
||||
|
||||
-spec recover(<<_:(32*8)>>, <<_:(65*8)>>, integer()) -> <<_:(32*8)>>.
|
||||
recover(_Hash, _Sig, _RecId) ->
|
||||
not_loaded(?LINE).
|
||||
|
||||
%%=============================================================================
|
||||
%% Internal Functions
|
||||
|
||||
load_local_nif() ->
|
||||
EbinDir = filename:dirname(code:which(?MODULE)),
|
||||
AppDir = filename:dirname(EbinDir),
|
||||
PrivDir = filename:join(AppDir, "priv"),
|
||||
SoName = filename:join(PrivDir, atom_to_list(?MODULE)),
|
||||
erlang:load_nif(SoName, 0).
|
||||
|
||||
load_prebuilt_nif() ->
|
||||
case code:priv_dir(ecrecoverprebuilt) of
|
||||
{error, _} ->
|
||||
{error, prebuilt_priv_dir_not_found};
|
||||
PrivDir ->
|
||||
SoName = filename:join(PrivDir, atom_to_list(?MODULE)),
|
||||
erlang:load_nif(SoName, 0)
|
||||
end.
|
||||
|
||||
recover_(_Input) ->
|
||||
not_loaded(?LINE).
|
||||
keccak256(Bin) ->
|
||||
sha3:hash(256, Bin).
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
-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]).
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
extern crate c_vec;
|
||||
extern crate ethcore_builtin;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate libc;
|
||||
extern crate parity_bytes;
|
||||
#[macro_use]
|
||||
extern crate rustler;
|
||||
|
||||
use crate::ethcore_builtin::Implementation;
|
||||
use ethcore_builtin::EcRecover;
|
||||
use parity_bytes::BytesRef;
|
||||
use rustler::*;
|
||||
|
||||
mod atoms {
|
||||
rustler_atoms! {
|
||||
atom ok;
|
||||
}
|
||||
}
|
||||
|
||||
rustler_export_nifs!(
|
||||
"ecrecover",
|
||||
[("recover_", 1, nif_ecrecover),],
|
||||
Some(on_load)
|
||||
);
|
||||
|
||||
#[no_mangle]
|
||||
fn on_load(_env: Env, _load_info: Term) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn nif_ecrecover<'a>(env: Env<'a>, args: &[Term<'a>]) -> Result<Term<'a>, Error> {
|
||||
let input: Binary = args[0].decode()?;
|
||||
let mut byte_ref = Vec::new();
|
||||
let ecrecover = EcRecover {};
|
||||
let _result = match ecrecover.execute(input.as_slice(), &mut BytesRef::Flexible(&mut byte_ref))
|
||||
{
|
||||
Ok(_) => (),
|
||||
Err(_e) => return Err(rustler::Error::Atom("ecrecover_failed")),
|
||||
};
|
||||
Ok((atoms::ok(), byte_ref.as_slice()).encode(env))
|
||||
}
|
||||
Reference in New Issue
Block a user