Skip to content

Commit

Permalink
feat: implement lib
Browse files Browse the repository at this point in the history
  • Loading branch information
mpolitzer committed Oct 26, 2023
1 parent e848edd commit ec13958
Show file tree
Hide file tree
Showing 26 changed files with 1,910 additions and 19 deletions.
66 changes: 57 additions & 9 deletions linux/libdriver/Makefile
Original file line number Diff line number Diff line change
@@ -1,26 +1,74 @@
all: libdriver.a
# make ioctl CROSS_COMPILE=riscv64-linux-gnu- libioctl.a
# make mock libmock.a

CC := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
CFLAGS := -Wall -pedantic

libdriver.a: ioctl/rollup.o ioctl/yield.o
all: libioctl.a libmock.a

ioctl_OBJ := \
ioctl/rollup.o \
ioctl/yield.o \

base_OBJ := \
base/buf.o \
base/abi.o \
base/keccak.o \
base/merkle.o \

mock_OBJ := \
mock/rollup.o \
mock/yield.o \

OBJ := \
$(ioctl_OBJ) \
$(base_OBJ) \
$(mock_OBJ)

%.o: %.c
$(CC) $(CFLAGS) -MT $@ -MMD -MP -MF $(@:.o=.d) -c -o $@ $<

libioctl.a: $(ioctl_OBJ) $(base_OBJ)
$(AR) rcs $@ $^
ioctl/rollup.o: ioctl/rollup.c
$(CC) -Wall -pedantic -march=rv64gc -mabi=lp64d -c -o $@ $<
ioctl/yield.o: ioctl/yield.c
$(CC) -Wall -pedantic -march=rv64gc -mabi=lp64d -c -o $@ $<

ioctl/rollup.o: ioctl/rollup.h base/rollup-driver-api.h
ioctl/yield.o: ioctl/yield.h base/yield-driver-api.h
libmock.a: $(mock_OBJ) $(base_OBJ)
$(AR) rcs $@ $^

ioctl/yield: examples/yield.c libioctl.a
$(CC) $(CFLAGS) -Iioctl -o $@ $^
ioctl/merkle: examples/merkle.c libmock.a
$(CC) $(CFLAGS) -Iioctl -o $@ $^
ioctl/rollup: examples/rollup.c libioctl.a
$(CC) $(CFLAGS) -Iioctl -o $@ $^

mock/yield: examples/yield.c libmock.a
$(CC) $(CFLAGS) -Imock -o $@ $^
mock/merkle: examples/merkle.c libmock.a
$(CC) $(CFLAGS) -Imock -o $@ $^
mock/rollup: examples/rollup.c libmock.a
$(CC) $(CFLAGS) -Imock -o $@ $^

tests/abi: tests/abi.c libmock.a
$(CC) $(CFLAGS) -Imock -o $@ $^
tests/keccak: tests/keccak.c libmock.a
$(CC) $(CFLAGS) -Imock -o $@ $^
tests/merkle: tests/merkle.c libmock.a
$(CC) $(CFLAGS) -Imock -o $@ $^

tools/merkle-zero-table: tools/merkle-zero-table.c libmock.a
$(CC) $(CFLAGS) -Imock -o $@ $^

doc: doc/theme
doxygen doc/Doxyfile
doc/theme:
git clone --depth=1 --branch=v2.2.1 \
[email protected]:jothepro/doxygen-awesome-css.git $@
clean:
rm libdriver.a ioctl/rollup.o ioctl/yield.o
rm -f $(OBJ)
rm -rf doc/html
distclean:
rm -rf doc/theme
.PHONY: doc

-include $(OBJ:%.o=%.d)
12 changes: 10 additions & 2 deletions linux/libdriver/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
Utility functions for rollup interaction.

- @ref libevm\_rollup
- @ref libevm\_abi
- @ref libevm\_buf
- @ref libevm\_keccak
- @ref libevm\_merkle

Userspace library to interact with cartesi kernel drivers

- @ref rollup
- @ref yield
- @ref rollup\_driver
- @ref yield\_driver

# Getting Started

Expand Down
217 changes: 217 additions & 0 deletions linux/libdriver/base/abi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
#include <assert.h>
#include <errno.h>
#include <string.h>
#include "abi.h"

uintptr_t align(uintptr_t p, size_t a)
{
return (p + (a-1)) & ~(a-1);
}

uint32_t evm_abi_funsel(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
return EVM_ABI_FUNSEL(a, b, c, d);
}

int evm_abi_put_funsel(evm_buf_t *me, uint32_t funsel)
{
int rc;
evm_buf_t x[1];
if ((rc = evm_buf_split(me, sizeof(funsel), x, me)))
return rc;
memcpy(x->p, &funsel, sizeof(funsel));
return 0;
}

int evm_abi_enc_uint_nr(size_t n, const uint8_t data[n], uint8_t out[EVM_WORD_LEN])
{
if (n > EVM_WORD_LEN) return EDOM;

for (int i=0; i<n; ++i)
out[EVM_WORD_LEN-1-i] = data[i];
for (int i=n; i<EVM_WORD_LEN; ++i)
out[EVM_WORD_LEN-1-i] = 0;

return 0;
}

int evm_abi_enc_uint_nn(size_t n, const uint8_t data[n], uint8_t out[EVM_WORD_LEN])
{
if (n > EVM_WORD_LEN) return EDOM;

for (int i=0; i<EVM_WORD_LEN-n; ++i)
out[i] = 0;
for (int i=EVM_WORD_LEN-n; i<EVM_WORD_LEN; ++i)
out[i] = data[i-EVM_WORD_LEN+n];

return 0;
}

int evm_abi_enc_uint(size_t n, const void *data, uint8_t out[EVM_WORD_LEN])
{
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
return evm_abi_enc_uint_nn(n, data, out);
#else
return evm_abi_enc_uint_nr(n, data, out);
#endif
}

int evm_abi_dec_uint_nr(const uint8_t data[EVM_WORD_LEN], size_t n, uint8_t out[n])
{
for (int i=0; i<EVM_WORD_LEN-n; ++i) if (data[i])
return EDOM;
for (int i=EVM_WORD_LEN-n; i<EVM_WORD_LEN; ++i)
out[EVM_WORD_LEN-1-i] = data[i];
return 0;
}

int evm_abi_dec_uint_nn(const uint8_t data[EVM_WORD_LEN], size_t n, uint8_t out[n])
{
for (int i=0; i<EVM_WORD_LEN-n; ++i) if (data[i])
return EDOM;
for (int i=EVM_WORD_LEN-n; i<EVM_WORD_LEN; ++i)
out[i-EVM_WORD_LEN+n] = data[i];
return 0;
}

int evm_abi_dec_uint(const uint8_t data[EVM_WORD_LEN], size_t n, uint8_t out[n])
{
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
return evm_abi_dec_uint_nn(data, n, out);
#else
return evm_abi_dec_uint_nr(data, n, out);
#endif
}

int evm_abi_put_uint(evm_buf_t *me, size_t n, const void *data)
{
evm_buf_t x;

if (n > EVM_WORD_LEN)
return EDOM;
if (evm_buf_split(me, EVM_WORD_LEN, &x, me))
return ENOBUFS;

evm_abi_enc_uint(n, data, x.p);
return 0;
}

int evm_abi_put_address(evm_buf_t *me, const uint8_t data[20])
{
evm_buf_t x;

if (evm_buf_split(me, EVM_WORD_LEN, &x, me))
return ENOBUFS;

evm_abi_enc_uint_nn(EVM_ADDRESS_LEN, data, x.p);
return 0;
}

int evm_abi_put_bytes_s(evm_buf_t *me, evm_buf_t *offset)
{
return evm_buf_split(me, EVM_WORD_LEN, offset, me);
}

int evm_abi_res_bytes_d(evm_buf_t *me, evm_buf_t *of, size_t n, evm_buf_t *out)
{
int rc;
evm_buf_t sz[1];
size_t n32 = align(n, EVM_WORD_LEN);

if ((rc = evm_buf_split(me, EVM_WORD_LEN, sz, me)))
return rc;
if ((rc = evm_buf_split(me, n32, out, me)))
return rc;

size_t offset = sz->p - of->p;
evm_abi_enc_uint(sizeof(offset), &offset, of->p);
evm_abi_enc_uint(sizeof(n), &n, sz->p);
memset(out->p + n, 0, n32 - n);
return 0;
}

int evm_abi_put_bytes_d(evm_buf_t *me, evm_buf_t *offset, size_t n, const void *data)
{
int rc;
evm_buf_t res[1];

if ((rc = evm_abi_res_bytes_d(me, offset, n, res)))
return rc;

memcpy(res->p, data, n);
return 0;
}

uint32_t evm_abi_peek_funsel(evm_buf_t *me)
{
assert(evm_buf_length(me) >= 4);
return EVM_ABI_FUNSEL(me->p[0], me->p[1], me->p[2], me->p[3]);
}

int evm_abi_check_funsel(evm_buf_t *me, uint32_t expected)
{
if (evm_buf_length(me) < 4)
return ENOBUFS;

if (evm_abi_peek_funsel(me) != expected)
return EBADMSG;

me->p += 4;
return 0;
}

int evm_abi_get_uint(evm_buf_t *me, size_t n, void *data)
{
int rc;
evm_buf_t x[1];

if (n > EVM_WORD_LEN) return EDOM;
if ((rc = evm_buf_split(me, EVM_WORD_LEN, x, me)))
return rc;

return evm_abi_dec_uint(x->p, n, data);
}

int evm_abi_get_address(evm_buf_t *me, uint8_t address[EVM_ADDRESS_LEN])
{
int rc;
evm_buf_t x[1];

if ((rc = evm_buf_split(me, EVM_WORD_LEN, x, me)))
return rc;

return evm_abi_dec_uint_nn(x->p, EVM_ADDRESS_LEN, address);
}

int evm_abi_get_bytes_s(evm_buf_t *me, evm_buf_t of[1])
{
return evm_buf_split(me, EVM_WORD_LEN, of, me);
}

/* 1. find the offset to (size, data) block, the dynamic section for this bytes.
* 2. read size part
* 3. read data part */
int evm_abi_peek_bytes_d(evm_buf_t *me, evm_buf_t of[1], evm_buf_t *bytes)
{
int rc;
uint64_t offset, size;
if ((rc = evm_abi_get_uint(of, sizeof(offset), &offset)))
return rc;

evm_buf_t it[1] = {{of->p + offset - EVM_WORD_LEN, me->q}};
if ((rc = evm_abi_get_uint(it, sizeof(size), &size)))
return rc;

return evm_buf_split(it, size, bytes, it);
}

int evm_abi_get_bytes_d(evm_buf_t *me, evm_buf_t of[1], size_t *n, void **data)
{
int rc;
evm_buf_t bytes[1];
if ((rc = evm_abi_peek_bytes_d(me, of, bytes)))
return rc;
*n = evm_buf_length(bytes);
*data = bytes->p;
return 0;
}
Loading

0 comments on commit ec13958

Please sign in to comment.