fedimint_ln_common/contracts/
mod.rspub mod incoming;
pub mod outgoing;
use std::io::Error;
use bitcoin_hashes::sha256::Hash as Sha256;
use bitcoin_hashes::{hash_newtype, Hash as BitcoinHash};
use fedimint_core::encoding::{Decodable, DecodeError, Encodable};
use fedimint_core::module::registry::ModuleDecoderRegistry;
use fedimint_core::OutPoint;
use serde::{Deserialize, Serialize};
pub trait IdentifiableContract: Encodable {
fn contract_id(&self) -> ContractId;
}
hash_newtype!(
pub struct ContractId(Sha256);
);
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
pub enum Contract {
Incoming(incoming::IncomingContract),
Outgoing(outgoing::OutgoingContract),
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, Eq, PartialEq, Hash, Encodable, Decodable, Serialize, Deserialize)]
pub enum FundedContract {
Incoming(incoming::FundedIncomingContract),
Outgoing(outgoing::OutgoingContract),
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
pub enum ContractOutcome {
Incoming(DecryptedPreimage),
Outgoing(OutgoingContractOutcome),
}
impl ContractOutcome {
pub fn is_permanent(&self) -> bool {
match self {
ContractOutcome::Incoming(o) => o.is_permanent(),
ContractOutcome::Outgoing(_) => true,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
pub struct OutgoingContractOutcome {}
impl IdentifiableContract for Contract {
fn contract_id(&self) -> ContractId {
match self {
Contract::Incoming(c) => c.contract_id(),
Contract::Outgoing(c) => c.contract_id(),
}
}
}
impl IdentifiableContract for FundedContract {
fn contract_id(&self) -> ContractId {
match self {
FundedContract::Incoming(c) => c.contract.contract_id(),
FundedContract::Outgoing(c) => c.contract_id(),
}
}
}
impl Contract {
pub fn to_outcome(&self) -> ContractOutcome {
match self {
Contract::Incoming(_) => ContractOutcome::Incoming(DecryptedPreimage::Pending),
Contract::Outgoing(_) => ContractOutcome::Outgoing(OutgoingContractOutcome {}),
}
}
pub fn to_funded(self, out_point: OutPoint) -> FundedContract {
match self {
Contract::Incoming(incoming) => {
FundedContract::Incoming(incoming::FundedIncomingContract {
contract: incoming,
out_point,
})
}
Contract::Outgoing(outgoing) => FundedContract::Outgoing(outgoing),
}
}
}
impl Encodable for ContractId {
fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, Error> {
self.to_byte_array().consensus_encode(writer)
}
}
impl Decodable for ContractId {
fn consensus_decode<D: std::io::Read>(
d: &mut D,
modules: &ModuleDecoderRegistry,
) -> Result<Self, DecodeError> {
Ok(ContractId::from_byte_array(Decodable::consensus_decode(
d, modules,
)?))
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
pub struct Preimage(pub [u8; 32]);
#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
pub struct PreimageKey(#[serde(with = "serde_big_array::BigArray")] pub [u8; 33]);
impl PreimageKey {
pub fn to_public_key(&self) -> Result<secp256k1::PublicKey, secp256k1::Error> {
secp256k1::PublicKey::from_slice(&self.0)
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
pub enum DecryptedPreimageStatus {
Pending,
Some(Preimage),
Invalid,
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Encodable, Decodable)]
pub enum DecryptedPreimage {
Pending,
Some(PreimageKey),
Invalid,
}
impl DecryptedPreimage {
pub fn is_permanent(&self) -> bool {
match self {
DecryptedPreimage::Pending => false,
DecryptedPreimage::Some(_) | DecryptedPreimage::Invalid => true,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash, Encodable, Decodable, Deserialize, Serialize)]
pub struct EncryptedPreimage(pub threshold_crypto::Ciphertext);
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Serialize, Deserialize)]
pub struct PreimageDecryptionShare(pub threshold_crypto::DecryptionShare);
impl EncryptedPreimage {
pub fn new(preimage_key: &PreimageKey, key: &threshold_crypto::PublicKey) -> EncryptedPreimage {
EncryptedPreimage(key.encrypt(preimage_key.0))
}
}