Skip to main content

fedimint_lnv2_common/
lib.rs

1#![deny(clippy::pedantic)]
2#![allow(clippy::module_name_repetitions)]
3#![allow(clippy::must_use_candidate)]
4#![allow(clippy::missing_errors_doc)]
5#![allow(clippy::missing_panics_doc)]
6
7//! # Lightning Module
8//!
9//! This module allows to atomically and trustlessly (in the federated trust
10//! model) interact with the Lightning network through a Lightning gateway.
11
12pub mod config;
13pub mod contracts;
14pub mod endpoint_constants;
15pub mod gateway_api;
16pub mod lnurl;
17pub mod tweak;
18
19use bitcoin::hashes::sha256;
20use bitcoin::secp256k1::schnorr::Signature;
21use config::LightningClientConfig;
22pub use fedimint_core::config::ExcessiveRelativeFeeError;
23use fedimint_core::core::{Decoder, ModuleInstanceId, ModuleKind};
24use fedimint_core::encoding::{Decodable, Encodable};
25use fedimint_core::module::{CommonModuleInit, ModuleCommon, ModuleConsensusVersion};
26use fedimint_core::{OutPoint, extensible_associated_module_type, plugin_types_trait_impl_common};
27pub use fedimint_ln_common::client::GatewayApi;
28use lightning_invoice::Bolt11Invoice;
29use serde::{Deserialize, Serialize};
30use thiserror::Error;
31use tpe::AggregateDecryptionKey;
32
33use crate::contracts::{IncomingContract, OutgoingContract};
34
35#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
36pub enum Bolt11InvoiceDescription {
37    Direct(String),
38    Hash(sha256::Hash),
39}
40
41#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Decodable, Encodable)]
42pub enum LightningInvoice {
43    Bolt11(Bolt11Invoice),
44}
45
46pub const KIND: ModuleKind = ModuleKind::from_static_str("lnv2");
47pub const MODULE_CONSENSUS_VERSION: ModuleConsensusVersion = ModuleConsensusVersion::new(1, 0);
48
49#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
50pub struct ContractId(pub sha256::Hash);
51
52extensible_associated_module_type!(
53    LightningInput,
54    LightningInputV0,
55    UnknownLightningInputVariantError
56);
57
58#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
59pub enum LightningInputV0 {
60    Outgoing(OutPoint, OutgoingWitness),
61    Incoming(OutPoint, AggregateDecryptionKey),
62}
63
64#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
65pub enum OutgoingWitness {
66    Claim([u8; 32]),
67    Refund,
68    Cancel(Signature),
69}
70
71impl std::fmt::Display for LightningInputV0 {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        write!(f, "LightningInputV0",)
74    }
75}
76
77extensible_associated_module_type!(
78    LightningOutput,
79    LightningOutputV0,
80    UnknownLightningOutputVariantError
81);
82
83#[allow(clippy::large_enum_variant)]
84#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
85pub enum LightningOutputV0 {
86    Outgoing(OutgoingContract),
87    Incoming(IncomingContract),
88}
89
90impl std::fmt::Display for LightningOutputV0 {
91    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92        write!(f, "LightningOutputV0")
93    }
94}
95
96#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
97pub struct LightningOutputOutcome;
98
99impl std::fmt::Display for LightningOutputOutcome {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        write!(f, "LightningOutputOutcome")
102    }
103}
104
105#[derive(Debug, Clone, Eq, PartialEq, Hash, Error, Encodable, Decodable)]
106pub enum LightningInputError {
107    #[error("The lightning input version is not supported by this federation")]
108    UnknownInputVariant(#[from] UnknownLightningInputVariantError),
109    #[error("No contract found for given ContractId")]
110    UnknownContract,
111    #[error("The preimage is invalid")]
112    InvalidPreimage,
113    #[error("The contracts locktime has passed")]
114    Expired,
115    #[error("The contracts locktime has not yet passed")]
116    NotExpired,
117    #[error("The aggregate decryption key is invalid")]
118    InvalidDecryptionKey,
119    #[error("The forfeit signature is invalid")]
120    InvalidForfeitSignature,
121}
122
123#[derive(Debug, Clone, Eq, PartialEq, Hash, Error, Encodable, Decodable)]
124pub enum LightningOutputError {
125    #[error("The lightning input version is not supported by this federation")]
126    UnknownOutputVariant(#[from] UnknownLightningOutputVariantError),
127    #[error("The contract is invalid")]
128    InvalidContract,
129    #[error("The contract is expired")]
130    ContractExpired,
131}
132
133#[derive(Debug, Clone, Hash, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
134pub enum LightningConsensusItem {
135    BlockCountVote(u64),
136    UnixTimeVote(u64),
137    #[encodable_default]
138    Default {
139        variant: u64,
140        bytes: Vec<u8>,
141    },
142}
143
144impl std::fmt::Display for LightningConsensusItem {
145    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146        match self {
147            LightningConsensusItem::BlockCountVote(c) => {
148                write!(f, "LNv2 Block Count {c}")
149            }
150            LightningConsensusItem::UnixTimeVote(t) => {
151                write!(f, "LNv2 Unix Time {t}")
152            }
153            LightningConsensusItem::Default { variant, bytes } => write!(
154                f,
155                "LNv2 Unknown - variant: {variant}, bytes_len: {}",
156                bytes.len()
157            ),
158        }
159    }
160}
161
162#[derive(Debug)]
163pub struct LightningCommonInit;
164
165impl CommonModuleInit for LightningCommonInit {
166    const CONSENSUS_VERSION: ModuleConsensusVersion = MODULE_CONSENSUS_VERSION;
167    const KIND: ModuleKind = KIND;
168
169    type ClientConfig = LightningClientConfig;
170
171    fn decoder() -> Decoder {
172        LightningModuleTypes::decoder()
173    }
174}
175
176pub struct LightningModuleTypes;
177
178plugin_types_trait_impl_common!(
179    KIND,
180    LightningModuleTypes,
181    LightningClientConfig,
182    LightningInput,
183    LightningOutput,
184    LightningOutputOutcome,
185    LightningConsensusItem,
186    LightningInputError,
187    LightningOutputError
188);