Cubane Blogs

Engineering

Relational state management on-chain for different types of queries

Cubane does not embed a SQL database in a blockchain. It treats relational semantics as a protocol-level abstraction over deterministic, versioned key-value state, and changes the execution strategy for each query. Ten example statements show how. Not a database inside a chain A common assumption about encrypted relational execution is that it means running a conventional database engine, such as PostgreSQL or MySQL, inside a blockchain node. That is not what Cubane does, and the difference matters for how state changes are managed. We manage state changes on top of a relational abstraction, and the relational abstraction is not the same thing as relational database management. Tables, columns, constraints and joins exist as a contract that developers and the protocol share. Underneath, there is no database server. There is deterministic, versioned key-value state that every node holds and every node can replay. Cubane does not put a conventional SQL database “inside the blockchain.” It makes relational semantics a protocol-level abstraction over deterministic versioned KV state, with the execution strategy changing according to the confidentiality and computational requirements of each query. Abstraction versus management A relational database management system is a piece of software that owns its storage, its locks, its query planner and its access control. It is operated by someone, and the people using it trust that operator. A relational abstraction in Cubane is a set of rules for how relational statements compile into operations on shared state. The rules are part of the protocol. The resulting state transitions are verified the same way as any other transaction, and the storage beneath them is the same versioned key-value store the rest of the chain uses.Two different things Conventional RDBMS Cubane relational abstraction Storage Pages and files on one operator’s machine Deterministic versioned KV state, committed per tick Trust The operator is trusted Every node reaches the same result by replay Concurrency Locks or local MVCC Version vectors (row, tick, branch) shared by all nodes Execution One engine for every query Strategy chosen per query by confidentiality and compute need Privacy Access control around plaintext Per-column scheme, mode and visibility Deletion Rows are removed Tombstone version; erasure by key destruction State changes on the abstraction Every relational statement, whether it reads, inserts, updates or deletes, becomes a set of versioned key-value operations. A read is a load of a specific version at a snapshot tick. A write creates a new version at the current tick. A delete creates a tombstone. Nothing is overwritten in place. The layers that perform this compilation are strictly separated. Each consumes only the layer below and exposes a typed contract upward, and the bottom layer is required to work without knowing whether a value is plaintext or ciphertext.The abstraction stack L1 Statement and canonical ASTDeterministic parse: sorted children, no floating point. L2 Schema registry and column policyTables, constraints and a (scheme, mode, visibility) tuple per column. L3 MVCC and conflict resolutionVersions identified by (row, tick, branch), independent of value. L4 KV and index projectionRows to keys; four index kinds, each with a declared leakage class. L5 Versioned KV state and commitmentsKey, value, version, tombstone. Merkle per tick, KZG per epoch. One statement, text to commitment The path a statement takes is the same for every query type. What changes is the plan produced at the policy step, and therefore which execution strategy runs.Statement lifecycle 01StatementParsed into a canonical syntax tree 02Policy lookupEach column’s scheme, mode and visibility 03PlanStrategy and fee quote fixed before execution 04Versioned opsLoad, Store, Delete, PrefixScan, QueryIndex 05CommitmentNew state root bound into the STU How a strategy is chosen Each column carries one validated tuple. The scheme says how the value is represented: plaintext, FHE ciphertext, ABE-encrypted plaintext or obfuscated plaintext. The mode says how it may be computed on: full FHE, hybrid, proof-only, or MPC and FHE combined. The visibility says who may see it. When encrypted computation is needed, the compiler chooses a scheme from a versioned cost table. TFHE handles comparisons and branches. CKKS handles packed approximate arithmetic such as sums and averages. BGV and BFV handle exact integer arithmetic such as balances. The choice follows a fixed precedence of query pragma, then table, then namespace, then protocol default, so it is never decided at random at runtime. The examples that follow use one illustrative schema and illustrative syntax. The comments under each statement show the plan the abstraction produces.Illustrative schema CREATE TABLE accounts ( account_id BYTES POLICY (plaintext, hybrid, public), branch TEXT POLICY (plaintext, hybrid, public), balance INT64 POLICY (bgv, full_fhe, confidential), amount INT64 POLICY (ckks, full_fhe, confidential) ); CREATE TABLE customers ( customer_id BYTES POLICY (plaintext, hybrid, public), national_id TEXT POLICY (abe, proof_only, compliance), risk_score INT32 POLICY (tfhe, full_fhe, confidential) ); Example 1: public point read The simplest case. Every column involved is public, so no encryption is needed. The index lookup and the load happen against a snapshot at a specific tick, which means every node returns the same value even while new versions are being written.Statement SELECT branch FROM accounts WHERE account_id = :id; — policy accounts.branch (plaintext, hybrid, public) — index plaintext B-tree on account_id — ops QueryIndex -> Load K @ snapshot tick T — output plaintext value Example 2: public aggregate Counting rows by a public column is also a plaintext operation. The abstraction still requires a deterministic plan: the scan order is fixed and the grouping is computed with integer arithmetic, so the result can be reproduced on any node.Statement SELECT branch, COUNT(*) FROM accounts GROUP BY branch; — policy all referenced columns public — strategy plaintext aggregation in the read path — ops PrefixScan over accounts @ tick T — output plaintext counts Example 3: confidential aggregate Here the query mixes visibilities. The planner splits it: the public filter runs as an ordinary predicate, and the sum runs homomorphically over encrypted amounts, packed so that many values are added in a single operation. The result is ciphertext, accompanied by a public zero-knowledge label. Dashboards and indexes consume the label. […]

Mempool-less by design: how DSPE removes ordering discretion

In most chains, whoever builds the block decides the order of transactions. Cubane replaces that decision with a function: admission is order-blind, the pool freezes at each tick, and the canonical order is computed, never chosen. The problem with a choice In most blockchains, a transaction does not go straight from your wallet into a block. It waits in a mempool, a shared buffer of pending transactions, until a block producer picks it up. The producer then decides which transactions to include and in what order. That decision has economic value. Whoever controls ordering can place their own transaction ahead of yours, behind yours, or on both sides of it. The industry has responded in several ways: private relays, order-flow auctions, encrypted mempools, proposer-builder separation. Each of these manages the value of the ordering decision. None of them removes the decision itself. Somebody, somewhere, still chooses. Cubane takes a different position. Ordering is not a decision that any participant makes. It is the output of a deterministic function whose inputs are fixed before anyone can act on them. This article explains how that works, layer by layer, and what it means for the people who submit transactions and the validators who agree on them. Three authorities that never overlap The Cubane transaction pipeline is split across three layers, and each one holds exactly one kind of authority. L0, handled by JetRay, owns admission: it decides whether a transaction is allowed in. L1, handled by DSPE, owns serialisation and execution: it decides the order and computes the resulting state. L2, handled by CCCM, owns validation and finality: it checks proofs and makes the result permanent. The important part is not what each layer does, but what each layer is forbidden to do. JetRay never orders. DSPE never influences who votes. CCCM never modifies execution output and never reorders serialised transactions. Tick boundaries are set by consensus, not by execution. These are written as mandatory invariants, not guidelines, and no single entity controls ingress, ordering, validation and finality together. Separating authority this way closes the gaps that ordering games usually exploit. A validator who can admit, order and finalise has every lever needed to extract value from users. A validator who can only check a proof has none.Three authorities, no overlap L0 JetRay: admission onlyValidates signatures, fees and rate limits. Never orders. L1 DSPE: serialisation and executionSole ordering authority; executes and produces proofs. Never selects validators or moves tick boundaries. L2 CCCM: validation and finalityVerifies proofs, votes and finalises. Never modifies output or reorders.The pipeline, end to end 01 Intake (L0, JetRay)Signature, fee, nonce and rate-limit checks. Accept or reject. No ordering decisions. 02 Tick freezeAdmission closes. The pool is frozen and hashed independently of arrival order. 03 Canonical order (L1, DSPE)A four-key deterministic sort produces the order and the serialisation hash. 04 Parallel execution (L1, DSPE)Conflict-free transactions run in parallel lanes; effects commit in canonical order. 05 State Transition UnitAn immutable artefact with 13 bound fields, including roots and proof. 06 Cube validation (L2, CCCM)Eight-node cubes verify the proof and vote. They cannot change the result. 07 Finality (L2, CCCM)Cube commits are aggregated into a tick root and finalised. Admission is order-blind JetRay is the front door. When a transaction arrives, it checks the signature, the fee, the nonce and the replay window, and applies rate limits at the global, per-sender and per-route level. It then either accepts the transaction into the current tick’s admission pool or rejects it with a typed error. JetRay also assigns transactions to admission lanes, such as priority, fast and standard. It is worth being precise about what a lane does. Under congestion, a lane changes the probability that a transaction is admitted. It does not change where that transaction will sit in the final order. The admission pool that JetRay produces is unordered by design. There is no global mempool behind this. Admission pools are scoped to a single tick, and nothing survives past the tick boundary in a hidden buffer. A transaction that is not admitted waits at the door; it does not wait in a queue that someone else can inspect and front-run. The freeze At each tick boundary, admission closes and the pool is frozen. The frozen pool is identified by a hash computed over the tick identifier and the sorted hashes of every transaction in it. The sort is bytewise and happens before hashing. That detail carries real weight. Two nodes that received the same transactions in different orders, because of network latency or deliberate manipulation, will compute the same pool hash. Arrival order, the raw material of most front-running, is erased at this step.Arrival order is erased 01Node A receivestx3, tx1, tx2 in that order 02Node B receivestx2, tx3, tx1 in that order 03Bytewise sortBoth sort hashes before hashing the pool 04Same pool hashIdentical commitment on every honest nodeTick freeze pool_hash = H(tick_id || sort_bytewise(all_tx_hashes)) // identical tx sets, any arrival order // -> identical pool_hash on every honest node The canonical order is computed Once the pool is frozen, DSPE sorts it with four keys applied in a fixed order of precedence. The first key is the SLA lane, from the highest declared and bonded tier to the lowest. The second is HTLC maturity, oldest commitment first, so that time-sensitive contracts are not starved. The third is the effective fee after normalisation. The fourth is a tie-break derived from the epoch’s verifiable random function, which no participant can predict or bias. The result is hashed together with the tick identifier and the previous state root to produce the serialisation hash. That hash identifies the order uniquely. If any node, cube or leader presents a different order for the same tick, the difference is detectable immediately. Note what the function does not accept as input: a proposer’s preference. There is no parameter through which a leader can express one. The leader’s role in a cube is to coordinate vote collection, and the leader is required to apply the canonical […]

Scroll to Top