Good morning,

I'm re-sending this message below as it appears to have gotten lost before it 
reached cc: bitcoin-dev.

Paul even replied to it and the reply reached on-list, so I'm re-sending it as 
others might have gotten confused about the discussion.

So far I've come to realize that 
sidechain-headers-on-mainchain/SHOM/SHM/driveproofs creates a very weak peg, 
and that only sidechain-only miners can take advantage of this weak peg.  This 
is because, the fee paid by sidechain-only miners to mainchain miners will 
approach TRANSFERLIMIT / 288 to protect against theft, and then sidechain 
miners will be unable to replenish their maincoin stock (to pay for the 
blind-merge-mine) if they do not transfer *only* their sidecoins earned.


-------- Original Message --------
Subject: Re: [bitcoin-dev] Sidechain headers on mainchain (unification of 
drivechains and spv proofs)
Local Time: September 8, 2017 10:56 PM
UTC Time: September 8, 2017 2:56 PM
To: Chris Stewart <>, CryptAxe <>, Paul 
Sztorc <>
Bitcoin Protocol Discussion <>

Good morning,

Chris mentioned the use of OP_WITHDRAWPROOFVERIFY.  I've come to realize
that this is actually superior to use OP_WITHDRAWPROOFVERIFY with a
sidechain-headers-on-mainchain approach.

Briefly, a payment to OP_WITHDRAWPROOFVERIFY is an instruction to transfer
value from the mainchain to a sidechain.  Thus, a payment to
OP_WITHDRAWPROOFVERIFY includes the sidechain to pay to, and a commitment
to a sidechain address (or whatever is the equivalent to a sidechain

Various OP_WITHDRAWPROOFVERIFY explanations exist.  Most of them include
OP_REORGPROOFVERIFY.  With sidechain-headers-on-mainchain, however, there is
no need for reorg proofs.  This is because, the mainchain can see, in real
time, which branch of the sidechain is getting extended.  Thus if someone
attempts to defraud a sidechain by forking the sidechain to an invalid
state, sidechainers can immediately detect this on the mainchain and
immediately act to prevent the invalid fork from being advanced.  After
all, a reorg proof is really just an SPV proof that is longer than some
previous SPV proof, that shows that the previous SPV proof is incorrect,
by showing that the block at the specified height of the WT is not present
on a longer SPV proof.

Since sidechain-headers-on-mainchain implies merge mining of sidechains,
with no option to have independent proof-of-work of sidechains, the
sidechain's entire history is recorded on the mainchain, visible to all
mainchain nodes.


An advantage of sidechain-headers-on-mainchain is a side-to-side peg without
passing through the mainchain.
That is, a 2-way peg between any two chains, whether side or main.

Sidechains supporting side-to-side transfer would require supporting
OP_WITHDRAWPROOFVERIFY, but not any of the other parts of sidechains.

We must consider a WT format (withdrawal transaction) that is compatible
with an OP_WITHDRAWPROOFVERIFY Bitcoin transaction.

***That is, a lockbox UTXO on one chain is a WT on another chain.***

Sidechains need not follow the mainchain format for its normal
transactions, only for WT transactions that move coins across chains.

For this, mainchain should also have its own "sidechain ID".  Perhaps a
sidechain ID of 0 would be appropriate for mainchain, as its status as

Suppose we have two sidechains, Ess and Tee, both of which support
side-to-side pegs.

An Ess fullnode is a Bitcoin fullnode, but an Ess fullnode is not
necessarily a Tee fullnode, and vice versa.

A lockbox redemption in sidechain-headers-on-mainchain is simply a spend of
a lockbox, pointing to the sidechain header containing WT, the merkle tree
path to the WT transaction from the h* commitment of the header, the output
which locks, and so on as per usual OP_WITHDRAWPROOFVERIFY.

Then a sidechain can create tokens from nothing, that are locked in a
OP_WITHDRAWPROOFVERIFY lockbox; this is the only way to create sidecoin.
When transferring into a sidechain from mainchain, or anywhere, the
sidechain either creates tokens locked into OP_WITHDRAWPROOFVERIFY, or
looks for an existing UTXO with OP_WITHDRAWPROOFVERIFY from the source
chain and spends them (the latter is preferred as it is fewer
transactions and less space on the sideblock, reducing sidechain fees).

OP_WITHDRAWPROOFVERIFY on a sidechain would query the mainchain fullnodes.
Whatever rules allow lockbox unlocking on mainchain, will also be the same
rules that allow lockbox unlocking on sidechains.
A mainchain RPC can even be made to simplify sidechain verification of
side-to-side pegs, and to ensure that sidechains follow the same consensus

So if we want transfer TeeCoin to EssCoin, we spend into a
OP_WITHDRAWPROOFVERIFY lockbox on Teechain pointing to Esschain (i.e. a
Tee->Ess lockbox).  This lockbox is itself a WT from the point of view of
Esschain.  On Esschain, we look for an existing Ess->Tee lockbox, or
create a Ess->Tee lockbox of our own for a EssCoin fee.  Then we create a
spend of the Ess->Tee lockbox on Esschain, wait until spending is
possible, and then post that transaction on Esschain.

Again, with sidechain-headers-on-mainchain, reorg proofs are unnecessary,
since any invalid chain should be quickly buried by a valid chain,
unless the economic majority decides that a sidechain is not worth


All is not well, however.  Remember, on a sidechain, we can create new
sidecoin for free, provided they are in a lockbox.  Unlocking that
lockbox would require a valid WT on the chain that the lockbox is
dedicated to.  However, a lockbox on one chain is a WT on the other
chain.  We can create a free lockbox on Ess, then use that lockbox as
a WT on Tee, inflating TeeCoin.

Instead, we add an additional parameter, wtFlag, to
This parameter is ignored by OP_WITHDRAWPROOFVERIFY opcode.

However, this parameter is used to determine if it is a WT.  Sidechain
consensus should require that freely-created lockboxes set this
parameter to 0, so that a side block that creates free lockboxes where
this parameter is non-zero is an invalid side block.  Then a sidechain
will only treat a lockbox on another chain as a WT if the wtFlag
parameter is nonzero.  This way, freely-created lockboxes are not
valid WT.  Valid WT must lock actual, already unlocked coins, not
create new locked coins.

On Bitcoin, of course, this parameter must always be nonzero, since
freely-created lockboxes are not allowed on mainchain, as asset
issuance on mainchain is already fixed.


Let us now flesh out how WT and lockboxes look like.  As we mentioned, a
lockbox on one chain is a WT on the destination chain.  Or to be more
precise, what a destination chain sees as a WT, is a lockbox on the source

Thus, a lockbox is a Bitcoin-formatted transaction output paying to the

  <sidechain address commitment> <sidechain ID> OP_WITHDRAWPROOFVERIFY

(assuming a softfork, additional OP_DROP operations may occur after

Suppose the above lockbox is paid to in the Bitcoin mainchain, with the
sidechain ID being the ID of Esschain.  This is itself a WT transaction
from the point of view of Esschain, on the principle that a lockbox on
one chain is a WT on another chain.

Assuming Esschain is a brand-new sidechain, it has no EssCoins yet.  The
sidechain allows the arbitrary creation of sidecoin provided the new
sidecoins are in a lockbox whose sidechain address commitment is 0.  So
in Esschain, we create the same coins on a UTXO paying to the


The first 0 is the sidechain address commitment, which is 0 since this
output was not created by transferring to a sidechain; we
reuse the sidechain address commitment as the wtFlag.  The
second 0 is the mainchain's ID.  The above is a lockbox from the point of
view of Esschain.  It is not a WT on mainchain, however, because the
sidechain address commitment is 0, which we use also as the wtFlag

Now, how does a main-to-side peg work?  After creating the above output on
Esschain, we now spend the output with the below scriptSig:

  <mainchain output ID> <mainchain WT transaction> <merkle path to WT 
transaction> <mainchain block hash>

On Esschain, OP_WITHDRAWPROOFVERIFY then verifies that the mainchain block
hash is a valid past block of the mainchain, then locates the mainchain
header.  It then checks the merkle tree path to the mainchain WT
confirming that the mainchain contains that transaction, and confirms that
indicated output is in fact, a payment to an OP_WITHDRAWPROOFVERIFY, which
pushes the Esschain ID, and with a nonzero sidechain address commitment.

(Esschain also needs to ensure that a single WT is not used to unlock
multiple lockboxes on Esschain; the easiest way is to add it to a set,
but this set cannot be pruned; other ways of ensuring only a WT is only
used to unlock once might be designed)

On Esschain, the sidechain does one final check: the transaction that spends
an OP_WITHDRAWPROOFVERIFY must have an output that pays to the sidechain
address committed to, and that output's value must be the same as the value
locked in the mainchain.

(for now, I think all lockboxes must have the same fixed amount, for

Now suppose we want to convert back our EssCoin to Bitcoin.  We create a
lockbox on Esschain, paying to the below:

  <bitcoin P2SH address> 0 OP_WITHDRAWPROOFVERIFY

The bitcoin P2SH address is mainchain address commitment; for simplicity
we just use P2SH on mainchain as it can encode any address.  The 0 is the
mainchain ID.  The above Esschain lockbox is itself a WT from Esschain to

Then, we look for an unspent lockbox on Esschain whose sidechain ID is the
Esschain ID.  Note that we can select any lockbox with the correct
sidechain ID, regardless of the sidechain address commitment it may have.

Locating an appropriate mainchain lockbox for Esschain coins, we then
provide the below scriptSig, paying out to the bitcoin P2SH address we

  <esschain output ID> <esschain WT tx> <merkle path to WT tx> <esschain block 
header hash>

On mainchain, we check that the indicated sidechain block header hash is a
block header on the longest chain of Esschain.  We check it has sufficient
depth.  Then we check if the merkle path to the WT tx is correct and goes
to esschain WT tx.  Finally, we check the indicated output ID, and check that
it is indeed an Esschain lockbox dedicated to mainchain.  Finally, we check
that the transaction has an output that spends the lockbox amount to the
specified bitcoin P2SH address.

(similarly mainchain nees to ensure that the Esschain WT is only used

The key insight here is that side-to-side pegs are just like side-to-main
pegs.  Suppose instead we want to transfer our coins from Esscoin to
Teecoin.  We would instead pay to the following lockbox on Esschain:

  <teecoin address commitment> <teechain ID> OP_WITHDRAWPROOFVERIFY

Then a Teechain transaction spending some Tee->Ess lockbox (or a fresh
lockbox if there are no Tee->Ess lockboxes on Teechain) is created.
We proceed as if it were a side-to-main peg, except it is a peg to
Teechain, either creating or unlocking TeeCoins.  Indeed, mainchain
fullnodes may even provide an RPC for checking OP_WITHDRAWPROOFVERIFY,
so as to reduce risk that a sidechain breaks consensus due to buggy


All is still not well with side-to-side pegs, however.

Suppose the economic majority decides that Esschain must die.  Perhaps it
has some irrecoverable security bug, perhaps it adds features that allow
Esschain fullnodes to kill baby seals, perhaps a successful theft of
Esschain lockboxes was performed and Esscoins are now functionally
worthless.  Killing a sidechain is done by bribing miners to put invalid
values into h*, and thus stealing Bitcoin->Ess lockboxes.

If Esschain dies, however, and the economic majority is not prepared to keep
Esschain dead, it is possible to unlock Tee->Ess lockboxes on Teechain.
Unlocking existing Tee->Ess lockboxes on Teechain is safe, since they
represent coins that were locked into Bitcoin->Tee lockboxes.  However,
it is still possible to create "free" Tee->Ess lockboxes on Teechain, then
provide an invalid Tee->Ess WT lockbox on the now-moribund Esschain to
unlock the free Tee->Ess lockbox on Teechain, inflating TeeCoin value.
Thus in the presence of side-to-side pegs, the death of even one sidechain
represents the death of every other sidechain!

Thus, to properly kill Esschain, the economic majority should spam the
Esschain headers slot with a fixed value, say 0, forever.  This makes it
very difficult to create a Tee->Ess WT lockbox on Esschain, as you would
now be able to reverse a one-way hash function.

Alternatively, Teechain can softfork so that Tee->Ess lockboxes are no
longer creatable or spendable.  However, the death of Esschain requires
that all other sidechains, including Youchain, Veechain, Dubyachain, and
so on, to softfork similarly.

Perhaps both can be done: first the economic majority wanting to kill
Esschain starts spamming it with invalid spends of Bitcoin->Ess lockboxes,
then when all Bitcoin->Ess lockboxes have been stolen, spam it with 0s
until all other sidechains have banned free Ess lockboxes on their chains.
Then, the economic majority can leave Esschain dead, and a later softfork
of mainchain prevents Esschain from being extended and allows mainchain
fullnodes to prune Esschain headers.


Thieves will still have the same difficulty stealing from sidechains, but
now their payoff is increased.  If a thief wants to steal Esschain
lockboxes, then it is possible to pack an invalid Esschain block full of
invalid WT to other chains.  Even chains that don't have lockboxes to
Esschain can create lockboxes to Esschain for free.  Thus, instead of
stealing only one lockbox at a time on mainchain, the thief can steal one
lockbox on mainchain, and on every sidechain that supports side-to-side
pegs, at a time.  The risk/reward ratio may shift drastically in that case.

However, this does mean that users of one chain must pay attention to
attacks on other chains, not just the chain they use.  If Teechain has no
side-to-side pegs, then Teechain users will not care if Esschain is under
attack.  But if side-to-side pegs are allowed on Teechain, then Teechain
users must also care about Esschain's health, as well as the health of
every other sidechain in existence.  Mainchain is protected since free
lockboxes are not creatable on mainchain.  Each sidechain is not; thus
the user of any sidechain must also stand by users of every other
sidechain, or else they all fall apart.  Of course, this could more
simply lead to "I will not use Teechain even if it would be useful to me,
because if I use Teechain, I have to care about Esschain and Youchain and


Side-to-side pegs are useful to allow better liquidity and provide
arbitrage quickly between sidechains, without having to pass through
mainchain.  Otherwise, Esscoin may be valued slightly lower than Bitcoin,
then Teecoin valued slightly higher than Bitcoin, creating a larger
difference between Esscoin and Teecoin values than what a full
side-to-side peg could support.  2-way pegs from mainchain
to sidechain stabilize sidecoin with respect to maincoin.  Side-to-side
pegs stabilize all sidecoins to all other sidecoins.

Side-to-side pegs are enabled implicitly by sidechain-headers-on-mainchain,
as all sidechain fullnodes must necessarily be mainchain fullnodes, and
any mainchain fullnode can judge the validity of any WT from any sidechain
without a miner voting period.

Side-to-side pegs are a generalization of main-to-side and side-to-main
pegs.  A sidechain can simply implement OP_WITHDRAWPROOFVERIFY and allow
free lockboxes, and that is sufficient for the sidechain to support
imports of bitcoin from mainchain and from any other sidechain.

Side-to-side pegs seem to imply that all pegs must have the same bitcoin
value transferred.  What that value must be, is something that may be
debated endlessly.

A side-to-side peg is a cut-through of a side-to-main peg from
one sidechain into a main-to-side peg into another sidechain.  If a
withdrawal from side-to-main peg would be accepted by mainchain, then
another sidechain could, in principle, accept a proof that would
authorize a side-to-main peg directly as a side-to-side peg.

Side-to-side pegs make attacks on sidechains more lucrative, as it
becomes possible to print sidecoins by successfully attacking a
different sidechain.

Drivechain cannot implement side-to-side pegs, as WT validity is
voted on by mainchain miners, and asking mainchain miners about
side-to-side pegs requires mainchain miners to be aware of both
sidechains.  Sidechain-headers-on-mainchain publishes SPV proofs
continuously to the mainchain, and since any sidechain fullnode is
also a mainchain fullnode (since sidechains are mergemined), then
every sidechain fullnode is automatically capable of accessing
and verifying SPV proofs for every other sidechain.

However, the pegging here seems less flexible than the pegging
supported by drivechain.  Drivechain lets pegs be any size, with
miner voting being the basis of knowing how much money is owned
by whom.

bitcoin-dev mailing list

Reply via email to