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

Further Reading