OK, I'm now leaning *against* this method.

1. It removes the ability to update a channel without access to the node's
   secret key.  At the moment the node secret key is only needed for
   gossip and to DH to set up a new peer connection.  c-lightning does
   not use this for now (we keep the per-channel keys in the HSM too),
   but it would be a perfectly acceptable tradeoff not to do this.
2. It doesn't get rid of temporary_channel_id, since we don't know
   the generation_number until both sides have sent it.  We have a
   workaround for this already in dual-funding anyway.
3. Because we need a generation counter, it's not quite as easily
   scannable as you'd hope (the "gap" problem).

I think the "encrypted blob served by peers", even in a very naive way,
offers another way to do this, though it requires the assumption that at
least one peer is honest.

Damn, because it was so clever!

Thoughts?
Rusty.  

Rusty Russell <ru...@rustcorp.com.au> writes:
> Lloyd Fournier <lloyd.fo...@gmail.com> writes:
>> Hi Rusty,
>>
>> On Tue, 20 Apr 2021 at 10:55, Rusty Russell <ru...@rustcorp.com.au> wrote:
>>
>>> Lloyd Fournier <lloyd.fo...@gmail.com> writes:
>>> > On Wed, Dec 9, 2020 at 4:26 PM Rusty Russell <ru...@rustcorp.com.au>
>>> wrote:
>>> >
>>> >>
>>> >> Say r1=SHA256(ss || counter || 0), r2 = SHA256(ss || counter || 1)?
>>> >>
>>> >> Nice work.  This would be a definite recovery win.  We should add this
>>> >> to the DF spec, because Lisa was almost finished implmenting it, so it's
>>> >> clearly due for a change!
>>> >>
>>> >
>>> > Yes that's certainly a fine way to do it.
>>> > I was also thinking you could eliminate all "basepoints" (not just
>>> funding
>>> > pubkey) using something like this. i.e. just use the node pubkey as the
>>> > "basepoint" for everything and randomize it using the shared secret for
>>> > each purpose.
>>>
>>> OK, I tried to spec this out, to implement it.  One issue is that you
>>> now can't sign the commitment_tx (or htlc_tx) without knowing the node's
>>> secret key (or, equivalently, knowing the tweaked key and being able to
>>> use the derivation scheme to untweak it).
>>>
>>
>> Using node secret key to sign the commitment_tx seems like something you
>> will have to accept to introduce this feature. For the idea to work it has
>> to be some public key that is known by others and gossiped through the
>> network. Of course you could extend the information that is gossiped about
>> a node to include a "commit_tx_point" but the nodeid seems the more natural
>> choice.
>
> Duh, yes, of course you need the funding_key secret to sign the
> commitment tx.
>
> But you really don't want to access the `remote_pubkey` (which in a
> modern option_static_remotekey world is simply the payment_basepoint).
> It's generally considered good practice *not* to have this accessible to
> your lightning node at all.
>
>>> c-lightning currently does a round-trip to the signing daemon for this
>>> already, but it'd be nice to avoid requiring it.
>>>
>>> So I somewhat reluctantly added `commit_basepoint` from which the others
>>> are derived: an implementation can use some hardened derivation from its
>>> privkey (e.g. SHA256(node_privkey || ss || counter)) to create
>>> this in a deterministic but still private manner.
>>>
>>> Or we could just leave all the other points in and just replace
>>> funding_pubkey.
>>>
>>
>> Another approach is to do things in "soft-fork" like manner.
>> Each node that wants to offer this feature sets their funding_pubkey to a
>> specified DH tweak of the nodeid. Nodes that want backup-free channel
>> recovery can just refuse to carry on the funding protocol if the
>> funding_pubkey is not set the way it wanted.
>
> Yeah, you can totally do this in an opt-in manner, except it doesn't
> work unless your peer does it too.  Since we expect everyone to want to
> do this, it's clearer to force everyone to calculate this and not have
> redundant and confusing fields in the message.
>
>>>From my pruisit crypto point of view having only one public key is nice but
>> I'm not sure how it impacts things architecturally and other protocols like
>> watchtowers.
>
> They can operate exactly like the existing scheme, AFAICT.
>
> Here's the spec diff (based on dual-funding, since it's easier to simply
> hard change).  Please check my EC math! :)
>
> diff --git a/02-peer-protocol.md b/02-peer-protocol.md
> index fbc56c8..1114068 100644
> --- a/02-peer-protocol.md
> +++ b/02-peer-protocol.md
> @@ -867,11 +867,9 @@ This message initiates the v2 channel establishment 
> workflow.
>     * [`u16`:`to_self_delay`]
>     * [`u16`:`max_accepted_htlcs`]
>     * [`u32`:`locktime`]
> -   * [`point`:`funding_pubkey`]
> +   * [`u64`:`generation`]
>     * [`point`:`revocation_basepoint`]
>     * [`point`:`payment_basepoint`]
> -   * [`point`:`delayed_payment_basepoint`]
> -   * [`point`:`htlc_basepoint`]
>     * [`point`:`first_per_commitment_point`]
>     * [`byte`:`channel_flags`]
>     * [`opening_tlvs`:`tlvs`]
> @@ -895,13 +893,16 @@ If nodes have negotiated `option_dual_fund`:
>  
>  The sending node:
>    - MUST set `funding_feerate_perkw` to the feerate for this transaction
> -  - MUST ensure `temporary_channel_id` is unique from any
> -    other channel ID with the same peer.
> +  - MUST set `generation` to a number greater than any previous
> +    `generation` it has sent to this receiving node which has reached
> +    `commitment_signed`.
> +  - SHOULD set `generation` to the lowest number which meets this 
> requirement.
>  
>  The receiving node:
>    - MAY fail the negotiation if:
>      - the `locktime` is unacceptable
>      - the `funding_feerate_per_kw` is unacceptable
> +    - the `generation` exceeds expectation by more than the maximum it would 
> scan for recovery.
>  
>  #### Rationale
>  `channel_id` for the `open_channel2` MUST be derived using a zero-d out
> @@ -926,6 +927,13 @@ Instead, the channel reserve is fixed at 1% of the total 
> channel balance
>  rounded down to the nearest whole satoshi or the `dust_limit_satoshis`,
>  whichever is greater.
>  
> +`generation` is a number which is used to generate the points used for
> +this pair of peers, with the aim of allowing automatic onchain
> +scanning for channels if all other information is lost.  Since this
> +scan would presumably only try a limited number of generations, it is
> +best if this number is low, but it also needs to change for each
> +successive channel between the peers, to avoid obvious fingerprinting.
> +
>  Note that `push_msat` has been omitted.
>  
>  ### The `accept_channel2` Message
> @@ -943,11 +951,9 @@ acceptance of the new channel.
>      * [`u32`:`minimum_depth`]
>      * [`u16`:`to_self_delay`]
>      * [`u16`:`max_accepted_htlcs`]
> -    * [`point`:`funding_pubkey`]
> +    * [`u64`:`generation`]
>      * [`point`:`revocation_basepoint`]
>      * [`point`:`payment_basepoint`]
> -    * [`point`:`delayed_payment_basepoint`]
> -    * [`point`:`htlc_basepoint`]
>      * [`point`:`first_per_commitment_point`]
>      * [`accept_tlvs`:`tlvs`]
>  
> @@ -967,6 +973,10 @@ additions.
>  
>  The accepting node:
>      - MAY respond with a `funding_satoshis` value of zero.
> +    - MUST set `generation` to a number greater than any previous
> +      `generation` it has sent to this receiving node which has reached
> +      `commitment_signed`.
> +    - SHOULD set `generation` to the lowest number which meets this 
> requirement.
>  
>  #### Rationale
>  
> @@ -985,6 +995,31 @@ Funding composition for channel establishment v2 makes 
> use of the
>  [Interactive Transaction Construction](#interactive-transaction-construction)
>  protocol, with the following additional caveats.
>  
> +#### Point Derivation
> +
> +The `funding_pubkey` and basepoints are derived from the two
> +`node_id`s and the higher of the two `generation` values; the
> +`payment_basepoint` is supplied directly.
> +
> +Derivation is done as follows:
> +
> +1. Start with two node ids, `N1` and `N2` (`N1` is the lesser of the
> +   two SEC1-encoded compressed public keys, `N2` the greater).
> +2. Derive a shared secret, `SS`, using ECDH on `N1` and `N2`.
> +3. Define tweaks `T` for each peer, using `SHA256(SS || generation || 
> node_id || name)`, where:
> +   1. `generation` is the `u64` larger of the two `generation` fields from 
> `open_channel2` and `accept_channel2`.
> +   2. `node_id` is the SEC1-encoded compressed public key of the peer.
> +   3. `name` is a non-terminated ASCII string, e.g. `htlc` is the four bytes
> +   `0x68 0x74 0x6C 0x63`
> +4. The `funding_pubkey` is defined as the `node_id` + G*T(`funding`).
> +5. The `delayed_payment_basepoint` is defined as `node_id` + 
> G*T(`delayed_payment`).
> +6. The `htlc_basepoint` is defined as the `node_id` + G*T(`htlc`).
> +
> +If the secret for `payment_basepoint` is derived in a similar manner,
> +it too can be easily recovered from just the `generation`, node key
> +and peer `node_id`.  However, it may also point to an address for a
> +completely separate system (e.g. cold storage), so it is specified
> +explicitly in the protocol.
>  
>  #### The `tx_add_input` Message
>  
_______________________________________________
Lightning-dev mailing list
Lightning-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev

Reply via email to