htlc_interceptor/
htlc_interceptor.rs

1use std::fs;
2
3///
4/// To use this demo:
5/// - create a 3 node network in polar (https://lightningpolar.com/) -- Alice, Bob and Carol
6/// - Create channels between Alice and Carol, and between Alice and Bob.
7/// - Create an invoice from Carol. Use the `decodepayreq` and `lookupinvoice` lncli commands to get preimage associated with Carol's invoice
8/// - Run this program with Alice's LND credentials, and the preimage from step above. For instance:
9///   `cargo run --example htlc_interceptor 127.0.0.1 10003 /Users/justin/.polar/networks/2/volumes/lnd/alice/tls.cert /Users/justin/.polar/networks/2/volumes/lnd/alice/data/chain/bitcoin/regtest/admin.macaroon <preimage>`
10/// - Have Bob pay the invoice via Polar UI
11/// - This program should output HTLC information. Polar should print success message.
12///
13
14#[tokio::main]
15async fn main() {
16    let mut args = std::env::args_os();
17    args.next().expect("not even zeroth arg given");
18
19    // Read the contents of the file into a vector of bytes
20    let cert_bytes = fs::read("path/to/tlscert").expect("FailedToReadTlsCertFile");
21    let mac_bytes = fs::read("path/to/macaroon").expect("FailedToReadMacaroonFile");
22
23    // Convert the bytes to a hex string
24    let cert = buffer_as_hex(cert_bytes);
25    let macaroon = buffer_as_hex(mac_bytes);
26
27    let socket = "localhost:10001".to_string();
28
29    let preimage = args.next().expect("missing argument: preimage");
30
31    let preimage = hex::decode(preimage.into_string().expect("preimage is invalid UTF-8")).unwrap();
32
33    let mut client = lnd_grpc_rust::connect(cert, macaroon, socket)
34        .await
35        .expect("failed to connect");
36
37    let (tx, rx) =
38        tokio::sync::mpsc::channel::<lnd_grpc_rust::routerrpc::ForwardHtlcInterceptResponse>(1024);
39    let stream = tokio_stream::wrappers::ReceiverStream::new(rx);
40
41    let mut htlc_stream = client
42        .router()
43        .htlc_interceptor(stream)
44        .await
45        .expect("Failed to call htlc_interceptor")
46        .into_inner();
47
48    while let Some(htlc) = htlc_stream
49        .message()
50        .await
51        .expect("Failed to receive htlcs")
52    {
53        println!("htlc {:?}", htlc);
54        let response = lnd_grpc_rust::routerrpc::ForwardHtlcInterceptResponse {
55            incoming_circuit_key: htlc.incoming_circuit_key,
56            action: 0,
57            preimage: preimage.clone(),
58            failure_code: 0,
59            failure_message: vec![],
60            in_amount_msat: todo!(),
61            out_amount_msat: todo!(),
62            out_wire_custom_records: todo!(),
63        };
64        tx.send(response).await.unwrap();
65    }
66}
67
68fn buffer_as_hex(bytes: Vec<u8>) -> String {
69    let hex_str = bytes
70        .iter()
71        .map(|b| format!("{:02x}", b))
72        .collect::<String>();
73
74    return hex_str;
75}