Browse Source

Test force-closing a cfd

Allow specifying oracle announcement and delivering a matching attestation for
it to decrypt the Cfd.
remove-long-heartbeat-interval-in-debug-mode
Mariusz Klochowicz 3 years ago
parent
commit
526838cbf6
No known key found for this signature in database GPG Key ID: 470C865699C8D4D
  1. 51
      daemon/tests/happy_path.rs
  2. 9
      daemon/tests/harness/maia.rs
  3. 12
      daemon/tests/harness/mocks/mod.rs
  4. 21
      daemon/tests/harness/mocks/oracle.rs
  5. 9
      daemon/tests/harness/mod.rs

51
daemon/tests/happy_path.rs

@ -5,6 +5,8 @@ use crate::harness::flow::next_cfd;
use crate::harness::flow::next_order; use crate::harness::flow::next_order;
use crate::harness::flow::next_some; use crate::harness::flow::next_some;
use crate::harness::init_tracing; use crate::harness::init_tracing;
use crate::harness::maia::OliviaData;
use crate::harness::mocks::oracle::dummy_wrong_attestation;
use crate::harness::start_both; use crate::harness::start_both;
use crate::harness::Maker; use crate::harness::Maker;
use crate::harness::MakerConfig; use crate::harness::MakerConfig;
@ -14,6 +16,7 @@ use daemon::connection::ConnectionStatus;
use daemon::model::cfd::OrderId; use daemon::model::cfd::OrderId;
use daemon::model::Usd; use daemon::model::Usd;
use daemon::monitor::Event; use daemon::monitor::Event;
use daemon::oracle;
use daemon::projection::CfdState; use daemon::projection::CfdState;
use daemon::projection::Identity; use daemon::projection::Identity;
use maia::secp256k1_zkp::schnorrsig; use maia::secp256k1_zkp::schnorrsig;
@ -129,7 +132,8 @@ async fn taker_takes_order_and_maker_accepts_and_contract_setup() {
#[tokio::test] #[tokio::test]
async fn collaboratively_close_an_open_cfd() { async fn collaboratively_close_an_open_cfd() {
let _guard = init_tracing(); let _guard = init_tracing();
let (mut maker, mut taker, order_id) = start_from_open_cfd_state().await; let (mut maker, mut taker, order_id) =
start_from_open_cfd_state(OliviaData::example_0().announcement()).await;
taker.propose_settlement(order_id).await; taker.propose_settlement(order_id).await;
@ -152,6 +156,38 @@ async fn collaboratively_close_an_open_cfd() {
assert_next_state!(CfdState::Closed, maker, taker, order_id); assert_next_state!(CfdState::Closed, maker, taker, order_id);
} }
#[tokio::test]
async fn force_close_an_open_cfd() {
let _guard = init_tracing();
let oracle_data = OliviaData::example_0();
let (mut maker, mut taker, order_id) =
start_from_open_cfd_state(oracle_data.announcement()).await;
// Taker initiates force-closing
taker.force_close(order_id).await;
deliver_event!(maker, taker, Event::CommitFinality(order_id));
sleep(Duration::from_secs(5)).await; // need to wait a bit until both transition
assert_next_state!(CfdState::OpenCommitted, maker, taker, order_id);
// After CetTimelockExpired, we're only waiting for attestation
deliver_event!(maker, taker, Event::CetTimelockExpired(order_id));
// Delivering the wrong attestation does not move state to `PendingCet`
deliver_event!(maker, taker, dummy_wrong_attestation());
sleep(Duration::from_secs(5)).await; // need to wait a bit until both transition
assert_next_state!(CfdState::OpenCommitted, maker, taker, order_id);
// Delivering correct attestation moves the state `PendingCet`
deliver_event!(maker, taker, oracle_data.attestation());
sleep(Duration::from_secs(5)).await; // need to wait a bit until both transition
assert_next_state!(CfdState::PendingCet, maker, taker, order_id);
deliver_event!(maker, taker, Event::CetFinality(order_id));
sleep(Duration::from_secs(5)).await; // need to wait a bit until both transition
assert_next_state!(CfdState::Closed, maker, taker, order_id);
}
#[tokio::test] #[tokio::test]
async fn taker_notices_lack_of_maker() { async fn taker_notices_lack_of_maker() {
let short_interval = Duration::from_secs(1); let short_interval = Duration::from_secs(1);
@ -217,7 +253,8 @@ async fn maker_notices_lack_of_taker() {
/// Hide the implementation detail of arriving at the Cfd open state. /// Hide the implementation detail of arriving at the Cfd open state.
/// Useful when reading tests that should start at this point. /// Useful when reading tests that should start at this point.
/// For convenience, returns also OrderId of the opened Cfd. /// For convenience, returns also OrderId of the opened Cfd.
async fn start_from_open_cfd_state() -> (Maker, Taker, OrderId) { /// `announcement` is used during Cfd's creation.
async fn start_from_open_cfd_state(announcement: oracle::Announcement) -> (Maker, Taker, OrderId) {
let heartbeat_interval = Duration::from_secs(60); let heartbeat_interval = Duration::from_secs(60);
let maker_listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); let maker_listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap();
let mut maker = Maker::start( let mut maker = Maker::start(
@ -240,8 +277,14 @@ async fn start_from_open_cfd_state() -> (Maker, Taker, OrderId) {
.await .await
.unwrap(); .unwrap();
taker.mocks.mock_oracle_announcement().await; taker
maker.mocks.mock_oracle_announcement().await; .mocks
.mock_oracle_announcement_with(announcement.clone())
.await;
maker
.mocks
.mock_oracle_announcement_with(announcement)
.await;
taker.take_order(received.clone(), Usd::new(dec!(5))).await; taker.take_order(received.clone(), Usd::new(dec!(5))).await;
let (_, _) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap(); let (_, _) = next_cfd(taker.cfd_feed(), maker.cfd_feed()).await.unwrap();

9
daemon/tests/harness/maia.rs

@ -1,4 +1,5 @@
use daemon::model::BitMexPriceEventId; use daemon::model::BitMexPriceEventId;
use daemon::oracle::Attestation;
use daemon::oracle::{self}; use daemon::oracle::{self};
use maia::secp256k1_zkp::schnorrsig; use maia::secp256k1_zkp::schnorrsig;
use maia::secp256k1_zkp::SecretKey; use maia::secp256k1_zkp::SecretKey;
@ -59,6 +60,14 @@ impl OliviaData {
} }
} }
pub fn attestation(&self) -> Attestation {
Attestation {
id: self.id,
price: self.price,
scalars: self.attestations.clone(),
}
}
const OLIVIA_PK: &'static str = const OLIVIA_PK: &'static str =
"ddd4636845a90185991826be5a494cde9f4a6947b1727217afedc6292fa4caf7"; "ddd4636845a90185991826be5a494cde9f4a6947b1727217afedc6292fa4caf7";

12
daemon/tests/harness/mocks/mod.rs

@ -7,6 +7,8 @@ use self::monitor::MonitorActor;
use self::oracle::OracleActor; use self::oracle::OracleActor;
use self::wallet::WalletActor; use self::wallet::WalletActor;
use super::maia::OliviaData;
pub mod monitor; pub mod monitor;
pub mod oracle; pub mod oracle;
pub mod wallet; pub mod wallet;
@ -49,10 +51,18 @@ impl Mocks {
} }
pub async fn mock_oracle_announcement(&mut self) { pub async fn mock_oracle_announcement(&mut self) {
self.mock_oracle_announcement_with(OliviaData::example_0().announcement())
.await;
}
pub async fn mock_oracle_announcement_with(
&mut self,
announcement: daemon::oracle::Announcement,
) {
self.oracle() self.oracle()
.await .await
.expect_get_announcement() .expect_get_announcement()
.return_const(Ok(oracle::dummy_announcement())); .return_const(Ok(announcement));
} }
pub async fn mock_oracle_monitor_attestation(&mut self) { pub async fn mock_oracle_monitor_attestation(&mut self) {

21
daemon/tests/harness/mocks/oracle.rs

@ -1,10 +1,13 @@
use crate::harness::maia::OliviaData; use daemon::model::BitMexPriceEventId;
use daemon::oracle; use daemon::oracle;
use mockall::*; use mockall::*;
use std::sync::Arc; use std::sync::Arc;
use time::OffsetDateTime;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use xtra_productivity::xtra_productivity; use xtra_productivity::xtra_productivity;
use crate::harness::maia::OliviaData;
/// Test Stub simulating the Oracle actor. /// Test Stub simulating the Oracle actor.
/// Serves as an entrypoint for injected mock handlers. /// Serves as an entrypoint for injected mock handlers.
pub struct OracleActor { pub struct OracleActor {
@ -50,6 +53,18 @@ pub trait Oracle {
} }
} }
pub fn dummy_announcement() -> oracle::Announcement { /// We do *not* depend on the current time in our tests, the valid combination of
OliviaData::example_0().announcement() /// announcement/attestation is hard-coded in OliviaData struct (along with event id's).
/// Therefore, an attestation based on current utc time will always be wrong.
pub fn dummy_wrong_attestation() -> oracle::Attestation {
let oracle::Attestation {
id: _,
price,
scalars,
} = OliviaData::example_0().attestation();
oracle::Attestation {
id: BitMexPriceEventId::with_20_digits(OffsetDateTime::now_utc()),
price,
scalars,
}
} }

9
daemon/tests/harness/mod.rs

@ -352,6 +352,15 @@ impl Taker {
.unwrap() .unwrap()
.unwrap(); .unwrap();
} }
pub async fn force_close(&self, order_id: OrderId) {
self.system
.cfd_actor_addr
.send(taker_cfd::Commit { order_id })
.await
.unwrap()
.unwrap();
}
} }
/// Deliver monitor event to both actor systems /// Deliver monitor event to both actor systems

Loading…
Cancel
Save