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::{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(ContractId, OutgoingWitness),
57    Incoming(ContractId, 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    #[error("A contract with this ContractId already exists")]
128    ContractAlreadyExists,
129}
130
131#[derive(Debug, Clone, Hash, Eq, PartialEq, Encodable, Decodable, Serialize, Deserialize)]
132pub enum LightningConsensusItem {
133    BlockCountVote(u64),
134    UnixTimeVote(u64),
135    #[encodable_default]
136    Default {
137        variant: u64,
138        bytes: Vec<u8>,
139    },
140}
141
142impl std::fmt::Display for LightningConsensusItem {
143    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144        write!(f, "LightningConsensusItem")
145    }
146}
147
148#[derive(Debug)]
149pub struct LightningCommonInit;
150
151impl CommonModuleInit for LightningCommonInit {
152    const CONSENSUS_VERSION: ModuleConsensusVersion = MODULE_CONSENSUS_VERSION;
153    const KIND: ModuleKind = KIND;
154
155    type ClientConfig = LightningClientConfig;
156
157    fn decoder() -> Decoder {
158        LightningModuleTypes::decoder()
159    }
160}
161
162pub struct LightningModuleTypes;
163
164plugin_types_trait_impl_common!(
165    KIND,
166    LightningModuleTypes,
167    LightningClientConfig,
168    LightningInput,
169    LightningOutput,
170    LightningOutputOutcome,
171    LightningConsensusItem,
172    LightningInputError,
173    LightningOutputError
174);