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

Peer Storage Feature – Part 2 #3623

Open
wants to merge 23 commits into
base: main
Choose a base branch
from

Conversation

adi2011
Copy link

@adi2011 adi2011 commented Feb 26, 2025

This is the second PR in the peer storage feature series.

Key Changes

  • Enable ChainMonitor to send peer storage to all channel partners whenever a new block is mined.
  • Add get_peer_storage_key() to NodeSigner.
  • Implement decryption logic for peer storage in handle_peer_storage_retrieval().

In the next one, I will add serialisation logic for ChannelMonitors inside peer storage.

@adi2011 adi2011 force-pushed the peer-storage/encrypt-decrypt branch 3 times, most recently from d8df7cf to 361738d Compare February 27, 2025 03:31
@adi2011 adi2011 marked this pull request as ready for review February 27, 2025 07:46
@tnull
Copy link
Contributor

tnull commented Feb 27, 2025

Seems this isn't properly rebased, hence CI is failing?

@adi2011 adi2011 force-pushed the peer-storage/encrypt-decrypt branch from 361738d to a1006e0 Compare February 27, 2025 11:25
@adi2011
Copy link
Author

adi2011 commented Feb 27, 2025

Seems this isn't properly rebased, hence CI is failing?

I think #3626 will fix this.

@tnull
Copy link
Contributor

tnull commented Feb 27, 2025

Seems this isn't properly rebased, hence CI is failing?

I think #3626 will fix this.

No, it fails with:

src/ln/our_peer_storage.rs - ln::our_peer_storage::OurPeerStorage (line 48) stdout ----
error[E0433]: failed to resolve: use of undeclared type `OurPeerStorage`
 --> src/ln/our_peer_storage.rs:49:28
  |
3 | let mut our_peer_storage = OurPeerStorage::new();
  |                            ^^^^^^^^^^^^^^ not found in this scope
  |
help: consider importing this struct
  |
2 | use lightning::ln::our_peer_storage::OurPeerStorage;
  |

error[E0433]: failed to resolve: use of undeclared type `OurPeerStorage`
 --> src/ln/our_peer_storage.rs:54:1
  |
8 | OurPeerStorage::decrypt_our_peer_storage(&mut decrypted, &encrypted).unwrap();
  | ^^^^^^^^^^^^^^ not found in this scope
  |
help: consider importing this struct
  |
2 | use lightning::ln::our_peer_storage::OurPeerStorage;
  |

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0433`.
Couldn't compile the test.

failures:
    src/ln/our_peer_storage.rs - ln::our_peer_storage::OurPeerStorage (line 48)

test result: FAILED. 28 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.00s

error: test failed, to rerun pass '--doc'

@adi2011
Copy link
Author

adi2011 commented Feb 27, 2025

That is because it’s trying to compile the commented code in the documentation, I will fix it in a bit.

@adi2011 adi2011 force-pushed the peer-storage/encrypt-decrypt branch 2 times, most recently from ff7fec7 to 465da4a Compare February 27, 2025 12:09
@jkczyz jkczyz added the weekly goal Someone wants to land this this week label Feb 27, 2025
@adi2011 adi2011 force-pushed the peer-storage/encrypt-decrypt branch 2 times, most recently from 4f29813 to 2113034 Compare February 28, 2025 04:51
Copy link
Contributor

@tnull tnull left a comment

Choose a reason for hiding this comment

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

Unfortunately CI is still failing as the code doesn't work in no_std.

use crate::ln::msgs::DecodeError;

/// [`OurPeerStorage`] is used to store channel information that allows for the creation of a
/// PeerStorage backup. It includes versioning and timestamping for comparison between
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: IIRC, we settled on snake_case here?

Suggested change
/// PeerStorage backup. It includes versioning and timestamping for comparison between
/// `peer_storage` backup. It includes versioning and timestamping for comparison between

Copy link
Author

Choose a reason for hiding this comment

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

Sorry, my bad. Fixed!

impl OurPeerStorage {
/// Returns a [`OurPeerStorage`] with version 1 and current timestamp.
pub fn new() -> Self {
let duration_since_epoch = std::time::SystemTime::now()
Copy link
Contributor

Choose a reason for hiding this comment

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

As LDK also supports no_std, we need to make this code work in no_std environments. As accessing time is only available in std, it means we either need to find a way to have the user provide the timestamp themselves, or feature-gate the peer storage to only work on std.

That said, are we positive that we need a timestamp in the first place?

Copy link
Author

Choose a reason for hiding this comment

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

No, I have added a timestamp so that if we receive multiple peer storage instances, we can select the latest one. I was thinking of replacing the timestamp with block height...

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure why we need to select the latest one specifically? Can't we just decode all of them and see if any have new data for our ChannelMonitors?

@adi2011 adi2011 requested a review from tnull March 1, 2025 07:08
@adi2011
Copy link
Author

adi2011 commented Mar 1, 2025

Thanks for the review @tnull.

Fixed the CI :)

Copy link

codecov bot commented Mar 1, 2025

Codecov Report

Attention: Patch coverage is 83.42246% with 31 lines in your changes missing coverage. Please review.

Project coverage is 89.90%. Comparing base (4c43a5b) to head (4adeeee).
Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
lightning/src/ln/channelmanager.rs 81.25% 11 Missing and 1 partial ⚠️
lightning/src/chain/chainmonitor.rs 77.77% 8 Missing ⚠️
lightning/src/ln/peer_handler.rs 60.00% 5 Missing and 1 partial ⚠️
lightning/src/ln/our_peer_storage.rs 95.83% 2 Missing ⚠️
lightning/src/util/test_utils.rs 66.66% 2 Missing ⚠️
lightning/src/ln/blinded_payment_tests.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3623      +/-   ##
==========================================
+ Coverage   89.24%   89.90%   +0.66%     
==========================================
  Files         155      156       +1     
  Lines      119280   124273    +4993     
  Branches   119280   124273    +4993     
==========================================
+ Hits       106448   111733    +5285     
+ Misses      10238     9982     -256     
+ Partials     2594     2558      -36     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines 861 to 870
/// This function derives an encryption key for peer storage by using the HKDF
/// (HMAC-based Key Derivation Function) with a specific label and the node
/// secret key. The derived key is used for encrypting or decrypting peer storage
/// data.
///
/// The process involves the following steps:
/// 1. Retrieves the node secret key.
/// 2. Uses the node secret key and the label `"Peer Storage Encryption Key"`
/// to perform HKDF extraction and expansion.
/// 3. Returns the first part of the derived key, which is a 32-byte array.
Copy link
Collaborator

Choose a reason for hiding this comment

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

No, this is a trait method, it doesn't, itself, do anything. Documentation on a trait method should describe what the method should do as well as additional context for when the method is called and possibly a possible implementation, but it what the method "does" do.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, makes sense. Fixed it.

@@ -2201,6 +2230,14 @@ impl NodeSigner for KeysManager {
self.inbound_payment_key.clone()
}

fn get_peer_storage_key(&self) -> [u8; 32] {
let (t1, _) = hkdf_extract_expand_twice(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Rather than HKDF'ing from the node secret, let's derive a new key from the next hardened idx off the seed in KeysManager::new?

Copy link
Author

Choose a reason for hiding this comment

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

Sure, I will update the PR to derive the key from the next hardened index. Could you share a bit more about the reasoning behind this approach?

Comment on lines 30 to 33
/// # Fields
/// - `version`: Defines the structure's version for backward compatibility.
/// - `timestamp`: UNIX timestamp indicating the creation or modification time of the instance.
/// - `ser_channels`: Serialized channel data.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems weird to document private things?

Copy link
Author

Choose a reason for hiding this comment

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

Yes. I initially implemented this with public fields for simplicity, but after further consideration, I refactored the code to use getter and setter methods instead.

impl OurPeerStorage {
/// Returns a [`OurPeerStorage`] with version 1 and current timestamp.
pub fn new() -> Self {
let duration_since_epoch = std::time::SystemTime::now()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure why we need to select the latest one specifically? Can't we just decode all of them and see if any have new data for our ChannelMonitors?

}
}

/// Stubs a channel inside [`OurPeerStorage`]
Copy link
Collaborator

Choose a reason for hiding this comment

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

I have no idea from the docs in this module what it means to "stub a channel" nor what this method does without looking at the code. Maybe just say that it "sets the serialized data to be included in the storage"?

Copy link
Author

Choose a reason for hiding this comment

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

Sorry for being less descriptive. Fixed it.


impl OurPeerStorage {
/// Returns a [`OurPeerStorage`] with version 1 and current timestamp.
pub fn new() -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This flow is fairly brittle. We currently have to create a dummy OurPeerStorage with new, then store the data we need with stub_channels after calling encrypt_our_peer_storage on the data. But at no point does any of this change the type. Instead, why not just have a method to create_from_data that takes the key and does the encryption, and a decrypt(&self) -> Vec<u8> data that returns the data decrypted?

Copy link
Author

Choose a reason for hiding this comment

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

Agreed. In the future PR we might need setter for ser_channels but not now. Thanks!

/// This trait extends [`MessageSendEventsProvider`], meaning it is capable of generating
/// message send events, which can be processed using
/// [`MessageSendEventsProvider::get_and_clear_pending_msg_events`].
pub trait SendingOnlyMessageHandler: MessageSendEventsProvider {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Its not clear to me why this needs a trait? MessageSendEventsProvider already lets us send messages, and send_peer_storage is only called internally in chainmonitor.rs so it doesn't seem like something we need to expose to the world (let along via a trait rather than letting ChainMonitor have the method directly)

Copy link
Author

Choose a reason for hiding this comment

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

Yes, that's what I initially thought as well. However, since we need to process events through PeerManager::process_events, I considered adding a new message handler to allow calling get_and_clear_pending_msg_events on ChainMonitor.

What could be an alternative structure that would still allow access to ChainMonitor::get_and_clear_pending_msg_events through PeerManager::process_events?

@@ -388,7 +392,7 @@ where C::Target: chain::Filter,
/// pre-filter blocks or only fetch blocks matching a compact filter. Otherwise, clients may
/// always need to fetch full blocks absent another means for determining which blocks contain
/// transactions relevant to the watched channels.
pub fn new(chain_source: Option<C>, broadcaster: T, logger: L, feeest: F, persister: P) -> Self {
pub fn new(chain_source: Option<C>, broadcaster: T, logger: L, feeest: F, persister: P, our_peerstorage_encryption_key: [u8; 32]) -> Self {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should explicitly document that this should be from the KeysManager's method to match what ChannelManager does.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for pointing this out. Fixed!

@@ -255,6 +257,8 @@ pub struct ChainMonitor<ChannelSigner: EcdsaChannelSigner, C: Deref, T: Deref, F
/// it to give to users (or [`MonitorEvent`]s for `ChannelManager` to process).
event_notifier: Notifier,
pending_send_only_events: Mutex<Vec<MessageSendEvent>>,
our_peer_storage: Mutex<OurPeerStorage>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure I understand the point of storing this in the ChainMonitor all the time. Rather, isn't it simpler to just build the OurPeerStorage that we need when send_peer_storage is called, encrypt it, and directly enqueue it as a message?

Copy link
Author

Choose a reason for hiding this comment

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

Agreed. Thanks for pointing out.

let mut res = vec![0; msg.data.len() - 16];
let our_peerstorage_encryption_key = self.node_signer.get_peer_storage_key();
let mut cyphertext_with_key = Vec::with_capacity(msg.data.len() + our_peerstorage_encryption_key.len());
cyphertext_with_key.extend(msg.data.clone());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please pass the key and ciphertext as separate arguments rather than concatenating them.

Copy link
Author

Choose a reason for hiding this comment

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

Implemented this change based on the feedback from #2943 (comment).

@adi2011 adi2011 requested a review from TheBlueMatt March 6, 2025 17:49
@tnull
Copy link
Contributor

tnull commented Mar 7, 2025

This unfortunately needs a rebase now.

Aditya Sharma and others added 2 commits March 8, 2025 02:56
Add get_peer_storage_key method to derive a 32-byte encryption key for securing Peer Storage.
This method utilizes HKDF with the node's secret key as input and a fixed info string to generate the encryption key.

 - Add 'get_peer_storage_key' to NodeSigner.
 - Implement 'get_peer_storage_key' for KeysManager & PhantomKeysManager.
Introduce the OurPeerStorage struct to manage serialized channel data for peer storage backups.
This struct facilitates the distribution of peer storage to channel partners and includes
versioning and timestamping for comparison between retrieved peer storage instances.

 - Add the OurPeerStorage struct with fields for version, timestamp, and serialized channel data (ser_channels).
 - Implement methods to encrypt and decrypt peer storage securely.
 - Add functionality to update channel data within OurPeerStorage.
@adi2011 adi2011 force-pushed the peer-storage/encrypt-decrypt branch from 62d2026 to 22fe4b2 Compare March 7, 2025 21:30
Aditya Sharma and others added 4 commits March 8, 2025 03:06
To enable ChainMonitor sending peer storage to channel partners whenever a new block is added,
We implement BaseMessageHandler for ChainMonitor.
This allows the `ChainMonitor` to handle the peer storage distribution.

Key changes:
 - Add BaseMessageHandler into the MessageHandler.
 - Implement BaseMessageHandler for ChainMonitor.
 - Process BaseMessageHandler events inside process_events().
Everytime a new block is added we send PeerStorage to all of our channel partner.

 - Add our_peer_storage and our_peerstorage_encryption_key to ChainMonitor
 - Write send_peer_storage() and send it to all channel partners whenever a new block is added
Ensure ChannelManager properly handles peer_storage_retrieval.

 - Write internal_peer_storage_retreival to verify if we recv correct peer storage.
 - Send error if we get invalid peer_storage data.
Ensure that we correctly handle the sendpeerstorage message event from chainmonitor
and process it through channelmonitor.

Key Changes:
- Retrieve sendpeerstorage message event from chainmonitor for both nodes.
- Handle peer storage messages exchanged between nodes and verify correct decryption.
@adi2011 adi2011 force-pushed the peer-storage/encrypt-decrypt branch from 22fe4b2 to 35863ce Compare March 7, 2025 21:41
@@ -616,12 +628,6 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
Arc::new(TestPersister { update_ret: Mutex::new(ChannelMonitorUpdateStatus::Completed) }),
));

let keys_manager = Arc::new(KeyProvider {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not quite sure why this code move is necessary?

Copy link
Author

@adi2011 adi2011 Mar 11, 2025

Choose a reason for hiding this comment

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

So that we can use keys_manager.get_peer_storage_key() inside ChainMonitor::new().

///
/// Implementations of this method must derive a secure encryption key using a
/// cryptographically strong key derivation function (e.g., HKDF or a hardened
/// child key derivation). The derived key is used to encrypt or decrypt peer
Copy link
Contributor

Choose a reason for hiding this comment

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

Could link BIP32 here.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, Thanks!

/// This method is invoked when encrypting or decrypting peer storage data.
/// It must return the same key every time it is called, ensuring consistency
/// for encryption and decryption operations.
fn get_peer_storage_key(&self) -> [u8; 32];
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does this return a [u8; 32] rather than simply a SecretKey?

Copy link
Author

@adi2011 adi2011 Mar 11, 2025

Choose a reason for hiding this comment

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

Agreed, fixing this...

/// and decryption to ensure data integrity and security during exchange or storage.
///
/// # Key Methods
/// - `create_from_data`: Returns an encrypted PeerStorage instance created from the provided data.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Tick/link PeerStorage

Copy link
Author

Choose a reason for hiding this comment

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

Fixed


impl OurPeerStorage {
/// Get `ser_channels` field from [`OurPeerStorage`]
pub fn get_ser_channels(&self) -> Vec<u8> {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: According to the Rust API guidlines, this should just be called ser_channels. Also, maybe it would be worth spelling/renaming out ser_channels as the name doesn't communicate super clearly what it holds.

Also, can we have this return a reference and leave it up to the callsite whether they want/need to clone or not?

let logger = WithContext::from(&self.logger, Some(counterparty_node_id), None, None);

log_debug!(logger, "Received unexpected peer_storage_retrieval from {}. This is unusual since we do not yet distribute peer storage. Sending a warning.", log_pubkey!(counterparty_node_id));
if msg.data.len() < 16 {
Copy link
Contributor

Choose a reason for hiding this comment

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

What are these 16 bytes exactly? Please introduce a clearly named constant for this.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, it's min_cyphertext_length because of the auth tag length. I will name it accordingly.

let mut res = vec![0; msg.data.len() - 16];
let our_peerstorage_encryption_key = self.node_signer.get_peer_storage_key();

match OurPeerStorage::decrypt_our_peer_storage(&mut res, &msg.data.clone(), our_peerstorage_encryption_key) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should be able to avoid this clone if we have decrypt_our_peer_storage take the argument by value.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, thanks for pointing this out.

), ChannelId([0; 32])));
}
}
let our_peer_storage = <OurPeerStorage as Readable>::read(&mut ::bitcoin::io::Cursor::new(res)).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

This make me wonder if it wouldn't be cleaner to introduce an EncryptedPeerStorage (or similar) helper type that we can transition to/from rather than doing all these conversions 'explictly'.

Copy link
Author

Choose a reason for hiding this comment

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

I should make the flow smoother. Modifying decrypt_our_peer_storage to directly return OurPeerStorage.

"Invalid peer_storage_retrieval message received.".into(),
), ChannelId([0; 32])))
if our_peer_storage.get_ser_channels().len() == 0 {
log_debug!(logger, "Received a peer storage from peer {} with 0 channels.", log_pubkey!(counterparty_node_id));
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we generally log (in TRACE?) when we successfully decrypted a backup, not only when it's length 0?

Copy link
Author

Choose a reason for hiding this comment

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

Currently we just distribute empty peer storages, in the next PR we are going to serialise channelmonitors and send them over.

@@ -1919,6 +1919,7 @@ fn test_trampoline_inbound_payment_decoding() {
fn sign_invoice(
&self, _invoice: &RawBolt11Invoice, _recipient: Recipient,
) -> Result<RecoverableSignature, ()> { unreachable!() }
fn get_peer_storage_key(&self) -> [u8;32] { unreachable!() }
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Formatting is off.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed.

@adi2011
Copy link
Author

adi2011 commented Mar 11, 2025

Thank you so much, @tnull and @TheBlueMatt, for taking the time to review this. I’ve done my best to address all the comments. Please let me know if there’s anything I might have missed or if further changes are needed.


if msg.data.len() < MIN_CYPHERTEXT_LEN {
log_debug!(logger, "Invalid YourPeerStorage received from {}", log_pubkey!(counterparty_node_id));
return Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Warn(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure we need to warn our peer if they send us bogus data.

Copy link
Author

@adi2011 adi2011 Mar 11, 2025

Choose a reason for hiding this comment

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

This won’t lead to a unilateral close and is also mentioned in the spec.

It's not compulsory, but it won’t make much of a difference, I guess?

The receiver of peer_storage_retrieval:

when it receives peer_storage_retrieval with an outdated or irrelevant data:
       MAY send a warning.

}
}

impl Writeable for OurPeerStorage {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We dont need to implement readable/writeable now since we use just a vec for the encrypted data, no?

Copy link
Author

Choose a reason for hiding this comment

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

Writeable is used internally inside create_from_data, and Readable is used inside decrypt_our_peer_storage. I agree we currently don’t need them very much, but in the next one, we are going to use them for serialisation and deserialisation. Wouldn’t it be better to have it in this one instead of implementing serialisation and deserialisation logic directly within those functions?

/// This method is invoked when encrypting or decrypting peer storage data.
/// It must return the same key every time it is called, ensuring consistency
/// for encryption and decryption operations.
fn get_peer_storage_key(&self) -> SecretKey;
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 this needs to be a SecretKey? SecretKey implies secp256k1 operations. We really want a [u8; 32], I think.

Copy link
Author

Choose a reason for hiding this comment

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

Done!

Comment on lines 844 to 845
/// - The derived key must be exactly **32 bytes** and suitable for symmetric
/// encryption algorithms.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is given by the return type, we don't have to specify it.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, I wrote it just as a note to implementations. But, yeah, the return type specifies it. Removing it.

///
/// # Returns
///
/// A [`SecretKey`] representing the encryption key for peer storage.
Copy link
Collaborator

Choose a reason for hiding this comment

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

What does this communicate that the function signature does not?

///
/// # Implementation Details
///
/// - The key must be derived from a node-specific secret to ensure uniqueness.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure what a "node-specific secret" means. Honestly, I'm not sure any of the sections below the first paragraph are needed.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, on second thought, I agree it’s unnecessary.

@adi2011 adi2011 requested review from TheBlueMatt and tnull March 12, 2025 04:22
@adi2011 adi2011 force-pushed the peer-storage/encrypt-decrypt branch from 10d7a4d to 4adeeee Compare March 12, 2025 04:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
weekly goal Someone wants to land this this week
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants