Skip to content
Draft

Dev #12

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
920684d
Move to monorepository structure
Hrom131 Sep 17, 2025
b4c6a99
Merge branch 'master' into dev
Hrom131 Sep 25, 2025
676c492
Add draft SPVGatewayV2 contract
Hrom131 Sep 30, 2025
63e66ab
add spv go services
DmitriiKJ Oct 1, 2025
ca3498c
rm links
DmitriiKJ Oct 1, 2025
fbb74d6
add serivces
DmitriiKJ Oct 1, 2025
1421968
delete configs
DmitriiKJ Oct 1, 2025
2198aca
Update ProofHelper library
Hrom131 Oct 1, 2025
d2e5c9d
Fix SPVGatewayV2 contract and add unit tests
Hrom131 Oct 1, 2025
5e3edd0
change LICENSE year, add config examples
DmitriiKJ Oct 7, 2025
4a5f884
Separate v1 and v2 contracts
Hrom131 Oct 8, 2025
641e1f1
Add unit tests and doc comments
Hrom131 Oct 8, 2025
729e25a
add bitcoin prover
DmitriiKJ Oct 9, 2025
55e0e44
update README
DmitriiKJ Oct 10, 2025
cf7cb28
fix blocks pulling
DmitriiKJ Oct 10, 2025
299bf61
add gas price limit
DmitriiKJ Oct 28, 2025
78cf7ac
.
DmitriiKJ Oct 28, 2025
449a62f
.
DmitriiKJ Oct 28, 2025
0516f5d
Move ERC20 logic to the SPVGatewayV2 contract
Hrom131 Oct 29, 2025
6c9b769
blocks pulling fix
DmitriiKJ Oct 30, 2025
6ebe207
Add more unit tests
Hrom131 Oct 30, 2025
8e63d22
Merge pull request #15 from distributed-lab/feature/spv_v2
Hrom131 Oct 30, 2025
bb8c014
remove unused code
DmitriiKJ Nov 3, 2025
d9965c7
Add deployment scripts for the SPVGatewayV2 contract
Hrom131 Nov 7, 2025
69f1252
Merge pull request #17 from distributed-lab/feature/deploy_scripts
Hrom131 Nov 7, 2025
ffc68f8
Merge pull request #14 from distributed-lab/feature/services
Hrom131 Nov 10, 2025
759047f
Merge pull request #16 from distributed-lab/feature/bitcoin_prover
Hrom131 Nov 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
20 changes: 0 additions & 20 deletions .github/actions/setup/action.yml

This file was deleted.

23 changes: 0 additions & 23 deletions .github/workflows/checks.yml

This file was deleted.

100 changes: 3 additions & 97 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,99 +1,5 @@
# ERC-8002: SPV Gateway
# ERC-8002: SPV Gateway

Introduce a singleton contract for on-chain verification of transactions that happened on Bitcoin. The contract acts as a trustless Simplified Payment Verification (SPV) gateway where anyone can submit Bitcoin block headers. The gateway maintains the mainchain of blocks and allows the existence of Bitcoin transactions to be verified via Merkle proofs.
This repository contains the smart contracts and services for the `SPV Gateway` — protocol that enables the trustless on-chain verification of transactions that happened on the Bitcoin network.

Link to [ERC-8002](https://ethereum-magicians.org/t/erc-8002-simplified-payment-verification-gateway/25038).

> [!NOTE]
> Since the ERC is currently a draft, there is no deployment on mainnet available. Please use [the contract on Sepolia](https://sepolia.etherscan.io/address/0xE8e6CA2113338c12eb397617371D92239f3E6A60) for testing purposes.

# How it Works

The gateway is a permissionless contract that operates by receiving raw Bitcoin block headers (anyone can submit them), which are then parsed and validated against Bitcoin's consensus rules:

1. Header Parsing: Raw 80-byte Bitcoin block headers are parsed into a structured *BlockHeader.HeaderData* format, handling Bitcoin's little-endian byte ordering.
2. Double SHA256 Hashing: Each block header is double SHA256 hashed to derive its unique block hash, which is then saved in a big-endian format.
3. Proof-of-Work Verification: The calculated block hash is checked against the current network difficulty target (derived from the *bits* field in the block header).
4. Chain Extension & Reorganization: New blocks are added to a data structure that allows for tracking multiple chains. When a new block extends a chain with larger cumulative work, the *mainchainHead* is updated, reflecting potential chain reorganizations.
5. Difficulty Adjustment: Every 2016 blocks, the contract calculates a new difficulty target based on the time taken to mine the preceding epoch. This ensures the 10-minute average block time is maintained.

Under the hood, the contract builds the mainchain but doesn't define its finality. The number of required block confirmations is up to the integration dApps to decide.

## Submitting Bitcoin Blocks

To submit a new Bitcoin block, call `addBlockHeader` function by passing a valid raw block header as a parameter. It is an open function that will revert in case Bitcoin PoW checks don't pass.

In case multiple blocks can be added, call `addBlockHeaderBatch` function to save ~15% on gas per block.

## Verifying Bitcoin Tx Inclusion

In order to verify the tx existence, the `checkTxInclusion` function needs to be called.

The list parameters to be passed:

1. `merkleProof` - Merkle path for a given transaction to be checked. The Merkle path can either be built locally or by calling `gettxoutproof` on a Bitcoin node.
2. `blockHash` - Hash of the block to check the tx inclusion against. This block is required to exist in the SPV storage.
3. `txId` - Tx hash (Merkle leaf) to be checked.
4. `txIndex` - The Merkle "direction bits" to decide on left or right hashing order.
5. `minConfirmationsCount` - Number of required mainchain confirmation for the block to have.

> [!TIP]
> Please check out [this test case](./test/SPVGateway.test.ts#L223) for more integration information.

## Permissionlessness

In order for the gateway to be truly permissionless, the contract's initialization needs to be permissionless as well. Alongside the regular `SPVGateway`, the repository hosts a `HistoricalSPVGateway` contract, that uses a "proof-of-bitcoin" ZK proof for its initialization. This enables verification of historical Bitcoin blocks and transactions otherwise too expensive to include. Since syncing up the gateway from Bitcoin's genesis would cost ~100 ETH on the mainnet.

# HistoricalSPVGateway

`HistoricalSPVGateway` is an extension of the basic `SPVGateway` contract. It uses "proof-of-bitcoin" ZK proof that compresses the entire Bitcoin block history into a single Merkle root to be used during the contract's initialization. This root can then used to verify the "historical" existence of some blocks and transactions.

> [!IMPORTANT]
> Currently, the "proof-of-bitcoin" ZK proof is generated to the first *912384* Bitcoin blocks. The circuits source code can be found [here](https://github.com/distributed-lab/bitcoin-prover).

## Building the History Merkle Tree

In order to prove the historical block existence, you need to pass the corresponding Merkle path to a smart contract. For that, the entire historical Merkle tree needs to be built:

1. Fetch all block hashes from the genesis block up to the height of `provedBlocksCount - 1`.
2. Split these blocks into *1024-block* chunks.
3. Create Level1 Merkle trees for each chunk.
4. Create an array containing all the Level1 tree roots.
5. Pad the array from the previous step with zeros for its length to reach the next power of 2.
6. Create a Level2 Merkle tree, using the array from the previous step as the tree's values.

> [!NOTE]
> For the Level1 Merkle tree use `SHA256("leaf1" | blockHash)` and `SHA256("node1" | left | right)` for hashing leaves and nodes. And for the Level2 Merkle tree, `SHA256("leaf2" | level1MerkleRoot)` and `SHA256("node2" | left | right)` respectively.

## Verifying History Bitcoin Blocks Inclusion

To verify the existence of a historical Bitcoin block, call the `checkHistoryBlockInclusion` function.

This function requires a `HistoryBlockInclusionProofData` struct as a parameter, which contains the following fields:

1. `level1MerkleProof` - Level1 Merkle path for the block hash being checked.
2. `level2MerkleProof` - Level2 Merkle path for the Level1 Merkle root (which is calculated from the `level1MerkleProof`)
3. `blockHash` - Block hash to be checked.
4. `blockHeight` - Block height of the passed block hash.

> [!TIP]
> Please check out [this test cases](./test/HistoricalSPVGateway.test.ts#L181) for more integration information.

## Verifying History Bitcoin Tx Inclusion

In order to verify the tx existence in the proven Bitcoin history, the `checkHistoryTxInclusion` function needs to be called.

The list of parameters to be passed:

1. `merkleProof` - Merkle path for a given transaction to be checked. The Merkle path can either be built locally or by calling `gettxoutproof` on a Bitcoin node.
2. `blockHeaderRaw` - Raw block header of the block to check the transaction's inclusion against.
3. `txId` - Tx hash (Merkle leaf) to be checked.
4. `txIndex` - The Merkle "direction bits" to decide on left or right hashing order.
5. `blockInclusionProofData` - The proof data for the historical block hash inclusion.

> [!TIP]
> Please check out [this test case](./test/HistoricalSPVGateway.test.ts#L309) for more integration information.

# Disclaimer

Bitcoin + Ethereum = <3
The protocol functions as a permissionless Simplified Payment Verification (SPV) gateway. Anyone can submit Bitcoin block headers to the gateway, which then validates them against Bitcoin's consensus rules. The gateway maintains the mainchain and allows dApps to verify a transaction's existence using Merkle proofs.
Loading