Skip to content

Commit

Permalink
feat: bolt12 support in submarine swaps
Browse files Browse the repository at this point in the history
  • Loading branch information
michael1011 committed Sep 12, 2024
1 parent 684d768 commit 57b1b0f
Show file tree
Hide file tree
Showing 45 changed files with 5,411 additions and 1,498 deletions.
657 changes: 397 additions & 260 deletions boltzr/Cargo.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions boltzr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ async-tungstenite = { version = "0.27.0", features = ["tokio-native-tls", "tokio
async-trait = "0.1.81"
futures-util = "0.3.30"
async-stream = "0.3.5"
anyhow = "1.0.87"
lightning = { version = "0.0.124", features = ["std"] }
lightning-invoice = { version = "0.32.0", features = ["std"] }
bech32 = "0.9.1"

[build-dependencies]
built = { version = "0.7.4", features = ["git2"] }
Expand Down
6 changes: 6 additions & 0 deletions boltzr/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ fn main() {
.protoc_arg("--experimental_allow_proto3_optional")
.compile(&["protos/boltzr.proto"], &["protos"])
.unwrap_or_else(|e| panic!("Could not build protos: {}", e));

tonic_build::configure()
.protoc_arg("--experimental_allow_proto3_optional")
.compile(&["../proto/cln/node.proto"], &["../proto"])
.unwrap_or_else(|e| panic!("Could not build CLN protos: {}", e));

built::write_built_file()
.unwrap_or_else(|e| panic!("Failed to acquire build-time information: {}", e));
}
93 changes: 93 additions & 0 deletions boltzr/protos/boltzr.proto
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ service BoltzR {
rpc SendWebHook (SendWebHookRequest) returns (SendWebHookResponse);

rpc SignEvmRefund (SignEvmRefundRequest) returns (SignEvmRefundResponse);

rpc DecodeInvoiceOrOffer (DecodeInvoiceOrOfferRequest) returns (DecodeInvoiceOrOfferResponse);
rpc FetchInvoice (FetchInvoiceRequest) returns (FetchInvoiceResponse);
}

message GetInfoRequest {}
Expand Down Expand Up @@ -101,3 +104,93 @@ message SignEvmRefundRequest {
message SignEvmRefundResponse {
bytes signature = 1;
}

message DecodeInvoiceOrOfferRequest {
string invoice_or_offer = 1;
}

enum Feature {
BASIC_MPP = 0;
}

message Bolt11Invoice {
bytes payee_pubkey = 1;
optional uint64 msat = 2;
bytes payment_hash = 3;

oneof description {
string memo = 4;
bytes description_hash = 5;
}

uint64 created_at = 6;
uint64 expiry = 7;
uint64 min_final_cltv_expiry = 8;

message RoutingHints {
message RoutingHint {
bytes node = 1;
uint64 channel_id = 2;

uint32 base_fee_msat = 3;
uint32 ppm_fee = 4;

uint64 cltv_expiry_delta = 5;
optional uint64 htlc_minimum_msat = 6;
optional uint64 htlc_maximum_msat = 7;
}

repeated RoutingHint hops = 1;
}

repeated RoutingHints hints = 9;
repeated Feature features = 10;
}

message Bolt12Offer {
bytes id = 1;
optional bytes signing_pubkey = 2;
optional string description = 3;
optional uint64 min_amount_msat = 4;
}

message Bolt12Invoice {
bytes signing_pubkey = 1;
optional uint64 msat = 2;
bytes payment_hash = 3;
optional string description = 4;
uint64 created_at = 5;
uint64 expiry = 6;

message Path {
optional bytes first_node_pubkey = 1;

uint32 base_fee_msat = 2;
uint32 ppm_fee = 3;

uint64 cltv_expiry_delta = 4;
}

repeated Path paths = 7;
repeated Feature features = 8;
}

message DecodeInvoiceOrOfferResponse {
bool is_expired = 1;

oneof decoded {
Bolt11Invoice bolt11 = 2;
Bolt12Offer offer = 3;
Bolt12Invoice bolt12_invoice = 4;
}
}

message FetchInvoiceRequest {
string currency = 1;
string offer = 2;
uint64 amount_msat = 3;
}

message FetchInvoiceResponse {
string invoice = 1;
}
7 changes: 7 additions & 0 deletions boltzr/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ use std::fs;
use std::path::Path;
use tracing::{debug, info, trace};

#[derive(Deserialize, Serialize, PartialEq, Clone, Debug)]
pub struct CurrencyConfig {
pub symbol: String,
pub cln: Option<crate::lightning::cln::Config>,
}

#[derive(Deserialize, Serialize, PartialEq, Clone, Debug)]
pub struct Config {
#[serde(rename = "dataDir")]
Expand Down Expand Up @@ -40,6 +46,7 @@ pub struct GlobalConfig {
pub mnemonic_path: Option<String>,

pub postgres: crate::db::Config,
pub currencies: Option<Vec<CurrencyConfig>>,
pub rsk: Option<crate::evm::Config>,

pub notification: Option<crate::notifications::Config>,
Expand Down
39 changes: 39 additions & 0 deletions boltzr/src/currencies.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use crate::config::CurrencyConfig;
use crate::lightning::cln::Cln;
use std::collections::HashMap;
use tracing::{debug, warn};

#[derive(Debug, Clone)]
pub struct Currency {
pub cln: Option<Cln>,
}

pub type Currencies = HashMap<String, Currency>;

pub async fn connect_nodes(currencies: Option<Vec<CurrencyConfig>>) -> anyhow::Result<Currencies> {
let mut curs = HashMap::new();

match currencies {
Some(currencies) => {
for currency in currencies {
debug!("Connecting to nodes of {}", currency.symbol);

let cln = match currency.cln.clone() {
Some(config) => {
let mut cln = Cln::new(&currency.symbol, config).await?;
cln.connect().await?;
Some(cln)
}
None => None,
};

curs.insert(currency.symbol.clone(), Currency { cln });
}
}
None => {
warn!("No currencies are configured");
}
}

Ok(curs)
}
10 changes: 10 additions & 0 deletions boltzr/src/grpc/server.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::currencies::Currencies;
use crate::db::helpers::web_hook::WebHookHelper;
use crate::evm::refund_signer::RefundSigner;
use crate::grpc::service::boltzr::boltz_r_server::BoltzRServer;
Expand Down Expand Up @@ -32,6 +33,8 @@ pub struct Config {
pub struct Server<W, N> {
config: Config,

currencies: Currencies,

web_hook_helper: Box<W>,
web_hook_caller: Caller,

Expand All @@ -49,9 +52,11 @@ where
W: WebHookHelper + Send + Sync + Clone + 'static,
N: NotificationClient + Send + Sync + 'static,
{
#[allow(clippy::too_many_arguments)]
pub fn new(
cancellation_token: CancellationToken,
config: Config,
currencies: Currencies,
swap_status_update_tx: tokio::sync::broadcast::Sender<Vec<SwapStatus>>,
web_hook_helper: Box<W>,
web_hook_caller: Caller,
Expand All @@ -60,6 +65,7 @@ where
) -> Self {
Server {
config,
currencies,
refund_signer,
web_hook_helper,
web_hook_caller,
Expand All @@ -85,6 +91,7 @@ where
Arc::new(Default::default());

let service = BoltzService::new(
self.currencies.clone(),
self.status_fetcher.clone(),
self.swap_status_update_tx.clone(),
Arc::new(self.web_hook_helper.clone()),
Expand Down Expand Up @@ -147,6 +154,7 @@ mod server_test {
use crate::ws;
use alloy::primitives::{Address, FixedBytes, Signature, U256};
use mockall::{mock, predicate::*};
use std::collections::HashMap;
use std::error::Error;
use std::fs;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -200,6 +208,7 @@ mod server_test {
certificates: None,
disable_ssl: Some(true),
},
HashMap::new(),
status_tx,
Box::new(make_mock_hook_helper()),
caller::Caller::new(
Expand Down Expand Up @@ -325,6 +334,7 @@ mod server_test {
certificates: Some(certs_dir.clone().to_str().unwrap().to_string()),
disable_ssl: Some(false),
},
HashMap::new(),
status_tx,
Box::new(make_mock_hook_helper()),
caller::Caller::new(
Expand Down
Loading

0 comments on commit 57b1b0f

Please sign in to comment.