From 7fc870e1c711993cfe5a41f247481a514b273f13 Mon Sep 17 00:00:00 2001 From: John Cantrell Date: Tue, 4 Oct 2022 15:36:47 -0400 Subject: [PATCH] refactor node id, remove cluster node concept, phantom payment test --- entity/src/cluster_node.rs | 95 ------------ entity/src/lib.rs | 1 - entity/src/node.rs | 10 -- entity/src/payment.rs | 6 + migration/src/lib.rs | 2 - .../m20220421_000001_create_nodes_table.rs | 4 +- .../m20220424_000003_create_payments_table.rs | 5 +- ...21003_000001_create_cluster_nodes_table.rs | 76 ---------- proto/sensei.proto | 13 +- senseicore/src/database.rs | 88 +---------- senseicore/src/event_handler.rs | 29 +++- senseicore/src/node.rs | 133 ++++------------- senseicore/src/services/admin.rs | 41 +++--- senseicore/src/services/node.rs | 20 +-- senseicore/tests/smoke_test.rs | 137 ++++++++++++++++-- src/grpc/adaptor.rs | 128 +++++----------- src/grpc/admin.rs | 4 +- src/grpc/node.rs | 60 +++----- src/http/admin.rs | 4 +- src/http/node.rs | 88 +---------- 20 files changed, 281 insertions(+), 663 deletions(-) delete mode 100644 entity/src/cluster_node.rs delete mode 100644 migration/src/m20221003_000001_create_cluster_nodes_table.rs diff --git a/entity/src/cluster_node.rs b/entity/src/cluster_node.rs deleted file mode 100644 index eaf3abc..0000000 --- a/entity/src/cluster_node.rs +++ /dev/null @@ -1,95 +0,0 @@ -use sea_orm::{entity::prelude::*, ActiveValue}; -use serde::{Deserialize, Serialize}; - -use crate::seconds_since_epoch; - -#[derive(Copy, Clone, Default, Debug, DeriveEntity)] -pub struct Entity; - -impl EntityName for Entity { - fn table_name(&self) -> &str { - "cluster_node" - } -} - -#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Deserialize, Serialize)] -pub struct Model { - pub id: String, - pub created_at: i64, - pub updated_at: i64, - pub node_id: String, - pub label: Option, - pub pubkey: String, - pub host: String, - pub port: i32, - pub macaroon_hex: String, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] -pub enum Column { - Id, - CreatedAt, - UpdatedAt, - NodeId, - Label, - Pubkey, - Host, - Port, - MacaroonHex, -} - -#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] -pub enum PrimaryKey { - Id, -} - -impl PrimaryKeyTrait for PrimaryKey { - type ValueType = String; - fn auto_increment() -> bool { - false - } -} - -#[derive(Copy, Clone, Debug, EnumIter)] -pub enum Relation {} - -impl ColumnTrait for Column { - type EntityName = Entity; - fn def(&self) -> ColumnDef { - match self { - Self::Id => ColumnType::String(None).def().unique(), - Self::CreatedAt => ColumnType::BigInteger.def(), - Self::UpdatedAt => ColumnType::BigInteger.def(), - Self::NodeId => ColumnType::String(None).def(), - Self::Label => ColumnType::String(None).def(), - Self::Pubkey => ColumnType::String(None).def(), - Self::Host => ColumnType::String(None).def(), - Self::Port => ColumnType::Integer.def(), - Self::MacaroonHex => ColumnType::String(None).def(), - } - } -} - -impl RelationTrait for Relation { - fn def(&self) -> RelationDef { - panic!("No RelationDef") - } -} - -impl ActiveModelBehavior for ActiveModel { - fn new() -> Self { - Self { - id: ActiveValue::Set(Uuid::new_v4().to_string()), - ..::default() - } - } - - fn before_save(mut self, insert: bool) -> Result { - let now: i64 = seconds_since_epoch(); - self.updated_at = ActiveValue::Set(now); - if insert { - self.created_at = ActiveValue::Set(now); - } - Ok(self) - } -} diff --git a/entity/src/lib.rs b/entity/src/lib.rs index a088d30..efe2e28 100644 --- a/entity/src/lib.rs +++ b/entity/src/lib.rs @@ -5,7 +5,6 @@ pub use sea_orm; pub mod prelude; pub mod access_token; -pub mod cluster_node; pub mod keychain; pub mod kv_store; pub mod macaroon; diff --git a/entity/src/node.rs b/entity/src/node.rs index 65d1ec6..9157bc4 100644 --- a/entity/src/node.rs +++ b/entity/src/node.rs @@ -54,7 +54,6 @@ pub struct Model { pub network: String, pub listen_addr: String, pub listen_port: i32, - pub pubkey: String, pub created_at: i64, pub updated_at: i64, pub status: i16, @@ -86,7 +85,6 @@ pub enum Column { Network, ListenAddr, ListenPort, - Pubkey, CreatedAt, UpdatedAt, Status, @@ -118,7 +116,6 @@ impl ColumnTrait for Column { Self::Network => ColumnType::String(None).def(), Self::ListenAddr => ColumnType::String(None).def(), Self::ListenPort => ColumnType::Integer.def(), - Self::Pubkey => ColumnType::String(None).def().unique(), Self::CreatedAt => ColumnType::BigInteger.def(), Self::UpdatedAt => ColumnType::BigInteger.def(), Self::Status => ColumnType::SmallInteger.def(), @@ -133,13 +130,6 @@ impl RelationTrait for Relation { } impl ActiveModelBehavior for ActiveModel { - fn new() -> Self { - Self { - id: ActiveValue::Set(Uuid::new_v4().to_string()), - ..::default() - } - } - fn before_save(mut self, insert: bool) -> Result { let now: i64 = seconds_since_epoch(); self.updated_at = ActiveValue::Set(now); diff --git a/entity/src/payment.rs b/entity/src/payment.rs index 5c57e05..423aae9 100644 --- a/entity/src/payment.rs +++ b/entity/src/payment.rs @@ -21,6 +21,8 @@ pub struct Model { pub origin: String, pub created_at: i64, pub updated_at: i64, + pub created_by_node_id: String, + pub received_by_node_id: Option, pub amt_msat: Option, pub fee_paid_msat: Option, pub preimage: Option, @@ -33,6 +35,8 @@ pub struct Model { pub enum Column { Id, NodeId, + CreatedByNodeId, + ReceivedByNodeId, PaymentHash, Preimage, Secret, @@ -67,11 +71,13 @@ impl ColumnTrait for Column { match self { Self::Id => ColumnType::String(None).def(), Self::NodeId => ColumnType::String(None).def(), + Self::CreatedByNodeId => ColumnType::String(None).def(), Self::PaymentHash => ColumnType::String(None).def(), Self::Status => ColumnType::String(None).def(), Self::Origin => ColumnType::String(None).def(), Self::CreatedAt => ColumnType::BigInteger.def(), Self::UpdatedAt => ColumnType::BigInteger.def(), + Self::ReceivedByNodeId => ColumnType::String(None).def().null(), Self::AmtMsat => ColumnType::BigInteger.def().null(), Self::FeePaidMsat => ColumnType::BigInteger.def().null(), Self::Preimage => ColumnType::String(None).def().null(), diff --git a/migration/src/lib.rs b/migration/src/lib.rs index 0cd1956..d14e88d 100644 --- a/migration/src/lib.rs +++ b/migration/src/lib.rs @@ -12,7 +12,6 @@ mod m20220428_000004_create_keychains_table; mod m20220616_000001_create_peers_table; mod m20220701_000001_create_peer_addresses_table; mod m20220808_000001_create_users_table; -mod m20221003_000001_create_cluster_nodes_table; pub struct Migrator; @@ -33,7 +32,6 @@ impl MigratorTrait for Migrator { Box::new(m20220616_000001_create_peers_table::Migration), Box::new(m20220701_000001_create_peer_addresses_table::Migration), Box::new(m20220808_000001_create_users_table::Migration), - Box::new(m20221003_000001_create_cluster_nodes_table::Migration), ] } } diff --git a/migration/src/m20220421_000001_create_nodes_table.rs b/migration/src/m20220421_000001_create_nodes_table.rs index 89fb4ac..4ecd272 100644 --- a/migration/src/m20220421_000001_create_nodes_table.rs +++ b/migration/src/m20220421_000001_create_nodes_table.rs @@ -27,7 +27,6 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(Node::Network).string().not_null()) .col(ColumnDef::new(Node::ListenAddr).string().not_null()) .col(ColumnDef::new(Node::ListenPort).integer().not_null()) - .col(ColumnDef::new(Node::Pubkey).string().not_null()) .col(ColumnDef::new(Node::CreatedAt).big_integer().not_null()) .col(ColumnDef::new(Node::UpdatedAt).big_integer().not_null()) .col(ColumnDef::new(Node::Status).small_integer().not_null()) @@ -45,15 +44,14 @@ impl MigrationTrait for Migration { #[derive(Iden)] enum Node { - Table, Id, + Table, Role, Username, Alias, Network, ListenAddr, ListenPort, - Pubkey, CreatedAt, UpdatedAt, Status, diff --git a/migration/src/m20220424_000003_create_payments_table.rs b/migration/src/m20220424_000003_create_payments_table.rs index b5f1eab..292c1f8 100644 --- a/migration/src/m20220424_000003_create_payments_table.rs +++ b/migration/src/m20220424_000003_create_payments_table.rs @@ -24,6 +24,8 @@ impl MigrationTrait for Migration { .col(ColumnDef::new(Payment::CreatedAt).big_integer().not_null()) .col(ColumnDef::new(Payment::UpdatedAt).big_integer().not_null()) .col(ColumnDef::new(Payment::NodeId).string().not_null()) + .col(ColumnDef::new(Payment::ReceivedByNodeId).string()) + .col(ColumnDef::new(Payment::CreatedByNodeId).string().not_null()) .col(ColumnDef::new(Payment::PaymentHash).string().not_null()) .col(ColumnDef::new(Payment::Preimage).string()) .col(ColumnDef::new(Payment::Secret).string()) @@ -44,7 +46,6 @@ impl MigrationTrait for Migration { .name("idx-nodeid-paymenthash") .col(Payment::NodeId) .col(Payment::PaymentHash) - .unique() .to_owned(), ) .await @@ -62,6 +63,8 @@ enum Payment { Table, Id, NodeId, + ReceivedByNodeId, + CreatedByNodeId, PaymentHash, Preimage, Secret, diff --git a/migration/src/m20221003_000001_create_cluster_nodes_table.rs b/migration/src/m20221003_000001_create_cluster_nodes_table.rs deleted file mode 100644 index b5e7300..0000000 --- a/migration/src/m20221003_000001_create_cluster_nodes_table.rs +++ /dev/null @@ -1,76 +0,0 @@ -use sea_schema::migration::prelude::*; -pub struct Migration; - -impl MigrationName for Migration { - fn name(&self) -> &str { - "m20221003_000001_create_cluster_nodes_table" - } -} - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - let _res = manager - .create_table( - Table::create() - .table(ClusterNode::Table) - .if_not_exists() - .col( - ColumnDef::new(ClusterNode::Id) - .string() - .not_null() - .primary_key(), - ) - .col( - ColumnDef::new(ClusterNode::CreatedAt) - .big_integer() - .not_null(), - ) - .col( - ColumnDef::new(ClusterNode::UpdatedAt) - .big_integer() - .not_null(), - ) - .col(ColumnDef::new(ClusterNode::NodeId).string().not_null()) - .col(ColumnDef::new(ClusterNode::Host).string().not_null()) - .col(ColumnDef::new(ClusterNode::Port).integer().not_null()) - .col(ColumnDef::new(ClusterNode::MacaroonHex).string().not_null()) - .col(ColumnDef::new(ClusterNode::Label).string()) - .col(ColumnDef::new(ClusterNode::Pubkey).string().not_null()) - .to_owned(), - ) - .await; - - manager - .create_index( - Index::create() - .table(ClusterNode::Table) - .name("idx-cn-nodeid-pubkey") - .col(ClusterNode::NodeId) - .col(ClusterNode::Pubkey) - .unique() - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - let mut drop_table_stmt = Table::drop(); - drop_table_stmt.table(ClusterNode::Table); - manager.drop_table(drop_table_stmt).await - } -} - -#[derive(Iden)] -enum ClusterNode { - Table, - Id, - CreatedAt, - UpdatedAt, - NodeId, - Host, - Port, - MacaroonHex, - Label, - Pubkey, -} diff --git a/proto/sensei.proto b/proto/sensei.proto index d9e3d27..a9d8126 100644 --- a/proto/sensei.proto +++ b/proto/sensei.proto @@ -30,6 +30,7 @@ service Node { rpc Keysend (KeysendRequest) returns (KeysendResponse); rpc CreateInvoice (CreateInvoiceRequest) returns (CreateInvoiceResponse); rpc CreatePhantomInvoice (CreatePhantomInvoiceRequest) returns (CreatePhantomInvoiceResponse); + rpc GetPhantomRouteHints (GetPhantomRouteHintsRequest) returns (GetPhantomRouteHintsResponse); rpc LabelPayment (LabelPaymentRequest) returns (LabelPaymentResponse); rpc DeletePayment (DeletePaymentRequest) returns (DeletePaymentResponse); rpc ConnectPeer (ConnectPeerRequest) returns (ConnectPeerResponse); @@ -45,9 +46,6 @@ service Node { rpc ListKnownPeers (ListKnownPeersRequest) returns (ListKnownPeersResponse); rpc AddKnownPeer (AddKnownPeerRequest) returns (AddKnownPeerResponse); rpc RemoveKnownPeer (RemoveKnownPeerRequest) returns (RemoveKnownPeerResponse); - rpc ListClusterNodes (ListClusterNodesRequest) returns (ListClusterNodesResponse); - rpc AddClusterNode (AddClusterNodeRequest) returns (AddClusterNodeResponse); - rpc RemoveClusterNode (RemoveClusterNodeRequest) returns (RemoveClusterNodeResponse); } message ListNode { @@ -340,11 +338,17 @@ message CreateInvoiceResponse { message CreatePhantomInvoiceRequest { uint64 amt_msat = 1; string description = 2; + repeated string phantom_route_hints_hex = 3; } message CreatePhantomInvoiceResponse { string invoice = 1; } +message GetPhantomRouteHintsRequest {} +message GetPhantomRouteHintsResponse { + string phantom_route_hints_hex = 1; +} + message ConnectPeerRequest { string node_connection_string = 1; } @@ -389,6 +393,9 @@ message Payment { string origin = 7; optional string label = 8; optional string invoice = 9; + string created_by_node_id = 10; + optional string received_by_node_id = 11; + string node_id = 12; } message PaymentsFilter { diff --git a/senseicore/src/database.rs b/senseicore/src/database.rs index fcc9c02..3234f70 100644 --- a/senseicore/src/database.rs +++ b/senseicore/src/database.rs @@ -8,8 +8,6 @@ use bdk::BlockTime; use bitcoin::BlockHash; use entity::access_token; use entity::access_token::Entity as AccessToken; -use entity::cluster_node; -use entity::cluster_node::Entity as ClusterNode; use entity::kv_store; use entity::kv_store::Entity as KVStore; use entity::macaroon; @@ -92,7 +90,7 @@ impl SenseiDatabase { pub async fn get_node_by_pubkey(&self, pubkey: &str) -> Result, Error> { Ok(Node::find() - .filter(node::Column::Pubkey.eq(pubkey)) + .filter(node::Column::Id.eq(pubkey)) .one(&self.connection) .await?) } @@ -137,7 +135,7 @@ impl SenseiDatabase { .filter( Condition::any() .add(node::Column::Alias.contains(&query_string)) - .add(node::Column::Pubkey.contains(&query_string)) + .add(node::Column::Id.contains(&query_string)) .add(node::Column::Username.contains(&query_string)), ) .order_by_desc(node::Column::UpdatedAt) @@ -498,88 +496,6 @@ impl SenseiDatabase { )) } - pub async fn delete_cluster_node(&self, node_id: &str, pubkey: &str) -> Result<(), Error> { - match self.find_cluster_node(node_id, pubkey).await? { - Some(cluster_node) => { - let _deleted = cluster_node.delete(&self.connection).await?; - Ok(()) - } - None => Ok(()), - } - } - - pub async fn find_cluster_node( - &self, - node_id: &str, - pubkey: &str, - ) -> Result, Error> { - Ok(ClusterNode::find() - .filter(entity::cluster_node::Column::NodeId.eq(node_id)) - .filter(entity::cluster_node::Column::Pubkey.eq(pubkey)) - .one(&self.connection) - .await?) - } - - pub fn find_cluster_node_sync( - &self, - node_id: &str, - pubkey: &str, - ) -> Result, Error> { - tokio::task::block_in_place(move || { - self.runtime_handle - .block_on(async move { self.find_cluster_node(node_id, pubkey).await }) - }) - } - - pub async fn label_cluster_node( - &self, - node_id: &str, - pubkey: &str, - label: String, - ) -> Result<(), Error> { - match self.find_cluster_node(node_id, pubkey).await? { - Some(cluster_node) => { - let mut cluster_node: cluster_node::ActiveModel = cluster_node.into(); - cluster_node.label = ActiveValue::Set(Some(label)); - cluster_node.update(&self.connection).await?; - Ok(()) - } - None => Ok(()), - } - } - - pub async fn list_cluster_nodes( - &self, - node_id: &str, - pagination: PaginationRequest, - ) -> Result<(Vec, PaginationResponse), Error> { - let query_string = pagination.query.unwrap_or_else(|| String::from("")); - let page_size: usize = pagination.take.try_into().unwrap(); - let page: usize = pagination.page.try_into().unwrap(); - - let cluster_node_pages = ClusterNode::find() - .filter(cluster_node::Column::NodeId.eq(node_id)) - .filter( - Condition::any() - .add(cluster_node::Column::Pubkey.contains(&query_string)) - .add(cluster_node::Column::Label.contains(&query_string)), - ) - .order_by_desc(cluster_node::Column::CreatedAt) - .paginate(&self.connection, page_size); - - let cluster_nodes = cluster_node_pages.fetch_page(page).await?; - let total = cluster_node_pages.num_items().await?; - let has_more = ((page + 1) * page_size) < total; - - Ok(( - cluster_nodes, - PaginationResponse { - has_more, - total: total.try_into().unwrap(), - }, - )) - } - pub async fn port_in_use(&self, listen_addr: &str, listen_port: i32) -> Result { self.get_node_by_connection_info(listen_addr, listen_port) .await diff --git a/senseicore/src/event_handler.rs b/senseicore/src/event_handler.rs index 1f86f73..13c9986 100644 --- a/senseicore/src/event_handler.rs +++ b/senseicore/src/event_handler.rs @@ -17,11 +17,13 @@ use crate::hex_utils; use crate::node::{ChannelManager, HTLCStatus, PaymentOrigin}; use bdk::wallet::AddressIndex; +use bitcoin::secp256k1::{self, PublicKey}; use bitcoin::{secp256k1::Secp256k1, Network}; use bitcoin_bech32::WitnessProgram; use entity::sea_orm::ActiveValue; use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; -use lightning::chain::keysinterface::PhantomKeysManager; +use lightning::chain::keysinterface::{KeysInterface, PhantomKeysManager, Recipient}; + use lightning::{ chain::chaininterface::ConfirmationTarget, util::events::{Event, EventHandler, PaymentPurpose}, @@ -43,6 +45,7 @@ pub struct LightningNodeEventHandler { pub tokio_handle: Handle, pub event_sender: broadcast::Sender, pub broadcaster: Arc, + pub secp_ctx: Secp256k1, } impl EventHandler for LightningNodeEventHandler { @@ -181,20 +184,31 @@ impl EventHandler for LightningNodeEventHandler { }; let payment_hash = hex_utils::hex_str(&payment_hash.0); + let preimage = payment_preimage.map(|preimage| hex_utils::hex_str(&preimage.0)); + let secret = payment_secret.map(|secret| hex_utils::hex_str(&secret.0)); + let amt_msat: Option = Some((*amount_msat).try_into().unwrap()); let existing_payment = self .database .find_payment_sync(self.node_id.clone(), payment_hash.clone()) - .unwrap_or(None); - - let preimage = payment_preimage.map(|preimage| hex_utils::hex_str(&preimage.0)); - let secret = payment_secret.map(|secret| hex_utils::hex_str(&secret.0)); - let amt_msat: Option = Some((*amount_msat).try_into().unwrap()); + .unwrap_or_else(|_| { + let phantom_node_secret = self + .keys_manager + .get_node_secret(Recipient::PhantomNode) + .unwrap(); + let phantom_node_pubkey = + PublicKey::from_secret_key(&self.secp_ctx, &phantom_node_secret) + .to_string(); + self.database + .find_payment_sync(phantom_node_pubkey, payment_hash.clone()) + .unwrap_or(None) + }); match existing_payment { Some(payment) => { let mut payment: entity::payment::ActiveModel = payment.into(); payment.status = ActiveValue::Set(HTLCStatus::Succeeded.to_string()); + payment.received_by_node_id = ActiveValue::Set(Some(self.node_id.clone())); payment.preimage = ActiveValue::Set(preimage); payment.secret = ActiveValue::Set(secret); payment.amt_msat = ActiveValue::Set(amt_msat); @@ -203,6 +217,9 @@ impl EventHandler for LightningNodeEventHandler { } None => { let payment = entity::payment::ActiveModel { + node_id: ActiveValue::Set(self.node_id.clone()), + created_by_node_id: ActiveValue::Set(self.node_id.clone()), + received_by_node_id: ActiveValue::Set(Some(self.node_id.clone())), payment_hash: ActiveValue::Set(payment_hash), status: ActiveValue::Set(HTLCStatus::Succeeded.to_string()), preimage: ActiveValue::Set(preimage), diff --git a/senseicore/src/node.rs b/senseicore/src/node.rs index 47848c4..ddd7b95 100644 --- a/senseicore/src/node.rs +++ b/senseicore/src/node.rs @@ -565,6 +565,7 @@ impl LightningNode { let existing_macaroon = self.database.find_macaroon_by_id(session.id).await?; if existing_macaroon.is_none() { + println!("macaroon not found by id"); return Err(Error::InvalidMacaroon); } @@ -588,6 +589,16 @@ impl LightningNode { node_pubkey.to_string() } + pub fn get_phantom_node_pubkey(&self) -> String { + let secp_ctx = Secp256k1::new(); + let node_secret = self + .keys_manager + .get_node_secret(Recipient::PhantomNode) + .unwrap(); + let node_pubkey = PublicKey::from_secret_key(&secp_ctx, &node_secret); + node_pubkey.to_string() + } + #[allow(clippy::too_many_arguments)] pub async fn new( config: Arc, @@ -834,6 +845,7 @@ impl LightningNode { chain_manager: chain_manager.clone(), event_sender: event_sender.clone(), broadcaster: broadcaster.clone(), + secp_ctx: Secp256k1::new(), }); let invoice_payer = Arc::new(InvoicePayer::new( @@ -1079,6 +1091,7 @@ impl LightningNode { let payment = entity::payment::ActiveModel { node_id: ActiveValue::Set(self.id.clone()), + created_by_node_id: ActiveValue::Set(self.id.clone()), payment_hash: ActiveValue::Set(payment_hash), secret: ActiveValue::Set(payment_secret), status: ActiveValue::Set(status.to_string()), @@ -1097,6 +1110,7 @@ impl LightningNode { &self, amt_msat: u64, description: String, + phantom_route_hints: Vec, ) -> Result { let currency = match self.config.network { Network::Bitcoin => Currency::Bitcoin, @@ -1105,58 +1119,6 @@ impl LightningNode { Network::Signet => Currency::Signet, }; - let nodes_pagination = PaginationRequest { - page: 0, - take: 5, - query: None, - }; - let (nodes, _pagination_response) = self - .database - .list_cluster_nodes(&self.id, nodes_pagination) - .await?; - - let mut phantom_route_hints = vec![]; - phantom_route_hints.push(self.channel_manager.get_phantom_route_hints()); - - let client = reqwest::Client::new(); - for node in nodes.iter() { - let url = format!( - "http://{}:{}/api/v1/node/phantom-route-hints", - node.host, node.port - ); - let hints: Option = match client - .get(&url) - .header("token", node.macaroon_hex.clone()) - .send() - .await - { - Ok(response) => match response.bytes().await { - Ok(bytes) => { - let mut readable = Cursor::new(bytes.to_vec()); - Some(PhantomRouteHints::read(&mut readable).unwrap()) - } - Err(e) => { - eprintln!( - "failed to convert phantom route hints response to bytes: {:?}", - e - ); - None - } - }, - Err(e) => { - eprintln!( - "failed to fetch phantom route hints at {} with error: {:?}", - url, e - ); - None - } - }; - - if let Some(hints) = hints { - phantom_route_hints.push(hints); - } - } - let invoice = utils::create_phantom_invoice::>( Some(amt_msat), None, @@ -1171,7 +1133,8 @@ impl LightningNode { let payment_secret = Some(hex_utils::hex_str(&(*invoice.payment_secret()).0)); let payment = entity::payment::ActiveModel { - node_id: ActiveValue::Set(self.id.clone()), + node_id: ActiveValue::Set(self.get_phantom_node_pubkey()), + created_by_node_id: ActiveValue::Set(self.id.clone()), payment_hash: ActiveValue::Set(payment_hash), secret: ActiveValue::Set(payment_secret), status: ActiveValue::Set(HTLCStatus::Pending.to_string()), @@ -1212,6 +1175,7 @@ impl LightningNode { let payment = entity::payment::ActiveModel { node_id: ActiveValue::Set(self.id.clone()), + created_by_node_id: ActiveValue::Set(self.id.clone()), payment_hash: ActiveValue::Set(payment_hash), secret: ActiveValue::Set(payment_secret), status: ActiveValue::Set(HTLCStatus::Pending.to_string()), @@ -1471,6 +1435,7 @@ impl LightningNode { }) } NodeRequest::GetPhantomRouteHints {} => { + println!("getting phantom route hints"); let hints = self.channel_manager.get_phantom_route_hints(); Ok(NodeResponse::GetPhantomRouteHints { phantom_route_hints_hex: hex_utils::hex_str(&hints.encode()), @@ -1571,8 +1536,19 @@ impl LightningNode { NodeRequest::GetPhantomInvoice { amt_msat, description, + phantom_route_hints_hex, } => { - let invoice = self.get_phantom_invoice(amt_msat, description).await?; + let phantom_route_hints = phantom_route_hints_hex + .into_iter() + .map(|hints_hex| { + let mut cursor = Cursor::new(hex_utils::to_vec(&hints_hex).unwrap()); + PhantomRouteHints::read(&mut cursor).unwrap() + }) + .collect::>(); + + let invoice = self + .get_phantom_invoice(amt_msat, description, phantom_route_hints) + .await?; let invoice_str = format!("{}", invoice); Ok(NodeResponse::GetPhantomInvoice { invoice: invoice_str, @@ -1725,55 +1701,6 @@ impl LightningNode { self.database.delete_peer(&self.id, &pubkey).await?; Ok(NodeResponse::RemoveKnownPeer {}) } - NodeRequest::ListClusterNodes { pagination } => { - let (cluster_nodes, pagination) = self - .database - .list_cluster_nodes(&self.id, pagination) - .await?; - Ok(NodeResponse::ListClusterNodes { - cluster_nodes, - pagination, - }) - } - NodeRequest::AddClusterNode { - pubkey, - label, - host, - port, - macaroon_hex, - } => { - let cluster_node = match self.database.find_cluster_node(&self.id, &pubkey).await? { - Some(cluster_node) => { - let mut cluster_node: entity::cluster_node::ActiveModel = - cluster_node.into(); - cluster_node.label = ActiveValue::Set(Some(label)); - cluster_node.host = ActiveValue::Set(host); - cluster_node.port = ActiveValue::Set(port.into()); - cluster_node.macaroon_hex = ActiveValue::Set(macaroon_hex); - cluster_node.update(self.database.get_connection()) - } - None => { - let cluster_node = entity::cluster_node::ActiveModel { - node_id: ActiveValue::Set(self.id.clone()), - pubkey: ActiveValue::Set(pubkey), - label: ActiveValue::Set(Some(label)), - host: ActiveValue::Set(host), - port: ActiveValue::Set(port.into()), - macaroon_hex: ActiveValue::Set(macaroon_hex), - ..Default::default() - }; - cluster_node.insert(self.database.get_connection()) - } - }; - - let _res = cluster_node.await.map_err(Error::Db)?; - - Ok(NodeResponse::AddClusterNode {}) - } - NodeRequest::RemoveClusterNode { pubkey } => { - self.database.delete_cluster_node(&self.id, &pubkey).await?; - Ok(NodeResponse::RemoveClusterNode {}) - } } } } diff --git a/senseicore/src/services/admin.rs b/senseicore/src/services/admin.rs index e349b7b..55a727a 100644 --- a/senseicore/src/services/admin.rs +++ b/senseicore/src/services/admin.rs @@ -38,7 +38,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::{collections::hash_map::Entry, fs, sync::Arc}; use tokio::sync::{broadcast, Mutex}; use tokio::task::JoinHandle; -use uuid::Uuid; pub struct NodeHandle { pub node: Arc, @@ -335,7 +334,7 @@ impl AdminService { setup, authenticated_admin, authenticated_node: true, - pubkey: Some(pubkey_node.pubkey), + pubkey: Some(pubkey_node.id), username: Some(pubkey_node.username), role: Some(pubkey_node.role), }) @@ -447,7 +446,7 @@ impl AdminService { self.start_node(node.clone(), passphrase).await?; } Ok(AdminResponse::CreateNode { - pubkey: node.pubkey, + pubkey: node.id.clone(), macaroon: hex_utils::hex_str(macaroon.as_slice()), listen_addr: node.listen_addr, listen_port: node.listen_port, @@ -475,7 +474,7 @@ impl AdminService { .map(|(node, macaroon, entropy, cross_node_entropy)| { let macaroon = macaroon.serialize(macaroon::Format::V2).unwrap(); NodeCreateResult { - pubkey: node.pubkey, + pubkey: node.id.clone(), macaroon: hex_utils::hex_str(macaroon.as_slice()), listen_addr: node.listen_addr, listen_port: node.listen_port, @@ -794,13 +793,6 @@ impl AdminService { } }; - // NODE ID - let node_id = Uuid::new_v4().to_string(); - - // NODE DIRECTORY - let node_directory = format!("{}/{}/{}", self.data_dir, self.config.network, node_id); - fs::create_dir_all(node_directory)?; - // NODE ENTROPY let entropy = match entropy { Some(entropy_hex) => { @@ -826,6 +818,18 @@ impl AdminService { let encrypted_cross_node_entropy = LightningNode::encrypt_entropy(&cross_node_entropy, passphrase.as_bytes())?; + let seed = LightningNode::get_seed_from_entropy(self.config.network, &entropy); + + // NODE PUBKEY + let node_pubkey = LightningNode::get_node_pubkey_from_seed(&seed); + + // NODE ID + let node_id = node_pubkey.clone(); + + // NODE DIRECTORY + let node_directory = format!("{}/{}/{}", self.data_dir, self.config.network, node_id); + fs::create_dir_all(node_directory)?; + let entropy_active_model = self .database .get_entropy_active_model(node_id.clone(), encrypted_entropy); @@ -834,14 +838,9 @@ impl AdminService { .database .get_cross_node_entropy_active_model(node_id.clone(), encrypted_cross_node_entropy); - let seed = LightningNode::get_seed_from_entropy(self.config.network, &entropy); - - // NODE PUBKEY - let node_pubkey = LightningNode::get_node_pubkey_from_seed(&seed); - // NODE MACAROON let (macaroon, macaroon_id) = - LightningNode::generate_macaroon(&entropy, node_pubkey.clone(), "*".to_string())?; + LightningNode::generate_macaroon(&seed, node_pubkey, "*".to_string())?; let encrypted_macaroon = LightningNode::encrypt_macaroon(&macaroon, passphrase.as_bytes())?; @@ -858,7 +857,6 @@ impl AdminService { // NODE let active_node = entity::node::ActiveModel { id: ActiveValue::Set(node_id.clone()), - pubkey: ActiveValue::Set(node_pubkey.clone()), username: ActiveValue::Set(username.clone()), alias: ActiveValue::Set(alias.clone()), network: ActiveValue::Set(self.config.network.to_string()), @@ -878,7 +876,6 @@ impl AdminService { network: self.config.network.to_string(), listen_addr, listen_port, - pubkey: node_pubkey, created_at: now, updated_at: now, status: node::NodeStatus::Stopped.into(), @@ -950,7 +947,7 @@ impl AdminService { ) -> Result<(), crate::error::Error> { let status = { let mut node_directory = self.node_directory.lock().await; - match node_directory.entry(node.pubkey.clone()) { + match node_directory.entry(node.id.clone()) { Entry::Vacant(entry) => { entry.insert(None); None @@ -988,14 +985,14 @@ impl AdminService { println!( "starting {}@{}:{}", - node.pubkey.clone(), + node.id.clone(), self.config.api_host.clone(), node.listen_port ); { let mut node_directory = self.node_directory.lock().await; - if let Entry::Occupied(mut entry) = node_directory.entry(node.pubkey.clone()) { + if let Entry::Occupied(mut entry) = node_directory.entry(node.id.clone()) { entry.insert(Some(NodeHandle { node: Arc::new(lightning_node.clone()), background_processor, diff --git a/senseicore/src/services/node.rs b/senseicore/src/services/node.rs index 0f5f42e..468ba26 100644 --- a/senseicore/src/services/node.rs +++ b/senseicore/src/services/node.rs @@ -214,6 +214,7 @@ pub enum NodeRequest { GetPhantomInvoice { amt_msat: u64, description: String, + phantom_route_hints_hex: Vec, }, LabelPayment { label: String, @@ -261,19 +262,6 @@ pub enum NodeRequest { RemoveKnownPeer { pubkey: String, }, - ListClusterNodes { - pagination: PaginationRequest, - }, - AddClusterNode { - pubkey: String, - label: String, - host: String, - port: u16, - macaroon_hex: String, - }, - RemoveClusterNode { - pubkey: String, - }, } #[derive(Serialize)] @@ -353,12 +341,6 @@ pub enum NodeResponse { }, AddKnownPeer {}, RemoveKnownPeer {}, - ListClusterNodes { - cluster_nodes: Vec, - pagination: PaginationResponse, - }, - AddClusterNode {}, - RemoveClusterNode {}, Error(NodeRequestError), } diff --git a/senseicore/tests/smoke_test.rs b/senseicore/tests/smoke_test.rs index 93f614d..8774bd0 100644 --- a/senseicore/tests/smoke_test.rs +++ b/senseicore/tests/smoke_test.rs @@ -70,8 +70,8 @@ mod test { start: bool, entropy: Option, cross_node_entropy: Option, - ) -> Arc { - let node_pubkey = match admin_service + ) -> (Arc, String, String) { + let (node_pubkey, entropy, cross_node_entropy) = match admin_service .call(AdminRequest::CreateNode { username: String::from(username), passphrase: String::from(passphrase), @@ -89,16 +89,17 @@ mod test { listen_port: _, pubkey, macaroon: _, - entropy: _, - cross_node_entropy: _, - } => Some(pubkey), + entropy, + cross_node_entropy, + } => Some((pubkey, entropy, cross_node_entropy)), _ => None, } .unwrap(); let directory = admin_service.node_directory.lock().await; let handle = directory.get(&node_pubkey).unwrap(); - handle.as_ref().unwrap().node.clone() + let node = handle.as_ref().unwrap().node.clone(); + (node, entropy, cross_node_entropy) } async fn create_admin_account( @@ -264,6 +265,17 @@ mod test { .unwrap() } + async fn get_channel_balance_sats(node: Arc) -> u64 { + match node.call(NodeRequest::GetBalance {}).await.unwrap() { + NodeResponse::GetBalance { + channel_balance_msats, + .. + } => Some(channel_balance_msats / 1000), + _ => None, + } + .unwrap() + } + async fn open_channels( bitcoind: &BitcoinD, from: Arc, @@ -465,6 +477,42 @@ mod test { .clone() } + async fn create_phantom_invoice( + node: Arc, + cluster: Vec>, + amt_sat: u64, + ) -> String { + let mut phantom_route_hints_hex = vec![]; + for cluster_node in cluster.iter() { + let hint = match cluster_node + .call(NodeRequest::GetPhantomRouteHints {}) + .await + .unwrap() + { + NodeResponse::GetPhantomRouteHints { + phantom_route_hints_hex, + } => Some(phantom_route_hints_hex), + _ => None, + } + .unwrap(); + phantom_route_hints_hex.push(hint); + } + + match node + .call(NodeRequest::GetPhantomInvoice { + amt_msat: amt_sat * 1000, + description: String::from("test"), + phantom_route_hints_hex, + }) + .await + .unwrap() + { + NodeResponse::GetPhantomInvoice { invoice } => Some(invoice), + _ => None, + } + .unwrap() + } + async fn create_invoice(node: Arc, amt_sat: u64) -> String { match node .call(NodeRequest::GetInvoice { @@ -629,11 +677,67 @@ mod test { }) } + async fn phantom_payment_test(bitcoind: BitcoinD, admin_service: AdminService) { + let _admin_token = create_admin_account(&admin_service, "admin", "admin").await; + let (alice, _alice_entropy, alice_cross_node_entropy) = + create_node(&admin_service, "alice", "alice", true, None, None).await; + let (bob, ..) = create_node( + &admin_service, + "bob", + "bob", + true, + None, + Some(alice_cross_node_entropy), + ) + .await; + + let cluster = vec![alice.clone(), bob.clone()]; + + let (charlie, ..) = + create_node(&admin_service, "charlie", "charlie", true, None, None).await; + + fund_node(&bitcoind, charlie.clone()).await; + + let _charlie_bob_channel = + open_channel(&bitcoind, charlie.clone(), bob.clone(), 1_000_000).await; + + let phantom_invoice = create_phantom_invoice(alice, cluster, 5000).await; + + let bob_start_balance = get_channel_balance_sats(bob.clone()).await; + + // charlie only has a channel to bob but should be able to pay alice's invoice + pay_invoice(charlie.clone(), phantom_invoice).await; + + let charlie_test = charlie.clone(); + let has_payments = move || { + let pagination = PaginationRequest { + page: 0, + take: 1, + query: None, + }; + let filter = PaymentsFilter { + status: Some(HTLCStatus::Succeeded.to_string()), + origin: None, + }; + let (_payments, pagination) = charlie_test + .database + .list_payments_sync(charlie_test.id.clone(), pagination, filter) + .unwrap(); + pagination.total == 1 as u64 + }; + + assert!(wait_until(has_payments, 60000, 500).await); + + let bob_balance = get_channel_balance_sats(bob.clone()).await; + assert!(bob_balance > bob_start_balance); + } + async fn smoke_test(bitcoind: BitcoinD, admin_service: AdminService) { let _admin_token = create_admin_account(&admin_service, "admin", "admin").await; - let alice = create_node(&admin_service, "alice", "alice", true, None, None).await; - let bob = create_node(&admin_service, "bob", "bob", true, None, None).await; - let charlie = create_node(&admin_service, "charlie", "charlie", true, None, None).await; + let (alice, ..) = create_node(&admin_service, "alice", "alice", true, None, None).await; + let (bob, ..) = create_node(&admin_service, "bob", "bob", true, None, None).await; + let (charlie, ..) = + create_node(&admin_service, "charlie", "charlie", true, None, None).await; fund_node(&bitcoind, alice.clone()).await; fund_node(&bitcoind, bob.clone()).await; let alice_bob_channel = @@ -739,10 +843,11 @@ mod test { async fn batch_open_channels_test(bitcoind: BitcoinD, admin_service: AdminService) { let _admin_token = create_admin_account(&admin_service, "admin", "admin").await; - let alice = create_node(&admin_service, "alice", "alice", true, None, None).await; - let bob = create_node(&admin_service, "bob", "bob", true, None, None).await; - let charlie = create_node(&admin_service, "charlie", "charlie", true, None, None).await; - let doug = create_node(&admin_service, "doug", "doug", true, None, None).await; + let (alice, ..) = create_node(&admin_service, "alice", "alice", true, None, None).await; + let (bob, ..) = create_node(&admin_service, "bob", "bob", true, None, None).await; + let (charlie, ..) = + create_node(&admin_service, "charlie", "charlie", true, None, None).await; + let (doug, ..) = create_node(&admin_service, "doug", "doug", true, None, None).await; fund_node(&bitcoind, alice.clone()).await; let alice_channels_with_counterparties = open_channels( @@ -809,4 +914,10 @@ mod test { fn run_smoke_test() { run_test("smoke_test", smoke_test) } + + #[test] + #[serial] + fn run_phantom_payment_test() { + run_test("phantom_payment", phantom_payment_test) + } } diff --git a/src/grpc/adaptor.rs b/src/grpc/adaptor.rs index f72d9f8..cafa0dc 100644 --- a/src/grpc/adaptor.rs +++ b/src/grpc/adaptor.rs @@ -8,17 +8,15 @@ // licenses. use super::sensei::{ - self, AddClusterNodeRequest, AddClusterNodeResponse, AddKnownPeerRequest, AddKnownPeerResponse, - Channel as ChannelMessage, ClusterNode, CreatePhantomInvoiceRequest, - CreatePhantomInvoiceResponse, DeletePaymentRequest, DeletePaymentResponse, Info as InfoMessage, - KnownPeer, LabelPaymentRequest, LabelPaymentResponse, ListClusterNodesRequest, - ListClusterNodesResponse, ListKnownPeersRequest, ListKnownPeersResponse, - NetworkGraphInfoRequest, NetworkGraphInfoResponse, - OpenChannelRequest as GrpcOpenChannelRequest, OpenChannelsRequest, OpenChannelsResponse, - PaginationRequest, PaginationResponse, Payment as PaymentMessage, PaymentsFilter, - Peer as PeerMessage, RemoveClusterNodeRequest, RemoveClusterNodeResponse, - RemoveKnownPeerRequest, RemoveKnownPeerResponse, StartNodeRequest, StartNodeResponse, - StopNodeRequest, StopNodeResponse, Utxo as UtxoMessage, + self, AddKnownPeerRequest, AddKnownPeerResponse, Channel as ChannelMessage, + CreatePhantomInvoiceRequest, CreatePhantomInvoiceResponse, DeletePaymentRequest, + DeletePaymentResponse, GetPhantomRouteHintsRequest, GetPhantomRouteHintsResponse, + Info as InfoMessage, KnownPeer, LabelPaymentRequest, LabelPaymentResponse, + ListKnownPeersRequest, ListKnownPeersResponse, NetworkGraphInfoRequest, + NetworkGraphInfoResponse, OpenChannelRequest as GrpcOpenChannelRequest, OpenChannelsRequest, + OpenChannelsResponse, PaginationRequest, PaginationResponse, Payment as PaymentMessage, + PaymentsFilter, Peer as PeerMessage, RemoveKnownPeerRequest, RemoveKnownPeerResponse, + StartNodeRequest, StartNodeResponse, StopNodeRequest, StopNodeResponse, Utxo as UtxoMessage, }; use super::sensei::{ @@ -94,6 +92,7 @@ impl From for ChannelMessage { impl From for PaymentMessage { fn from(payment: entity::payment::Model) -> Self { Self { + node_id: payment.node_id, hash: payment.payment_hash, preimage: payment.preimage, secret: payment.secret, @@ -103,6 +102,8 @@ impl From for PaymentMessage { origin: payment.origin, label: payment.label, invoice: payment.invoice, + created_by_node_id: payment.created_by_node_id, + received_by_node_id: payment.received_by_node_id, } } } @@ -377,6 +378,7 @@ impl From for NodeRequest { NodeRequest::GetPhantomInvoice { amt_msat: req.amt_msat, description: req.description, + phantom_route_hints_hex: req.phantom_route_hints_hex, } } } @@ -392,6 +394,27 @@ impl TryFrom for CreatePhantomInvoiceResponse { } } +impl From for NodeRequest { + fn from(_req: GetPhantomRouteHintsRequest) -> Self { + NodeRequest::GetPhantomRouteHints {} + } +} + +impl TryFrom for GetPhantomRouteHintsResponse { + type Error = String; + + fn try_from(res: NodeResponse) -> Result { + match res { + NodeResponse::GetPhantomRouteHints { + phantom_route_hints_hex, + } => Ok(Self { + phantom_route_hints_hex, + }), + _ => Err("impossible".to_string()), + } + } +} + impl From for NodeRequest { fn from(req: LabelPaymentRequest) -> Self { NodeRequest::LabelPayment { @@ -735,86 +758,3 @@ impl TryFrom for RemoveKnownPeerResponse { } } } - -impl From for ClusterNode { - fn from(cluster_node: entity::cluster_node::Model) -> Self { - Self { - pubkey: cluster_node.pubkey, - label: cluster_node.label, - host: cluster_node.host, - port: cluster_node.port as u32, - macaroon_hex: cluster_node.macaroon_hex, - } - } -} - -impl From for NodeRequest { - fn from(req: ListClusterNodesRequest) -> Self { - NodeRequest::ListClusterNodes { - pagination: req.pagination.map(|p| p.into()).unwrap_or_default(), - } - } -} - -impl TryFrom for ListClusterNodesResponse { - type Error = String; - - fn try_from(res: NodeResponse) -> Result { - match res { - NodeResponse::ListClusterNodes { - cluster_nodes, - pagination, - } => { - let pagination: PaginationResponse = pagination.into(); - Ok(Self { - cluster_nodes: cluster_nodes - .into_iter() - .map(|cluster_node| cluster_node.into()) - .collect::>(), - pagination: Some(pagination), - }) - } - _ => Err("impossible".to_string()), - } - } -} - -impl From for NodeRequest { - fn from(req: AddClusterNodeRequest) -> Self { - NodeRequest::AddClusterNode { - pubkey: req.pubkey, - label: req.label, - host: req.host, - port: req.port as u16, - macaroon_hex: req.macaroon_hex, - } - } -} - -impl TryFrom for AddClusterNodeResponse { - type Error = String; - - fn try_from(res: NodeResponse) -> Result { - match res { - NodeResponse::AddClusterNode {} => Ok(Self {}), - _ => Err("impossible".to_string()), - } - } -} - -impl From for NodeRequest { - fn from(req: RemoveClusterNodeRequest) -> Self { - NodeRequest::RemoveClusterNode { pubkey: req.pubkey } - } -} - -impl TryFrom for RemoveClusterNodeResponse { - type Error = String; - - fn try_from(res: NodeResponse) -> Result { - match res { - NodeResponse::RemoveClusterNode {} => Ok(Self {}), - _ => Err("impossible".to_string()), - } - } -} diff --git a/src/grpc/admin.rs b/src/grpc/admin.rs index 3d841b0..c05add9 100644 --- a/src/grpc/admin.rs +++ b/src/grpc/admin.rs @@ -61,7 +61,7 @@ impl TryFrom for ListNodesResponse { nodes: nodes .into_iter() .map(|node| ListNode { - id: node.id, + id: node.id.clone(), created_at: node.created_at, updated_at: node.updated_at, role: node.role as u32, @@ -70,7 +70,7 @@ impl TryFrom for ListNodesResponse { network: node.network, listen_addr: node.listen_addr, listen_port: node.listen_port as u32, - pubkey: node.pubkey, + pubkey: node.id, status: node.status as u32, }) .collect::>(), diff --git a/src/grpc/node.rs b/src/grpc/node.rs index 7b71f19..1e39a84 100644 --- a/src/grpc/node.rs +++ b/src/grpc/node.rs @@ -13,22 +13,20 @@ pub use super::sensei::node_server::{Node, NodeServer}; use super::{ sensei::{ - AddClusterNodeRequest, AddClusterNodeResponse, AddKnownPeerRequest, AddKnownPeerResponse, - CloseChannelRequest, CloseChannelResponse, ConnectPeerRequest, ConnectPeerResponse, - CreateInvoiceRequest, CreateInvoiceResponse, CreatePhantomInvoiceRequest, - CreatePhantomInvoiceResponse, DecodeInvoiceRequest, DecodeInvoiceResponse, - DeletePaymentRequest, DeletePaymentResponse, GetBalanceRequest, GetBalanceResponse, + AddKnownPeerRequest, AddKnownPeerResponse, CloseChannelRequest, CloseChannelResponse, + ConnectPeerRequest, ConnectPeerResponse, CreateInvoiceRequest, CreateInvoiceResponse, + CreatePhantomInvoiceRequest, CreatePhantomInvoiceResponse, DecodeInvoiceRequest, + DecodeInvoiceResponse, DeletePaymentRequest, DeletePaymentResponse, GetBalanceRequest, + GetBalanceResponse, GetPhantomRouteHintsRequest, GetPhantomRouteHintsResponse, GetUnusedAddressRequest, GetUnusedAddressResponse, InfoRequest, InfoResponse, KeysendRequest, KeysendResponse, LabelPaymentRequest, LabelPaymentResponse, - ListChannelsRequest, ListChannelsResponse, ListClusterNodesRequest, - ListClusterNodesResponse, ListKnownPeersRequest, ListKnownPeersResponse, + ListChannelsRequest, ListChannelsResponse, ListKnownPeersRequest, ListKnownPeersResponse, ListPaymentsRequest, ListPaymentsResponse, ListPeersRequest, ListPeersResponse, ListUnspentRequest, ListUnspentResponse, NetworkGraphInfoRequest, NetworkGraphInfoResponse, OpenChannelsRequest, OpenChannelsResponse, PayInvoiceRequest, PayInvoiceResponse, - RemoveClusterNodeRequest, RemoveClusterNodeResponse, RemoveKnownPeerRequest, - RemoveKnownPeerResponse, SignMessageRequest, SignMessageResponse, StartNodeRequest, - StartNodeResponse, StopNodeRequest, StopNodeResponse, VerifyMessageRequest, - VerifyMessageResponse, + RemoveKnownPeerRequest, RemoveKnownPeerResponse, SignMessageRequest, SignMessageResponse, + StartNodeRequest, StartNodeResponse, StopNodeRequest, StopNodeResponse, + VerifyMessageRequest, VerifyMessageResponse, }, utils::raw_macaroon_from_metadata, }; @@ -217,6 +215,16 @@ impl Node for NodeService { .map(Response::new) .map_err(|_e| Status::unknown("unknown error")) } + async fn get_phantom_route_hints( + &self, + request: tonic::Request, + ) -> Result, Status> { + self.authenticated_request(request.metadata().clone(), request.into_inner().into()) + .await? + .try_into() + .map(Response::new) + .map_err(|_e| Status::unknown("unknown error")) + } async fn label_payment( &self, request: tonic::Request, @@ -367,34 +375,4 @@ impl Node for NodeService { .map(Response::new) .map_err(|_e| Status::unknown("unknown error")) } - async fn list_cluster_nodes( - &self, - request: tonic::Request, - ) -> Result, tonic::Status> { - self.authenticated_request(request.metadata().clone(), request.into_inner().into()) - .await? - .try_into() - .map(Response::new) - .map_err(|_e| Status::unknown("unknown error")) - } - async fn add_cluster_node( - &self, - request: tonic::Request, - ) -> Result, tonic::Status> { - self.authenticated_request(request.metadata().clone(), request.into_inner().into()) - .await? - .try_into() - .map(Response::new) - .map_err(|_e| Status::unknown("unknown error")) - } - async fn remove_cluster_node( - &self, - request: tonic::Request, - ) -> Result, tonic::Status> { - self.authenticated_request(request.metadata().clone(), request.into_inner().into()) - .await? - .try_into() - .map(Response::new) - .map_err(|_e| Status::unknown("unknown error")) - } } diff --git a/src/http/admin.rs b/src/http/admin.rs index d1943f7..3690a9a 100644 --- a/src/http/admin.rs +++ b/src/http/admin.rs @@ -747,7 +747,7 @@ pub async fn login_node( match node { Some(node) => { let request = AdminRequest::StartNode { - pubkey: node.pubkey.clone(), + pubkey: node.id.clone(), passphrase: params.passphrase, }; match admin_service.call(request).await { @@ -759,7 +759,7 @@ pub async fn login_node( .finish(); cookies.add(macaroon_cookie); Ok(Json(json!({ - "pubkey": node.pubkey, + "pubkey": node.id, "alias": node.alias, "macaroon": macaroon, "role": node.role as u16 diff --git a/src/http/node.rs b/src/http/node.rs index 4b17f46..72a87bf 100644 --- a/src/http/node.rs +++ b/src/http/node.rs @@ -19,8 +19,7 @@ use http::{HeaderValue, StatusCode}; use senseicore::services::admin::AdminRequest; use senseicore::services::node::{NodeRequest, NodeRequestError, NodeResponse, OpenChannelRequest}; use senseicore::services::{ - ListChannelsParams, ListClusterNodesParams, ListKnownPeersParams, ListPaymentsParams, - ListTransactionsParams, + ListChannelsParams, ListKnownPeersParams, ListPaymentsParams, ListTransactionsParams, }; use senseicore::utils; use serde::Deserialize; @@ -48,6 +47,7 @@ impl From for NodeRequest { pub struct GetPhantomInvoiceParams { pub amt_msat: u64, pub description: String, + pub phantom_route_hints_hex: Vec, } impl From for NodeRequest { @@ -55,6 +55,7 @@ impl From for NodeRequest { Self::GetPhantomInvoice { amt_msat: params.amt_msat, description: params.description, + phantom_route_hints_hex: params.phantom_route_hints_hex, } } } @@ -240,40 +241,6 @@ impl From for NodeRequest { } } -#[derive(Deserialize)] -pub struct AddClusterNodeParams { - pub pubkey: String, - pub label: String, - pub host: String, - pub port: u16, - pub macaroon_hex: String, -} - -impl From for NodeRequest { - fn from(params: AddClusterNodeParams) -> Self { - Self::AddClusterNode { - pubkey: params.pubkey, - label: params.label, - host: params.host, - port: params.port, - macaroon_hex: params.macaroon_hex, - } - } -} - -#[derive(Deserialize)] -pub struct RemoveClusterNodeParams { - pub pubkey: String, -} - -impl From for NodeRequest { - fn from(params: RemoveClusterNodeParams) -> Self { - Self::RemoveClusterNode { - pubkey: params.pubkey, - } - } -} - pub fn add_routes(router: Router) -> Router { router .route("/v1/node/payments", get(handle_get_payments)) @@ -302,9 +269,6 @@ pub fn add_routes(router: Router) -> Router { .route("/v1/node/known-peers", get(list_known_peers)) .route("/v1/node/known-peers", post(add_known_peer)) .route("/v1/node/known-peers", delete(remove_known_peer)) - .route("/v1/node/cluster-nodes", get(list_cluster_nodes)) - .route("/v1/node/cluster-nodes", post(add_cluster_node)) - .route("/v1/node/cluster-nodes", delete(remove_cluster_node)) .route("/v1/node/ldk/phantom-route-hints", get(phantom_route_hints)) } @@ -313,6 +277,7 @@ pub async fn phantom_route_hints( AuthHeader { macaroon, token: _ }: AuthHeader, cookies: Cookies, ) -> Result, Response> { + println!("received request for phantom route hints"); handle_authenticated_request( admin_service, NodeRequest::GetPhantomRouteHints {}, @@ -765,48 +730,3 @@ pub async fn remove_known_peer( }?; handle_authenticated_request(admin_service, request, macaroon, cookies).await } - -pub async fn list_cluster_nodes( - Extension(admin_service): Extension>, - Query(params): Query, - AuthHeader { macaroon, token: _ }: AuthHeader, - cookies: Cookies, -) -> Result, Response> { - let request = NodeRequest::ListClusterNodes { - pagination: params.clone().into(), - }; - - handle_authenticated_request(admin_service, request, macaroon, cookies).await -} - -pub async fn add_cluster_node( - Extension(admin_service): Extension>, - Json(payload): Json, - AuthHeader { macaroon, token: _ }: AuthHeader, - cookies: Cookies, -) -> Result, Response> { - let request = { - let params: Result = serde_json::from_value(payload); - match params { - Ok(params) => Ok(params.into()), - Err(_) => Err((StatusCode::UNPROCESSABLE_ENTITY, "invalid params").into_response()), - } - }?; - handle_authenticated_request(admin_service, request, macaroon, cookies).await -} - -pub async fn remove_cluster_node( - Extension(admin_service): Extension>, - Json(payload): Json, - AuthHeader { macaroon, token: _ }: AuthHeader, - cookies: Cookies, -) -> Result, Response> { - let request = { - let params: Result = serde_json::from_value(payload); - match params { - Ok(params) => Ok(params.into()), - Err(_) => Err((StatusCode::UNPROCESSABLE_ENTITY, "invalid params").into_response()), - } - }?; - handle_authenticated_request(admin_service, request, macaroon, cookies).await -}