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