{"type":"rich","version":"1.0","title":"Anthony Towns [ARCHIVE] wrote","author_name":"Anthony Towns [ARCHIVE] (npub17r…x9l2h)","author_url":"https://yabu.me/npub17rld56k4365lfphyd8u8kwuejey5xcazdxptserx03wc4jc9g24stx9l2h","provider_name":"njump","provider_url":"https://yabu.me","html":"📅 Original date posted:2021-10-08\n📝 Original message:\nHi all,\n\nHere's my proposal for replacing BOLT#2 and BOLT#3 to take advantage of\ntaproot and implement PTLCs. \n\nIt's particularly inspired by ZmnSCPxj's thoughts from Dec 2019 [0], and\nsome of his and Lloyd Fournier's posts since then (which are listed in\nreferences) -- in particular, I think those allow us to drop the latency\nfor forwarding a payment *massively* (though refunding a payment still\nrequires roundtrips), and also support receiving via a mostly offline\nlightning wallet, which seems kinda cool.\n\nI somehow hadn't realised it prior to a conversation with @brian_trollz\nvia twitter DM, but I think switching to PTLCs, even without eltoo,\nmeans that there's no longer any need to permanently store old payment\ninfo in order to recover the entirety of the channel's funds. (Some brute\nforce is required to recover the timeout info, but in my testing I think\nthat's about 0.05 seconds of work per ptlc output via python+libsecp256k1)\n\nThis doesn't require any soft-forks, so I think we could start work on\nit immediately, and the above benefits actually seem pretty worth it,\neven ignoring any privacy/efficiency benefits from doing taproot key\npath spends and forwarding PTLCs.\n\nI've sketched up the musig/musig2 parts for the \"balance\" transactions\nin python [1] and tested it a little on signet [2], which I think is\nenough to convince me that this is implementable. There'll be a bit of\npreliminary work needed in actually defining specs/BIPs for musig and\nmusig2 and adaptor signatures, I think.\n\nAnyway, details follow. They're also up on github as a gist [3] if that\nfloats your boat.\n\n[0] https://lists.linuxfoundation.org/pipermail/lightning-dev/2019-December/002375.html\n\n[1] https://github.com/ajtowns/bitcoin/blob/202109-ptlc-lnpenalty/test/functional/feature_ln_ptlc.py\n\n[2] The balance transaction (spending the funding tx and with outputs\n    being Alice's and Bob's channel balance is at):\n    https://explorer.bc-2.jp/tx/ba58d99dfaad83e105a0de1a9becfcf8eaf897aaaada54bd7b08134ff579997c?input:0\u0026expand\n\n[3] https://gist.github.com/ajtowns/12f58fa8a4dc9f136ed04ca2584816a2/\n\nGoals\n=====\n\n1. Support HTLCs\n2. Support PTLCs\n3. Minimise long-term data storage requirements\n4. Minimise latency when forwarding payments\n5. Minimise latency when refunding payments\n6. Support offline receiving\n7. Minimise on-chain footprint\n8. Minimise ability for third-parties to analyse\n\nSetup\n=====\n\nWe have two participants in the channel, Alice and Bob. They each have\nbip32 private keys, a and b, and share the corresponding xpubs A and B\nwith each other.\n\nMusig\n-----\n\nWe will use musig to combine the keys, where P = musig(A,B) = H(A,B,1)*A\n+ H(A,B,2)*B. We'll talk about subkeys of P, eg P/4/5/6, which are\ncalculated by taking subkeys of the input and then applying musig,\neg P/4/5/6 = musig(A/4/5/6, B/4/5/6). (Note that we don't use hardened\npaths anywhere)\n\nMusig2\n------\n\nWe'll use musig2 to sign for these keys, that is both parties will\npre-share two nonce points each, NA1, NA2, NB1, NB2, and the nonce will be\ncalculated as: R=(NA1+NB1)+k(NA2+NB2), where k=Hash(P,NA1,NA2,NB1,NB2,m),\nwhere P is the pubkey that will be signing and m is the message to be\nsigned. Note that NA1, NA2, NB1, NB2 can be calculated and shared prior\nto knowing what message will be signed.\n\nThe partial sig by A for a message m with nonce R as above is calculated as:\n\n    sa = (na1+k*na2) + H(R,A+B,m)*a\n\nwhere na1, na2, and a are the secrets generating NA1, NA2 and A respectively.\nCalculating the corresponding partial signature for B,\n\n    sb = (nb1+k*nb2) + H(R,A+B,m)*b\n\ngives a valid signature (R,sa+sb) for (A+B):\n\n    (sa+sb)G = R + H(R,A+B,m)*(A+B)\n\nNote that BIP340 sepcifies x-only pubkeys, so A+B and R implicitly have\neven y, however since those values are caluclated via musig and musig2\nrespectively, this cannot be ensured in advance. Instead, if we find:\n\n    H(A,B,1)*A + H(A,B,2)*B\n\ndoes not have even y, we calculate:\n\n    P = (-H(A,B,1))*A + (-H(A,B,2))*B\n\ninstead, which will have even y. Similarly, if (NA1+NB1+k(NA2+NB2)) does\nnot have even y, when signing, we replace each partial nonce by its negation,\neg: sa = -(na1+k*na2) + H(R,A+B,m).\n\nAdaptor Sigs\n------------\n\nAn adaptor signature for P for secret X is calculated as:\n\n    s = r + H(R+X, P, m)*p\n\nwhich gives:\n\n    (s+x)G = (R+X) + H(R+X, P, m)*P\n\nso that (R+X,s+x) is a valid signature by P of m, and the preimage for\nX can be calculated as the difference between the published sig and the\nadaptor sig, x=(s+x)-(s).\n\nNote that if R+X does not have even Y, we will need to negate both R and X,\nand the recovered secret preimage will be -x instead of x.\n\nRevocable Secrets\n-----------------\n\nAlice and Bob have shachain secrets RA(n) and RB(n) respectively,\nand second level shachain secrets RA2(n,i) and RB2(n,i), with n and i\ncounting up from 0 to a maximum.\n\nSummary\n=======\n\nWe'll introduce four layers of transactions:\n\n 1. The funding transaction - used to establish the channel, provides\n    the utxo backing the channel while the channel is open.\n 2. The balance transaction - tracks the funding transaction, contains\n    a \"balance\" output for each of the participants.\n 3. The inflight transactions - spends a balance output from the balance\n    transaction and provides outputs for any inflight htlc/ptlc transactions.\n 4. Layered transactions - spends inflight htlc/ptlc outputs by revealing\n    the preimage, while still allowing for the penalty path.\n\nFunding transaction\n===================\n\nThe funding transaction simply pays to P/0/f via taproot, where f starts\nat 0 and increases any time the funding transaction is updated onchain\n(eg when splicing funds in or out).\n\nBalance transaction\n===================\n\nThe balance transaction spends the funding transaction, and has two\noutputs, one for Alice's balance and one for Bob's balance (omitting a\nzero/dust balance).\n\nWe count the number of balance updates, starting at 0, and call it \"n\".\n\"n\" is encoded in the transaction locktime and the input nsequence, so\nif a balance transaction appears on chain, \"n\" can be decoded from the\nnsequence and locktime.\n\nAlice's balance is paid to an address with internal pubkey P/1/n/0\nand a script path of \"\u003cA/1/n\u003e CHECKSIGVERIFY \u003cD\u003e CSV\" where D is\nAlice's to_self_delay. Bob's balance is similar, with internal pubkey\nP/1/n/1.\n\nIn order to update to a new balance transaction, the process is as follows.\nFirst, nonces are exchanged in advance:\n\n  Alice:\n    Generates a nonce pair NA1, NA2 derived from RA(n). Shares this with\n    Bob.\n  Bob:\n    Generates a nonce pair NB1, NB2 derived from RB(n). Shares this with\n    Alice.\n\nThen, presuming Alice initiates the update:\n\n  Alice:\n    Generates deterministic nonce pair, DA1, DA2. Combines this with\n    Bob's NB1, NB2 nonce pair.  Generates partial signature for nonce\n    (DA, NB) for the transaction. Sends DA1 and DA2 and the partial\n    signature to Bob.\n\n  Bob:\n    Checks the partial signature is valid. Updates to the new balance\n    transaction. Generates a nonce pair, DB1, DB2, and gnerates a partial\n    signature for the balance transaction for nonce (NA, DB). Sends DB1,\n    DB2, and the partial signature to Alice. Generates a new revocable\n    secret RB(n+1). Revokes the previous secret RB(n) and sends the\n    details of both to Alice.\n\n  Alice:\n    Checks the partial signature is valid. Updates to the new balance\n    transaction. Checks the secret revocation info is correct and stores\n    it. Generates a new revocable secret RA(n+1). Revokes the previous\n    secret RA(n) and sends the details of both to Bob.\n\n  Bob:\n    Checks the secret revocation info is correct an stores it.\n\nThis means that both Alice and Bob have the same balance transaction here\n(with the same txid) but have different signatures for it (and thus\ndiffering wtxids).\n\nBecause updating the balance transaction involves two round trips\nbefore Bob can be sure Alice cannot use the old state, we move all the\ntransaction information to the inflight transactions, which we will be\nable to update immediately, without requiring a round trip at all.\n\nNote that if Bob publishes the signature for an old state, then the\nsignature is:\n\n   s = ((DA1+NB1) + k(DA2+NB2)) + H(R,A+B,m)(a+b)\n\nbut Alice can calculate the secrets for both DA1 and DA2 (she generated\nthose deterministically herself in the first place), and NB1 and NB2 (she\nhas the secret revocation information, and verified that it correctly\ngenerated the nonces Bob was using), which allows her to calculate Bob's\nprivate key using modular arithmetic:\n\n   b = H(R,P,m) / (s - (DA1+NB1) - b(DA2+NB2)) - a\n\nwhich means she can then directly sign without Bob's assistance, allowing\nher to claim any funds.\n\nInflight and Layered Transactions\n=================================\n\nWe construct two inflight transactions on top of the current balance\ntransaction, one spending Alice's balance, and one spending Bob's balance.\n\nWe will use \"i\" to represent the number of times a given inflight\ntransaction has been updated for the nth update to the balance\ntransaction.\n\nAt any time Alice can update the inflight transaction spending her balance\nto transfer funds towards Bob, either by updating the balances directly,\nor adding a htlc/ptlc entry to conditionally transfer funds to Bob. (And\nconversely for Bob)\n\nWe will define RP=musig(A/2/n/i, RB2(n,i)).\n\nThe inflight transaction spending Alice's balance can have multiple\ntypes of outputs:\n\n * Alice's remaining balance: pays directly to A/2/n/i\n\n * Bob's remaining balances: pays to RP/2 with script path\n   \"\u003cB/2/n/i\u003e CHECKSIGVERIFY \u003cD\u003e CSV\"\n\n * An htlc paying to Bob: pays to RP/2/k with script paths:\n   + \"LENGTH 32 EQUALVERIFY HASH160 \u003cX\u003e EQUALVERIFY \u003cB/2/n/i/k\u003e CHECKSIGVERIFY \u003cA/2/n/i/k\u003e CHECKSIG\"\n   + \"\u003cA/2/n/i/k/1\u003e CHECKSIGVERIFY \u003cT\u003e CLTV\"\n\n * A ptlc paying to Bob: pays to RP/2/k with script paths:\n   + \"\u003cB/2/n/i/k\u003e CHECKSIG NOTIF \u003cT\u003e CLTV DROP ENDIF \u003cA/2/n/i/k\u003e CHECKSIG\"\n\nAny outputs that would be zero or dust are not included.\n\nNote that we number each currently inflight transaction by \"k\",\nstarting at 0. The same htlc/ptlc may have a different value for k\nbetween different inflight transactions.\n\nThe inflight transation's locktime is set to the current block\nheight. This enables brute force searching for the locktime of any\ninflight ptlcs (so that in a penalty scenario when the other party posts\nan out of date inflight transaction, you can search through a small\nnumber of possible timeout values simply by not sending any ptlcs with\na timeout more that L blocks in the future).\n\nThe balance input's nsequence is used to encode the value of the lower\n24 bits of i in the same way the balance transaction's fund input's\nnsequence encodes the upper 24 bits of n.\n\nThe layered transaction will spend the htlc/ptlc outputs, with an\nANYONECANPAY|SINGLE signature by Alice using the A/2/n/i/k path.\nThe output committed to is:\n\n * pays to RP/3/k with script path:\n   + \u003cB/3/n/i/k\u003e CHECKSIGVERIFY \u003cD\u003e CSV\n\nwith no absolute or relative locktime.\n\nTo update the inflight transaction spending Alice's balance as well as\nany dependent layered transactions, the process is as follows:\n\n  Bob:\n    Generates a second level revocable secret, RB2(n,i) and sends Alice\n    the corresponding point, PB2. Calculates a nonce pair, NB1, NB2, and\n    sends that to Alice. This is done in advance.\n\n  Alice:\n    Calculates the new inflight transaction. Calculates new nonces NA1,\n    NA2, and partially signs the spend of her balance via the key path,\n    with musig2 nonces NA1, NB1, NA2, NB2. For each inflight htlc,\n    Alice provides a signature via A/2/n/i/k. For each inflight ptlc,\n    Alice provides an adaptor signature via the A/2/n/i/k/0 path that\n    is conditional on the ptlc's point.\n\n  Bob:\n    Bob verifies the new proposed inflight state and each of the\n    signatures. Bob may now rely on the new state. Bob revokes their\n    prior secret, RB2(n, i-1), and sends a new point/nonce pair (PB2',\n    NB1', NB2') to Alice to prepare for the next round.\n\nNote that Bob could stream multiple point/nonce pairs in advance,\nallowing Alice to do multiple inflight tx updates within the time taken\nfor a roundtrip.\n\nAlice can unilaterally do the following safely:\n\n 1. transfer from Alice's balance to Bob's balance\n 2. accept that a htlc/ptlc succeeded, removing the corresponding output\n    and allocating the funds associated with it directly to Bob's balance\n 3. introduce a htlc/ptlc, spending funds from Alice's balance\n\nHowever refunding/cancelling a htlc/ptlc requires a two-phase commit\nwith 1.5 round trips:\n\n - Bob proposes refunding a htlc/ptlc\n - Alice agrees and sends a partial signature for the new transaction\n   with the htlc/ptlc funds transferred back to her balance,\n - Bob records the new transaction, and revokes the earlier second\n   level secret RB2(n, i-1).\n - Alice verifies the revocation, and can safely treat the funds as\n   refunded (and thus refund back to the original payer, eg).\n\nThe advantage of doing this over negotiating a new balance transaction\nis that only the second level revocation secrets need to be online,\nallowing for operation by semi-offline lightning nodes (ie, having the\nchannel private key and first level revocation secrets offline). Such\nsemi-offline nodes risk losing funds in the \"inflight\" transaction\n(either by revealing the second level revocation secrets or by simply\ndata loss of the current inflight/layered transactions) but do not risk\nlosing or spending funds in their own output of the balance transaction.\n\nThis means the funds locked in Alice's balance can be spent in the\nfollowing ways:\n\n * Alice can claim them directly if Bob does not post the inflight\n   transaction before the delay expires, via the script balance output's\n   script path. Alice gets the entire balance in this case.\n\n * Bob can post a revoked inflight transaction, for which Alice knows the\n   secret for RB(n,i). In this case Alice recovers the value of i from\n   the nsequence (using brute force for the upper bits if she has\n   provided more than 16M updates of the inflight tx for any given\n   balance transaction), and then calculates the secret key for PB,\n   and hence PB/2/k and PB/3/k, at which point she can claim every\n   output via a key path spend, even if Bob posts some or all of the\n   layered transactions. Alice gets the entire balance in this case\n   (though spends more on fees).\n\n * Bob can post a current inflight transaction, along with layered\n   transactions for any of the inflight htlc/ptlcs for which he knows the\n   corresponding preimage, allowing Alice to recover the preimages from\n   the on-chain spends immediately. Alice can claim her balance output and\n   any timed out funds immediately as well. Bob can finish claiming his\n   balance and any claimed htlc/ptlc funds after the delay has finished.\n\nNote that Bob never shares his signature to spend Alice's balance prior\nto posting the inflight transaction, so Alice can never post an inflight\ntransaction that spends her own balance.\n\nThe cases where Alice may have difficulty claiming funds is Bob posts\na revoked inflight transaction (possibly spending a revoked balance\ntransaction) are:\n\n * if the inflight transaction contains a htlc output, then if Alice\n   has not retained the old htlc details (the hash160 and the timeout)\n   she will not be able to reconstruct the script path, and thus will\n   not be able to calculate the TapTweak to sign for the key path.\n   However if Bob attempts to claim the output (via the pre-signed\n   layered transaction), that will reveal the information she was missing,\n   and she can immediately claim the funds via the layered transaction\n   output, prior to Bob being able to spend that output.\n\n * if the inflight transaction contains a ptlc output, then if Alice\n   has not retained the old ptlc details (the point and the timeout)\n   she will not trivially be able to reconstruct the script path,\n   which includes the timeout. However, presuming the timeout was\n   within 5000 blocks, then the only possible timeouts are the inflight\n   tx's nlocktime+i with 0\u003ci\u003c=5000, and she will only need to calculate\n   5000*k cases and match the corresponding scriptPubKeys to exhaustively\n   enumerate every possible ptlc output, which should take under a minute,\n   and be easily achievable. In addition, if Bob attempts to claim the\n   funds, he will reveal the script path, and Alice will be either able\n   to claim the inflight output directly or the layered output.\n\nMisc\n====\n\nIn order to transition from BOLT#3 format to this proposal, an onchain\ntransaction is required, as the \"revocable signatures\" arrangement cannot\nbe mimicked via the existing 2-of-2 CHECKMULTISIG output.\n\nTo allow splicing in/out, it may be important to maintain multiple\nconcurrent funding transactions (paying to P/0/f and P/0/f+1 eg),\nwhich then requires maintaining multiple current balance transactions\n(paying to P/1/n/* and P/1/n+1/x eg) and likewise multiple current\ninflight/layered transactions. This will require ensuring the states\nfor all those transactions are synchoronised when verifying upates,\nand requires sharing multiple nonces for signing (eg RA(n) and RA(n+1)\nand RB2(n,i), and RB2(n+1,i)).\n\nFees for the balance and inflight transactions must be considered upfront,\nand paid for from the channel balance (or perhaps via additional anchor\noutputs that allocate more than the dust threshold and are immediately\nspendable). Fees for the layered transactions however can (and must)\nbe provided by whoever is attempting to claim the funds.\n\nBob having a current inflight transaction spending Alice's balance is\nadvantageous to Alice as Bob posting the inflight transaction allows\nher to immediately claim her balance, rather than having to wait for\nthe delay to complete.\n\nIf two nodes agree to only forward ptlcs in future, then updating the\nfunding transaction (to P/0/f+1 eg) and ignoring any proposed inflight\ntransactions that include htlc outputs is enough to ensure that all htlc\nrecords can be forgotten without risking any part of the channel balance\nbeing unclaimable.\n\nThis does not support option_static_remotekey, but compensates for that\nby allowing balances to be recovered with only the channel setup data\neven if all revocation data is lost.\n\n\nReferences\n==========\n\nHopefully the above includes enough explanation to be understood on its own,\nbut here's references for a bunch of the concepts.\n\n * musig: https://blockstream.com/2018/01/23/en-musig-key-aggregation-schnorr-signatures/\n\n * musig2: https://medium.com/blockstream/musig2-simple-two-round-schnorr-multisignatures-bf9582e99295\n\n * adaptor sigs: https://github.com/ElementsProject/scriptless-scripts/blob/master/md/atomic-swap.md\n\n * fast forwards [ZmnSCPxj]\n    https://lists.linuxfoundation.org/pipermail/lightning-dev/2019-April/001986.html\n    https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-May/003043.html\n    https://lists.linuxfoundation.org/pipermail/lightning-dev/2021-October/003265.html\n\n * revocable signatures [LLFourn]\n    https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-August/002785.html"}
