Skip to content

Commit

Permalink
feat!: add value to voucher
Browse files Browse the repository at this point in the history
  • Loading branch information
mpolitzer committed Feb 9, 2024
1 parent d447123 commit 6951d01
Show file tree
Hide file tree
Showing 16 changed files with 746 additions and 864 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Changed
- Added a value field to vouchers
- Tools are now implemented in terms of libcmt
- Added libcmt

## [0.14.1] - 2023-12-18
### Fixed
Expand Down
7 changes: 3 additions & 4 deletions sys-utils/ioctl-echo-loop/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@ RVCXX = $(TOOLCHAIN_PREFIX)g++
RVCOPY = $(TOOLCHAIN_PREFIX)objcopy
RVDUMP = $(TOOLCHAIN_PREFIX)objdump
STRIP = $(TOOLCHAIN_PREFIX)strip
CFLAGS :=-Wall -Wextra -pedantic -O2 \
`PKG_CONFIG_PATH=/usr/riscv64-linux-gnu/lib/pkgconfig pkg-config --cflags libcmt`
LDLIBS := \
`PKG_CONFIG_PATH=/usr/riscv64-linux-gnu/lib/pkgconfig pkg-config --libs libcmt`
CFLAGS +=-Wall -Wextra -pedantic -O2 `pkg-config --cflags libcmt`
LDLIBS += `pkg-config --libs libcmt`

CONTAINER_MAKE := /usr/bin/make
CONTAINER_BASE := /opt/cartesi/tools
Expand All @@ -45,6 +43,7 @@ ioctl-echo-loop.with-toolchain with-toolchain:
extra.ext2.with-toolchain:
$(MAKE) toolchain-exec CONTAINER_COMMAND="$(CONTAINER_MAKE) $@.toolchain"

ioctl-echo-loop: export PKG_CONFIG_PATH ?= /usr/riscv64-linux-gnu/lib/pkgconfig
ioctl-echo-loop: ioctl-echo-loop.c
$(RVCC) $(CFLAGS) -o ioctl-echo-loop ioctl-echo-loop.c $(LDLIBS)
$(STRIP) ioctl-echo-loop
Expand Down
2 changes: 1 addition & 1 deletion sys-utils/ioctl-echo-loop/ioctl-echo-loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ static int write_notices(cmt_rollup_t *me, unsigned count, uint32_t length, cons
static int write_vouchers(cmt_rollup_t *me, unsigned count, uint8_t destination[CMT_ADDRESS_LENGTH]
,uint32_t length, const void *data) {
for (unsigned i = 0; i < count; i++) {
int rc = cmt_rollup_emit_voucher(me, destination, length, data);
int rc = cmt_rollup_emit_voucher(me, CMT_ADDRESS_LENGTH, destination, 0, NULL, length, data);
if (rc) return rc;
}
return 0;
Expand Down
231 changes: 231 additions & 0 deletions sys-utils/libcmt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,234 @@ And finally, a couple of utility modules used by the high level API are also exp

The header files and a compiled RISC-V version of this library can be found [here](https://github.com/cartesi/machine-emulator-tools/).
We also provide `.pc` (pkg-config) files to facilitate linking.

# mock and testing

This library provides a mock implementation of @ref libcmt\_io\_driver that is
able to simulate requests and replies on the host machine.

- Build it with: `make mock.build`.
- Install it with: `make mock.install`, use `PREFIX` to specify the installation path:
(The command below will install the library and headers on `$PWD/_install` directory)
```
make mock.install PREFIX=_install
```

## testing

Use the environment variable @p CMT\_INPUTS to inject inputs into the application compiled with the mock.
Outputs will be written to files with names derived from the input name.

example:
```
CMT_INPUTS="0:advance.bin" ./application
```

The first output will generate the file:
```
advance.output-0.bin
```

The first report will generate the file:
```
advance.report-0.bin
```

The first exception will generate the file:
```
advance.exception-0.bin
```

The (verifiable) outputs root hash:
```
advance.outputs_root_hash.bin
```

inputs must follow this syntax, a comma separated list of reason number followed by a filepath:
```
CMT_INPUTS="<reason-number> ':' <filepath> ( ',' <reason-number> ':' <filepath> ) *"
```

In addition to @p CMT\_INPUTS, there is also the @p CMT\_DEBUG variable. Enable it
for a verbose version of the low level calls.

```
CMT_DEBUG=yes ./application
```

## generating inputs

Inputs and Outputs are expected to be EVM-ABI encoded. Encoding and decoding
can be acheived multiple ways, including writing tools with this library. A
simple way to generate testing data is to use the @p cast tool from
[foundry](http://book.getfoundry.sh/reference/cast/cast.html) and `xxd`.

Encoding an @p EvmAdvance:
```
cast calldata "EvmAdvance(address,uint256,uint256,uint256,bytes)" \
0x0000000000000000000000000000000000000000 \
0x0000000000000000000000000000000000000000 \
0x0000000000000000000000000000000000000000 \
0x0000000000000000000000000000000000000000 \
0x`echo "advance-0" | xxd -p -c0` | xxd -r -p > 0.bin
```

Encoding an @p EvmInspect:
```
cast calldata "EvmInspect(bytes)" \
0x`echo "inspect-0" | xxd -p -c0` | xxd -r -p > 1.bin
```

## parsing outputs

Decoding a @p Voucher:
```
cast calldata-decode "Voucher(address,uint256,bytes)" 0x`xxd -p -c0 "$1"` | (
read address
read value
read bytes
echo "{"
printf '\t"address" : "%s",\n' $address
printf '\t"value" : "%s",\n' $value
printf '\t"bytes" : "%s"\n' $bytes
echo "}"
)
# sh decode-voucher.sh $1 | jq '.bytes' | xxd -r
```

Decoding a @p Notice:
```
cast calldata-decode "Notice(bytes)" 0x`xxd -p -c0 "$1"` | (
read bytes
echo "{"
printf '\t"bytes" : "%s"\n' $bytes
echo "}"
)
# sh decode-notice.sh $1 | jq '.bytes' | xxd -r
```

# binds

This library is intented to be used with programming languages other than C.
They acheive this by different means.

## Go

Go is able to include C headers directly.

The application can be compiled with: `go build main.go`. Assuming that the
mock was installed at `./libcmt-0.1.0`.
(Code below is for demonstration purposes and not intended for production)

```
package main
/*
#cgo CFLAGS: -Ilibcmt-0.1.0/include/
#cgo LDFLAGS: -Llibcmt-0.1.0/lib/ -lcmt
#include "libcmt/rollup.h"
*/
import "C"
import (
"math/big"
"fmt"
"unsafe"
)
func main() {
var rollup C.cmt_rollup_t
err := C.cmt_rollup_init(&rollup)
if err != 0 {
fmt.Printf("initialization failed\n")
}
bytes_s := []byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
}
wei := new(big.Int).SetBytes(bytes_s)
finish := C.cmt_rollup_finish_t{
accept_previous_request: true,
}
for {
var advance C.cmt_rollup_advance_t
err = C.cmt_rollup_finish(&rollup, &finish)
if err != 0 { return; }
err = C.cmt_rollup_read_advance_state(&rollup, &advance);
if err != 0 { return; }
bytes:= wei.Bytes()
size := len(bytes)
C.cmt_rollup_emit_voucher(&rollup,
C.CMT_ADDRESS_LENGTH, &advance.sender[0],
C.uint(size), unsafe.Pointer(&bytes[0]),
advance.length, advance.data)
C.cmt_rollup_emit_report(&rollup, advance.length, advance.data)
}
}
```

## Rust

Rust interop with C requires bindings to be generated, we'll use bindgen to
accomplish this.

Create the initial directory layout with `cargo`, then add the library to it:
```
cargo init --bin cmt
# download the library and extract it into cmt/libcmt-0.1.0
cd cmt
```

Generate the bindings, execute:
```
# join all header files into one.
cat libcmt-0.1.0/include/libcmt/*.h > src/libcmt.h
# generate the bindings
bindgen src/libcmt.h -o src/bindings.rs --allowlist-function '^cmt_.*' --allowlist-type '^cmt_.*' --no-doc-comments -- -I libcmt-0.1.0/include/libcmt
```

Include the bindings to the project, add the following to: `src/lib.rs`
```
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
include!("bindings.rs");
```

Tell cargo to link with the C library, add the following to: `build.rs`
```
fn main() {
println!("cargo:rustc-link-search=libcmt-0.1.0/lib");
println!("cargo:rustc-link-lib=cmt");
}
```

An example of the raw calls to C, add the following to: `src/main.rs`
```
use std::mem;
fn main() {
let mut rollup: cmt::cmt_rollup_t = unsafe { mem::zeroed() };
let rc = unsafe { cmt::cmt_rollup_init(&mut rollup) };
println!("got return value: {}!", rc);
}
```

Messages like the one below most likely mean that cargo didn't find the library
`libcmt.a` or `build.rs` is incomplete:
```
undefined reference to `cmt_rollup_emit_voucher'
```
52 changes: 52 additions & 0 deletions sys-utils/libcmt/doc/examples/abi_multi.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "libcmt/abi.h"
#include "libcmt/buf.h"

// Echo(bytes)
#define ECHO CMT_ABI_FUNSEL(0x5f, 0x88, 0x6b, 0x86)

static int encode_echo(cmt_buf_t *tx, uint32_t funsel, size_t length, void *data) {
cmt_buf_t wr = *tx;
cmt_buf_t of;
void *params_base = wr.begin + 4; // after funsel

// static section
return cmt_abi_put_funsel(&wr, funsel)
|| cmt_abi_put_bytes_s(&wr, &of)
// dynamic section
|| cmt_abi_put_bytes_d(&wr, &of, length, data, params_base)
;
}

static int decode_echo(cmt_buf_t *rx, uint32_t funsel, size_t *length, void **data) {
cmt_buf_t rd = *rx;
cmt_buf_t of;
void *params_base = wr.begin + 4; // after funsel

// static section
return cmt_abi_get_funsel(&wr, funsel)
|| cmt_abi_get_bytes_s(&wr, &of)
// dynamic section
|| cmt_abi_get_bytes_d(&wr, &of, length, data, params_base)
;
}

int f(cmt_buf_t *wr, cmt_buf_t *rd)
{
int rc;
size_t length;
void *data;

if (cmt_buf_length(rd) < 4)
return -ENOBUFS;
switch (cmt_abi_peek_funsel(rd)) {
case ECHO:
rc = decode_echo(rd, CALL, &length, &data);
if (rc) return rc;

rc = encode_echo(wr, CALL, length, data);
if (rc) return rc;

break;
}
return 0;
}
2 changes: 1 addition & 1 deletion sys-utils/libcmt/doc/examples/rollup.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ int main(void) {
break;
}

rc = cmt_rollup_emit_voucher(&rollup, advance.sender, advance.length, advance.data);
rc = cmt_rollup_emit_voucher(&rollup, sizeof advance.sender, advance.sender, 0, NULL, advance.length, advance.data);
if (rc < 0) {
fprintf(stderr, "%s:%d Error on voucher %s (%d)\n", __FILE__, __LINE__, strerror(-rc), (-rc));
break;
Expand Down
Loading

0 comments on commit 6951d01

Please sign in to comment.