Program reference
The accounts, instructions, events and errors of the curta program.
Accounts
| Account | Kind | Holds |
|---|---|---|
| Config | PDA, one per program | The authority, the FeeVault address, the turn reward in lamports and the protocol share rate in basis points. |
| Model | Keypair account, one per model | The 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 accounts | Keypair accounts, two or more per model | One 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. |
| ModelVault | PDA, one per model | The model’s settled royalties, until the publisher claims them. |
| Run | Keypair account, one per run | The 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. |
| FeeVault | PDA, one per program | The 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.
| Account | Tag | Size |
|---|---|---|
| Config | CURTACFG | 128 bytes |
| Model | CURTAMDL | 4,096 bytes |
| Run | CURTARUN | 256-byte header, then the working state |
| weight account | CURTAWGT | 2,048-byte header, then the section’s bytes |
| ModelVault | CURTAVLT | 8 bytes |
| FeeVault | CURTAFEE | 8 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
| Account | Seeds | SDK helper |
|---|---|---|
| Config | "config" | configAddress |
| FeeVault | "fee" | feeVaultAddress |
| ModelVault | "model-vault", the model’s address | modelVaultAddress |
| 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
| Instruction | Who signs | What it does |
|---|---|---|
| init_config | The program’s upgrade authority | Creates the Config account and the FeeVault. |
| set_config | The authority | Sets the turn reward and the protocol share rate for runs opened afterwards. |
| create_model | The publisher and the model keypair | Writes the Model account with its configuration, name, royalty, weights hash and weight account descriptors, and creates the ModelVault. |
| write_weights | The publisher | Writes 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_model | The publisher | Hashes 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_royalty | The publisher | Sets the model’s royalty per token for runs opened afterwards. |
| claim_royalties | The publisher | Moves lamports from the ModelVault to the publisher. An amount of zero claims the whole balance above the vault’s rent. |
| open_run | The opener, a wallet or a program’s PDA | Opens 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. |
| turn | Anyone | Advances the run’s forward pass, pays the signer the turn reward from the budget and accrues the royalty and protocol share. |
| fund | Anyone | Moves SOL from the signer into the budget of a running or starved run. |
| cancel | The opener | Marks a running or starved run cancelled. |
| settle | Anyone | Moves 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_run | The opener | Closes 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.
| Tag | Instruction | Accounts, in order | Arguments |
|---|---|---|---|
| 0 | init_config | authority (signer, writable), config (writable), feeVault (writable), System program, programData | turn reward u64, protocol share basis points u16, config bump u8, fee bump u8 |
| 1 | set_config | authority (signer), config (writable) | turn reward u64, protocol share basis points u16 |
| 2 | create_model | publisher (signer, writable), model (signer, writable), modelVault (writable), System program | royalty 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 |
| 3 | write_weights | publisher (signer), model (writable), weights (writable) | section u32, offset u64, chunk bytes |
| 4 | seal_model | publisher (signer), model (writable), weights (the section being sealed) | expected step u64 |
| 5 | set_royalty | publisher (signer), model (writable) | royalty u64 |
| 6 | claim_royalties | publisher (signer, writable), model, modelVault (writable) | amount u64 |
| 7 | open_run | opener (signer, writable), model (writable), run (writable), config, metadata (the model’s section zero weight account), System program | max tokens u32, temperature Q16 u32, seed u64, budget u64, prompt length u32, prompt UTF-8 |
| 8 | turn | cranker (signer, writable), run (writable), model, config, metadata, weights (the first matrix section the turn reads), then the second matrix section when the turn reads two | expected turn u64, nonce u64, weight account count u8 (1 or 2) |
| 9 | fund | funder (signer, writable), run (writable), System program | amount u64 |
| 10 | cancel | opener (signer), run (writable) | none |
| 11 | settle | caller (signer), run (writable), model (writable), modelVault (writable), feeVault (writable), config | none |
| 12 | close_run | opener (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.
| Code | Error | What it means |
|---|---|---|
| 6000 | InvalidInstruction | The 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. |
| 6001 | InvalidAccount | The 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. |
| 6002 | MissingSignature | An account that must sign did not sign. |
| 6003 | InvalidOwner | An account is not owned by the curta program. |
| 6004 | InvalidSize | An account’s data length, or a weight chunk’s length, is not the one the instruction requires. |
| 6005 | AlreadyInitialized | An account that must be new already holds data. |
| 6006 | InvalidAuthority | The 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. |
| 6007 | InvalidState | The 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. |
| 6008 | InvalidConfig | A 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. |
| 6009 | InvalidModel | The 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. |
| 6010 | InvalidWeights | A 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. |
| 6011 | InvalidOffset | A write offset is not a multiple of 800, or a seal step is not the model’s current step. |
| 6012 | HashMismatch | The hash of the written weights differs from the weights hash the model declared. |
| 6013 | ArithmeticOverflow | A lamport sum or product exceeds 64 bits. |
| 6014 | InsufficientBudget | A turn’s charge exceeds the run’s remaining budget. |
| 6015 | StaleTurn | The turn names a turn index the run has already passed, because another turn landed first. |
| 6016 | CoreError | The inference core returned an error for the step. |
| 6017 | NotSettled | close_run was sent for a run that has not settled. |
| 6018 | InvalidEvent | The event authority account is not the program’s, or an event instruction is malformed. |
| 6019 | InsufficientFunds | An 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.