Browse Source

Add acknowledge message at the end of contract setup

This is to avoid going on chain in a scenario where one party sent the signed lock transaction, but did not get the signed transaction from the other party before running into the timeout.
With this solution, we fail the setup (on either side) if we don't receive an acknowledgment message at the end of the setup.

The acknoledge message is a temporary fix.
Once we add monitoring for incomplete DLCs (special case of contract-setup / rollover / collaborative-settlement failing) the ack message should be removed.
chore/leaner-release-process
Daniel Karzel 3 years ago
parent
commit
57ad8a645a
No known key found for this signature in database GPG Key ID: 30C3FC2E438ADB6E
  1. 17
      daemon/src/setup_contract.rs
  2. 18
      daemon/src/wire.rs

17
daemon/src/setup_contract.rs

@ -2,7 +2,7 @@ use crate::model::cfd::{Cet, Dlc, RevokedCommit, Role};
use crate::model::{Leverage, Price, Usd}; use crate::model::{Leverage, Price, Usd};
use crate::tokio_ext::FutureExt; use crate::tokio_ext::FutureExt;
use crate::wire::{ use crate::wire::{
Msg0, Msg1, Msg2, RollOverMsg, RollOverMsg0, RollOverMsg1, RollOverMsg2, SetupMsg, Msg0, Msg1, Msg2, Msg3, RollOverMsg, RollOverMsg0, RollOverMsg1, RollOverMsg2, SetupMsg,
}; };
use crate::{model, oracle, payout_curve, wallet}; use crate::{model, oracle, payout_curve, wallet};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
@ -231,6 +231,8 @@ pub async fn new(
.merge(msg2.signed_lock) .merge(msg2.signed_lock)
.context("Failed to merge lock PSBTs")?; .context("Failed to merge lock PSBTs")?;
tracing::info!("Exchanged signed lock transaction");
// TODO: In case we sign+send but never receive (the signed lock_tx from the other party) we // TODO: In case we sign+send but never receive (the signed lock_tx from the other party) we
// need some fallback handling (after x time) to spend the outputs in a different way so the // need some fallback handling (after x time) to spend the outputs in a different way so the
// other party cannot hold us hostage // other party cannot hold us hostage
@ -271,7 +273,18 @@ pub async fn new(
}) })
.collect::<Result<HashMap<_, _>>>()?; .collect::<Result<HashMap<_, _>>>()?;
tracing::info!("Exchanged signed lock transaction"); // TODO: Remove send- and receiving ACK messages once we are able to handle incomplete DLC
// monitoring
sink.send(SetupMsg::Msg3(Msg3))
.await
.context("Failed to send Msg3")?;
let _ = stream
.select_next_some()
.timeout(Duration::from_secs(60))
.await
.context("Expected Msg3 within 60 seconds")?
.try_into_msg3()
.context("Failed to read Msg3")?;
Ok(Dlc { Ok(Dlc {
identity: sk, identity: sk,

18
daemon/src/wire.rs

@ -209,6 +209,13 @@ pub enum SetupMsg {
/// Upon receiving this message from the other party we merge our signature and then the lock /// Upon receiving this message from the other party we merge our signature and then the lock
/// tx is fully signed and can be published on chain. /// tx is fully signed and can be published on chain.
Msg2(Msg2), Msg2(Msg2),
/// Message acknowledging that we received everything
///
/// Simple ACK message used at the end of the message exchange to ensure that both parties sent
/// and received everything and we did not run into timeouts on the other side.
/// This is used to avoid one party publishing the lock transaction while the other party ran
/// into a timeout.
Msg3(Msg3),
} }
impl SetupMsg { impl SetupMsg {
@ -235,6 +242,14 @@ impl SetupMsg {
bail!("Not Msg2") bail!("Not Msg2")
} }
} }
pub fn try_into_msg3(self) -> Result<Msg3> {
if let Self::Msg3(v) = self {
Ok(v)
} else {
bail!("Not Msg3")
}
}
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -334,6 +349,9 @@ pub struct Msg2 {
pub signed_lock: PartiallySignedTransaction, // TODO: Use binary representation pub signed_lock: PartiallySignedTransaction, // TODO: Use binary representation
} }
#[derive(Debug, Serialize, Deserialize)]
pub struct Msg3;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type", content = "payload")] #[serde(tag = "type", content = "payload")]
pub enum RollOverMsg { pub enum RollOverMsg {

Loading…
Cancel
Save