Erlang integration (basic) done. Docs updated

This commit is contained in:
John Newby 2019-08-02 15:55:46 +02:00
parent 155bcfbe11
commit 5ca237202e
13 changed files with 290 additions and 82 deletions

View File

@ -1,13 +1,26 @@
DEBUG ?= 0
ifeq ($(DEBUG), 1)
CFLAGS =-DDEBUG=1
else
CFLAGS=-DNDEBUG
endif
CC = gcc CC = gcc
LIBS = -llibecrecover.so LIBS = -llibecrecover.so
LDPATH = -Ltarget/debug LDPATH = -Ltarget/debug
INCLUDEPATH = -Iinclude
%.o: %.c $(DEPS) %.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CC) $(CFLAGS) -c -o $(INCLUDEPATH) $@ $<
all: test erl_ecrecover
test: src/test.c src/base64.c target/debug/libecrecover.so
test: src/test.c target/debug/libecrecover.so $(CC) -o $@ $^ $(INCLUDEPATH) $(CFLAGS) $(LDPATH)
$(CC) -o $@ $^ $(CFLAGS) $(LDPATH)
./test ./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

View File

@ -1,13 +1,14 @@
# ecrecover # ecrecover
FFI export of Ethereum's ecrecover FFI export of Ethereum's ecrecover, with Erlang integration.
prerequisite: 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`) - 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: to compile:
`cargo build` `cargo build`
`make` (automatically runs tests).
to test: to test:
`make` (requires gcc) `make test` (requires gcc)
(if you don't see `Test passed` then something went wrong). (if you don't see `Test passed` then something went wrong).

View File

@ -0,0 +1 @@
4717328000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18000000000000000000000000f941ba12e03

View File

@ -0,0 +1 @@
47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03

7
include/base64.h Normal file
View 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

View File

@ -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
View 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
View 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
View 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
View 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
View 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));
}
}

View File

@ -14,13 +14,17 @@ const INPUT_LENGTH: usize = 512;
const OUTPUT_LENGTH: usize = 32; const OUTPUT_LENGTH: usize = 32;
#[no_mangle] #[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 ecrecover = EcRecover { };
let mut byte_ref = Vec::new(); let mut byte_ref = Vec::new();
ecrecover.execute(unsafe { std::slice::from_raw_parts(input as *const u8, INPUT_LENGTH) }, ecrecover.execute(unsafe { std::slice::from_raw_parts(input as *const u8, INPUT_LENGTH) },
&mut BytesRef::Flexible(&mut byte_ref)); &mut BytesRef::Flexible(&mut byte_ref));
let mut ptr: &mut[u8] = unsafe { std::slice::from_raw_parts_mut(output as *mut u8, OUTPUT_LENGTH) }; 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()); ptr.copy_from_slice(byte_ref.as_slice());
return 1;
} }
#[cfg(test)] #[cfg(test)]

View File

@ -1,4 +1,4 @@
// -*- C -*- // -*-C-*-
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
@ -21,76 +21,3 @@ int main(int arc, char **argv)
assert(strcmp(bin2hex(output, OUTPUT_LENGTH), expected) == 0); assert(strcmp(bin2hex(output, OUTPUT_LENGTH), expected) == 0);
printf("Test passed\n"); 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;
}