Skip to content

BTCSentinelCOMMUNITY/proof-submit

Repository files navigation

Bitcoin Awakening Prover

A zero-knowledge system built on SP1 designed to trace and prove the activation of ancient Bitcoin assets. The core focus of this repository is to cryptographically verify that submitted Bitcoin transactions have successfully activated specific dormant BTC addresses. By generating and verifying SP1 ZK proofs, the system trustlessly links historical UTXO snapshots with active Bitcoin transactions, proving their awakening directly to EVM smart contracts.

Features

  • Address Activation Verification - Validates that specific UTXOs belonging to ancient/dormant snapshots have been correctly spent.
  • Block Header Chain Verification - Validates Bitcoin block header continuity and difficulty adjustments.
  • Merkle Proof Verification - Cryptographic proof that transactions exist within blocks.
  • Ancient Root Check - Validates historical UTXO state against a committed Merkle root.
  • Minimum Confirmation Check - Ensures transactions have sufficient confirmations (3 blocks after the tx block).
  • EVM-Compatible Proofs - Generate Groth16 proofs for low-cost on-chain verification.

System Architecture

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│   Blockbook     │────▶│  Python Tooling  │────▶│   SP1 Prover    │
│  (BTC Data)     │     │ (Prep + Submit)  │     │  (ZK Proof)     │
└─────────────────┘     └──────────────────┘     └─────────────────┘
                               │                        │
                               ▼                        ▼
                        ┌──────────────────────────────────┐
                        │       BitcoinAnchor.sol          │
                        │    (EVM Smart Contract)          │
                        └──────────────────────────────────┘

Project Structure

├── program/              # ZKVM Guest - Verification logic (Rust)
│   └── src/main.rs       # Header chain + merkle proof verification
├── script/               # ZKVM Host - Data prep and proof generation (Rust)
│   └── src/bin/          # main.rs, evm.rs, vkey.rs, gen_proof.rs, get_root.rs
├── lib/                  # Shared library - Bitcoin data structures (Rust)
│   └── src/lib.rs        # BlockHeader, Transaction, MerkleProof
├── contracts/            # Solidity smart contracts (Foundry)
│   └── src/BitcoinAnchor.sol
└── utils/                # Utility scripts and helpers
    ├── fetch_data_blockbook.py  # Fetch BTC data from Blockbook
    ├── submit_tx.py      # Process a Bitcoin txid into a proving batch
    ├── submit_proof.py   # Submit ZK proofs on-chain
    ├── contracts_evm.py  # EVM contract interaction client
    └── btc_anchor_common.py # Shared helpers

Requirements

Rust Components

  • Rust (stable)
  • SP1
    • Required: SP1 toolchain v6.0.0 (sp1up -v v6.0.0)
    • Note: SP1 can currently be run natively on Linux and macOS.

Ubuntu/Debian System Packages

Some Rust dependencies (e.g. prost-build / bindgen) may require system tools on Ubuntu/Debian:

sudo apt-get update
sudo apt-get install -y build-essential pkg-config protobuf-compiler clang libclang-dev

Python Components

  • Python 3.10+
  • uv pip install -r requirements.txt

Foundry (Smart Contracts)

  • Foundry
    • Uses sp1-contracts verifier v6.0.0 (see contracts/foundry.lock)

Submitting Proofs to EVM (Quick Start)

The automated pipeline script handles fetching block data from Blockbook, generating the SP1 ZK proof, and submitting the transaction on-chain.

1. Setup Environment Configuration

Copy the example environment file:

cp .env.example .env
vim .env

Ensure your .env file includes the connection details and the target EVM contract address:

SP1_PROVER=cpu
BLOCKBOOK_URL=
SNAPSHOT_BIN_PATH=address/dormant_snapshot.bin
EVM_RPC_URL=
PRIVATE_KEY=0x...
CONTRACT_ADDRESS=0x...

2. Prepare Environment

Install the SP1 toolchain (required to compile the ZK guest program):

curl -L https://sp1.succinct.xyz | bash
sp1up -v v6.0.0

This repo pins Rust dependencies via Cargo.lock. Use --locked in CI/reproducible builds. Note: the Rust sp1-* crates are pinned to 6.0.2 (via Cargo.lock), while the circuit/verifier version is v6.0.0. The Rust binaries (vkey / proof generation) will exit early if the SP1 circuit version is not v6.0.0.

Initialize submodules (required for sp1-contracts and forge-std):

git submodule update --init --recursive

Create and activate a Python virtual environment:

uv venv
source .venv/bin/activate
uv pip install -r requirements.txt

3. Submit a Proof

Use submit_tx.py as the user-facing entrypoint. It fetches BTC data, prepares proving input, generates proof, and submits on-chain.

Submit by txid (auto-select eligible input addresses):

python utils/submit_tx.py --txid <txid>

Submit by txid + vin index (target one specific input):

python utils/submit_tx.py --txid <txid> --index <vin_index>

Optionally set reward submitter identity in proof public values:

python utils/submit_tx.py --txid <txid> --submitter <evm_address>

Default behavior: if --submitter is omitted, the pipeline will set pv.submitter to the EVM address derived from PRIVATE_KEY (i.e., the transaction sender used for submission). Note that pv.submitter is part of the proof public values and cannot be changed at submission time.

Batch submission is also feasible by composing existing utilities, but no dedicated one-command batch CLI is provided in this repo. The default batch size is 10, which can be configured via the BATCH_SIZE environment variable. Note that BATCH_SIZE limits the maximum number of activatable inputs (addresses) processed in a single proving batch concurrently (whether they come from a single transaction or multiple transactions).

When generating vkey / proofs, always use --locked to avoid dependency drift across environments.

Development Guide

Input/Output Alignment (Critical)

The order of stdin.write() calls in Host (script/src/bin/main.rs) must match the order of sp1_zkvm::io::read() calls in Guest (program/src/main.rs) exactly.

Public Values

On-chain verified public values are defined via alloy_sol_types::SolType. Modifications will affect the ABI.

Address Activation Semantics

  • The contract stores activation state in activeAddresses[keccak256(addrBytes)].
  • AddressActivated emits AddressActivated(bytes32 indexed addrHash, bytes addr, uint64 amount, bytes32 txid).
  • isAddressActive(bytes) expects raw BTC address bytes (typically UTF-8 bytes of the address string), not the hash.

Bitcoin Serialization

BlockHeader uses a custom serialize() method to match the Bitcoin 80-byte standard format.

Troubleshooting

GLIBC_x.y not found when running prebuilt binaries: The bitcoin-anchor binary is dynamically linked against glibc. If you build on a newer distro (e.g. glibc 2.39) and run on an older one (e.g. Ubuntu 22.04 glibc 2.35), it will fail at runtime. Build the binary on a glibc version <= your target environment (Ubuntu 22.04 is a good compatibility baseline).

SP1 circuit version mismatch: Ensure you installed the SP1 toolchain with sp1up -v v6.0.0 and are building with cargo ... --locked.

Header mismatch: Ensure block headers in the generated btc_data.json form a valid connected chain.

Insufficient confirmations: utils/submit_tx.py requires Blockbook confirmations >= 4 (tx block + 3 blocks after it) before running the proving pipeline.

Reverts / duplicate submissions: The contract will revert if any address in the proof is already activated (e.g., "Address already active"). The submission flow attempts a best-effort pre-check (isAddressActive) before sending the transaction, but it cannot guarantee success because on-chain state can change between the check and the actual submission.

Historical submission restrictions: When submitting a proof for a historical transaction (one that occurred before the contract's current finalizedHeight), the proof must anchor exactly to the current finalizedHeight and finalizedHash. Additionally, historical submissions cannot span across different Bitcoin difficulty epoch periods unless performed by a whitelisted admin address. This admin exemption exists to simplify extreme edge-case data recovery for highly delayed anchor submissions (e.g., allowing a single cross-epoch historical submission instead of splitting it into multiple transactions).

Start height too old: The contract enforces a deploymentFinalizedHeight, which represents the minimum allowed block height at deployment time. Submissions attempting to verify blocks older than this deployment anchor will revert with "Start height too old". This is a hard protocol constraint—no one, including the contract owner or whitelisted addresses, can bypass this restriction.

Hardware incompatibility (.cargo/config.toml): By default, this project is configured to compile Rust code with target-cpu=native and +avx512f features to speed up proof generation. If your machine does not support these instructions (resulting in compilation or runtime errors), you can comment out or remove these flags in .cargo/config.toml.

Cast / Foundry missing: The pipeline uses cast for EVM calls, calldata generation, and transaction submission. Ensure Foundry is installed and cast is on PATH.

Out of memory: EVM proofs require 16GB+ RAM. Consider using the Prover Network.

License

MIT (Based on SP1 template, original license retained)

Resources

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors