Re: [Lightning-dev] [RFC] Lightning gossip alternative

2022-03-22 Thread Olaoluwa Osuntokun
Hi Rusty,

> Timestamps are replaced with block heights.

This is a conceptually small change, but would actually make things like
rate limiting updates for implementations easier and more uniform. A simple
rule would be only allowing an update per block, which cuts down a lot on
potential chatter traffic, but maybe it's _too_ restrictive? Based on my
network observations, these days some many power user nodes more
aggressively
update their fee schedules in response to liquidity imbalances or as an
attempt to incentive usage of some channels vs others.

> 1. Nodes send out weekly node_announcement_v2, proving they own some
> UTXOs.

If a node doesn't send out this announcement, then will others start to
ignore their "channels"?

> 3. This uses UTXOs for anti-spam, but doesn't tie them to channels
> directly.

As I hinted a bit in prior discussion, and also my recent ML [1] post
outlining a possible "do most of the same things" stop gap, this has the
potentially undesirable effect of allowing parties on the network to utilize
_existing_ outputs to advertise false channels and inflate the "total
network capacity" metric. We'd effectively be moving away from "Alice and
Bob have N BTC of bound capacity between them to", "Bob has N BTC he can use
for signing these proofs".

Also while we're at it, why not add a merkle proof here (independent of
which direction we go with) which makes it possible for constrained/mobile
nodes to more easily verify gossip data (could be an optional query flag).

> FIXME: what about tapscripts?

Yeah, one side effect of moving to nodes advertising how much BTC they can
sign w/ vs the _actual_ BTC they have in "channels", is that to extend
validation here, the verifiers would need to fully verify possible script
path spends (assuming a scenario where a NUMs point is used as the internal
key).

> Legacy proofs are two signatures, similar to the existing
> channel_announcement.

Why not musig2? We'd be able to get away with just a single sig with this
modified `node_announcement_v2` and if we go the `channel_announcement2`
route, we'd be able to compress those 4 sigs into one.

> - If two node_announcement_v2 claim the same UTXO, use the first seen,
> discard any others.

So then this would mean that nodes that _actually_ have a channel between
them can't _individually_ claim the capacity?

> - node_announcement_v2 are discarded after a week (1000 blocks).  - Nodes
> do not need to monitor existence of UTXOs after initial check (since they
> will automatically prune them after a week).

A side effect of this would be _continual_ gossip churn in order to keep
channels alive. Today we do have the 2 week `channel_update` heart beat, but
channel updates are relatively small compared to this `node_announcement_v2`
message.

> - The total proved utxo value (not counting any utxos which are spent) is
> multiplied by 10 to give the "announcable_channel_capacity" for that node.

I don't see how this is at all useful in practice. We'd end up with inflated
numbers for the total node capacity, and path finding would be more
difficult as it isn't clear exactly how large an HTLC I can send over the
"channel". Sure there's the existence of max_htlc, but in that case why add
this "leverage" factor in the first place?

> 1. type: 273 (`channel_update_v2`)

This seems to allow the advertisement of channels which aren't actually
anchored in the chain, which I *think* is a cool thing to have? On the other
hand, the graph at the _edge_ level would be far more dynamic than it is
today (Bob can advertise an entirely distinct topology from one day to
another). Would need to think about the implications here for path finding
algorithms and nodes that want to maintain an update to date view of the
network...

> - `channel_id_and_claimant` is a 31-bit per-node channel_id which can be
> used in onion_messages, and a one bit stolen for the `claim` flag.

Where would this `channel_id` be derived from? FWIW, using this value in the
onion means we get a form of pubkey based routing [3] depending on how these
are derived.

> This simplifies gossip, requiring only two messages instead of three,
> and reducing the UTXO validation requirements to per-node instead of
> per-channel.

I'm not sure this would actually _simplify_ gossip in practice, given that
we'd be moving to a channel graph that isn't entirely based in the reality
of what's routable, and would be far more dynamic than it is today.

> We can use a convention that a channel_update_v2 with no `capacity` is a
> permanent close.

On the neutrino side, we tried to do something where if we see both channels
be disabled, then we'd mark the channel as closed. But in practice if you're
not syncing _every_ channel update every transmitted, then you'll end up
actually missing them.

> It also allows "leasing" of UTXOs: you could pay someone to sign their
> UTXO for your node_announcement, with some level of trust.

I'm not sure this is entirely a *good* thing, as the

[Lightning-dev] Taproot-aware Channel Announcements + Proof Verification

2022-03-22 Thread Olaoluwa Osuntokun
Hi y'all,

On the lnd side we've nearly finished fully integrating taproot into the
codebase [1] (which includes the btcsuite set of libraries and also full
btcwallet support), scheduled to ship in 0.15 (~April), which will enable
existing users of lnd's on-chain wallet and APIs to start getting taprooty
wit it. As any flavor of taproot will mean a different on-chain funding
output, the _existing_ gossip layer needs some sort of modification, as the
BOLTs today don't define how to validate that a given output is actually a
taproot channel. Discussions during the prior spec meetings seem to have
centered in on two possible paths:

  1. Use this as an opportunity to entirely redesign the channel validation
  portion of the gossip layer (ring sigs? zkps? less validation? better
  privacy?).

  2. Defer the above, and instead go with a more minimal mostly the same
  channel_announcement-like message for taproot channels.

In this mail, I want to explore the second option in detail, as Rusty has
already started a thread on what option #1 may look like [2].

## A new taproot-aware `channel_announcement2` message

A simple `channel_announcement2` message that was taproot aware could look
something like:

1. type: xxx (`channel_announcement2`) 2. data:
* [`signature`:`announcement_sig`]
* [`u16`:`len`]
* [`len*byte`:`features`]
* [`chain_hash`:`chain_hash`]
* [`short_channel_id`:`short_channel_id`]
* [`point`:`node_id_1`]
* [`point`:`node_id_2`]
* [`point`:`bitcoin_key_1`]
* [`point`:`bitcoin_key_2`]

(can assume it'll be just native TLV prob also)

This is pretty much the same as the _existing_ `channel_announcement`
message but instead of us carrying around 4 signatures, we'd use musig2 to
generate a _single_ signature under the aggregate public key
(`node_id_1`+`node_id_2`+`bitcoin_key_1`+`bitcoin_key_2`).

While were here, similar to what's been proposed in [2], it likely makes
sense to add an optional (?) merkle proof here to make channel validation
more feasible for constrained/mobile clients (they don't need to fetch all
those blocks any longer). The tradeoff here is that the merkle proof would
potentially be the largest part of the message, which means more on-chain
data needed to store the full channel graph. Alternatively, we could make
this into another gossip query option, with nodes only fetching the proofs
if they actually need it (full nodes with a txindex and just fetch the
transaction).

### Should the proof+verification strongly bind to the LN context?

As far as on-chain output validation, the main difference would be how nodes
actually validate the Bitcoin output (referenced by the `short_channel_id`)
on chain. Today, nodes use the two bitcoin keys and construct a p2wsh
multi-sig script and then verify that the script matches what has been
confirmed on chain. With taproot, the output is actually just a single key.
So if we want to maintain the same level of binding (which makes it harder
to advertise fake channels using just a change output have or something),
then we'd specify that nodes reconstruct the aggregated bitcoin public key
(Q = a_1*B_1 + a_2*_B_2, where a_i is a blinding factor derived using the
target key and every other key in the signing set) and assert that this
matches the pkScript on chain.

By verifying that this output key is just an aggregated key, then we can
also ensure that there's no actual committed script root (a la BIP 86 [3])
which binds the output to our context further. However maybe we want to also
include a `tapscript_root` field as well (so use the musig2 key as the
internal key and then apply the tweaking operations and verify things match
up), which would enable more elaborate unlocking/multi-sig functionality for
the normal funding output.

Alternatively, if we decided that this strong binding isn't as desirable
(starting to get into option 1 territory), then we'd specify just a single
Bitcoin key and look for that directly in the on chain script. IMO, if we're
going the route of something that very closely resembles what we have today,
then we shouldn't drop the strong binding, and fully verify that the key is
indeed a musig2 aggregated public key.

## `announcement_signatures2` and musig2 awareness

The `announcement_signatures` message would also need to change as we'd only
be sending a single signature across the wire: the musig2 _partial_
signature.

1. type: xxx (`announcement_signatures2`) 2. data:
* [`channel_id`:`channel_id`]
* [`short_channel_id`:`short_channel_id`]
* [`signature`:`partial_chan_proof_sig`]

Once both sides exchange this, as normal either party can generate the
`channel_announcement` message to broadcast to the network.

The addition of musig2 carries with it an additional dependency: before
these signatures can be generated, both sides need to exchange their public
nonce (in practice it's two nonces points R_1 and R_2), which is then used
to generate the aggregated nonce using for sign

Re: [Lightning-dev] A Proposal for Adding Bandwidth Metered Payment to Onion Messages

2022-03-22 Thread Olaoluwa Osuntokun
Hi Rusty,

> AMP seems to be a Lightning Labs proprietary extension.  You mean keysend,
> which at least has a draft spec?

I'm confused: the keyspend specification lives today as a very succinct bLIP
[1] (use this record that contains the preimage settle the payment), and the
AMP spec has had an open PR [2] (which admittedly needs to be mega-rebased)
for sometime now and is amongst the oldest PRs in the BOLT tracker. Your
definition of a "proprietary extension" here would seem to cover just about
every open BOLT pull request that hasn't yet been widely adopted by multiple
implementations.

With that aside, AMP is used here instead of keysend as each payment split
uses a different payment hash, which makes it harder to correlate payment
splits as both the amount and hash will differ. Also given that the e2e
payment needs to drop off additional fees (to pay for the forwarding pass)
to each hop, the receiver doesn't actually know how much to expect as total
payment (no invoice exists in this scenario). With keysend, it's possible
the receiver accidentally pulls early, with the funds irrevocably sent,
while no true onion messaging session has been constructed. With AMP the
sender is the one that controls _when_ all the funds can be pulled, which
eliminates such edge cases.

> Sure, let's keep encouraging people to use HTLCs for free to send data?  I
> can certainly implement that if you prefer!

I think the difference here is that HTLCs aren't that great for sending
data: any space you allocate to arbitrary data takes away from the total
route length. Also given the existence of the max_htlc parameters in channel
updates, nodes can increase this value which allows them to discourage
certain classes of behavior, as the HTLC that transmits the data serves
effectively as an ephemeral bond, meaning that HTLC data transfer attempts
incur an opportunity cost w.r.t the capital locked up.

As a result, what's deployed in the wild today that uses HTLCs to send data
(importantly at no additional marginal cost, since you sling 1.3KB across
the wire anyway for normal payments), imo is mostly cases that only need a
smaller amount of data, or use it mainly as a signalling layer. In contrast,
onion messaging would allow users to send 32 KB (and beyond?), which makes
certain classes of applications more feasible.

> I suggest naively limiting to 10/sec for peers with channels, and 1/sec
> for peers without for now.

Curious to see what a fleshed out version of this would look like. IMO if
this rate limiting event doesn't somehow make it back to the sender, then it
isn't clear exactly why they're unable to even fetch an invoice to _attempt_
a payment. I think one issue with defaulting to always fetching invoices in
a multi-hop manner is that a node failure may mean that a user can't even
obtain an invoice, compared to just hitting an API or scanning a QR code
that encodes one (pretty much 99% chance of success).

(I think there's also a side discussion here w.r.t if tightly coupling an
invoice/offer to a single node is compatible with the multi-node receive
architectures that some services are beginning to develop/deploy, but we can
make another thread for that.)

> You mean:
> 1. Don't use an even TLV field.

I don't see why one _wouldn't_ use an even field here: if the node doesn't
know what this means, then I want them to reject the payment, as otherwise
they aren't able to properly do the bandwidth metering. Even assuming a
feature bit, I think an even field would make sense, but ofc I'm open to
further reasoning.

> I think it's a premature optimization?  Make standard duration 2016
> blocks; then they can request multiples if they want?  Reduces
> node_announcement size.

Hmm, potentially but if I just need this to ask a node about their latest
ephemeral onion service, do I really need the session to persist for 2016
blocks? At just 8 bytes here, it's smaller than a tor v3 onion address and
even most feature bit distributions. Also there's nothing stopping someone
from advertising optional feature bit 12,324 which means that nodes need to
lug around and store all those extra bytes.

> I'd be tempted to use 16 bytes?  Collisions here are not really a thing
> since you'd need a network packet per probe, and you're time limited.

Yeah if the 32 bytes for each hop ends up eating too much into the total
route length, then most use cases can get by with 16 bytes.

> AFAICT this is easy to implement on top of onion_messages as they stand
> today (if you don't want to fwd free onion messages at all, don't set
> that bit?).

Correct! The idea is to give nodes that don't want to forward for free an
option to charge for forwarding and supplement their existing routing node
revenue.

On Twitter, Lisa brought up that as the data forwarding and payment aren't
"atomic", you're reliant on the nodes to actually "do the thing" once the
payment has been completed. This is correct, and imo can be mitigated mainly
via a "tit for tat approac