OP_WITHDRAWPROOFVERIFY — The op code that powers SPV sidechains

Chris Stewart
4 min readMar 8, 2017

--

There has been a lot of excitement about sidechains in the Bitcoin ecosystem. I think of them as the holy grail of innovations. A sidechain allows you to use another token (such as Bitcoin) as the underlying asset for another blockchain. This prevents us from having to reboot the network effect of money and avoids the moral hazards that come with creating a new token. Contemporary issues in the Bitcoin blockchain can be solved with sidechains. For instance a developer could spin up a new sidechain that has a 2MB block without asking permission of anyone else.

There has been a few different models published for sidechains with various security trade offs. One is SPV sidechains, another is drivechains. In this blog post I’m going to focus on the op code that powers SPV chains — OP_WITHDRAWPROOFVERIFY.

What does OP_WITHDRAWPROOFVERIFY do at a high level?

OP_WPV is the op code that unlocks ‘reserve’ coins on a sidechain. A user needs to provide inputs to an output such that the output will evaluate to true — which will unlock the reserve coins. The user is credited on the sidechain with the amount of coins they locked up on the bitcoin blockchain. The change on the sidechain is sent back to the federation’s reserve address.

What does the script look like that holds all of the federations coins?

First let’s look at what an OP_WPV output looks like on elements.

This is fairly simple. the constant “0622..10f” is just the genesis block hash of the blockchain we are pegged to. In this case, it is the bitcoin blockchain I am running in regression test mode.

In plain English, to unlock coins from the federation’s reserve address, I must provide input(s) to the script above to make it evaluate to true. So let’s start looking at the things I need to provide to the OP_WPV output to get it to give me some coins!

What a user needs to provide to the OP_WPV output to redeemcoins

Taken from the elements implementation of OP_WITHDRAWPROOFVERIFY:

// 1. genesis block hash of the chain the withdraw is coming from

// 2. the index within the locking tx’s outputs we are claiming

// 3. the locking tx itself (WithdrawProofReadStackItem)

// 4. the merkle block structure which contains the block in which

// the locking transaction is present (WithdrawProofReadStackItem)

// 5. The contract which we are expected to send coins to

Let’s go through these one by one to add some commentary around what exactly these things mean.

1. genesis block hash of the chain the withdraw is coming from

This is self explanatory, we need to tell the OP_WPV output what chain we are trying to withdraw from. Since OP_WPV could theoretically support pegs from multiple blockchains, we need to be explicit about what chain we are withdrawing from. If we were supporting a peg to just one blockchain, I don’t think we would need this argument.

2. the index within the locking tx’s outputs we are claiming

Since our transaction that we are locking funds in will most likely have multiple outputs, we need to indicate which output contains the locked funds via its index in the transaction.

3. the locking tx itself (WithdrawProofReadStackItem)

This is the transaction that locks funds inside of the Bitcoin blockchain. We use the output index given before to find the output that specifically locks the funds on the blockchain. We will use this transaction to get the amount of coins we want to redeem on the sidechain.

4. the merkle block structure which contains the block in which the locking transaction is present (WithdrawProofReadStackItem)

This is the cryptographic proof that indicates the locking tx was included in the bitcoin blockchain. This is the same proof that SPV nodes use to validate a payment was included in the bitcoin blockchain. OP_WPV will make sure the locking transaction’s txid is included in the merkle block. It will also verify that the merkle block has the amount of proof of work it claims to have.

5. The contract which we are expected to send coins to

This is where the user’s unlocked sidechain coins will be sent if the OP_WITHDRAWPROOFVERIFY script evaluates to true. There is some rather fancy stuff happening underneath the hood here. One thing is that the federation cannot spend from the deposit address on the bitcoin blockchain until they have seen this contract since it is part of the redeem script. For the sake of complexity though, just pretend like this is a sidechain address that only you can control and the OP_WPV output can only send coins to this address — not any other address.

Here is a concrete example of what all of these arguments look like when you use them to claim coins on a sidechain:

If you provide all of this information, you can spend your sidechain coins freely! Yay! It should be noted though that elements validates proof of work on the bitcoin blockchain by making RPC calls to bitcoind itself. It also validates the transaction has X confirmations, where X is configurable. This is different that what the sidechains white paper suggests.

We are currently working on an implementation of OP_WITHDRAWPROOFVERIFY at SuredBits. We hope that our work will help move the industry towards interoperable open blockchains — which will allow us to avoid contentious debates in the future over parameters for a blockchain (such as block size). If this stuff interests you, please follow my company @SuredBits or my personal twitter account @Chris_Stewart_5.

Special thanks to gwillen, andytoshi, and instagibbs for clarifications on the implementation of OP_WITHDRAWPROOFVERIFY in elements.

EDIT:

Follow up blog post about what can go wrong when using OP_WPV to transfer coins into a sidechain.

https://medium.com/@Chris_Stewart_5/what-can-go-wrong-when-transferring-coins-into-a-sidechain-with-op-withdrawproofverify-b2f49b02ab60#.rnp30tm8n

--

--