Skip to content

Commit

Permalink
wip: Add submarine swap daemon
Browse files Browse the repository at this point in the history
* add new bifrost messages for new lnpbp feature "swap".
* implement `swapd` for performing swap.
* launch `swapd` from `lnpd` and enable user to perform swap via RPC.
  • Loading branch information
joemphilips committed Feb 14, 2023
1 parent 35f921e commit 7b8ccdd
Show file tree
Hide file tree
Showing 26 changed files with 1,211 additions and 96 deletions.
4 changes: 0 additions & 4 deletions Cargo.lock

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

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ required-features = ["server"]
name = "signd"
required-features = ["server"]

[[bin]]
name = "swapd"
required-features = ["server"]

[dependencies]
# LNP/BP crates
amplify = "3.13.0"
Expand Down Expand Up @@ -120,3 +124,6 @@ tor = ["microservices/tor", "internet2/tor"]

[package.metadata.configure_me]
spec = "config_spec.toml"

[patch.crates-io]
lnp-core = { path = "../lnp-core" }
8 changes: 8 additions & 0 deletions cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ impl Command {
Command::Open { .. } => s!("Opening channel"),
Command::Invoice { .. } => s!("Creating invoice"),
Command::Pay { .. } => s!("Paying invoice"),
Command::SwapIn { .. } => s!("perform loop-in swap"),
Command::SwapOut { .. } => s!("perform loop-out swap"),
}
}
}
Expand Down Expand Up @@ -161,6 +163,12 @@ impl Exec for Opts {
)?;
runtime.report_progress()?;
}
Command::SwapIn { amount_asset, address } => {
todo!()
}
Command::SwapOut { amount_asset, node, .. } => {
todo!()
}
}
Ok(())
}
Expand Down
5 changes: 5 additions & 0 deletions cli/src/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,11 @@ pub enum Command {
/// amount. Overrides amount provided by the invoice.
amount_msat: Option<u64>,
},

/// perform loop in swap
SwapIn { amount_asset: AmountOfAsset, address: String },
/// perform loop out swap
SwapOut { node: NodeId, amount_asset: AmountOfAsset, max_swap_fee: u64 },
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error, From)]
Expand Down
3 changes: 3 additions & 0 deletions rpc/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ pub enum FailureCode {
/// LNPD-related error
Lnpd = 0x010,

/// SWAPD-related error
Swap = 0x40,

/// Error coming from other ESB interface reported to a different sservice
Nested = 0xFFE,
}
Expand Down
36 changes: 35 additions & 1 deletion rpc/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use lightning_invoice::Invoice;
use lnp::addr::LnpAddr;
use lnp::channel::bolt::{AssetsBalance, ChannelState, CommonParams, PeerParams};
use lnp::p2p::bolt::{ChannelId, ChannelType};
use lnpbp::chain::AssetId;
use lnpbp::chain::{AssetId, Chain};
use microservices::esb::ClientId;
use microservices::rpc;
use microservices::util::OptionDetails;
Expand Down Expand Up @@ -130,12 +130,46 @@ pub enum RpcMsg {
#[display("funds_info({0})", alt = "{0:#}")]
#[from]
FundsInfo(FundsInfo),

#[display("swap_in({0})", alt = "{0:#}")]
#[from]
SwapIn(SwapIn),

#[display("swap_out({0})", alt = "{0:#}")]
#[from]
SwapOut(SwapOut),
}

impl RpcMsg {
pub fn success() -> Self { RpcMsg::Success(OptionDetails::new()) }
}

#[derive(Clone, PartialEq, Eq, Debug, Display, NetworkEncode, NetworkDecode)]
#[display(Debug)]
pub enum NodeOrChannelId {
NodeId(NodeId),
ChannelId(ChannelId),
}

#[derive(Clone, PartialEq, Eq, Debug, Display, NetworkEncode, NetworkDecode)]
#[display(Debug)]
pub struct SwapIn {
pub amount: u64,
pub asset: Option<AssetId>,
pub address: String,
pub node_or_chan_id: NodeOrChannelId,
}

#[derive(Clone, PartialEq, Eq, Debug, Display, NetworkEncode, NetworkDecode)]
#[display("swapout({amount}, {chain}, ...)")]
pub struct SwapOut {
pub amount: u64,
pub asset: Option<AssetId>,
pub chain: Chain,
pub node_or_chan_id: NodeOrChannelId,
pub max_swap_fee: u64,
}

/// Request to create channel originating from a client
#[derive(Clone, PartialEq, Eq, Debug, Display, NetworkEncode, NetworkDecode)]
#[display("{remote_peer}, {funding_sat}, ...")]
Expand Down
10 changes: 9 additions & 1 deletion rpc/src/service_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use std::str::FromStr;

use internet2::addr::NodeId;
use lnp::p2p::bifrost::BifrostApp;
use lnp::p2p::bifrost::{BifrostApp, SwapId};
use lnp::p2p::bolt::{ChannelId, TempChannelId};
use microservices::esb::{self, ClientId, ServiceName};
use strict_encoding::{strict_deserialize, strict_serialize};
Expand Down Expand Up @@ -68,6 +68,14 @@ pub enum ServiceId {
#[strict_encoding(value = 0x24)]
ChannelApp(BifrostApp),

#[display("swapd")]
#[strict_encoding(value = 0x28)]
Swapd(SwapId),

#[display("swapapp<{0}>")]
#[strict_encoding(value = 0x40)]
SwapApp(BifrostApp),

#[display("other<{0}>")]
#[strict_encoding(value = 0xFF)]
Other(ServiceName),
Expand Down
37 changes: 37 additions & 0 deletions shell/_lnp-cli
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,31 @@ _arguments "${_arguments_options[@]}" \
'::amount-msat -- Amount of milli-satoshis to pay. Required for invoices lacking amount. Overrides amount provided by the invoice:' \
&& ret=0
;;
(swap-in)
_arguments "${_arguments_options[@]}" \
'-R+[ZMQ socket for connecting daemon RPC interface]:CONNECT: ' \
'--rpc=[ZMQ socket for connecting daemon RPC interface]:CONNECT: ' \
'-h[Print help information]' \
'--help[Print help information]' \
'*-v[Set verbosity level]' \
'*--verbose[Set verbosity level]' \
':amount-asset:' \
':address:' \
&& ret=0
;;
(swap-out)
_arguments "${_arguments_options[@]}" \
'-R+[ZMQ socket for connecting daemon RPC interface]:CONNECT: ' \
'--rpc=[ZMQ socket for connecting daemon RPC interface]:CONNECT: ' \
'-h[Print help information]' \
'--help[Print help information]' \
'*-v[Set verbosity level]' \
'*--verbose[Set verbosity level]' \
':node:' \
':amount-asset:' \
':max-swap-fee:' \
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" \
'-R+[ZMQ socket for connecting daemon RPC interface]:CONNECT: ' \
Expand Down Expand Up @@ -189,6 +214,8 @@ _lnp-cli_commands() {
'open:Opens a new channel with a remote peer, which must be already connected' \
'invoice:Create an invoice' \
'pay:Pay the invoice' \
'swap-in:perform loop in swap' \
'swap-out:perform loop out swap' \
'help:Print this message or the help of the given subcommand(s)' \
)
_describe -t commands 'lnp-cli commands' commands "$@"
Expand Down Expand Up @@ -248,5 +275,15 @@ _lnp-cli__ping_commands() {
local commands; commands=()
_describe -t commands 'lnp-cli ping commands' commands "$@"
}
(( $+functions[_lnp-cli__swap-in_commands] )) ||
_lnp-cli__swap-in_commands() {
local commands; commands=()
_describe -t commands 'lnp-cli swap-in commands' commands "$@"
}
(( $+functions[_lnp-cli__swap-out_commands] )) ||
_lnp-cli__swap-out_commands() {
local commands; commands=()
_describe -t commands 'lnp-cli swap-out commands' commands "$@"
}

_lnp-cli "$@"
20 changes: 20 additions & 0 deletions shell/_lnp-cli.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Register-ArgumentCompleter -Native -CommandName 'lnp-cli' -ScriptBlock {
[CompletionResult]::new('open', 'open', [CompletionResultType]::ParameterValue, 'Opens a new channel with a remote peer, which must be already connected')
[CompletionResult]::new('invoice', 'invoice', [CompletionResultType]::ParameterValue, 'Create an invoice')
[CompletionResult]::new('pay', 'pay', [CompletionResultType]::ParameterValue, 'Pay the invoice')
[CompletionResult]::new('swap-in', 'swap-in', [CompletionResultType]::ParameterValue, 'perform loop in swap')
[CompletionResult]::new('swap-out', 'swap-out', [CompletionResultType]::ParameterValue, 'perform loop out swap')
[CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
break
}
Expand Down Expand Up @@ -152,6 +154,24 @@ Register-ArgumentCompleter -Native -CommandName 'lnp-cli' -ScriptBlock {
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Set verbosity level')
break
}
'lnp-cli;swap-in' {
[CompletionResult]::new('-R', 'R', [CompletionResultType]::ParameterName, 'ZMQ socket for connecting daemon RPC interface')
[CompletionResult]::new('--rpc', 'rpc', [CompletionResultType]::ParameterName, 'ZMQ socket for connecting daemon RPC interface')
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help information')
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Set verbosity level')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Set verbosity level')
break
}
'lnp-cli;swap-out' {
[CompletionResult]::new('-R', 'R', [CompletionResultType]::ParameterName, 'ZMQ socket for connecting daemon RPC interface')
[CompletionResult]::new('--rpc', 'rpc', [CompletionResultType]::ParameterName, 'ZMQ socket for connecting daemon RPC interface')
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help information')
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information')
[CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Set verbosity level')
[CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Set verbosity level')
break
}
'lnp-cli;help' {
[CompletionResult]::new('-R', 'R', [CompletionResultType]::ParameterName, 'ZMQ socket for connecting daemon RPC interface')
[CompletionResult]::new('--rpc', 'rpc', [CompletionResultType]::ParameterName, 'ZMQ socket for connecting daemon RPC interface')
Expand Down
52 changes: 51 additions & 1 deletion shell/lnp-cli.bash
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,20 @@ _lnp-cli() {
ping)
cmd+="__ping"
;;
swap-in)
cmd+="__swap__in"
;;
swap-out)
cmd+="__swap__out"
;;
*)
;;
esac
done

case "${cmd}" in
lnp__cli)
opts="-h -V -R -v --help --version --rpc --verbose listen connect ping info funds peers channels open invoice pay help"
opts="-h -V -R -v --help --version --rpc --verbose listen connect ping info funds peers channels open invoice pay swap-in swap-out help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand Down Expand Up @@ -371,6 +377,50 @@ _lnp-cli() {
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
lnp__cli__swap__in)
opts="-h -R -v --help --rpc --verbose <AMOUNT_ASSET> <ADDRESS>"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--rpc)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
-R)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
lnp__cli__swap__out)
opts="-h -R -v --help --rpc --verbose <NODE> <AMOUNT_ASSET> <MAX_SWAP_FEE>"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--rpc)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
-R)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
esac
}

Expand Down
40 changes: 40 additions & 0 deletions src/bin/swapd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#![recursion_limit = "256"]
// Coding conventions
#![deny(
non_upper_case_globals,
non_camel_case_types,
non_snake_case,
unused_mut,
unused_imports,
dead_code,
missing_docs
)]
//! Main executable for swapd: microservice for performing submarine swap.
//! transactions.

#[macro_use]
extern crate log;

use clap::Parser;
use lnp_node::swapd::Opts;
use lnp_node::Config;

fn main() {
println!("swapd: submarine swap service");

let mut opts = Opts::parse();
trace!("Command-line arguments: {:?}", &opts);
opts.process();
trace!("Processed arguments: {:?}", &opts);

let config: Config = opts.clone().into();
trace!("Daemon configuration: {:?}", &config);
debug!("MSG RPC socket {}", &config.msg_endpoint);
debug!("CTL RPC socket {}", &config.ctl_endpoint);

debug!("Starting runtime ...");
// swapd::run(config).expect("Error running swapd runtime");

todo!();
unreachable!()
}
2 changes: 1 addition & 1 deletion src/bus/ctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub enum CtlMsg {

// Node connectivity API
// ---------------------
// Sent from lnpd to peerd
// Sent from lnpd to peerd, swapd to peerd/channeld
#[display("get_info()")]
GetInfo,

Expand Down
5 changes: 4 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use wallet::psbt::sign::SignError;

use crate::bus::ServiceBus;
use crate::channeld;
use crate::lnpd::automata::launch;
use crate::lnpd::automata::{launch, swap};
use crate::lnpd::{funding, Daemon};
use crate::routed::PaymentError;
use crate::rpc::{self, ServiceId};
Expand Down Expand Up @@ -100,6 +100,9 @@ pub enum Error {
#[from]
Signing(SignError),

#[from]
SwapLaunch(swap::Error),

/// bridge interface failure: {0}
#[from(zmq::Error)]
#[from]
Expand Down
Loading

0 comments on commit 7b8ccdd

Please sign in to comment.