This repository contains the Python bindings for the Cartesi machine guest library (libcmt). The bindings expose libcmt’s C API (rollup I/O, ABI, Merkle trees, buffers, etc.) for utilization in python applications as an object. The library is written in cython and it should be compiled for the system. This would serve as an alternative to the HttpServer and offer methods to manage a Cartesi application instance.
The repo includes:
- Library:
pycmt— the main cython library definition. - Sample apps:
echo_app(handles asset deposit and voucher emission) andapp_template(minimal starter). - Cartesi config:
cartesi.echoApp.tomlfor building and running the echo app in the Cartesi machine. - Tests:
/testsUtilizes cartesapp to test the sample application which uses the libcmt-python-bindings.
- Docker — for building the RISC-V image and running the Cartesi machine.
- Python 3.8+ — for the test suite (cartesapp).
You can use pip to install:
pip3 install pycmt --find-links https://prototyp3-dev.github.io/pip-wheels-riscv/wheels/Note: the wheels are already compiled at https://prototyp3-dev.github.io/pip-wheels-riscv/wheels/. Alternatively you can install directly from the repo:
pip3 install pycmt@git+https://github.com/Mugen-Builders/libcmt-binding-pythonThe following snippets show how to use the libcmt Python bindings. A more detailed use can be found on the echo app.
Creating a rollup and main request loop:
from pycmt import Rollup
rollup = Rollup()
# Main loop
while True:
next_request_type = rollup.finish(True)Handling an advance request (read input, optionally emit voucher/notice):
from pycmt import Rollup
def handle_advance(rol):
advance = rol.read_advance_state()
msg_sender = advance['msg_sender'].hex().lower()
print(f"[app] Received advance request from {msg_sender=} with length {len(advance['payload']['data'])}")
return True
rollup = Rollup()
accept_previous_request = True
# Main loop
while True:
next_request_type = rollup.finish(accept_previous_request)
if next_request_type == 'advance':
accept_previous_request = handle_advance(rollup):Handling an inspect request (read-only query):
from pycmt import Rollup
def handle_inspect(rol):
advance = rol.read_advance_state()
print(f"[app] Received inspect request with length {len(advance['payload']['data'])}")
return True
rollup = Rollup()
accept_previous_request = True
# Main loop
while True:
next_request_type = rollup.finish(accept_previous_request)
if next_request_type == 'inspect':
accept_previous_request = handle_inspect(rollup):Emitting a notice (data that can be validated on-chain):
from pycmt import Rollup
rollup = Rollup()
# Main loop
while True:
next_request_type = rollup.finish(True)
if next_request_type == 'advance':
# payload in bytes
rollup.emit_notice(b'Hello')Emitting a voucher (transaction to be executed on L1):
from pycmt import Rollup
rollup = Rollup()
# Main loop
while True:
next_request_type = rollup.finish(True)
if next_request_type == 'advance':
# address_hex: 20-byte destination (40 hex chars), e.g. "0x..."
# value: int ETH value
# payload: calldata
rollup.emit_voucher(
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
1_000_000_000_000_000_000,
b''
)Emitting a report (log; not validated on-chain):
from pycmt import Rollup
rollup = Rollup()
# Main loop
while True:
next_request_type = rollup.finish(True)
rollup.emit_report(b'report')Config is in cartesi.echoApp.toml; the root filesystem is built from sample_apps/echo_app/Dockerfile.
Build the machine image (RISC-V):
cartesi build -c "./cartesi.echoApp.toml"Run the Cartesi machine:
cartesi runThis starts the rollup node with the echo app; you can then send deposits, advances and inspect requests to the application.
Tests are written in Python using cartesapp and run inside the Cartesi machine.
Prerequisites: Python 3.12+, virtualenv with cartesapp installed (see Installation).
Run tests (with Cartesi machine emulator):
python3 -m venv .venv
. .venv/bin/activate
pip3 install cartesapp[dev]@git+https://github.com/prototyp3-dev/cartesapp@v1.2.1
cartesapp test --config-file "./cartesi.echoApp.toml" --log-level debug --cartesi-machineThis builds, starts the machine, and runs the test client.
Run tests (pytest only, if you have a running node):
Test modules live in tests/ (e.g. test_echo.py, model.py).
See LICENSE.
