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