222 lines
7.7 KiB
Markdown
222 lines
7.7 KiB
Markdown
|
# infernet-container-starter
|
||
|
|
||
|
Starter examples for deploying to infernet.
|
||
|
|
||
|
# Getting Started
|
||
|
|
||
|
To interact with infernet, one could either create a job by accessing an infernet
|
||
|
node directly through it's API (we'll refer to this as an off-chain job), or by
|
||
|
creating a subscription on-chain (we'll refer to this as an on-chain job).
|
||
|
|
||
|
## Requesting an off-chain job: Hello World!
|
||
|
|
||
|
The easiest way to get started is to run our hello-world container.
|
||
|
This is a simple [flask-app](projects/hello-world/container/src/app.py) that
|
||
|
is compatible with `infernet`, and simply
|
||
|
[echoes what you send to it](./projects/hello-world/container/src/app.py#L16).
|
||
|
|
||
|
We already have it [hosted on docker hub](https://hub.docker.com/r/ritualnetwork/hello-world-infernet) .
|
||
|
If you're curious how it's made, you can
|
||
|
follow the instructions [here](projects/hello-world/container/README.md) to build your own infernet-compatible
|
||
|
container.
|
||
|
|
||
|
### Install Docker
|
||
|
|
||
|
To run this, you'll need to have docker installed. You can find instructions
|
||
|
for installing docker [here](https://docs.docker.com/install/).
|
||
|
|
||
|
### Running Locally
|
||
|
|
||
|
First, ensure that the docker daemon is running.
|
||
|
|
||
|
Then, from the top-level project directory, Run the following make command:
|
||
|
|
||
|
```
|
||
|
project=hello-world make deploy-container
|
||
|
```
|
||
|
|
||
|
This will deploy an infernet node along with the `hello-world` image.
|
||
|
|
||
|
### Creating an off-chain job through the API
|
||
|
|
||
|
You can create an off-chain job by posting to the `node` directly.
|
||
|
|
||
|
```bash
|
||
|
curl -X POST http://127.0.0.1:4000/api/jobs \
|
||
|
-H "Content-Type: application/json" \
|
||
|
-d '{"containers":["hello-world"], "data": {"some": "input"}}'
|
||
|
# returns
|
||
|
{"id":"d5281dd5-c4f4-4523-a9c2-266398e06007"}
|
||
|
```
|
||
|
|
||
|
This will return the id of that job.
|
||
|
|
||
|
### Getting the status/result/errors of a job
|
||
|
|
||
|
You can check the status of a job like so:
|
||
|
|
||
|
```bash
|
||
|
curl -X GET http://127.0.0.1:4000/api/jobs?id=d5281dd5-c4f4-4523-a9c2-266398e06007
|
||
|
# returns
|
||
|
[{"id":"d5281dd5-c4f4-4523-a9c2-266398e06007", "result":{"container":"hello-world","output": {"output":"hello, world!, your input was: {'source': 1, 'data': {'some': 'input'}}"}} ,"status":"success"}]
|
||
|
```
|
||
|
|
||
|
### Configuration
|
||
|
|
||
|
This project already comes with a pre-filled config file. The config
|
||
|
file for the hello-world project is located [here](projects/hello-world/container/config.json):
|
||
|
|
||
|
```bash
|
||
|
projects/hello-world/config.json
|
||
|
```
|
||
|
|
||
|
## Requesting an on-chain job
|
||
|
|
||
|
In this section we'll go over how to request an on-chain job in a local testnet.
|
||
|
|
||
|
### Infernet's Anvil Testnet
|
||
|
|
||
|
To request an on-chain job, you'll need to deploy contracts using the infernet sdk.
|
||
|
We already have a public [anvil node](https://hub.docker.com/r/ritualnetwork/infernet-anvil) docker image which has the
|
||
|
corresponding infernet sdk contracts deployed, along with a node that has
|
||
|
registered itself to listen to on-chain subscription events.
|
||
|
|
||
|
* Coordinator Address: `0x5FbDB2315678afecb367f032d93F642f64180aa3`
|
||
|
* Node Address: `0x70997970C51812dc3A010C7d01b50e0d17dc79C8` (This is the second account in the anvil's accounts.)
|
||
|
|
||
|
### Deploying Infernet Node & Infernet's Anvil Testnet
|
||
|
|
||
|
This step is similar to the section above:
|
||
|
|
||
|
```bash
|
||
|
project=hello-world make deploy-container
|
||
|
```
|
||
|
|
||
|
In another terminal, run `docker container ls`, you should see something like this
|
||
|
|
||
|
```bash
|
||
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||
|
c2ca0ffe7817 ritualnetwork/infernet-anvil:0.0.0 "anvil --host 0.0.0.…" 9 seconds ago Up 8 seconds 0.0.0.0:8545->3000/tcp anvil-node
|
||
|
0b686a6a0e5f ritualnetwork/hello-world-infernet:0.0.2 "gunicorn app:create…" 9 seconds ago Up 8 seconds 0.0.0.0:3000->3000/tcp hello-world
|
||
|
28b2e5608655 ritualnetwork/infernet-node:0.1.1 "/app/entrypoint.sh" 10 seconds ago Up 10 seconds 0.0.0.0:4000->4000/tcp deploy-node-1
|
||
|
03ba51ff48b8 fluent/fluent-bit:latest "/fluent-bit/bin/flu…" 10 seconds ago Up 10 seconds 2020/tcp, 0.0.0.0:24224->24224/tcp deploy-fluentbit-1
|
||
|
a0d96f29a238 redis:latest "docker-entrypoint.s…" 10 seconds ago Up 10 seconds 0.0.0.0:6379->6379/tcp deploy-redis-1
|
||
|
```
|
||
|
|
||
|
You can see that the anvil node is running on port `8545`, and the infernet
|
||
|
node is running on port `4000`. Same as before.
|
||
|
|
||
|
### Deploying Consumer Contracts
|
||
|
|
||
|
We have a [sample forge project](./projects/hello-world/contracts) which contains
|
||
|
a simple consumer contract, [`SaysGM`](./projects/hello-world/contracts/src/SaysGM.sol).
|
||
|
All this contract does is to request a job from the infernet node, and upon receiving
|
||
|
the result, it will use the `forge` console to print the result.
|
||
|
|
||
|
**Anvil Logs**: First, it's useful to look at the logs of the anvil node to see what's going on. In
|
||
|
a new terminal, run `docker logs -f anvil-node`.
|
||
|
|
||
|
**Deploying the contracts**: In another terminal, run the following command:
|
||
|
|
||
|
```bash
|
||
|
project=hello-world make deploy-contracts
|
||
|
```
|
||
|
|
||
|
You should be able to see the following logs in the anvil logs:
|
||
|
|
||
|
```bash
|
||
|
eth_sendRawTransaction
|
||
|
eth_getTransactionReceipt
|
||
|
|
||
|
Transaction: 0x23ca6b1d1823ad5af175c207c2505112f60038fc000e1e22509816fa29a3afd6
|
||
|
Contract created: 0x663f3ad617193148711d28f5334ee4ed07016602
|
||
|
Gas used: 476669
|
||
|
|
||
|
Block Number: 1
|
||
|
Block Hash: 0x6b026b70fbe97b4a733d4812ccd6e8e25899a1f6c622430c3fb07a2e5c5c96b7
|
||
|
Block Time: "Wed, 17 Jan 2024 22:17:31 +0000"
|
||
|
|
||
|
eth_getTransactionByHash
|
||
|
eth_getTransactionReceipt
|
||
|
eth_blockNumber
|
||
|
```
|
||
|
|
||
|
We can see that a new contract has been created at `0x663f3ad617193148711d28f5334ee4ed07016602`.
|
||
|
That's the address of the `SaysGM` contract.
|
||
|
|
||
|
### Calling the contract
|
||
|
|
||
|
Now, let's call the contract. In the same terminal, run the following command:
|
||
|
|
||
|
```bash
|
||
|
project=hello-world make call-contract
|
||
|
```
|
||
|
|
||
|
You should first see that a transaction was sent to the `SaysGm` contract:
|
||
|
|
||
|
```bash
|
||
|
eth_getTransactionReceipt
|
||
|
|
||
|
Transaction: 0xe56b5b6ac713a978a1631a44d6a0c9eb6941dce929e1b66b4a2f7a61b0349d65
|
||
|
Gas used: 123323
|
||
|
|
||
|
Block Number: 2
|
||
|
Block Hash: 0x3d6678424adcdecfa0a8edd51e014290e5f54ee4707d4779e710a2a4d9867c08
|
||
|
Block Time: "Wed, 17 Jan 2024 22:18:39 +0000"
|
||
|
eth_getTransactionByHash
|
||
|
|
||
|
```
|
||
|
|
||
|
Then, right after that you should see another transaction submitted by the `node`,
|
||
|
which is the result of the job request:
|
||
|
|
||
|
```bash
|
||
|
eth_chainId
|
||
|
eth_sendRawTransaction
|
||
|
|
||
|
|
||
|
_____ _____ _______ _ _ _
|
||
|
| __ \|_ _|__ __| | | | /\ | |
|
||
|
| |__) | | | | | | | | | / \ | |
|
||
|
| _ / | | | | | | | |/ /\ \ | |
|
||
|
| | \ \ _| |_ | | | |__| / ____ \| |____
|
||
|
|_| \_\_____| |_| \____/_/ \_\______|
|
||
|
|
||
|
|
||
|
subscription Id 1
|
||
|
interval 1
|
||
|
redundancy 1
|
||
|
node 0x70997970C51812dc3A010C7d01b50e0d17dc79C8
|
||
|
input:
|
||
|
0x
|
||
|
output:
|
||
|
0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000607b276f7574707574273a202268656c6c6f2c20776f726c64212c20796f757220696e707574207761733a207b27736f75726365273a20302c202764617461273a20273437366636663634323036643666373236653639366536373231277d227d
|
||
|
proof:
|
||
|
0x
|
||
|
|
||
|
Transaction: 0x949351d02e2c7f50ced2be06d14ca4311bd470ec80b135a2ce78a43f43e60d3d
|
||
|
Gas used: 94275
|
||
|
|
||
|
Block Number: 3
|
||
|
Block Hash: 0x57ed0cf39e3fb3a91a0d8baa5f9cb5d2bdc1875f2ad5d6baf4a9466f522df354
|
||
|
Block Time: "Wed, 17 Jan 2024 22:18:40 +0000"
|
||
|
|
||
|
|
||
|
eth_blockNumber
|
||
|
eth_newFilter
|
||
|
|
||
|
```
|
||
|
|
||
|
We can see that the address of the `node` matches the address of the node in
|
||
|
our ritual anvil node.
|
||
|
|
||
|
### Next Steps
|
||
|
|
||
|
To learn more about on-chain requests, check out the following resources:
|
||
|
|
||
|
1. [Tutorial](./projects/hello-world/contracts/Tutorial.md) on this project's consumer smart contracts.
|
||
|
2. [Infernet Callback Consumer Tutorial](https://docs.ritual.net/infernet/sdk/consumers/Callback)
|
||
|
3. [Infernet Nodes Docoumentation](https://docs.ritual.net/infernet/nodes)
|
||
|
|
||
|
|