use crate::model::cfd::CfdOfferId; use crate::model::Usd; use crate::CfdOffer; use bdk::bitcoin::secp256k1::Signature; use bdk::bitcoin::util::psbt::PartiallySignedTransaction; use bdk::bitcoin::{Address, Amount, PublicKey, Txid}; use cfd_protocol::{CfdTransactions, PartyParams, PunishParams}; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, DisplayFromStr}; #[serde_as] #[derive(Debug, Serialize, Deserialize)] pub struct AdaptorSignature(#[serde_as(as = "DisplayFromStr")] cfd_protocol::EcdsaAdaptorSignature); impl std::ops::Deref for AdaptorSignature { type Target = cfd_protocol::EcdsaAdaptorSignature; fn deref(&self) -> &Self::Target { &self.0 } } #[derive(Debug, Serialize, Deserialize)] #[serde(tag = "type", content = "payload")] #[allow(clippy::large_enum_variant)] pub enum TakerToMaker { TakeOffer { offer_id: CfdOfferId, quantity: Usd }, // TODO: Currently the taker starts, can already send some stuff for signing over in the first // message. StartContractSetup(CfdOfferId), Protocol(SetupMsg), } #[derive(Debug, Serialize, Deserialize)] #[serde(tag = "type", content = "payload")] #[allow(clippy::large_enum_variant)] pub enum MakerToTaker { CurrentOffer(Option), // TODO: Needs RejectOffer as well ConfirmTakeOffer(CfdOfferId), // TODO: Include payout curve in "accept" message from maker InvalidOfferId(CfdOfferId), Protocol(SetupMsg), } #[derive(Debug, Serialize, Deserialize)] #[serde(tag = "type", content = "payload")] pub enum SetupMsg { Msg0(Msg0), Msg1(Msg1), } impl SetupMsg { pub fn try_into_msg0(self) -> Result { if let Self::Msg0(v) = self { Ok(v) } else { Err(self) } } pub fn try_into_msg1(self) -> Result { if let Self::Msg1(v) = self { Ok(v) } else { Err(self) } } } #[derive(Debug, Serialize, Deserialize)] pub struct Msg0 { pub lock_psbt: PartiallySignedTransaction, // TODO: Use binary representation pub identity_pk: PublicKey, #[serde(with = "bdk::bitcoin::util::amount::serde::as_sat")] pub lock_amount: Amount, pub address: Address, pub revocation_pk: PublicKey, pub publish_pk: PublicKey, } impl From<(PartyParams, PunishParams)> for Msg0 { fn from((party, punish): (PartyParams, PunishParams)) -> Self { let PartyParams { lock_psbt, identity_pk, lock_amount, address, } = party; let PunishParams { revocation_pk, publish_pk, } = punish; Self { lock_psbt, identity_pk, lock_amount, address, revocation_pk, publish_pk, } } } impl From for (PartyParams, PunishParams) { fn from(msg0: Msg0) -> Self { let Msg0 { lock_psbt, identity_pk, lock_amount, address, revocation_pk, publish_pk, } = msg0; let party = PartyParams { lock_psbt, identity_pk, lock_amount, address, }; let punish = PunishParams { revocation_pk, publish_pk, }; (party, punish) } } #[derive(Debug, Serialize, Deserialize)] pub struct Msg1 { pub commit: AdaptorSignature, pub cets: Vec<(Txid, AdaptorSignature)>, pub refund: Signature, } impl From for Msg1 { fn from(txs: CfdTransactions) -> Self { Self { commit: AdaptorSignature(txs.commit.1), cets: txs .cets .into_iter() .map(|(tx, sig, _, _)| (tx.txid(), AdaptorSignature(sig))) .collect(), refund: txs.refund.1, } } }