| Status | Draft for internal review |
| Type | Standards Track |
| Category | Core |
| Author(s) | Cowboy Foundation |
| Created | 2025‑09‑17 |
| Updated | 2026‑06‑11 |
| License | CC0‑1.0 |
Note: This document provides complete technical specifications for Cowboy. For architectural rationale and design decisions, see the Design Decisions Overview. Changelog 2026‑06‑11 — consensus randomness and the runner‑selection seed are specified by the absolute‑roundcommonwarethreshold‑VRFSeedmodel (§Randomness, Part II §3.4, §5.3); normative selection algorithm: CIP-11 §9.2 as finalized by CIP-11 r1.3 (COW-2198 / cowboyinc/cowboy#152, in flight at the time of this erratum; until it lands, this erratum supersedes the pre‑r1.3 CIP-11 §9.2 v2 seed) (COW-2200).
Abstract
Cowboy is a general-purpose Layer-1 blockchain that combines a Python-based actor-model execution environment with a proof‑of‑stake consensus and a market for verifiable off‑chain computation. Smart contracts on Cowboy are actors: Python programs with private state, a mailbox for messages, and chain‑native timers for autonomous scheduling. For heavy tasks like LLM inference, web requests, MCP tool calls, or containerized batch jobs, Cowboy integrates a decentralized network of Runners who execute jobs and attest to results under selectable trust models: N-of-M consensus, TEEs, and ZK-proofs (planned). Jobs MAY attach encrypted volumes (client-side encryption on CBFS, the Cowboy File System) and pull authorized secrets via threshold encryption (CBSS, the Cowboy Secret Service) without exposing plaintext on-chain; OCI container execution is governed by an on-chain image allowlist. Cowboy introduces a dual-metered gas model, separating pricing for computation (Cycles) and data (Cells) into independent, EIP-1559-style fee markets. Security is provided by Simplex BFT consensus with proof‑of‑stake, fast finality, and mandatory proposer rotation. This document specifies Cowboy’s complete technical architecture, state transition function, economic mechanisms, consensus protocol, and all implementation parameters.Introduction
Cowboy is designed to enable autonomous agents by providing a native blockchain execution environment optimized for asynchronous, Python-based applications. This document provides complete technical specifications for implementers, auditors, and protocol developers. Ethereum gave us programmable money, but its execution model is fundamentally reactive — smart contracts sit inert until an externally-controlled system calls them. Cowboy introduces a new unit of execution: the actor, an immortal, stateful program that schedules itself into the future, bids for its own blockspace, and runs indefinitely without a human in the loop. No amount of keeper networks or cron-job infrastructure on Ethereum provides a first-class primitive for autonomous, self-funding, self-scheduling programs. This new model requires a new protocol. Cowboy further innovates by adopting Python as its execution language, replacing the domain-specific languages required by existing chains (Solidity on Ethereum, Rust on Solana). Python’s ubiquity in AI and general-purpose development reduces the barrier to entry for both human developers and AI coding agents, which already generate Python more reliably than niche smart contract languages.Architectural Overview
This section is descriptive and non‑binding. Normative requirements are in §§1–17.Terminology
- Actor: A Python program with persistent key/value state and a mailbox.
- Message: A datagram delivered to an actor handler.
- Cycle: Unit of metered on‑chain compute.
- Cell: Unit of metered bytes (1 cell = 1 byte).
- Runner: Off‑chain worker that executes a job and returns an attested result.
- CBFS (Cowboy File System) / attachable volume: Distributed encrypted object storage: Runners read and write volumes via a client library (FUSE + QUIC); storage nodes see ciphertext only. CapTokens bind mount rights to a Runner address; manifest roots are anchored on-chain at the Storage Manager system actor (0x0A, §9).
- CBSS (Cowboy Secret Service): Threshold-encryption service that releases an account’s secrets to authorized Runners without ever exposing plaintext on-chain (Secrets Manager system actor, 0x04, §9).
- Entitlement: A permission governing an actor’s or runner’s capabilities.
- GBA: Gas Bidding Agent — an actor that dynamically bids for timer execution on behalf of another actor.
Key Features
Cowboy implements four core technical features:- Deterministic Python Actors. Smart contracts on Cowboy are actors: Python programs with private state, a mailbox for asynchronous messages, and chain‑native timers. Actors execute in a sandboxed Python VM (PVM) pinned to Python 3.11.8 with deterministic floating‑point (softfloat), disabled GC, fixed hash seed, and a whitelisted module set. Reentrancy is depth‑capped to 32; per‑call memory is bounded at 10 MiB.
-
Native Timers & Scheduler. Actors schedule their own future execution via
set_timerandset_intervalwithout external keeper infrastructure. The scheduler indexes timers by their target block height (FIFO within a bucket) and uses a per-firefee_payermodel that pre-charges gas at fire time and refunds the unused remainder. A future EIP-1559 hybrid (Tier-3 governance-activated) layers a timer-lane basefee, a priority tip, and a per-actor fairness weight on top. Anti-DoS measures include the per-fire pre-charge, a non-refundable per-timer scheduling cost, amax_timers_per_actor = 1,024cap, and a dedicated 20%-of-block timer execution lane. - Verifiable Off‑Chain Compute. A decentralized Runner marketplace executes jobs (LLM inference, HTTP fetches, MCP tools, custom compute, container batch jobs) off‑chain. Jobs MAY mount encrypted volumes backed by CBFS. Runners stake CBY and are selected via VRF. Results are verified under developer‑selected trust models: N‑of‑M quorum, economic bond, TEE attestation, structured matching, semantic similarity, or ZK‑proofs (planned). A commit‑reveal protocol with a 15‑minute challenge window and slashing enforces honesty. Container images MUST appear in the on-chain Container Image Registry unless a governed TEE exception applies.
- Dual‑Metered Gas. Two independent fee markets price computation (Cycles) and data (Cells) separately. Each meter uses a basefee that adjusts dynamically with demand and is burned; tips go to proposers. This prevents cross‑subsidization between compute‑heavy and storage‑heavy workloads.
Differences vs. Ethereum
| Aspect | Ethereum | Cowboy |
|---|---|---|
| Execution | EVM bytecode (Solidity) | Python actors in sandboxed PVM |
| Fees | Single gas scalar | Dual meters (Cycles + Cells) |
| Scheduling | External keepers required | Native timers with GBA auction |
| Off‑chain compute | External oracles | Verifiable Runner marketplace |
| State management | Indefinite storage | Rent with eviction and restoration |
Accounts and State
Cowboy distinguishes two object types:- External Accounts (EOAs): Controlled by private keys. They initiate transactions and hold balances of CBY and other assets. Key management may be abstracted via passkeys or other WebAuthn‑compatible mechanisms in a future revision.
- Actors: Autonomous Python programs executed in the PVM. Actors own storage, receive messages, and can send messages to other actors.
State : Address → { balance, nonce, code_hash?, storage?, metadata }
where actor storage is a key/value map subject to quotas and rent. System actors and precompiles occupy a reserved prefix of the address space (0x0000…0100); low-order allocations for the runner and fee subsystems are listed in §9.
Transactions and Message Passing
A user interacts with Cowboy by sending a signed transaction specifying a destination, a payload, and resource limits: a cycles limit and a cells limit alongside maximum and tip prices for each. An actor interacts with other actors by sending messages. Messages carry a payload, may transfer value, and may trigger further messages. Delivery is exactly‑once after finality; before finality it is at‑least‑once and may be reverted. Handlers MUST be idempotent. Actors may schedule timers that insert messages at a future block height. To avoid denial‑of‑service through explosive fanout, a transaction (including all nested sends) MUST NOT enqueue more than 1,024 messages. This1,024 cap governs cross‑actor message sends specifically; event‑hook emits (the publish/subscribe notification path, where enabled) are a distinct operation with their own, separate and much smaller per‑transaction budget — the two are not drawn from a shared pool.
Native Timers and the Actor Scheduler
Cowboy provides protocol‑native timers, eliminating the need for external keeper networks. Actors schedule messages to themselves or other actors at a future block height or on a recurring interval. The whitepaper specifies two layers — the currently implemented mechanism (FIFO with per-fire fee payer, §5.1a) and the target design (EIP-1559 timer-lane basefee + priority tip + per-actor fairness weight, §5.1b). The target activates by Tier-3 governance proposal; until then, §5.1a is canonical.5.1a Currently Implemented
The running node executes:- Storage: timers are indexed by
height; same-height bucket is FIFO by insertion order (no priority queue, no tiered calendar). - Per-fire
fee_payermodel. Each timer recordswho pays(fee_payer),how much gas per fire(gas_limit_per_fire), andwhen it gives up(expires_at). At end-of-block the protocol pre-chargesmax_cost = gas_limit_per_fire × cycle_basefee + max_cells × cell_basefeefromfee_payer, executes the handler, refunds unused gas, and removes the timer. Insufficient-funds or TTL-expired timers self-destruct without firing. - Three-path lifecycle: natural fire / TTL expiry / insufficient-funds self-destruct, plus explicit
cancel_timerand validator-setSYS_CANCEL_TIMER. - Lane separation:
LANE_TIMER_CYCLES = 8,888,890(execution lane, ~11% of the block cap) is separate fromTIMER_GC_CYCLES(cleanup lane) so a TTL-expiry storm cannot starve live execution. - Per-actor limit:
max_timers_per_actor = 1,024active timers (default, governance-tunable). - Per-fire caps:
max_cycles_per_fire = 550,000,max_cells_per_fire = 550,000. - Same-block prohibition: timers created in the current block MUST NOT fire in the same block.
5.1b Target Design (EIP-1559 hybrid)
The target mechanism supersedes the first-price auction and exponential-bias mechanism from earlier drafts. It activates by Tier-3 governance proposal at a chosen block height:- Timer-lane EIP-1559 basefee. A per-block basefee is maintained against
LANE_TIMER_CYCLESutilisation; target 50%, max change ±12.5% per block; 100% of the lane basefee is burned. - Priority tip. Each
schedule_timercall accepts(max_fee_per_cycle, max_priority_fee_per_cycle). The effective priority ismin(max_priority_fee_per_cycle, max_fee_per_cycle − lane_basefee). Tips go to the block proposer. - Per-actor fairness weight
W(actor) ∈ [1, 2]computed over a 1,000-block rolling window: actors at or below the network-median fire rate getW = 2(maximum boost); actors at 2× median or above getW = 1. Inclusion ordering:priority_per_cycle × W(actor). - Per-timer cycle cap during auction phase:
MAX_CYCLES_PER_FIRE_AUCTION_PHASE = 250,000(= 12.5% of the lane), preventing any single timer from monopolising. The 550k FIFO-phase cap remains in force during the FIFO phase. - Default GBA:
max_fee_per_cycle = 2 × lane_basefee;max_priority_fee_per_cycle = previous_block_p50_priority_tip_per_cycle. SDKs expose apriority_tier_hint ∈ {economy, standard, fast, urgent}mapping to multipliers{0.8×, 1.0×, 1.5×, 2.5×}on the priority fee. - Lane fee multiplier:
1.0×at genesis (no subsidy), Tier-0 tunable. - All FIFO-phase invariants retained: Tx-then-Timer block ordering, per-fire
fee_payerpre-charge + refund (the priority tip extendsmax_costbut does not change the mechanics), three-path lifecycle, lane separation, system-instruction opcodes 48/49/50, same-block prohibition.
DoS Prevention (both phases)
| Attack Vector | Mitigation |
|---|---|
| Schedule millions of timers | max_timers_per_actor = 1,024 + per-fire fee_payer pre-charge |
| Sybil attack across many actors | Per‑block execution budget caps total timer work (LANE_TIMER_CYCLES, ~11% of block cap) |
| Timer bomb (many timers, one block) | Per‑tx fanout cap (1,024 enqueued timers/messages) + max_timers_per_actor = 1,024 + non‑refundable 200‑cycle scheduling cost per timer; the same‑block prohibition stops any newly scheduled timer from firing in the creating block |
| Fill queue far in advance | (FIFO phase) per-fire max_cost re-checked at each fire; (auction phase) lane basefee rises with utilisation |
| Outbid everyone perpetually | (auction phase only) per-actor fairness weight W(actor) ∈ [1, 2] over 1,000-block window |
| DoS then cancel for refund | Pre-charge happens at fire time, not at schedule time; scheduling cost (200 cycles) is non-refundable |
Asynchronous Execution and Multi‑Block Semantics
Single‑Block Atomicity
Cowboy provides atomicity only within a single block. All state reads, writes, and outbound messages within a handler are atomic — they either all commit or all revert. There is no cross‑block atomicity. Once a handler completes and the block is finalized, subsequent handlers execute in potentially different world state.Why No Cross‑Block Transactions
Cross‑block atomicity would require either global locks (destroying parallelism and creating deadlock vectors) or speculative execution with rollbacks (creating griefing opportunities and unpredictable costs). Cowboy explicitly rejects both approaches. The fundamental problems with suspending execution across blocks are: (1) stale state — values read before the yield may have changed; (2) invalid control flow — branches taken on pre‑yield state may no longer be appropriate; (3) composability explosion — nested yields create interleavings where each path depends on invalidated assumptions; (4) adversarial griefing — attackers can mutate state between yield points.Message‑Passing Continuation Model
Instead of implicit continuations, Cowboy uses explicit message passing for all asynchronous operations. When an actor dispatches an off‑chain job, the result arrives as a separate message in a later block. The actor must re‑read and re‑validate any state assumptions in the callback handler. This model requires explicit context capture — any state needed in the continuation must be included in the outbound message. Correlation IDs enable matching responses to requests. If an actor sends multiple requests, responses may arrive in any order. Actors MUST implement timeout handling for operations that depend on external responses. The recommended pattern combines correlation tracking with native timers: schedule a timeout timer alongside each outbound request, and cancel the timer when the response arrives.| Model | Atomicity | Developer Burden | Griefing Resistance |
|---|---|---|---|
| Ethereum (sync calls) | Single TX | Low | High |
| Cross‑block locks | Multi‑block | Low | Low (deadlocks, lock griefing) |
| Optimistic + rollback | Multi‑block | Medium | Low (rollback spam) |
| Cowboy (message passing) | Single block | Medium | High |
The Cowboy Actor VM (PVM)
Cowboy uses Python as its execution language. The PVM executes Python bytecode in a deterministic sandbox pinned to Python 3.11.8, with restrictions to ensure identical results across all nodes.Determinism Guarantees
Runtime Environment:- No JIT compilation — pure interpretation mode only.
- Deterministic memory management via reference counting. The cyclic garbage collector is disabled; creating reference cycles MUST raise
DeterminismError. - Fixed recursion limit: 256 (integrated with cycle metering).
- All floating‑point operations use a cross‑platform software math library (softfloat), not the host FPU.
- Transcendental functions (
sin,cos,log,exp, etc.) use deterministic softfloat implementations. - If the
decimalmodule is used, it MUST use fixed rounding mode (ROUND_HALF_EVEN) and fixed precision.
PYTHONHASHSEEDfixed to0.dictiteration is insertion‑ordered (deterministic per Python 3.7+).- Built‑in
setandfrozensetare replaced withordered_setfromcowboy_sdk.collections(transparent to user code).
- All data crossing a trust boundary MUST use its declared canonical encoding (deterministic:
one value ⇒ exactly one byte string, strict decode), per that boundary’s specification:
- Chain consensus types (transactions, blocks, instructions, account/actor/mailbox state,
receipts) use the canonical
commonware‑codecbinary encoding (§2.5, Appendix A) — ordered fields, minimal varints, strict decoders. (This is the normative encoding for everything hashed into a block/state/receipt root.) - SDK ↔ runtime CBOR uses the CIP‑6 §11.5 profile; connectivity uses the CIP‑11 §4.2.1 profile. Where a sub‑spec pins a CBOR profile, that profile governs that boundary.
- Chain consensus types (transactions, blocks, instructions, account/actor/mailbox state,
receipts) use the canonical
- Indefinite‑length containers, non‑minimal integers, and floats are forbidden in any canonical
encoding.
pickleis forbidden. JSON output (non‑canonical surfaces only) MUST usesort_keys=True, separators=(',', ':').
collections, dataclasses, enum, functools, itertools, json, re, struct, math, decimal, typing, abc, hashlib, cowboy_sdk. No C extensions. No dynamic imports. Additional modules may be added via governance after determinism audit.
Forbidden Operations:
| Category | Forbidden |
|---|---|
| System | sys.exit(), os.environ, os.system(), subprocess.* |
| Time | time.time(), datetime.now(), time.sleep() |
| Randomness | random.* (use cowboy_sdk.vrf instead) |
| Networking | socket.*, urllib.*, http.*, requests.* |
| Filesystem | All except /tmp scratch space (256 KiB limit, wiped post‑handler) |
| Reflection | eval(), exec(), compile(), globals() modification |
| Introspection | sys._getframe(), inspect.currentframe(), gc.* |
| Weak References | weakref.* (non‑deterministic collection timing) |
| Threading | threading.*, multiprocessing.*, concurrent.* |
| Identity | is comparisons on strings or numbers (use ==) |
Storage and State Persistence
The storage architecture uses a three‑layer model:- The Ledger: Append‑only log of blocks — the sequential, historical source of truth.
- The Triedb: An authenticated Merkle trie (QMDB) generating a verifiable
state_rootper block via blake3, holding all account, code, and storage state. (Transaction and receipt roots use keccak256.) - Auxiliary Indexes: Rebuildable, read‑optimized tables for transaction hashes, event topics, etc. Not part of the consensus‑critical state root.
vm_ns (VM namespace) flag in storage keys allows PVM and future EVM storage to coexist without collision at the same address. A standardized C‑ABI wrapper enables cross‑VM calls.
All actor storage is subject to state rent (see §4.4 and the Data Availability section below).
Pricing: Cycles and Cells
Ethereum uses a single gas scalar. Cowboy splits pricing into two independent meters:- Cycles measure compute: Python operations and host calls each have a fixed cost defined in a consensus‑critical cost table. Cycles resemble Erlang reductions — a budget of discrete steps bounding handler execution.
- Cells measure bytes: calldata, return data, blobs, and storage writes all consume cells (1 cell = 1 byte).
Off‑Chain Compute: The Runner Marketplace
Actors can outsource computation — LLM inference, HTTP fetches, MCP tool invocation, heavy transforms, and one-shot container jobs — to a decentralized network of Runners who stake CBY. The marketplace is verifiable: the chain accepts results under trust models chosen by the developer, and dishonest runners risk slashing. Attachable storage. Jobs MAY declarevolume_mounts: Runners that declare storage capability mount encrypted volumes through CBFS (the Cowboy File System; client-side encryption, with storage nodes seeing ciphertext only). CapTokens bind mount rights to a Runner address, and manifest roots are anchored on-chain at the Storage Manager (0x0A). This supports large artifacts and multi-step tool chains without putting raw payloads in calldata. The full design lives in the Cowboy Storage Whitepaper.
Secret release. Jobs frequently need third-party credentials (API keys, signing tokens). The Cowboy Secret Service (CBSS) lets an account store secrets encrypted so that the plaintext never appears on-chain and is never exposed to the proxy committee or the dispatcher. Secrets are released by a committee of staked proxy operators using threshold identity-based encryption (a t-of-n threshold-BLS construction on BLS12-381): the proxies return partial signatures that an authorized Runner combines to decrypt the secret just-in-time at execution. Only that authorized Runner sees the plaintext; the dispatcher is never on the key path. The trust root is t-of-n proxy non-collusion plus slashing, not a hardware enclave. CBSS is also the key-delivery layer for private CBFS volumes. The Secrets Manager system actor (0x04, §9) holds proxy registration, per-account key material, per-secret access policy, and release receipts; the full design lives in the Cowboy Secrets Whitepaper.
Job Lifecycle:
- Post: Actor submits a job with escrowed price, resource bounds, and trust model.
- Assign: A committee of M runners is selected via VRF from eligible (staked, healthy) runners.
- Commit: Runners return
commit = keccak256(output || salt). - Reveal: Runners reveal
{output, salt, proof?}. - Challenge: A 15‑minute window opens; challengers post a 100 CBY bond.
- Resolve: Proven dishonesty triggers slashing; operational failures result in reputation penalties only.
- Payout: 89% of job payment to runner(s), 10% burned, 1% to Treasury.
| Mode | Level of Trust |
|---|---|
| N‑of‑M Quorum | Committee executes; runtime accepts consensus result. |
| N‑of‑M with Dispute | Runners stake a bond; disputers may prove incorrect results within a fixed window. |
| TEE Attestation | Execution within a Trusted Execution Environment; attestation verified on‑chain. |
| ZK‑Proof (planned) | Runners provide zk‑SNARKs for cryptographic verification. |
Runner Resource Accounting
Every job submission includes explicit resource bounds (max tokens, max wall time, max memory, max price). Runners publish rate cards to an on‑chain registry. Job pricing follows:actual_payment = min(reported_usage × rates, max_price). Tips incentivize priority during high demand.
Runner‑reported usage is trusted by default, subject to reputation scoring and anomaly detection (>2× expected usage triggers automatic review). For stronger guarantees, actors can require TEE‑attested metering. Proven dishonesty (e.g., fabricated results, misreported usage) is subject to stake slashing via the challenge mechanism; operational failures (timeouts, crashes) result in reputation penalties only.
Payment and Failure Handling:
| Outcome | Runner Payment | Actor Refund |
|---|---|---|
| Success | 89% of min(reported_usage × rates, max_price) + tip (10% burned, 1% Treasury) | max_price - actual_payment |
| Runner fault (timeout, invalid result, crash) | 0 | 100% of escrow |
| Impossible job (bounds too tight) | Pro‑rata based on progress | Remainder of escrow |
| Actor fault (malformed input) | Minimum fee (gas cost recovery) | Remainder of escrow |
| External fault (API down, model unavailable) | Pro‑rata based on progress | Remainder of escrow |
LLM Result Verification
LLM outputs are inherently non‑deterministic — the same prompt can produce semantically equivalent but byte‑different outputs. Cowboy provides multiple verification modes:| Mode | Runners | Verification | Challenge Scope | Use Case |
|---|---|---|---|---|
none | 1 | None | Non‑delivery only | Prototyping, low‑stakes |
economic_bond | 1 | Objective checks | Objective failures | Subjective generation |
majority_vote | N‑of‑M | Vote on field value | Objective failures | Classification |
structured_match | N‑of‑M | Verifier functions | Objective failures | Structured extraction |
deterministic | N‑of‑M | Exact match + TEE | Full reproduction | Critical deterministic |
semantic_similarity | N‑of‑M | Embedding threshold | Objective failures | Subjective with similarity |
| Failure | Detection | Consequence |
|---|---|---|
| Schema violation | Output fails declared JSON schema | Reputation penalty, no payment |
| Timeout | No result within max_wall_time | Reputation penalty, no payment |
| Empty/garbage output | Output below min_length or fails entropy check | Reputation penalty, no payment |
| Non‑delivery | Runner accepted job but never submitted | Reputation penalty, no payment |
| Wrong model | TEE attestation shows different model hash | Slash (proven dishonesty) |
| Prompt injection leak | Output contains system prompt markers | Reputation penalty, no payment |
External Data and Oracle Semantics
Actors frequently need external data: price feeds, web APIs, public datasets. External data is inherently mutable and non‑deterministic. Different sources require different verification strategies:| Source Type | Characteristics | Verification Strategy |
|---|---|---|
| Deterministic API | Versioned, stable, structured (blockchain RPC, static files) | Exact match |
| Semi‑stable API | Structured with variable metadata (REST APIs) | Structured match, ignore metadata |
| Time‑series data | Values change over time (price feeds) | Median/majority with freshness bounds |
| Web scraping | Unstructured, highly variable (HTML pages) | Extraction‑based matching |
| Authenticated endpoints | Requires credentials | Single runner + TEE |
block, submission, or absolute) and a max_age_seconds parameter.
Snapshot Modes. When multiple runners fetch mutable data, the protocol selects a canonical result via one of: first_valid (first runner’s result is authoritative), median (for numeric data), majority (for categorical data), or latest (most recent by timestamp).
Extraction‑Based Verification. For web scraping, runners apply extraction rules (CSS selectors, XPath, JSONPath, regex) and submit extracted data rather than raw HTML. Verification compares extracted fields, ignoring irrelevant page differences.
HTTP access is governed by the Entitlements system. Actors declare required domains; runners advertise supported domains. The protocol provides curated domain sets (price_feeds, government_us, social_apis, blockchain_rpc).
Randomness
Consensus emits one random beacon per round: thecommonware threshold scheme produces a verified Seed { round: Round(epoch, view), signature }, a BLS12‑381 threshold signature over the absolute round encoding. Exactly one valid seed exists for a given absolute round — whether that round notarizes, finalizes, or nullifies — and it verifies against the epoch’s threshold public key. Seeds are identified by their absolute round, never by block height: a height n and a Seed.round are not interchangeable, and “the seed of whatever round finalizes height n” is not a well‑defined beacon. The execution‑readable beacon for a block is the parent beacon — the verified seed of the absolute round immediately preceding the round in which the block was proposed (a round‑relative object that exists even if that preceding round nullified; never a height‑addressed lookup) — because using a round’s own randomness to affect execution in that same round is unsafe. Actors access sub‑randomness via HKDF(R, label) for fair committee sampling, lotteries, and games; protocol components that consume the beacon (e.g. runner selection, CIP-11 §9.2) MUST name the absolute round whose seed they consume.
Consensus and Networking
Cowboy uses Simplex BFT with proof‑of‑stake. Key parameters: ~1‑second blocks, ~2‑second finality, fault tolerance up to f < n/3 Byzantine validators. Consensus Flow:- Propose: Current proposer (selected by VRF, weighted by stake) broadcasts a block.
- Vote: Validators vote; signatures are buffered and batch‑verified at quorum (2f+1).
- Certify: A Quorum Certificate (QC) is formed from 2f+1 votes.
- Finalize: A block is final when its direct child has a QC (two‑chain commit).
Validator Set
The validator set is open and permissionless. Requirements: stake ≥minimum_validator_stake (governance‑tunable), self‑stake only (no delegation at launch), compliant validator software. No protocol cap on validator count.
Lifecycle: Register (stake CBY, submit BLS12‑381 key) → Activate (next epoch boundary) → Operate (propose, vote, earn rewards) → Exit (signal unbonding) → Withdraw (after 7‑day unbonding period).
Epochs: 3600 blocks (~1 hour). Validator set updates, slashing penalties, and epoch randomness derivation occur at epoch boundaries.
Staking and Rewards
Block rewards (from inflation per §8.2) are distributed proportionally to stake. Proposers additionally receive 100% of cycle/cell tips on blocks they finalize. No per‑transaction validator commission or surcharge is charged to users beyond tips; the entire user‑derived validator income is the tip stream. Staking is self‑bonded only; delegation is a planned addition.Slashing
Cowboy uses a conservative slashing model — most offenses result in jailing (temporary removal) rather than stake destruction:| Offense | Penalty |
|---|---|
| Double signing | Jail + slash 1% of stake |
| Proposer equivocation | Jail + slash 1% of stake |
| Extended downtime (>50% of votes over 1000 blocks) | Jail (no slash) |
| Invalid block proposal | Jail (no slash) |
Network Layer
Transport: QUIC over TLS 1.3 (required). Gossip: transactions flood to all peers; blocks are relayed by validators; votes go directly to the proposer. Peer discovery: DHT‑based with bootstrap nodes.Dedicated Lanes
Block space is partitioned into dedicated lanes with reserved capacity and per‑lane fee multipliers:| Lane | Reserved Capacity | Fee Multiplier | Contents |
|---|---|---|---|
| System | 50% (40M cyc) | 1.0× | Validator updates, governance, slashing |
| Timer | ~11% (8.89M cyc) | 1.0× | Scheduled timer executions |
| Runner | ~11% (8.89M cyc) | 1.0× | Runner job results, attestations, and related on-chain follow-ups (e.g. storage manifest anchors) |
| User | ~28% (22.2M cyc) | 1.0× | User‑initiated transactions |
lane_basefee = global_basefee × lane_fee_multiplier; all four multipliers default to 1.0× at genesis (no lane subsidy or surcharge). The multipliers are Tier-0 governance-tunable; see §13.1 for the canonical parameter registry.
MEV Reduction
Cowboy mitigates MEV through four mechanisms: (1) mandatory per‑block proposer rotation via VRF prevents multi‑block observation; (2) VRF‑based transaction ordering within blocks prevents strategic placement; (3) ~2‑second finality minimizes the observation window; (4) lane isolation prevents congestion attacks that delay victim transactions. No encrypted mempool is used — the marginal benefit does not justify the added latency given the already‑minimal MEV surface. This design does not address single-block proposer censorship, private orderflow MEV, or JIT MEV against actors with predictable on-chain state. Application-level mitigations (commit-reveal, slippage caps, batch auctions) remain an actor concern. The full enumeration and rationale are in §6.5.Data Availability, State Rent, and Storage
Inline Data vs. Blobs
Small outputs (≤ 64 KiB) are stored inline and paid for with cells. Larger artifacts MUST be stored as content‑addressed blobs (e.g., IPFS) with the multihash referenced on‑chain.State Rent
All persistent actor storage is subject to state rent — an ongoing fee for occupying space in the global state trie. Rent rates adjust dynamically based on total network state size:rent_rate_{i+1} = rent_rate_i × (1 + clamp((S - T) / (T × alpha), -delta, +delta))
where S is the current total state size, T is the target (governance‑tunable), alpha = 8, and delta = 0.125.
Rent is auto‑deducted from the actor’s balance each rent epoch (default: 1 day). Actors may also prepay rent for cost certainty, and any account may sponsor rent on behalf of any actor. Each actor maintains a minimum balance reserve (~5 weeks of rent) as a buffer before entering grace period.
Grace Period and Eviction
When an actor cannot pay rent (balance, reserve, and prepaid epochs exhausted):- Grace period (7 rent‑epochs): Actor remains fully functional; flagged as “rent overdue”; catch‑up fee accumulates (10% of missed rent).
- Warning period (3 rent‑epochs): Actor flagged as “eviction imminent”; events emitted to alert dependent actors.
- Eviction (after 10 rent‑epochs of unpaid rent — 7 grace + 3 warning): Actor storage and active timers are pruned. Code, address, balance, and storage root hash are preserved. The actor enters a “dormant” state.
Storage Quotas
Each actor has a base storage quota of 1 MiB, extendable up to 8 MiB via a storage bond. The bond is locked while the quota is in use, returned when reduced, and forfeited if the actor is evicted. Rent applies to the full allocated quota.The State Transition Function
The state transition function takes a block and an input state and returns the next state. Let σ be the global state, B a block with transactions T_i, basefees (bf_c, bf_b), and randomness R.- Header/Proposer: Determined by Simplex; R derives from the parent QC.
- Execute Transactions: Per‑lane selection, then VRF ordering. Lane selection applies the dedicated per‑lane budgets defined in §6.3, with each lane’s basefee scaled by its governance‑tunable
lane_fee_multiplier. For each transaction: validate signature, nonce, and balance; initialize meters; dispatch to target (fanout ≤ 1,024, reentrancy depth ≤ 32); enforce memory (10 MiB), mailbox (≤ 1,000,000 bytes), and storage quotas; deduct fees and burn basefees. - Deliver Timers: Inject due timers at height(B).
- Resolve Jobs: Process commitments, reveals, challenges, and payouts.
- Adjust Basefees: Update (bf_c, bf_b) based on block utilization.
- Mint Rewards: Distribute per‑block inflation to validators.
Normative Conventions
This document uses MUST/SHOULD/MAY as defined in RFC 2119. Parameters marked governance‑tunable can be changed by on‑chain governance (see §11).1. Accounts, Addresses, and Keys
1.1 Signatures. External accounts MUST use secp256k1 (ECDSA) with chain‑id separation. 1.2 Actor address derivation (CREATE2‑style). New actor addresses MUST be:addr = last_20_bytes(keccak256(creator || salt || code_hash)) where code_hash = keccak256(python_source_bytes).
python_source_bytes MUST be canonicalized as UTF‑8, NFC‑normalized, LF line endings, and no BOM. The canonical bytes are what are hashed and stored.
1.3 System address space.
The range 0x0000…0100 is reserved for system actors and precompiles (see §9 for the normative allocation table of low-order system actors).
2. Transaction Types & Encoding
2.1 Instruction‑based tx (dual meters). Cowboy transactions are instruction‑based, not flatto/value/payload: the operation is
a typed Instruction (System | Actor | Custom | Library) that carries its own operands (e.g. a
transfer is System(Transfer { to, amount })). A transaction comprises:
chain_id, nonce, instruction, cycles_limit, cells_limit, max_fee_per_cycle, max_fee_per_cell, max_priority_fee_per_cycle, max_priority_fee_per_cell, from, access_list?, metadata, origin_tx_hash?, origin_remaining_cycles?, origin_remaining_cells?, signature, additional_signers.
chain_idis bound into the signing hash (replay protection); a node MUST reject a tx whosechain_iddoes not match its own.fromis the 20‑byte sender;additional_signersis a (possibly empty) list of(address, signature)pairs that MUST be strictly ascending by address (no duplicates).origin_tx_hash/origin_remaining_*are present only on system‑injected deferred txs (which are not signature‑verified); they are absent on ordinary signed txs.access_listis optional and reserved (v1: always absent /null, not enforced; reserved for future parallel‑scheduling/prefetch).metadatais caller‑attached bytes (bound into the signing hash).
chain_id mismatch, (e) additional_signers not strictly
ascending / contains duplicates, or (f) encoding is non‑canonical / fails to decode (§2.5).
(access_list is advisory/reserved in v1 and is not validated.)
2.3 Fee accounting.
Let bc, bb be the block basefees for cycles/cells. Fees are:
fee = cycles_used * (bc + min(max_priority_fee_per_cycle, max_fee_per_cycle - bc)) + cells_used * (bb + min(max_priority_fee_per_cell, max_fee_per_cell - bb)).
Unused limits MUST be refunded at the user’s max_fee_* rates.
2.4 EBNF (informative).
Tx = chain_id nonce instruction gas from [access_list] metadata [origin] signature additional_signers
gas = cycles_limit cells_limit max_fee_per_cycle max_fee_per_cell max_priority_fee_per_cycle max_priority_fee_per_cell
instruction = category sub_type body (e.g. System(0) Transfer(1) to amount)
origin = origin_tx_hash origin_remaining_cycles origin_remaining_cells (deferred only)
signature = r s v ; additional_signers = [ (address, signature) ... ]
2.5 Encoding (normative).
Transactions MUST be encoded with the chain’s canonical commonware‑codec binary encoding —
the same deterministic, ordered encoding used for Block, Instruction, Account, and all other
consensus types (it is NOT CBOR). The encoding is a flat concatenation of the fields in this
frozen order:
chain_id, nonce, instruction, cycles_limit, cells_limit, max_fee_per_cycle, max_fee_per_cell, max_priority_fee_per_cycle, max_priority_fee_per_cell, from, access_list, metadata, origin_tx_hash, origin_remaining_cycles, origin_remaining_cells, signature, additional_signers
- Scalar
u64fields (chain_id,nonce, the gas/fee fields) use a minimal varint (UInt); collection lengths use a varint length prefix. Fixed‑width values (the 20‑bytefrom/addresses, the 65‑bytesignature=r‖s‖v, 32‑byte digests) are raw bytes.Option<T>is a 1‑byte tag (0x00= absent,0x01= present, followed by the value).Vec<T>/ byte strings are a varint length prefix followed by the elements.Instructionis[category, sub_type, body](e.g.Transfer=System(0) Transfer(1) to(20B) amount(8‑byte big‑endian u64)). - The encoding is canonical: every transaction has exactly one valid byte encoding. Decoders
MUST be strict — reject non‑minimal varints, non‑
{0,1}option/bool tags, unknown enum discriminants, and trailing bytes — sodecode(encode(tx)) = txandencode(decode(b)) = b. - The signing hash MUST be
keccak256(canonical_encode(Tx_without_signatures))— the canonical encoding with the primarysignatureand everyadditional_signerssignature zeroed (signer addresses retained). The transactiondigest(its identity / BMT leaf) is the same value, so the identity is signature‑independent. Every signer signs this hash.
3. Execution Model (Actors)
3.1 Runtime & Determinism.- Official SDKs: Python SDK. The runtime MUST enforce determinism:
- Allowed operations: Standard Python operations, file I/O limited to
/tmp;async/awaitis syntax sugar only and does not suspend across blocks. - Forbidden:
sys.exit(),randommodule (except chain VRF),time.time()/datetime.now(),os.environaccess, socket/network operations, subprocess calls, path traversal outside/tmp. - Floating point: Permitted; Cowboy provides a deterministic math library.
- Scratch space:
/tmpMUST be per‑invocation, capped at 256 KiB (counts towardcells_used), wiped post‑handler.
- Allowed operations: Standard Python operations, file I/O limited to
- Per‑call memory limit: 10 MiB heap memory.
- Per‑actor persistent storage quota: 1 MiB (governance‑tunable) with state rent (§4.4).
- Quota extensions: An actor MAY post a storage bond up to 8 MiB total; rent applies to the full allocated quota.
- Delivery: Exactly‑once after finality (before finality: at‑least‑once). Each message ID MUST be
keccak256(sender||nonce||msg_hash)and recorded in a per‑actor dedup set (counts toward actor storage or a separate metered mailbox store). Dedup entries MUST be retained for at leastdedup_windowafter finality. - Mailbox: Capacity 1,000,000 bytes (or equivalent cell‑metered limit); enqueue beyond the limit MUST revert.
- Per‑tx fanout: A transaction (including all nested sends) MUST NOT enqueue more than 1,024 messages.
- Reentrancy: Allowed within a single block only; there is no synchronous call/return across blocks. Recursion/await depth cap = 32.
- Timers (chain‑native): The following timer primitives are provided:
timer_id = set_timer(height, handler, data)— Schedule a one-time timer for the specified block height. Returns a uniquetimer_id.timer_id = set_interval(every_n_blocks, handler, data)— Schedule a recurring timer. Returns a uniquetimer_id.cancel_timer(timer_id)— Cancel a pending timer by its ID. Returns the deposit if successful.- Timer delivery is best‑effort; execution depends on the timer scheduler (see §5.1a for current rules and the same-block-prohibition rule).
- Consensus MUST produce a threshold‑BLS VRF seed per round:
Seed { round: Round(epoch, view), signature }, wheresignatureis the epoch threshold signature over the absolute round encoding (commonware’s canonicalRoundcodec; see CIP-11 §9.2), verifiable against the epoch’s threshold public key. Exactly one valid seed exists per absolute round (notarized, finalized, or nullified). Seeds are identified by absoluteRound(epoch, view); implementations MUST NOT address a seed by block height and MUST NOT derive the beacon from a parent QC. - Actors MAY call an API which returns
HKDF(R, label), whereRis the execution‑readable parent beacon of the executing block — the verified seed of the absolute round immediately preceding the executing block’s proposal round. A round’s own seed MUST NOT affect execution in that same round.
- Exact metering is consensus‑critical; implementers MUST match the reference cost table.
| Primitive | Cycles |
|---|---|
| Python arithmetic ops | 1 |
| Python function call | 10 |
| Dictionary get/set | 3 |
| List append/access | 2 |
| String operations (per char) | 1 |
| host: mailbox send (per msg excl. payload) | 80 |
| host: timer set/cancel | 200 |
| host: blob commit (per KiB) | 40 |
| Operation | Cycles |
|---|---|
| BLS12‑381 signature verification | 8,000 |
| Ed25519 signature verification | 5,000 |
| secp256k1 (ECDSA) signature verification | 10,000 |
| SHA‑256 (base + per 64‑byte block) | 500 + 8 × ⌈len/64⌉ |
| Keccak‑256 (per 32 bytes) | 6 × ⌈len/32⌉ |
| HKDF randomness derivation | 1,000 |
4. Fees, Metering, and Basefee Adjustment
4.1 Meters.- Cycles: Deterministic step count over Python operations + host calls.
- Cells: Bytes used by calldata, return data, inline blobs (≤ 64 KiB), and /tmp.
U_c, T_c be cycles usage/target; U_b, T_b be cells usage/target. Block space is partitioned into independently-capped lanes (§6.3) whose budgets sum to 4× the target, so the per-block hard cap for any one workload is the largest lane. Adjustment uses:
basefee_{x,i+1} = max(MIN_BASEFEE, basefee_{x,i} * (1 + clamp((U_x - T_x)/(T_x*alpha), -1/alpha, +1/alpha)))
where x ∈ {cycle, cell}, alpha = 96, the per-block change is capped at ±1/96 (~1.04%), and MIN_BASEFEE = 10,000. The learning rate is calibrated for 1-second blocks so 12-second compounding (1 + 1/96)^12 ≈ 13% stays close to EIP-1559’s 12.5%/12s ramp. Nodes MUST burn 100% of basefees; tips go to proposers/validators.
4.3 Targets (genesis defaults).
T_c(cycles target): 20,000,000 cycles; the per-block hard cap is 80,000,000 (the sum of the four lane budgets, §6.3).T_b(cells target): 4,000,000 bytes.
5. Off‑Chain Compute
5.1 Model registry.model_id = keccak256(weights||arch||tokenizer||license) MUST uniquely identify a model revision. Publishing is permissionless with a refundable 1,000 CBY deposit. Governance MAY flag/ban models.
5.2 Runner staking.
Runners MUST stake max(10,000 CBY, 1.5 × declared_max_job_value) in the Runner Registry.
Jobs MAY attach encrypted volumes through CapToken-authorized mounts (CapToken mounts are authorized and checked on-chain) and MAY specify Container execution; the Storage Manager (0x0A) anchors volume manifests, the Container Image Registry holds the OCI image allowlist (§9), and the Governance actor (0x09) holds settable protocol parameters. Jobs MAY also release account secrets through the Secrets Manager (0x04) via threshold encryption (§9). Field-level requirements (e.g. volume_mounts, image allowlists) — including job-spec encoding, registry semantics, and container policy — will be elaborated in future CIPs.
5.3 Job lifecycle.
- Post: Actor posts a job with escrowed price.
- Assign: A committee of M runners is sampled. The committee is sized adaptively:
M = clip(ceil(2·log₂(N_active) / max(HHI, 0.01)), 3, 9),N = ceil(2M/3), recomputed per epoch (M=5, N=3was the initial fixed fallback). LLM jobs MAY use committees or single-runner. Selection is stake‑weighted Fisher‑Yates VRF with weightw = stake · sqrt(reputation). Aggregator is uniformly drawn from committee members with reputation ≥ p50 (target). Aggregator receives 1.5% of gross job payment from the runner share on successful settlement. The selection draw is seeded by the verifiedcommonwarethreshold seed of a named absolute round under domaincowboy-runner-select-v3:(never a block hash or height‑anchored beacon): single‑runner jobs select immediately in the submission block from the parent beacon; multi‑runner committees bind in the submission block and select from the seed of the absolute future roundadvance_round(r_submit, K)(commit‑then‑reveal; CIP-11 §9.2). - Commit: Runner returns
commit = keccak256(output||salt). - Reveal: Runner reveals
{output, salt, proof?}. - Challenge: A challenge window of 15 min is opened, requiring a 100 CBY bond.
- Resolve: Proven dishonesty ⇒ stake slashing via challenge mechanism. Operational failures (timeouts, crashes) result in reputation penalties only.
- Payout: On finalization, 89% of job payment to runner(s), 10% burned, 1% to Treasury.
toolchain_digest and seed. On‑chain return data MUST be ≤ 64 KiB.
5.5 TEE option.
A job MAY set tee_required=true. A valid attestation MUST match accepted policies.
6. Consensus, Randomness, and Networking
6.1 Consensus. Simplex BFT PoS; ~1s target block time; finality on commit (~2s). Proposers rotate every block using the VRF beacon (mandatory rotation for MEV resistance). Votes aggregate via BLS12‑381 with buffered batch verification. Message types (normative):PROPOSE, VOTE, NEW_VIEW.
Quorum certificate (QC): QC = {block_hash, height, round, aggregated_signature, signer_bitmap} where aggregated_signature is BLS12‑381 over the block_hash || height || round domain.
VRF: Each block header MUST include the proposer’s VRF output and proof for the current height; validators MUST verify it against the epoch seed.
Finality rule: A block B_h is final when its direct child has a QC (two‑chain commit). Concretely, if QC(B_{h+1}) exists and B_h is the parent of B_{h+1}, then B_h is finalized. Implementations MAY expose both “commit” and “finalized” states explicitly.
View change: On timeout, validators broadcast NEW_VIEW containing their highest known QC. The next proposer MUST build on the highest‑QC block.
6.2 P2P transport.
Implementations MUST support QUIC over TLS 1.3.
NAT traversal. In‑protocol NAT traversal (ICE/STUN/TURN‑style hole punching) is out of scope at genesis: the protocol specifies the wire transport (QUIC/TLS 1.3) and peer discovery (DHT + bootstrap nodes), but does not mandate a hole‑punching mechanism. Operators are responsible for mutual reachability — production validators are expected to run with publicly reachable QUIC endpoints (static IP / port‑forward), and development networks MAY use an overlay (e.g. Tailscale/WireGuard) for connectivity. This keeps the consensus/transport layer simple and unopinionated; a protocol‑level traversal mechanism, if warranted by operator demand, is a candidate for a future networking CIP rather than a launch requirement.
6.3 Dedicated Lanes.
Block space is partitioned into dedicated lanes with reserved capacity and per‑lane fee multipliers:
| Lane | Reserved Capacity | Priority | Fee Multiplier | Contents |
|---|---|---|---|---|
| System | 50% (40M) | Highest | 1.0× | Validator updates, governance, slashing |
| Timer | ~11% (8.89M) | High | 1.0× | Scheduled timer executions |
| Runner | ~11% (8.89M) | High | 1.0× | Runner job results, attestations, storage manifest anchors |
| User | ~28% (22.2M) | Normal | 1.0× | User transactions |
- Timer and runner lanes prevent user transaction spam from blocking autonomous actor execution
- Unused capacity in higher-priority lanes cascades to lower-priority lanes
- Each lane’s basefee is
lane_basefee = global_basefee × lane_fee_multiplier. All four multipliers default to1.0×at genesis (no subsidy, no surcharge) and are Tier-0 governance-tunable.
tx_hash), then apply VRF ordering within the selected set. For ordering, effective_fee is computed using intrinsic costs only:effective_fee = intrinsic_cycles × min(max_fee_per_cycle, basefee_cycle + tip_per_cycle) + intrinsic_cells × min(max_fee_per_cell, basefee_cell + tip_per_cell).Transactions are tagged by lane type. No private builders or encrypted mempool at launch—MEV resistance relies on fast finality and mandatory proposer rotation. 6.5 MEV Reduction (Limitations Apply). Cowboy’s MEV mitigation strategy combines multiple mechanisms: Mandatory proposer rotation: Simplex consensus rotates proposers every block via VRF. Unlike stable-leader protocols, no single validator can observe transaction flow across multiple blocks, limiting MEV extraction windows. VRF-based transaction ordering: Within each block, transactions are ordered by:
- Front-running (limited observation time)
- Sandwich attacks (high risk of failed execution)
- Time-bandit attacks (chain never reorgs past finality)
7. Data Availability & Blobs
Non‑goal — no DA‑sampling layer. “Data availability” here means blob storage durability, not a Celestia/EigenDA‑style erasure‑coded data‑availability‑sampling layer. Cowboy has no such layer. Larger‑than‑inline data lives in the Cowboy File System (CBFS): durability comes from Reed‑Solomon replication across storage relays plus on‑chain Proof‑of‑Retrievability challenges andStorageCommitment anchoring, not from probabilistic availability sampling. See the Cowboy Storage Whitepaper for the canonical CBFS model.
7.1 Inline cap.
Inline blob cap is 64 KiB per output.
7.2 External blobs.
Larger data MUST be content‑addressed (e.g., IPFS). The on‑chain commitment MUST be a multihash.
7.3 Blob lifecycle.
Blobs have no protocol‑level TTL or automatic expiry at genesis. Their lifetime is tied to ownership and rent, not to a timer:
- Inline blobs (≤ 64 KiB, stored in the state trie) live as part of the owning actor’s storage and are subject to the same state rent as any other state (§4.4 / the State Rent section); they disappear only when the owner overwrites/deletes the value or the owning actor is evicted for unpaid rent.
- CBFS‑stored blobs (the off‑chain shard layer) persist until the owner explicitly deletes them or the owning account is evicted. There is no background expiry sweep over live blobs.
- Orphaned shards — previous shard versions left behind after a new manifest commits (CIP‑9’s
write_idkeeps old shards retrievable for rollback) — are the one garbage‑collected class: relay nodes prune them afterORPHAN_SHARD_TTL(86,400 blocks, ~24 h at 1s blocks; CIP‑9 §14).
8. Economics, Inflation, and Fees
8.1 Ticker & supply. CBY. Genesis supply 1,000,000,000 CBY. 8.2 Inflation. A decreasing inflation schedule is used to bootstrap network security. Gross inflation is offset by protocol burn mechanisms (§8.4); net inflation depends on network usage.| Phase | Years | Gross Inflation | Rationale |
|---|---|---|---|
| Bootstrap | 1–2 | 8% / 6% | Attract validators and runners while fee revenue is immature |
| Glidepath | 3–4 | 4% / 3% | Reduce dilution as fee revenue and network stability improve |
| Steady‑state | 5+ | 2% floor | Maintain security budget with low long‑run dilution |
| Bucket | % of Total | CBY | Vesting |
|---|---|---|---|
| Team & Core Contributors | 20.00% | 200,000,000 | 1‑year cliff, 4‑year linear monthly |
| Investors (Warrants / Token Rights) | 20.00% | 200,000,000 | 10% at TGE, 6‑month cliff, 24‑month linear |
| Advisors | 3.33% | 33,300,000 | 6‑month cliff, 24‑month linear, milestone gates |
| Treasury / Governance | 13.34% | 133,400,000 | 5% seed liquidity at TGE, remainder governance‑voted |
| Foundation / Ops Reserve | 10.00% | 100,000,000 | 5% at TGE, quarterly board‑approved releases over 36 months |
| Bucket | % of Total | CBY | Emission Model |
|---|---|---|---|
| Validator Rewards | 18.00% | 180,000,000 | Decreasing emission over 60 months |
| Runner Compute Incentives | 8.00% | 80,000,000 | Usage‑based; paid per runner‑hour |
| Developer Grants | 3.00% | 30,000,000 | Milestone‑based, grant committee |
| Liquidity Mining / DEX | 2.33% | 23,300,000 | Front‑loaded over 12 months |
| Community / Airdrops | 2.00% | 20,000,000 | 2 drops (TGE + 6 months) |
| Source | Split | Destination |
|---|---|---|
| Cycle & Cell basefees | 100% | Burned |
| Cycle & Cell tips | 100% | Proposer / validators |
| Runner job payments | 89% | Runner(s)¹ |
| Runner job payments | 10% | Burned |
| Runner job payments | 1% | Treasury |
| Slashed stake | 100% | Burned² |
aggregator_bonus_bps = 150 (= 1.5% of gross) of this 89% on successful settlement. The bonus is carved out of the runner share, not from the burn or treasury shares — so this row remains the literal 89% to runner‑side recipients.
² Distribution governance lives in SlashDistribution { burn_bps, submitter_bps, treasury_bps }. Genesis defaults (10000, 0, 0) preserve the 100%-burn commitment listed in this row; any non-zero submitter_bps or treasury_bps requires a Tier-3 governance proposal that updates this row in lockstep.
The runner fee burn is the primary deflationary mechanism beyond basefee burns. As network usage grows, the burn rate increases proportionally, creating a reflexive supply‑reduction loop that offsets inflation (see §8.2). Governance MAY adjust the runner fee burn percentage via standard proposal + timelock.
9. System Actors & Precompiles
This table is the single authoritative registry of system-actor addresses. Every protocol specification (the CIP series) that introduces, renumbers, or references a system actor MUST agree with this table; per-specification copies are informative mirrors of this section.| Address | Name | Status | Function |
|---|---|---|---|
| 0x01 | Runner Registry | code-deployed | Runner registration, staking, capabilities, health, reputation |
| 0x02 | Job Dispatcher | code-deployed | Job submission, VRF selection, lifecycle management |
| 0x03 | Result Verifier | code-deployed | Commit-reveal aggregation, verification, callback dispatch |
| 0x04 | Secrets Manager (CBSS) | code-deployed | Threshold-IBE (BLS12-381) secret storage and threshold release via a t-of-n proxy committee; holds proxy registration, per-account key material, per-secret policy, and release receipts |
| 0x05 | TEE Verifier | code-deployed | Remote attestation and trusted measurement verification. State co-location: handler semantics are live, but TEE state (trusted keys, attestation records) is currently persisted under 0x04; 0x05 holds the genesis actor record |
| 0x06 | Dual Basefee · Token Registry | code-deployed | Protocol dual-metered basefee state. Deliberately co-located: the fungible-token registry stores its state under the same address with disjoint storage keys; the two roles share an address but not semantics |
| 0x07 | Entitlement Registry | code-deployed | Runner Pool access control, general RBAC |
| 0x08 | Treasury | code-deployed | Protocol fee collection and distribution; receives the 1% runner settlement fee and other protocol-directed payments |
| 0x09 | Governance | code-deployed | On-chain protocol parameter governance; stores SettlementConfig (runner/burn/treasury split ratios) and other governable parameters |
| 0x0A | Storage Manager | code-deployed | Volume ownership, CapToken issuance/revocation, manifest anchoring, storage rent accounting (see Cowboy Storage Whitepaper) |
| 0x0B | Relay Registry | code-deployed | Storage Relay Node registration, staking, heartbeats, proof-of-retrievability challenges |
| 0x0C | Session Actor | code-deployed | Multi-party-payment session state: escrow and cumulative-voucher settlement |
| 0x0D | Stream Key Manager | code-deployed | Paid stream access tracking, billing, and content-key SealRequest emission to the Secrets Manager (CBSS) |
| 0x0E | Route Registry | code-deployed | Domain-binding records and FQDN → actor resolution |
| 0x0F | Gateway Registry | code-reserved | Gateway registration, staking, health; system-mediated ingress dispatch. Address constant allocated in code; handlers pending |
| 0x10 | Receipt Registry | code-reserved | Domain-action receipts. Address constant allocated in code; handlers pending |
| 0x11 | Container Registry | spec-allocated | OCI base-image allowlist and resource classes for container batch jobs |
| 0x12 | PaymentGate | spec-allocated | HTTP-native payment settlement (MPP / x402 wire formats normalize to one settlement layer) |
| 0x13 | BankActor | spec-allocated | Agent banking: long-lived card accounts, gas charging, policy enforcement |
| 0x1D | Event Subscription | virtual (code-active) | Subscription-bidding market RPC surface. No deployed actor: calls are intercepted in the PVM host and routed to native handlers; deliberately outside the dense 0x01–0x13 band |
node, runner/src/system_actors.rs), handlers not yet implemented. spec-allocated: claimed by an accepted specification in the CIP series, not yet in code. virtual: host-intercepted address with no code-bearing actor record.
Note (normative — allocation rules):Field-level instruction schemas, registry semantics, and on-chain encodings for each system actor are elaborated in the CIP series.
- The implementation’s system-actor registry (
node,runner/src/system_actors.rs) is the source of truth for every address with code-deployed or code-reserved status; this table MUST track it.- On a collision between specification claims, a deployed claim wins. Among undeployed claims, the earlier (lowest-numbered) specification’s claim wins; the losing specification MUST renumber to the next free slot.
- A specification that introduces a new system actor MUST claim the next free address in the dense sequence (
0x14next, as of this revision) and MUST update this table in the same change.- The full low-address space below 0x100 is reserved in the sense of state-rent exemption (
RESERVED_SYSTEM_ADDRESS_LIMIT): actors below it are exempt from rent. User actors cannot land there because deployed addresses are CREATE2-derived from(deployer, salt, code_hash)— the band is unreachable by construction rather than actively rejected. The PVM separately rejects the dense system band 0x01–0x0F forfee_payeroverrides;0x1Dsits deliberately outside that enforced band (see its row).
10. Developer Experience (DX)
- SDKs: A primary Python SDK (
cowboy-py) is provided. - Local dev: A suite of tools including a single-node devnet (
cowboyd), runner simulator, faucet, and explorer will be available. - Best practices: Reentrancy guards, capability-scoped handles, and idempotent message handling are encouraged via the SDK.
11. Governance & Upgrades
- Model: Token‑weighted on‑chain governance from genesis (bicameral: staked CBY + validator one‑vote). A permanent Security Council 7‑of‑9 holds narrow emergency authority (cancel queued proposals during timelock, fast‑track Tier‑3 upgrades, circuit‑break a system actor with mandatory retroactive ratification). Tier values, quorums, deposits, voting windows, and Council scope will be elaborated in a future CIP.
- Timelocks: Standard actions 7 days; emergency fast‑track 6 hours.
- Upgrades: Hot‑code upgrades coordinated by governance.
12. Security Considerations
12.1 DoS limits (consensus‑enforced; governance‑tunable).max_tx_size= 128 KiBmax_message_depth_per_tx= 32per_actor_per_block_cycles= 1,000,000 (burstable)
13. Parameters (Genesis Defaults)
Execution:memory_per_call = 10 MiB; storage_quota_per_actor = 1 MiB; reentrancy_depth = 32; fanout_per_tx = 1024; mailbox_capacity_bytes = 1,000,000; dedup_window = 10,000 blocks.
Fees:
T_c = 20,000,000 cycles (per-block hard cap = 80,000,000 across lanes); T_b = 4,000,000 bytes; basefee_alpha = 96; basefee_max_change = ±1/96 (~1.04%/block); MIN_BASEFEE = 10,000.
Consensus:
minimum_validator_stake = governance-tunable; epoch = 3600 blocks (~1 h); block_time = 1 s; finality = ~2 s; unbonding_period = 7 days; jail_period = 24 h; double_sign_slash = 1%; consensus_protocol = Simplex BFT.
Dedicated Lanes:
system_lane_capacity = 5%; timer_lane_capacity = 20%; runner_lane_capacity = 25%; user_lane_capacity = 50%.
lane_fee_multiplier_system = 1.0; lane_fee_multiplier_timer = 1.0; lane_fee_multiplier_runner = 1.0; lane_fee_multiplier_user = 1.0. (All Tier-0 governance-tunable.)
Off‑chain:
committee M, threshold N = adaptive (active): M = clip(ceil(2 · log₂(N_active) / max(HHI, 0.01)), 3, 9) (m_min=3, m_max=9), N = ceil(2M/3); recomputed per 3,600-block epoch with EMA smoothing of HHI. (M = 5, N = 3 was the initial fixed fallback.) challenge_window = 15 min; challenge_bond = 100 CBY; runner_stake_floor = 10,000 CBY (CBY-denominated; no oracle dependency at launch); dispute_window_blocks = 75. reputation_half_life_blocks = 1,209,600 (~14 days at 1s blocks); aggregator_eligibility_percentile = 50 (p50 reputation); aggregator_bonus_bps = 150 (1.5% of gross, paid from runner share); non_reveal_slash_bps = 2500 (25% of effective stake on proven non-reveal); slash_distribution.{burn_bps, submitter_bps, treasury_bps} = (10000, 0, 0) (genesis 100%-burn per §8.4; Tier-3 to amend).
State Rent:
target_state_size = governance-tunable; grace_period = 7 rent‑epochs; warning_period = 3 rent‑epochs; catch_up_fee = 10% (Tier‑0 tunable as rent_catchup_bps = 1000); reserve_multiplier = 0.1; rent_rate = 0.001 CBY/byte/year (Tier‑0); rent_epoch_length = 86,400 blocks (~1 day at 1s blocks per WP §6.1); eviction_threshold_epochs = 10; grace_threshold = 10,240 bytes (10 KB).
Economics:
supply = 1,000,000,000; company_reserve = 66.67%; inflation follows the schedule in §8.2; basefee burn = 100%; runner_fee_burn = 10%; job_fee_to_treasury = 1%; runner_payout = 89%.
13.1 Parameter Governance Registry
The canonical mapping from each governance‑tunable parameter group to the 0x09 Governance storage key that holds it, its owning specification, and its genesis default. Storage keys are verified against the reference implementation (node/types/src/constants.rs); per‑parameter live values and their amendment history are also addressable through the generic registry prefix system:gov:param:<key> with an audit trail at system:gov:param:history:<key>.
| Parameter group | Spec | 0x09 storage key | Genesis default | Tier |
|---|---|---|---|---|
| Settlement split (runner/burn/treasury) | CIP‑2 | system:settlement_config | 89% / 10% / 1% | Tier‑3 |
Basefee config (T_c, T_b, alpha, delta) | CIP‑3 | system:basefee_config | 20,000,000 / 4,000,000 / 96 / 1/96 | Tier‑0 |
| Lane fee multipliers (system/timer/runner/user) | CIP‑3 | system:lane_fee_multipliers | all 1.0× | Tier‑0 |
| Timer config | CIP‑5 | system:timer_config | see §5.1 | Tier‑0 |
State‑rent config (rent_rate, rent_catchup_bps, …) | CIP‑4 | system:cip4:rent_config | 0.001 CBY/byte/yr; 1,000 bps | Tier‑0 |
| Reputation config (half‑life, percentile) | CIP‑2 | system:cip2:reputation_config | 1,209,600 blk; p50 | Tier‑0 |
Aggregator config (aggregator_bonus_bps) | CIP‑2 | system:cip2:aggregator_config | 150 bps | Tier‑0 |
Slash distribution (burn/submitter/treasury_bps) | CIP‑2 / §8.4 | system:cip2:slash_distribution | (10000, 0, 0) | Tier‑3 |
Non‑reveal slash (non_reveal_slash_bps) | CIP‑2 | system:cip2:non_reveal_config | 2,500 bps | Tier‑0 |
Committee sizing (M, N) | CIP‑2 | system:cip2:committee_config | M=5, N=3 (static fallback) | Tier‑0 |
| Semantic‑similarity model id | CIP‑2 | system:cip2:semantic_similarity_embedding_model | (governance‑set) | Tier‑0 |
| Generic registered parameters | CIP‑12 | system:gov:param:<key> (+ …:history:<key>) | per parameter | Tier‑0/3 |
constants.rs / gas.rs is tracked as a follow‑up. The state‑rent rate (spec 0.001 vs code ≈ 1 CBY/byte/yr) differs from the reference implementation and is being reconciled under COW‑2266. Where the registry mirrors spec prose, the spec value is shown; the CI check will surface every such divergence.
14. Differences vs. Ethereum
- Execution: Python actors vs. EVM contracts.
- Fees: Dual meters (cycles/cells) vs. single gas scalar.
- Timers: Native timers vs. external keepers.
- Off‑chain compute: Native verifiable Runner market (encrypted CBFS volumes, container jobs) vs. external oracles only.
- State: Rent with eviction vs. indefinite storage.
15. Entitlements
A declarative, composable permissions system governs the capabilities of actors and runners. Entitlements control access to resources like networking, storage, and execution parameters, enforcing least-privilege by default. The system is enforced at deployment time, by the scheduler, and at the VM syscall gate. 15.1 Goals- Least privilege by default.
- Deterministic enforcement.
- Declarative & composable.
- Auditable on-chain.
- Actor Entitlements: Permissions the actor requires.
- Runner Entitlements: Capabilities the runner provides.
- MUST: Actors
requireentitlements; runnersprovidethem. - MUST: Scheduler matches only if
requires ⊆ provides. - MUST: Syscalls fail if the corresponding entitlement is missing.
- MUST: Child actors only inherit entitlements marked
inheritable:true.
16. Ethereum Interoperability
Cowboy’s interoperability with Ethereum is a primary design goal, enabling seamless asset transfer and cross-chain communication. This is achieved through a combination of shared cryptographic primitives, a governance-selected third-party bridge, and event subscription mechanisms. Actor access to bridge operations is gated by thebridge.asset and bridge.subscribe_event entitlements.
16.1. Account Unification
- Cowboy external accounts (EOAs) MUST use the same
secp256k1elliptic curve for signatures as Ethereum. This allows a single private key to control accounts on both networks, simplifying key management for users and agents. - An actor, through a host call, MAY verify an EIP-712 signed data structure against a given Ethereum address, enabling actors to validate off-chain authorizations from Ethereum users.
16.2. Bridge Infrastructure
Cowboy relies on third‑party bridge infrastructure for asset transfers and cross‑chain message passing between Cowboy and Ethereum. Requirements:- The bridge MUST support the locking of native ETH and ERC-20 tokens on Ethereum to mint a corresponding wrapped representation on Cowboy (
wETH,wERC-20), and the reverse burn‑to‑unlock flow. - The bridge MUST support generic message passing: a transaction on one chain triggering a message call to a designated recipient on the other.
- Bridge selection and integration are determined by governance. The protocol does not implement its own bridge validator set.
16.3. Event Subscription (Ethereum to Cowboy)
- Cowboy actors MAY subscribe to event logs emitted by specific contracts on the Ethereum blockchain.
- A system actor on Cowboy,
EventListener(deferred; address to be assigned from the next free slot per the §9 allocation rules —0x14as of this revision), SHALL manage these subscriptions when implemented. This actor relies on the bridge validator set to act as a decentralized oracle, monitoring the Ethereum chain for specified events. - When a subscribed event is confirmed (i.e., finalized on Ethereum), the
EventListeneractor MUST enqueue a message to the subscribing Cowboy actor, delivering the event’s topic and data as the message payload. - The cost of this subscription service SHALL be paid by the actor in CBY, covering the gas fees incurred by the oracle validators on Ethereum.
16.4. Policy and Security
- All interoperability functions available to an actor, such as
bridge_assetorsubscribe_event, MUST be governed by the Entitlements system (§15). - An actor’s deployment manifest MUST declare the specific Ethereum contracts it is permitted to interact with and the types of assets it is allowed to bridge, enforcing the principle of least privilege.
17. Fee Model Specification
This section is authoritative; any conflicting values elsewhere are non‑normative.17.1. Overview
Cowboy uses a dual-metered fee system:| Meter | Unit | Purpose |
|---|---|---|
| Cycles | Compute units | CPU time, opcode execution, actor API calls |
| Cells | Data units (bytes) | Storage writes, calldata, bandwidth |
- On-chain execution — Cycles consumed by transaction processing
- On-chain storage — Cells consumed by state writes + ongoing state rent
- Off-chain services — Direct CBY payments to Runners (LLM, HTTP, MCP, containers, etc.) and Providers (blob storage)
17.2. Transaction Intrinsic Costs
Every transaction pays a base cost before execution begins:| Transaction Type | Base Cycles | Base Cells | Notes |
|---|---|---|---|
| Transfer | 21,000 | 0 | EOA-to-EOA value transfer |
| Deploy | 100,000 | code_size | Actor deployment |
| ActorMessage | 21,000 | calldata_size | Method invocation |
| LlmRequest | 10,000 | prompt_size | Off-chain inference request |
| TimerSchedule | 5,000 | 64 | Schedule future execution |
Note: Intrinsic costs for other runner-related txs (e.g. JobSubmit payloads for HTTP, MCP, Container, VolumeAnchorManifest) will be enumerated in future CIPs as those transaction types are formalized.
17.3. Execution Costs (Cycles)
Opcode Costs
Python opcode costs are implementation-defined and not protocol-specified. The runtime MUST ensure deterministic cycle consumption across all validators.Actor API Costs
| Operation | Base Cost | Variable Cost |
|---|---|---|
send_message() | 80 cycles | — |
storage_read() | 100 cycles | — |
storage_write() | 200 cycles | — |
hash() | per algorithm (keccak256 ~6/32B, sha256 500+8/block) | — |
verify_signature() | 5,000 (Ed25519) / 10,000 (secp256k1) / 8,000 (BLS) | — |
get_block_info() | 100 cycles | — |
emit_event() | 500 cycles | +5 cycles/byte |
The authoritative per-opcode cost schedule and its update procedure will be elaborated in a future CIP.
Platform Token Costs
| Operation | Cycles | Cells |
|---|---|---|
token_transfer() | 1,000 | 64 |
token_transfer_from() | 1,500 | 96 |
token_approve() | 500 | 32 |
token_balance_of() | 100 | 0 |
token_mint() | 1,000 | 64 |
token_burn() | 500 | 64 |
token_create() | 10,000 | 256 + name + symbol |
17.4. On-Chain Storage Costs (Cells)
| Operation | Cell Cost |
|---|---|
| State write | 1 cell/byte written |
| State read | 0.01 cells/byte (bandwidth metering) |
| Calldata | 1 cell/byte of transaction data |
| Event emission | 0.5 cells/byte of event data |
17.5. State Rent
Accounts exceeding the grace threshold pay ongoing rent. This section provides the operational summary plus the governance monitoring cadence for CBY-denominated rent.- Accounts ≤10 KB: No rent charged
- Accounts >10 KB: Rent charged on excess bytes only
- Unpaid rent accumulates as debt against the account (rate-stamped to the epoch the debt was incurred; rate hikes apply prospectively only)
- Eviction after 10 rent-epochs of accumulated debt (state archived; recoverable on debt repayment plus 10% catch-up fee)
[$1, $10] / MiB / year. If the implied USD value drifts outside the band for two consecutive monthly reviews, a Tier-0 governance proposal MUST be filed to adjust rent_rate. Re-pegging to USD via oracle (with a battle-tested CBY/USD oracle module as precondition) is left to a future revision.
17.6. Off-Chain Blob Storage
Large data (images, datasets, AI inference traces) uses Retention Contracts:| Cost Component | How Charged |
|---|---|
| BlobRef storage | ~64 bytes on-chain → Cell cost + state rent |
| Provider payments | Direct CBY to Provider via escrow (market rate) |
17.7. Off-Chain Compute (Runner Marketplace)
Off-chain job execution (LLM, HTTP, MCP, Custom, Container) is not gas-metered on the cycle/cell meters. Runners operate in a competitive marketplace:| Aspect | Specification |
|---|---|
| Pricing | Runners publish rate cards (e.g. CBY per token, per HTTP request, per compute second; storage/volume capability and container limits declared in registry metadata) |
| Selection | Actors specify max_price (and optional tip) in JobSpec; dispatcher matches eligible runners via VRF sortition |
| Settlement | On verified delivery: 89% to runner, 10% burned, 1% to Treasury |
| Collateral | runner_stake >= max(10,000 CBY, 1.5 × declared_max_job_value) |
| Verification | N-of-M, TEE, structured matching, etc.; attestation and challenges enforced by the on-chain Result Verifier |
Field-level JobSpec / RateCard / verification-mode schemas, and the full runner-marketplace state machine, will be elaborated in future CIPs.
17.8. Fee Adjustment (EIP-1559 Style)
Both Cycles and Cells use independent basefee adjustment:α = 96(BASEFEE_ALPHA — calibrated for 1-second blocks, vs Ethereum’s 8 for 12-second blocks)- max change = ±1/96 (~1.04%) per block (BASEFEE_MAX_CHANGE_DENOM = 96)
MIN_BASEFEE = 10,000(floor; keeps the basefee in the geometric-update regime)clamp(v, -1/96, +1/96)caps the per-block adjustment
| Parameter | Value |
|---|---|
| Target | 20,000,000 cycles/block |
| Block hard cap | 80,000,000 cycles (sum of lanes) |
| Max change/block | ±1/96 (~1.04%) |
| α (BASEFEE_ALPHA) | 96 |
| Parameter | Value |
|---|---|
| Target | 4,000,000 bytes/block |
| Max change/block | ±1/96 (~1.04%) |
| α (BASEFEE_ALPHA) | 96 |
17.9. Reserved Capacity (Execution Lanes)
Block space is partitioned to guarantee execution for critical transaction types:| Lane | Cycle Budget | Percentage | Fee Multiplier | Purpose |
|---|---|---|---|---|
| System | 40,000,000 | 50% | 1.0× | Governance, upgrades |
| User | 22,222,222 | ~27.8% | 1.0× | Regular transactions |
| Runner | 8,888,888 | ~11.1% | 1.0× | Runner job results, attestations, callbacks (incl. storage manifest anchors) |
| Timer | 8,888,890 | ~11.1% | 1.0× | Scheduled actor execution |
- Unused capacity in reserved lanes spills to User lane
- User lane cannot borrow from reserved lanes
- Timer lane has highest priority within its reserved capacity; execution is still subject to GBA bidding and per‑block limits
- Per‑lane
Fee Multiplierscales the lane’s effective basefee (lane_basefee = global_basefee × lane_fee_multiplier); all four lanes default to1.0×(no subsidy, no surcharge). Tier-0 governance-tunable.
17.10. Fee Estimation
Wallets and applications SHOULD estimate fees as:Appendix A. Transaction Encoding Test Vectors (Normative)
These vectors specify the canonicalcommonware‑codec encoding (§2.5). Hex is lowercase, no
0x prefix. They are the byte contract cross‑implementation clients (wallet, SDK) MUST reproduce.
Shared transfer fields (both vectors): chain_id=42, nonce=0,
instruction = System(Transfer { to=0x2222222222222222222222222222222222222222, amount=1 }),
cycles_limit=50000, cells_limit=50000, max_fee_per_cycle=1, max_fee_per_cell=1,
max_priority_fee_per_cycle=0, max_priority_fee_per_cell=0,
from=0x19e7e376e7c213b7e7e7e46cc70a5dd086daff2a (derived from the fixed key 0x11…11, 32 bytes),
access_list=null, metadata="", origin_*=null, additional_signers=[].
Vector 1 — Unsigned (all signatures zero) = the signing/identity preimage:
2a=chain_id 42 (UInt) · 00=nonce · 00 01=System / Transfer · 2222…22=to
(20B) · 0000000000000001=amount (8‑byte BE) · d08603 d08603=cycles/cells_limit 50000 (UInt) ·
01 01=fees · 00 00=priority fees · 19e7…ff2a=from (20B) · 00=access_list None ·
00=metadata len 0 · 00 00 00=origin_* None · 65 zero bytes=signature · 00=additional_signers len 0.
The signing hash = keccak256(the bytes above) =
203b9aa5435ad7de1164fa534c9d72de46e734a9d99703790756380c67b8304a. The transaction digest
(identity) equals this value (signature‑independent).
Vector 2 — Signed (Vector 1 signed with the fixed key 0x11…11; secp256k1 RFC‑6979 deterministic,
low‑S; signature = r‖s‖v):

