PoWer of the Proof of Work!
At ETHDenver, I had the pleasure of meeting Sensei James Prestwich who explained how his company Summa enables swaps between ETH and BTC without any centralized system, with ingenious use of PoW. His design sparked joy in me, so I thought I’d write it up.
Summa’s cross-chain “stateless” swaps work via an Ethereum contract that is deployed on the Ethereum Mainnet and provides an on-chain exchange of ETH <-> BTC.
I’ll keep this short with links to more in-depth articles. Let’s walk through the flow:
BTC/ETH: Bitcoin and Ethereum respectively currencies.
Bitcoin/Ethereum: the blockchains.
UTXO: Unspent Transaction Output, Bitcoin maintains a UTXO set which are the outputs of previous transactions, in order to spend BTC the inputs to the transaction must point to a valid UTXO. Once used as input to a transaction the UTXO is no longer valid.
Dust: a very small amount of BTC.
Seller/Maker: the actor who wishes to make a sale / open an offer: exchange ETH for BTC.
Buyer/Taker: the actor who wishes to take the seller’s offered ETH for the requested amount of BTC.
Gulliver: Seller of ETH.
Lilly: Buyer of ETH (with BTC).
We will walk through a scenario where Gulliver wants to sell 5 ETH for 1 BTC and creates an offer in the Summa contract. Lilly takes his offer and gives him 1 BTC and in return receives 5 ETH.
- Gulliver creates a partial BTC transaction with a small amount of input “dust” (e.g. 0.001 BTC) and an output of 1 BTC, the desired amount, plus the dust, transferred to his Bitcoin account. This transaction is not valid yet since Gulliver’s 0.001 input does not equal the output of 1.001 BTC. To be a valid Bitcoin transaction, the sum of the input UTXOs must be equal or greater than the sum of the output UTXOs: Sum(inputUTXO) >= Sum(outputsUTXO) (if the input UTXOs are greater than the output, anything extra is paid to the miners).
The trick here is that Gulliver creates this transaction so that anyone who obtains the transaction bytes (via email, Signal, FTP, a smart contract, etc.) can add the missing inputs and outputs and make the transaction valid. The now valid transaction can then be submitted to the Bitcoin network. Once the valid transaction is accepted in the Bitcoin blockchain, Gulliver’s 1BTC output will be transferred to his account.
[Technical detail this part can be skipped]
This is made possible thanks to a little known SIGHASH modifier SINGLEANYONECANPAY, which James breaks down in Cross-chain Auctions via Bitcoin Double Spends:
The Bitcoin protocol defines three different sighash types: SIGHASH_ALL, SIGHASH_SINGLE, and SIGHASH_NONE. And before you ask, the convention is to capitalize them. It’s annoying. For convenience, we’ll call the types “ALL” and “SINGLE.” We can ignore “NONE” because it’s a bad idea and we won’t be talking about it again. When you sign your input, you choose one of these sighash types.
ALL commits to the entire transaction: every input and every output. Once you sign with ALL, nobody can change the transaction in any way without invalidating your signature. This means you have a complete veto over any change. On the other hand, SINGLE commits to all inputs, but only a single output. Signatures made with SINGLE ensure that nobody can add more inputs, but anybody can add more outputs.
In addition to the sighash types, there’s a modifier we can set: ANYONECANPAY. It can be mixed in with ALL or SINGLE. If ANYONECANPAY is set, then rather than committing to every input, we only commit to the specific one we’re signing. This means other people can add new inputs to the transaction — just like it says, anyone can pay! ALLANYONECANPAY locks in all outputs, while SINGLEANYONECANPAY (SACP) commits to only one output. As such, SACP gives others leeway to add inputs and/or outputs.
The partial SACP Bitcoin transaction that Gulliver created has a small SINGLEANYONECANPAY signed UTXO input (AKA dust), and an output with the amount of BTC Gulliver has agreed to sell his ETH for, e.g. 1 BTC.
This partial transaction is not valid because inputs .001 BTC != 1.001 BTC outputs.
2. Gulliver now has a partial transaction that a buyer can pick up, add input and outputs to in order to make it valid, and submit to the Bitcoin blockchain. Next he selects a configurable security parameter, which represents the estimated amount the seller would have to spend to “fool” the buyer to pay out ETH without receiving BTC. This is where the ingenious use of Proof of Work comes in.
The security parameter is the difficulty of mining a consecutive chain of blocks, and is derived from the target parameter set in every Bitcoin block header. The target field indicates how hard it is to mine a single block (roughly, the number of leading 0s that the discovered PoW hash needs to contain in order to be valid). The target is recalculated every 2016 blocks to keep block commitment rate at around 10 mins. The seller can set the security parameter based on a fuzzy calculation of the current difficulty set in the current head of the chain, James/Summa would say a sane default would be >=4 headers. The Summa contract will only accept a chain of N blocks where the sum of the difficulties is greater than the security parameter . The security parameter is an approximate cost to produce X blocks, e.g. how much hashing power would be needed in order to create a chain of X blocks starting from the block where the transaction was accepted.
The security parameter is based on the difficulty number set on every Bitcoin block header which the fiat cost of PoW (mining) each block can be roughly and probabilistically calculated, so if Gulliver wants to set a security parameter equal to 1 million dollars (i.e. it would cost the buyer more than $1m to “fool” Gulliver) , he would require the buyer/taker to wait N blocks after the transaction was accepted (more on this later).
The current difficulty as of this writing is 6068891541676, but for our example we’ll pretend the current blocks have a difficulty of 1. The difficulty is derived from the bits field in the block header, also referred to as target. If Gulliver selects a security parameter of 5, then the buyer would have to wait 5 blocks until the Summa contract would accept the exchange. Note that the bit/target field has to be converted into the difficulty representation: difficulty = 0xffff x 256⁰x1d-3/target .
Gulliver selects a security parameter == 5
3. Now Gulliver has what he needs to create the offer in the Summa contract. Gulliver sends an Ethereum transaction including the SACP partial Bitcoin transaction, a transfer of 5 ETH to the Summa contract, and the security parameter to the Summa contract.
- Lilly sees the offer of 5 ETH for 1 BTC and wants to take it.
- Lilly has accounts on the Bitcoin network, she takes the partial SACP Bitcoin transaction and signs a 3 BTC UTXO input with the associate key from her BTC account. The 1.001BTC output remains fixed to the seller’s/Gulliver’s account. Lilly adds a new UTXO output of 2 BTC that goes to an account that she owns, so she can get the change. Now we have a valid Bitcoin transaction.
3.001 input == 3.001 output, and valid signatures (SACP and ALL).
3. Additionally, Lilly adds an output that specifies her Ethereum address where Gulliver’s 5 ETH will be sent if the exchange is accepted.
4. Lilly then submits the valid Bitcoin transaction and waits for her transaction to be accepted into a block X.
5. She then waits for X + N blocks such that the sum of the difficulties of the X + N blocks is equal to a security parameter Y that was set by Gulliver. In our example Gulliver’s security parameter was 5, and the difficulty of each block was 1, so Lilly waits 5 blocks.
6. Once the number of blocks accepted into the Bitcoin chain meet the security parameter requirement, Lilly takes the Merkle root (proof of inclusion) and the X subsequent block headers and submits her buy action to the Summa contract on the Ethereum Mainnet.
NOTE: there are no messy/unsafe timeouts, Lilly doesn’t know how long it might take for her transaction and subsequent blocks to get confirmed. If Gulliver wants to withdraw his offer he must submit a cancel transaction to the Blockchain network spending his dust input, this will cancel the sell offer as no one else will be able to submit the partial transaction (SACP) because the input has been spent and a subsequent attempt to submit the transaction would point to the same input dust UTXO and fail thanks to double spend protection.
7. The Summa contract will check the Merkle root of inclusion and the block headers against the security parameter, and if all is good, the contract will transfer Gulliver’s 5 ETH (held in escrow) to Lilly’s Ethereum account on the Ethereum Mainnet. BAM!
Bitcoin has a constraint that an input UTXO to a TX can only be spent once, no double spends, that means only one buy transaction for a seller’s offer will make it into the Bitcoin network. This is also used when cancelling a sell order, all cancellations or fulfillments happen on the Bitcoin side.
Gulliver (the seller of ETH) has an open offer with a partial SACP Bitcoin transaction that has not been accepted on chain, and he wants to cancel it. No problem! Summa has a Bitcoin solution for this. Gulliver simply submits a full ALL (no open inputs as opposed to the open SACP transaction) Bitcoin transaction directly to the Bitcoin blockchain using the same (fixed) UTXO dust input from SACP Bitcoin transaction that is open in Summa contract. Once the ALL cancellation transaction is accepted in the Bitcoin network, the SACP sitting in the Summa contract will no longer be valid, as it now has an input UTXO that has been spent!
Now Gulliver can send the Merkle root of the block that accepted his cancellation transaction and the subsequent Bitcoin blocks to the Summa contract and the 5 ETH will be sent to the Ethereum address he specified in the cancellation transaction output.
- The simplicity sparks joy! Simple ain’t easy, but you know it when you’ve got it. There are minimal intertwining of concerns, each piece is separate yet has an important function.
- There are no timing assumption.
- Uses Bitcoin primitives like lego blocks to build up a functioning, secure (configurable), system.
- It uses PoW in a novel way, showing the power of a non-interactive distributed system algorithm. I always get excited about PoW.
- It uses UTXOs as the enforcing constraint to avoid double spends which in Summa’s case would be two actors executing take the same order, e.g. two actors on the Bitcoin network successfully submitting the completed Bitcoin transaction.
- They made some cool libraries to parse BTC blocks in solidity (madness).
Thanks to James Prestwich for coming up with Summa, for explain it, and for reviewing!