Before Segwit2x was cancelled, there was some talk about fork futures. Charlie Lee and Adam Back, among others, offered to take the short position. Bitfinex distributed BT2 “chain split tokens” representing SegWit2x futures, which traded agaist USD and BTC at about ~$900. The market is pretty dead now. But what about next time?
Next time there’s a major chain split in the future, It’d be really nice if we could do fork futures without a trusted third-party, right? Like, using some sort of blockchain or something. Patrick McCorry and Ethan Heilman designed a really nifty fork future construction that does not require a malleability fix, but does require strong replay protection. Here I’m presenting a version that requires a malleability fix, but works with weak replay protection.
Taking advantage of replay protection
We can create an on-chain forward of a coin that doesn’t exist yet. We do this by leveraging the replay protection mechanism. Its details should be known well in advance of the fork. We can create and sign, months before the chain fork, a series of transactions that splits the coins. Then we broadcast them after the fork. As long as the timing of the fork and the replay protection mechanism remain unchanged, everything is safe and trustless.
Segwit2x did not have any form of replay protection. This means the construction here could not have worked with Segwit2X. Previously they implemented a weak replay protection system: all transactions sending BTC to a specific address were to be invalid on the 2x chain. They removed it. I’m going to use it as an example in this post, but this construction should work with any weak replay protection.
Constructing the forward
DO NOT DO THIS YOUR COINS WILL BE STOLEN. SERIOUSLY. THIS DOES NOT WORK WITHOUT A REPLAY-PROTECTED FORK.
Alice and Bob agree to trade Alice’s post-split BT2 for Bob’s post-split BTC. Alice wants to end up with only BTC. Bob with only BT2.
- Alice and Bob each create the following script and calculate its P2SH address. We call this the shared multisig:
OP_2 <Alice Pubkey> <Bob Pubkey> OP_2 OP_CHECKMULTISIGVERIFY
- Alice and Bob each create, but do not sign, transactions sending pre-fork coins to the shared multisig’s P2SH address. We call Alice’s funding transaction tx1, and Bob’s funding transaction tx2.
- Alice and Bob create, but do not sign, transactions spending the outputs of their funding transactions as follows:
- tx3: A transaction spending tx1 and tx2’s outputs, sending them to Alice. This transaction includes replay protection, and is valid only on the BTC chain. Time locked until 2 weeks after the fork.
- tx4: A transaction spending tx1 and tx2’s outputs, sending them to Bob. This transaction does not require replay protection. This transaction is time locked until 3 weeks after the fork.
- tx5: A transaction refunding tx1 to Alice, no replay protection required, time locked until at least 4 weeks after the fork.
- Bob signs transactions 3 and 5, and sends them to Alice.
- Alice signs transaction 4, and sends it to Bob.
- Alice signs tx1, and broadcasts it to the network in advance of the fork.
- Bob signs tx2, and broadcasts it to the network in advance of the fork.
- If Bob does not sign and broadcast tx2, then tx3 and tx4 are invalid, and Alice may retrieve her coins via tx5 after the time lock.
- Both parties wait for the fork.
- After its time lock elapses (after the fork), Alice signs and broadcasts tx3. This transaction is valid only on BTC, due to the inclusion of replay protection. Alice receives the BTC.
- After tx4’s time lock elapses, Bob broadcasts tx4. This transaction is valid only on BT2, because its inputs have been spent on the BTC chain by tx4. Bob receives the BT2.
- Confirmation of tx3 and tx4 renders tx5 invalid on both chains. It may be discarded.
This structure assumes that both chains progress at a reasonable rate. However, theft of funds is not allowed, even if block rates are significantly different between chains. Because tx3 is always valid on BTC before tx4 or tx5, Alice is guaranteed her BTC. Because tx3 is never valid on BT2, and tx4 is always valid on BT2 before tx5, Bob is guaranteed his BT2. The worst outcome is long delays for one party.
Strong replay protection
If the replay protection is strong, it provides additional protection for Alice if she has trouble getting tx3 confirmed on her chain. Using strong replay protection in tx3 and tx4 will prevent Bob from submitting tx4 to the wrong chain and stealing Alice’s coins. If strong replay protection is mandatory (as it should be), they’ll need to make two versions of tx5: one for each chain. These should be created in step 3, and signed by Bob in step 4.
Instead of making tx1 and tx2, Alice and Bob could cooperate to make a joint funding tx. Other transactions would be modified to spend the single output from this transaction, rather than the two outputs from tx1 and tx2. This would simplify the setup process, and decrease on-chain complexity.
Assuming transactions are constructed properly and verified by both parties before funds are moved, there are few failure cases. These relate mostly to parties not broadcasting their transactions in a timely manner. The major exception is chain-split related failures, which are discussed below.
If Bob does not sign and broadcast tx2, he may ‘troll’ Alice by forcing her to lock her coins for several weeks. This results not in loss of funds, but rather in opportunity costs for Alice as her funds are locked. This may be solvable via transaction invalidation constructions like the one used in McCorry and Heilman’s paper above.
If Alice does not broadcast tx3 in a timely manner, Bob will take her coins by broadcasting tx4 on both networks. Alice is responsible for ensuring that tx3 is included in a BTC block before tx4 becomes valid.
If Bob does not broadcast tx4 in a timely manner, Alice can broadcast tx5 on BT2. This would invalidate tx4 and steal some of Bob’s expected BT2 payout. The remaining BT2 would be “stuck” in the shared multisig. Bob would then have to convince Alice to cooperate to gain access to those coins again. Bob must ensure that tx4 is included in a BT2 block before tx5 becomes valid.
Chain-split related failures
This construction relies on knowledge about the timing of the chain split and its replay protection mechanism. We implement replay protection before the split, with time locks set after the split. Once we’ve set up a trade and both parties have funded the shared multisig any change to the chain split plans is dangerous.
If the chain split is delayed significantly, it’s possible that tx3 would unlock before the split. This would allow Alice to steal Bob’s funds by broadcasting tx3. Alice would receive all pre-split coins, and thus all post-split coins.
If the chain split is moved forward significantly, it is only risky if it interrupts the setup process. For example, if Alice has funded pre-split coins, and Bob funds post-split BT2 only, then tx3 never becomes valid. Bob may steal Alice’s BT2 via tx4, and Alice will be forced to wait for tx5 to become valid to reclaim her post-split BTC.
If the replay protection mechanism is changed after both parties fund the shared multisig, then tx3 may become valid (or invalid!) on both chains. If tx3 is valid on both chains, Alice will submit it to steal Bob’s BT2. If tx3 is invalid on both chains, Bob may submit tx4 to both chains to steal Alice’s BTC.
It is crucial that both parties have a high degree of confidence that the split will occur as scheduled, and that the replay protection mechanism will not change. It is also advisable that both parties enter into an enforceable legal contract that prevails in the event of unforeseen circumstances.
Minimizing wait times
One major downside of this approach is that Bob is forced to wait longer than Alice to retrieve his coins. We can minimze Bob’s wait time while maintaining safety by adding an additional script and transaction. This ensures that Bob’s coins are accessible as soon as Alice retrieves hers.
In case you missed it the first time: DO NOT DO THIS YOUR COINS WILL BE STOLEN.
- Alice creates a secret, k, and computes its hash H(k).
- We modify the shared multisig script as follows:
OP_IF OP_2 <Alice Pubkey> <Bob Pubkey> OP_2 OP_CHECKMULTISIGVERIFY OP_ELSE OP_HASH160 <H(k)> OP_EQUALVERIFY OP_DUP OP_HASH160 <Bob's pubkeyhash> OP_EQUALVERIFY OP_CHECKSIG OP_ENDIF
- We modify tx3 to pay, instead of Alice, the following script, which we call Alice’s retrieval script:
OP_IF OP_HASH160 <H(k)> OP_EQUALVERIFY OP_DUP OP_HASH160 <Alice's pubkeyhash> OP_ELSE <time> OP_CHECKSEQUENCEVERIFY OP_DROP OP_DUP OP_HASH160 <Bob's pubkeyhash> OP_ENDIF OP_EQUALVERIFY OP_CHECKSIG
- We create tx6, in which Alice uses knowledge of k to spend funds held by Alice’s retrieval script. Alice must broadcast tx3, wait for it to confirm, and then broadcast tx6 to gain access to the BTC. Alice has a limited time after tx3 confirms to broadcast tx6. If she does not broadcast tx6 in a timely manner, Bob can retrieve her coins.
- Seeing tx6, Bob may use knowledge of k to create tx7, which spends from the shared multisig via the
- If Alice does not broadcast tx6, Bob may create and broadcast tx8, which takes Alice’s BTC. Bob would then wait for tx4 to become valid in order to retrieve his BT2.
With this construction, Bob is guaranteed his BT2 by tx4, but may retrieve his BT2 as soon as Alice retrieves her BTC. His time lock is the lower of (tx3’s time lock + n blocks) and tx4’s time lock. The worst that Alice can do is delay the broadcast of tx3 and tx6 until just before she expects tx4’s time lock to lapse. This is risky for Alice. The closer she gets to tx4’s time lock date, the more likely it is that she will lose her coins.
On-chain fork forwards should be possible for all SegWit-enabled coins. There is no implementation of the protocols described above. So right now, this is just a curiosity. I intend to have a solid implementation by the next major fork event. If you’re interested in these sorts of transactions on forks or across multiple chains, please shoot me an email, or a DM on twitter.
Originally published at prestwi.ch on December 4, 2017.