[Lightning-dev] Using Per-Update Credential to enable Eltoo-Penalty

ZmnSCPxj ZmnSCPxj at protonmail.com
Sun Jul 14 04:48:22 UTC 2019


Good morning Atoine,

Thank you for your proposal.

> Eltoo has been criticized to lower the cost for a malicious party to
> test your monitoring of the chain. If we're able to reintroduce some
> form of punishment without breaking transaction symmetry that would be great.

The primary advantage of Decker-Russell-Osuntokun is that it eliminates "toxic waste".

By this we mean, older version of your channel database are "toxic" in that you, ***or someone who wants to attack you***, can use it (accidentally in your case, deliberately in the attacker case), and then you will lose all funds in the channel.

Note that access to your channel database, without necessarily accessing your node private keys, is often easier.
For example, C-Lightning stores channel data into an SQLITE database and exposes every transaction it makes to a `db_hook` that plugins can use to replicate the database elsewhere.
If you were to use an insufficiently secured plugin to replicate your database, an attacker might be able to access your channel data, replicate your database, and use an older version to frame you for theft and make you lose all your channel funds.

Thus, Decker-Russell-Osuntokun removes the punitive consideration so that you being framed for theft does not lose all your funds, it merely closes your channels.

However, it look to me that you attempt to fix the toxic waste issue, as you mention a "Mallory" later that attempts to frame Alice (possibly by broadcasting old state).
On the other hand, it seems, there is no description of how Alice might go about protecting herself from Mallory.

In particular, it seems to me that it would be trivial for Alice to avoid punishment by first creating a fake "Mallory", then taking whatever path would let Alice "off the hook" for a framing Mallory when at risk of getting caught, thus returning the "reduced cost for trying to steal channel funds".

>
> Transaction symmetry implies that we can't deduce from observing
> txid which party broadcast a previous state. How to assign the
> faulty broadcast to the right party to punish it in consequence ?
> Thanks to taproot we have cheap witness asymmetry.
> Witness asymmetry can be used as a way to force the broadcaster to reveal
> a secret, and so committing thatn the transaction is the latest one.
>
> If the party misbehaves, we wish to use the revealed secret to punish
> him on a second stage transaction. Doing so would be really insecure
> in case of reorg or even mempool monitoring by enabling a replay attack
> of your committed secret on a lower state update tx. i.e Mallory
> would counterfeit being Alice, and so enable the use of a punishment tx
> against an honest peer.
>
> To solve the assignment problem, we need to have per-update credentials,
> a secret committed to a state number. You need a scheme were both your
> highest credential can't be used against you while at the same time if some
> attacker broadcast a transaction with a lower credential you are able to
> punish him.
>
> How to make Bitcoin Script aware of a secret committed to
> a lower state number ? To do so, we may use some SIGHASH magic, if you sign
> two messages with the same key and we can be sure thatn the only difference between
> them is the nLocktime (encoding the state-number in eltoo), that means you
> tried to breach the contract.

Could a hash preimage be used instead, with revocation?
We would require that the hash preimage be unique per-update, but the same technique used in current Poon-Dryja (Russell shachain) can be used to store the preimages of revoked states.

>
> Without access to arbitrary messages on the stack, the only messages we can
> enforce signatures on are Bitcoin transactions. We force a party
> broadcasting an Update tx to sign it with
> SIGHASH_ANYPREVOUTSCRIPT|SIGHASH_NONE|SIGHASH_SINGLE. If someone can shows a
> Litigation Tx with a higher state than the Update, we know that this one has
> been revoked, and someone is cheating among channel parties. We enter in a
> Litigation phase, the Settlement Tx will be encumbered by a Challenge Tx against
> which you will need to produce a signature with the same SIGHASH flags as the Update Tx.,
> The only difference will be the nLocktime inherited from Litigation.
>
> Assume Alice is trying to cheat, now Bob can take the signature from her broadcast Update tx
> and Alice’s signature on the Challenge tx, pass it as witness to a script verifying their validity
> and identity. If their validity is true and identity is false, you can spend with a Justice tx,
> 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,
> she can redeem her funds.
>
> Eltoo-Penalty Transaction Tree
> ==============================
>
>                          
>                                Friendly Settlement Tx                                       Challenge Tx -- Justice Tx
>                                  /                                                                   /
>                                 /                                                                  /
> Funding-Output -- Update Tx -- Litigation Tx -- .. -- Hostile Settlement Tx --  Challenge Tx -- Justice Tx
>                                                                                                   \
>                                                                                                    \  Challenge Tx -- Justice Tx
>

I am uncertain if some of the alignment has gotten lost above, but currently your graph is somewhat confusing.

> Eltoo-Penalty Scripts
> ================
>
> (I've omitted chaperon signatures)
>
> FUNDING_OUTPUT:
> output 0:
> Q = P + tG
> P = muSig(A,B,C)
> scripts = [
> "OP_1 CHECKSIGVERIFY <Alice_key> CHECKSIGVERIFY" (Alice script path)
> "OP_1 CHECKSIGVERIFY <Bob_key> CHECKSIGVERIFY" (Bob script path)
> "OP_1 CHECKSIGVERIFY <Caroll_key> CHECKSIGVERIFY" (Caroll script path)
> ]
>
> UPDATE TX:
> nLocktime: 500e6 + n
> output 0:
> P = muSig(A,B,C)
> scripts = [
> "OP_1 CHECKSIGVERIFY" (friendly settlement script path)

This branch seems pointless --- could you not just use the non-taproot path?
You do not describe the friendly-settlement transaction anywhere.
Is the friendly-settlement have `nSequence` delay?
When is it created?


> "OP_1 CHECKSGIVERIFY 500e6+n OP_CLTV OP_DROP" (litigation script path)
> witness:
> "sig(A, hash_type=SINGLE|ANYPREVOUTANYSCRIPT|NONE) sig(P, hash_type=SINGLE)"  (Alice commitment signature)
> "sig(B, hash_type=SINGLE|ANYPREVOUTANYSCRIPT|NONE) sig(P, hash_type=SINGLE)"  (Bob commitment signature)
> "sig(C, hash_type=SINGLE|ANYPREVOUTANYSCRIPT|NONE) sig(P, hash_type=SINGLE)"  (Caroll commitment signature)

It looks to me that you cannot use a later update transaction to replace an older update transaction, as the shared signature does not use `SIGHASH_ANYPREVOUT`?

>
> LITIGATION TX:
> nLocktime: 500e6 + n
> nSequence: [delay]
> output 0:
> P = muSig(A,B,C)
> scripts = [
> "OP_1 CHECKSIG" (litigation script path)    
> "OP_1 CHECKSIGVERIFY" (hostile settlement script path)
> witness:
> "sig(P, hash_type=SINGLE|ANYPREVOUTANYSCRIPT)

You mentions later that "if anyone has a highest Litigation tx, he can use it", but it does not look like that the litigation script path enforces this, did you forget to add some `OP_CHECKLOCKTIMEVERIFY` here?

>
> HOSTILE SETTLEMENT TX:
> nLocktime: 0
> nSequence: [delay]
> output 0: (to_Alice)
> P = muSig(A,B,C)
> scripts = [
> "OP_1 CHECHSIGVERIFY <Alice_key> CHECKSIGVERIFY 500e6n OP_CLTV OP_DROP" (Alice challenge script path)
> ]
> output 1: (to_Bob)
> P = muSig(A,B,C)
> scripts = [
> "OP_1 CHECHSIGVERIFY <Bob_key> CHECKSIGVERIFY 500e6n OP_CLTV OP_DROP" (Bob challenge script path)
> ]
> output 2: (to_Caroll)
> P = muSig(A,B,C)
> scripts = [
> "OP_1 CHECHSIGVERIFY <Caroll_key> CHECKSIGVERIFY 500e6n OP_CLTV OP_DROP" (Caroll challenge script path)
> ]
> output N (pending HTLCs)
> witness:
> "sig(P, hash_type=ALL)
>
> CHALLENGE TX: (Alice case)
> nLocktime: 500e6n
> nSequence: 0
> output 0:
> P = muSig(A,B,C)
> scripts = [
> "OP_1 CHECKSIGVERIFY OP_DUP <Alice_key> CHECKSIGVERIFY OP_DUP OP_SWAP <Alice_key> CHECKSIGVERIFY
>     OP_EQUAL OP_NOT OP_VERIFY"  (proof-of-Alice-fraud script path)
> "<n> OP_CSV <Alice refund_key> (refund Alice script path)
> ]
> witness:
> "sig(A, hash_type=SINGLE|ANYPREVOUTANYSCRIPT|NONE) sig(P, hash_type=ALL)"
>
> JUSTICE TX: (Alice punishment)
> nLocktime: 500e6n
> nSequence: 0
> output 0: (to_Caroll)
> output 1: (to_Bob)    
> witness:
> "sig_Alice_from_update_tx sig_Alice_from_challenge_tx sig(P, hash_type=ALL)"

`P` here is `muSig(A,B,C)`?
Why would Alice willingly sign a `SIGHASH_ALL` signature (meaning the transaction IDs are known at this point and have been confirmed deeply onchain, so this is after Alice has gone and performed any attempts at theft) that would punish her?
What happens when the Litigation Tx is later than the initial Update Tx?

Maybe this should instead be a revocation key whose privkey Alice reveals as part of the update ritual?

If a later Litigation Tx is used, than the Update Tx that was put onchain, is the signature from the Update Tx valid on the same transaction where the Challenge Tx is valid?


Explicitly stating what transaction outputs are spent by each transaction input would be better, especially since your graph is unclear.


>
> State Update
> ============
>
> Alice, Bob and Caroll build new friendly Settlement tx N, new Update Tx and revoke old one by
> generating a Justice tx with state higher than the previous one, a hostile Settlement tx plus
> Y challenge txn and Y justice txn with Y number of parties.

You do not describe the friendly settlement transaction.
I assume it has some `nSequence` somewhere.

>
> Cooperative Case
> ================
>
> After X updates, Alice, Bob, Caroll, cooperate to closing transaction using key path
> spending of funding Taproot output, the spending transactions contains accurate balances.
>
> Unilateral Case
> ================
>
> After X updates, Alice broadcast the last Update tx N, by signing it with her private key with
> SIGHASH_NONE,SIGHASH_ANYPREVOUTANYSCRIPT,SIGHASH_SINGLE and use MuSig previously distributed
> between parties at state update. Her signature doesn't protect anything except commitment to
> the latest state number.
>
> After finalization of the friendly settlement tx, she can redeem her balance, and timeout/fulfill
> her outputs.
>
> If she has broadcast the latest state, none of the parties should be able to broadcast a Litigation
> tx with a highest state number. Her signature committing to the locktime, no one is able to
> counterfeit her identity by spending the funding taproot output with a lowest update tx.
>
> Malicious Case
> ==============
>
> Bob is broadcasting a lowest Update tx with his signature committing to it. Alice use Litigation tx
> to spend it, if anyone has a highest Litigation tx, he can use it. After Litigation tx finalization,
> hostile settlement transaction is used. Each output returning to a channel party, is encumbered
> by a "challenge". To unlock your funds, you must provide a signature against same pubkey and same
> SIGHASH flags than the one encumbering your tapscript for funding output.
>
> Challenge tx is using a taproot output, one leaf returning fund to Alice after some timelock,
> The other one, let anyone with a MuSig and two valid signatures committing to different nLocktime
> to send challenged fund to a Justice tx, doing an equal split between other channel parties.
>
> You need signatures to be safe against third-party malleability, i.e being able to tweak
> 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.
>
> Okay, I'm quite sure that Script gurus on this list are going to point flaws of this scheme.
> It's more a thought experiment and I was curious if anyone has other ideas to get Eltoo + penalties,
> if yes let it know !

The descriptions of the transactions and scripts involved are confusing and I am uncertain if you actually achieve your target.
Could you clarify?

Regards,
ZmnSCPxj


More information about the Lightning-dev mailing list