Instantiating computation

Section Goal
  • implement smart contract instantiate method to start the Descartes computation
  • understand Descartes parameters

After creating our basic HelloWorld DApp project and building our Hello World Cartesi Machine, we can now implement the method that actually instantiates and triggers the specified computation from an Ethereum smart contract.

To do that, open the helloworld/contracts/HelloWorld.sol file and add the following code:

bytes32 templateHash = 0x3f5762be44332cb56188fc77b8ac02472399dabe610cebc9d75aae3f77a755a7;
uint64 outputPosition = 0x9000000000000000;
uint8 outputLog2Size = 5;
uint256 finalTime = 1e11;
uint256 roundDuration = 51;
DescartesInterface.Drive[] drives;

Let's go into some detail over these declarations. First of all, templateHash can be understood as an identifier of the computation we intend to perform, and effectively corresponds to the initial hash that was computed for our Hello World Cartesi Machine template. In other words, the hash 0x3f5762be... represents the complete initial state of our computation, and can be used by the Descartes nodes to securely trigger that computation off-chain.

The second declaration, outputPosition, bears a little more in-depth understanding of Cartesi Machines. As thoroughly described in the Cartesi Machine command line section, flash drives are by default set to start at the beginning of the second half of the machine's address space, with a separation of 260 bytes between each drive. As discussed here, the first drive is by default the one containing the machine's root file system, which thus starts at address 0x8000000000000000. Therefore, the next drive, which corresponds to the output drive defined for our HelloWorld computation, shall be set to start at address 0x9000000000000000. Should there be more drives in our DApp, they would subsequently be located at addresses 0xA000000000000000, 0xB000000000000000, and so forth. Complementing this information, the outputLog2Size declaration represents the log2 of the output drive's size, given in bytes. As such, the provided value of 5 means that the output drive has a total size of just 32 bytes.

After that, finalTime corresponds to a maximum limit of cycles allowed for the computation to execute. In our case, we can set it to value 1e11, which is more than enough to run our Hello World machine. Additionally, roundDuration corresponds to the amount of time allowed for each actor (claimer and challenger) to respond, and is given in seconds. Finally, the drives declaration allows for the definition of additional input drives, which will not be needed for our first DApp.

With those declarations all set up, we can finally implement our instantiate method to trigger the computation:

function instantiate(address[] memory parties) public returns (uint256) {
return descartes.instantiate(
finalTime,
templateHash,
outputPosition,
outputLog2Size,
roundDuration,
parties,
drives
);
}

The method receives as arguments the addresses of the parties that will execute and validate the computation, otherwise known as the claimer and challenger nodes. In our development environment, these will correspond to the addresses for alice and bob.

The instantiation itself simply calls the corresponding method in the Descartes smart contract. This will trigger a transaction in the Ethereum network, requesting the specified computation to be carried out off-chain by the specified actors. Descartes will ensure that the appropriate nodes automatically step in to perform the computation, resolve any disputes, and finally validate the result.

At last, we should note that our method has a uint256 return value. This value corresponds to an index for this HelloWorld computation instance, which can later be used to retrieve results as explained in the next section.