Drives

This section describes in detail the Drive[] _inputDrives parameter of the instantiate call. It describes an array of Drives, each representing one of the inputs that the machine should receive before executing.

Since Cartesi Machines are deterministic, input drives are necessary to make their calculations interesting: without input drives, whenever the machine is executed it returns the same result to the output drive.

For example, our first Hello World tutorial does exactly that, passing no drives to the instantiate call and always obtaining "Hello World!" as an output.

In order to specify input drives to the machine, one should start by looking at the Drive structure defined in DescartesInterface.sol:

struct Drive {
uint64 position;
uint64 driveLog2Size;
bytes directValue;
bytes32 loggerRootHash;
address provider;
bool waitsProvider;
bool needsLogger;
}

What follows is a description of the fields that compose a Drive.

position refers to the beginning of the drive's representation with respect to the address space of the off-chain machine. The position of a drive is determined when building the Cartesi Machine, as explained previously for the output drive's position.

driveLog2Size similarly to the outputLog2Size parameter described in the previous section, this argument represents the log2 of the input drive's size given in bytes. As such, a value of 10 would represent an input drive with a size of 1024 bytes. This value cannot be smaller than 5 (i.e., the drive size must be at least 32 bytes).

directValue contains actual input data in the form of a variable size bytes array, which can effectively be up to 1024 bytes long.

loggerRootHash identifies data that is not given directly, but instead is stored using the logger functionality. This is used to input larger drives into the machine, and will only be discussed in a later section.

For now, the reader should focus on what happens when the Logger is disabled and in this case only drives of 32 bytes are supported.

At this point, one can already explore an interesting range of applications to Descartes. To do that, let's instantiate a Drive without initializing any of the other fields, such as in this example:

Drive({
position: 0x9000000000000000,
driveLog2Size: 5,
directValue: "Alice",
loggerRootHash: 0,
provider: address(0),
waitsProvider: false,
needsLogger: false,
})

In the above example, a drive is specified at position 0x9000000000000000 and with contents given by the string "Alice". The Linux machine running off-chain will receive this input and will be able to process it as desired.

Note, however, that there are two limitations to this way of dealing with the content of the drives. First, these contents have to be readily available at the time of initialization. Secondly, the drive sizes are in practice bounded by the maximum transaction size imposed by the Ethereum network itself.

The two next sections describe how to overcome each of these limitations.