This project provides a simplified Rust simulation of the concepts presented in the ColliderVM: Stateful Computation on Bitcoin paper. It demonstrates the core mechanisms of ColliderVM, particularly the use of presigned transaction flows and hash collision challenges for enabling stateful computation on Bitcoin without relying on fraud proofs.
Disclaimer: This is a toy simulation and does not implement a production-ready ColliderVM protocol. It simplifies some aspects for clarity and focuses on the protocol's structural flow and the hash collision mechanism.
The ColliderVM paper proposes a method to achieve stateful computation on Bitcoin, addressing limitations of the Bitcoin script language. Key concepts include:
- Stateful Computation: Enabling computations (data & logic) to persist across multiple Bitcoin transactions.
- Actors:
- Signers (n): Offline setup participants who create and sign transaction templates (flows). Assume 1-of-n are honest for safety (preventing invalid state transitions).
- Operators (m): Online execution participants who provide inputs, find nonces via hashing, and broadcast transactions. Assume 1-of-m are honest for liveness (ensuring the process can proceed).
- Presigned Flows (
D
): A set of2^L
pre-agreed, parallel transaction sequences. Each flow corresponds to a unique identifierd
from the setD
. - Hash Collision Challenge: To ensure the same input
x
is used across steps in a chosen flowd
, the Operator must find a noncer
such that the firstB
bits of a hashH(x, r)
match that specific flow identifierd
(i.e.,H(x, r)|_B = d ∈ D
). - Computational Gap:
- Honest Work: Finding any valid pair
(x, r)
such thatH(x, r)|_B ∈ D
takes~2^(B-L)
hash computations. - Malicious Work (Double Collision): Finding two different pairs
(x, r) ≠ (x', r')
that map to the same flowd
(i.e.,H(x, r)|_B = H(x', r')|_B = d
) takes significantly more work (~2^(B-L/2)
), making it computationally expensive to cheat by using different inputs within the same flow.
- Honest Work: Finding any valid pair
- Capital Efficiency: A key goal is to avoid the capital lock-up periods associated with fraud-proof-based systems like BitVM2.
This simulation implements a minimal proof-of-concept:
- Simple Function (
F
): Instead of complex logic (like STARK verification), the computationF(x)
is split into two subfunctions:F1(x)
: Checks ifinput_value > 100
.F2(x)
: Checks ifinput_value < 200
.- The overall computation succeeds only if
F1(x) AND F2(x)
is true for the same inputx
within the chosen flow.
- Simulated Actors: Generates
n
Signers andm
Operators withsecp256k1
key pairs (SignerInfo
,OperatorInfo
), but their roles in complex multi-party signing or liveness are simplified. - Simulated Presigning: Creates placeholder Bitcoin
Transaction
structures (create_placeholder_tx
) and calculates simplified sighash messages (create_toy_sighash_message
). It collects real Schnorr signatures but doesn't handle actual UTXO management or realistic fee calculation. - Simplified Bitcoin Script:
- Hash Check: The script check
H(x, r)|_B = d
is executed according to the rules of the paper for the prefix check. - Signature Check: Scripts include
OP_CHECKSIGVERIFY
and the Signer's public key. However, thebitvm::execute_script_buf
function used for simulation does not perform cryptographic signature verification. It checks script logic but assumes signatures are valid if provided.
- Hash Check: The script check
- Limited Flows: Generates
min(2^L, 16)
flows instead of the full2^L
for performance reasons in this demo. - Off-Chain Hashing: The Operator's nonce search (
find_valid_nonce
) uses Rust'sblake3
library to simulate the~2^(B-L)
off-chain work.
The codebase is organized into three main Rust modules:
src/main.rs
:- The executable entry point.
- Parses command-line arguments (for the input value
x
). - Sets up the
ColliderVmConfig
(n, m, L, B, k). - Calls
simulation::run_simulation
to orchestrate the entire process. - Prints the final simulation results.
src/core.rs
:- Defines the core data structures (
ColliderVmConfig
,SignerInfo
,OperatorInfo
,PresignedStep
,PresignedFlow
). - Contains constants (e.g.,
F1_THRESHOLD
). - Implements helper functions primarily used off-chain or for setup:
create_toy_sighash_message
: Simulates sighash generation.calculate_flow_id
: ComputesH(x, r)|_B
using Blake3.find_valid_nonce
: Simulates the Operator's hash search.
- Implements functions to build the Bitcoin locking scripts (
build_script_f1_locked
,build_script_f2_locked
) incorporating the simplified logic, hash, and signature checks.
- Defines the core data structures (
src/simulation.rs
:- Implements the two main phases of the ColliderVM simulation protocol:
offline_setup
: Simulates the Signers generating keys and creating/signing all thePresignedFlow
s for all potential flow IDsd
.online_execution
: Simulates the Operator finding a nonce for a given inputx
, selecting the corresponding flowd
, constructing the full witness and script, and executing the F1 and F2 scripts.
- Uses helper functions and data structures from
core.rs
. - Uses
bitvm::execute_script_buf
to simulate the execution of the constructed Bitcoin scripts.
- Implements the two main phases of the ColliderVM simulation protocol:
The cargo run [input_value]
command triggers the following sequence:
-
Initialization (
main.rs
): Parses the optionalinput_value
(or defaults to 114) and sets up theColliderVmConfig
(n=3, m=2, L=4, B=8, k=2). -
Offline Setup Phase (
simulation::offline_setup
): Simulates actions performed by Signers before the inputx
is known.- Generates keypairs for 3 Signers and 2 Operators.
- Loops
2^L = 16
times (forflow_id
0 to 15). - Inside the loop (for each
flow_id
d
):- F1 Setup:
- Builds the F1 locking script (
build_script_f1_locked
) containing checks forx > 100
,flow_id == d
, and a Signer signature. - Creates a placeholder F1 transaction (
create_placeholder_tx
) spending a dummy input. - Calculates a toy sighash for F1 (
create_toy_sighash_message
). - All 3 Signers sign this sighash, producing signatures.
- Stores the F1 template, sighash, signatures, and script in a
PresignedStep
.
- Builds the F1 locking script (
- F2 Setup:
- Builds the F2 locking script (
build_script_f2_locked
) containing checks forx < 200
,flow_id == d
, and a Signer signature. - Creates a placeholder F2 transaction spending the output of the F1 placeholder transaction.
- Calculates a toy sighash for F2.
- All 3 Signers sign this sighash.
- Stores the F2 template, sighash, signatures, and script in a second
PresignedStep
.
- Builds the F2 locking script (
- Adds the
PresignedFlow
(containing the F1 and F2 steps) to aHashMap
keyed by theflow_id
(d
).
- F1 Setup:
- Returns the generated Signer/Operator info and the
presigned_flows_map
.
-
Online Execution Phase (
simulation::online_execution
): Simulates actions performed by an Operator after the inputx
(input_value
) is known.- Nonce Search: Calls
find_valid_nonce(input_value, B, L)
.- This function starts with
nonce = 0
. - It repeatedly calculates
d = calculate_flow_id(input_value, nonce, B, L)
(which computesBlake3(input_value || nonce)|_B
). - If
d < 2^L
(i.e.,d
is in the setD
= {0..15}), it returns the successful(nonce, d)
. This simulates the~2^(B-L)
=~2^(8-4)
=~16
expected hashes. - If not, it increments the nonce and tries again.
- This function starts with
- Flow Selection: Retrieves the
PresignedFlow
for theflow_id
(d
) returned byfind_valid_nonce
from thepresigned_flows_map
. - (Optional) Off-Chain Checks: Verifies the Signer 0 signature for F1/F2 and the hash calculation
H(x,r)|_B = d
using Rust crypto functions (for logging/debugging). - F1 Script Execution:
- Constructs the witness script:
script_builder.push(sig_f1).push(flow_id).push(input_value)
. - Concatenates the witness script bytes with the F1 locking script bytes (
step_f1.locking_script
). - Calls
bitvm::execute_script_buf
on the combined script. - Stores the success/failure result (
script_f1_success
).
- Constructs the witness script:
- F2 Script Execution:
- Constructs the witness script:
script_builder.push(sig_f2).push(flow_id).push(input_value)
. - Concatenates the witness script bytes with the F2 locking script bytes (
step_f2.locking_script
). - Calls
bitvm::execute_script_buf
on the combined script. - Stores the success/failure result (
script_f2_success
).
- Constructs the witness script:
- Result Calculation: Determines overall
success
asscript_f1_success && script_f2_success
. - Returns a
SimulationResult
containing the success status and results of individual script executions.
- Nonce Search: Calls
-
Output (
main.rs
): Prints a summary message indicating whether the simulation succeeded or failed, based on the returnedSimulationResult
.
- Prerequisites: Ensure you have Rust and Cargo installed (https://www.rust-lang.org/tools/install).
- Build: Navigate to the project directory and build the project:
Usage: collidervm_toy [OPTIONS]
Options:
-i, --input <INPUT>
Input value to test (default: 114)
[default: 114]
-p, --preset <PRESET>
Preset configuration to use
[default: default]
Possible values:
- default: Default configuration (quick to run for demos)
- medium: Medium difficulty (10-15 seconds)
- hard: Higher difficulty (~1 minute)
- custom: Custom configuration (use with -n, -m, -l, -b, -k options)
-s, --signers <SIGNERS>
Number of signers (1-of-n honest for safety)
-o, --operators <OPERATORS>
Number of operators (1-of-m honest for liveness)
-l, --l-param <L_PARAM>
Flow set size parameter L (set D size = 2^L)
-b, --b-param <B_PARAM>
Hash prefix bits parameter B
-k, --k-param <K_PARAM>
Number of subfunctions (fixed at 2 for the toy model)
--hash-rate <HASH_RATE>
Skip hash rate calibration and use the provided value
--no-calibration
Disable hash rate calibration
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
Started with love by AbdelStark 🧡
Feel free to follow me on Nostr if you’d like, using my public key:
npub1hr6v96g0phtxwys4x0tm3khawuuykz6s28uzwtj5j0zc7lunu99snw2e29
Or just scan this QR code to find me:
Thanks goes to these wonderful people (emoji key):
A₿del ∞/21M 💻 📖 🤔 |
Stephen 💻 |
Phạm Xuân Trung 💻 |
Maciej Kamiński @ StarkWare 💻 |
This project follows the all-contributors specification. Contributions of any kind welcome!