Skip to main content

Introduction

Cowboy’s Actor VM executes Python code in a deterministic and sandboxed environment. This document explains the technical challenges and solutions for running a high-level, dynamic language like Python on a blockchain.
Core Challenge: Python is inherently non-deterministic and has unlimited system access. We must constrain it without breaking its expressiveness.
Note: Examples in this page are conceptual snippets/pseudocode. Final interfaces and usage should follow the SDK and Developer Guide. CIP specifications define normative protocol behavior.

Why Determinism Matters

The Consensus Requirement

Same input and environment MUST lead to the same state transition and outputs on all nodes; any divergence implies consensus failure. What happens if non-deterministic:
  • ❌ Nodes cannot agree on state root
  • ❌ Chain halts or forks
  • ❌ Network is unusable

Sources of Non-Determinism

Key sources include: system time, OS randomness, filesystem and network I/O, hardware floating-point variance, and reliance on container iteration order. These must be either prohibited or made deterministic per protocol rules.

Cowboy’s Determinism Solutions

1. No System Dependencies

Problem: System calls produce different results on different machines. Solution: Complete isolation from host system.

2. Software Floating-Point

Problem: Hardware FPUs produce slightly different results across CPU architectures. Solution: Deterministic software implementation of IEEE 754.
Trade-off:
  • ✅ Deterministic across all platforms
  • ❌ ~2-5× slower than native FPU
  • ✅ Acceptable for blockchain consensus

3. Deterministic Memory Management

Problem: Garbage collection timing is non-deterministic in standard Python. Solution: Reference counting with immediate, deterministic cleanup.
Key properties:
  • Immediate: Objects destroyed when refcount reaches 0
  • Deterministic: Same operations → same cleanup timing
  • Metered: Destruction costs charged in Cycles
  • No cycle detection: Circular references forbidden

4. No JIT Compilation

Problem: JIT compilers make non-deterministic optimization decisions. Solution: Pure interpretation mode only.
Trade-off:
  • ✅ Deterministic execution
  • ✅ Predictable gas costs
  • ❌ Slower than JIT (10-100×)
  • ✅ Acceptable for blockchain (security > speed)

5. Dictionary Ordering and Serialization

Problem: Relying on dictionary iteration order can introduce non-determinism. Solution: Do not rely on in-memory iteration order when it affects results. When order matters, sort keys explicitly. Per CIP‑3, dictionary keys MUST be sorted lexicographically during serialization to ensure determinism.
Implementation:
  • Serialization: keys sorted lexicographically (CIP-3 requirement)
  • In execution paths where order impacts results, explicitly sort

6. Prohibited Async Concurrency

Problem: async/await scheduling can be non-deterministic. Solution: Strict deterministic scheduling (FIFO queue).
Rules:
  • Single-threaded execution only
  • FIFO queue for awaiting coroutines
  • No asyncio.gather() or similar
  • Deterministic scheduling guaranteed

7. String Encoding Determinism

Problem: Encoding edge cases handled differently across platforms. Solution: UTF-8 only, strict mode.

8. Integer Precision Limits

Problem: Arbitrary precision enables DoS attacks. Solution: 4096-bit limit with overflow checks.
Benefits:
  • ✅ Prevents big-int DoS attacks
  • ✅ Proportional costs for large integers
  • ✅ Still larger than practical needs (4096 bits >> 256 bits for crypto)

Sandboxing Mechanisms

Module Whitelist

Enforcement: Import hook intercepts all imports.
Costs:
  • First import: 100 cycles + module init
  • Cached import: 5 cycles
  • Failed import: 50 cycles (penalty)

System Isolation

Actors cannot perform file, network, or process operations. Access to host OS is prohibited; only protocol-provided, deterministic and metered host APIs are available.

Resource Limits

Enforcement overview:
  • Cycles: instruction-level metering; execution halts on limit (CIP‑3).
  • Cells: metered at I/O boundaries (calldata, storage, blobs, return data) per CIP‑3.
  • Memory/stack: hard limits enforced; overflow triggers deterministic errors.

Host Function APIs

Enforcement: Only whitelisted host functions callable.

Testing Determinism

A determinism test suite validates that identical inputs produce identical outputs and state transitions across environments, covering metering, serialization (sorted keys), exception handling, and software floating‑point behavior.

Sandboxing Verification

Security Audit Checklist

  • No file system access
  • No network access
  • No process creation
  • No system time access
  • No environment variable access
  • No native code execution
  • Import whitelist enforced
  • No dynamic module loading
  • No C extension loading
  • Standard library limited
  • Protocol APIs only
  • Cycle limit enforced
  • Cell limit enforced
  • Memory limit enforced
  • Stack depth limit enforced
  • Integer size limit enforced
  • Software FPU only
  • No JIT compilation
  • Deterministic GC
  • No true randomness
  • No system dependencies

Performance Considerations

Determinism and security take precedence over raw speed. The VM uses software floating‑point, prohibits JIT, and enforces deterministic memory management per CIP‑3.

Best Practices

Design with determinism in mind from the start:
Leverage protocol-provided functionality:
Verify determinism in tests:

Next Steps

Actor VM Overview

High-level VM architecture

Resource Limits

Detailed limit specifications

CIP-3 Metering

Complete metering specification

Best Practices

Writing efficient actors

Further Reading