Program reference

The accounts, instructions, events and errors of the curta program.

Accounts

AccountKindHolds
ConfigPDA, one per programThe authority, the FeeVault address, the turn reward in lamports and the protocol share rate in basis points.
ModelKeypair account, one per modelThe publisher, the ModelVault address, the configuration, the name, the royalty per token, the weights hash, the sealed flag and sealing progress, one descriptor per weight account (address, length, bytes written), and counters of runs opened, tokens settled and royalties settled.
weight accountsKeypair accounts, two or more per modelOne section of the model each: the tokenizer and lookup tables in section zero, the matrices in the others. The header names the model and the section and carries the upload bitmap.
ModelVaultPDA, one per modelThe model’s settled royalties, until the publisher claims them.
RunKeypair account, one per runThe opener, the model, the Config address, the state and settled flag, the parameters, the turn reward, royalty and protocol share rate in force when it opened, the budget deposited and remaining, the rewards paid, the royalty and protocol share accrued, the turn and token counts, the cost of the next turn, and the working state: prompt, activations, attention cache, output token ids and text bytes.
FeeVaultPDA, one per programThe settled protocol share. No key signs for it.

Account tags and sizes

Account data is little-endian, and each account opens with an 8-byte tag that names its type.

AccountTagSize
ConfigCURTACFG128 bytes
ModelCURTAMDL4,096 bytes
RunCURTARUN256-byte header, then the working state
weight accountCURTAWGT2,048-byte header, then the section’s bytes
ModelVaultCURTAVLT8 bytes
FeeVaultCURTAFEE8 bytes

The state byte of a Run reads 0 for running, 1 for starved, 2 for complete and 3 for cancelled. Call from a program shows the reader that decodes a Run for you. The SDK decodes each account with decodeConfig, decodeModel, decodeWeights and decodeRun.

Program addresses

AccountSeedsSDK helper
Config"config"configAddress
FeeVault"fee"feeVaultAddress
ModelVault"model-vault", the model’s addressmodelVaultAddress
event authority"__event_authority"eventAuthorityAddress

Model, weight and run accounts are keypair accounts. A System instruction at the top level of the transaction creates each one at its full size, owned by the curta program.

Instructions

InstructionWho signsWhat it does
init_configThe program’s upgrade authorityCreates the Config account and the FeeVault.
set_configThe authoritySets the turn reward and the protocol share rate for runs opened afterwards.
create_modelThe publisher and the model keypairWrites the Model account with its configuration, name, royalty, weights hash and weight account descriptors, and creates the ModelVault.
write_weightsThe publisherWrites one 800-byte chunk into a weight account and sets its bit in the upload bitmap. The last chunk of a section is the remainder.
seal_modelThe publisherHashes the next 65,536 bytes of the written weights into the running hash and validates 512 tokenizer entries. The step that reaches the end compares the running hash with the weights hash and seals the model.
set_royaltyThe publisherSets the model’s royalty per token for runs opened afterwards.
claim_royaltiesThe publisherMoves lamports from the ModelVault to the publisher. An amount of zero claims the whole balance above the vault’s rent.
open_runThe opener, a wallet or a program’s PDAOpens a Run on a sealed model in a run account created earlier in the transaction, which holds its rent plus the budget. Records the rates in force and the cost of the first turn.
turnAnyoneAdvances the run’s forward pass, pays the signer the turn reward from the budget and accrues the royalty and protocol share.
fundAnyoneMoves SOL from the signer into the budget of a running or starved run.
cancelThe openerMarks a running or starved run cancelled.
settleAnyoneMoves a complete or cancelled run’s accrued royalty to the ModelVault and its accrued protocol share to the FeeVault, once, and adds the run’s tokens and royalty to the model’s counters.
close_runThe openerCloses a settled Run and returns every lamport in it to the opener: the unspent budget and the rent.

Runs and turns follows the run instructions through a run’s life, and Publish a model the model instructions.

Accounts and arguments

Instruction data is a one-byte tag, the instruction’s position in this table counted from zero, followed by the arguments in little-endian. Every instruction’s account list ends with two more read-only accounts: the event authority and the curta program.

TagInstructionAccounts, in orderArguments
0init_configauthority (signer, writable), config (writable), feeVault (writable), System program, programDataturn reward u64, protocol share basis points u16, config bump u8, fee bump u8
1set_configauthority (signer), config (writable)turn reward u64, protocol share basis points u16
2create_modelpublisher (signer, writable), model (signer, writable), modelVault (writable), System programroyalty u64, configuration (seven u32), name length u8, name UTF-8 of up to 64 bytes, weights hash 32 bytes, section count u32, then per section: weight account address and length u64
3write_weightspublisher (signer), model (writable), weights (writable)section u32, offset u64, chunk bytes
4seal_modelpublisher (signer), model (writable), weights (the section being sealed)expected step u64
5set_royaltypublisher (signer), model (writable)royalty u64
6claim_royaltiespublisher (signer, writable), model, modelVault (writable)amount u64
7open_runopener (signer, writable), model (writable), run (writable), config, metadata (the model’s section zero weight account), System programmax tokens u32, temperature Q16 u32, seed u64, budget u64, prompt length u32, prompt UTF-8
8turncranker (signer, writable), run (writable), model, config, metadata, weights (the first matrix section the turn reads), then the second matrix section when the turn reads twoexpected turn u64, nonce u64, weight account count u8 (1 or 2)
9fundfunder (signer, writable), run (writable), System programamount u64
10cancelopener (signer), run (writable)none
11settlecaller (signer), run (writable), model (writable), modelVault (writable), feeVault (writable), confignone
12close_runopener (signer, writable), run (writable)none

The SDK builds each one with a function named after it: openRunInstruction, turnInstruction, settleInstruction and so on. instructionNames and instructionAccounts list the names and account orders, and decodeInstruction reads instruction data back into them.

What a turn write-locks

A turn write-locks two accounts: the run and its signer. The model and its weight accounts are read-only in a turn, so turns on different runs execute in parallel, including runs on the same model.

The vaults receive lamports in settle, and claim_royalties pays out of the ModelVault.

Events

Every instruction emits one event as a signed inner call from the program to itself, with the event authority as signer. The event data is the 8-byte tag e445a52e51cb9a1d, the instruction’s tag as one byte, three addresses (the account acted on, the signer and a related account), six u64 values, a token count as u32 and that many token ids as u32.

A turn event carries the new turn count, the reward paid, the royalty accrued, the protocol share accrued, the budget remaining and the run’s state, with the id of every token the turn completed. The SDK reads events with decodeEvent.

Errors

The program’s errors, in the order the program declares them. The first has code 6000 and each one after it the next number.

CodeErrorWhat it means
6000InvalidInstructionThe instruction tag is unknown or the arguments do not decode: wrong length, an empty weight chunk, a fund amount of zero, or a weight account count other than 1 or 2.
6001InvalidAccountThe account list has the wrong length, an account is not at the address the program derives, its tag is not the expected one, or its writable flag is wrong.
6002MissingSignatureAn account that must sign did not sign.
6003InvalidOwnerAn account is not owned by the curta program.
6004InvalidSizeAn account’s data length, or a weight chunk’s length, is not the one the instruction requires.
6005AlreadyInitializedAn account that must be new already holds data.
6006InvalidAuthorityThe signer is not the Config authority, the model’s publisher or the run’s opener, whichever the instruction requires. For init_config, the signer is not the program’s upgrade authority.
6007InvalidStateThe model or run is not in the state the instruction needs: a write after sealing began, a run opened on an unsealed model, a turn on a run that is not running, a fund or cancel on a run that has ended, or a settle on a run that is still open or already settled.
6008InvalidConfigA turn reward of zero, a protocol share above 10,000 basis points, a model configuration outside the supported ranges, or a prompt length or max tokens outside what a run allows.
6009InvalidModelThe model name is empty, longer than 64 bytes or not UTF-8, or the model and Config passed are not the ones the run records.
6010InvalidWeightsA weight account is not the one the model names for that section, its contents do not match the model, a chunk differs from bytes already written, a section is unwritten at sealing, or a turn names sections other than the ones its position needs.
6011InvalidOffsetA write offset is not a multiple of 800, or a seal step is not the model’s current step.
6012HashMismatchThe hash of the written weights differs from the weights hash the model declared.
6013ArithmeticOverflowA lamport sum or product exceeds 64 bits.
6014InsufficientBudgetA turn’s charge exceeds the run’s remaining budget.
6015StaleTurnThe turn names a turn index the run has already passed, because another turn landed first.
6016CoreErrorThe inference core returned an error for the step.
6017NotSettledclose_run was sent for a run that has not settled.
6018InvalidEventThe event authority account is not the program’s, or an event instruction is malformed.
6019InsufficientFundsAn account holds fewer lamports than the instruction needs: a run account below its rent plus the budget, a model account below its rent, or a claim above the vault’s balance.

The SDK exports the names as PROGRAM_ERRORS, and decodeProgramError turns a code into its name. A transaction the program rejects shows its reason on the site, at the action that sent it.