Skip to content
Logo

CartesiMachine

Interface

This is the complete TypeScript interface of a machine object. Descriptions for each method are in the following sections.

export interface CartesiMachine {
    //// Machine Lifecycle
    isEmpty(): boolean;
    isJsonrpcMachine(): boolean;
    create(
        config: MachineConfig,
        runtimeConfig?: MachineRuntimeConfig,
        dir?: string,
    ): void;
    load(
        dir: string,
        runtimeConfig?: MachineRuntimeConfig,
        sharing?: SharingMode,
    ): void;
    cloneEmpty(): CartesiMachine;
    store(dir: string, sharing?: SharingMode): void;
    cloneStored(fromDir: string, toDir: string): void;
    renameStored(fromDir: string, toDir: string): void;
    removeStored(dir: string): void;
    syncStored(dir: string): void;
    destroy(): void;
    
    //// Configuration
    getDefaultConfig(): MachineConfig;
    getInitialConfig(): MachineConfig;
    setRuntimeConfig(runtimeConfig: MachineRuntimeConfig): void;
    getRuntimeConfig(): MachineRuntimeConfig;
    getAddressRanges(): AddressRangeDescription[];
 
    //// Memory Operations
    replaceMemoryRange(rangeConfig: MemoryRangeConfig): void;
    readWord(address: bigint): bigint;
    writeWord(address: bigint, value: bigint): void;
    readMemory(address: bigint, length: bigint): Uint8Array;
    writeMemory(address: bigint, data: Uint8Array): void;
    readVirtualMemory(address: bigint, length: bigint): Uint8Array;
    writeVirtualMemory(address: bigint, data: Uint8Array): void;
    translateVirtualAddress(vaddr: bigint): bigint;
 
    //// Console
    readConsoleOutput(maxLength?: bigint): Uint8Array;
    writeConsoleInput(data: Uint8Array): number;
 
    //// Register Operations
    getRegAddress(reg: Reg): bigint;
    getUarchPristineHash(): Uint8Array;
    readReg(reg: Reg): bigint;
    writeReg(reg: Reg, value: bigint): void;
 
    //// Execution
    run(mcycleEnd?: bigint): BreakReason;
    runUarch(uarchCycleEnd: bigint): UarchBreakReason;
    resetUarch(): void;
 
    //// Root Hash Collection
    collectMcycleRootHashes(
        mcycleEnd: bigint,
        log2McyclePeriod: number,
        mcyclePhase: bigint,
        log2BundleMcycleCount: number,
        previousPartialBundle?: PartialBundle,
    ): McycleRootHashes;
    collectMcycleBundle(
        bundleOffset: bigint,
        log2McyclePeriod: number,
        log2BundleMcycleCount: number,
    ): Uint8Array[];
    collectUarchCycleRootHashes(
        mcycleEnd: bigint,
        log2BundleUarchCycleCount: number,
        revertUarchTail?: Uint8Array[],
    ): UarchCycleRootHashes;
    collectUarchCycleBundle(
        bundleOffset: bigint,
        log2BundleUarchCycleCount: number,
        revertUarchTail?: Uint8Array[],
    ): Uint8Array[];
 
    //// Hash Tree Operations
    getRootHash(): Uint8Array;
    readRevertRootHash(): Uint8Array;
    writeRevertRootHash(hash: Uint8Array): void;
    getNodeHash(address: bigint, log2Size: number): Uint8Array;
    getProof(address: bigint, log2Size: number, log2RootSize?: number): Proof;
    verifyHashTree(): boolean;
    getHashTreeStats(clear?: boolean): HashTreeStats;
 
    //// Execution Log
    logStep(mcycleCount: bigint, logFilename: string): BreakReason;
    logStepUarch(logType: AccessLogType): AccessLog;
    logResetUarch(logType: AccessLogType): AccessLog;
    logSendCmioResponse(
        reason: HtifYieldReason,
        data: Uint8Array,
        logType: AccessLogType,
        revertRootHash?: Uint8Array,
    ): string;
 
    //// Verification
    verifyStepUarch(rootHashBefore: Uint8Array, log: AccessLog): Uint8Array;
    verifyResetUarch(rootHashBefore: Uint8Array, log: AccessLog): Uint8Array;
 
    //// CMIO Operations
    sendCmioResponse(
        reason: HtifYieldReason,
        data: Uint8Array,
        revertRootHash?: Uint8Array,
    ): void;
    receiveCmioRequest(): {
        cmd: HtifYieldCommand;
        reason: HtifYieldReason;
        data: Uint8Array;
    };
 
    //// Address Introspection
    getAddressName(paddr: bigint): string;
}

isEmpty

Checks if the machine object is empty (does not hold a machine instance).

isEmpty(): boolean;

isJsonrpcMachine

Checks if the machine object is a remote machine controlled via the JSON-RPC API.

isJsonrpcMachine(): boolean;

create

Creates a new machine instance from the given configuration and optional runtime configuration. The machine object must be empty. The optional dir sets the directory for on-disk backing stores.

create(
    config: MachineConfig,
    runtimeConfig?: MachineRuntimeConfig,
    dir?: string,
): void;

load

Loads a machine instance from a previously stored directory, with optional runtime configuration. The machine object must be empty. The sharing mode controls whether machine changes stay in-memory (SharingMode.None, the default) or are reflected on-disk.

load(
    dir: string,
    runtimeConfig?: MachineRuntimeConfig,
    sharing?: SharingMode,
): void;

cloneEmpty

Clones an empty machine object from an existing one. The new object is empty and of the same type (local or remote) as the original.

cloneEmpty(): CartesiMachine;

store

Stores the current machine instance to a directory, serializing its entire state. Will not overwrite an existing directory. The sharing mode defaults to SharingMode.All (store the full current state).

store(dir: string, sharing?: SharingMode): void;

cloneStored

Clones a stored machine directory.

cloneStored(fromDir: string, toDir: string): void;

renameStored

Renames a stored machine directory and makes the rename durable. The source and destination must be on the same filesystem.

renameStored(fromDir: string, toDir: string): void;

removeStored

Removes a stored machine directory.

removeStored(dir: string): void;

syncStored

Flushes all files of a previously stored machine to permanent storage. The expected usage is to sync after the machine using the stored files has been closed.

syncStored(dir: string): void;

destroy

Destroys the current machine instance and removes it from the object. Does not delete the machine object itself.

destroy(): void;

getDefaultConfig

Returns the default machine configuration. The returned config is not sufficient to run a machine; additional fields must be set.

getDefaultConfig(): MachineConfig;

getInitialConfig

Returns the initial configuration used to create the current machine instance.

getInitialConfig(): MachineConfig;

setRuntimeConfig

Changes the machine runtime configuration.

setRuntimeConfig(runtimeConfig: MachineRuntimeConfig): void;

getRuntimeConfig

Returns the current machine runtime configuration.

getRuntimeConfig(): MachineRuntimeConfig;

getAddressRanges

Returns a list of all address ranges in the machine.

getAddressRanges(): AddressRangeDescription[];

replaceMemoryRange

Replaces a memory range in the machine. The new range must match an existing range's start and length.

replaceMemoryRange(rangeConfig: MemoryRangeConfig): void;

readWord

Reads a 64-bit word from memory at the given physical address.

readWord(address: bigint): bigint;

writeWord

Writes a 64-bit word to memory at the given physical address.

writeWord(address: bigint, value: bigint): void;

readMemory

Reads a chunk of data from memory at the given physical address and length.

readMemory(address: bigint, length: bigint): Uint8Array;

writeMemory

Writes a chunk of data to memory at the given physical address and length.

writeMemory(address: bigint, data: Uint8Array): void;

readVirtualMemory

Reads a chunk of data from memory at the given virtual address and length, using the current address mapping.

readVirtualMemory(address: bigint, length: bigint): Uint8Array;

writeVirtualMemory

Writes a chunk of data to memory at the given virtual address and length, using the current address mapping.

writeVirtualMemory(address: bigint, data: Uint8Array): void;

translateVirtualAddress

Translates a virtual memory address to its corresponding physical memory address.

translateVirtualAddress(vaddr: bigint): bigint;

readConsoleOutput

Reads and consumes bytes the guest has written to its console. Without a maxLength, everything currently buffered is returned; an empty result means the guest has written nothing since the last call.

The machine has to be configured for it, with console.output_destination: "to_buffer" in its runtime configuration — otherwise this throws. See Terminal for the loop this belongs in.

readConsoleOutput(maxLength?: bigint): Uint8Array;

writeConsoleInput

Appends bytes to the guest's console input, as if they had been typed. Returns how many were accepted: the buffer is finite, so a caller that hands over more than fits keeps the rest for the next call.

The machine has to be configured for it, with console.input_source: "from_buffer" in its runtime configuration, and it has to be unreproducible (processor.registers.iunrep: 1) — what the host types cannot be replayed.

writeConsoleInput(data: Uint8Array): number;

getRegAddress

Returns the address of a register.

getRegAddress(reg: Reg): bigint;

getUarchPristineHash

Returns the Keccak-256 hash of the pristine microarchitecture state (its shadow and RAM), which a uarch reset restores. On a Keccak-256 machine it is the hash-tree node at PmaConstant.UarchStateStart of size 2^PmaConstant.UarchStateLog2Size. Also available as a module-level function.

getUarchPristineHash(): Uint8Array;

readReg

Reads the value of a register.

readReg(reg: Reg): bigint;

writeReg

Writes a value to a register.

writeReg(reg: Reg, value: bigint): void;

run

Runs the machine until the given cycle, or until it yields or halts. If no argument is provided, runs until MAX_MCYCLE (the maximum cycle value), which is equivalent to running until the machine yields or halts.

run(mcycleEnd?: bigint): BreakReason;

Note: MAX_MCYCLE is exported as a constant and can be used to explicitly specify the maximum cycle value.

runUarch

Runs the machine microarchitecture until the given micro cycle or until it halts.

runUarch(uarchCycleEnd: bigint): UarchBreakReason;

resetUarch

Resets the entire microarchitecture state to pristine values.

resetUarch(): void;

collectMcycleRootHashes

Runs the machine until mcycleEnd or a fixed point (a manual yield, a halt or an mcycle overflow), collecting the state root hash after every 2^log2McyclePeriod cycles. With a non-zero log2BundleMcycleCount, each entry is instead the root hash of a bundle of 2^log2BundleMcycleCount consecutive state root hashes. A collection that stops halfway through a period or a bundle is resumed by passing back the mcyclePhase and partialBundle it returned. Past a fixed point, its state root hash (or, for a rejected input, the revert root hash) pads the sequence.

collectMcycleRootHashes(
    mcycleEnd: bigint,
    log2McyclePeriod: number,
    mcyclePhase: bigint,
    log2BundleMcycleCount: number,
    previousPartialBundle?: PartialBundle,
): McycleRootHashes;
 
interface McycleRootHashes {
    hashes: Uint8Array[];
    mcyclePhase: bigint;
    breakReason: BreakReason; // as run() would have returned
    partialBundle?: PartialBundle; // absent when no bundle is in progress
    consoleIoError?: string; // reported, but does not stop collection
}

collectMcycleBundle

Collects the 2^log2BundleMcycleCount state root hashes of a single bundle: bundles are counted from the current mcycle, each spanning 2^(log2McyclePeriod + log2BundleMcycleCount) cycles. Execution first advances to the start of bundle bundleOffset, then samples every 2^log2McyclePeriod cycles; a fixed point reached before the bundle ends fills the rest of it. A machine already at a fixed point is left unchanged.

collectMcycleBundle(
    bundleOffset: bigint,
    log2McyclePeriod: number,
    log2BundleMcycleCount: number,
): Uint8Array[];

collectUarchCycleRootHashes

Runs the machine uarch cycle by uarch cycle until mcycleEnd or a fixed point, resetting the microarchitecture between mcycles, and collects the state root hash after every uarch cycle (or, with a non-zero log2BundleUarchCycleCount, the root hash of each bundle of them). mcycleHashOffsets delimits the entries of each mcycle: within one, the next-to-last entry is the state root hash after the uarch halted, which pads the mcycle, and the last is the state root hash after the reset.

revertUarchTail is the unbundled collection of the machine the revert root hash names, taken while it waited for its input: it has to end with the revert root hash. The emulator needs it whenever the call may run an mcycle that is not a fixed point — any such mcycle could end in a rejected input — or starts at a rejected input.

collectUarchCycleRootHashes(
    mcycleEnd: bigint,
    log2BundleUarchCycleCount: number,
    revertUarchTail?: Uint8Array[],
): UarchCycleRootHashes;
 
interface UarchCycleRootHashes {
    hashes: Uint8Array[];
    mcycleHashOffsets: number[];
    breakReason: BreakReason; // as run() would have returned
}

collectUarchCycleBundle

Collects the 2^log2BundleUarchCycleCount state root hashes of one bundle of the current mcycle, expanded to 2^20 positions, one per uarch cycle: once the uarch halts its state root hash repeats up to the last position, which holds the one after the reset. The machine is left as collectUarchCycleRootHashes leaves it with mcycleEnd one past the current mcycle.

collectUarchCycleBundle(
    bundleOffset: bigint,
    log2BundleUarchCycleCount: number,
    revertUarchTail?: Uint8Array[],
): Uint8Array[];

getRootHash

Obtains the root hash of the current machine state.

getRootHash(): Uint8Array;

getNodeHash

Obtains the hash of a node in the machine state hash tree.

getNodeHash(address: bigint, log2Size: number): Uint8Array;

getProof

Obtains a Merkle proof for a range in the machine state. log2RootSize defaults to 64 (the full state).

getProof(address: bigint, log2Size: number, log2RootSize?: number): Proof;

verifyHashTree

Verifies the integrity of the hash tree against the current machine state.

verifyHashTree(): boolean;

getHashTreeStats

Returns hash tree statistics, optionally clearing the counters.

getHashTreeStats(clear?: boolean): HashTreeStats;

logStep

Runs the machine for the given cycle count and generates a log of accessed pages and proof data.

logStep(mcycleCount: bigint, logFilename: string): BreakReason;

logStepUarch

Runs the machine microarchitecture for one cycle and returns a log of state accesses.

logStepUarch(logType: AccessLogType): AccessLog;

logResetUarch

Resets the microarchitecture state to pristine values and returns a log of state accesses.

logResetUarch(logType: AccessLogType): AccessLog;

logSendCmioResponse

Sends a cmio response and returns a log of state accesses. The revert root hash is recorded as part of the logged input; it defaults to the machine's current root hash.

logSendCmioResponse(
    reason: HtifYieldReason,
    data: Uint8Array,
    logType: AccessLogType,
    revertRootHash?: Uint8Array,
): string;

verifyStepUarch

Note: verifying a big-machine step log (verifyStep) is a module-level function, not a machine method:

import { verifyStep } from "@cartesi/machine";
 
verifyStep(
    rootHashBefore,
    logFilename,
    mcycleCount,
); // returns the obtained root hash after the step, for the caller to check

Checks the validity of a state transition produced by a microarchitecture step log and returns the root hash obtained after the step, for the caller to check.

verifyStepUarch(rootHashBefore: Uint8Array, log: AccessLog): Uint8Array;

verifyResetUarch

Checks the validity of a state transition produced by a microarchitecture reset log and returns the root hash obtained after the reset, for the caller to check.

verifyResetUarch(rootHashBefore: Uint8Array, log: AccessLog): Uint8Array;

sendCmioResponse

Sends a cmio response to a manual yield. The revert root hash is the machine root hash to revert to in case the response is eventually rejected. For advance-state responses it has to match the machine's current root hash when an accepted manual yield is pending — which is what it defaults to — and is ignored otherwise; other responses (inspect-state queries and GIO responses) refuse it. A response the machine is not waiting for, one that does not fit in the rx buffer, or an advance-state response to a yield other than an accepted one is a no-op, exactly as the logged transition is.

sendCmioResponse(
    reason: HtifYieldReason,
    data: Uint8Array,
    revertRootHash?: Uint8Array,
): void;

receiveCmioRequest

Receives a cmio request, including the yield command, reason, and data.

receiveCmioRequest(): {
    cmd: HtifYieldCommand;
    reason: HtifYieldReason;
    data: Uint8Array;
};

readRevertRootHash / writeRevertRootHash

Reads and writes the revert root hash recorded in the shadow state — the root hash verifiers accept for a rejected rollup input.

readRevertRootHash(): Uint8Array;
writeRevertRootHash(hash: Uint8Array): void;

getAddressName

Gets a description of what is at a given target physical address (also available as a module-level function).

getAddressName(paddr: bigint): string;