From 142bb1cee1ac991eec80a4dbf005ea60f0985e8c Mon Sep 17 00:00:00 2001 From: Randall Naar Date: Fri, 12 Apr 2024 10:17:40 -0400 Subject: [PATCH] Simplified the getting-started example. --- examples/rust/getting-started/Cargo.toml | 4 +- .../rust/getting-started/src/extensions.rs | 59 +++++++ examples/rust/getting-started/src/main.rs | 152 ++++++++---------- 3 files changed, 129 insertions(+), 86 deletions(-) create mode 100644 examples/rust/getting-started/src/extensions.rs diff --git a/examples/rust/getting-started/Cargo.toml b/examples/rust/getting-started/Cargo.toml index dfcbfa63d..fd0b4f6d3 100644 --- a/examples/rust/getting-started/Cargo.toml +++ b/examples/rust/getting-started/Cargo.toml @@ -10,4 +10,6 @@ gl-client = {path = "../../../libs/gl-client"} rand = "*" bip39 = { version = "*", features=["rand_core"] } tokio = {version="1.29.1", features=["rt", "macros"]} -hex = "0.4.3" \ No newline at end of file +hex = "0.4.3" +runeauth = "0.1" +anyhow.workspace = true diff --git a/examples/rust/getting-started/src/extensions.rs b/examples/rust/getting-started/src/extensions.rs new file mode 100644 index 000000000..39bdcdb82 --- /dev/null +++ b/examples/rust/getting-started/src/extensions.rs @@ -0,0 +1,59 @@ +use anyhow::{anyhow, Result}; +use gl_client::{ + credentials::{Device, Nobody}, + signer::Signer, +}; + +pub trait CredentialExt { + fn with_identity(device_cert: V, device_key: V) -> Self + where + V: Into>; +} + +impl CredentialExt for Nobody { + fn with_identity(device_cert: V, device_key: V) -> Self + where + V: Into>, + { + let mut creds = Nobody::default(); + creds.cert = device_cert.into(); + creds.key = device_key.into(); + creds + } +} + +impl CredentialExt for Device { + fn with_identity(device_cert: V, device_key: V) -> Self + where + V: Into>, + { + let mut creds = Device::default(); + creds.cert = device_cert.into(); + creds.key = device_key.into(); + creds + } +} + +pub trait SignerExt { + // I would name this create_default_rune but it might cause confusion + // with the Default::default() used in the Device's default + fn add_base_rune_to_device_credentials(&self, creds: Device) -> Result; +} + +impl SignerExt for Signer { + fn add_base_rune_to_device_credentials(&self, mut creds: Device) -> Result { + if creds.rune != String::default() { + return Err(anyhow!("A rune has already been set for these credentials")); + } + + let alt = runeauth::Alternative::new( + "pubkey".to_string(), + runeauth::Condition::Equal, + hex::encode(self.node_id()), + false, + ) + .unwrap(); + creds.rune = self.create_rune(None, vec![vec![&alt.encode()]]).unwrap(); + Ok(creds) + } +} diff --git a/examples/rust/getting-started/src/main.rs b/examples/rust/getting-started/src/main.rs index 6d0819712..56d370873 100644 --- a/examples/rust/getting-started/src/main.rs +++ b/examples/rust/getting-started/src/main.rs @@ -1,72 +1,20 @@ -use gl_client::credentials::{Device, Nobody}; +use anyhow::{anyhow, Result}; +use gl_client::credentials::{Device, Nobody, RuneProvider, TlsConfigProvider}; +use gl_client::node::ClnClient; +use gl_client::pb::{self, cln}; use gl_client::scheduler::Scheduler; use gl_client::{bitcoin::Network, signer::Signer}; use tokio; -use gl_client::node::ClnClient; -const CA_RAW: &[u8] = include_str!("../../tls/ca.pem").as_bytes(); + +mod extensions; +use extensions::*; #[tokio::main] async fn main() { + let seed = create_seed(); } -async fn starting_a_node(device_cert: Vec, device_key: Vec, seed: Vec) { - let node_id = - hex::decode("02058e8b6c2ad363ec59aa136429256d745164c2bdc87f98f0a68690ec2c5c9b0b").unwrap(); - let network = gl_client::bitcoin::Network::Testnet; - - let tls = gl_client::tls::TlsConfig::new() - .identity(device_cert.clone(), device_key.clone()); - - let scheduler = gl_client::scheduler::Scheduler::new(node_id, network) - .await - .unwrap(); - let mut node: gl_client::node::ClnClient = scheduler.schedule(tls).await.unwrap(); - - //p2 - use gl_client::pb::cln; - let info = node.getinfo(cln::GetinfoRequest::default()).await.unwrap(); - let peers = node - .list_peers(gl_client::pb::cln::ListpeersRequest::default()) - .await - .unwrap(); - - //p3 - node.invoice(cln::InvoiceRequest { - label: "label".to_string(), - description: "description".to_string(), - ..Default::default() - }) - .await - .unwrap(); - - //p4 - let (tx, mut rx) = tokio::sync::mpsc::channel(1); - - let tls = gl_client::tls::TlsConfig::new() - .unwrap() - .identity(device_cert, device_key); - let signer = - gl_client::signer::Signer::new(seed, gl_client::bitcoin::Network::Bitcoin, tls).unwrap(); - signer.run_forever(rx).await.unwrap(); -} - -async fn recover(device_cert: Vec, device_key: Vec, seed: Vec) { - let tls = gl_client::tls::TlsConfig::new() - .unwrap() - .identity(device_cert, device_key); - let signer = - gl_client::signer::Signer::new(seed, gl_client::bitcoin::Network::Bitcoin, tls).unwrap(); - let scheduler = gl_client::scheduler::Scheduler::new( - signer.node_id(), - gl_client::bitcoin::Network::Bitcoin, - ) - .await - .unwrap(); - - let res = scheduler.recover(&signer).await.unwrap(); -} - -async fn make_seed(cert: Vec, key: Vec, _secret: Vec) { +async fn create_seed() -> Vec { use bip39::{Language, Mnemonic}; let mut rng = rand::thread_rng(); @@ -78,33 +26,19 @@ async fn make_seed(cert: Vec, key: Vec, _secret: Vec) { const EMPTY_PASSPHRASE: &str = ""; let seed = &m.to_seed(EMPTY_PASSPHRASE)[0..32]; // Only need the first 32 bytes - let secret = seed[0..32].to_vec(); - // Store the seed on the filesystem, or secure configuration system + seed[0..32].to_vec() +} - //------- - //Registering the node / Initializing nobody credentials - //--------- - +async fn register_node(seed: Vec, developer_cert: Vec, developer_key: Vec) { // Creating a new `TlsConfig` object using your developer certificate // cert: contains the content of `client.crt` // key: contains the content of `client-key.pem` - let creds = Nobody::with(cert, key, key); - + let developer_creds = Nobody::with_identity(developer_cert, developer_key); + let signer = Signer::new(seed, Network::Bitcoin, developer_creds.clone()).unwrap(); - - //------- - //Creating a signer - //--------- - - let signer = Signer::new(secret, Network::Bitcoin, creds.clone()).unwrap(); - - - - //Registering a new node - - let scheduler = Scheduler::new(signer.node_id(), Network::Bitcoin, creds) + let scheduler = Scheduler::new(signer.node_id(), Network::Bitcoin, developer_creds) .await .unwrap(); @@ -112,11 +46,59 @@ async fn make_seed(cert: Vec, key: Vec, _secret: Vec) { // ownership of the `node_id` let registration_response = scheduler.register(&signer, None).await.unwrap(); + // Authenticating the scheduler + let device_creds = Device::from_bytes(registration_response.creds); - //Authenticating the scheduler - let creds = Device::from_bytes(registration_response.creds); + // Save the credentials somewhere safe - - let scheduler = scheduler.authenticate(creds).await.unwrap(); + let scheduler = scheduler.authenticate(device_creds).await.unwrap(); let mut node: ClnClient = scheduler.node().await.unwrap(); } + +async fn start_node(signer: Signer, device_creds: Device) { + let scheduler = gl_client::scheduler::Scheduler::new( + signer.node_id(), + gl_client::bitcoin::Network::Bitcoin, + device_creds.clone(), + ) + .await + .unwrap(); + + let mut node: gl_client::node::ClnClient = scheduler.node().await.unwrap(); + + let (_tx, rx) = tokio::sync::mpsc::channel(1); + tokio::spawn(async move { + signer.run_forever(rx).await.unwrap(); + }); + + node.invoice(cln::InvoiceRequest { + label: "label".to_string(), + description: "description".to_string(), + ..Default::default() + }) + .await + .unwrap(); +} + +async fn recover_node( + device_cert: Vec, + device_key: Vec, + seed: Vec, +) -> Result { + let network = gl_client::bitcoin::Network::Bitcoin; + let signer_creds = Device::with_identity(device_cert.clone(), device_key.clone()); + let signer = gl_client::signer::Signer::new(seed, network, signer_creds.clone()).unwrap(); + + let scheduler_creds = signer + .add_base_rune_to_device_credentials(signer_creds) + .unwrap(); + let scheduler = gl_client::scheduler::Scheduler::new( + signer.node_id(), + gl_client::bitcoin::Network::Bitcoin, + scheduler_creds, + ) + .await + .unwrap(); + + scheduler.recover(&signer).await +}