Hi ZmnSCPxj, Deep thanks for your review.
Biggest gains with Eltoo are of course transaction symmetry and removing toxic waste. Reintroducing penalty on top of this shouldn't affect this two goals, that's why I'm trying to play with witnesses asymmetry and signatures committed to a state number with my proposal > 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". By creating a fake "Mallory" you mean being another party in the channel ? With current design to kick-off unilateral closing you need to reveal your signature to spend the funding output to the Update tx, so you can't equivocate after first step. You can be both Alice and Bob, try to cheat with Alice and don't broadcast Litigation as Bob, if Caroll is honest she should be able to punish you on Alice funds. > 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. There is few issues with preimages, if you use per-update preimages, you need to keep a Hostile Settlement tx for every update because preimages are paired with a given Hostile Settllement tx and can't be used to punish on any Hostile Settlement tx. Plus, in multiparty channels, Hostile Settlement tx at state N - 2, doesn't reflect the correct balance between honest participants at state N. If you go with one unique preimage, which stays the same for every update, you're not safe against reorg or mempool snooping, where a malicious party take your preimage and replays it on a lower state Update tx. > I am uncertain if some of the alignment has gotten lost above, but currently your graph is somewhat confusing. Friendly Settlement Tx must spend the Update Tx after some delay. We have one Challenge Tx per-party and it must spend the to_party output on Hostile Settlement Tx. (transactions graph by mail are an uncertain art, sorry about that) > 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? Oh you're right, you can use the taproot key spend path there. Friendly Settlement transaction is spending the Update tx and supports one output per party as return fund and HTLC outputs for every pending one. E.g to_Alice output is just encumbered by a Alice pubkey and HTLC outputs have timeout/preimage_fulfill branches. None of these outputs is encumbered by a punishment path. It should be created with every Update tx, it's symmetric for every channel party and yes should have nSequence set to some delay to let someone broadcast a Litigation tx on the Update tx. > 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`? Yes that's intentional, IMO a current flaw of Eltoo is if you share an Update tx with watchtowers, any of them can close the channel on your behalf, of course if at least one of them is honest it will broadcast the latest Update tx and your funds are safe minus transaction fees. But you have lost a channel. Splitting unilateral channel closing and enforcement of correct state on two different transactions should avoid this issue. Know you just give the Justice tx to everyone of your watchtower and keep the Update tx on your local client. If you don't have HTLCs in the flight that should be secure. > 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? Oh yes, thanks again I forgot to add an OP_CLTV in litigation script path. > `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? Yes P is muSig(A,B,C). If she has misbehaved, she is not going to be willingly to sign the Challenge tx, and let anyone use the signature comparison as a proof of cheat. So you're again right, a timelocked script spend path should be added on the to_Alice output where after some delay any honest channel party can spend it with the Justice tx. At initial state, there shouldn't be any Litigation tx, if you have a Litigation tx with a highest state number than an Update tx it means the Update tx has been revoked (and shouldn't be broadcast). > Maybe this should instead be a revocation key whose privkey Alice reveals as part of the update ritual? Hmmm I think if it's a private key revealed at update ritual, it means anyone can use it to spend the funding_output while counterfeiting being Alice. > 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? Main idea of this scheme is to used Per-Update Commitment to solve the assignment problem in a safe way. What we need on a higher-level are messages tied to a specific party and committed to a given state number. If anyone can prove to the blockchain you have broadcast 2 messages with different state number it means you breach the contract. Now how to do that with Script ? Only messages interpreted by the blockchain are bitcoin transactions. If we follow Taproot current transaction digest algorithm, without sighash flags set, assuming we spend a taproot output we have the following hashed elements : epoch, hash_type, nVersion, nLockTime, sha_prevouts, sha_amounts, sha_sequences, sha_outputs, spend_type, input_index, sha_annex. If we use SIGHASH_ANYPREVOUTANYSCRIPT + SIGHASH_NONE, we get the following hashed elements : epoch, hash_type, nVersion, nLocktime, spend_type, amount, nSequence, sha_annex. If we force to sign 2 different transactions with these both sighashes against same pubkey, and assuming there are spending the same amount and nSequences are equals, we should get identical signatures. If they are not, the only difference element is the nLocktime. That could be a way to make script aware of committed per-party state number. Using this in a Eltoo-Penalty scheme, the Challenge tx script is encumbered by a branch where if you show up with 2 valid signatures but non-identical, that's a proof the challenged party has tried to cheat. Of course, I guess you need a bit of expansion on script primitives, like SIGHASH_ANYPREVOUTANYSCRIPTANYAMOUNT and an OP_CHECKSIG_WITH_STATE_NUMBER with following syntax <sig> <state_number> <pubkey> OP_CSWSN and following semantic "verify this signature against this pubkey but first mask nLocktime of transaction with the second-to-top stack item". Because signatures need to be both valid on same transaction but they have committed to different nLocktime, Justice tx need to have a mutable nLocktime field at verification. I didn't think about the need of something like OP_CSWSN in first mail, some people pointed me the issue, so here the updated scripts. CHALLENGE TX: (Alice case) nLocktime: 500e6n nSequence: 0 output 0: P = muSig(A,B,C) scripts = [ "OP_1 CHECKSIGVERIFY OP_DUP <2> OP_ROLL <Alice_key> CHECKSIGVERIFY_WITH_STATE_NUMBER OP_SWAP OP_DUP <3> OP_ROLL <Alice_key> CHECKSIGVERIFY_WITH_STATE_NUMBER 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: "<state_number_update_tx> <sig_Alice_from_update_tx> <state_number_challenge_tx> <sig_Alice_from_challenge_tx> <sig(P, hash_type=ALL)>" To say it again, it's more a thought experiment, so if you hold so far, I thank you again :) Best, Antoine Le dim. 14 juil. 2019 à 00:48, ZmnSCPxj <zmnsc...@protonmail.com> a écrit : > 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 >
_______________________________________________ Lightning-dev mailing list Lightning-dev@lists.linuxfoundation.org https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev