Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split KeysInterface into EntropySource, NodeSigner, and SignerProvider #1910

Merged

Conversation

arik-so
Copy link
Contributor

@arik-so arik-so commented Dec 10, 2022

Context for reviewers:

The idea behind this PR is splitting KeysInterface into the three independent tasks and traits it actually comprises. The core changes of this PR are basically lightning::src::chain::keysinterface.rs:429-561.

While updating the trait implementers (KeyProvider [fuzz::chanmon_consistency, fuzz::full_stack, fuzz::onion_messages], Keys [channel::tests], KeysManager, PhantomKeysManager, OnlyReadsKeysInterface [util::test_utils], TestKeysInterface [util::test_utils]), we noticed that they all pretty much had the same implementation for get_node_id(), ecdh(), and sign_invoice(), with the sole exceptions of the PhantomKeysManager and TestKeysInterface.

So rather than requiring each type duplicate the same code, we put the implementation on the trait itself (NodeSigner), which, for sign_invoice(), required the addition of a secp context parameter.

All the other changes in this PR are simply a reflection of the new method location (docs) and the new method signature (mostly the invoice crate, which was using sign_invoice extensively, as well as a couple tests).

@TheBlueMatt
Copy link
Collaborator

Needs rebase, sorry about that.

lightning/src/chain/keysinterface.rs Outdated Show resolved Hide resolved
lightning/src/chain/keysinterface.rs Outdated Show resolved Hide resolved
///
/// This method should return a different value each time it is called, to avoid linking
/// on-chain funds across channels as controlled to the same user.
fn get_destination_script(&self) -> Script;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, ISTM that get_destination_script and get_shutdown_script should be merged (we have an old issue for this, maybe a PR too?) and maybe placed in the Signer instead - its value should really be channel-specific.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also fair point

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you thinking to push this off to a later PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the merging of these two should be in a separate PR imo

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, maybe lets not move these into Sign when we merge them. That way someone using an external wallet for static payouts doesn't need to touch InMemorySigner.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, interesting point. Thankfully outside the scope of this PR, but do you think that's sufficient reason? These values really are rather channel-specific.

In a more object-oriented world, the signers could in principle retain a reference to their SignerProvider, and by default take the value from there if they don't override the implementation, but I don't think that's a path we wanna go down.

@arik-so
Copy link
Contributor Author

arik-so commented Dec 12, 2022

Agree with your comments, Matt, just trying not to break too much at once.

@codecov-commenter
Copy link

codecov-commenter commented Dec 13, 2022

Codecov Report

Base: 90.73% // Head: 91.44% // Increases project coverage by +0.71% 🎉

Coverage data is based on head (9d7bb73) compared to base (56afbf5).
Patch coverage: 65.85% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1910      +/-   ##
==========================================
+ Coverage   90.73%   91.44%   +0.71%     
==========================================
  Files          94       95       +1     
  Lines       49603    53483    +3880     
  Branches    49603    53483    +3880     
==========================================
+ Hits        45006    48908    +3902     
+ Misses       4597     4575      -22     
Impacted Files Coverage Δ
lightning-background-processor/src/lib.rs 95.42% <ø> (ø)
lightning-invoice/src/utils.rs 97.76% <ø> (ø)
lightning/src/ln/chan_utils.rs 93.56% <ø> (ø)
lightning/src/ln/channel.rs 88.76% <0.00%> (-0.10%) ⬇️
lightning/src/ln/functional_test_utils.rs 93.73% <ø> (ø)
lightning/src/ln/functional_tests.rs 98.39% <ø> (+1.44%) ⬆️
lightning/src/ln/inbound_payment.rs 93.49% <ø> (ø)
lightning/src/ln/onion_route_tests.rs 97.64% <ø> (ø)
lightning/src/ln/payment_tests.rs 99.30% <ø> (+0.55%) ⬆️
lightning/src/ln/priv_short_conf_tests.rs 96.54% <ø> (ø)
... and 28 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@arik-so arik-so force-pushed the 2022-12-keys-interface-name-split branch from 01cecb7 to 7b70d4b Compare December 13, 2022 05:38
@TheBlueMatt TheBlueMatt added the blocked on next release Should Wait Until Next Release To Land label Dec 13, 2022
@TheBlueMatt
Copy link
Collaborator

Think this should wait for 114, given it, by itself, leaves the code in a kinda intermediate state.

@arik-so arik-so force-pushed the 2022-12-keys-interface-name-split branch 2 times, most recently from f07dbf9 to 06af918 Compare December 14, 2022 21:29
@arik-so arik-so changed the title WIP: Split KeysInterface into EntropySource, NodeSigner, and SignerProvider Split KeysInterface into EntropySource, NodeSigner, and SignerProvider Dec 14, 2022
@arik-so arik-so marked this pull request as ready for review December 14, 2022 21:29
@wpaulino wpaulino self-requested a review December 15, 2022 02:34
Copy link
Contributor

@wpaulino wpaulino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last unresolved link to fix:

error: unresolved link to `KeysInterface::derive_channel_signer`
   --> lightning/src/ln/channel.rs:743:8
    |
743 |     /// [`KeysInterface::derive_channel_signer`].
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `KeysInterface` has no associated item named `derive_channel_signer`

lightning/src/chain/keysinterface.rs Outdated Show resolved Hide resolved
// We need to override the invoice signing implementation for phantom keys managers
fn sign_invoice<C: Signing>(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient, _secp_context: &Secp256k1<C>) -> Result<RecoverableSignature, ()> {
let preimage = construct_invoice_preimage(&hrp_bytes, &invoice_data);
let secret = self.get_node_secret(recipient)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't we want to return an error if Recipient::Node is provided so that we don't accidentally sign with the node secret? I know we currently can't because the PhantomKeysManager owns KeysManager, but perhaps we could if we took a reference?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will be part of your get_node_secret removal PR :)

T::Target: BroadcasterInterface,
K::Target: KeysInterface,
K::Target: KeysInterface + NodeSigner,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need the explicit NodeSigner constraint after keeping the methods with default implementations on the traits and not on impl blocks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, we do.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not (anymore).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry. When I responded, we still had the default implementation in the trait.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why I said "anymore" :)

lightning/src/ln/inbound_payment.rs Outdated Show resolved Hide resolved
lightning-invoice/src/utils.rs Outdated Show resolved Hide resolved
@arik-so arik-so force-pushed the 2022-12-keys-interface-name-split branch 2 times, most recently from 37535c1 to 7536509 Compare December 16, 2022 05:38
@arik-so arik-so removed the blocked on next release Should Wait Until Next Release To Land label Dec 16, 2022
Copy link
Contributor

@wpaulino wpaulino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, let's remove "WIP" from the commit message. Also needs yet another rebase.

wpaulino
wpaulino previously approved these changes Dec 16, 2022
fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()>;
/// Get a script pubkey which we send funds to when claiming on-chain contestable outputs.
fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()> {
let mut node_secret = self.get_node_secret(recipient)?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should add a default implementation here - (a) we want to remove get_node_secret, not rely on it more, (b) it makes this single commit less move-only, which I'd really prefer to keep it as move-only as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I see your point. When writing this PR, the idea was to just keep the same functions, but move them around, and for that situation, a reimplementation of the same code seemed redundant. I can add back the non-default implementations, or just leave it for @wpaulino's follow-up PR that's removing node_secret. Same with ecdh and sign_invoice.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not moving then is less diff :)

/// on-chain funds across channels as controlled to the same user.
fn get_shutdown_scriptpubkey(&self) -> ShutdownScript;
/// Errors if the [`Recipient`] variant is not supported by the implementation.
fn sign_invoice<C: Signing>(&self, hrp_bytes: &[u8], invoice_data: &[u5], recipient: Recipient, secp_context: &Secp256k1<C>) -> Result<RecoverableSignature, ()> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

@@ -954,7 +984,6 @@ impl ReadableArgs<SecretKey> for InMemorySigner {
pub struct KeysManager {
secp_ctx: Secp256k1<secp256k1::All>,
node_secret: SecretKey,
node_id: PublicKey,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you removing the caching here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it was throwing a notice saying it wasn't used.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, when you drop the default methods you'll want to keep the caching here. Even more reason to not do the default methods :)

@TheBlueMatt
Copy link
Collaborator

Once we land this, we'll definitely want to land the followup(s) required to at least split the traits into different objects in the same release. It'd be nice to get the followup PRs open sooner rather than later, though we can land this without.

@arik-so
Copy link
Contributor Author

arik-so commented Dec 19, 2022

Soo… once I undo the part of the PR where I remove the overrides, is this PR otherwise ready?

@TheBlueMatt
Copy link
Collaborator

I'm happy with it, yes. As long as we move quickly to splitting the interfaces up fully.

@TheBlueMatt
Copy link
Collaborator

Please dont change something in one commit and then revert it in the next.

@arik-so
Copy link
Contributor Author

arik-so commented Dec 19, 2022

Huh, what do you mean? Isn't the idea to squash all of these commits into one at the end?

@TheBlueMatt
Copy link
Collaborator

No - we dont squash + merge, we've always used merge commits.

@arik-so
Copy link
Contributor Author

arik-so commented Dec 19, 2022

Right, but before we do that, I was planning to squash these commits myself.

@arik-so arik-so force-pushed the 2022-12-keys-interface-name-split branch from 953127a to 7d8b0aa Compare December 19, 2022 21:37
@TheBlueMatt
Copy link
Collaborator

Please go ahead and squash so we can ACK it :)

@arik-so
Copy link
Contributor Author

arik-so commented Dec 19, 2022

I will once the tests complete so it's easier to compare and go back. Will do once they're all green.

@arik-so
Copy link
Contributor Author

arik-so commented Dec 19, 2022

Ok, enough tests have passed to to squash it now, I think

@@ -17,7 +17,7 @@ use lightning::ln::inbound_payment::{create, create_from_hash, ExpandedKey};
use lightning::routing::gossip::RoutingFees;
use lightning::routing::router::{InFlightHtlcs, Route, RouteHint, RouteHintHop};
use lightning::util::logger::Logger;
use secp256k1::PublicKey;
use secp256k1::{PublicKey};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep diffs minimal.

@@ -54,7 +54,7 @@ use core::time::Duration;
pub fn create_phantom_invoice<K: Deref, L: Deref>(
amt_msat: Option<u64>, payment_hash: Option<PaymentHash>, description: String,
invoice_expiry_delta_secs: u32, phantom_route_hints: Vec<PhantomRouteHints>, keys_manager: K,
logger: L, network: Currency,
logger: L, network: Currency
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here (and on many lines below)

T::Target: BroadcasterInterface,
K::Target: KeysInterface,
F::Target: FeeEstimator,
L::Target: Logger,
L::Target: Logger
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incl here and below in tests.

T::Target: BroadcasterInterface,
K::Target: KeysInterface,
K::Target: KeysInterface + NodeSigner,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not (anymore).

@TheBlueMatt
Copy link
Collaborator

In the future, this kind of PR would probably be a chunk easier to review if it were separate commits - adding separate commits for the new traits would give a reviewer fewer things to look at in more digestible chunks.

@arik-so arik-so force-pushed the 2022-12-keys-interface-name-split branch from aa24b99 to 9d7bb73 Compare December 20, 2022 18:09
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Next time please be more careful with the patch.

/// By parameterizing by the raw invoice bytes instead of the hash, we allow implementors of
/// this trait to parse the invoice and make sure they're signing what they expect, rather than
/// blindly signing the hash.
/// The hrp is ascii bytes, while the invoice data is base32.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you decapitalize ASCII (and remove ticks on hrp, which maybe should read hrp_bytes instead)?


#[cfg(feature = "std")]
use std::time::{SystemTime, UNIX_EPOCH};
use bitcoin::secp256k1::ecdh::SharedSecret;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this get moved away from the other secp entries?

@TheBlueMatt TheBlueMatt merged commit f7211fb into lightningdevkit:main Dec 20, 2022
@valentinewallace
Copy link
Contributor

FYI if there's gonna be a follow-up, it looks like some unused warnings were introduced were introduced in cargo test

@arik-so
Copy link
Contributor Author

arik-so commented Dec 20, 2022

I'm pretty sure some of them are false positives that depend on the configuration flag, because removing the unuseds causes things to break. I will try to narrow down the config flags for those imports in the follow-up though.

And yes, there will be at least two follow-ups to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants