From 58e15e5d56664d1ea5c55fa4c698a3cca868a68f Mon Sep 17 00:00:00 2001 From: Enderson Maia Date: Wed, 23 Oct 2024 15:04:06 -0300 Subject: [PATCH] feat: update cpp-low-level template --- cpp-low-level/Dockerfile | 25 ++++--- cpp-low-level/Makefile | 31 +++++++- cpp-low-level/dapp.c | 91 ++++++++++++++++++++++ cpp-low-level/dapp.cpp | 158 --------------------------------------- 4 files changed, 134 insertions(+), 171 deletions(-) create mode 100644 cpp-low-level/dapp.c delete mode 100644 cpp-low-level/dapp.cpp diff --git a/cpp-low-level/Dockerfile b/cpp-low-level/Dockerfile index 8b1e62b..7f07c8f 100644 --- a/cpp-low-level/Dockerfile +++ b/cpp-low-level/Dockerfile @@ -1,4 +1,5 @@ # syntax=docker.io/docker/dockerfile:1 +ARG MACHINE_EMULATOR_TOOLS_VERSION=0.16.1 FROM --platform=linux/riscv64 ubuntu:22.04 AS builder ARG DEBIAN_FRONTEND=noninteractive @@ -6,17 +7,19 @@ RUN < +#include +#include +#include +#include +#include +#include + +#include "libcmt/rollup.h" + +static int finish_request(cmt_rollup_t *me, cmt_rollup_finish_t *finish) { + finish->accept_previous_request = true; + return cmt_rollup_finish(me, finish); +} + +static int handle_advance_state_request(cmt_rollup_t *me, uint64_t *index) { + cmt_rollup_advance_t advance; + int rc = cmt_rollup_read_advance_state(me, &advance); + if (rc) + return rc; + *index = advance.index; + fprintf(stderr, "handling advance with index %d\n", (int) advance.index); + return 0; +} + +static int handle_inspect_state_request(cmt_rollup_t *me) { + cmt_rollup_inspect_t inspect; + int rc = cmt_rollup_read_inspect_state(me, &inspect); + if (rc) + return rc; + fprintf(stderr, "handling inspect\n"); + return 0; +} + +static int handle_request(cmt_rollup_t *me, cmt_rollup_finish_t *finish, uint64_t *index) { + switch (finish->next_request_type) { + case HTIF_YIELD_REASON_ADVANCE: + return handle_advance_state_request(me, index); + case HTIF_YIELD_REASON_INSPECT: + return handle_inspect_state_request(me); + default: + /* unknown request type */ + fprintf(stderr, "Unknown request type %d\n", finish->next_request_type); + return -1; + } + return 0; +} + +int main() { + cmt_rollup_t rollup; + uint64_t advance_index = 0; + + if (cmt_rollup_init(&rollup) != 0) + return EXIT_FAILURE; + + /* Accept the initial request */ + cmt_rollup_finish_t finish; + if (finish_request(&rollup, &finish) != 0) { + exit(1); + } + + /* handle a request, then wait for next */ + for (;;) { + if (handle_request(&rollup, &finish, &advance_index) != 0) { + break; + } + if (finish_request(&rollup, &finish) != 0) { + break; + } + } + + cmt_rollup_fini(&rollup); + fprintf(stderr, "Exiting...\n"); + return 1; +} diff --git a/cpp-low-level/dapp.cpp b/cpp-low-level/dapp.cpp deleted file mode 100644 index b52e90b..0000000 --- a/cpp-low-level/dapp.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -// The rollup.h header file specifies how the userspace interacts with the Cartesi Rollup device -// driver. -// This header is provided by the Cartesi version of the Linux kernel and it is bundled with the -// Cartesi toolchain. -// Hence, it is recommended to use the Cartesi Toolchain Docker image to build this example. -// The latest version of this header is available in the Cartesi Linux repository. -// https://github.com/cartesi/linux/blob/linux-5.5.19-ctsi-y/include/uapi/linux/cartesi/rollup.h -extern "C" -{ -#include -} - -// Path to the Cartesi Rollup device driver inside the Cartesi Machine. -#define ROLLUP_DEVICE_NAME "/dev/rollup" - -// To interact with the Cartesi Rollup, it is necessary to open the respective device driver. -// Currently, only one system process can open the Rollup driver at a time. -static int open_rollup_device() -{ - int fd = open(ROLLUP_DEVICE_NAME, O_RDWR); - if (fd < 0) - { - throw std::system_error(errno, std::generic_category(), "unable to open rollup device"); - } - return fd; -} - -static std::string get_ioctl_name(int request) -{ - switch (request) - { - case IOCTL_ROLLUP_WRITE_VOUCHER: - return {"write voucher"}; - case IOCTL_ROLLUP_WRITE_NOTICE: - return {"write notice"}; - case IOCTL_ROLLUP_WRITE_REPORT: - return {"write report"}; - case IOCTL_ROLLUP_FINISH: - return {"finish"}; - case IOCTL_ROLLUP_READ_ADVANCE_STATE: - return {"advance state"}; - case IOCTL_ROLLUP_READ_INSPECT_STATE: - return {"inspect state"}; - case IOCTL_ROLLUP_THROW_EXCEPTION: - return {"throw exception"}; - default: - return {"unknown"}; - } -} - -// Call the ioctl system call to interact with the Cartesi Rollup device driver. -// Currently, that is the only way to interact with the driver. -static void rollup_ioctl(int fd, unsigned long request, void *data) -{ - if (ioctl(fd, request, data) < 0) - { - throw std::system_error(errno, std::generic_category(), "unable to " + get_ioctl_name(request)); - } -} - -static std::string hex(const uint8_t *data, uint64_t length) -{ - std::stringstream ss; - ss << "0x"; - for (auto b : std::string_view{reinterpret_cast(data), length}) - { - ss << std::hex << std::setfill('0') << std::setw(2) << static_cast(b); - } - return ss.str(); -} - -void handle_advance(int fd, rollup_bytes payload_buffer) -{ - struct rollup_advance_state request - { - }; - request.payload = payload_buffer; - rollup_ioctl(fd, IOCTL_ROLLUP_READ_ADVANCE_STATE, &request); - auto data = std::string_view{reinterpret_cast(request.payload.data), request.payload.length}; - std::cout << "[DApp] Received advance request data " << data << std::endl; - // TODO: add application logic here -} - -void handle_inspect(int fd, rollup_bytes payload_buffer) -{ - struct rollup_inspect_state request - { - }; - request.payload = payload_buffer; - rollup_ioctl(fd, IOCTL_ROLLUP_READ_INSPECT_STATE, &request); - auto data = std::string_view{reinterpret_cast(request.payload.data), request.payload.length}; - std::cout << "[DApp] Received inspect request data " << data << std::endl; - // TODO: add application logic here -} - -// Below, the DApp performs a system call finishing the previous Rollup request and asking for the -// next one. -// The Cartesi Machine is paused until the next request is available. -// The finish call returns the type of the next request and the number of bytes of the payload so -// the code can allocate a buffer. -// After the finish call, it is necessary to perform either the read advance or the read inspect -// call to obtain the actual request payload. -// After receiving the payload, the DApp can send notices, vouchers, reports or exceptions to the -// driver. -// Finally, when the DApp finishes to process the request, it must call finish again and restart the -// cycle. -int main(int argc, char **argv) -try -{ - int fd = open_rollup_device(); - struct rollup_finish finish_request - { - }; - finish_request.accept_previous_request = true; - std::vector payload_buffer; - while (true) - { - std::cout << "[DApp] Sending finish" << std::endl; - rollup_ioctl(fd, IOCTL_ROLLUP_FINISH, &finish_request); - auto len = static_cast(finish_request.next_request_payload_length); - std::cout << "[DApp] Received finish with payload length " << len << std::endl; - payload_buffer.resize(len); - if (finish_request.next_request_type == CARTESI_ROLLUP_ADVANCE_STATE) - { - handle_advance(fd, {payload_buffer.data(), len}); - } - else if (finish_request.next_request_type == CARTESI_ROLLUP_INSPECT_STATE) - { - handle_inspect(fd, {payload_buffer.data(), len}); - } - } - close(fd); - return 0; -} -catch (std::exception &e) -{ - std::cerr << "Caught exception: " << e.what() << '\n'; - return 1; -} -catch (...) -{ - std::cerr << "Caught unknown exception\n"; - return 1; -} \ No newline at end of file