fedimint_lnv2_common/
lib.rs

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