Skip to content

Commit

Permalink
Import initial sunodo project from cpp template
Browse files Browse the repository at this point in the history
Generated by @sunodo/cli v0.10.4
  • Loading branch information
juztamau5 committed Mar 10, 2024
1 parent 25ca39f commit e0068f7
Show file tree
Hide file tree
Showing 8 changed files with 379 additions and 0 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/clang-format-check.yml
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/.sunodo
48 changes: 48 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# syntax=docker.io/docker/dockerfile:1
################################################################################
#
# 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.
#
################################################################################
FROM --platform=linux/riscv64 riscv64/ubuntu:22.04 as builder

RUN <<EOF
set -e
apt-get update
apt-get install -y --no-install-recommends autoconf automake ca-certificates curl build-essential libtool wget
rm -rf /var/lib/apt/lists/*
EOF

COPY --from=sunodo/sdk:0.2.0 /opt/riscv /opt/riscv
WORKDIR /opt/cartesi/dapp
COPY src/backend .
RUN make

FROM --platform=linux/riscv64 riscv64/ubuntu:22.04

LABEL io.sunodo.sdk_version=0.2.0
LABEL io.cartesi.rollups.ram_size=128Mi

ARG MACHINE_EMULATOR_TOOLS_VERSION=0.12.0
RUN <<EOF
set -e
apt-get update
apt-get install -y --no-install-recommends busybox-static=1:1.30.1-7ubuntu3 ca-certificates=20230311ubuntu0.22.04.1 curl=7.81.0-1ubuntu1.15
curl -fsSL https://github.com/cartesi/machine-emulator-tools/releases/download/v${MACHINE_EMULATOR_TOOLS_VERSION}/machine-emulator-tools-v${MACHINE_EMULATOR_TOOLS_VERSION}.tar.gz \
| tar -C / --overwrite -xvzf -
rm -rf /var/lib/apt/lists/*
EOF

ENV PATH="/opt/cartesi/bin:${PATH}"

WORKDIR /opt/cartesi/dapp
COPY --from=builder /opt/cartesi/dapp/dapp .

ENTRYPOINT ["/opt/cartesi/dapp/dapp"]
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,20 @@ Please note that ROMs are not included and you must obtain them yourself. Most R

## Dependencies

Nodejs, Docker, Sunodo ([Sunodo Docs](https://docs.sunodo.io/guide/introduction/installing)).

Sunodo is a build tool that simplifies the process of building and running Cartesi Machines. It is used to build the Cartesi Machine that runs the game emulator and the learning agent. It is also used to build the website frontend.

For frontend development, the pnpm tool is also used (`npm i -g pnpm`).

## Quick Start

To build the backend, run the command:

```bash
sunodo build
```

To build and run the website frontend, enter the `src/frontend/` directory and use standard pnpm commands:

```bash
Expand Down
92 changes: 92 additions & 0 deletions src/backend/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: DontAlign
AlignOperands: true
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '<EGL/.*\.h>'
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
...
2 changes: 2 additions & 0 deletions src/backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Build files
/dapp
22 changes: 22 additions & 0 deletions src/backend/Makefile
Original file line number Diff line number Diff line change
@@ -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
169 changes: 169 additions & 0 deletions src/backend/dapp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* 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 <cstring>
#include <iomanip>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>

#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>

// 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 <linux/cartesi/rollup.h>
}

// 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<const char*>(data), length})
{
ss << std::hex << std::setfill('0') << std::setw(2) << static_cast<unsigned>(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<const char*>(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<const char*>(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<uint8_t> payload_buffer;
while (true)
{
std::cout << "[DApp] Sending finish" << std::endl;
rollup_ioctl(fd, IOCTL_ROLLUP_FINISH, &finish_request);
auto len = static_cast<uint64_t>(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;
}

0 comments on commit e0068f7

Please sign in to comment.