Introduce a singleton contract for on-chain verification of transactions that happened on Bitcoin. The contract is available at "0xTODO" , acting 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.
Ethereum's long-term mission has always been to revolutionize the financial world through decentralization, trustlessness, and programmable value enabled by smart contracts. Many great use cases have been discovered so far, including the renaissance of Decentralized Finance (DeFi), emergence of Real-World Assets (RWA), and rise of privacy-preserving protocols.
However, one gem has been unreachable to date -- Bitcoin. Due to its extremely constrained programmability, one can only hold and transfer bitcoins in a trustless manner. This EIP tries to expand its capabilities by laying a solid foundation for bitcoins to be also used in various EVM-based DeFi protocols, unlocking a whole new trillion-dollar market.
The singleton SPV gateway contract defined in this proposal acts as a trustless one-way bridge between Bitcoin and Ethereum, already enabling use cases such as using native BTC as a lending collateral for stablecoin loans. Moreover, with the recent breakthroughs in the BitVM technology, the full-fledged, ownerless two-way bridge may soon become a reality, powering the permissionless and wrapless issuance of BTC on Ethereum.
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
In Bitcoin, each block contains a header, which has a fixed size of 80 bytes and follows the following structure:
| Field | Size | Format | Description |
|---|---|---|---|
| Version | 4 bytes | little-endian | The version number of the block. |
| Previous Block | 32 bytes | natural byte order | The block hash of a previous block this block is building on top of. |
| Merkle Root | 32 bytes | natural byte order | A fingerprint for all of the transactions included in the block. |
| Time | 4 bytes | little-endian | The current time as a Unix timestamp. |
| Bits | 4 bytes | little-endian | A compact representation of the current target (difficulty). |
| Nonce | 4 bytes | little-endian | A 32-bit number which miners compute to find a valid block hash. |
The fields within the block header are sequentially ordered as presented in the table above.
Bitcoin's Proof-of-Work (PoW) consensus mechanism has a probabilistic finality, thus relying on a dynamic difficulty target adjustments. The target's initial value is set to 0x00000000ffff0000000000000000000000000000000000000000000000000000, which also serves as the minimum difficulty threshold.
The target is recalculated every 2016 blocks (approximately every two weeks), a period commonly referred to as a difficulty adjustment period.
The expected duration for each adjustment period is 1,209,600 seconds (2016 blocks * 10 minutes/block). The new target value is derived by multiplying the current target by the ratio of the actual time taken to mine the preceding 2016 blocks to this expected duration.
To prevent drastic difficulty fluctuations, the adjustment multiplier is capped at 4x and 1/4x respectively.
For a Bitcoin block header to be considered valid and accepted into the chain, it MUST adhere to the following consensus rules:
Chain Cohesion: The Previous Block hash field MUST reference the hash of a valid block that is present in the set of existing block headers.
Timestamp Rules:
Time field MUST be strictly greater than the Median Time Past (MTP) of the previous 11 blocks.Time field MUST NOT be more than 2 hours in the future relative to the validating node's network-adjusted time.PoW Constraint: When the block header is hashed twice using SHA256, the resulting hash MUST be less than or equal to the current target value, as derived from the difficulty adjustment mechanism.
Every Bitcoin block header has a field Merkle Root that corresponds to a Merkle root of the transactions tree included in this block.
The transactions Merkle tree is built recursively performing double SHA256 hash on each pair of sibling nodes, where the tree leaves are the double SHA256 hash of the raw transaction bytes. In case the node has no siblings, the hashing is done over the node with itself.
To verify the transaction inclusion into the block, one SHOULD build the Merkle root from the ground up and compare it with the Merkle Root stored in the selected block header. The corresponding Merkle path and hashing direction bits can be obtained and processed by querying a Bitcoin full node.
Bitcoin's mainchain is determined not just by its length, but by the greatest cumulative PoW among all valid competing chains. This cumulative work represents the total computational effort expended to mine all blocks within a specific chain.
The work contributed by a single block is inversely proportional to its target value. Specifically, the work of a block can be calculated as (2**256 - 1) / (target + 1). The target value for a block is derived from its Bits field, where the first byte encodes the required left hand bit shift, and the other three bytes the actual target value.
The total cumulative work of a chain is the sum of the work values of all blocks within that chain. A block is considered part of the mainchain if it extends the chain with the greatest cumulative PoW.
The SPVGateway contract MUST provide a permissionless mechanism for its initialization. This mechanism MUST allow for the submission of a valid Bitcoin block header, its corresponding block height, and the cumulative PoW up to that block, without requiring special permissions.
The SPVGateway MUST implement the following interface:
All fields within the BlockHeaderData struct MUST be converted to big-endian byte order for internal representation and processing within the smart contract.
The addBlockHeader function MUST perform the following checks:
BlockHeaderAdded event upon successful addition of the block header.MainchainHeadUpdated event if the mainchain was updated.The checkTxInclusion function MUST perform the following steps:
blockHash is part of the mainchain and ensure its number of confirmations is at least equal to the minConfirmationsCount parameter. If any of these checks fail, the function MUST return false.merkleProof, txId, and txIndex, the function MUST compute the Merkle root.Merkle Root field stored within the block header identified by blockHash.Merkle Root, the function MUST return true. Otherwise, it MUST return false.During the design process of the SPVGateway contract, several decisions have been made that require clarification. The following initialization options of the smart contract were considered:
Upon submitting the raw block header, the gateway expects the BlockHeaderData fields to be converted to big-endian byte order. This is required to maintain EVM's efficiency, which is contrary to Bitcoin's native little-endian integer serialization.
There are no "finality" rules in the SPVGateway contract. The determination of such is left to consuming protocols, allowing individual definition to meet required security thresholds.
The inclusion of an OPTIONAL addBlockHeaderBatch function offers significant gas optimizations. For batches exceeding 11 blocks, MTP can be calculated using timestamps from calldata, substantially reducing storage reads and transaction costs.
This EIP is fully backwards compatible.
TBD
TBD
A reference implementation of the SPVGateway contract can be found here.
TargetsHelper is a supporting library that provides utility functions for working with Bitcoin's difficulty targets. It includes methods to convert the Bits field from a block header to the corresponding target value and vice versa, as well as functions to calculate the new difficulty target during adjustment periods.
Please note that the reference implementation depends on the
@openzeppelin/contracts v5.2.0,@solarity/solidity-lib v3.2.0andsolady v0.1.23.
Among potential security issues, the following can be noted:
The security of the SPVGateway is directly dependent on the security of Bitcoin's underlying PoW consensus. A successful 51% attack on the Bitcoin network would allow an attacker to submit fraudulent block headers that would be accepted by the contract, compromising its state.
The block header validation rules require a Bitcoin node to check that the newly created block is not more than 2 hours ahead of the node's network-adjusted time. This check is impossible to implement on the SPVGateway smart contract, hence it is omitted.
Unlike other blockchain systems with deterministic finality, Bitcoin's consensus is probabilistic. The SPVGateway contract SHOULD be designed to handle chain reorganizations of arbitrary depth, but it cannot prevent them. As a result, transactions included in a block may not be permanently final. All dApps and protocols relying on this contract MUST implement their own security policies to determine a sufficient number of block confirmations before a transaction is considered "final" for their specific use case.
While the addBlockHeader function is permissionless and validates each new header cryptographically, the contract's initial state (its starting block header, height, and cumulative PoW) is a point of trust. The integrity of the entire chain history within the contract is built upon the correctness of this initial data. Although the EIP's design allows for flexible bootstrapping, the responsibility for verifying the initial state falls on the community and the dApps that choose to use a specific deployment of the SPVGateway.
Copyright and related rights waived via CC0.