Erlang integration (basic) done. Docs updated
This commit is contained in:
parent
155bcfbe11
commit
5ca237202e
21
Makefile
21
Makefile
@ -1,13 +1,26 @@
|
||||
DEBUG ?= 0
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS =-DDEBUG=1
|
||||
else
|
||||
CFLAGS=-DNDEBUG
|
||||
endif
|
||||
|
||||
CC = gcc
|
||||
LIBS = -llibecrecover.so
|
||||
LDPATH = -Ltarget/debug
|
||||
INCLUDEPATH = -Iinclude
|
||||
|
||||
%.o: %.c $(DEPS)
|
||||
$(CC) -c -o $@ $<
|
||||
$(CC) $(CFLAGS) -c -o $(INCLUDEPATH) $@ $<
|
||||
|
||||
all: test erl_ecrecover
|
||||
|
||||
|
||||
test: src/test.c target/debug/libecrecover.so
|
||||
$(CC) -o $@ $^ $(CFLAGS) $(LDPATH)
|
||||
test: src/test.c src/base64.c target/debug/libecrecover.so
|
||||
$(CC) -o $@ $^ $(INCLUDEPATH) $(CFLAGS) $(LDPATH)
|
||||
./test
|
||||
|
||||
erl_ecrecover: src/erl_ecrecover.c src/base64.c src/erl_comm.c target/debug/libecrecover.so
|
||||
$(CC) -o$ $@ $^ $(INCLUDEPATH) $(CFLAGS) $(LDPATH)
|
||||
|
||||
clean:
|
||||
rm -f erl_ecrecover test
|
||||
|
@ -1,13 +1,14 @@
|
||||
# ecrecover
|
||||
FFI export of Ethereum's ecrecover
|
||||
FFI export of Ethereum's ecrecover, with Erlang integration.
|
||||
|
||||
prerequisite:
|
||||
- a checked out copy of my fork of parity-ethereum (https://github.com/johnsnewby/parity-ethereum) checked out in the same directory this is (i.e. it will be referenced as `../parity-ethereum`)
|
||||
|
||||
to compile:
|
||||
`cargo build`
|
||||
`make` (automatically runs tests).
|
||||
|
||||
to test:
|
||||
`make` (requires gcc)
|
||||
`make test` (requires gcc)
|
||||
|
||||
(if you don't see `Test passed` then something went wrong).
|
1
data/erl_ecrecover.input-fail.bin
Normal file
1
data/erl_ecrecover.input-fail.bin
Normal file
@ -0,0 +1 @@
|
||||
4717328000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18000000000000000000000000f941ba12e03
|
1
data/erl_ecrecover.input.bin
Normal file
1
data/erl_ecrecover.input.bin
Normal file
@ -0,0 +1 @@
|
||||
47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03
|
7
include/base64.h
Normal file
7
include/base64.h
Normal file
@ -0,0 +1,7 @@
|
||||
#if !defined __AE__BASE64_H
|
||||
#define __AE__BASE64_H
|
||||
|
||||
char *bin2hex(unsigned char*, int);
|
||||
unsigned char *hex2bin(const char*);
|
||||
|
||||
#endif
|
@ -1,2 +1,6 @@
|
||||
#if !defined __AE_ECRECOVER_H
|
||||
#define __AE_ECRECOVER_H
|
||||
|
||||
void ecrecover(const unsigned char *input, unsigned char *output);
|
||||
int ecrecover(const unsigned char *input, unsigned char *output);
|
||||
|
||||
#endif
|
||||
|
20
include/erl_comm.h
Normal file
20
include/erl_comm.h
Normal file
@ -0,0 +1,20 @@
|
||||
#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
|
77
src/base64.c
Normal file
77
src/base64.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include "base64.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
char *bin2hex(unsigned char *p, int len)
|
||||
{
|
||||
char *hex = malloc(((2*len) + 1));
|
||||
char *r = hex;
|
||||
|
||||
while(len && p)
|
||||
{
|
||||
(*r) = ((*p) & 0xF0) >> 4;
|
||||
(*r) = ((*r) <= 9 ? '0' + (*r) : 'a' - 10 + (*r));
|
||||
r++;
|
||||
(*r) = ((*p) & 0x0F);
|
||||
(*r) = ((*r) <= 9 ? '0' + (*r) : 'a' - 10 + (*r));
|
||||
r++;
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
*r = '\0';
|
||||
|
||||
return hex;
|
||||
}
|
||||
|
||||
unsigned char *hex2bin(const char *str)
|
||||
{
|
||||
int len, h;
|
||||
unsigned char *result, *err, *p, c;
|
||||
|
||||
err = malloc(1);
|
||||
*err = 0;
|
||||
|
||||
if (!str)
|
||||
return err;
|
||||
|
||||
if (!*str)
|
||||
return err;
|
||||
|
||||
len = 0;
|
||||
p = (unsigned char*) str;
|
||||
while (*p++)
|
||||
len++;
|
||||
|
||||
result = malloc((len/2)+1);
|
||||
h = !(len%2) * 4;
|
||||
p = result;
|
||||
*p = 0;
|
||||
|
||||
c = *str;
|
||||
while(c)
|
||||
{
|
||||
if(('0' <= c) && (c <= '9'))
|
||||
*p += (c - '0') << h;
|
||||
else if(('A' <= c) && (c <= 'F'))
|
||||
*p += (c - 'A' + 10) << h;
|
||||
else if(('a' <= c) && (c <= 'f'))
|
||||
*p += (c - 'a' + 10) << h;
|
||||
else
|
||||
return err;
|
||||
|
||||
str++;
|
||||
c = *str;
|
||||
|
||||
if (h)
|
||||
h = 0;
|
||||
else
|
||||
{
|
||||
h = 4;
|
||||
p++;
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
45
src/ecrecover.erl
Normal file
45
src/ecrecover.erl
Normal file
@ -0,0 +1,45 @@
|
||||
-module(ecrecover).
|
||||
-export([start/1, stop/0, init/1]).
|
||||
-export([ecrecover/1]).
|
||||
|
||||
start(ExtPrg) ->
|
||||
spawn(?MODULE, init, [ExtPrg]).
|
||||
stop() ->
|
||||
ecrecover ! stop.
|
||||
|
||||
ecrecover(X) ->
|
||||
call_port({ecrecover, X}).
|
||||
|
||||
call_port(Msg) ->
|
||||
ecrecover ! {call, self(), Msg},
|
||||
receive
|
||||
{ecrecover, Result} ->
|
||||
Result
|
||||
end.
|
||||
|
||||
init(ExtPrg) ->
|
||||
register(ecrecover, self()),
|
||||
process_flag(trap_exit, true),
|
||||
Port = open_port({spawn, ExtPrg}, [{packet, 2}]),
|
||||
loop(Port).
|
||||
|
||||
loop(Port) ->
|
||||
receive
|
||||
{call, Caller, Msg} ->
|
||||
Port ! {self(), {command, encode(Msg)}},
|
||||
receive
|
||||
{Port, {data, Data}} ->
|
||||
Caller ! {ecrecover, Data}
|
||||
end,
|
||||
loop(Port);
|
||||
stop ->
|
||||
Port ! {self(), close},
|
||||
receive
|
||||
{Port, closed} ->
|
||||
exit(normal)
|
||||
end;
|
||||
{'EXIT', Port, _} ->
|
||||
exit(port_terminated)
|
||||
end.
|
||||
|
||||
encode({_, X}) -> [1, X].
|
63
src/erl_comm.c
Normal file
63
src/erl_comm.c
Normal file
@ -0,0 +1,63 @@
|
||||
// -*- C -*-
|
||||
|
||||
#include "erl_comm.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int read_cmd(byte *buf)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (read_exact(buf, 2) != 2)
|
||||
return(-1);
|
||||
len = (buf[0] << 8) | buf[1];
|
||||
DEBUG_PRINTF("Len is %d\n", len);
|
||||
if(len > ECRECOVER_BUFFER_MAX - 1) {
|
||||
DEBUG_PRINTF("Avoiding overflow\n");
|
||||
return 0; // let's not overflow.
|
||||
}
|
||||
int read = read_exact(buf, len);
|
||||
DEBUG_PRINTF("read_cmd returning %d\n", read);
|
||||
return read;
|
||||
}
|
||||
|
||||
int write_cmd(byte *buf, int len)
|
||||
{
|
||||
byte li;
|
||||
|
||||
li = (len >> 8) & 0xff;
|
||||
write_exact(&li, 1);
|
||||
|
||||
li = len & 0xff;
|
||||
write_exact(&li, 1);
|
||||
|
||||
return write_exact(buf, len);
|
||||
}
|
||||
|
||||
int read_exact(byte *buf, int len)
|
||||
{
|
||||
int i, got=0;
|
||||
DEBUG_PRINTF("Read exact\n");
|
||||
do {
|
||||
if ((i = read(0, buf+got, len-got)) <= 0) {
|
||||
DEBUG_PRINTF("got=%d len=%d i=%d\n", got, len, i);
|
||||
return(i);
|
||||
}
|
||||
got += i;
|
||||
} while (got<len);
|
||||
DEBUG_PRINTF("Read %d returning %d\n", got, len);
|
||||
return(len);
|
||||
}
|
||||
|
||||
int write_exact(byte *buf, int len)
|
||||
{
|
||||
int i, wrote = 0;
|
||||
|
||||
do {
|
||||
if ((i = write(1, buf+wrote, len-wrote)) <= 0)
|
||||
return (i);
|
||||
wrote += i;
|
||||
} while (wrote<len);
|
||||
|
||||
return (len);
|
||||
}
|
45
src/erl_ecrecover.c
Normal file
45
src/erl_ecrecover.c
Normal file
@ -0,0 +1,45 @@
|
||||
// -*- C -*-
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ecrecover.h"
|
||||
#include "erl_comm.h"
|
||||
#include "base64.h"
|
||||
|
||||
#define OUTPUT_LENGTH 32
|
||||
|
||||
int main(int arc, char **argv)
|
||||
{
|
||||
int fn, arg, len;
|
||||
byte buf[ECRECOVER_BUFFER_MAX];
|
||||
|
||||
while ((len = read_cmd(buf)) > 0) {
|
||||
DEBUG_PRINTF("len %d\n", len);
|
||||
fn = buf[0];
|
||||
DEBUG_PRINTF("Function %d len %d\n", fn, len);
|
||||
buf[len] = '\0';
|
||||
if (fn == 1) {
|
||||
int result;
|
||||
byte *input = hex2bin(buf+1);
|
||||
byte *output = malloc(ECRECOVER_BUFFER_MAX);
|
||||
result = ecrecover(input, output);
|
||||
free(input);
|
||||
DEBUG_PRINTF("Return value is %d", result);
|
||||
if(result) {
|
||||
byte *hex_result = bin2hex(output, OUTPUT_LENGTH);
|
||||
strcpy(buf, hex_result);
|
||||
free(hex_result);
|
||||
DEBUG_PRINTF("result is %s len %ld\n", buf, strlen(buf));
|
||||
} else {
|
||||
strcpy("failed", buf);
|
||||
}
|
||||
free(output);
|
||||
} else {
|
||||
strcpy("function not found", buf);
|
||||
}
|
||||
DEBUG_PRINTF("Returning %s\n", buf);
|
||||
write_cmd(buf, strlen(buf));
|
||||
}
|
||||
}
|
@ -14,13 +14,17 @@ const INPUT_LENGTH: usize = 512;
|
||||
const OUTPUT_LENGTH: usize = 32;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ecrecover(input: *const libc::c_uchar, output: *mut libc::c_uchar) {
|
||||
pub unsafe extern "C" fn ecrecover(input: *const libc::c_uchar, output: *mut libc::c_uchar) -> i16 {
|
||||
let ecrecover = EcRecover { };
|
||||
let mut byte_ref = Vec::new();
|
||||
ecrecover.execute(unsafe { std::slice::from_raw_parts(input as *const u8, INPUT_LENGTH) },
|
||||
&mut BytesRef::Flexible(&mut byte_ref));
|
||||
let mut ptr: &mut[u8] = unsafe { std::slice::from_raw_parts_mut(output as *mut u8, OUTPUT_LENGTH) };
|
||||
if byte_ref.len() != OUTPUT_LENGTH {
|
||||
return 0;
|
||||
}
|
||||
ptr.copy_from_slice(byte_ref.as_slice());
|
||||
return 1;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
73
src/test.c
73
src/test.c
@ -21,76 +21,3 @@ int main(int arc, char **argv)
|
||||
assert(strcmp(bin2hex(output, OUTPUT_LENGTH), expected) == 0);
|
||||
printf("Test passed\n");
|
||||
}
|
||||
|
||||
char *bin2hex(unsigned char *p, int len)
|
||||
{
|
||||
char *hex = malloc(((2*len) + 1));
|
||||
char *r = hex;
|
||||
|
||||
while(len && p)
|
||||
{
|
||||
(*r) = ((*p) & 0xF0) >> 4;
|
||||
(*r) = ((*r) <= 9 ? '0' + (*r) : 'a' - 10 + (*r));
|
||||
r++;
|
||||
(*r) = ((*p) & 0x0F);
|
||||
(*r) = ((*r) <= 9 ? '0' + (*r) : 'a' - 10 + (*r));
|
||||
r++;
|
||||
p++;
|
||||
len--;
|
||||
}
|
||||
*r = '\0';
|
||||
|
||||
return hex;
|
||||
}
|
||||
|
||||
unsigned char *hex2bin(const char *str)
|
||||
{
|
||||
int len, h;
|
||||
unsigned char *result, *err, *p, c;
|
||||
|
||||
err = malloc(1);
|
||||
*err = 0;
|
||||
|
||||
if (!str)
|
||||
return err;
|
||||
|
||||
if (!*str)
|
||||
return err;
|
||||
|
||||
len = 0;
|
||||
p = (unsigned char*) str;
|
||||
while (*p++)
|
||||
len++;
|
||||
|
||||
result = malloc((len/2)+1);
|
||||
h = !(len%2) * 4;
|
||||
p = result;
|
||||
*p = 0;
|
||||
|
||||
c = *str;
|
||||
while(c)
|
||||
{
|
||||
if(('0' <= c) && (c <= '9'))
|
||||
*p += (c - '0') << h;
|
||||
else if(('A' <= c) && (c <= 'F'))
|
||||
*p += (c - 'A' + 10) << h;
|
||||
else if(('a' <= c) && (c <= 'f'))
|
||||
*p += (c - 'a' + 10) << h;
|
||||
else
|
||||
return err;
|
||||
|
||||
str++;
|
||||
c = *str;
|
||||
|
||||
if (h)
|
||||
h = 0;
|
||||
else
|
||||
{
|
||||
h = 4;
|
||||
p++;
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user