Browse Source

Merge pull request #48 from comit-network/refund-timeout

no-contract-setup-message
Philipp Hoenisch 4 years ago
committed by GitHub
parent
commit
f2ebfccda3
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      daemon/src/model/cfd.rs
  2. 25
      daemon/src/taker_cfd_actor.rs

31
daemon/src/model/cfd.rs

@ -299,6 +299,20 @@ fn calculate_profit(
Ok((Amount::ZERO, Usd::ZERO))
}
pub trait AsBlocks {
/// Calculates the duration in Bitcoin blocks.
///
/// On Bitcoin there is a block every 10 minutes/600 seconds on average.
/// It's the caller's responsibility to round the resulting floating point number.
fn as_blocks(&self) -> f32;
}
impl AsBlocks for Duration {
fn as_blocks(&self) -> f32 {
self.as_secs_f32() / 60.0 / 10.0
}
}
/// Calculates the buyer's margin in BTC
///
/// The margin is the initial margin and represents the collateral the buyer has to come up with to
@ -510,6 +524,23 @@ mod tests {
r#"{"type":"Error","payload":{"common":{"transition_timestamp":{"secs_since_epoch":0,"nanos_since_epoch":0}}}}"#
);
}
#[test]
fn test_secs_into_blocks() {
let error_margin = f32::EPSILON;
let duration = Duration::from_secs(600);
let blocks = duration.as_blocks();
assert!(blocks - error_margin < 1.0 && blocks + error_margin > 1.0);
let duration = Duration::from_secs(0);
let blocks = duration.as_blocks();
assert!(blocks - error_margin < 0.0 && blocks + error_margin > 0.0);
let duration = Duration::from_secs(60);
let blocks = duration.as_blocks();
assert!(blocks - error_margin < 0.1 && blocks + error_margin > 0.1);
}
}
/// Contains all data we've assembled about the CFD through the setup protocol.

25
daemon/src/taker_cfd_actor.rs

@ -2,7 +2,9 @@ use crate::db::{
insert_cfd, insert_cfd_offer, insert_new_cfd_state_by_offer_id, load_all_cfds,
load_offer_by_id, OfferOrigin,
};
use crate::model::cfd::{Cfd, CfdOffer, CfdOfferId, CfdState, CfdStateCommon, FinalizedCfd};
use crate::model::cfd::{
AsBlocks, Cfd, CfdOffer, CfdOfferId, CfdState, CfdStateCommon, FinalizedCfd,
};
use crate::model::Usd;
use crate::wire;
use crate::wire::{AdaptorSignature, Msg0, Msg1, SetupMsg};
@ -21,6 +23,20 @@ use std::collections::HashMap;
use std::time::SystemTime;
use tokio::sync::{mpsc, watch};
/// A factor to be added to the CFD offer term for calculating the refund timelock.
///
/// The refund timelock is important in case the oracle disappears or never publishes a signature.
/// Ideally, both users collaboratively settle in the refund scenario. This factor is important if
/// the users do not settle collaboratively.
/// `1.5` times the term as defined in CFD offer should be safe in the extreme case where a user
/// publishes the commit transaction right after the contract was initialized. In this case, the
/// oracle still has `1.0 * cfdoffer.term` time to attest and no one can publish the refund
/// transaction.
/// The downside is that if the oracle disappears: the users would only notice at the end
/// of the cfd term. In this case the users has to wait for another `1.5` times of the
/// term to get his funds back.
pub const REFUND_THRESHOLD: f32 = 1.5;
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
pub enum Command {
@ -119,15 +135,17 @@ where
.build_party_params(bitcoin::Amount::ZERO, pk) // TODO: Load correct quantity from DB
.unwrap();
let cfd = load_offer_by_id(offer_id, &mut conn).await.unwrap();
let (actor, inbox) = setup_contract(
{
let inbox = out_msg_maker_inbox.clone();
move |msg| inbox.send(wire::TakerToMaker::Protocol(msg)).unwrap()
},
taker_params,
sk,
oracle_pk,
cfd,
);
tokio::spawn({
@ -170,6 +188,7 @@ fn setup_contract(
taker: PartyParams,
sk: SecretKey,
oracle_pk: schnorrsig::PublicKey,
offer: CfdOffer,
) -> (
impl Future<Output = FinalizedCfd>,
mpsc::UnboundedSender<SetupMsg>,
@ -193,7 +212,7 @@ fn setup_contract(
(maker.clone(), maker_punish),
(taker.clone(), taker_punish),
oracle_pk,
0, // TODO: Calculate refund timelock based on CFD term
offer.term.mul_f32(REFUND_THRESHOLD).as_blocks().ceil() as u32,
vec![],
sk,
)

Loading…
Cancel
Save