diff --git a/src/bundle.rs b/src/bundle.rs index f03069b2..c716e352 100644 --- a/src/bundle.rs +++ b/src/bundle.rs @@ -15,6 +15,34 @@ use crate::crypto::{Keys, SharedKeyId, SharedSecretKeys, Signatures, TaggedEleme use crate::protocol_message; use crate::swap::Swap; +#[derive(Debug, Clone, Display)] +#[display(Debug)] +pub struct Proof { + pub proof: Ctx::Proof, +} + +impl Encodable for Proof +where + Ctx: Swap, +{ + fn consensus_encode(&self, s: &mut W) -> Result { + self.proof.as_canonical_bytes().consensus_encode(s) + } +} + +impl Decodable for Proof +where + Ctx: Swap, +{ + fn consensus_decode(d: &mut D) -> Result { + Ok(Self { + proof: Ctx::Proof::from_canonical_bytes(unwrap_vec_ref!(d).as_ref())?, + }) + } +} + +impl_strict_encoding!(Proof, Ctx: Swap); + /// Alice parameters required for the initialization step of a swap and used to generate the /// [`CommitAliceParameters`] and [`RevealAliceParameters`] protocol messages in the commit/reveal /// round. @@ -37,7 +65,6 @@ pub struct AliceParameters { pub accordant_shared_keys: Vec::SharedSecretKey>>, pub destination_address: ::Address, - pub proof: Ctx::Proof, pub cancel_timelock: Option<::Timelock>, pub punish_timelock: Option<::Timelock>, pub fee_strategy: Option::FeeUnit>>, @@ -62,7 +89,6 @@ where .destination_address .as_canonical_bytes() .consensus_encode(s)?; - len += self.proof.as_canonical_bytes().consensus_encode(s)?; len += self.cancel_timelock.consensus_encode(s)?; len += self.punish_timelock.consensus_encode(s)?; Ok(len + self.fee_strategy.consensus_encode(s)?) @@ -96,7 +122,6 @@ where destination_address: ::Address::from_canonical_bytes( unwrap_vec_ref!(d).as_ref(), )?, - proof: Ctx::Proof::from_canonical_bytes(unwrap_vec_ref!(d).as_ref())?, cancel_timelock: Decodable::consensus_decode(d)?, punish_timelock: Decodable::consensus_decode(d)?, fee_strategy: Decodable::consensus_decode(d)?, @@ -123,7 +148,6 @@ where extra_accordant_keys: msg.extra_accordant_keys, accordant_shared_keys: msg.accordant_shared_keys, destination_address: msg.address, - proof: msg.proof, cancel_timelock: None, punish_timelock: None, fee_strategy: None, @@ -152,7 +176,6 @@ pub struct BobParameters { pub accordant_shared_keys: Vec::SharedSecretKey>>, pub refund_address: ::Address, - pub proof: Ctx::Proof, pub cancel_timelock: Option<::Timelock>, pub punish_timelock: Option<::Timelock>, pub fee_strategy: Option::FeeUnit>>, @@ -176,7 +199,6 @@ where .refund_address .as_canonical_bytes() .consensus_encode(s)?; - len += self.proof.as_canonical_bytes().consensus_encode(s)?; len += self.cancel_timelock.consensus_encode(s)?; len += self.punish_timelock.consensus_encode(s)?; Ok(len + self.fee_strategy.consensus_encode(s)?) @@ -207,7 +229,6 @@ where refund_address: ::Address::from_canonical_bytes( unwrap_vec_ref!(d).as_ref(), )?, - proof: Ctx::Proof::from_canonical_bytes(unwrap_vec_ref!(d).as_ref())?, cancel_timelock: Decodable::consensus_decode(d)?, punish_timelock: Decodable::consensus_decode(d)?, fee_strategy: Decodable::consensus_decode(d)?, @@ -233,7 +254,6 @@ where extra_accordant_keys: msg.extra_accordant_keys, accordant_shared_keys: msg.accordant_shared_keys, refund_address: msg.address, - proof: msg.proof, cancel_timelock: None, punish_timelock: None, fee_strategy: None, diff --git a/src/protocol_message.rs b/src/protocol_message.rs index 48c95202..8c2f6518 100644 --- a/src/protocol_message.rs +++ b/src/protocol_message.rs @@ -52,6 +52,8 @@ fn verify_vec_of_commitments( .map(|_| ()) } +// CommitAliceParameters + /// Forces Alice to commit to the result of her cryptographic setup before receiving Bob's setup. /// This is done to remove adaptive behavior in the cryptographic parameters. #[derive(Clone, Debug, Display)] @@ -188,6 +190,8 @@ where type Strategy = AsStrict; } +// CommitBobParameters + /// Forces Bob to commit to the result of his cryptographic setup before receiving Alice's setup. /// This is done to remove adaptive behavior in the cryptographic parameters. #[derive(Clone, Debug, Display)] @@ -318,6 +322,63 @@ where type Strategy = AsStrict; } +// RevealProof + +/// Reveals the proof. +#[derive(Clone, Debug, Display)] +#[display(Debug)] +pub struct RevealProof { + /// The swap identifier related to this message. + pub swap_id: SwapId, + /// Reveal the cross-group discrete logarithm zero-knowledge proof. + pub proof: Ctx::Proof, +} + +impl Encodable for RevealProof +where + Ctx: Swap, +{ + fn consensus_encode(&self, s: &mut W) -> Result { + let len = self.swap_id.consensus_encode(s)?; + Ok(len + self.proof.as_canonical_bytes().consensus_encode(s)?) + } +} + +impl Decodable for RevealProof +where + Ctx: Swap, +{ + fn consensus_decode(d: &mut D) -> Result { + Ok(Self { + swap_id: Decodable::consensus_decode(d)?, + proof: Ctx::Proof::from_canonical_bytes(unwrap_vec_ref!(d).as_ref())?, + }) + } +} + +impl_strict_encoding!(RevealProof, Ctx: Swap); + +impl Strategy for RevealProof +where + Ctx: Swap, +{ + type Strategy = AsStrict; +} + +impl From<(SwapId, bundle::Proof)> for RevealProof +where + Ctx: Swap, +{ + fn from(bundle: (SwapId, bundle::Proof)) -> Self { + Self { + swap_id: bundle.0, + proof: bundle.1.proof, + } + } +} + +// RevealAliceParameters + /// Reveals the parameters commited by the [`CommitAliceParameters`] protocol message. #[derive(Clone, Debug, Display)] #[display(Debug)] @@ -348,8 +409,6 @@ pub struct RevealAliceParameters { Vec::SharedSecretKey>>, /// Reveal the destination address. pub address: ::Address, - /// Reveal the cross-group discrete logarithm zero-knowledge proof. - pub proof: Ctx::Proof, } impl Encodable for RevealAliceParameters @@ -365,11 +424,11 @@ where len += self.adaptor.as_canonical_bytes().consensus_encode(s)?; len += self.extra_arbitrating_keys.consensus_encode(s)?; len += self.arbitrating_shared_keys.consensus_encode(s)?; + // this can go? len += self.spend.as_canonical_bytes().consensus_encode(s)?; len += self.extra_accordant_keys.consensus_encode(s)?; len += self.accordant_shared_keys.consensus_encode(s)?; - len += self.address.as_canonical_bytes().consensus_encode(s)?; - Ok(len + self.proof.as_canonical_bytes().consensus_encode(s)?) + Ok(len + self.address.as_canonical_bytes().consensus_encode(s)?) } } @@ -401,7 +460,6 @@ where address: ::Address::from_canonical_bytes( unwrap_vec_ref!(d).as_ref(), )?, - proof: Ctx::Proof::from_canonical_bytes(unwrap_vec_ref!(d).as_ref())?, }) } } @@ -433,7 +491,6 @@ where extra_accordant_keys: bundle.1.extra_accordant_keys, accordant_shared_keys: bundle.1.accordant_shared_keys, address: bundle.1.destination_address, - proof: bundle.1.proof, } } } @@ -466,8 +523,6 @@ pub struct RevealBobParameters { Vec::SharedSecretKey>>, /// The refund Bitcoin address. pub address: ::Address, - /// The cross-group discrete logarithm zero-knowledge proof. - pub proof: Ctx::Proof, } impl Encodable for RevealBobParameters @@ -485,8 +540,7 @@ where len += self.spend.as_canonical_bytes().consensus_encode(s)?; len += self.extra_accordant_keys.consensus_encode(s)?; len += self.accordant_shared_keys.consensus_encode(s)?; - len += self.address.as_canonical_bytes().consensus_encode(s)?; - Ok(len + self.proof.as_canonical_bytes().consensus_encode(s)?) + Ok(len + self.address.as_canonical_bytes().consensus_encode(s)?) } } @@ -515,7 +569,6 @@ where address: ::Address::from_canonical_bytes( unwrap_vec_ref!(d).as_ref(), )?, - proof: Ctx::Proof::from_canonical_bytes(unwrap_vec_ref!(d).as_ref())?, }) } } @@ -546,7 +599,6 @@ where extra_accordant_keys: bundle.1.extra_accordant_keys, accordant_shared_keys: bundle.1.accordant_shared_keys, address: bundle.1.refund_address, - proof: bundle.1.proof, } } } diff --git a/src/role.rs b/src/role.rs index 7da91b3f..71e7345a 100644 --- a/src/role.rs +++ b/src/role.rs @@ -11,8 +11,8 @@ use crate::blockchain::{ }; use crate::bundle::{ AliceParameters, BobParameters, CoreArbitratingTransactions, CosignedArbitratingCancel, - FullySignedBuy, FullySignedPunish, FullySignedRefund, SignedAdaptorBuy, SignedAdaptorRefund, - SignedArbitratingLock, + FullySignedBuy, FullySignedPunish, FullySignedRefund, Proof, SignedAdaptorBuy, + SignedAdaptorRefund, SignedArbitratingLock, }; use crate::consensus::{self, Decodable, Encodable}; use crate::crypto::{ @@ -223,7 +223,7 @@ where Ctx::Proof, >, public_offer: &PublicOffer, - ) -> Res> { + ) -> Res<(AliceParameters, Proof)> { let extra_arbitrating_keys: Res::PublicKey>> = ::extra_keys() .into_iter() @@ -264,23 +264,25 @@ where let (spend, adaptor, proof) = key_gen.generate_proof()?; - Ok(AliceParameters { - buy: key_gen.get_pubkey(ArbitratingKeyId::Buy)?, - cancel: key_gen.get_pubkey(ArbitratingKeyId::Cancel)?, - refund: key_gen.get_pubkey(ArbitratingKeyId::Refund)?, - punish: key_gen.get_pubkey(ArbitratingKeyId::Punish)?, - adaptor, - extra_arbitrating_keys: extra_arbitrating_keys?, - arbitrating_shared_keys: arbitrating_shared_keys?, - spend, - extra_accordant_keys: extra_accordant_keys?, - accordant_shared_keys: accordant_shared_keys?, - destination_address: self.destination_address.clone(), - proof, - cancel_timelock: Some(public_offer.offer.cancel_timelock), - punish_timelock: Some(public_offer.offer.punish_timelock), - fee_strategy: Some(public_offer.offer.fee_strategy.clone()), - }) + Ok(( + AliceParameters { + buy: key_gen.get_pubkey(ArbitratingKeyId::Buy)?, + cancel: key_gen.get_pubkey(ArbitratingKeyId::Cancel)?, + refund: key_gen.get_pubkey(ArbitratingKeyId::Refund)?, + punish: key_gen.get_pubkey(ArbitratingKeyId::Punish)?, + adaptor, + extra_arbitrating_keys: extra_arbitrating_keys?, + arbitrating_shared_keys: arbitrating_shared_keys?, + spend, + extra_accordant_keys: extra_accordant_keys?, + accordant_shared_keys: accordant_shared_keys?, + destination_address: self.destination_address.clone(), + cancel_timelock: Some(public_offer.offer.cancel_timelock), + punish_timelock: Some(public_offer.offer.punish_timelock), + fee_strategy: Some(public_offer.offer.fee_strategy.clone()), + }, + Proof { proof }, + )) } /// Generates the witness on the [`Refundable`] transaction and adaptor sign it. @@ -791,7 +793,7 @@ impl Bob { Ctx::Proof, >, public_offer: &PublicOffer, - ) -> Res> { + ) -> Res<(BobParameters, Proof)> { let extra_arbitrating_keys: Res::PublicKey>> = ::extra_keys() .into_iter() @@ -832,22 +834,24 @@ impl Bob { let (spend, adaptor, proof) = key_gen.generate_proof()?; - Ok(BobParameters { - buy: key_gen.get_pubkey(ArbitratingKeyId::Buy)?, - cancel: key_gen.get_pubkey(ArbitratingKeyId::Cancel)?, - refund: key_gen.get_pubkey(ArbitratingKeyId::Refund)?, - adaptor, - extra_arbitrating_keys: extra_arbitrating_keys?, - arbitrating_shared_keys: arbitrating_shared_keys?, - spend, - extra_accordant_keys: extra_accordant_keys?, - accordant_shared_keys: accordant_shared_keys?, - refund_address: self.refund_address.clone(), - proof, - cancel_timelock: Some(public_offer.offer.cancel_timelock), - punish_timelock: Some(public_offer.offer.punish_timelock), - fee_strategy: Some(public_offer.offer.fee_strategy.clone()), - }) + Ok(( + BobParameters { + buy: key_gen.get_pubkey(ArbitratingKeyId::Buy)?, + cancel: key_gen.get_pubkey(ArbitratingKeyId::Cancel)?, + refund: key_gen.get_pubkey(ArbitratingKeyId::Refund)?, + adaptor, + extra_arbitrating_keys: extra_arbitrating_keys?, + arbitrating_shared_keys: arbitrating_shared_keys?, + spend, + extra_accordant_keys: extra_accordant_keys?, + accordant_shared_keys: accordant_shared_keys?, + refund_address: self.refund_address.clone(), + cancel_timelock: Some(public_offer.offer.cancel_timelock), + punish_timelock: Some(public_offer.offer.punish_timelock), + fee_strategy: Some(public_offer.offer.fee_strategy.clone()), + }, + Proof { proof }, + )) } /// Initialize the core arbitrating transactions composed of: [`Lockable`], [`Cancelable`], and diff --git a/tests/bundles.rs b/tests/bundles.rs index 54a293a2..2a3cddc6 100644 --- a/tests/bundles.rs +++ b/tests/bundles.rs @@ -1,7 +1,7 @@ use farcaster_core::swap::btcxmr::{BtcXmr, KeyManager}; use farcaster_core::blockchain::FeePriority; -use farcaster_core::bundle::{AliceParameters, BobParameters}; +use farcaster_core::bundle::{AliceParameters, BobParameters, Proof}; use farcaster_core::consensus::deserialize; use farcaster_core::crypto::CommitmentEngine; use farcaster_core::negotiation::PublicOffer; @@ -58,11 +58,12 @@ fn create_alice_parameters() { .unwrap(); let commitment_engine = CommitmentEngine; - let alice_params = alice + let (alice_params, alice_proof) = alice .generate_parameters(&mut key_manager, &pub_offer) .unwrap(); test_strict_ser!(alice_params, AliceParameters); + test_strict_ser!(alice_proof, Proof); let commit_alice_params = CommitAliceParameters::commit_to_bundle(swap_id, &commitment_engine, alice_params.clone()); @@ -91,11 +92,12 @@ fn create_bob_parameters() { .unwrap(); let commitment_engine = CommitmentEngine; - let bob_params = bob + let (bob_params, bob_proof) = bob .generate_parameters(&mut key_manager, &pub_offer) .unwrap(); test_strict_ser!(bob_params, BobParameters); + test_strict_ser!(bob_proof, Proof); let commit_bob_params = CommitBobParameters::commit_to_bundle(swap_id, &commitment_engine, bob_params.clone()); @@ -133,7 +135,7 @@ fn tampered_reveal_must_fail() { .unwrap(); let commitment_engine = CommitmentEngine; - let bob_params = bob + let (bob_params, _bob_proof) = bob .generate_parameters(&mut key_manager, &pub_offer) .unwrap(); @@ -144,7 +146,8 @@ fn tampered_reveal_must_fail() { let reveal_bob_params: RevealBobParameters<_> = ( swap_id, bob.generate_parameters(&mut key_manager2, &pub_offer) - .unwrap(), + .unwrap() + .0, ) .into(); // MUST error since we reveal other parameters @@ -167,7 +170,7 @@ fn missing_commitment_in_vec() { .unwrap(); let commitment_engine = CommitmentEngine; - let bob_params = bob + let (bob_params, _bob_proof) = bob .generate_parameters(&mut key_manager, &pub_offer) .unwrap(); let mut partial_params = bob_params; @@ -181,7 +184,8 @@ fn missing_commitment_in_vec() { let reveal_bob_params: RevealBobParameters<_> = ( swap_id, bob.generate_parameters(&mut key_manager, &pub_offer) - .unwrap(), + .unwrap() + .0, ) .into(); // MUST error since we reveal params not committed diff --git a/tests/protocol.rs b/tests/protocol.rs index afc8239f..d0663631 100644 --- a/tests/protocol.rs +++ b/tests/protocol.rs @@ -77,14 +77,14 @@ fn execute_offline_protocol() { // // Commit/Reveal round // - let alice_params = alice + let (alice_params, _alice_proof) = alice .generate_parameters(&mut alice_key_manager, &pub_offer) .unwrap(); let commit_alice_params = CommitAliceParameters::commit_to_bundle(swap_id, &commitment_engine, alice_params.clone()); test_strict_ser!(commit_alice_params, CommitAliceParameters); - let bob_params = bob + let (bob_params, _bob_proof) = bob .generate_parameters(&mut bob_key_manager, &pub_offer) .unwrap(); let commit_bob_params =