Re: [Lightning-dev] Deriving channel keys deterministically from seed, musig, and channel establishment v2

2021-10-13 Thread Lloyd Fournier
Hi SomberNight,

I started a similar discussion less than a year ago on the list. The idea I
put forward works fine with MuSig and taproot.

https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-December/002907.html

The idea was considered for channel establishment v2 but in the end there
were various objections to it becoming specified as it forces
implementations to handle keys in a certain way. You can still do it
informally though by fixing your funding pubkey to be derived from the
Diffie-Hellman key of the two node ids. This makes the funding public keys
a (secret) deterministic function of the two node ids without making a
privacy leak.

FWIW I still think this is a good idea but in hindsight I think the
objections to it being mandatory are valid.

Cheers,

LL

On Sat, 18 Sept 2021 at 02:14, SomberNight via Lightning-dev <
lightning-dev@lists.linuxfoundation.org> wrote:

> Hi all,
>
> TL;DR: an approach is described how to derive channel keys
> deterministically that allows certain forms of recovery from just
> a seed, that works today. This approach however will no longer work
> with e.g. MuSig key aggregation in the future. An idea for a proposal
> is given how the channel-open flow (e.g. as part of channel v2) could be
> changed to make a similar approach work independent of key aggregation.
>
> -
>
> While implementing anchor output support in Electrum, we have realised
> one difficulty is to do with the remote-force-close case where the
> to_remote output is no longer a simple p2wpkh.
>
> Currently, pre-anchor-support, Electrum sets option_static_remotekey
> to required (feature bit 12), and we restrict lightning usage to wallets
> that derive p2wpkh addresses, and payment_basepoint is set
> to a bip32-derived pubkey that corresponds to a wallet address.
> Hence, if a user were to restore from seed words, and their channel
> counterparty force closed their channel, the to_remote output of the
> broadcast commitment tx would directly pay to the user's wallet.
> That is, in many typical scenarios, funds are not lost when restoring
> from seed.
>
> (Also, if we are the channel-funder/opener, it is easy to find the
> funding transaction, just by testing txs in the wallet history.
> Further, for the cases we are the channel-funder/opener,
> there is a setting to put an OP_RETURN in the funding tx, which stores
> the nodeid of the counterparty, allowing us to identify who to contact
> to get the channel closed.
> Also, we are (ab)using dataloss_protect to ask the remote
> to force-close when restoring from seed, so the user does not even have
> to wait for an arbitrarily long time.)
>
> With anchors, the to_remote is now a p2wsh that involves a CSV,
> and we cannot easily make this script correspond to a wallet address,
> i.e. we lose the property that the remote-force-close pays directly
> to a wallet address.
>
> So, the problem we would like to solve, is:
> - having seed words
> - having access to blockchain data
> - somehow having identified our channel counterparties (node IDs),
>   and our channels with them (funding outpoints)
> - and assuming we can get the remote to do a force-close
> --> we would like to be able to spend the to_remote output
>
> Solutions:
>
> 1) Naively, we could just derive a static key to be used as
> payment_basepoint, reused between all our channels, and watch the
> single resulting p2wsh script on-chain.
> Clearly this has terrible privacy implications.
>
> 2) Or, we could derive a new bip32 chain/sequence of pubkeys
> used as payment_basepoint for channels, and watch these p2wsh scripts,
> with a gap limit.
> Particularly the gap limit part makes this undesirable though
> (just consider having more than "gap limit" channels open and restoring
> from seed).
>
> Instead, it seems desirable to see whether we can extract some entropy
> from the blockchain, and use that as a nonce to be combined with a
> static private secret derived from our seed.
> We could extract data either from the funding tx, or from the
> remote-commitment-transaction that spent the funding output.
>
> 3) We exploit the fact that the funding output uses a
> 2of2 OP_CHECKMULTISIG script composed of the funding pubkeys of
> each party. The funding pubkey itself can be used as a nonce, and
> it can be recovered from the witness of the commitment tx.
> The privkey for payment_basepoint can then be derived as e.g.
> hash(bip32_derive(seed, HARDCODED_PATH) + funding_pubkey).
>
> In fact (3) is not novel at all: eclair has been deriving
> all their channel keys like this [0] for some time, from
> a static seed-based secret combined with the funding_pubkey as nonce,
> and generating the funding_privkey from ~os.urandom.
>
> Electrum will likely use (3) at least for the payment_basepoint,
> as part of adapting to anchors.
>
> -
>
> Note that the idea (3) relies on recovering the funding_pubkey from
> the witness of the spending transaction, which will break in the future
> if the funding 

Re: [Lightning-dev] Deriving channel keys deterministically from seed, musig, and channel establishment v2

2021-09-20 Thread ZmnSCPxj via Lightning-dev
Good morning SomberNight,

> Good morning ZmnSCPxj,
>
> > > Solutions:
> > >
> > > 1.  Naively, we could just derive a static key to be used as
> > > payment_basepoint, reused between all our channels, and watch the
> > > single resulting p2wsh script on-chain.
> > > Clearly this has terrible privacy implications.
> > >
> >
> > If the only problem is horrible privacy, and you have an 
> > `OP_RETURN`identifying the channel counterparty node id anyway, would it 
> > not be possible to tweak this for each channel?
> > static_payment_basepoint_key + hash(seed | counterparty_node_id)
> > This (should) result in a unique key for each counterparty, yet each 
> > individual counterparty cannot predict this tweak (and break your privacy 
> > by deriving the `static_payment_basepoint_key * G`).
>
> The OP_RETURN containing the encrypted counterparty node id
> is only an option, ideally it should not be required.
>
> Also, your proposal needs a counter too, to avoid reuse between multiple
> channels with the same counterparty. This counter is actually quite
> problematic as users should be able to open new channels after
> restoring from seed, which means they need to be able to figure out
> the last value of the counter reliably, which seems potentially
> problematic, so actually this might have to be a random nonce that is
> wide enough to make collisions unlikely... (potentially taking up
> valuable blockchain space in the OP_RETURN)


Yes, that does seem to be somewhat problematic.

As to your proposal to change the open v2 protocol --- as I understand it, the 
current channel establishment v2 is already deployed in production on 
C-Lightning nodes, so at minimum your proposed extension should probably use 
different feature bits and message IDs, I think.
CCing lisa for comment.

In any case, I think changing the actual commitment scheme to use 
MuSig1/MuSig2/MuSig-DN is lower priority than deploying PTLCs (and PTLCs can be 
used perfectly fine with the current commitment scheme, since you can spend 
from SegWitv1 P2WPKH to P2TR perfectly fine).
Though it certainly depends on others what exactly they prioritize.
I estimate that by the time we get around to MuSig, we may very well already 
have some kind of `SIGHASH_NOINPUT` or other more complicated scheme (I hope, 
maybe?) and might want to switch directly to Decker-Russell-Osuntokun instead 
of MuSig(2/DN)-Poon-Dryja.


Regards,
ZmnSCPxj
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


Re: [Lightning-dev] Deriving channel keys deterministically from seed, musig, and channel establishment v2

2021-09-20 Thread SomberNight via Lightning-dev
Good morning ZmnSCPxj,

> > Solutions:
> >
> > 1.  Naively, we could just derive a static key to be used as
> > payment_basepoint, reused between all our channels, and watch the
> > single resulting p2wsh script on-chain.
> > Clearly this has terrible privacy implications.
>
> If the only problem is horrible privacy, and you have an 
> `OP_RETURN`identifying the channel counterparty node id anyway, would it not 
> be possible to tweak this for each channel?
> static_payment_basepoint_key + hash(seed | counterparty_node_id)
> This (should) result in a unique key for each counterparty, yet each 
> individual counterparty cannot predict this tweak (and break your privacy by 
> deriving the `static_payment_basepoint_key * G`).

The OP_RETURN containing the encrypted counterparty node id
is only an option, ideally it should not be required.

Also, your proposal needs a counter too, to avoid reuse between multiple
channels with the same counterparty. This counter is actually quite
problematic as users should be able to open new channels after
restoring from seed, which means they need to be able to figure out
the last value of the counter reliably, which seems potentially
problematic, so actually this might have to be a random nonce that is
wide enough to make collisions unlikely... (potentially taking up
valuable blockchain space in the OP_RETURN)

Regards,
SomberNight

___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


Re: [Lightning-dev] Deriving channel keys deterministically from seed, musig, and channel establishment v2

2021-09-20 Thread ZmnSCPxj via Lightning-dev
Good morning SomberNight,


> Solutions:
>
> 1.  Naively, we could just derive a static key to be used as
> payment_basepoint, reused between all our channels, and watch the
> single resulting p2wsh script on-chain.
> Clearly this has terrible privacy implications.

If the only problem is horrible privacy, and you have an `OP_RETURN` 
identifying the channel counterparty node id anyway, would it not be possible 
to tweak this for each channel?

static_payment_basepoint_key + hash(seed | counterparty_node_id)

This (should) result in a unique key for each counterparty, yet each individual 
counterparty cannot predict this tweak (and break your privacy by deriving the 
`static_payment_basepoint_key * G`).

?

Regards,
ZmnSCPxj
___
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev


[Lightning-dev] Deriving channel keys deterministically from seed, musig, and channel establishment v2

2021-09-17 Thread SomberNight via Lightning-dev
Hi all,

TL;DR: an approach is described how to derive channel keys
deterministically that allows certain forms of recovery from just
a seed, that works today. This approach however will no longer work
with e.g. MuSig key aggregation in the future. An idea for a proposal
is given how the channel-open flow (e.g. as part of channel v2) could be
changed to make a similar approach work independent of key aggregation.

-

While implementing anchor output support in Electrum, we have realised
one difficulty is to do with the remote-force-close case where the
to_remote output is no longer a simple p2wpkh.

Currently, pre-anchor-support, Electrum sets option_static_remotekey
to required (feature bit 12), and we restrict lightning usage to wallets
that derive p2wpkh addresses, and payment_basepoint is set
to a bip32-derived pubkey that corresponds to a wallet address.
Hence, if a user were to restore from seed words, and their channel
counterparty force closed their channel, the to_remote output of the
broadcast commitment tx would directly pay to the user's wallet.
That is, in many typical scenarios, funds are not lost when restoring
from seed.

(Also, if we are the channel-funder/opener, it is easy to find the
funding transaction, just by testing txs in the wallet history.
Further, for the cases we are the channel-funder/opener,
there is a setting to put an OP_RETURN in the funding tx, which stores
the nodeid of the counterparty, allowing us to identify who to contact
to get the channel closed.
Also, we are (ab)using dataloss_protect to ask the remote
to force-close when restoring from seed, so the user does not even have
to wait for an arbitrarily long time.)

With anchors, the to_remote is now a p2wsh that involves a CSV,
and we cannot easily make this script correspond to a wallet address,
i.e. we lose the property that the remote-force-close pays directly
to a wallet address.

So, the problem we would like to solve, is:
- having seed words
- having access to blockchain data
- somehow having identified our channel counterparties (node IDs),
  and our channels with them (funding outpoints)
- and assuming we can get the remote to do a force-close
--> we would like to be able to spend the to_remote output

Solutions:

1) Naively, we could just derive a static key to be used as
payment_basepoint, reused between all our channels, and watch the
single resulting p2wsh script on-chain.
Clearly this has terrible privacy implications.

2) Or, we could derive a new bip32 chain/sequence of pubkeys
used as payment_basepoint for channels, and watch these p2wsh scripts,
with a gap limit.
Particularly the gap limit part makes this undesirable though
(just consider having more than "gap limit" channels open and restoring
from seed).

Instead, it seems desirable to see whether we can extract some entropy
from the blockchain, and use that as a nonce to be combined with a
static private secret derived from our seed.
We could extract data either from the funding tx, or from the
remote-commitment-transaction that spent the funding output.

3) We exploit the fact that the funding output uses a
2of2 OP_CHECKMULTISIG script composed of the funding pubkeys of
each party. The funding pubkey itself can be used as a nonce, and
it can be recovered from the witness of the commitment tx.
The privkey for payment_basepoint can then be derived as e.g.
hash(bip32_derive(seed, HARDCODED_PATH) + funding_pubkey).

In fact (3) is not novel at all: eclair has been deriving
all their channel keys like this [0] for some time, from
a static seed-based secret combined with the funding_pubkey as nonce,
and generating the funding_privkey from ~os.urandom.

Electrum will likely use (3) at least for the payment_basepoint,
as part of adapting to anchors.

-

Note that the idea (3) relies on recovering the funding_pubkey from
the witness of the spending transaction, which will break in the future
if the funding script is changed to e.g. a p2tr that uses musig.

Crucially, note that all the approach needs is some blockchain-visible
nonce that is already known at the time we need to construct the
open_channel message (as we want to be able to derive some of the keys
that are sent as part of the open_channel message
(e.g. payment_basepoint) from it).
As long as the funding output uses a 2of2 OP_CHECKMULTISIG,
the local funding_pubkey fits the bill.

Note that irrespective of any restrictions on the script used in
the funding output, we could use the funding scriptPubKey/address as
the nonce, if the open_channel/accept_channel messages were
split into two.
For example, instead of the single round of open_channel/accept_channel,
there could be two rounds:
- an open_channel_part1, where the peers exchange only
  the funding_pubkey (and the other non-pubkey fields), and
- an open_channel_part2, where the rest of the pubkeys are sent
This way the peers would learn what the funding address would be after
the first round finishes, and could potentially use that