Skip to content

Commit

Permalink
wip: support submarine swap in bifrost
Browse files Browse the repository at this point in the history
* messages resembles those of [peerswap protocol](https://github.com/ElementsProject/peerswap/blob/master/docs/peer-protocol.md#the-swap_in_request-message)
* It does not support compatibility with peerswap daemon
* LNPBP specification is not ready yet.
  • Loading branch information
joemphilips committed Feb 15, 2023
1 parent 0063e2c commit 60093c6
Show file tree
Hide file tree
Showing 4 changed files with 356 additions and 0 deletions.
45 changes: 45 additions & 0 deletions lnp2p/src/bifrost/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ mod app;
mod channel;
mod ctrl;
mod msg;
mod peerswap;
mod proposals;
mod types;

Expand All @@ -185,6 +186,7 @@ use internet2::{CreateUnmarshaller, Payload, Unmarshall, Unmarshaller};
use lnpbp::bech32::Blob;
pub use msg::Msg;
use once_cell::sync::Lazy;
pub use peerswap::*;
pub use proposals::*;
use strict_encoding::{self, StrictDecode, StrictEncode};
pub use types::{
Expand Down Expand Up @@ -257,6 +259,49 @@ pub enum Messages {

#[api(type = 0x0028)]
CloseChannel(CloseChannel),

#[api(type = 0x0040)]
SwapInRequest(SwapInRequestMsg),

#[api(type = 0x0041)]
SwapInAgreement(SwapInAgreementMsg),

#[api(type = 0x0042)]
SwapOutRequest(SwapOutRequestMsg),

#[api(type = 0x0043)]
SwapOutAgreement(SwapOutAgreementMsg),

#[api(type = 0x0044)]
OpeningTxBroadcasted(OpeningTxBroadcastedMsg),

#[api(type = 0x0045)]
Cancel(CancelMsg),

#[api(type = 0x0046)]
CoopClose(CoopCloseMsg),
}

impl Messages {
pub fn swap_id(&self) -> Option<&SwapId> {
match self {
Self::SwapInRequest(SwapInRequestMsg { swap_id, .. })
| Self::SwapOutRequest(SwapOutRequestMsg { swap_id, .. })
| Self::SwapInAgreement(SwapInAgreementMsg { swap_id, .. })
| Self::SwapOutAgreement(SwapOutAgreementMsg { swap_id, .. })
| Self::OpeningTxBroadcasted(OpeningTxBroadcastedMsg {
swap_id,
..
})
| Self::Cancel(CancelMsg { swap_id, .. })
| Self::CoopClose(CoopCloseMsg { swap_id, .. }) => Some(swap_id),
_ => None,
}
}

pub fn is_swap_msg(&self) -> bool {
self.swap_id().is_some()
}
}

impl StrictEncode for Messages {
Expand Down
300 changes: 300 additions & 0 deletions lnp2p/src/bifrost/peerswap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
// LNP P2P library, plmeneting both bolt (BOLT) and Bifrost P2P messaging
// system for Lightning network protocol (LNP)
//
// Written in 2020-2021 by
// Dr. Maxim Orlovsky <orlovsky@pandoracore.com>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the MIT License
// along with this software.
// If not, see <https://opensource.org/licenses/MIT>.

use amplify::{Display, Slice32};
use bitcoin::hashes::{sha256, sha256t};
use bitcoin::Txid;
use lnpbp::chain::AssetId;
use secp256k1::{PublicKey, SecretKey};
#[cfg(feature = "serde")]
use serde_with::{As, DisplayFromStr};

use crate::bolt;

pub const PROTOCOL_VERSION: u16 = 1;
pub const BIFROST_APP_PEERSWAP: u16 = 0x8008;

// SHA256("bifrost:swap")
const SWAP_ID_MIDSTATE: [u8; 32] = [
0x4e, 0x2e, 0x6e, 0xb2, 0xa3, 0xda, 0x16, 0xbc, 0x03, 0xe3, 0x38, 0x30,
0xb3, 0xfa, 0xae, 0x6f, 0xe2, 0x76, 0x00, 0x1b, 0x2e, 0x79, 0xf1, 0x8f,
0xd3, 0x8c, 0x43, 0xdc, 0x79, 0xfb, 0x99, 0xdd,
];

/// Tag used for [`SwapId`] hash type
pub struct SwapIdTag;

impl sha256t::Tag for SwapIdTag {
#[inline]
fn engine() -> sha256::HashEngine {
let midstate = sha256::Midstate::from_inner(SWAP_ID_MIDSTATE);
sha256::HashEngine::from_midstate(midstate, 64)
}
}

#[derive(
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Debug,
Display,
Default,
Wrapper,
From,
NetworkEncode,
NetworkDecode
)]
#[display(LowerHex)]
#[wrapper(FromStr, LowerHex, UpperHex, BorrowSlice)]
#[cfg_attr(
feature = "serde",
serde_as,
derive(Serialize, Deserialize),
serde(crate = "serde_crate", transparent)
)]
pub struct SwapId(
#[cfg_attr(feature = "serde", serde(with = "As::<DisplayFromStr>"))]
Slice32,
);

impl SwapId {
#[inline]
pub fn random() -> Self {
SwapId::from(Slice32::random())
}
}

#[derive(
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Debug,
Display,
NetworkEncode,
NetworkDecode
)]
#[cfg_attr(
feature = "serde",
serde_as,
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
#[display(Debug)]
#[network_encoding(use_tlv)]
pub struct SwapInRequestMsg {
pub protocol_version: u64,
pub swap_id: SwapId,
pub asset: Option<AssetId>,
pub network: String,
pub scid: bolt::ChannelId,
pub amount: u64,
pub pubkey: PublicKey,
}

#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error)]
#[display(doc_comments)]
pub enum ValidationError {
/// Network and asset has different value.
NetworkMismatch,

/// Unknown Network {0}
UnknownNetwork(String),
}

impl SwapInRequestMsg {
pub fn validate(&self) -> Result<(), ValidationError> {
let _network_ok = {
match self.network.as_str() {
"mainnet" => Ok(()),
"testnet" => Ok(()),
"testnet3" => Ok(()),
"signet" => Ok(()),
"regtest" => Ok(()),
x => Err(ValidationError::UnknownNetwork(x.to_string())),
}
}?;

Ok(())
}
}

#[derive(
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Debug,
Display,
NetworkEncode,
NetworkDecode
)]
#[cfg_attr(
feature = "serde",
serde_as,
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
#[display(Debug)]
#[network_encoding(use_tlv)]
pub struct SwapInAgreementMsg {
pub protocol_version: u64,
pub swap_id: SwapId,
pub pubkey: PublicKey,
pub premium: u64,
}

#[derive(
Clone,
PartialEq,
Eq,
Hash,
Ord,
PartialOrd,
Debug,
Display,
NetworkEncode,
NetworkDecode
)]
#[cfg_attr(
feature = "serde",
serde_as,
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
#[display(Debug)]
#[network_encoding(use_tlv)]
pub struct SwapOutRequestMsg {
pub protocol_version: u64,
pub swap_id: SwapId,
pub asset: Option<AssetId>,
pub network: String,
pub scid: bolt::ChannelId,
pub amount: u64,
pub pubkey: PublicKey,
}

#[derive(
Clone,
PartialEq,
Eq,
Hash,
Ord,
PartialOrd,
Debug,
Display,
NetworkEncode,
NetworkDecode
)]
#[cfg_attr(
feature = "serde",
serde_as,
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
#[display(Debug)]
#[network_encoding(use_tlv)]
pub struct SwapOutAgreementMsg {
pub protocol_version: u64,
pub swap_id: SwapId,
pub pubkey: PublicKey,
pub payreq: String,
}

#[derive(
Clone,
PartialEq,
Eq,
Hash,
Ord,
PartialOrd,
Debug,
Display,
NetworkEncode,
NetworkDecode
)]
#[cfg_attr(
feature = "serde",
serde_as,
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
#[display(Debug)]
#[network_encoding(use_tlv)]
pub struct OpeningTxBroadcastedMsg {
pub swap_id: SwapId,
pub payreq: String,
pub tx_id: Txid,
pub script_out: u64,
pub blinding_key: SecretKey,
}

#[derive(
Clone,
PartialEq,
Eq,
Hash,
Ord,
PartialOrd,
Debug,
Display,
NetworkEncode,
NetworkDecode
)]
#[cfg_attr(
feature = "serde",
serde_as,
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
#[display(Debug)]
#[network_encoding(use_tlv)]
pub struct CancelMsg {
pub swap_id: SwapId,
pub message: String,
}

#[derive(
Clone,
PartialEq,
Eq,
Hash,
Ord,
PartialOrd,
Debug,
Display,
NetworkEncode,
NetworkDecode
)]
#[cfg_attr(
feature = "serde",
serde_as,
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
#[display(Debug)]
#[network_encoding(use_tlv)]
pub struct CoopCloseMsg {
pub swap_id: SwapId,
pub message: String,
pub privkey: SecretKey,
}
6 changes: 6 additions & 0 deletions lnp2p/src/bifrost/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ impl sha256t::Tag for ChannelIdTag {
)]
#[wrapper(Debug, LowerHex, BorrowSlice)]
#[wrapper(Index, IndexRange, IndexFrom, IndexTo, IndexFull)]
#[cfg_attr(
feature = "serde",
serde_as,
derive(Serialize, Deserialize),
serde(crate = "serde_crate", transparent)
)]
pub struct ChannelId(sha256t::Hash<ChannelIdTag>);

impl ChannelId {
Expand Down
5 changes: 5 additions & 0 deletions lnp2p/src/bolt/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@ pub struct Alias(
)]
#[derive(LightningEncode, LightningDecode)]
#[cfg_attr(feature = "strict_encoding", derive(NetworkEncode, NetworkDecode))]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate")
)]
#[display("{block_height}x{tx_index}x{output_index}")]
pub struct ShortChannelId {
pub block_height: u24,
Expand Down

0 comments on commit 60093c6

Please sign in to comment.