-
Notifications
You must be signed in to change notification settings - Fork 403
Creating fresh destination scripts for every channel in KeysManager #1312
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
Conversation
5421128
to
d478137
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great!....except misses backwards compat in a few places.
d478137
to
7747490
Compare
Codecov ReportBase: 90.70% // Head: 90.70% // No change to project coverage 👍
Additional details and impacted files@@ Coverage Diff @@
## main #1312 +/- ##
=======================================
Coverage 90.70% 90.70%
=======================================
Files 91 91
Lines 48392 48392
Branches 48392 48392
=======================================
Hits 43893 43893
Misses 4499 4499 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. |
00d4141
to
7b49a35
Compare
@TheBlueMatt do you know why the payment script we create from the pubkey in spendable outputs is not matching the output script? 🤔 |
Just using a derivation_idx of 3 in the spender doesn't solve it, you have to actually derive using the same pattern in both places. |
@TheBlueMatt Does this mean that instead of driving private keys using the derivation_idx, I'm just creating a fresh witness script directly? Right now we derive the private key -> pubkey -> Witness, Payment script. |
The new derivation you've added here isn't simply a derivation index of 3, which is what you've left in the spending side, both the spending side (the |
@TheBlueMatt So I guess the derivation_idx should be the first 8 bytes of the |
Addon question: There is secp engine which is passed to the spenable_outputs method and there is one available as part of the KeysManager. The newly derived destination script are using the KeysManager secp engine. Does that make a difference? Should I be passing the secp engine onto the KeysInterface method as a parameter? |
Yep, exactly, the two things just have to match exactly. Now that I look closer, actually, however, I think we should do a two-level derivation for the
Nope, the secp engine doesn't matter at all. |
@TheBlueMatt If we are deriving two different destination scripts for |
e86fb20
to
6463ef3
Compare
Hmm, I'm not sure I understand your question. My understanding of the goal here is to (a) on the creation side, we have a configuration boolean that determines whether we do "old-style" derivation, or "new-style" and (b) on the spending side, we always try new-style (if we have the |
6463ef3
to
c557fd5
Compare
@TheBlueMatt I changed the creation side to create the new style destination script if the flag is set or set the idx to 3. For the tests that are failing, i noticed that both side use the channel_keys_id (spending / creation). Any idea why it's not matching? (the payment script and output script in spendable_outputs) |
Double check exactly what's derived where -
|
8b7dbc5
to
215f4f2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work getting it all passing! I should have been a bit more clear in my previous feedback, I apologize for that, one suggested change in derivation and I think we're there.
lightning/src/chain/keysinterface.rs
Outdated
SpendableOutputDescriptor::StaticOutput { ref output, .. } => { | ||
SpendableOutputDescriptor::StaticOutput { ref output, channel_keys_id,.. } => { | ||
|
||
let destination_script = channel_keys_id.map_or_else(|| self.destination_script.clone(),|s| self.get_destination_script(s)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this is unused for the !channel_keys_id.is_some()
, maybe just map
and leave it as None
, then in the if below do if Some(&output.script_pubkey) == destination_script.as_ref()
lightning/src/chain/keysinterface.rs
Outdated
}; | ||
match ExtendedPrivKey::new_master(Network::Testnet, &self.seed) { | ||
Ok(master_key) => { | ||
match master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(derivation_idx as u32).expect("key space exhausted")){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I actually liked the two-level derivation - it seems like kinda strange to have two different sets of derivations against the master key - one with a few fixed indexes and one with a random number. I'd strongly prefer to just create a new fixed index (I think 4 is free?) and do the new-style derivations off of that. Obvious the old style derivations will need to stay where they are (fixed at 3 directly off the master).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so basically derive from the channel_master_key at either 3 or 4 (4 for new style), and then derive the byte slice from the channel_keys_id if it's new style?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep! That sounds great to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TheBlueMatt I'm assuming that we'll have to use and derive the channel master key on the spending side as well? I tried out the changes and have some tests failing 😞
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I basically have the assertion for the shutdown pubkey failing (2 tests).
215f4f2
to
8f4bf67
Compare
lightning/src/chain/keysinterface.rs
Outdated
} else { | ||
2 | ||
}; | ||
|
||
let master_derivation_idx = if self.new_style_derivation{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't be looking at new_style_derivation
at all in this method, I think - we can totally have something that had the keys picked in the current version of LDK, but which needs to be spent in a new version with this code. In that case, we have to decide which derivation to use purely based on the output.script_pub_key
field, not the setting here.
Sorry about the response delay here. |
8f4bf67
to
524359e
Compare
Let me know when you want another round of review or if you're stuck getting CI to pass again after trying a few times. |
@TheBlueMatt I was afk for a couple of weeks so couldn't do this then (sorry about that). |
lightning/src/chain/keysinterface.rs
Outdated
let secret = { | ||
// Note that when we aren't serializing the key, network doesn't matter | ||
match ExtendedPrivKey::new_master(Network::Testnet, &self.seed) { | ||
match self.channel_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(master_derivation_idx).expect("key space exhausted")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you're always deriving a child key here? We should derive a child key if we're doing a new-style derivation, but if we're not we should just use the channel_master_key derivation and use that key directly.
lightning/src/chain/keysinterface.rs
Outdated
let master_derivation_idx = if output.script_pubkey == self.destination_script{ | ||
3 | ||
} else { | ||
4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe simplify all of this by moving the key derivation into the if's and do it all in one go - ie just use the single above if statement, and do the secret derivation in that if and store the key, instead of figuring out the indexes and then setting a variable based on it.
Looks like this needs a rebase to address conflicts with upstream. |
cac19ff
to
67ee51a
Compare
Let me know when you want another round of review! |
Needs rebase again, sadly. Do you intend to push this forward? |
@TheBlueMatt Hey, been caught up with work. I'll try to work on this and wrap this up soon. Sorry about the massive delay 😓 |
67ee51a
to
75e7377
Compare
lightning/src/chain/keysinterface.rs
Outdated
@@ -439,7 +444,7 @@ pub trait KeysInterface { | |||
/// | |||
/// 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; | |||
fn get_destination_script(&self, channel_keys_id : [u8; 32]) -> Script; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're passing a channel_keys_id
that's pretty clear indication the method belongs in Sign
instead :)
75e7377
to
153b048
Compare
@vss96 Did you close this on purpose, or are you still working on this? |
@tnull Working on it, I discarded the commit and started fresh cause the code diverged. |
Great to hear, thank you! |
This fixes #1139