<div>Good morning Conner,<br></div><div><br></div><div class="protonmail_signature_block"><div class="protonmail_signature_block-user protonmail_signature_block-empty"><br></div></div><div> <br></div><blockquote class="protonmail_quote" type="cite"><div dir="ltr"><p class="inbox-inbox-p1"><br></p><div><span class="inbox-inbox-s1">Hi </span><span class="inbox-inbox-s2">ZmnSCPxj,</span><span class="inbox-inbox-s1"><br></span></div><div>&gt; Can you describe the "encrypted blob" approach to me? Or point me to<br></div><div>&gt; materials?<br></div><div><br></div><div>There's an awesome watchtower thread on the mailing list from 2016 that starts<br></div><div>here [1]. It covers a broader range of possibilities than just the encrypted<br></div><div><span class="inbox-inbox-s1">blob approach, and also considers other revocation schemes, e.g. </span><span class="inbox-inbox-s2">elkrem</span><span class="inbox-inbox-s1">.<br><br>Similar to what you described, one encrypted blob approached discussed in<br>that thread is:<br></span><span class="inbox-inbox-s1">1. </span><span class="inbox-inbox-s2">hint</span><span class="inbox-inbox-s1"> = </span><span class="inbox-inbox-s2">tixd</span><span class="inbox-inbox-s1">[:16]<br></span><span class="inbox-inbox-s1">2. </span><span class="inbox-inbox-s2">blob</span><span class="inbox-inbox-s1"> = Enc(data, </span><span class="inbox-inbox-s2">txid</span><span class="inbox-inbox-s1">[16:])<br></span>3. Send (hint, blob) to watchtower.</div><div><br></div><div>Whenever a new block is mined, the watchtower checks if it has an entry for each<br></div><div><span class="inbox-inbox-s2">txid</span><span class="inbox-inbox-s1">[:16]. If so, it </span><span class="inbox-inbox-s2">decrypts</span><span class="inbox-inbox-s1"> using </span><span class="inbox-inbox-s2">txid</span><span class="inbox-inbox-s1">[16:], assembles the justice </span><span class="inbox-inbox-s2">txn</span><span class="inbox-inbox-s1">, and<br></span>broadcasts (assuming the reward output matches what was negotiated).</div><div><br></div><p><br></p></div></blockquote><div>Thank you, that is indeed similar to what I was thinking given the name "encrypted blob".<br></div><div><br></div><div>Also, thank you for the link. I have not had much time to back-read anything older than 2017 in the archives. I observe that neither Poon nor Dryja seem to strongly participate in this list from 2017 onwards.<br></div><div><br></div><blockquote class="protonmail_quote" type="cite"><div dir="ltr"><p class="inbox-inbox-p1"><br></p><div><span class="inbox-inbox-s1"><br>&gt; Do you have a description of the&nbsp;</span><span class="inbox-inbox-s2">WatchTower</span><span class="inbox-inbox-s1"> protocol used in </span><span class="inbox-inbox-s2">lnd</span><span class="inbox-inbox-s1">? It may be<br></span><span class="inbox-inbox-s1">&gt; useful to be </span><span class="inbox-inbox-s2">intercompatible</span><span class="inbox-inbox-s1">.<br></span></div><div>We don't have anything written up formally, though what we have currently<br></div><div>operates on the design above.<br></div><p><br></p></div></blockquote><div>I understand. It would be good to know what you have, and perhaps consider planning a new BOLT document for such.<br></div><div><br></div><div>Nicolas Dorier mentioned plans for BTCPay to somehow host "merchant support networks" where merchants may expose WatchTower endpoints, which other merchants may post revocation information for their channels to.<br></div><div><br></div><blockquote class="protonmail_quote" type="cite"><div dir="ltr"><p class="inbox-inbox-p1"><br></p><div><br></div><div>I'll also take this time to brain dump some recent investigations I've been doing on<br></div><p><br></p><p class="inbox-inbox-p1"><br></p><div>watchtowers. TL;DR @ fin.<br></div><p><br></p><p class="inbox-inbox-p1"><br></p><div>FWIW, I've been thinking about this in the context of the simple encrypted<br></div><div>blob approach, though the observations can generalize to other schemes.<br></div><p><br></p><p class="inbox-inbox-p1"><br></p><div><span class="inbox-inbox-s1">As </span><span class="inbox-inbox-s2">Laolu</span><span class="inbox-inbox-s1"> mentioned, the storage requirement for the watchtower is dominated by<br></span><span class="inbox-inbox-s1">the number of </span><span class="inbox-inbox-s2">HTLC</span><span class="inbox-inbox-s1"> signatures included in the encrypted blob. Due to<br></span><span class="inbox-inbox-s1">independence of the second stage transactions, there is a </span><span class="inbox-inbox-s2">combinatoric</span><span class="inbox-inbox-s1"> blowup in<br></span><span class="inbox-inbox-s1">the number of signatures that would need to be </span><span class="inbox-inbox-s2">pre</span><span class="inbox-inbox-s1">-signed under the revocation<br></span>private key _if sweeping of HTLC outputs is batched_.</div><div><br></div><div>If we want to batch sweep without more liberal sighash flags, I think we'd need to<br></div><div>pre-sign n*2^n signatures. There are 2^n&nbsp;<span class="inbox-inbox-s1">possible ways that n HTLCs can straddle<br>the first and second stages, and each permutation would require n distinct signatures<br>since the set of inputs is unique to each permutation. Needless to say, this isn't feasible<br>with the maximum number of&nbsp;</span><span class="inbox-inbox-s2">HTLCs&nbsp;</span>allowed in the protocol.<br></div></div></blockquote><div><br></div><div>Yes, I thought this too.<br></div><blockquote class="protonmail_quote" type="cite"><div dir="ltr"><p class="inbox-inbox-p1"><br></p><div><br></div><div>However, I have some observations that might inform an efficient set of<br></div><div>signatures we can choose to include in the encrypted blobs.<br></div><p><br></p><p class="inbox-inbox-p1"><br></p><div><span class="inbox-inbox-s1">The first is that the&nbsp;</span><span class="inbox-inbox-s2">HTLC</span><span class="inbox-inbox-s1"> timeout or </span><span class="inbox-inbox-s2">HTLC</span><span class="inbox-inbox-s1"> success transaction _must_ be<br></span>broadcast before the attacker can move funds back into their wallet. If</div><div>these transactions are never mined, it is actually fine to do nothing and leave<br></div><div>those outputs in the breached state.<br></div><div><br></div><div>If/when the victim comes back online, they themselves can sign and broadcast<br></div><div>a justice transaction that executes the revocation clause of either the offered or<br></div><div><span class="inbox-inbox-s1">received </span><span class="inbox-inbox-s2">HTLC</span><span class="inbox-inbox-s1"> scripts, based on the observed </span><span class="inbox-inbox-s2">spentness</span><span class="inbox-inbox-s1"> of the various commitment<br></span><span class="inbox-inbox-s2">HLTC</span><span class="inbox-inbox-s1"> outputs at that time. So, we can save on signature data by only requiring the<br></span>watchtower to act if second stage transactions are confirmed.</div></div></blockquote><div><br></div><div>This is a good observation!&nbsp; I initially thought that we would have to provide both the first-stage and second-stage revocation signatures.<br></div><blockquote class="protonmail_quote" type="cite"><div dir="ltr"><p class="inbox-inbox-p1"><br></p><div><span class="inbox-inbox-s1"><span class="inbox-inbox-inbox-inbox-s1">One&nbsp;</span><span class="inbox-inbox-inbox-inbox-s2"><span class="colour" style="color:inherit"><span class="size" style="font-size:inherit">reallyyy</span></span></span><span class="inbox-inbox-inbox-inbox-s1">&nbsp;nice thing about not having the watchtower sweep the&nbsp;</span><span class="inbox-inbox-inbox-inbox-s2">HTLC</span><span class="inbox-inbox-inbox-inbox-s1">&nbsp;outputs<br></span><span class="inbox-inbox-inbox-inbox-s1">on the commitment&nbsp;</span><span class="inbox-inbox-inbox-inbox-s2"><span class="colour" style="color:inherit"><span class="size" style="font-size:inherit">txn</span></span></span><span class="inbox-inbox-inbox-inbox-s1">&nbsp;directly is that it doesn't need to know how to<br></span><span class="inbox-inbox-inbox-inbox-s1">reconstruct the more complex&nbsp;</span><span class="inbox-inbox-inbox-inbox-s2">HTLC</span><span class="inbox-inbox-inbox-inbox-s1">&nbsp;redeem scripts. It only needs to reconstruct<br></span>commitment&nbsp;<span style="display:inline;border-bottom:2px solid transparent;background-repeat:no-repeat" class="inbox-inbox-gr_ inbox-inbox-gr_1315 inbox-inbox-gr-alert inbox-inbox-gr_spell inbox-inbox-gr_inline_cards inbox-inbox-gr_run_anim inbox-inbox-ContextualSpelling inbox-inbox-ins-del">to-local</span>&nbsp;and second-stage to-local scripts and witnesses. This means<br>the blob primarily contains:<br><span class="inbox-inbox-inbox-inbox-s1"><span class="inbox-inbox-inbox-inbox-Apple-converted-space">&nbsp;</span>- 1 revocation&nbsp;</span><span class="inbox-inbox-inbox-inbox-s2"><span class="colour" style="color:inherit"><span class="size" style="font-size:inherit">pubkey</span></span><br></span><span class="inbox-inbox-inbox-inbox-s1"><span class="inbox-inbox-inbox-inbox-Apple-converted-space">&nbsp;</span>- 1 local delay&nbsp;</span><span class="inbox-inbox-inbox-inbox-s2"><span class="colour" style="color:inherit"><span class="size" style="font-size:inherit">pubkey</span></span><br></span><span class="inbox-inbox-inbox-inbox-s1"><span class="inbox-inbox-inbox-inbox-Apple-converted-space">&nbsp;</span>- 1&nbsp;</span><span class="inbox-inbox-inbox-inbox-s2">CSV</span><span class="inbox-inbox-inbox-inbox-s1">&nbsp;delay<br>&nbsp;- 2 commitment signatures<br></span><span class="inbox-inbox-inbox-inbox-Apple-converted-space">&nbsp;</span>- n HTLC signatures<br><span class="inbox-inbox-inbox-inbox-s1">and we don't have to bother sending&nbsp;</span><span class="inbox-inbox-inbox-inbox-s2">CLTVs, local/remote htlc pubkeys,</span><span class="inbox-inbox-inbox-inbox-s1">&nbsp;or&nbsp;<br></span></span>payment hashes at all.</div><div><br></div><div>The storage for this ends up being something like ~100&nbsp;+ 64*(2+nhtlcs) when you<br></div><div>include other things like the sweep address.<br></div></div></blockquote><div><br></div><div>Thank you, that seems like a start at something that can be implemented.<br></div><blockquote class="protonmail_quote" type="cite"><div dir="ltr"><p class="inbox-inbox-p1"><br></p><div>The second observation is that the second stage transactions could be broadcast<br></div><div><span class="inbox-inbox-s1">sequentially such that the </span><span class="inbox-inbox-s2">CSV</span><span class="inbox-inbox-s1"> delays don't overlap at all. In this event, the<br></span>watchtower needs to sweep the HTLCs iteratively to prevent the attacker from</div><div>sweeping any of the outputs as the relative timelocks expire.<br></div></div></blockquote><div><br></div><div>Sorry, I seem confused this idea.&nbsp; Can you give example for commitment with 2x HTLC?<br></div><blockquote class="protonmail_quote" type="cite"><div dir="ltr"><p class="inbox-inbox-p1"><br></p><div><span class="inbox-inbox-s1">One minimal&nbsp;</span>solution could be to send signatures for independent sweep<br></div><div>transactions, allowing&nbsp;<span class="inbox-inbox-s1">the watchtower to sweep each </span><span class="inbox-inbox-s2">HTLC</span><span class="inbox-inbox-s1"> output individually.<br>This is nice because it&nbsp;</span><span class="inbox-inbox-s1">permits the watchtower to sweep exactly the subset of<br></span><span class="inbox-inbox-s2">HTLCs</span><span class="inbox-inbox-s1"> that ever transition&nbsp;</span><span class="inbox-inbox-s1">into the second stage, and under any permutation<br></span><span class="inbox-inbox-s2">wrt</span><span class="inbox-inbox-s1">. </span><span class="inbox-inbox-s2">ordering&nbsp;</span>of confirmed second stage transactions.</div></div></blockquote><div><br></div><div>Yes, this seems like a good general idea.<br></div><blockquote class="protonmail_quote" type="cite"><div dir="ltr"><p class="inbox-inbox-p1"><br></p><div><span class="inbox-inbox-s1">With the single transaction per&nbsp;</span><span class="inbox-inbox-s2">HTLC</span><span class="inbox-inbox-s1"> approach, the total number of signatures that<br></span><span class="inbox-inbox-s1">are sent to the watchtower remains linear in the number </span><span class="inbox-inbox-s2">HTLCs</span><span class="inbox-inbox-s1"> on the commitment<br></span>transaction. This approach does have the downside of consuming slightly more</div><div>fees, since each output is swept with a distinct transaction.<br></div><p><br></p><p class="inbox-inbox-p1"><br></p><div>However, this approach is fairly efficient in preventing the attacker entirely from<br></div><div>moving funds from the channel into their wallet wrt. to the amount of data stored.<br></div><div>Considering that the majority of the<span class="inbox-inbox-Apple-converted-space">&nbsp;</span>channel balance is expected to be in<br></div><div>the commitment outputs and that hypothetically on-chains fees are offset by the<br></div><div>remote balance, this could be an&nbsp;<span class="inbox-inbox-s1">acceptable </span><span class="inbox-inbox-s2">tradeoff</span><span class="inbox-inbox-s1">.</span><br></div><p><br></p><p class="inbox-inbox-p1"><br></p><div>I suspect that in practice, most second stage transactions will be valid by the<span class="inbox-inbox-Apple-converted-space">&nbsp;<br></span>time an attacker would drop to chain. Because of this, it's possible that they</div><div>could be mined in the same block as the breach transaction.<br></div><div><br></div><div>If everything is mined in the same block or in quick succession, it might be<br></div><div><span class="inbox-inbox-s1">worthwhile to also </span><span class="inbox-inbox-s2">pre</span><span class="inbox-inbox-s1">-sign a justice </span><span class="inbox-inbox-s2">txn</span><span class="inbox-inbox-s1"> that batch sweeps all </span><span class="inbox-inbox-s2">HTLCs</span><span class="inbox-inbox-s1"> directly<br></span><span class="inbox-inbox-s1">from the second layer, requiring one additional signature/</span><span class="inbox-inbox-s2">HTLC</span><span class="inbox-inbox-s1">.<span class="inbox-inbox-Apple-converted-space">&nbsp;<br></span></span></div><div>This could be a plausible scenario if the offender breached unintentionally, and<span class="inbox-inbox-Apple-converted-space">&nbsp;<br></span>their implementation tries to proceed normally. However it does require all of the<span class="inbox-inbox-Apple-converted-space"><br></span><span class="inbox-inbox-s2">CSV</span><span class="inbox-inbox-s1"> delays to conincide. If that doesn't happen, the watchtower can always<br></span>resort to sweeping the outputs individually.</div><div><span class="inbox-inbox-s1"><br>All in all, I think the ability to sweep each&nbsp;</span><span class="inbox-inbox-s2">HTLC</span><span class="inbox-inbox-s1"> independently is more-or-less<br></span>a requirement just given the complexity of how the on-chain state-space can<span class="inbox-inbox-Apple-converted-space">&nbsp;<br></span>manifest, especially if CLTVs have already expired. Other scenarios may</div><div>be worth including on a case by case basis or if we feel they are justified. This<br></div><div>could be handled dynamically by including some&nbsp;<span class="inbox-inbox-s2">bitvector</span><span class="inbox-inbox-s1"> or some compact<br>representation of how to reconstruct the transactions&nbsp;</span>for any additional, included</div><div>signatures.<br></div></div></blockquote><div><br></div><div>Okay.&nbsp; So it seems, the blob contains:<br></div><div><br></div><div>1.&nbsp; Revocation pubkey (from our revocation basepoint and per-commitment basepoint)<br></div><div>2.&nbsp; Their delayed payment pubkey (needed in scripts)<br></div><div>3.&nbsp; Our imposed to_self_delay (the setting we indicate, that we impose on the remote side)<br></div><div>4.&nbsp; Our payment pubkey<br></div><div>5.&nbsp; 0 or 1 or 2 signatures for the main outputs. These sign a single transaction that claims only the main outputs.<br></div><div>6.&nbsp; 0 or more second-stage HTLC revocation signatures.&nbsp; These sign individual transactions (one per HTLC) that claims only the second-stage HTLC output.<br></div><div>7.&nbsp; scriptpubkey to put all the funds in.<br></div><div><br></div><div>When the commitment txid is found onchain, the WatchTower creates a single main output claim transaction using the 1 or 2 signatures for the main outputs.&nbsp; And for each HTLC outpoint on the commitment transaction, if it gets spent, the WatchTower creates one HTLC justice transaction from the second-stage HTLC transaction.<br></div><div><br></div><div>Is that approximately what is needed?&nbsp; Have I missed anything?<br></div><div><br></div><div>Regards,<br></div><div>ZmnSCPxj<br></div>