BIP: 300 Layer: Consensus (soft fork) Title: Hashrate Escrows (Consensus layer) Author: Paul Sztorc <email@example.com> CryptAxe <firstname.lastname@example.org> Comments-Summary: No comments yet. Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0300 Status: Draft Type: Standards Track Created: 2017-08-14 License: BSD-2-Clause Post-History: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2017-May/014364.html
Table of Contents
A "Hashrate Escrow" is a clearer term for the concept of "locked to an SPV Proof", which is itself a restatement of the phrase "within a sidechain" as described in the 2014 Blockstream whitepaper.
A Hashrate Escrow resembles a 2-of-3 multisig escrow, where the 3rd party (who will arbitrate any disputes) is a decentralized group of people: the dynamic-membership set of Bitcoin Miners. However, the 3rd party does not sign escrow-withdrawal transactions with a private key. Instead, these are "signed" by the accumulation of hashpower over time.
Sidechains have many potential benefits, including:
- Protect Bitcoin from competition from altcoins and spinoffs.
- Protect Bitcoin from hard fork campaigns. (Such campaigns represent an existential threat to Bitcoin, as well as an avenue for developer corruption.)
- Help with review, by making it much easier for reviewers to ignore bad ideas.
- Provide an avenue for good-but-confusing ideas to prove their value safely.
Hashrate Escrows are built of two types of component:  new databases, and  new message-interpretations.
- D1. "Escrow_DB" -- a database of "accounts" and their attributes.
- D2. "Withdrawal_DB" -- a database of pending withdrawals from these accounts, and their statuses.
- M1. "Propose New Escrow"
- M2. "ACK Escrow Proposal"
- M3. "Propose Withdrawal"
- M4. (implied) "ACK Withdrawal"
- M5. "Execute Deposit" -- a transfer of BTC from-main-to-side
- M6. "Execute Withdrawal" -- a transfer of BTC from-side-to-main
The table below enumerates the new database fields, their size in bytes, and their purpose. In general, an escrow designer (for example, a sidechain-designer), is free to choose any value for these.
|Field No.||Label||Type||Description / Purpose|
|1||Escrow Number||uint8_t||A number assigned to the entire escrow. Used to make it easy to refer to each escrow.|
|2||Sidechain Deposit Script Hex||string||The script that will be deposited to, and update the CTIP of the sidechain.|
|3||Sidechain Private Key||string||The private key of the sidechain deposit script.|
|4||Escrow Name||string||A human-readable name of the sidechain.|
|5||Escrow Description||string||A human-readable name description of the sidechain. More than enough space to hold a 32 byte hash.|
|6||Hash ID 1||uint256||A field of 32 bytes, which could be any bytes such as a sha256 hash.|
|7||Hash ID 2||uint256||A field of 32 bytes, which could be any bytes such as a sha256 hash.|
|8||"CTIP" -- Part 1 "TxID"||uint256||The CTIP, or "Critical (TxID, Index) Pair" is a variable for keeping track of where the escrow's money is (ie, which member of the UTXO set).|
|9||"CTIP" -- Part 2 "Index"||int32_t||Of the CTIP, this is second element of the pair: the Index. See #9 above.|
D1 is updated via M1 and M2.
1-byte - OP_RETURN (0x6a) 4-byte - Commitment header (0xD5E0C4AF) N-byte - The serialization of the sidechain.
1-byte - OP_RETURN (0x6a) 4-byte - Commitment header (0xD6E1C5BF) 32-byte - Commitment hash: sha256D hash of sidechain's serialization
- Escrows are added in a procedure that resembles BIP 9 soft fork activation: the network must see a properly-formatted M1, followed by "acknowledgment" of the sidechain in 95% of the following 2016 blocks.
- It is possible to "overwrite" an escrow. This requires 6 months (26298 blocks) of M2s, instead of 2 weeks (XXXX). This possibility does not change the security assumptions (because we already assume that users perform extra-protocolic validation at a rate of 1 bit per 26298 blocks).
D2 changes deterministically with respect to M3, M4, M5, and M6.
|Field No.||Label||Type||Description / Purpose|
|1||Escrow Number||uint8_t||Links the withdrawal-request to a specific escrow.|
|2||WT^ Hash||uint256||This is a "blinded transaction id" (ie, the double-Sha256 of a txn that has had two fields zeroed out, see M6) of a withdrawal-attempt.|
|3||ACKs (Work Score)||uint16_t||The current total number of ACKs (PoW)|
|4||Blocks Remaining (Age)||uint16_t||The number of blocks which this WT^ has remaining to accumulate ACKs|
- A hash commitment to D2 exists in each block (even if D2 is blank).
- Withdrawals in D2 are sorted first by field #1 (Escrow Number) and second by field #4 (Age). This imposes a unique sort.
- From one block to the next, "Age" fields must increase by exactly 1.
- Withdrawals are stored in D2 until they fail ("Age" = "MaxAge"), or they succeed (the blockchain contains a txn whose blinded txID matches "WT^").
1-byte - OP_RETURN (0x6a) 1-byte - Push the following 36 bytes (0x24) 4-byte - Commitment header (0xD45AA943) 32-byte - The WT^ hash to populate a new D2 entry
- If the network detects a properly-formatted M3, it must add an entry to D2 in the very next block. The starting values of fields #3 and #4 are zero, and #5 is pulled over by extracting the relevant value from D1.
- Each block can only contain one M3 per sidechain.
M4 is a way of describing changes to the "ACKs" column of D2.
From one block to the next, "ACKs" can only change as follows:
- The ACK-counter of any withdrawal can only change by (-1,0,+1).
- Within a sidechain-group, upvoting one withdrawal ("+1") requires you to downvote all other withdrawals in that group. However, the minimum ACK-value is zero (and, therefore, downvotes cannot reduce it below zero).
- While only one withdrawal can be upvoted at once, they can all be unchanged at once ("abstain") and they can all be downvoted at once ("alarm").
4-byte - Message identifier (0x????????) 1-byte - Version of this message 1-byte - Length (in bytes) of this message; total number of withdrawal attempts; y = ceiling( sum_i(m_i +2)/8 ). Nodes should already know what length to expect, because they know the sequence of M3s and therefore the vector of WT^s. N-byte - stream of bits (not bytes), with a 1 indicating the position of the chosen action [downvote all, abstain, upvote1, upvote2, ...]
But sometimes M4 does not need to be transmitted at all! If there are n Escrows and m Withdrawals-per-escrow, then there are (m+2)^n total candidates for the next D2. So, when m and n are low, all of the possible D2s can be trivially computed in advance.
Miners can impose a "soft limit" on m, blocking new withdrawal-attempts until previous ones expire. For a worst-case scenario of n=200 and m=1,000, honest nodes can communicate M4 with ~25 KB per block [4+1+1+(200\*(1000+1+1)/8)].
Both M5 and M6 are regular Bitcoin txns. They are identified by meeting an important criteria: they select a one of the Critical TxID-index Pairs (a "CTIP") as one of their inputs.
Just as these txns must select a CTIP input, they must create a new CTIP output. D1 is then updated to match only the latest CTIP output. The purpose of this is to have all of the escrow's money (ie all of the sidechain's money) in one TxID, so that depositors immediately undo any UTXO bloat they may cause.
Deposits ("M5") are distinguished from withdrawals ("M6") by simply checking to see if money is "going in", or "out".
As far as mainchain consensus is concerned, deposits to the escrow are always valid.
However, in practice there will be additional requirements. The escrow account (ie the "sidechain") needs to know how to credit depositors. One well-known method, is for mainchain depositors to append a zero-value OP Return to a Deposit txn, so that the sidechain knows how to credit funds. Mainchain users must upgrade their wallet software, of course, (on an individual basis) in order to become aware of and take advantage of new deposit-methods.
We come, finally, to the critical matter: where users can take their money *out* of the escrow account, and return it to the "regular" UTXO set. As previously mentioned, this txn is one which (a) spends from a CTIP and (b) reduces the quantity of BTC in an account's CTIP. Most of the work has already been done by D1, M3, M4, and D2. Furthermore, existing Bitcoin tx-rules prevent the sidechain from ever withdrawing more money than has been placed into it.
In each block, a withdrawal in D2 is considered "approved" if its "ACKs" value meets the threshold (13,150).
Approved withdrawals give the green light to their respective "WT^". A "WT^" is 32-bytes which aspire to represent the withdrawing transaction (the txn that actually withdraws funds from the escrow). The two cannot match exactly, because "WT^" is defined at onset, and the withdrawing TxID depends on the its CTIP input (which is constantly changing).
To solve this, we define a "blinded TxID" as a way of hashing a txn, in which some bytes are first overwritten with zeros. Specifically, these bytes are the first input and the first output.
So, withdrawals must meet the following three criteria:
- "Be ACKed" -- The "blinded TxID" of this txn must be member of the "approved candidate" set in the D2 of this block.
- "Return Change to Account" -- TxOut0 must pay to the "critical account" (see D1) that corresponds to the CTIP that was selected as a TxIn.
- "Return *all* Change to Account" -- Sum of inputs must equal the sum of outputs. No traditional tx fee is possible.
As a soft fork, older software will continue to operate without modification. Non-upgraded nodes will see a number of phenomena that they don't understand -- coinbase txns with non-txn data, value accumulating in anyone-can-spend UTXOs for months at a time, and then random amounts leaving the UTXO in single, infrequent bursts. However, these phenomena don't affect them, or the validity of the money that they receive.
( As a nice bonus, note that the sidechains themselves inherit a resistance to hard forks. The only way to guarantee that the WT^s reported by different clients will continue to match identically, is to upgrade sidechains via soft forks of themselves. )
This BIP will be deployed by "version bits" BIP9 with the name "hrescrow" and using bit 4.
// Deployment of Drivechains (BIPX, BIPY) consensus.vDeployments[Consensus::DEPLOYMENT_DRIVECHAINS].bit = 4; consensus.vDeployments[Consensus::DEPLOYMENT_DRIVECHAINS].nStartTime = 1579072881; // January 15th, 2020. consensus.vDeployments[Consensus::DEPLOYMENT_DRIVECHAINS].nTimeout = 1610695281; // January 15th, 2021.
Also, for interest, see an example sidechain here: https://github.com/drivechain-project/bitcoin/tree/sidechainBMM
Thanks to everyone who contributed to the discussion, especially: ZmnSCPxj, Adam Back, Peter Todd, Dan Anderson, Sergio Demian Lerner, Chris Stewart, Matt Corallo, Sjors Provoost, Tier Nolan, Erik Aronesty, Jason Dreyzehner, Joe Miyamoto, Ben Goldhaber.
This BIP is licensed under the BSD 2-clause license.