Skip to content

Commit

Permalink
feat: add libdriver
Browse files Browse the repository at this point in the history
mock: components can be compiled natively:
1. make mock tests

ioctl: require the cartesi headers and a riscv compiler:
1. Build or download a compatible kernel and `.deb` headers
2. Setup a cross compilation debian environment by running the setup[1]
   script.
3. `make ioctl CROSS_COMPILE=riscv64-linux-gnu-`

[1] setup.sh
```
apt update && \
DEBIAN_FRONTEND="noninteractive" apt-get install --no-install-recommends --allow-downgrades -y \
  bc \
  bison \
  build-essential \
  flex \
  genext2fs \
  rsync \
  gcc-riscv64-linux-gnu \
  libc6-dev-riscv64-cross \
  ./linux-libc-dev-riscv64-cross-6.5.9-ctsi-1-v0.0.0.deb
```
  • Loading branch information
mpolitzer committed Nov 10, 2023
1 parent 063d6d3 commit 7e030b2
Show file tree
Hide file tree
Showing 44 changed files with 5,878 additions and 5 deletions.
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ RUN cd ${BUILD_BASE}twuewand/rndaddentropy/ && \
# copy tools
COPY linux/ ${BUILD_BASE}tools/linux/

# build C/C++ libs
# ------------------------------------------------------------------------------
RUN make -C ${BUILD_BASE}tools/linux/libdriver/ CROSS_COMPILE=""

# build C/C++ tools
# ------------------------------------------------------------------------------
RUN make -C ${BUILD_BASE}tools/linux/xhalt/ CROSS_COMPILE="" xhalt.toolchain
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ MACHINE_EMULATOR_TOOLS_TAR_GZ := machine-emulator-tools-$(MACHINE_EMULATOR_TOOL
MACHINE_EMULATOR_TOOLS_DEB := machine-emulator-tools-$(MACHINE_EMULATOR_TOOLS_VERSION).deb
MACHINE_EMULATOR_TOOLS_IMAGE := cartesi/machine-emulator-tools:$(MACHINE_EMULATOR_TOOLS_VERSION)

LINUX_SOURCES_VERSION ?= 5.15.63-ctsi-2
LINUX_SOURCES_FILEPATH := dep/linux-$(LINUX_SOURCES_VERSION).tar.gz
LINUX_SOURCES_URLPATH := https://github.com/cartesi/linux/archive/refs/tags/v$(LINUX_SOURCES_VERSION).tar.gz
LINUX_SOURCES_VERSION ?= rollup-rework
LINUX_SOURCES_FILEPATH := dep/$(LINUX_SOURCES_VERSION).tar.gz
LINUX_SOURCES_URLPATH := https://github.com/cartesi/linux/archive/refs/heads/feature/$(LINUX_SOURCES_VERSION).tar.gz

RNDADDENTROPY_VERSION ?= 3.0.0
RNDADDENTROPY_FILEPATH := dep/twuewand-$(RNDADDENTROPY_VERSION).tar.gz
Expand Down
5 changes: 3 additions & 2 deletions linux/htif/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ RVCXX = $(CROSS_COMPILE)g++
RVCOPY = $(CROSS_COMPILE)objcopy
RVDUMP = $(CROSS_COMPILE)objdump
STRIP = $(CROSS_COMPILE)strip
RISCV_CFLAGS :=-march=$(RISCV_ARCH) -mabi=$(RISCV_ABI)
CFLAGS := -O2 -Wall -pedantic -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -I../libdriver/ioctl
LDLIBS := -L../libdriver -ldriver

CONTAINER_MAKE := /usr/bin/make
CONTAINER_BASE := /opt/cartesi/tools
Expand All @@ -42,7 +43,7 @@ extra.ext2: yield
$(MAKE) toolchain-exec CONTAINER_COMMAND="$(CONTAINER_MAKE) $@.toolchain"

yield.toolchain:
$(RVCC) -O2 -o yield yield.c
$(RVCC) $(CFLAGS) -o yield yield.c $(LDLIBS)
$(STRIP) yield

extra.ext2.toolchain:
Expand Down
100 changes: 100 additions & 0 deletions linux/libdriver/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
CC := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
CFLAGS := -O2 -g -Wall -pedantic

#all: mock tests
#mock: libmock.a $(mock_BINS)
#ioctl: libioctl.a $(ioctl_BINS)
#tests: tests/abi tests/keccak tests/merkle
#tools: tools/merkle-zero-table tools/funsel

help:
@echo "Cleaning targets:"
@echo " clean - remove the binaries and objects."
@echo " mock - build a reference mock library and examples for running in host mode."
@echo " ioctl - build the actual ioctl library and examples."
@echo " tools - build additional utilities for development."
@echo " with CROSS_COMPILE="

mock: libmock.a mock/yield mock/rollup-driver mock/rollup
ioctl: libioctl.a ioctl/yield ioctl/rollup-driver ioctl/rollup
tests: tests/abi tests/keccak tests/merkle

base_SRC := \
base/buf.c \
base/abi.c \
base/keccak.c \
base/merkle.c \
base/rollup.c

libmock_SRC := \
mock/rollup-driver.c \
mock/yield-driver.c \
$(base_SRC)

libioctl_SRC := \
ioctl/rollup-driver.c \
ioctl/yield-driver.c \
$(base_SRC)

libmock_OBJDIR := build/libmock/
libioctl_OBJDIR := build/libioctl/

libmock_OBJ := $(patsubst %.c,$(libmock_OBJDIR)%.o,$(libmock_SRC))
libioctl_OBJ := $(patsubst %.c,$(libioctl_OBJDIR)%.o,$(libioctl_SRC))

OBJ := $(libmock_OBJ) $(libioctl_OBJ)

$(libmock_OBJ): $(libmock_OBJDIR)%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -Imock -MT $@ -MMD -MP -MF $(@:.o=.d) -c -o $@ $<

$(libioctl_OBJ): $(libioctl_OBJDIR)%.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -Iioctl -MT $@ -MMD -MP -MF $(@:.o=.d) -c -o $@ $<

libmock.a: $(libmock_OBJ)
$(AR) rcs $@ $^

libioctl.a: $(libioctl_OBJ)
$(AR) rcs $@ $^

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

mock/yield-driver: examples/yield-driver.c libmock.a
$(CC) $(CFLAGS) -Imock -o $@ $^
mock/rollup-driver: examples/rollup-driver.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 base/keccak.o
$(CC) $(CFLAGS) -Imock -o $@ $^
tools/funsel: tools/funsel.c base/keccak.o
$(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 -f libmock.a $(mock_BINS) libioctl.a $(ioctl_BINS) $(OBJ) $(OBJ:%.o=%.d)
rm -rf doc/html
distclean:
rm -rf doc/theme
.PHONY: doc

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

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

Thin wrappers to the cartesi kernel drivers

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

# Getting Started

Download the static library from [cartesi tools](https://github.com/cartesi/machine-emulator-tools/).
232 changes: 232 additions & 0 deletions linux/libdriver/base/abi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
#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_bool(evm_buf_t *me, bool value)
{
uint8_t boolean = !!value;
return evm_abi_put_uint(me, sizeof(boolean), &boolean);
}

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, const void *start)
{
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 - (uint8_t *)start;
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, const void *start)
{
int rc;
evm_buf_t res[1];

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

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

uint32_t evm_abi_peek_funsel(evm_buf_t *me)
{
if (evm_buf_length(me) < 4)
return 0;
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_bool(evm_buf_t *me, bool *value)
{
int rc;
uint8_t boolean = 0;
if ((rc = evm_abi_put_uint(me, sizeof(boolean), &boolean)))
return rc;
*value = boolean;
return 0;
}

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

int evm_abi_peek_bytes_d(const evm_buf_t *start, 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;

/* from the beginning, after funsel */
evm_buf_t it[1] = {{start->p + offset, start->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(const 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 7e030b2

Please sign in to comment.