Skip to content

Commit

Permalink
docs: Linked getting-started docs to example code snippets.
Browse files Browse the repository at this point in the history
  • Loading branch information
Randy808 committed Apr 15, 2024
1 parent 42b3245 commit 597efc5
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 121 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 1 addition & 10 deletions docs/src/getting-started/recover.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,7 @@ In order to recover access all you need to do is recover the `seed` from the BIP

=== "Rust"
```rust
use gl_client::{Signer, TlsConfig, Scheduler, Bitcoin};

let cert = ...; // Your developer certificate (client.crt)
let key = ...; // Your developer key (client-key.pem)

let tls = TlsConfig().identity(cert, key);
let signer = Signer(seed, Network::Bitcoin, tls);
let scheduler = Scheduler::new(signer.node_id(), Network::Bitcoin).await;

let res = scheduler.recover(&signer).await?;
--8<-- "main.rs:recover_node"
```

=== "Python"
Expand Down
38 changes: 9 additions & 29 deletions docs/src/getting-started/register.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ phrase and then convert it into a seed secret we can use:

=== "Rust"
```rust
--8<-- "main.rs:70:82"
--8<-- "main.rs:create_seed"
```

=== "Python"
Expand All @@ -75,20 +75,15 @@ phrase and then convert it into a seed secret we can use:
funds on the node will be lost forever! We mean it when we say _you're
the only one with access to the seed_!

## Registering the node
## Initializing the signer

We'll configure mTLS using our developer identity. Any connection using the
`TlsConfig`-object specified below will allow you to register new Greenlight
To initialize a signer we'll first need to configure `Nobody` credentials so we can talk to the scheduler using mTLS. Nobody credentials require data from the files downloaded from the Greenlight Developer Console, so the files must be accessible from wherever the node registration program is run. Any connection using the
`developer_creds` object will allow you to register new Greenlight
nodes.

=== "Rust"
```rust
use gl_client::tls::TlsConfig;

# 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 tls = TlsConfig::new().identity(cert, key);
--8<-- "main.rs:dev_creds"
```

=== "Python"
Expand All @@ -115,9 +110,7 @@ We'll pick `bitcoin`, because ... reckless 😉

=== "Rust"
```rust
use gl_client::signer::Signer;
use gl_client::bitcoin::Network;
let signer = Signer::new(secret, Network::Bitcoin, tls).unwrap();
--8<-- "main.rs:init_signer"
```

=== "Python"
Expand All @@ -142,15 +135,7 @@ node's private key. Since the private key is managed exclusively by the

=== "Rust"
```rust
use gl_client::scheduler::Scheduler;
use gl_client::bitcoin::Network;

let scheduler = Scheduler::new(signer.node_id(), Network::Bitcoin).await.unwrap();

// Passing in the signer is required because the client needs to prove
// ownership of the `node_id`
scheduler.register(&signer, None).await.unwrap();

--8<-- "main.rs:register_node"
```

=== "Python"
Expand All @@ -176,13 +161,8 @@ going forward to talk to the scheduler and the node itself.
these credentials can access your node.

=== "Rust"
```
let tls = TlsConfig::new().unwrap().identity(res.device_cert, res.device_key);

// Use the configured `tls` instance when creating `Scheduler` and `Signer`
// instance going forward
let signer = Signer(seed, Network::Bitcoin, tls);
let scheduler = Scheduler::with(signer.node_id(), Network::Bitcoin, "uri", &tls).await?;
```rust
--8<-- "main.rs:get_node"
```

=== "Python"
Expand Down
29 changes: 4 additions & 25 deletions docs/src/getting-started/schedule.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,7 @@ Greenlight infrastructure:

=== "Rust"
```rust
use hex;
let node_id = hex::decode("02058e8b6c2ad363ec59aa136429256d745164c2bdc87f98f0a68690ec2c5c9b0b")?;
let network = "testnet";

let tls = TlsConfig::new().unwrap().identity(device_cert, device_key);

let scheduler = gl_client::scheduler::Scheduler(node_id, network)?;
let node: gl_client::node::ClnClient = scheduler.schedule(tls).await?;
--8<-- "main.rs:start_node"
```

=== "Python"
Expand All @@ -52,9 +45,7 @@ Once we have an instance of the `Node` we can start interacting with it via the

=== "Rust"
```rust
use gl_client::pb::cln;
let info = node.get_info(cln::GetinfoRequest::default()).await?;
let peers = node.list_peers(gl_client::pb::cln::ListpeersRequest::default()).await?;
--8<-- "main.rs:list_peers"
```
=== "Python"
```python
Expand All @@ -71,11 +62,7 @@ only component with access to your key.

=== "Rust"
```rust
node.invoice(cln::InvoiceRequest {
label: "label".to_string(),
description: "description".to_string(),
..Default::default(),
}).await?;
--8<-- "main.rs:create_invoice"
```

=== "Python"
Expand All @@ -100,15 +87,7 @@ in the last chapter, instantiate the signer with it and then start it.

=== "Rust"
```rust
let seed = ... // Load from wherever you stored it
let (cert, key) = ... // Load the cert and key you got from the `register` call

// The signer task will run until we send a shutdown signal on this channel
let (tx, mut rx) = tokio::sync::mpsc::channel(1);

let tls = TlsConfig().identity(cert, key);
signer = Signer(seed, Network::Bitcoin, tls);
signer.run_forever(rx).await?;
--8<-- "main.rs:start_signer"
```

Notice that `signer.run_forever()` returns a `Future` which you can spawn a
Expand Down
2 changes: 2 additions & 0 deletions examples/rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
seed
creds
14 changes: 13 additions & 1 deletion examples/rust/getting-started/src/extensions.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use anyhow::{anyhow, Result};
use gl_client::{
credentials::{Device, Nobody},
credentials::{Device, Nobody, TlsConfigProvider},
signer::Signer,
util::get_node_id_from_tls_config,
};

pub trait CredentialExt {
Expand Down Expand Up @@ -34,12 +35,23 @@ impl CredentialExt for Device {
}
}

pub trait DeviceExt {
fn node_id(&self) -> Result<Vec<u8>>;
}

impl DeviceExt for Device {
fn node_id(&self) -> Result<Vec<u8>> {
get_node_id_from_tls_config(&self.tls_config())
}
}

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<Device>;
}

//TODO: Delete after Device::upgrade is made idempotent
impl SignerExt for Signer {
fn add_base_rune_to_device_credentials(&self, mut creds: Device) -> Result<Device> {
if creds.rune != String::default() {
Expand Down
80 changes: 60 additions & 20 deletions examples/rust/getting-started/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::fs::{self, File};
use std::io::Write;

use anyhow::{anyhow, Result};
use bip39::{Language, Mnemonic};
use gl_client::credentials::{Device, Nobody, RuneProvider, TlsConfigProvider};
use gl_client::node::ClnClient;
use gl_client::pb::{self, cln};
Expand All @@ -10,88 +14,123 @@ mod extensions;
use extensions::*;

#[tokio::main]
async fn main() {
let seed = create_seed();
async fn main() {}

fn save_to_file(file_name: &str, data: Vec<u8>) {
fs::write(file_name, data).unwrap();
}

async fn create_seed() -> Vec<u8> {
use bip39::{Language, Mnemonic};
fn read_file(file_name: &str) -> Vec<u8>{
fs::read(file_name).unwrap()
}

async fn create_seed() -> Vec<u8> {
// ---8<--- [start: create_seed]
let mut rng = rand::thread_rng();
let m = Mnemonic::generate_in_with(&mut rng, Language::English, 24).unwrap();
let phrase = m.word_iter().fold("".to_string(), |c, n| c + " " + n);

// Prompt user to safely store the phrase
//Show seed phrase to user
let phrase = m.word_iter().fold("".to_string(), |c, n| c + " " + n);

const EMPTY_PASSPHRASE: &str = "";
let seed = &m.to_seed(EMPTY_PASSPHRASE)[0..32]; // Only need the first 32 bytes

// Store the seed on the filesystem, or secure configuration system
seed[0..32].to_vec()
}
save_to_file("seed", seed.to_vec());

async fn register_node(seed: Vec<u8>, developer_cert: Vec<u8>, developer_key: Vec<u8>) {
// Creating a new `TlsConfig` object using your developer certificate
// cert: contains the content of `client.crt`
// key: contains the content of `client-key.pem`
// ---8<--- [end: create_seed]
seed.to_vec()
}

async fn register_node(seed: Vec<u8>, developer_cert_path: String, developer_key_path: String) {
// ---8<--- [start: dev_creds]
let developer_cert = std::fs::read(developer_cert_path).unwrap_or_default();
let developer_key = std::fs::read(developer_key_path).unwrap_or_default();
let developer_creds = Nobody::with_identity(developer_cert, developer_key);
let signer = Signer::new(seed, Network::Bitcoin, developer_creds.clone()).unwrap();
// ---8<--- [end: dev_creds]

// ---8<--- [start: init_signer]
let network = Network::Bitcoin;
let signer = Signer::new(seed, network, developer_creds.clone()).unwrap();
// ---8<--- [end: init_signer]

let scheduler = Scheduler::new(signer.node_id(), Network::Bitcoin, developer_creds)
// ---8<--- [start: register_node]
let scheduler = Scheduler::new(signer.node_id(), network, developer_creds)
.await
.unwrap();

// Passing in the signer is required because the client needs to prove
// 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);
save_to_file("creds", device_creds.to_bytes());
// ---8<--- [end: register_node]

// Save the credentials somewhere safe

// ---8<--- [start: get_node]
let scheduler = scheduler.authenticate(device_creds).await.unwrap();
let mut node: ClnClient = scheduler.node().await.unwrap();
// ---8<--- [end: get_node]
}

async fn start_node(signer: Signer, device_creds: Device) {
async fn start_node(device_creds_path: String) {
// ---8<--- [start: start_node]
let device_creds = Device::from_path(device_creds_path);
let scheduler = gl_client::scheduler::Scheduler::new(
signer.node_id(),
device_creds.node_id().unwrap(),
gl_client::bitcoin::Network::Bitcoin,
device_creds.clone(),
)
.await
.unwrap();

let mut node: gl_client::node::ClnClient = scheduler.node().await.unwrap();
// ---8<--- [end: start_node]

// ---8<--- [start: list_peers]
let info = node.getinfo(cln::GetinfoRequest::default()).await.unwrap();
let peers = node
.list_peers(gl_client::pb::cln::ListpeersRequest::default())
.await
.unwrap();
// ---8<--- [end: list_peers]

// ---8<--- [start: start_signer]
let network = Network::Bitcoin;
let seed = read_file("seed");
let signer = Signer::new(seed, network, device_creds.clone()).unwrap();

let (_tx, rx) = tokio::sync::mpsc::channel(1);
tokio::spawn(async move {
signer.run_forever(rx).await.unwrap();
});
// ---8<--- [end: start_signer]

// ---8<--- [start: create_invoice]
node.invoice(cln::InvoiceRequest {
label: "label".to_string(),
description: "description".to_string(),
..Default::default()
})
.await
.unwrap();
// ---8<--- [end: create_invoice]
}

async fn recover_node(
device_cert: Vec<u8>,
device_key: Vec<u8>,
seed: Vec<u8>,
) -> Result<pb::scheduler::RecoveryResponse> {
// ---8<--- [start: recover_node]
let seed = read_file("seed");
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,
Expand All @@ -101,4 +140,5 @@ async fn recover_node(
.unwrap();

scheduler.recover(&signer).await
// ---8<--- [end: recover_node]
}
2 changes: 1 addition & 1 deletion libs/gl-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub mod credentials;
/// Functionality to integrate greenlight with a Lightning Service Provider
pub mod lsps;

mod util;
pub mod util;

use thiserror::Error;

Expand Down
Loading

0 comments on commit 597efc5

Please sign in to comment.