<oembed><type>rich</type><version>1.0</version><author_name>npub1g5zswf6y48f7fy90jf3tlcuwdmjn8znhzaa4vkmtxaeskca8hpss23ms3l</author_name><author_url>https://nostr.ae/npub1g5zswf6y48f7fy90jf3tlcuwdmjn8znhzaa4vkmtxaeskca8hpss23ms3l</author_url><provider_name>njump</provider_name><provider_url>https://nostr.ae</provider_url><html>📅 Original date posted:2022-02-23&#xA;📝 Original message:Subject: Turing-Completeness, And Its Enablement Of Drivechains&#xA;&#xA;Introduction&#xA;============&#xA;&#xA;Recently, David Harding challenged those opposed to recursive covenants&#xA;for *actual*, *concrete* reasons why recursive covenants are a Bad Thing&#xA;(TM).&#xA;&#xA;Generally, it is accepted that recursive covenants, together with the&#xA;ability to update loop variables, is sufficiently powerful to be&#xA;considered Turing-complete.&#xA;So, the question is: why is Turing-completness bad, if it requires&#xA;*multiple* transactions in order to implement Turing-completeness?&#xA;Surely the practical matter that fees must be paid for each transaction&#xA;serves as a backstop against Turing-completeness?&#xA;i.e. Fees end up being the &#34;maximum number of steps&#34;, which prevents a&#xA;language from becoming truly Turing-complete.&#xA;&#xA;I point out here that Drivechains is implementable on a Turing-complete&#xA;language.&#xA;And we have already rejected Drivechains, for the following reason:&#xA;&#xA;1.  Sidechain validators and mainchain miners have a strong incentive to&#xA;    merge their businesses.&#xA;2.  Mainchain miners end up validating and commiting to sidechain blocks.&#xA;3.  Ergo, sidechains on Drivechains become a block size increase.&#xA;&#xA;Also:&#xA;&#xA;1.  The sidechain-to-mainchain peg degrades the security of sidechain&#xA;    users from consensus &#34;everyone must agree to the rules&#34; to democracy&#xA;    &#34;if enough enfranchised voters say so, they can beat you up and steal&#xA;    your money&#34;.&#xA;&#xA;In this write-up, I will demonstrate how recursive covenants, with&#xA;loop variable update, is sufficient to implement a form Drivechains.&#xA;Logically, if the construct is general enough to form Drivechains, and&#xA;we rejected Drivechains, we should also reject the general construct.&#xA;&#xA;Digression: `OP_TLUV` And `OP_CAT` Implement Recursive Covenants&#xA;================================================================&#xA;&#xA;Let me now do some delaying tactics and demonstrate how `OP_TLUV` and&#xA;`OP_CAT` allow building recursive covenants by quining.&#xA;&#xA;`OP_TLUV` has a mode where the current Tapleaf is replaced, and the&#xA;new address is synthesized.&#xA;Then, an output of the transaction is validated to check that it has&#xA;the newly-synthesized address.&#xA;&#xA;Let me sketch how a simple recursive covenant can be built.&#xA;First, we split the covenant into three parts:&#xA;&#xA;1.  A hash.&#xA;2.  A piece of script which validates that the first witness item&#xA;    hashes to the above given hash in part #1, and then pushes that&#xA;    item into the alt stack.&#xA;3.  A piece of script which takes the item from the alt stack,&#xA;    hashes it, then concatenates a `OP_PUSH` of the hash to that&#xA;    item, then does a replace-mode `OP_TLUV`.&#xA;&#xA;Parts 1 and 2 must directly follow each other, but other SCRIPT&#xA;logic can be put in between parts 2 and 3.&#xA;Part 3 can even occur multiple times, in various `OP_IF` branches.&#xA;&#xA;In order to actually recurse, the top item in the witness stack must&#xA;be the covenant script, *minus* the hash.&#xA;This is supposed to be the quining argument.&#xA;&#xA;The convenant script part #2 then checks that the quining argument&#xA;matches the hash that is hardcoded into the SCRIPT.&#xA;This hash is the hash of the *rest* of the SCRIPT.&#xA;If the quining argument matches, then it *is* the SCRIPT minus its&#xA;hash, and we know that we can use that to recreate the original SCRIPT.&#xA;It then pushes them out of the way into the alt stack.&#xA;&#xA;Part #3 then recovers the original SCRIPT from the alt stack, and&#xA;resynthesizes the original SCRIPT.&#xA;The `OP_TLUV` is then able to resynthesize the original address.&#xA;&#xA;Updating Loop Variables&#xA;-----------------------&#xA;&#xA;But repeating the same SCRIPT over and over is boring.&#xA;&#xA;What is much more interesting is to be able to *change* the SCRIPT&#xA;on each iteration, such that certain values on the SCRIPT can be&#xA;changed.&#xA;&#xA;Suppose our SCRIPT has a loop variable `i` that we want to change&#xA;each time we execute our SCRIPT.&#xA;&#xA;We can simply put this loop variable after part 1 and before part 2.&#xA;Then part 2 is modified to first push this loop variable onto the&#xA;alt stack.&#xA;&#xA;The SCRIPT that gets checked is always starts from part 2.&#xA;Thus, the SCRIPT, minus the loop variable, is always constant.&#xA;The SCRIPT can then access the loop variable from the alt stack.&#xA;Part 2 can be extended so that the loop variable is on top of the&#xA;quined SCRIPT on the alt stack.&#xA;This lets the SCRIPT easily access the loop variable.&#xA;The SCRIPT can also update the loop variable by replacing the top&#xA;of the alt stack with a different item.&#xA;&#xA;Then part 3 first pops the alt stack top (the loop variable),&#xA;concatenates it with an appropriate push, then performs the&#xA;hash-then-concatenate dance.&#xA;This results in a SCRIPT that is the same as the original SCRIPT,&#xA;but with the loop variable possibly changed.&#xA;&#xA;The SCRIPT can use multiple loop variables; it is simply a question&#xA;of how hard it would be to access from the alt stack.&#xA;&#xA;Drivechains Over Recursive Covenants&#xA;====================================&#xA;&#xA;Drivechains can be split into four parts:&#xA;&#xA;1.  A way to commit to the sidechain blocks.&#xA;2.  A way to move funds from mainchain to sidechain.&#xA;3.  A way to store sidechain funds.&#xA;4.  A way to move funds from sidechain to mainchain.&#xA;&#xA;The first three can be easily implemented by a recursive covenant&#xA;without a loop variable, together with an opcode to impose some&#xA;restriction on amounts, such as `OP_IN_OUT_AMOUNT`.&#xA;&#xA;The technique we would use would be to put the entire sidechain&#xA;funds into a single UTXO, protected by a recursive covenant.&#xA;The recursive covenant ensures that it can store the sidechain&#xA;funds.&#xA;This covers part 3.&#xA;&#xA;The recursive covenant could, with the help of `OP_CAT` and&#xA;`OP_CTV`, check that every transaction spending the UTXO has a&#xA;second output that is an `OP_RETURN` with a commitment to the&#xA;sidechain block.&#xA;We can ensure that only one such transaction exists in each&#xA;mainchain block by adding a `&lt;1&gt; OP_CSV`, ensuring that only one&#xA;sidechain-commitment transaction can occur on each mainchain&#xA;block.&#xA;This covers part 1.&#xA;&#xA;Mainchain-to-sidechain pegs require the cooperation of a&#xA;sidechain validator.&#xA;The sidechain validator creates a block that instantiates the&#xA;peg-in on the sidechain, then creates a transaction that commits&#xA;to that sidechain block including the peg-in, and spending the&#xA;current sidechain UTXO *and* the mainchain funds being transferred&#xA;in.&#xA;Then the entity requesting the peg-in checks the sidechain block&#xA;and the commitment on the transaction, then signs the transaction.&#xA;The value restriction on the recursive covenant should then be to&#xA;allow the output to be equal, or larger, than the input.&#xA;This covers part 2.&#xA;&#xA;The recursive sidechain covenant by itself has a constant SCRIPT,&#xA;and thus has a constant address.&#xA;&#xA;The last part of Drivechains -- sidechain-to-mainchain peg ---&#xA;is significantly more interesting.&#xA;&#xA;Digression: Hashes As Peano Naturals&#xA;------------------------------------&#xA;&#xA;It is possible to represent natural numbers using the following&#xA;Haskell data type:&#xA;&#xA;```Haskell&#xA;data Nat = Z&#xA;         | S Nat&#xA;-- Z :: Nat&#xA;-- S :: Nat -&gt; Nat&#xA;```&#xA;&#xA;We can represent naturals as:&#xA;&#xA;* `0` == `Z`&#xA;* `1` == `S Z`&#xA;* `2` == `S (S Z)`&#xA;* `3` == `S (S (S Z))`&#xA;* etc.&#xA;&#xA;How do we translate this into Bitcoin SCRIPT?&#xA;&#xA;* `Z` == Any arbitrary 160-bit number.&#xA;* `S` == `OP_HASH160`.&#xA;&#xA;Thus:&#xA;&#xA;* `0` == `Z`&#xA;* `1` == `hash160(Z)`&#xA;* `2` == `hash160(hash160(Z))`&#xA;* `3` == `hash160(hash160(hash160(Z)))`&#xA;* etc.&#xA;&#xA;In particular:&#xA;&#xA;* We can increment a number by simply doing `OP_HASH160`.&#xA;* We can decrement a number by having the supposed&#xA;  decrementation be supplied on the witness stack, then&#xA;  validating that it is indeed the next lower number by&#xA;  hashing the witness item and comparing it to the number&#xA;  we have.&#xA;&#xA;Note also that ***we do not need `OP_ADD` or `OP_SUB` for&#xA;this***, though that would actually make it simpler.&#xA;(But yeah, the whole point is that *BITCOIN IS A LOT MORE&#xA;POWERFUL THAN YOU EXPECT*.)&#xA;&#xA;This is relevant to us due to how sidechain-to-mainchain&#xA;pegs are implemented.&#xA;&#xA;Drivechain Peg-Out&#xA;------------------&#xA;&#xA;In Drivechains, first somebody proposes to withdraw some&#xA;amount of funds from the sidechain to a mainchain address.&#xA;Then mainchain miners enter a voting period, during&#xA;which they either agree to the withdrawal, or disagree.&#xA;&#xA;We can use the above schema to keep track of a running&#xA;total number of votes.&#xA;&#xA;We define some numbers:&#xA;&#xA;* `Z` == `0`&#xA;* `P` == some maximum time period.&#xA;&#xA;We then encode `Z`, `P / 2`, and `P` using the hashed-Peano&#xA;encoding in the previous subsection.&#xA;&#xA;In order to allow withdrawals, we have an alternate branch,&#xA;such as a different Tapleaf, for a withdrawal SCRIPT.&#xA;This only requires that the first output has the same address&#xA;as itself (i.e. the sidechain covenant), and the second output&#xA;has a new recursive covenant, the peg-out covenant.&#xA;&#xA;The peg-out covenant has three loop variables:&#xA;&#xA;* `v`, initialized to `Z`.&#xA;  * This is the &#34;validity level&#34; of the peg-out.&#xA;  * Voters who want to vote &#34;for validity&#34; would *increment*&#xA;    this count.&#xA;  * Voters who want to vote &#34;against validity&#34; would&#xA;    *do nothing*.&#xA;* `t`, initialized to `Z`.&#xA;  * This is the voting time period.&#xA;  * Each time the peg-out covenant is used, this loop&#xA;    variable is incremented.&#xA;  * Once it reaches `P`, voting ends and the voting&#xA;    branches of the peg-out covenant are disabled,&#xA;* `a`, initialized to the peg-out address.&#xA;  * This is not actually changed in the covenant, but&#xA;    it is useful to keep it in the loop variable storage&#xA;    area.&#xA;  * With `OP_CTV` this can be an address that commits to&#xA;    any number of promised outputs.&#xA;&#xA;The peg-out covenant has these branches:&#xA;&#xA;* If `v` equals `P / 2`, then the UTXO can be spent to the&#xA;  address `a`.&#xA;  This is synthesized with an `OP_CTV` and `OP_CAT`.&#xA;* If `t` equals `P`, then the UTXO can only be spent&#xA;  by being pegged into the sidechain covenant.&#xA;  If this branch is not entered, we increment `t`.&#xA;  * This implies an inter-recursion between the sidechain&#xA;    covenant and the peg-out covenant.&#xA;* Check if the witness stack top is true or not:&#xA;  * If true, increment `v` and recurse (&#34;vote-for&#34; branch).&#xA;  * Else just recurse (&#34;vote-against&#34; branch).&#xA;&#xA;### Fixing Inter-recursion&#xA;&#xA;We can observe that the inter-recursion between the sidechain&#xA;covenant and the peg-out covenant is problematic:&#xA;&#xA;* `OP_CTV` requires that the hash of the output covenant is&#xA;  known.&#xA;* `OP_TLUV` will only replace the same output index as the&#xA;  input index it is on.&#xA;&#xA;This prevents the inter-recursion between the sidechain&#xA;covenant and the peg-out covenant.&#xA;&#xA;To fix this, we can observe that we can translate any set&#xA;of inter-recursive functions, such as this:&#xA;&#xA;```Haskell&#xA;foo :: FooArg -&gt; Result&#xA;foo fa = bar (fooCode fa)&#xA;bar :: BarArg -&gt; Result&#xA;bar ba = foo (barCode ba)&#xA;```&#xA;&#xA;...into a single self-recursive function:&#xA;&#xA;```Haskell&#xA;fooBar :: Either FooArg BarArg -&gt; Result&#xA;fooBar a = case a of&#xA;             Left  fa -&gt; fooBar (Right (fooCode fa))&#xA;             Right ba -&gt; fooBar (Left (barCode ba))&#xA;```&#xA;&#xA;Similarly, we can instead convert the inter-recursive&#xA;sidechain and peg-out covenants into a single&#xA;self-recursive covenant.&#xA;&#xA;This single covenant would have the same set of loop&#xA;variables `v`, `t`, and `a` as the peg-out covenant&#xA;described above.&#xA;This time, `a` is not an address, but an entire output&#xA;(i.e. `scriptPubKey` and `amount`).&#xA;&#xA;By default, `v`, `t`, and `a` are a number `0`.&#xA;If so, then there is no pending peg-out being voted on.&#xA;&#xA;If there is no pending peg-out, then either we just&#xA;commit to a sidechain block, or we commit to a sidechain&#xA;block *and* start a new peg-out by filling in `a`, and&#xA;initializing `v` and `t` to `Z`.&#xA;&#xA;If there is a pending peg-out, then either we just commit&#xA;to a sidechain block (and implicitly downvote the pending&#xA;peg-out) or commit to a sidechain block *and* indicate an&#xA;upvote of the pending peg-out.&#xA;&#xA;If `v` has reached the limit then we require, using&#xA;`OP_CTV`, that `a` appear on the second output, and that&#xA;the same SCRIPT (with `v`, `t`, and `a` reseet to `0`)&#xA;is on the first output, and do not impose any minimum&#xA;value for the first output, and the sidechain commitment&#xA;is now an `OP_RETURN` on the third output, and no other&#xA;outputs.&#xA;&#xA;If `t` has reached the limit, then we require simply that&#xA;the `v`, `t`, and `a` are reset to 0 and the sidechain&#xA;commitment.&#xA;&#xA;With the above, all components of Drivechain are implementable&#xA;with:&#xA;&#xA;* `OP_TLUV`&#xA;* `OP_CAT`&#xA;* `OP_CTV`&#xA;* `OP_IN_OUT_AMOUNT` of some kind, including the ability to&#xA;  check the output amount is larger than the input amount&#xA;  (e.g. by `OP_EQUAL` or `OP_GREATER`).&#xA;* Existing Bitcoin SCRIPT (`OP_ADD` **not** needed!).&#xA;&#xA;Conclusion&#xA;==========&#xA;&#xA;PH34R THE RECURSIVE COVENANT!&#xA;PH34R!!!!!!!</html></oembed>