<div dir="ltr">Hi all,<br><br>Eltoo has been criticized to lower the cost for a malicious party to<br>test your monitoring of the chain. If we&#39;re able to reintroduce some <br>form of punishment without breaking transaction symmetry that would be great.<br><br>Transaction symmetry implies that we can&#39;t deduce from observing<br>txid which party broadcast a previous state. How to assign the<br>faulty broadcast to the right party to punish it in consequence ?<br>Thanks to taproot we have cheap witness asymmetry.<br>Witness asymmetry can be used as a way to force the broadcaster to reveal <br>a secret, and so committing thatn the transaction is the latest one.<br><br>If the party misbehaves, we wish to use the revealed secret to punish <br>him on a second stage transaction. Doing so would be really insecure<br>in case of reorg or even mempool monitoring by enabling a replay attack <br>of your committed secret on a lower state update tx. i.e Mallory<br>would counterfeit being Alice, and so enable the use of a punishment tx <br>against an honest peer.<br><br>To solve the assignment problem, we need to have per-update credentials,<br>a secret committed to a state number. You need a scheme were both your <br>highest credential can&#39;t be used against you while at the same time if some<br>attacker broadcast a transaction with a lower credential you are able to<br>punish him.<br><br>How to make Bitcoin Script aware of a secret committed to <br>a lower state number ? To do so, we may use some SIGHASH magic, if you sign <br>two messages with the same key and we can be sure thatn the only difference between <br>them is the nLocktime (encoding the state-number in eltoo), that means you <br>tried to breach the contract.<br><br>Without access to arbitrary messages on the stack, the only messages we can <br>enforce signatures on are Bitcoin transactions. We force a party <br>broadcasting an Update tx to sign it with <br>SIGHASH_ANYPREVOUTSCRIPT|SIGHASH_NONE|SIGHASH_SINGLE. If someone can shows a <br>Litigation Tx with a higher state than the Update, we know that this one has <br>been revoked, and someone is cheating among channel parties. We enter in a <br>Litigation phase, the Settlement Tx will be encumbered by a Challenge Tx against <br>which you will need to produce a signature with the same SIGHASH flags as the Update Tx.,<br>The only difference will be the nLocktime inherited from Litigation. <br><br>Assume Alice is trying to cheat, now Bob can take the signature from her broadcast Update tx<br>and Alice’s signature on the Challenge tx, pass it as witness to a script verifying their validity<br>and identity. If their validity is true and identity is false, you can spend with a Justice tx,<br>splitting Alice’s funds between the other parties. If validity is true and identity is true, then the script should fail. After timelock expiration, if no one has proven Alice misbehaved,<br>she can redeem her funds.<br><br>Eltoo-Penalty Transaction Tree<br>==============================<br><br><br><br>                          <br>                               Friendly Settlement Tx                                       Challenge Tx -- Justice Tx<br>                                 /                                                                   /<br>                                /                                                                  /<br>Funding-Output -- Update Tx -- Litigation Tx -- .. -- Hostile Settlement Tx --  Challenge Tx -- Justice Tx<br>                                                                                                  \<br>                                                                                                   \  Challenge Tx -- Justice Tx<br><br><br>Eltoo-Penalty Scripts<br>================<br><br>(I&#39;ve omitted chaperon signatures)<br><br>FUNDING_OUTPUT:<br>output 0:<br>Q = P + tG<br>P = muSig(A,B,C)<br>scripts = [<br>&quot;OP_1 CHECKSIGVERIFY &lt;Alice_key&gt; CHECKSIGVERIFY&quot; (Alice script path)<br>&quot;OP_1 CHECKSIGVERIFY &lt;Bob_key&gt; CHECKSIGVERIFY&quot; (Bob script path)<br>&quot;OP_1 CHECKSIGVERIFY &lt;Caroll_key&gt; CHECKSIGVERIFY&quot; (Caroll script path)<br>]<br><br>UPDATE TX:<br>nLocktime: 500e6 + n <br>output 0:<br>P = muSig(A,B,C)<br>scripts = [<br>&quot;OP_1 CHECKSIGVERIFY&quot; (friendly settlement script path)<br>&quot;OP_1 CHECKSGIVERIFY 500e6+n OP_CLTV OP_DROP&quot; (litigation script path)<br>witness:<br>&quot;sig(A, hash_type=SINGLE|ANYPREVOUTANYSCRIPT|NONE) sig(P, hash_type=SINGLE)&quot;  (Alice commitment signature)<br>&quot;sig(B, hash_type=SINGLE|ANYPREVOUTANYSCRIPT|NONE) sig(P, hash_type=SINGLE)&quot;  (Bob commitment signature)<br>&quot;sig(C, hash_type=SINGLE|ANYPREVOUTANYSCRIPT|NONE) sig(P, hash_type=SINGLE)&quot;  (Caroll commitment signature)<br><br>LITIGATION TX:<br>nLocktime: 500e6 + n<br>nSequence: [delay]<br>output 0:<br>P = muSig(A,B,C)<br>scripts = [<br>&quot;OP_1 CHECKSIG&quot; (litigation script path)    <br>&quot;OP_1 CHECKSIGVERIFY&quot; (hostile settlement script path)<br>witness:<br>&quot;sig(P, hash_type=SINGLE|ANYPREVOUTANYSCRIPT)<br><br><br>HOSTILE SETTLEMENT TX:<br>nLocktime: 0<br>nSequence: [delay]<br>output 0: (to_Alice)<br>P = muSig(A,B,C)<br>scripts = [<br>&quot;OP_1 CHECHSIGVERIFY &lt;Alice_key&gt; CHECKSIGVERIFY 500e6n OP_CLTV OP_DROP&quot; (Alice challenge script path)<br>]<br>output 1: (to_Bob)<br>P = muSig(A,B,C)<br>scripts = [<br>&quot;OP_1 CHECHSIGVERIFY &lt;Bob_key&gt; CHECKSIGVERIFY 500e6n OP_CLTV OP_DROP&quot; (Bob challenge script path)<br>]<br>output 2: (to_Caroll)<br>P = muSig(A,B,C)<br>scripts = [<br>&quot;OP_1 CHECHSIGVERIFY &lt;Caroll_key&gt; CHECKSIGVERIFY 500e6n OP_CLTV OP_DROP&quot; (Caroll challenge script path)<br>]<br>output N (pending HTLCs)<br>witness:<br>&quot;sig(P, hash_type=ALL)<br><br>CHALLENGE TX: (Alice case)<br>nLocktime: 500e6n<br>nSequence: 0<br>output 0:<br>P = muSig(A,B,C)<br>scripts = [<br>&quot;OP_1 CHECKSIGVERIFY OP_DUP &lt;Alice_key&gt; CHECKSIGVERIFY OP_DUP OP_SWAP &lt;Alice_key&gt; CHECKSIGVERIFY <br>    OP_EQUAL OP_NOT OP_VERIFY&quot;  (proof-of-Alice-fraud script path)<br>&quot;&lt;n&gt; OP_CSV &lt;Alice refund_key&gt; (refund Alice script path)<br>]<br>witness:<br>&quot;sig(A, hash_type=SINGLE|ANYPREVOUTANYSCRIPT|NONE) sig(P, hash_type=ALL)&quot;<br><br>JUSTICE TX: (Alice punishment)<br>nLocktime: 500e6n<br>nSequence: 0<br>output 0: (to_Caroll)<br>output 1: (to_Bob)    <br>witness:<br>&quot;sig_Alice_from_update_tx sig_Alice_from_challenge_tx sig(P, hash_type=ALL)&quot;<br><br><br>State Update <br>============<br><br>Alice, Bob and Caroll build new friendly Settlement tx N, new Update Tx and revoke old one by<br>generating a Justice tx with state higher than the previous one, a hostile Settlement tx plus <br>Y challenge txn and Y justice txn with Y number of parties.<br><br>Cooperative Case<br>================<br><br>After X updates, Alice, Bob, Caroll, cooperate to closing transaction using key path<br>spending of funding Taproot output, the spending transactions contains accurate balances.<br><br>Unilateral Case<br>================<br><br>After X updates, Alice broadcast the last Update tx N, by signing it with her private key with <br>SIGHASH_NONE,SIGHASH_ANYPREVOUTANYSCRIPT,SIGHASH_SINGLE and use MuSig previously distributed<br>between parties at state update. Her signature doesn&#39;t protect anything except commitment to <br>the latest state number.<br><br>After finalization of the friendly settlement tx, she can redeem her balance, and timeout/fulfill<br>her outputs.<br><br>If she has broadcast the latest state, none of the parties should be able to broadcast a Litigation<br>tx with a highest state number. Her signature committing to the locktime, no one is able to<br>counterfeit her identity by spending the funding taproot output with a lowest update tx.<br><br>Malicious Case<br>==============<br><br>Bob is broadcasting a lowest Update tx with his signature committing to it. Alice use Litigation tx<br>to spend it, if anyone has a highest Litigation tx, he can use it. After Litigation tx finalization,<br>hostile settlement transaction is used. Each output returning to a channel party, is encumbered<br>by a &quot;challenge&quot;. To unlock your funds, you must provide a signature against same pubkey and same<br>SIGHASH flags than the one encumbering your tapscript for funding output. <br><br>Challenge tx is using a taproot output, one leaf returning fund to Alice after some timelock, <br>The other one, let anyone with a MuSig and two valid signatures committing to different nLocktime <br>to send challenged fund to a Justice tx, doing an equal split between other channel parties.<br><br>You need signatures to be safe against third-party malleability, i.e being able to tweak<br>your signatures to be still valid but diff being interpreted as a proof of commitment on lowest state number. On the Justice tx, you need a new key type to enforce that every signature must have sighash SIGHASH_MASKLOCKTIMEWITH, where you expect the signature to be followed by the state number which is going to be used as locktime in transaction digest algorithm. So in this way state number are provided in witness and you can equivocate Justice tx as both revoked Update Tx and Challenge Tx.<br><br>Okay, I&#39;m quite sure that Script gurus on this list are going to point flaws of this scheme.<br>It&#39;s more a thought experiment and I was curious if anyone has other ideas to get Eltoo + penalties, <br>if yes let it know !<br></div>