Skip to content

Initial implementation of LDK Node#11

Merged
tnull merged 1 commit intolightningdevkit:mainfrom
tnull:2022-09-initial-setup-and-api
Mar 16, 2023
Merged

Initial implementation of LDK Node#11
tnull merged 1 commit intolightningdevkit:mainfrom
tnull:2022-09-initial-setup-and-api

Conversation

@tnull
Copy link
Collaborator

@tnull tnull commented Sep 1, 2022

Based on #8, #9, #10, #33.

This PR wraps the previously mentioned PRs and provides initial implementations of Node, Builder, as well as basic API methods.

@tnull tnull force-pushed the 2022-09-initial-setup-and-api branch 6 times, most recently from fe1e326 to 55966e7 Compare September 6, 2022 10:27
@tnull tnull force-pushed the 2022-09-initial-setup-and-api branch 7 times, most recently from fdabd21 to c0425dd Compare September 8, 2022 12:30
@tnull tnull force-pushed the 2022-09-initial-setup-and-api branch 6 times, most recently from 4c62cd8 to 9f7085d Compare September 14, 2022 16:52
@tnull tnull force-pushed the 2022-09-initial-setup-and-api branch from 9f7085d to 37bf53b Compare September 19, 2022 16:52
@tnull
Copy link
Collaborator Author

tnull commented Sep 19, 2022

Rebased on #9/#10.

@tnull tnull force-pushed the 2022-09-initial-setup-and-api branch from 37bf53b to 8d8955d Compare September 22, 2022 13:53
@tnull tnull force-pushed the 2022-09-initial-setup-and-api branch 4 times, most recently from f52524e to 54a25b7 Compare September 30, 2022 08:25
@tnull tnull force-pushed the 2022-09-initial-setup-and-api branch 6 times, most recently from a68fa60 to 20f8f47 Compare December 15, 2022 11:32
@tnull
Copy link
Collaborator Author

tnull commented Dec 15, 2022

Rebased after now using a custom KeysInterface.

@tnull tnull force-pushed the 2022-09-initial-setup-and-api branch 6 times, most recently from 3d770e0 to 36e59e4 Compare December 19, 2022 10:57
@tnull tnull changed the title Initial implementation of LdkLite Initial implementation of LDK Node Jan 4, 2023
@tnull
Copy link
Collaborator Author

tnull commented Jan 27, 2023

Squashed fixup commits and rebased on main after merge of #33.

Copy link
Contributor

@jkczyz jkczyz left a comment

Choose a reason for hiding this comment

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

Only partway through.

@tnull tnull mentioned this pull request Mar 13, 2023
47 tasks
Copy link
Contributor

@jkczyz jkczyz left a comment

Choose a reason for hiding this comment

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

Feel fee to squash fixups.

let ldk_data_dir = format!("{}/ldk", config.storage_dir_path);
let network_graph_path = format!("{}/network_graph", ldk_data_dir);

if let Ok(file) = fs::File::open(network_graph_path) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What if we don't yet have a NetworkGraph?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not sure I'm understanding the question? In case we don't have a persisted network graph at the given location, the results won't be Ok and hence we'll return an empty one via NetworkGraph::new below?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I missed that. Why do we need to use a Result then?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good point, removed the Result, will likely need to touch this anyways again when integrating RGS though.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this logic robust enough? For instance, if we get PermissionDenied, we'll create a new NetworkGraph and then presumably fail to write it later.

Copy link
Collaborator Author

@tnull tnull Mar 15, 2023

Choose a reason for hiding this comment

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

Yes, was thinking about this, too, but I'll have to rework all this anyways in the upcoming switch to SQLite and trait-based persistence remodel.

Currently all of this follows the assumption is just lying around somewhere on disk where we have access to it and we can read out-of-bounds it before we feed it into LDK. After the remodel all of these operations need to go through a trait-based interface that probably will extend KVStorePersister (already implementing a KVStoreUnpersister in #13), a KVStoreAccess trait or similar is still missing.

Also, even asserting that we can open the file in write mode at this point doesn't ensure we won't fail persistence to it in the future, e.g., because permissions changed.

Ok(())
}

/// Disconnects all peers, stops all running background tasks, and shuts down [`Node`].
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps specify if operations are no longer valid once called, to reflect the start docs.

Copy link
Collaborator Author

@tnull tnull Mar 14, 2023

Choose a reason for hiding this comment

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

Now included a corresponding note in the docs.

I'm however a bit split on the API design here for the exposed methods that don't require the runtime loaded. Previously all methods returned Error::NotRunning when no runtime was loaded which gave a clear API-level distinction between started and stopped states. Currently I however opted to not do this for any methods that don't require the runtime, e.g., node_id() or new_funding_address() would work, whether the Node is started or not.

On the one hand I think being able to access some of Node's methods in a stopped state could come in handy (e.g., if users want to keep many nodes in a Vec and could therefore query which node is which without the need to start them), on the other drawing a clear line could be beneficial too in order to avoid confusion, and it would allow us to change to some runtime-dependant behavior under the hood without breaking API going forward.

Copy link
Contributor

@jkczyz jkczyz left a comment

Choose a reason for hiding this comment

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

Feel free to punt on anything that requires a large change.

Comment on lines +414 to +472
running,
config,
wallet,
tx_sync,
event_queue,
channel_manager,
chain_monitor,
peer_manager,
keys_manager,
network_graph,
gossip_sync,
persister,
logger,
scorer,
inbound_payments,
outbound_payments,
peer_store,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider packing these on a few lines if rustfmt supports that. Probably worth doing in a follow-up later if it will result in a lot of churn.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, rustfmt doesn't allow manually changing this. I can experiment and see if any config knob allows to change this, but I doubt it, as this is one of the behaviors why Matt is NACK on introducing rustfmt it in LDK?

Comment on lines +661 to +711
let _background_processor = BackgroundProcessor::start(
Arc::clone(&self.persister),
Arc::clone(&event_handler),
Arc::clone(&self.chain_monitor),
Arc::clone(&self.channel_manager),
BPGossipSync::p2p(Arc::clone(&self.gossip_sync)),
Arc::clone(&self.peer_manager),
Arc::clone(&self.logger),
Some(Arc::clone(&self.scorer)),
);
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 use the async interface now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We can't unfortunately due to lightningdevkit/rust-lightning#2003. Will hopefully include a fix in 0.0.115.

pub(crate) fn add_peer(&self, peer_info: PeerInfo) -> Result<(), Error> {
let mut locked_peers = self.peers.write().unwrap();

locked_peers.insert(peer_info.pubkey, peer_info);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it intended to override an existing peer if present?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, we may want to do that a bit more fine-grained if we'd ever add additional data, but currently we just override the whole struct to allow for address changes.

Comment on lines +136 to +153
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), lightning::io::Error> {
self.pubkey.write(writer)?;

match self.address.ip() {
IpAddr::V4(v4addr) => {
0u8.write(writer)?;
u32::from(v4addr).write(writer)?;
}
IpAddr::V6(v6addr) => {
1u8.write(writer)?;
u128::from(v6addr).write(writer)?;
}
}

self.address.port().write(writer)?;

Ok(())
}
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 use TLV encoding in case we add more fields?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Generally yes, currently holding off since I still hope to simply be able to reuse NetAddress here (cf. lightningdevkit/rust-lightning#2056). If said issue doesn't land I'll probably just newtype it and impl the FromStr here.

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.

4 participants