Truebit is a blockchain enhancement which enables smart contracts to securely perform complex computations in standard programming languages at reduced gas costs. As described in the whitepaper and this graphical, developer-oriented overview, Task Givers can issue computational tasks while Solvers and Verifiers receive remuneration for correctly solving them. You may wish to familiarize yourself with the practical, high-level user guide before proceeding.
This comprehensive Ethereum implementation includes everything you need to create (from C, C++, or Rust code), issue, solve, and verify Truebit tasks. This repo includes the Truebit-OS command line client configurations for solving and verifying tasks, some libraries ported to WebAssembly, an wasm module wrapper for adding runtime hooks, a Rust tool for generating tasks, the off-chain interpreter for executing and snapshotting computations, as well as sample tasks. You can install Truebit using Docker or build it from source for Linux, MacOS, or Windows.
Feel free to browse the legacy wiki, contribute to this repo's wiki, or check out these classic development blog posts:
- Developing with Truebit: An Overview
- Using the Truebit Filesystem
- Truebit Toolchain & Transmute
- Writing a Truebit Task in Rust
- JIT for Truebit
In addition, Truebit's Reddit channel features links to some excellent introductions and mainstream media articles about Truebit. If you'd like to speak with developers working on this project, come say hello on Truebit's Gitter and Discord channels.
- Before you begin: what you will need (Requirements)
- Install Truebit’s Hardhat Framework
- Configuration Overview
- Configure Infura
- Create your Ethereum accounts
- Export Private Keys
- Share your accounts with your environment
- Share your accounts with Hardhat
- Dependencies: Install libraries
- Environment: Test Accounts
- Truebit Commands
- Forking with Ganache
- Hardhat: interacting with Truebit Smart Contracts
- Hardhat Test structure for Truebit
- Task execution using Ganache
- Truebit - Hardhat standard development environment
Make sure you have the following packages properly installed
-
Docker: Developers - Docker (Getting Started)
-
Download and configure TruebitOS Docker Image Solvers/Verifiers Getting Started Guide
-
NodeJS Latest LTS version: Download Node.js
-
Git for your system: Git - Downloads
-
Visual Studio Code: Download VS Code
Clone Truebit’s Hardhat repository; it has pre-configured networks and TruebitOS commands built-in: GitHub - TruebitProtocol/hardhat-truebit
Open the folder with Visual Code (Download VS Code). Truebit’s hardhat repository has a environment variables example file (.env.example
), we will modify it and rename it as .env
. You will modify this file to add your personal keys as you follow along.
~/hardhat-truebit/.env.example
INFURA_KEY=<YOUR_API_KEY>
ACCOUNT_PRIVATE_KEY1 = <YOUR ETHEREUM PRIVATE KEY>
ACCOUNT_PRIVATE_KEY2 = <YOUR ETHEREUM PRIVATE KEY>
ACCOUNT_PRIVATE_KEY3 = <YOUR ETHEREUM PRIVATE KEY>
API_URL=<YOUR URL AND PORT>
Note: As API_URL example, need to change it by your Docker address and port
In order to fork from an Ethereum Goerli or Mainnet, you will need a free account with Infura. Create an account before continuing: Ethereum API | IPFS API & Gateway | ETH Nodes as a Service
Create a New Project
Then press Create
After the creation, click on MANAGE YOUR KEYS button.
Copy the API KEY string, something like this <38c9e686f44946c3 .... f24d664799d1>
Insert your API KEY in the .env
file
INFURA_KEY=<YOUR_API_KEY>
ACCOUNT_PRIVATE_KEY1 = <YOUR ETHEREUM PRIVATE KEY>
ACCOUNT_PRIVATE_KEY2 = <YOUR ETHEREUM PRIVATE KEY>
ACCOUNT_PRIVATE_KEY3 = <YOUR ETHEREUM PRIVATE KEY>
API_URL=<YOUR URL AND PORT>
During TruebitOS setup, you had the chance to create multiple accounts using clef; we will extract the private keys from the JSON files generated by clef. (Please look into TruebitOS Docker setup for more details)
TruebitOS accounts are located inside the folder /root/.ethereum/[goerli | mainnet]/keystore
depending on which network you connected to while creating the accounts with clef. Alternatively, they can be located in the shared folder that you defined when launching the docker run --network host -v $YYY/docker-geth:/root/.ethereum -v .....
For example, for Goerli, you will find:
ls -l /root/.ethereum/goerli/keystore
-rw------- 1 root root 491 Apr 26 13:57 UTC--2022-04-26T13-57-55.369487731Z--2f25f5df360305977fef8f6730883a787785b802
-rw------- 1 root root 491 Apr 27 12:48 UTC--2022-04-27T12-48-24.658746176Z--353510ef7b01b4baad9616ae23d344c5945c6771
-rw------- 1 root root 491 Apr 28 12:13 UTC--2022-04-28T12-13-13.380635292Z--1da28542742614b3ca2941f9dfcd23ffc3cb0071
-rw------- 1 root root 491 May 5 14:27 UTC--2022-05-05T14-27-07.990563701Z--40641bc33cc3b30ab84473b95ca4bbd2ce8a015c
Once you have all the keystore JSON files located you can run the following command for each keystore JSON private key file:
npx hardhat pk --file <RELATIVE_PATH_TO_KEYSTORE_JSON_FILE> --password <PASSWORD_TO_DECRYPT_JSON_PK>
You will receive the address and the private key as the output in string hex format.
You can use as many accounts as you want (create accounts with clef inside the TruebitOS docker), and insert your Ethereum private keys in the file .env. Account #0 corresponds to KEY1, account #1 to KEY2, and so on. You can use as many keys as you need. In the example below we set up accounts: #0, #1, and #2.
INFURA_KEY=38c9e686f4aaaaaaaaa4d664799d1
ACCOUNT_PRIVATE_KEY1 = 2b40c512afsfasf2342aaaaaade5afb3b19af599461e814afab7175e5f6e
ACCOUNT_PRIVATE_KEY2 = 2b30c5dfa3r2g232d32bbbbbbde5afb3b19af599461e814afab7175e5aae
ACCOUNT_PRIVATE_KEY3 = 2b90c5liu23j23'k142ccccccce5afb3b19af599461e814afab7175e5bbe
API_URL=http://localhost:3000
Once you setup your process.env, we need to make Hardhat aware of these accounts; we will modify hardhat.config.js
Look into the networks section, and add the accounts you created in .env; below is an example with the three accounts we created previously. Note that you can reference to the private keys using:
${process.env.ACCOUNT_PRIVATE_KEYn};
where "n" needs to match the numbers you used in .env
.
networks: {
mainnet: {
chainId: 1,
url: `<https://mainnet.infura.io/v3/${process.env.INFURA_KEY}`,> // ${INFURA_KEY} - must be your API key in process.env
// include your accounts PK
accounts: [`${process.env.ACCOUNT_PRIVATE_KEY1}`, `${process.env.ACCOUNT_PRIVATE_KEY2}`, `${process.env.ACCOUNT_PRIVATE_KEY3}`],
},
goerli: {
chainId: 5,
url: `<https://goerli.infura.io/v3/${process.env.INFURA_KEY}`,> // ${INFURA_KEY} - must be your API key in process.env
// include your accounts PK
accounts: [`${process.env.ACCOUNT_PRIVATE_KEY1}`, `${process.env.ACCOUNT_PRIVATE_KEY2}`, `${process.env.ACCOUNT_PRIVATE_KEY3}`],
},
}
Before you can use hardhat, you need to install npm package dependencies; move inside the folder where you cloned hardhat-truebit:
cd hardhat-truebit
npm install
Test the local hardhat environment you should see the accounts you created and configured in the previous step (Share your accounts with Hardhat):
npx hardhat accounts --network localhost
You should see the account you configure in the previous step (Create your Ethereum accounts)
npx hardhat accounts --network goerli
You should see the account you configure in the previous step (Create your Ethereum accounts)
npx hardhat accounts --network mainnet
TruebitOS Smart Contracts have an installation on the Goerli Testnet. Using a faucet, you can get Goerli ETH to run Truebit in the Goerli. Goerli PoW Faucet
For every command, you can select the network with the flag --network
and values localhost / goerli / mainnet
in order to connect the desired network. For this guide purpose, we will execute commands on Ganache local fork network (localhost).
npx hardhat accounts --network localhost
This command will display the fork accounts created by Ganache
npx hardhat balance --a 0 --network localhost
This command will display the account selected balance
npx hardhat bonus --network localhost
This command will display Truebit bonus incentives
npx hardhat license price --network localhost
This command will display the Solver license price in ETH.
npx hardhat license check --a 0 --network localhost
This command will display if the selected account, owns a Solver license or not
npx hardhat license purchase --a 0 --network localhost
This command will purchase a Solver license for the selected account
npx hardhat token price --network localhost
This command will display the TRU token price on ETH, for purchasing and retiring
npx hardhat token purchase --v 1000 --a 0 --network localhost
This command will purchase the desired amount of TRU (--v) into the selected account (--a)
npx hardhat token retire --v 500 --a 0 --network localhost
This command will retire the desired amount of TRU (--v) from the selected account (--a)
npx hardhat token deposit --v 300 --a 0 --network localhost
This command will deposit TRU tokens into your account, to be used for task execution purposes
npx hardhat token withdraw --v 100 --a 0 --network localhost
This command will withdraw TRU tokens from your deposited balance
npx hardhat token transfer-eth --v 3 --a 0 --t 1 --network localhost
This command will transfer the desired amount of ETH (-v) from account (--a) X to account (--t) Y.
npx hardhat token transfer-tru --v 100 --a 0 --t 1 --network localhost
This command will transfer the desired amount of TRU (-v) from account (--a) X to account (--t) Y.
npx hardhat start solver --a 0 --network localhost
This command will initialize a Solver process in the desired account (the account must have a Solver license to act as Solver)
npx hardhat start verifier --a 1 --network localhost
This command will initialize a Verifier process in the desired account
npx hardhat ps --network localhost
This command will display initialized process for Solver’s and Verifier’s with a process index (used to stop the current process)
npx hardhat stop solver --p 0 --network localhost
This command will stop the Solver process (--p) initialized before
npx hardhat stop verifier --p 0 --network localhost
This command will stop the Verifier process (--p) initialized before
npx hardhat process-status solver --p 0 --network localhost
This command will display Solver process logs of the desired process index (--p)
npx hardhat process-status verifier --p 0 --network localhost
This command will display Verifier process logs of the desired process index (--p)
npx hardhat task list --network localhost
This command will display Task Giver account logs of tasks submitted in TruebitOS
npx hardhat task submit --a 2 --f factorial.json --network localhost
This command will submit desired task execution (--f) from the desired account (--a). Here will find detailed information about Task Submit command.
NOTE REGARDING HARDHAT FORKS: Technically Hardhat also allows forking (without Ganache), but the current implementation has some issues with event propagation, and these are needed during task execution so we will only use Ganache for the time being.
Truebit-Hardhat allows you to fork Goerli or Mainnet in a local blockchain that you can use for development. Doing this has several advantages: a) you don’t need to request test tokens on a faucet which can be challenging at times, b) you will get better error reporting from the local fork, and c) transactions are mined and finalized much faster.
Below is a diagram that shows the relationship between Ethereum Goerli or Mainnet with your local fork. It’s important to note that once you stop your local fork all the transactions recorded in it will be lost and a new fork will commence on the latest block of the corresponding Ethereum chain (Goeli or Mainnet).
Ganache communicates with both: Hardhat and TruebitOS Docker through RPC, it in turn communicates with the upstream chain using Infura and the key you created previously.
Before you can use Ganache for local development, you need to install it and launch it; instructions for both tasks are detailed below.
Ganache is distributed as an npm package, you can refer to Ganache’s web page for more details about its configuration and use; to install it, use this command:
npm install ganache --global
To launch Ganache you need to specify two command options:
- Fork URL: This is your Infura endpoint, you should include your Infura API key
- Block Production Time interval: This is needed because TruebitOS assumes that blocks are being produced to calculate timeouts. You can customize this value to your needs; during testing, we found that a 5s interval works in most situations.
You can launch your local blockchain fork like so:
ganache --fork.url https://goerli.infura.io/v3/<YOUR_INFURA_API_KEY> --miner.blockTime 5
NOTE:
if your task needs more than 5 seconds to execute, you can modify the option --miner.blockTime 5
Hardhat commands accept a “network” optional parameter that allows you to indicate which network should resolve the request. you can use any hardhat command with --network localhost to indicate that the command should be directed to Ganache's local fork. For example, to get the token price from your local fork you can use the following:
#token price
npx hardhat token price --network localhost
Normally TruebitOS will connect to either Goerli or Mainnet using a local geth instance; it is possible to direct geth to use your local fork; this will allow you to start and stop solvers and verifiers on the local fork and to submit a task that is resolved using the local fork as well.
To use TruebitOS inside of Docker, start the service like this:
./goerli.sh
(then stop it, you can also use mainnet.sh instead)
Then execute the next command on directory /truebit-eth/
to start TurebitOS with API flag:
script -efq /ethereum/consensus/stdout.log -c "./truebit-os --api -p ws://host.docker.internal:8545"
NOTE: Start goerli.sh or mainnet.sh and stop it, this will set some environment variables and start a demon required for the task execution.
Ganache on Host PC
TruebitOS on Docker
If you need to interact with TruebitOS smart contracts from ethers.js
or web3.js
, you can find the ABIs in the following directories:
/client/goerli.json
/client/mainnet.json
You can write unit tests that interact with Truebit’s Smart Contracts; here is an example of how you could write tests; note the use of Truebit’s Smart Contract ABIs for either Goeli or Mainnet.
/test/truebitLicense.js
First, run a local instance of ethereum blockchain with ganache
- mocha
- chai
- sinon
In the current version of Hardhat Truebit, you need to launch task executions from within TruebitOS (Docker). However, the execution of these tasks can use your local fork if you started TruebitOS as directed above (See: Docker TruebitOS: Connecting to Ganache local fork).
You should have access to Ganache’s default accounts and their funding (1000 ETH each by default, configurable in ganache).
Test that you can access them by issuing the accounts
command from within TruebitOS. Ganache start showing your nine available accounts with From TruebitOS:
Check the account balance:
Quick setup for a task execution: Before issuing a task, make sure you have the appropriate setup, you can type these commands in your hardhat prompt:
npx hardhat token purchase --a 0 --v 1000
npx hardhat token deposit --a 0 --v 1000
npx hardhat token purchase --a 1 --v 1000
npx hardhat token deposit --a 1 --v 1000
npx hardhat token purchase --a 2 --v 1000
npx hardhat token deposit --a 2 --v 1000
npx hardhat license purchase --a 0
npx hardhat start solver --a 0
npx hardhat start verifier --a 1
You can submit a task from Hardhat like so:
npx hardhat task submit --a 2 --f factorial.json --network localhost
This command will submit desired task execution (--f) from the desired account (--a).
In TruebitOS CLI, will display the entire execution, with Task Giver, Solver, and Verifier logs
This project is meant to test Truebit. This section suggest the use of VSCode, but you can use the IDE of your preference.
- Visual Studio Code (latest version)
- Visual Studio Code required extensions:
ESLint:"dbaeumer.vscode-eslint"
,
Prettier-Code Formatter:"esbenp.prettier-vscode"
,
Solidity:"nomicfoundation.hardhat-solidity"
VSCode extesion install command:
code --install-extension <publisher.extension>
- Visual Studio Code recommended extensions:
Back & Forth:"nick-rudenko.back-n-forth"
,
Code Spell Checker:"streetsidesoftware.code-spell-checker"
,
Git Graph:"mhutchie.git-graph"
,
Git History:"donjayamanne.githistory"
,
GitLens — Git supercharged:"eamodio.gitlens"
,
TODO Highlight:"wayou.vscode-todo-highlight"
,
Todo Tree:"gruntfuggly.todo-tree"
, - Nodejs environment:
Hardhat supports the latest LTS version of NodeJS. The project has a package.json property to set the minimum versions of node and npm:"engines": { "npm": ">=8.19.3", "node": ">=18.13.0" },
- Install dependencies:
npm install
- Set in the
.env
file the required environment variables according to what it is indicated in.env.example
file and the use scenario. - Setup and run the Ethereum network and TruebitOS. Please follow the "Getting Started Guide" https://truebit.io/guide/prerequisites/
- Execute the tests or tasks:
Note: Please note that localhost is the default network, so it is not necessary to set it on the commands.
If you want to use a different network please add--network [networkName]
at the end of the commands.
Tests (example):
npx hardhat test
Tasks (example):
npx hardhat accounts
npx hardhat balance --a 0
- Execute ESlint and TypeScript check types:
npm run lint
npm run check-types
- Check for available dependencies updates:
npx ncu
- Pre-commit hook:
This hook will be executed every time you do a commit, and it will execute lint and check-types package.json scripts. If any of those have a finding it won't allow you to finish the commit until you fix the issue.
This configuration is set on package.json"scripts": { "lint": "npx eslint . --ext .ts", "check-types": "npx tsc --noEmit", "ncu": "npx ncu -e 2" }, "pre-commit": { "run": [ "lint", "check-types", "ncu" ], "silent": true, "colors": true }
- Github pull request template
.github/PULL_REQUEST_TEMPLATE.md
This template will show up every time you create a PR as description template. - For coding styling and other rules please see the following configuration files:
.prettierrc
.eslintrc.json
This VSCode workspace configuration file.vscode/settings.json
is set to auto format every time you paste or save a file using the plugin"esbenp.prettier-vscode"
as default formatter.