Skip to main content

Overview

Cowboy introduces four fundamental innovations that enable autonomous agents and verifiable computation at the protocol level. Each innovation addresses a critical limitation in existing blockchain platforms.
Note: The examples below are conceptual snippets to illustrate architecture and mechanisms. Final interfaces and usage should follow the SDK and Developer Guide.

Native Timers

Protocol-level scheduling with O(1) performance

Dual-Metered Gas

Independent pricing for compute and storage

Python Smart Contracts

Deterministic VM for high-level language

Verifiable Off-Chain

Decentralized computation with cryptographic proofs

1. Native Protocol Timers

The Problem

Traditional blockchains have no concept of time-based execution:
// ❌ Ethereum: This function never executes itself
contract Liquidator {
    function checkPosition() public {
        if (position.isUndercollateralized()) {
            liquidate();
        }
        // Who calls this function? When?
    }
}
Current workarounds:
  • Cron jobs: Centralized, single point of failure
  • Keeper networks: Expensive, complex to integrate
  • User triggers: Poor UX, unreliable

Cowboy’s Solution: Hierarchical Calendar Queue

A three-tiered scheduling system built into the consensus layer:
+--------------------------------------------------------------------+
|  Layer 3: Overflow Sorted Set (long-term)                          |
|  - Merkleized balanced BST                                         |
|  - For distant future timers                                       |
+-------------------------------+------------------------------------+
                                | Promote timers as they enter range
                                v
+--------------------------------------------------------------------+
|  Layer 2: Epoch Queue (mid-term)                                   |
|  - Array of epoch buckets (e.g., hourly epochs)                    |
|  - Amortized promotion cost                                        |
+-------------------------------+------------------------------------+
                                | Promote timers as epoch approaches
                                v
+--------------------------------------------------------------------+
|  Layer 1: Block Ring Buffer (near-term)                            |
|  - Fixed-size array (e.g., 256 blocks)                             |
|  - O(1) enqueue and dequeue                                        |
|  - Bucket per block height                                         |
+--------------------------------------------------------------------+
Key properties:
  • O(1) scheduling: Constant-time enqueue for near-term timers
  • Scalable: Handles millions of timers efficiently
  • Deterministic: Part of consensus state
  • Fair: Gas bidding prevents DoS

Dynamic Gas Bidding

Actors compete for timer execution during congestion (CIP-1):
  • Schedule a timer referencing a designated Gas Bidding Agent (GBA).
  • When due, the producer queries the GBA with protocol context to obtain fee params.
  • Timers are prioritized by effective tip within a fixed per-block processing budget.
// CIP-1: Standard GBA interface (normative)
interface GasBiddingAgent {
  function getGasBid(bytes calldata context) external view returns (TxFeeParams);
}
Context provided to GBA: Context provided to GBA (CIP-1):
  • trigger_block_height — originally scheduled height
  • current_block_height — current height (for delay)
  • basefee_cycle — current cycle basefee
  • basefee_cell — current cell basefee
  • last_block_cycle_usage — congestion indicator
  • owner_actor_balance — actor’s current CBY balance
Benefits:
  • Actors self-prioritize based on urgency
  • Market-driven resource allocation
  • DeFi liquidations can bid high during volatility
  • Non-critical tasks bid low during congestion

DoS Protection

Fixed per-block budget prevents abuse:
# Protocol constants
TIMER_PROCESSING_BUDGET_CYCLES = 10_000_000  # Example value per block
RING_BUFFER_SIZE = 256  # Example ring buffer size
EPOCH_SIZE = 360  # Example epoch blocks (~1 hour)
How it works:
  1. At each block, timers sorted by effective tip
  2. Execute highest-priority timers first
  3. Stop when budget exhausted
  4. Unexecuted timers roll over to next block
Result: Regular transactions always have guaranteed block space.

2. Dual-Metered Gas Model

The Problem

Single gas metrics are fundamentally unfair:
# Scenario A: Heavy compute, small storage
def verify_proof(proof):  # 100,000 gas
    # Complex cryptography
    return is_valid

# Scenario B: Light compute, large storage  
def store_blob(data):  # 100,000 gas
    storage[key] = data  # 10 KB

# Problem: Both cost the same, but have different resource impacts!
Real-world impacts:
  • Storage-heavy apps subsidized by compute-heavy apps
  • Unpredictable costs (gas depends on market, not actual usage)
  • Incentive misalignment (storage should cost more long-term)

Cowboy’s Solution: Cycles + Cells

Two independent dimensions with separate fee markets:
What it measures: CPU workMetering method: Instruction-level trackingExamples:
# Arithmetic: 1 cycle
x = a + b

# Function call: 10 cycles  
result = foo(x)

# Dictionary access: 3 cycles
value = my_dict[key]

# Cryptography: 3,000 cycles
verify_ecdsa(msg, sig, pubkey)

# String operation: 1 cycle per character
result = "hello" + "world"  # 10 cycles
See: Fee Model Overview

Independent Fee Markets

Each resource has its own EIP-1559 style basefee:
# Cycle market
basefee_cycle_new = basefee_cycle_old × (1 + (U_c - T_c) / T_c / α)

# Cell market  
basefee_cell_new = basefee_cell_old × (1 + (U_b - T_b) / T_b / α)

# Where:
# U = actual usage in parent block
# T = target usage (typically 50% of limit)
# α = adjustment speed (e.g., 8)
Benefits:
  • Each resource priced based on its own demand
  • Compute-heavy apps don’t affect storage prices
  • Storage bloat doesn’t affect compute prices
  • Fair for all use cases

Example: Fair Pricing in Action

# App A: AI inference (high compute, low storage)
def run_model(input_data):
    result = heavy_computation(input_data)  # 50,000 Cycles
    self.storage.set("result", result)      # 100 Cells
    return result

# Cost: 50,000 × basefee_c + 100 × basefee_b
# Mostly pays for compute ✅

# App B: Data marketplace (low compute, high storage)
def store_dataset(dataset):
    self.storage.set("data", dataset)  # 1,000,000 Cells
    return "stored"                     # 500 Cycles

# Cost: 500 × basefee_c + 1,000,000 × basefee_b  
# Mostly pays for storage ✅

3. Deterministic Python VM

The Problem

Smart contract languages are niche and difficult:
// Solidity: Steep learning curve
contract Counter {
    uint256 private count;
    
    function increment() public {
        count += 1;
    }
}
Challenges:
  • New language to learn
  • Limited tooling and libraries
  • Difficult to express complex logic
  • Small developer community

Cowboy’s Solution: Python with Determinism

# Conceptual example (non-normative API)
class Counter:
    def __init__(self):
        self.count = 0
    def increment(self):
        self.count += 1
        return self.count

Achieving Determinism

Challenge: Python is inherently non-deterministic (dict ordering, floats, GC, etc.) Cowboy’s approach: Constrained deterministic subset
All floating-point operations use deterministic software implementation.
# ✅ Deterministic across all hardware
x = 3.14159 * 2.71828  # Software math library

# ❌ Hardware FPU (non-deterministic)
Only whitelisted modules allowed.
# ✅ Allowed
import math  # Deterministic software impl
import hashlib  # Deterministic hashing
import cowboy  # Protocol APIs

# ❌ Prohibited
import os  # System calls
import requests  # Network I/O
import random  # Non-deterministic
Reference counting + no cycle detection during execution.
# Memory management is immediate and deterministic
obj = [1, 2, 3]  # Allocate: charged Cells
del obj           # Deallocate: charged Cycles
Pure interpretation mode only.
  • Ensures identical execution across nodes
  • Predictable gas costs
  • No non-deterministic optimization
No concurrency, no race conditions.
# ✅ Single message at a time
def handle_message(self, msg):
    # No concurrent access to self.state
    self.state += 1

# ❌ No threads, no asyncio.gather(), etc.

Sandboxing

The VM enforces strict isolation:
  • ✅ Allowed (conceptual): persistent storage via host functions; actor messaging; timer scheduling; deterministic hashing.
  • ❌ Prohibited: file I/O, network access, system calls, non-deterministic randomness.

Resource Metering

Every operation has a precise cost:
# Operation costs (examples)
x = 1 + 2                    # 1 Cycle
foo()                        # 10 Cycles (call)
"hello" + "world"            # base + per-char surcharge
[x for x in range(1000)]     # 40 + 2000 + ... Cycles
verify_ecdsa(msg, sig, pk)   # 3000 Cycles
See also: Fee Model Metering Points

4. Verifiable Off-Chain Compute

The Problem

On-chain computation is expensive and limited:
# ❌ Can't do this on-chain
def analyze_sentiment(text):
    model = load_model("bert-large")  # 500 MB model
    return model.predict(text)        # 1B+ operations

# ❌ Can't do this on-chain  
def fetch_price():
    response = requests.get("https://api.coingecko.com/...")
    return response.json()
But off-chain introduces trust issues!

Cowboy’s Solution: Decentralized Runner Network

Outsource computation to a marketplace of runners with verifiable results (CIP-2):
  • Submit a task to the Dispatcher with a mandatory result_schema and payment terms.
  • Runners self-select via VRF-based logic and either execute or skip deterministically.
  • Results and (optional) proofs are submitted on-chain; when N results are collected, a deferred callback is triggered.
  • The Actor consumes a chosen result and finalizes payment distribution.

VRF-Based Runner Selection

No centralized scheduler required:
# Deterministic, verifiable selection
start_index = hash(vrf_seed + (submission_block - vrf_generation_block)) % list_size
selected_runners = active_runner_list[start_index : start_index + N]
Properties:
  • ✅ Decentralized: No single coordinator
  • ✅ Verifiable: Anyone can check selection validity
  • ✅ Unpredictable: Can’t game the system
  • ✅ Fair: All runners have equal probability

Runner Lifecycle

+--------------------------------------------------------------------+
|  1. Task Submission                                                |
|  Developer submits task + schema + payment                         |
+-------------------------------+------------------------------------+
                                |
                                v
+--------------------------------------------------------------------+
|  2. VRF Selection                                                  |
|  Deterministic runner assignment                                   |
+-------------------------------+------------------------------------+
                                |
                                v
+--------------------------------------------------------------------+
|  3. Off-Chain Execution                                            |
|  Selected runners execute task                                     |
|  - Download data/models                                            |
|  - Run computation                                                 |
|  - Generate proof (if required)                                    |
+-------------------------------+------------------------------------+
                                |
                                v
+--------------------------------------------------------------------+
|  4. Result Submission                                              |
|  Runners submit results + proofs on-chain                          |
+-------------------------------+------------------------------------+
                                |
                                v
+--------------------------------------------------------------------+
|  5. Deferred Callback                                              |
|  When N results collected, callback triggered                      |
+-------------------------------+------------------------------------+
                                |
                                v
+--------------------------------------------------------------------+
|  6. Payment Distribution                                           |
|  Actor chooses winning result, runner gets paid                    |
+--------------------------------------------------------------------+

Flexible Verification

Choose the proof type based on your requirements:
Use case: General computation with economic security
  • Configure N runners; accept when ≥ quorum match.
  • Pros: Simple, broad applicability
  • Cons: Pay multiple runners

Economic Model

Market-driven pricing, not protocol gas:
# Runners self-price based on:
# • Compute time
# • Memory usage  
# • Model download costs
# • Hardware costs (TEE premium)
# • Desired profit margin

# Actors choose based on:
# • Task urgency
# • Required proof type
# • Budget constraints
Result: Efficient market where actors pay fair prices for actual resources consumed.

How They Work Together

These four innovations combine to enable powerful use cases:

Example: Autonomous DeFi Liquidation Bot

Steps (illustrative):
  1. Submit off-chain task to fetch prices (CIP-2)
  2. Process results (compute-heavy → cycles)
  3. Execute necessary storage updates (data-heavy → cells)
  4. Schedule next check with GBA (CIP-1)
Uses all four innovations:
  1. Native Timers: Self-schedules every 60 blocks
  2. Dual Gas: Pays fairly for compute vs. storage
  3. Python VM: Express complex logic easily
  4. Off-Chain: Fetch external price data

Next Steps

Architecture Deep Dive

Understand the complete system design

Actor VM

Learn how the Python VM achieves determinism

Fee Model

Deep dive into Cycles and Cells metering

Scheduler

Read the timer and bidding overview

Further Reading