fedimint_ln_common/contracts/
mod.rs1pub mod incoming;
2pub mod outgoing;
3
4use std::fmt::Display;
5use std::io::Error;
6#[cfg(feature = "uniffi")]
7use std::str::FromStr;
8
9use bitcoin::hashes::sha256::Hash as Sha256;
10use bitcoin::hashes::{Hash as BitcoinHash, hash_newtype};
11use fedimint_core::encoding::{Decodable, DecodeError, Encodable};
12use fedimint_core::hex::ToHex;
13use fedimint_core::module::registry::ModuleDecoderRegistry;
14use fedimint_core::{OutPoint, secp256k1};
15use serde::{Deserialize, Serialize};
16
17pub trait IdentifiableContract: Encodable {
19 fn contract_id(&self) -> ContractId;
20}
21
22hash_newtype!(
23 pub struct ContractId(Sha256);
25);
26
27#[cfg(feature = "uniffi")]
28uniffi::custom_type!(ContractId, String, {
29 lower: |contract_id| contract_id.to_string(),
30 try_lift: |s| ContractId::from_str(&s).map_err(Into::into),
31});
32
33#[allow(clippy::large_enum_variant)]
36#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
37pub enum Contract {
38 Incoming(incoming::IncomingContract),
39 Outgoing(outgoing::OutgoingContract),
40}
41
42#[allow(clippy::large_enum_variant)]
44#[derive(Debug, Clone, Eq, PartialEq, Hash, Encodable, Decodable, Serialize, Deserialize)]
45pub enum FundedContract {
46 Incoming(incoming::FundedIncomingContract),
47 Outgoing(outgoing::OutgoingContract),
48}
49
50#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
53pub enum ContractOutcome {
54 Incoming(DecryptedPreimage),
55 Outgoing(OutgoingContractOutcome),
56}
57
58impl ContractOutcome {
59 pub fn is_permanent(&self) -> bool {
60 match self {
61 ContractOutcome::Incoming(o) => o.is_permanent(),
62 ContractOutcome::Outgoing(_) => true,
63 }
64 }
65}
66
67#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
68pub struct OutgoingContractOutcome {}
69
70impl IdentifiableContract for Contract {
71 fn contract_id(&self) -> ContractId {
72 match self {
73 Contract::Incoming(c) => c.contract_id(),
74 Contract::Outgoing(c) => c.contract_id(),
75 }
76 }
77}
78
79impl IdentifiableContract for FundedContract {
80 fn contract_id(&self) -> ContractId {
81 match self {
82 FundedContract::Incoming(c) => c.contract.contract_id(),
83 FundedContract::Outgoing(c) => c.contract_id(),
84 }
85 }
86}
87
88impl Contract {
89 pub fn to_outcome(&self) -> ContractOutcome {
92 match self {
93 Contract::Incoming(_) => ContractOutcome::Incoming(DecryptedPreimage::Pending),
94 Contract::Outgoing(_) => ContractOutcome::Outgoing(OutgoingContractOutcome {}),
95 }
96 }
97
98 pub fn to_funded(self, out_point: OutPoint) -> FundedContract {
100 match self {
101 Contract::Incoming(incoming) => {
102 FundedContract::Incoming(incoming::FundedIncomingContract {
103 contract: incoming,
104 out_point,
105 })
106 }
107 Contract::Outgoing(outgoing) => FundedContract::Outgoing(outgoing),
108 }
109 }
110}
111
112impl Encodable for ContractId {
113 fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), Error> {
114 self.to_byte_array().consensus_encode(writer)
115 }
116}
117
118impl Decodable for ContractId {
119 fn consensus_decode_partial<D: std::io::Read>(
120 d: &mut D,
121 modules: &ModuleDecoderRegistry,
122 ) -> Result<Self, DecodeError> {
123 Ok(ContractId::from_byte_array(
124 Decodable::consensus_decode_partial(d, modules)?,
125 ))
126 }
127}
128
129#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
130pub struct Preimage(pub [u8; 32]);
131
132impl Display for Preimage {
133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 write!(f, "{}", self.0.encode_hex::<String>())
135 }
136}
137
138#[cfg(feature = "uniffi")]
139impl FromStr for Preimage {
140 type Err = anyhow::Error;
141
142 fn from_str(s: &str) -> Result<Self, Self::Err> {
143 let bytes: [u8; 32] = fedimint_core::hex::FromHex::from_hex(s)?;
144 Ok(Self(bytes))
145 }
146}
147
148#[cfg(feature = "uniffi")]
149uniffi::custom_type!(Preimage, String, {
150 lower: |p| p.to_string(),
151 try_lift: |s| Preimage::from_str(&s).map_err(Into::into),
152});
153
154#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
155pub struct PreimageKey(#[serde(with = "serde_big_array::BigArray")] pub [u8; 33]);
156
157impl PreimageKey {
158 pub fn to_public_key(&self) -> Result<secp256k1::PublicKey, secp256k1::Error> {
165 secp256k1::PublicKey::from_slice(&self.0)
166 }
167}
168
169#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
171pub enum DecryptedPreimageStatus {
172 Pending,
174 Some(Preimage),
176 Invalid,
178}
179
180#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
182pub enum DecryptedPreimage {
183 Pending,
185 Some(PreimageKey),
187 Invalid,
189}
190
191impl DecryptedPreimage {
192 pub fn is_permanent(&self) -> bool {
193 match self {
194 DecryptedPreimage::Pending => false,
195 DecryptedPreimage::Some(_) | DecryptedPreimage::Invalid => true,
196 }
197 }
198}
199#[derive(Debug, Clone, Eq, PartialEq, Hash, Encodable, Decodable, Deserialize, Serialize)]
201pub struct EncryptedPreimage(pub threshold_crypto::Ciphertext);
202
203#[derive(Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Serialize, Deserialize)]
205pub struct PreimageDecryptionShare(pub threshold_crypto::DecryptionShare);
206
207impl EncryptedPreimage {
208 pub fn new(preimage_key: &PreimageKey, key: &threshold_crypto::PublicKey) -> EncryptedPreimage {
209 EncryptedPreimage(key.encrypt(preimage_key.0))
210 }
211}