Skip to content

Commit

Permalink
feat: add rollup test
Browse files Browse the repository at this point in the history
  • Loading branch information
mpolitzer committed Apr 17, 2024
1 parent baed41f commit 0288471
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 8 deletions.
7 changes: 3 additions & 4 deletions sys-utils/libcmt/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ TOOLCHAIN_PREFIX ?= riscv64-linux-gnu-
TARGET_CC := $(TOOLCHAIN_PREFIX)gcc
TARGET_AR := $(TOOLCHAIN_PREFIX)ar
TARGET_CFLAGS := -Wvla -O2 -g -Wall -pedantic -Wextra -Isrc
CFLAGS := -Wvla -O2 -g -Wall -pedantic -Wextra -Isrc
CFLAGS := -fsanitize=address,undefined -pedantic -fstrict-aliasing -Wstrict-aliasing=3 -Wvla -O2 -g -Wall -pedantic -Wextra -Isrc
CC := gcc

all: libcmt host
Expand Down Expand Up @@ -125,7 +125,6 @@ unittests_BINS := \
$(mock_OBJDIR)/buf \
$(mock_OBJDIR)/keccak \
$(mock_OBJDIR)/merkle \
$(mock_OBJDIR)/rollup

$(mock_OBJDIR)/abi-multi: tests/abi-multi.c $(mock_LIB)
$(CC) $(CFLAGS) -o $@ $^
Expand All @@ -145,8 +144,8 @@ $(mock_OBJDIR)/merkle: tests/merkle.c $(mock_LIB)
$(mock_OBJDIR)/rollup: tests/rollup.c $(mock_LIB)
$(CC) $(CFLAGS) -o $@ $^

test: $(unittests_BINS)
$(foreach test,$(unittests_BINS),$(test) &&) true
test: $(unittests_BINS) $(mock_OBJDIR)/rollup
$(foreach test,$(unittests_BINS),$(test) &&) tests/rollup.sh $(mock_OBJDIR)/rollup && true

#-------------------------------------------------------------------------------
tools_OBJDIR := build/tools
Expand Down
26 changes: 23 additions & 3 deletions sys-utils/libcmt/src/io-mock.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,21 @@
#include <stdlib.h>
#include <string.h>

/** track the number of open "devices". Mimic the kernel driver behavior by limiting it to 1 */
static int open_count = 0;

static int read_whole_file(const char *name, size_t max, void *data, size_t *length);
static int write_whole_file(const char *name, size_t length, const void *data);

int cmt_io_init(cmt_io_driver_t *_me) {
if (!_me) {
return -EINVAL;
}
if (open_count) {
return -EBUSY;
}

open_count++;
cmt_io_driver_mock_t *me = &_me->mock;

if (me->tx->begin || me->rx->begin) {
Expand Down Expand Up @@ -68,10 +76,18 @@ void cmt_io_fini(cmt_io_driver_t *_me) {
if (!_me) {
return;
}

if (open_count == 0) {
return;
}

open_count--;
cmt_io_driver_mock_t *me = &_me->mock;

free(me->tx->begin);
free(me->rx->begin);

memset(_me, 0, sizeof(*_me));
}

cmt_buf_t cmt_io_get_tx(cmt_io_driver_t *me) {
Expand Down Expand Up @@ -104,12 +120,16 @@ static int load_next_input(cmt_io_driver_mock_t *me, struct cmt_io_yield *rr) {
size_t file_length = 0;
int rc = read_whole_file(filepath, cmt_buf_length(me->rx), me->rx->begin, &file_length);
if (rc) {
(void) fprintf(stderr, "failed to load \"%s\". %s\n", filepath, strerror(-rc));
if (cmt_util_debug_enabled()) {
(void) fprintf(stderr, "failed to load \"%s\". %s\n", filepath, strerror(-rc));
}
return rc;
}
// NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
if (sscanf(filepath, " %127[^.]%15s", me->input_filename, me->input_fileext) != 2) {
(void) fprintf(stderr, "failed to parse filename: \"%s\"\n", filepath);
if (cmt_util_debug_enabled()) {
(void) fprintf(stderr, "failed to parse filename: \"%s\"\n", filepath);
}
return -EINVAL;
}

Expand Down Expand Up @@ -146,7 +166,7 @@ static int store_output(cmt_io_driver_mock_t *me, const char *filepath, struct c
static int store_next_output(cmt_io_driver_mock_t *me, char *ns, int *seq, struct cmt_io_yield *rr) {
char filepath[128 + 32 + 8 + 16];
// NOLINTNEXTLINE(cert-err33-c, clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
snprintf(filepath, sizeof filepath, "%s.%s%d%s", me->input_filename, ns, *seq++, me->input_fileext);
snprintf(filepath, sizeof filepath, "%s.%s%d%s", me->input_filename, ns, (*seq)++, me->input_fileext);
return store_output(me, filepath, rr);
}

Expand Down
5 changes: 4 additions & 1 deletion sys-utils/libcmt/src/rollup.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,12 @@ int cmt_rollup_emit_voucher(cmt_rollup_t *me, uint32_t address_length, const voi
cmt_buf_t of[1];
void *params_base = tx->begin + 4; // after funsel

if (address_length != CMT_ADDRESS_LENGTH)
return -EINVAL;

// clang-format off
if (DBG(cmt_abi_put_funsel(wr, VOUCHER))
|| DBG(cmt_abi_put_uint_be(wr, address_length, address_data))
|| DBG(cmt_abi_put_address(wr, address_data))
|| DBG(cmt_abi_put_uint_be(wr, value_length, value_data))
|| DBG(cmt_abi_put_bytes_s(wr, of))
|| DBG(cmt_abi_put_bytes_d(wr, of, length, data, params_base))) {
Expand Down
150 changes: 150 additions & 0 deletions sys-utils/libcmt/tests/rollup.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/* Copyright Cartesi and individual authors (see AUTHORS)
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "rollup.h"

void test_rollup_init_and_fini(void)
{
cmt_rollup_t rollup;

// init twice returns failure, same as when using the kernel driver
assert(cmt_rollup_init(&rollup) == 0);
assert(cmt_rollup_init(&rollup) == -EBUSY);
cmt_rollup_fini(&rollup);

// and should reset when closed
assert(cmt_rollup_init(&rollup) == 0);
cmt_rollup_fini(&rollup);

// double free is a bug, but try to avoid crashing
cmt_rollup_fini(&rollup);

// fail to initialize with NULL
assert(cmt_rollup_init(NULL) == -EINVAL);
cmt_rollup_fini(NULL);

printf("test_rollup_init_and_fini passed!\n");
}

static void check_first_input(cmt_rollup_t *rollup)
{
cmt_rollup_advance_t advance;

assert(cmt_rollup_read_advance_state(rollup, &advance) == 0);
assert(advance.chain_id == 1);
// clang-format: off
uint8_t expected_app_contract[CMT_ADDRESS_LENGTH] = {
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02,
};
uint8_t expected_msg_sender[CMT_ADDRESS_LENGTH] = {
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03,
};
char expected_payload[] = "advance-0";
// clang-format: on

// verify the parsed data
assert(memcmp(advance.app_contract, expected_app_contract, CMT_ADDRESS_LENGTH) == 0);
assert(memcmp(advance.msg_sender, expected_msg_sender, CMT_ADDRESS_LENGTH) == 0);
assert(advance.block_number == 4);
assert(advance.block_timestamp == 5);
assert(advance.index == 6);
assert(advance.payload_length == strlen(expected_payload));
assert(memcmp(advance.payload, expected_payload, strlen(expected_payload)) == 0);
}

static void check_second_input(cmt_rollup_t *rollup)
{
cmt_rollup_inspect_t inspect;

char expected_payload[] = "inspect-0";
assert(cmt_rollup_read_inspect_state(rollup, &inspect) == 0);
assert(inspect.payload_length == strlen(expected_payload));
assert(memcmp(inspect.payload, expected_payload, strlen(expected_payload)) == 0);
}

void test_parse_inputs(void) {
cmt_rollup_t rollup;
cmt_rollup_finish_t finish = { .accept_previous_request = true };

assert(cmt_rollup_init(&rollup) == 0);
assert(cmt_rollup_finish(&rollup, &finish) == 0);
check_first_input(&rollup);

assert(cmt_rollup_finish(&rollup, &finish) == 0);
check_second_input(&rollup);

assert(cmt_rollup_finish(&rollup, &finish) == -ENODATA);

cmt_rollup_fini(&rollup);
}

void emit_outputs_reports_and_exceptions(void) {
cmt_rollup_t rollup;
uint64_t index = 0;

// clang-format: off
uint8_t address[CMT_ADDRESS_LENGTH] = {
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01};
// clang-format: on

uint8_t value[] = {0xde, 0xad, 0xbe, 0xef};
char voucher_data[] = "voucher-0";
assert(cmt_rollup_init(&rollup) == 0);
assert(cmt_rollup_emit_voucher(&rollup,
sizeof address, address,
sizeof value, value,
strlen(voucher_data), voucher_data, &index) == 0);
assert(index == 0);

char notice_data[] = "notice-0";
assert(cmt_rollup_emit_notice(&rollup,
strlen(notice_data), notice_data, &index) == 0);
assert(index == 1);

char report_data[] = "report-0";
assert(cmt_rollup_emit_report(&rollup,
strlen(report_data), report_data) == 0);

char exception_data[] = "exception-0";
assert(cmt_rollup_emit_exception(&rollup,
strlen(exception_data), exception_data) == 0);
cmt_rollup_fini(&rollup);
}

int main(void)
{
test_rollup_init_and_fini();
test_parse_inputs();

// binaries must be compared to known good values
emit_outputs_reports_and_exceptions();
return 0;
}
34 changes: 34 additions & 0 deletions sys-utils/libcmt/tests/rollup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash
# create test data on the fly (must match the test)

BIN=$1; shift

[ ! -d build/data/ ] && mkdir build/data/
cast calldata "EvmAdvance(uint256,address,address,uint256,uint256,uint256,bytes)" \
0x0000000000000000000000000000000000000001 \
0x0000000000000000000000000000000000000002 \
0x0000000000000000000000000000000000000003 \
0x0000000000000000000000000000000000000004 \
0x0000000000000000000000000000000000000005 \
0x0000000000000000000000000000000000000006 \
0x`echo -en "advance-0" | xxd -p -c0` | xxd -r -p > build/data/valid-advance.bin

dd if=/dev/zero of=build/data/large-advance.bin bs=1M count=4

echo -en "inspect-0" > build/data/valid-inspect.bin
echo -en "report-0" > build/data/valid-report.bin
echo -en "exception-0" > build/data/valid-exception.bin

cast calldata "Voucher(address,uint256,bytes)" \
0x0000000000000000000000000000000000000001 \
0x00000000000000000000000000000000deadbeef \
0x`echo -en "voucher-0" | xxd -p -c0` | xxd -r -p > build/data/valid-voucher.bin

cast calldata "Notice(bytes)" \
0x`echo -en "notice-0" | xxd -p -c0` | xxd -r -p > build/data/valid-notice.bin

CMT_INPUTS=0:build/data/valid-advance.bin,1:build/data/valid-inspect.bin,0:build/data/large-advance.bin "$BIN"
cmp build/data/valid-voucher.bin none.output-0.bin
cmp build/data/valid-notice.bin none.output-1.bin
cmp build/data/valid-exception.bin none.exception-0.bin
cmp build/data/valid-report.bin none.report-0.bin

0 comments on commit 0288471

Please sign in to comment.