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