-
Notifications
You must be signed in to change notification settings - Fork 411
Add KeysInterface trait to handle keys management, first part: when C… #214
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
Early work, just to agree on the general KeysInterface thing. I don't follow the event model we talked previously on irc as it doesn't fit well with ChannelMonitor, I've more thought to something like ChainWatchInterface. (note I commented an assert in test_utils, because of hanging of ChannelMonintor serialization, which could be changed with ongoing #61, before I'm done here ) |
src/ln/channelmonitor.rs
Outdated
writer.write_all(&[0;32])?; | ||
|
||
} | ||
|
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.
you don't want to persist secret? also, seems it's better to re-sign local_commitment_tx can when it's loaded onto the memory and strip off signature when it's stored into hard disk.
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 I get derivation scheme right you can't do nothing with a per_commitment_point, you still need basepoint and basepoint_secret? ChannelMonitor handling current per_commitment_point is to avoid KeysManager or whatsever having to remember the per_commitment_point for each new commitment, without knowing if it's gonna be useful.
Hard disk storage thing is under revision, so here it's temporary.
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.
Definitely do want to persist, but you should only do it in case of for_local_storage.
Thanks for the quick work on this one! The nice thing about Events is that they are inherintly asynchronous and we don't have to worry about lock inversions between rust-lightning bits and client bits. Making a callback for something that is asynchronous just feels like asking for more complexity than we need there. What about just making SimpleManyChannelMonitor an EventsProvider? |
83d8947
to
96567d8
Compare
Rebased, with EventsProvider model, with two Interfaces: ln --> wallet and wallet --> ln, still WIP. |
96567d8
to
4c53b79
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.
High-level interface looks good!
src/ln/channelmonitor.rs
Outdated
|
||
if let Some(ref per_commitment_point) = *per_commitment_point { | ||
spendable_outputs.push((Some(per_commitment_point.clone()), redeemscript, BitcoinOutPoint { txid: htlc_success_tx.txid(), vout: 0 })); |
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.
The script here is a bit confused - sometimes its the redeemscript sometimes its the script itself. Also, a script isn't really the best way to tell a user how to spend an output - I think an enum (that might contain data, eg a redeemscript) may be more useful.
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 something like output script descriptor seems to be the right solution ? But it's still not into rust-bitcoin..
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.
Indeed, though I dont think the descriptor stuff is always sufficiently expressive for custom scripts. A simple enum with clear docs that explain what you have to put in the witness stack for the spend to succeed should be sufficient.
src/ln/channelmonitor.rs
Outdated
@@ -226,6 +246,9 @@ pub struct ChannelMonitor { | |||
prev_local_signed_commitment_tx: Option<LocalSignedTx>, | |||
current_local_signed_commitment_tx: Option<LocalSignedTx>, | |||
|
|||
prev_latest_per_commitment_point: Option<SecretKey>, |
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 dont think we actually need these right now? They are only used for the local htlc tx case, but I think we actually want the delayed_payment_key there, which we derive.
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.
The user wallet has to have access to local_delay key. We can derive this one from delayed_payment_basepoint and local per_commitment_point, but actually ChannelMonitor doesn't have any of them ? So I think we need them and also add delayed_payment_basepoint in KeyStorage ? If so it's nice for the user wallet because it hasn't to be aware of LN derivation scheme, it just gets the right key
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.
Do we need more than the local_delayedkey anywhere? Maybe only store that?
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.
Nop right only need local_delayedkey for dynamic outputs, we store it only in PrivMode ? How a user will be able to spend if watchtower's channel monitor only send him back local_delayedpubkey ?
Hmm still working on it, should we provide destination_script as a P2WPKH with a key derive from seed or let the user provide us destination_script (multisig, ...) ? Seems 2nd is better. For shutdown_scriptpubkey, following BOLT 2, there is 4 forms, we pick one by default for user ? |
I think ideally for shutdown_scriptpubkey and destination_script we'd derive something from a user-provided secret (eg just do an HD derivation from a user-provided HD master key). If we double-derive on accident and reuse them we'll just have slightly less privacy but that's OK cause we already exposed a persistent identifier via our node_id. |
a1ea971
to
7b4d1f2
Compare
Okay rebased with addition of CustomOutputScriptDescriptor. Still lack some integrations of KeysManager in other places and maybe tests to be finished. Still open : #214 (comment) ? which conditions writer/reader of per_commitment_point and some TODO in ChannelMonitor |
src/ln/channelmonitor.rs
Outdated
@@ -490,6 +519,13 @@ impl ChannelMonitor { | |||
self.payment_preimages.insert(payment_hash.clone(), payment_preimage.clone()); | |||
} | |||
|
|||
/// Provides latest local per_commitment_point secret. Useful to derive private key for protocol exit points based | |||
/// on local commitment tx. | |||
pub(super) fn provide_latest_per_commitment_point(&mut self, per_commitment_point: SecretKey) { |
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 currently never called, but I think you should be able to add the info to provide_latest_local_commitment_tx_info and move the fields into LocalTx, no?
src/ln/channelmonitor.rs
Outdated
writer.write_all(&[0;32])?; | ||
|
||
} | ||
|
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.
Definitely do want to persist, but you should only do it in case of for_local_storage.
src/ln/keysinterface.rs
Outdated
pub enum CustomOutputScriptDescriptor { | ||
/// Outpoint commits to a P2PWKH, should be spend by the following witness : | ||
/// <signature> <pubkey> OP_CHECKSIG | ||
StaticOutput { |
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.
Shouldn't this include the publickey so that the user knows which pubkey to use?
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.
Yes updated with "With pubkey being bip32 /1' from HMAC-Sha512 of user-provided seed as master private key" ?
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.
Well KeysInterface is just an interface so would have to specify it as "get_destination_script() return value", but I was thinking more because a user might find it easier to see the pubkey here as it would allow them to claim the output without having to go look up the output on-chain - they could just create a transaction from only the data in the event.
src/ln/channelmonitor.rs
Outdated
@@ -1446,6 +1518,9 @@ impl<R: ::std::io::Read> Readable<R> for ChannelMonitor { | |||
_ => return Err(DecodeError::InvalidValue), | |||
}; | |||
|
|||
let prev_latest_per_commitment_point = Some(unwrap_obj!(SecretKey::from_slice(&secp_ctx, read_bytes!(32)))); |
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.
Can't unwrap_obj! if it was optional at write-time.
src/util/test_utils.rs
Outdated
@@ -55,7 +55,7 @@ impl channelmonitor::ManyChannelMonitor for TestChannelMonitor { | |||
// to a watchtower and disk... | |||
let mut w = VecWriter(Vec::new()); | |||
monitor.write_for_disk(&mut w).unwrap(); | |||
assert!(channelmonitor::ChannelMonitor::read(&mut ::std::io::Cursor::new(&w.0)).unwrap() == monitor); | |||
//assert!(channelmonitor::ChannelMonitor::read(&mut ::std::io::Cursor::new(&w.0)).unwrap() == monitor); |
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 dont think you need this anymore with the current code (at least if you remove the unwrap_obj that I flagged)?
177956e
to
8e7ec6d
Compare
… ChannelMonitor detects a spendable outputs onchain it will send back an Event to user wallet with needed data to be at disposal Add CustomOutputScriptDescriptor to ease user wallet spending of onchain lightning outputs Extend KeyStorage with delayed_payment_base_key and per_commitment_point to derive local_delayed private key
8e7ec6d
to
981a9ed
Compare
componenents, responsible to get seed from the former and derive appropriate keyring materials Move ChannelKeys into keysinterface for generate a set of it from master_seed
981a9ed
to
3a8c01a
Compare
Drop channel_close_key from ChannelKeys
ChannelManager/Channel Drop channel_monitor_claim_key from ChannelKeys
let router = Arc::new(Router::new(PublicKey::from_secret_key(&secp_ctx, &our_network_key), watch.clone(), Arc::clone(&logger))); | ||
let mut seed = [0; 32]; | ||
let mut rng = thread_rng(); | ||
rng.fill_bytes(&mut seed); |
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.
fuzz targets must be fully deterministic - if you need to read bytes, read them from the input buffer, though ideally you'd keep consistency with the existing input data.
Will take as #225. |
…hannelMonitor
detects a spendable outputs onchain it will notify back the user wallet
with needed data to spend it with register_spendable_outputs