From 75d2d20dcf2c02563ae74d00fa5bf8387cfccaa3 Mon Sep 17 00:00:00 2001 From: juztamau5 Date: Mon, 26 Feb 2024 19:49:58 -0800 Subject: [PATCH] Import initial sunodo project from cpp template Generated by @sunodo/cli v0.10.4 --- .github/workflows/clang-format-check.yml | 35 +++++ .gitignore | 1 + Dockerfile | 64 +++++++++ src/.clang-format | 92 ++++++++++++ src/backend/.gitignore | 2 + src/backend/Makefile | 22 +++ src/backend/dapp.cpp | 171 +++++++++++++++++++++++ 7 files changed, 387 insertions(+) create mode 100644 .github/workflows/clang-format-check.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 src/.clang-format create mode 100644 src/backend/.gitignore create mode 100644 src/backend/Makefile create mode 100644 src/backend/dapp.cpp diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml new file mode 100644 index 000000000..0f37bd49c --- /dev/null +++ b/.github/workflows/clang-format-check.yml @@ -0,0 +1,35 @@ +################################################################################ +# +# Copyright (C) 2024 retro.ai +# This file is part of retro3 - https://github.com/retroai/retro3 +# +# SPDX-License-Identifier: AGPL-3.0-or-later +# See the file LICENSE.txt for more information. +# +################################################################################ + +name: Clang Format Check + +on: [push, pull_request] + +jobs: + format: + # The type of runner that the job will run on + runs-on: ubuntu-22.04 + + defaults: + run: + # Set the working directory to src folder + working-directory: src + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Clang Format + run: sudo apt-get install -y clang-format-15 + + - name: Run Clang Format + run: | + find . -regex '.*\.\(cpp\|hpp\)' -exec clang-format-15 -style=file -i {} \; + git diff --exit-code --color diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..964a43755 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.sunodo diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..042b6cfff --- /dev/null +++ b/Dockerfile @@ -0,0 +1,64 @@ +# syntax=docker.io/docker/dockerfile:1.4 +################################################################################ +# +# Copyright (C) 2024 retro.ai +# This file is part of retro3 - https://github.com/retroai/retro3 +# +# This file is derived from Sunodo under the Apache 2.0 License +# Copyright (C) 2023-2024 Sunodo (https://docs.sunodo.io) +# +# SPDX-License-Identifier: AGPL-3.0-or-later AND Apache-2.0 +# See the file LICENSE.txt for more information. +# +################################################################################ + +# +# builder +# + +FROM --platform=linux/riscv64 riscv64/ubuntu:22.04 as builder + +RUN <' + Priority: 6 + - Regex: '(["/]PlatformDefs|"(system|system_gl|system_egl))\.h"' + Priority: 5 + - Regex: '"platform/[^/]+/' + Priority: 2 + - Regex: '^<[a-z0-9_]+>$' + Priority: 3 + - Regex: '^<(assert|complex|ctype|errno|fenv|float|inttypes|iso646|limits|locale|math|setjmp|signal|stdalign|stdarg|stdatomic|stdbool|stddef|stdint|stdio|stdlib|stdnoreturn|string|tgmath|threads|time|uchar|wchar|wctype)\.h>$' + Priority: 3 + - Regex: '^<' + Priority: 4 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '$' +IndentCaseLabels: true +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60000 +PointerAlignment: Left +ReflowComments: false +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 8 +UseTab: Never +... diff --git a/src/backend/.gitignore b/src/backend/.gitignore new file mode 100644 index 000000000..757f93807 --- /dev/null +++ b/src/backend/.gitignore @@ -0,0 +1,2 @@ +# Build files +/dapp diff --git a/src/backend/Makefile b/src/backend/Makefile new file mode 100644 index 000000000..3ef30c99f --- /dev/null +++ b/src/backend/Makefile @@ -0,0 +1,22 @@ +################################################################################ +# +# Copyright (C) 2024 retro.ai +# This file is part of retro3 - https://github.com/retroai/retro3 +# +# This file is derived from Sunodo under the Apache 2.0 License +# Copyright (C) 2023-2024 Sunodo (https://docs.sunodo.io) +# +# SPDX-License-Identifier: AGPL-3.0-or-later AND Apache-2.0 +# See the file LICENSE.txt for more information. +# +################################################################################ + +CXX := g++ + +.PHONY: clean + +dapp: dapp.cpp + $(CXX) -pthread -std=c++17 -I /opt/riscv/kernel/work/linux-headers/include -o $@ $^ + +clean: + @rm -rf dapp diff --git a/src/backend/dapp.cpp b/src/backend/dapp.cpp new file mode 100644 index 000000000..62a2e714f --- /dev/null +++ b/src/backend/dapp.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2024 retro.ai + * This file is part of retro3 - https://github.com/retroai/retro3 + * + * This file is derived from Sunodo under the Apache 2.0 License + * Copyright (C) 2023-2024 Sunodo (https://docs.sunodo.io) + * + * SPDX-License-Identifier: AGPL-3.0-or-later AND Apache-2.0 + * See the file LICENSE.txt for more information. + */ + +#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; +}