Skip to content
This repository was archived by the owner on Mar 12, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions py-basic-crud/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
machine
**/DS_Store
26 changes: 26 additions & 0 deletions py-basic-crud/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2022 Cartesi Pte. Ltd.
#
# SPDX-License-Identifier: Apache-2.0
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use
# this file except in compliance with the License. You may obtain a copy of the
# License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.

MACHINE_DIR := machine

.PHONY: clean console

$(MACHINE_DIR):
@make -C server
@mv server/machine $@

console:
@make -C server console

clean:
@make -C server clean
@rm -rf $(MACHINE_DIR)
154 changes: 154 additions & 0 deletions py-basic-crud/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Simple Python Basic Crud DApp

This example shows how to build and interact with a minimalistic Cartesi Rollups application. This DApp's back-end is written in Python.

## Building the environment

To run the py-basic-crud example, clone the repository as follows:

```shell
$ git clone https://github.com/cartesi/rollups-examples.git
```

Then, build the back-end for the py-basic-crud example:

```shell
$ cd rollups-examples/py-basic-crud
$ make machine
```

## Running the environment

In order to start the containers in production mode, simply run:

```shell
$ docker-compose up --build
```

_Note:_ If you decide to use [Docker Compose V2](https://docs.docker.com/compose/cli-command/), make sure you set the [compatibility flag](https://docs.docker.com/compose/cli-command-compatibility/) when executing the command (e.g., `docker compose --compatibility up`).

Allow some time for the infrastructure to be ready.
How much will depend on your system, but after some time showing the error `"concurrent call in session"`, eventually the container logs will repeatedly show the following:

```shell
server_manager_1 | Received GetVersion
server_manager_1 | Received GetStatus
server_manager_1 | default_rollups_id
server_manager_1 | Received GetSessionStatus for session default_rollups_id
server_manager_1 | 0
server_manager_1 | Received GetEpochStatus for session default_rollups_id epoch 0
```

To stop the containers, first end the process with `Ctrl + C`.
Then, remove the containers and associated volumes by executing:

```shell
$ docker-compose down -v
```

## Interacting with the application

### CLI way

With the infrastructure in place, go to a separate terminal window and send an input as follows:

Go to https://www.online-toolz.com/tools/decode-hex.php and paste there following json:

```json
{
"path": "/users",
"method": "POST",
"payload": {
"name": "John Doe",
"email": "johndoe@example.com"
}
}
```

Copy hex output and replace phrase `<hex>` in below command.

```shell
$ docker exec py-basic-crud-hardhat npx hardhat --network localhost py-basic-crud:addInput --input "0x<hex>"
```

The input will have been accepted when you receive a response similar to the following one:

```shell
Added input '0x...' to epoch '0' (timestamp: ..., signer: 0x..., tx: 0x...)
```

In order to verify the notices generated by your inputs, run the command:

```shell
$ curl http://localhost:4000/graphql -H 'Content-Type: application/json' -d '{ "query" : "query getNotice { GetNotice( query: { session_id: \"default_rollups_id\", epoch_index: \"0\", input_index: \"0\" } ) { session_id epoch_index input_index notice_index payload } }" }'
```

The response should be something like this:

```shell
{"data":{"GetNotice":[{"session_id":"default_rollups_id","epoch_index":"0","input_index":"0","notice_index":"0","payload":"63617274657369da"}]}}
```

### Built-in PHP proxy server

You can simply use Postman or even curl and send `POST` request to `http://localhost:8000/users` with payload

```json
{
"name": "John Doe",
"email": "johndoe@example.com"
}
```

## Advancing time

To advance time, in order to simulate the passing of epochs, run:

```shell
$ docker exec echo_hardhat_1 npx hardhat --network localhost util:advanceTime --seconds 864010
```

## Running the environment in host mode

When developing an application, it is often important to easily test and debug it. For that matter, it is possible to run the Cartesi Rollups environment in [host mode](../README.md#host-mode), so that the DApp's back-end can be executed directly on the host machine, allowing it to be debugged using regular development tools such as an IDE.

The first step is to run the environment in host mode using the following command:

```shell
docker-compose -f docker-compose-host.yml up --build
```
---

The next step is to run the echo server in your machine. The application is written in Python, so you need to have `python3` installed.

In order to start the echo server, run the following commands in a dedicated terminal:

```shell
cd echo/server/
python3 -m venv .env
. .env/bin/activate
pip install -r requirements.txt
HTTP_DISPATCHER_URL="http://127.0.0.1:5004" gunicorn --reload --workers 1 --bind 0.0.0.0:5003 echo:app
```

This will run the echo server on port `5003` and send the corresponding notices to port `5004`. The server will also automatically reload if there is a change in the source code, enabling fast development iterations.

The final command, which effectively starts the server, can also be configured in an IDE to allow interactive debugging using features like breakpoints. In that case, it may be interesting to add the parameter `--timeout 0` to gunicorn, to avoid having it time out when the debugger stops at a breakpoint.

After the server successfully starts, it should print an output like the following:

```
[2022-01-21 12:38:23,971] INFO in echo: HTTP dispatcher url is http://127.0.0.1:5004
[2022-01-21 12:38:23 -0500] [79032] [INFO] Starting gunicorn 19.9.0
[2022-01-21 12:38:23 -0500] [79032] [INFO] Listening at: http://0.0.0.0:5003 (79032)
[2022-01-21 12:38:23 -0500] [79032] [INFO] Using worker: sync
[2022-01-21 12:38:23 -0500] [79035] [INFO] Booting worker with pid: 79035
```

After that, you can interact with the application normally [as explained above](#interacting-with-the-application).

Finally, to stop the containers, removing any associated volumes, execute:

```shell
docker-compose -f docker-compose-host.yml down -v
```
10 changes: 10 additions & 0 deletions py-basic-crud/config/bs-config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[block_subscriber]

# max delay between retries in seconds
max_delay = 64

# max number of retries
max_retries = 5

# timeout for block subscriber in seconds
timeout = 120
18 changes: 18 additions & 0 deletions py-basic-crud/config/indexer-config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[polling_config]

# unique session identifier for machine manager
session_id = "default_rollups_id"

# node starts syncing from inital epoch
initial_epoch = 0

# node starts syncing from epoch index
epoch_index = 0

# polling interval
interval = 10

# end points
postgres_endpoint = "postgres://postgres:password@database/postgres"
state_server_endpoint = "http://state_server:50051"
mm_endpoint = "http://server_manager:5001"
23 changes: 23 additions & 0 deletions py-basic-crud/config/logic-config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[logic_config]

# unique session identifier for machine manager
session_id = "default_rollups_id"

# node starts syncing from inital epoch
initial_epoch = 0

# gas estimation/price multiplier
gas_multiplier = 1
gas_price_multiplier = 1

# number of blocks before resubmting tx
rate = 20

# depth of blocks before considering tx finalized
confirmations = 10

# end points
provider_http_endpoint = "http://hardhat:8545"
ws_endpoint = "ws://hardhat:8545"
state_fold_grpc_endpoint = "http://state_server:50051"
mm_endpoint = "http://server_manager:5001"
13 changes: 13 additions & 0 deletions py-basic-crud/config/sf-config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[state_fold]

# concurrent events fetch for state fold access
concurrent_events_fetch = 16

# genesis block number for state fold access
genesis_block = "0x1"

# query limit error for state fold access
query_limit_error_codes = [-32005]

# number of blocks (depth) before considering state finalized
safety_margin = 1
10 changes: 10 additions & 0 deletions py-basic-crud/config/tm-config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[tx_manager]

# max delay between retries in seconds
max_delay = 64

# max number of retries
max_retries = 5

# timeout for a sent transaction in seconds
transaction_timeout = 5
1 change: 1 addition & 0 deletions py-basic-crud/contracts/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
7 changes: 7 additions & 0 deletions py-basic-crud/contracts/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cache
coverage
deployments/localhost
deployments/*/solcInputs/*.json
dist
export/abi/localhost.json
node_modules
3 changes: 3 additions & 0 deletions py-basic-crud/contracts/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"tabWidth": 4
}
22 changes: 22 additions & 0 deletions py-basic-crud/contracts/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM node:16-buster-slim

# install git
RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get install -y \
git \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /app

# build to bring node_modules
COPY ["package.json", "yarn.lock", "./"]
RUN yarn install --non-interactive

# build app
COPY . .
RUN yarn install --non-interactive

# expose hardhat node port
EXPOSE 8545

ENTRYPOINT ["npx", "hardhat"]
CMD ["node"]
6 changes: 6 additions & 0 deletions py-basic-crud/contracts/config/.dapprc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"inputDuration": 86400,
"challengePeriod": 604800,
"inputLog2Size": 25,
"validators": "0,1,2"
}
6 changes: 6 additions & 0 deletions py-basic-crud/contracts/config/polygon_mumbai/.dapprc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"inputDuration": 86400,
"challengePeriod": 604800,
"inputLog2Size": 25,
"validators": "0"
}
32 changes: 32 additions & 0 deletions py-basic-crud/contracts/deploy/01_rollups.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2022 Cartesi Pte. Ltd.

// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
// this file except in compliance with the License. You may obtain a copy of the
// License at http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

import { DeployFunction } from "hardhat-deploy/types";
import { cosmiconfig } from "cosmiconfig";

const explorer = cosmiconfig("dapp");

const func: DeployFunction = async ({ network, run }) => {
// search for DApp configuration, starting from 'config/{network}' and traversing up
const configResult = await explorer.search(`config/${network.name}`);

// bail out if we don't find a config
if (!configResult || configResult.isEmpty) {
throw new Error("dapp configuration not found");
}

console.log(`dapp configuration loaded from ${configResult.filepath}`);

// deploy Rollups smart contracts
await run("rollups:create", configResult.config);
};

export default func;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
80001
Loading