Examples
Hello, World!

Hello, World!

Welcome to the first tutorial of Infernet! In this tutorial, we will guide you through the process of setting up and running an Infernet Node, and then demonstrate how to create and monitor off-chain compute jobs and on-chain subscriptions.

Hardware Requirements

Any laptop or desktop computer should be able to run this tutorial.

ℹ️

Infernet Nodes execute containerized workflows. As such, installing and running (opens in a new tab) a modern version of Docker is a prerequisite, regardless of your choice of how to run the node.

Tutorial Video

Web2 off-chain compute

The easiest way to test the Web2 workflow of the Infernet Node is to run the hello-world example container from our Infernet Container Starter (opens in a new tab) repository.

Clone the starter repository

# Clone locally
git clone --recurse-submodules https://github.com/ritual-net/infernet-container-starter
# Navigate to the repository
cd infernet-container-starter

Build the hello-world container

Once inside the repository directory, you can run a simple command to build the hello-world container:

make build-container project=hello-world

Run the hello-world container

With your container built, you can now run a simple command to deploy the hello-world container along with bootstrapping the rest of the Infernet node stack in one go:

make deploy-container project=hello-world

You can quickly observe the containers that are now active by running docker ps in a new Terminal session:

CONTAINER ID   IMAGE                                       COMMAND                  CREATED         STATUS          PORTS                    NAMES
5ee470dc1de5   ritualnetwork/infernet-anvil:1.0.0          "anvil --host 0.0.0.…"   8 seconds ago   Up 8 seconds    0.0.0.0:8545->3000/tcp   infernet-anvil
af6fb2ef81b2   ritualnetwork/hello-world-infernet:latest   "gunicorn app:create…"   8 seconds ago   Up 8 seconds    0.0.0.0:3000->3000/tcp   hello-world
519e68e107be   ritualnetwork/infernet-node:1.3.1           "/app/entrypoint.sh"     9 seconds ago   Up 10 seconds   0.0.0.0:4000->4000/tcp   infernet-node
c38df86e49a6   fluent/fluent-bit:3.1.4                     "/fluent-bit/bin/flu…"   9 seconds ago   Up 10 seconds   2020/tcp, 24224/tcp      infernet-fluentbit
1c943f224fee   redis:7.4.0                                 "docker-entrypoint.s…"   9 seconds ago   Up 10 seconds   0.0.0.0:6379->6379/tcp   infernet-redis

Notice that five different containers are running, including the infernet-node and the hello-world containers.

Create an off-chain compute job

With the relevant containers now running, we can go ahead and create an off-chain compute request using the REST API (opens in a new tab), calling our hello-world container with input data.

curl -X POST http://127.0.0.1:4000/api/jobs \
-H "Content-Type: application/json" \
-d '{"containers": ["hello-world"], "data": {"some": "input"}}'

Immediately, our Infernet Node should response with an ID of the compute job that was created:

{"id": "e45b5ebc-c71e-4ab8-b10f-d1202e7fb16e"}

Collect job status

To check for the current status of the job (including any results or errors), we can poll the /api/jobs (opens in a new tab) endpoint with the ID of our job from above:

curl -X GET "http://127.0.0.1:4000/api/jobs?id=e45b5ebc-c71e-4ab8-b10f-d1202e7fb16e"

Here is the result you can expect:

[
    {
        "id": "e45b5ebc-c71e-4ab8-b10f-d1202e7fb16e",
        "result": {
            "container": "hello-world",
            "output": {
                "output": "hello, world!, your input was: {'source': 1, 'data': {'some': 'input'}}"
            }
        },
        "status": "success"
    }
]

Additional Resources

  1. To look at the node configuration, code, and other resources for the hello-world container, reference the Infernet Container Starter (opens in a new tab) repository.
  2. To build an Infernet-compatible container image, reference the container docs (opens in a new tab).

Web3 on-chain subscriptions

To test the Web3 workflow of the Infernet Node, we will need to scaffold some additional components. Below, we:

  1. Deploy an Anvil (opens in a new tab) local testnet node with the Infernet SDK (opens in a new tab) contracts already setup (via our infernet-anvil (opens in a new tab) image).
  2. Deploy a simple Infernet Consumer contract (opens in a new tab) for our Web3 demo application.
  3. Deploy an Infernet Node ready to service our requests.

Then, once this preliminary infrastructure is setup, we:

  1. Make a subscription request to our newly-deployed consumer contract, creating an on-chain subscription.
  2. Monitor the full lifecycle of the subscription, from the:
  • node listening to the subscription event,
  • to the node processing the subscription,
  • to the node sending the result back to the our consumer contract on-chain.

Clone the starter repository

# Clone locally
git clone --recurse-submodules https://github.com/ritual-net/infernet-container-starter
# Navigate to the repository
cd infernet-container-starter

Build the hello-world container

Once inside the repository directory, you can run a simple command to build the hello-world container:

make build-container project=hello-world

Run the hello-world container

Akin to the Web2 demo above, we will bootstrap all relevant services and infrastructure in one go:

make deploy-container project=hello-world

In another terminal, you can run docker container ls to see a list of the now running containers:

CONTAINER ID   IMAGE                                       COMMAND                  CREATED         STATUS          PORTS                    NAMES
5ee470dc1de5   ritualnetwork/infernet-anvil:1.0.0          "anvil --host 0.0.0.…"   8 seconds ago   Up 8 seconds    0.0.0.0:8545->3000/tcp   infernet-anvil
af6fb2ef81b2   ritualnetwork/hello-world-infernet:latest   "gunicorn app:create…"   8 seconds ago   Up 8 seconds    0.0.0.0:3000->3000/tcp   hello-world
519e68e107be   ritualnetwork/infernet-node:1.3.1           "/app/entrypoint.sh"     9 seconds ago   Up 10 seconds   0.0.0.0:4000->4000/tcp   infernet-node
c38df86e49a6   fluent/fluent-bit:3.1.4                     "/fluent-bit/bin/flu…"   9 seconds ago   Up 10 seconds   2020/tcp, 24224/tcp      infernet-fluentbit
1c943f224fee   redis:7.4.0                                 "docker-entrypoint.s…"   9 seconds ago   Up 10 seconds   0.0.0.0:6379->6379/tcp   infernet-redis

Notice that five different containers are running, including the infernet-node and the hello-world containers. The Anvil node is also running on port 8545.

By default, the infernet-anvil (opens in a new tab) image used deploys the Infernet SDK (opens in a new tab) and other relevant contracts for you:

  • Coordinator: 0x5FbDB2315678afecb367f032d93F642f64180aa3
  • Primary node: 0x70997970C51812dc3A010C7d01b50e0d17dc79C8

Note, that the primary node address assigned is the default second account in Anvil. This account is prefunded with 10,000 ETH with private key: 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d.

Deploy a consumer

Next, we must deploy a consumer contract that implements the simple Infernet SDK interface (opens in a new tab).

Our SaysGM (opens in a new tab) contract is a simple, example consumer. All this contract does is request a compute output from an Infernet Node, and upon receiving the result, use the forge console to print the result. We can deploy this contract via the associated forge project (opens in a new tab).

Anvil logs

During this process, it is useful to look at the logs of the Anvil node to see what's going on. To follow the logs, in a new terminal, run:

docker logs -f infernet-anvil

Deploying the contract

Once ready, to deploy the SaysGM consumer contract, in another terminal, run:

make deploy-contracts project=hello-world

You should expect to see similar Anvil logs:

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

From our logs, we can see that the SaysGM contract has been deployed to address 0x663f3ad617193148711d28f5334ee4ed07016602.

Call the contract

Now, let's call the contract initiating a request to the Infernet Node. In the same terminal, run:

make call-contract project=hello-world

You should first expect to see an initiation transaction sent to the SaysGm contract:

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

Shortly after that you should see another transaction submitted from the Infernet Node which is the result of your on-chain subscription and its associated job request:

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

🎉 Congratulations! You have successfully created an on-chain subscription request!

Next steps

This container is a dummy service with little practical use. Continue to the next tutorials that solve real-world problems by running a variety of ML models!