Switched to C based nif
This commit is contained in:
parent
39ab0b2caa
commit
53b4d36a29
@ -1,5 +0,0 @@
|
||||
[target.'cfg(target_os = "macos")']
|
||||
rustflags = [
|
||||
"-C", "link-arg=-undefined",
|
||||
"-C", "link-arg=dynamic_lookup",
|
||||
]
|
@ -23,8 +23,6 @@ commands:
|
||||
&& sudo apt-get \
|
||||
install \
|
||||
build-essential \
|
||||
cargo \
|
||||
cmake \
|
||||
autoconf \
|
||||
libncurses5-dev
|
||||
- run:
|
||||
@ -33,10 +31,6 @@ commands:
|
||||
curl -fsSL -o otp-src.tar.gz https://github.com/erlang/otp/archive/OTP-<< parameters.OTP_VERSION >>.tar.gz
|
||||
tar -zxf otp-src.tar.gz --strip-components=1
|
||||
./otp_build autoconf && ./configure && make -j$(nproc) && sudo make install
|
||||
- run:
|
||||
name: Install rest
|
||||
command: |
|
||||
curl https://sh.rustup.rs -sSf | sh -s -- -yq && source $HOME/.cargo/env
|
||||
|
||||
setup_macos:
|
||||
description: "Setup macos environment"
|
||||
@ -49,7 +43,7 @@ commands:
|
||||
name: Setup environment
|
||||
command: |
|
||||
brew update
|
||||
brew install rust cmake erlang@<< parameters.OTP_VERSION >>
|
||||
brew install erlang@<< parameters.OTP_VERSION >>
|
||||
brew link --force erlang@<< parameters.OTP_VERSION >>
|
||||
|
||||
run_build:
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,8 +1,7 @@
|
||||
/target
|
||||
**/*.rs.bk
|
||||
**/*~
|
||||
/parity-ethereum
|
||||
/_build
|
||||
/ebin
|
||||
/priv/ecrecover.dll
|
||||
/priv/ecrecover.so
|
||||
/c_src/ecrecover.d
|
||||
/c_src/ecrecover.o
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "c_src/secp256k1"]
|
||||
path = c_src/secp256k1
|
||||
url = https://github.com/bitcoin-core/secp256k1.git
|
1996
Cargo.lock
generated
1996
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
19
Cargo.toml
19
Cargo.toml
@ -1,19 +0,0 @@
|
||||
[package]
|
||||
name = "ecrecover"
|
||||
version = "0.1.0"
|
||||
authors = ["John Newby <john@newby.org>"]
|
||||
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 = { git = "https://github.com/paritytech/parity-ethereum.git", rev = "acf7c48" }
|
||||
lazy_static = "1.3.0"
|
||||
libc = "0.2.60"
|
||||
parity-bytes = "0.1.0"
|
||||
rustler = "0.21.0"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
30
Makefile
30
Makefile
@ -1,30 +0,0 @@
|
||||
UNAME := $(shell uname)
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
nif_lib_src = ecrecover.dll
|
||||
nif_lib = ecrecover.dll
|
||||
else
|
||||
ifeq ($(UNAME), Linux)
|
||||
nif_lib_src = libecrecover.so
|
||||
nif_lib = ecrecover.so
|
||||
endif
|
||||
ifeq ($(UNAME), Darwin)
|
||||
nif_lib_src = libecrecover.dylib
|
||||
nif_lib = ecrecover.so
|
||||
endif
|
||||
endif
|
||||
|
||||
all: priv/$(nif_lib) compile
|
||||
|
||||
compile:
|
||||
./rebar3 compile
|
||||
|
||||
priv/$(nif_lib): src/lib.rs
|
||||
ifneq ($(ECRECOVER_DISABLE_NIF_BUILD), true)
|
||||
cargo build --release
|
||||
cp target/release/$(nif_lib_src) $@
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f priv/$(nif_lib) target/release/$(nif_lib_src)
|
||||
./rebar3 clean
|
25
Makefile.win32
Normal file
25
Makefile.win32
Normal file
@ -0,0 +1,25 @@
|
||||
secp256k1_dir := c_src/secp256k1
|
||||
secp256k1_lib_dir := c_src/secp256k1/.libs
|
||||
|
||||
CFLAGS := -MT -DNOMINMAX -Ox -DNDEBUG -openmp -W4 -Zi -EHsc -nologo -I$(secp256k1_dir)/include
|
||||
LDFLAGS := -LIBPATH:$(secp256k1_lib_dir) -nologo
|
||||
|
||||
.PHONY: win32_ecrecover
|
||||
win32_ecrecover: $(secp256k1_lib_dir)/libsecp256k1.lib
|
||||
|
||||
$(secp256k1_lib_dir)/libsecp256k1.lib: $(secp256k1_lib_dir)/secp256k1.lib
|
||||
lib ${LDFLAGS} -OUT:$@ -nodefaultlib $^
|
||||
|
||||
$(secp256k1_lib_dir)/secp256k1.lib: $(secp256k1_obj_dir)/fp.obj
|
||||
lib ${LDFLAGS} -OUT:$@ -nodefaultlib $<
|
||||
|
||||
$(secp256k1_obj_dir)/fp.obj: $(secp256k1_src_dir)/fp.cpp
|
||||
cl -c ${CFLAGS} $< -Fo$@
|
||||
|
||||
$(secp256k1_obj_dir)/bn_c384_256.obj: $(secp256k1_src_dir)/bn_c384_256.cpp
|
||||
cl -c ${CFLAGS} $< -Fo$@
|
||||
|
||||
clean_win32_secp256k1:
|
||||
make -C $(secp256k1_dir) clean
|
||||
rm -f $(secp256k1_lib_dir)/*.lib $(secp256k1_lib_dir)/*.dll $(secp256k1_lib_dir)/*.exp
|
||||
|
102
c_src/ecrecover.c
Normal file
102
c_src/ecrecover.c
Normal file
@ -0,0 +1,102 @@
|
||||
#include "erl_nif.h"
|
||||
#include "secp256k1_recovery.h"
|
||||
|
||||
|
||||
static secp256k1_context *ctx = NULL;
|
||||
|
||||
static ERL_NIF_TERM error_result(ErlNifEnv* env, char* error_msg)
|
||||
{
|
||||
return enif_make_tuple2(env, enif_make_atom(env, "error"), enif_make_string(env, error_msg, ERL_NIF_LATIN1));
|
||||
}
|
||||
|
||||
static ERL_NIF_TERM ok_result(ErlNifEnv* env, ERL_NIF_TERM *r)
|
||||
{
|
||||
return enif_make_tuple2(env, enif_make_atom(env, "ok"), *r);
|
||||
}
|
||||
|
||||
static ERL_NIF_TERM
|
||||
recover(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
|
||||
{
|
||||
ERL_NIF_TERM r;
|
||||
ErlNifBinary message, csignature;
|
||||
int result;
|
||||
int compressed = SECP256K1_EC_UNCOMPRESSED;
|
||||
size_t pubkeylen = 65;
|
||||
int recid;
|
||||
unsigned char* finished_recpubkey_buf;
|
||||
secp256k1_ecdsa_recoverable_signature signature;
|
||||
secp256k1_pubkey recpubkey;
|
||||
|
||||
if (!enif_inspect_binary(env, argv[0], &message)) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
|
||||
if (!enif_inspect_binary(env, argv[1], &csignature)) {
|
||||
return enif_make_badarg(env);
|
||||
}
|
||||
|
||||
if (!enif_get_int(env, argv[2], &recid)) {
|
||||
return error_result(env, "Recovery id invalid 0-3");
|
||||
}
|
||||
|
||||
if (recid < 0 || recid > 3) {
|
||||
error_result(env, "Recovery id invalid 0-3x");
|
||||
}
|
||||
printf("xx1\r\n");
|
||||
result = secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &signature, csignature.data, recid);
|
||||
printf("xx2\r\n");
|
||||
if (!result) {
|
||||
return error_result(env, "ecdsa_signature_parse_compact returned 0");
|
||||
}
|
||||
|
||||
// Now do ECDSA recovery
|
||||
result = secp256k1_ecdsa_recover(ctx, &recpubkey, &signature, message.data);
|
||||
|
||||
if (!result) {
|
||||
return error_result(env, "ecdsa recovery problem");
|
||||
}
|
||||
|
||||
// Now serialize recpubkey based on the compression flag
|
||||
finished_recpubkey_buf = enif_make_new_binary(env, pubkeylen, &r);
|
||||
|
||||
printf("pubker[0] = %d\r\n", recpubkey.data[0]);
|
||||
|
||||
|
||||
result = secp256k1_ec_pubkey_serialize(ctx, finished_recpubkey_buf,
|
||||
&pubkeylen, &recpubkey, compressed);
|
||||
|
||||
if (!result) {
|
||||
return error_result(env, "ecdsa pubkey serialize error");
|
||||
}
|
||||
|
||||
return ok_result(env, &r);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
load(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
|
||||
{
|
||||
ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
upgrade(ErlNifEnv* env, void** priv, void** old_priv, ERL_NIF_TERM load_info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
unload(ErlNifEnv* env, void* priv)
|
||||
{
|
||||
secp256k1_context_destroy(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
static ErlNifFunc nif_funcs[] =
|
||||
{
|
||||
{"recover", 3, recover}
|
||||
};
|
||||
|
||||
ERL_NIF_INIT(ecrecover, nif_funcs, &load, NULL, NULL, &unload);
|
1
c_src/secp256k1
Submodule
1
c_src/secp256k1
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit cbe41ac138bc0773d60ab1942b7ad6fc5eccfc19
|
@ -1 +0,0 @@
|
||||
4717328000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18000000000000000000000000f941ba12e03
|
@ -1 +0,0 @@
|
||||
47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03
|
@ -1,7 +0,0 @@
|
||||
#if !defined __AE__BASE64_H
|
||||
#define __AE__BASE64_H
|
||||
|
||||
char *bin2hex(unsigned char*, int);
|
||||
unsigned char *hex2bin(const char*);
|
||||
|
||||
#endif
|
@ -1,6 +0,0 @@
|
||||
#if !defined __AE_ECRECOVER_H
|
||||
#define __AE_ECRECOVER_H
|
||||
|
||||
int ecrecover(const unsigned char *input, unsigned char *output);
|
||||
|
||||
#endif
|
@ -1,10 +0,0 @@
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
|
||||
extern "C" {
|
||||
|
||||
void ecrecover(const unsigned char *input, unsigned char *output);
|
||||
|
||||
} // extern "C"
|
@ -1,20 +0,0 @@
|
||||
#if !defined __AE__ERL_COMM_H
|
||||
#define __AE__ERL_COMM_H
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#define DEBUG_PRINTF printf
|
||||
#else
|
||||
#define DEBUG_PRINTF
|
||||
#endif
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#define ECRECOVER_BUFFER_MAX 1024
|
||||
|
||||
int read_cmd(byte *buf);
|
||||
int write_cmd(byte *buf, int len);
|
||||
int read_exact(byte *buf, int len);
|
||||
int write_exact(byte *buf, int len);
|
||||
|
||||
#endif
|
42
rebar.config
42
rebar.config
@ -1,17 +1,39 @@
|
||||
{deps, [
|
||||
%% ecrecover prebuilt libraries
|
||||
{ecrecoverprebuilt,
|
||||
{ecrecoverprebuilt_app_with_priv_from_git,
|
||||
{git, "https://github.com/aeternity/ecrecover-prebuilt.git",
|
||||
{ref, "4027374"}}}}
|
||||
{deps,
|
||||
[{sha3, {git, "https://github.com/aeternity/erlang-sha3", {ref, "b5f27a2"}}}]}.
|
||||
|
||||
{pre_hooks, [ {compile, "git submodule update --init"}
|
||||
, {"(linux|darwin)", compile, "sh -c \"cd c_src/secp256k1 && ./autogen.sh && ./configure --enable-module-recovery && make\""}
|
||||
, {"win32", compile, "make -f Makefile.win32 win32_ecrecover"}
|
||||
]}.
|
||||
|
||||
{plugins, [{rebar_ecrecoverprebuilt_dep,
|
||||
{git, "https://github.com/aeternity/rebar3-ecrecover-prebuilt-plugin.git",
|
||||
{ref, "7286efd"}}}
|
||||
{post_hooks, [ {"(linux|darwin)", clean, "make -C \"c_src/secp256k1\" clean"}
|
||||
, {"win32", clean, "make -f Makefile.win32 clean_win32_ecrecover"}
|
||||
]}.
|
||||
|
||||
|
||||
{plugins, [pc]}.
|
||||
|
||||
{provider_hooks, [
|
||||
{post, [ {compile, {pc, compile}}
|
||||
, {clean, {pc, clean}}
|
||||
]}
|
||||
]}.
|
||||
|
||||
{port_specs, [{"priv/ecrecover.so", ["c_src/*.c"]}]}.
|
||||
|
||||
{port_env, [ {"darwin", "CFLAGS", "$CFLAGS -fPIC -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes -I c_src/secp256k1/include"}
|
||||
, {"darwin", "CXXFLAGS", "$CXXFLAGS -fPIC -O3 -finline-functions -Wall"}
|
||||
, {"darwin", "LDFLAGS", "$LDFLAGS c_src/secp256k1/.libs/libsecp256k1.a"}
|
||||
|
||||
, {"linux", "CFLAGS", "$CFLAGS -fPIC -O3 -std=c99 -finline-functions -Wall -Wmissing-prototypes -I c_src/secp256k1/include"}
|
||||
, {"linux", "CXXFLAGS", "$CXXFLAGS -fPIC -O3 -finline-functions -Wall"}
|
||||
, {"linux", "LDFLAGS", "$LDFLAGS c_src/secp256k1/.libs/libsecp256k1.a -lstdc++"}
|
||||
|
||||
, {"win32", "CFLAGS", "$CFLAGS /LD /MD /Fe /Ox /DNDEBUG /DMCLBN_DONT_EXPORT /Ic_src/secp256k1/include"}
|
||||
, {"win32", "LDFLAGS", "$LDFLAGS /LIBPATH:c_src/cybozulib_ext/lib c_src/secp256k1/.libs/secp256k1.lib"}
|
||||
]}.
|
||||
|
||||
{dialyzer, [{warnings, [unknown]},
|
||||
{plt_apps, all_deps},
|
||||
{base_plt_apps, [erts, kernel, stdlib, crypto]}
|
||||
{base_plt_apps, [erts, kernel, stdlib]}
|
||||
]}.
|
||||
|
@ -1,5 +1 @@
|
||||
[{<<"ecrecoverprebuilt">>,
|
||||
{ecrecoverprebuilt_app_with_priv_from_git,
|
||||
{git,"https://github.com/aeternity/ecrecover-prebuilt.git",
|
||||
{ref,"402737411420fc4c500e1f42c921ef185a35cc56"}}},
|
||||
0}].
|
||||
[].
|
||||
|
@ -4,8 +4,7 @@
|
||||
{registered, []},
|
||||
{applications,
|
||||
[kernel,
|
||||
stdlib,
|
||||
ecrecoverprebuilt
|
||||
stdlib
|
||||
]},
|
||||
{env,[]},
|
||||
{modules, []},
|
||||
|
@ -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.
|
||||
|
||||
-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
src/lib.rs
42
src/lib.rs
@ -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))
|
||||
}
|
22
test/ecrecover_tests.erl
Normal file
22
test/ecrecover_tests.erl
Normal file
@ -0,0 +1,22 @@
|
||||
%%%=============================================================================
|
||||
%%% @copyright (C) 2023, Aeternity Foundation
|
||||
%%% @doc
|
||||
%%% Unit tests for ecrecover
|
||||
%%% @end
|
||||
%%%=============================================================================
|
||||
-module(ecrecover_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
%% MSG and SIG from aecontract_SUITE, in turn taken from
|
||||
%% https://github.com/aeternity/parity-ethereum/blob/master/ethcore/builtin/src/lib.rs#L656
|
||||
%% GoodHexSig1 = "47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03",
|
||||
%% <<GoodMsg1:32/binary, _:31/binary, GoodSig1_v:65/binary>> = aeu_hex:hex_to_bin(GoodHexSig1)
|
||||
-define(MSG, <<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>>).
|
||||
-define(SIG, <<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>>).
|
||||
-define(EXPECTED_PUBKEY, <<0,0,0,0,0,0,0,0,0,0,0,0,192,139,85,66,209,119,172,102,134,148,105,32,64,151,65,70,58,21,221,219>>).
|
||||
|
||||
|
||||
recover_test() ->
|
||||
PubKey = ecrecover:recover(?MSG, ?SIG),
|
||||
?assertEqual(?EXPECTED_PUBKEY, PubKey).
|
Loading…
x
Reference in New Issue
Block a user