Skip to content

Commit

Permalink
create parallels for settlement tests that previously relied on cron_…
Browse files Browse the repository at this point in the history
…tick
  • Loading branch information
alexytsu committed Sep 5, 2023
1 parent e405d3b commit 03c23a5
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 5 deletions.
73 changes: 72 additions & 1 deletion actors/market/tests/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,10 @@ pub fn cron_tick_and_assert_balances(
current_epoch: ChainEpoch,
deal_id: DealID,
) -> (TokenAmount, TokenAmount) {
// fetch current client escrow balances
// fetch current client escrow balances
// NOTE(alexytsu): this code could be factored out and shared it with settle_deal_payments_and_assert_balances
// except that this path will probably be deleted when https://github.com/filecoin-project/builtin-actors/issues/1389
// is actioned
let c_acct = get_balance(rt, &client_addr);
let p_acct = get_balance(rt, &provider_addr);
let mut amount_slashed = TokenAmount::zero();
Expand Down Expand Up @@ -840,6 +843,74 @@ pub fn settle_deal_payments(
res
}

pub fn settle_deal_payments_and_assert_balances(
rt: &MockRuntime,
client_addr: Address,
provider_addr: Address,
current_epoch: ChainEpoch,
deal_id: DealID,
) -> (TokenAmount, TokenAmount) {
// fetch current client escrow balances
let c_acct = get_balance(rt, &client_addr);
let p_acct = get_balance(rt, &provider_addr);
let mut amount_slashed = TokenAmount::zero();

let s = get_deal_state(rt, deal_id);
let d = get_deal_proposal(rt, deal_id);

// end epoch for payment calc
let mut payment_end = d.end_epoch;
if s.slash_epoch != EPOCH_UNDEFINED {
rt.expect_send_simple(
BURNT_FUNDS_ACTOR_ADDR,
METHOD_SEND,
None,
d.provider_collateral.clone(),
None,
ExitCode::OK,
);
amount_slashed = d.provider_collateral;

if s.slash_epoch < d.start_epoch {
payment_end = d.start_epoch;
} else {
payment_end = s.slash_epoch;
}
} else if current_epoch < payment_end {
payment_end = current_epoch;
}

// start epoch for payment calc
let mut payment_start = d.start_epoch;
if s.last_updated_epoch != EPOCH_UNDEFINED {
payment_start = s.last_updated_epoch;
}
let duration = payment_end - payment_start;
let payment = duration * d.storage_price_per_epoch;

// expected updated amounts
let updated_client_escrow = c_acct.balance - &payment;
let updated_provider_escrow = (p_acct.balance + &payment) - &amount_slashed;
let mut updated_client_locked = c_acct.locked - &payment;
let mut updated_provider_locked = p_acct.locked;
// if the deal has expired or been slashed, locked amount will be zero for provider .
let is_deal_expired = payment_end == d.end_epoch;
if is_deal_expired || s.slash_epoch != EPOCH_UNDEFINED {
updated_client_locked = TokenAmount::zero();
updated_provider_locked = TokenAmount::zero();
}

settle_deal_payments(rt, provider_addr, vec![deal_id]);

let client_acct = get_balance(rt, &client_addr);
let provider_acct = get_balance(rt, &provider_addr);
assert_eq!(updated_client_escrow, client_acct.balance);
assert_eq!(updated_client_locked, client_acct.locked);
assert_eq!(updated_provider_escrow, provider_acct.balance);
assert_eq!(updated_provider_locked, provider_acct.locked);
(payment, amount_slashed)
}

pub fn settle_deal_payments_expect_abort(
rt: &MockRuntime,
caller: Address,
Expand Down
80 changes: 76 additions & 4 deletions actors/market/tests/market_actor_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ fn worker_balance_after_withdrawal_must_account_for_slashed_funds() {
);

// activate the deal
activate_deals_legacy(&rt, end_epoch + 1, PROVIDER_ADDR, publish_epoch, &[deal_id]);
activate_deals(&rt, end_epoch + 1, PROVIDER_ADDR, publish_epoch, &[deal_id]);
let st = get_deal_state(&rt, deal_id);
assert_eq!(publish_epoch, st.sector_start_epoch);
let proposal = get_deal_proposal(&rt, deal_id);
Expand Down Expand Up @@ -1348,7 +1348,7 @@ fn terminating_a_deal_removes_proposal_synchronously() {
let rt = setup();
let addrs = &MinerAddresses::default();

let (deal_id, proposal) = publish_and_activate_deal_legacy(
let (deal_id, proposal) = publish_and_activate_deal(
&rt,
CLIENT_ADDR,
addrs,
Expand All @@ -1369,8 +1369,9 @@ fn terminating_a_deal_removes_proposal_synchronously() {
check_state(&rt);
}

// TODO: remove tests for legacy behaviour: https://github.com/filecoin-project/builtin-actors/issues/1389
#[test]
fn fail_when_deal_update_epoch_is_in_the_future() {
fn settling_deal_fails_when_deal_update_epoch_is_in_the_future() {
let start_epoch = 50;
let end_epoch = start_epoch + 200 * EPOCHS_IN_DAY;
let sector_expiry = end_epoch + 100;
Expand All @@ -1397,8 +1398,41 @@ fn fail_when_deal_update_epoch_is_in_the_future() {

// set current epoch of the deal to the end epoch so it's picked up for "processing" in the next cron tick.
rt.set_epoch(end_epoch);

expect_abort(ExitCode::USR_ILLEGAL_STATE, cron_tick_raw(&rt));
let ret = settle_deal_payments(&rt, MinerAddresses::default().provider, vec![deal_id]);
assert_eq!(ret.results.codes(), &[ExitCode::USR_ILLEGAL_STATE]);

check_state_with_expected(
&rt,
&[Regex::new("deal \\d+ last updated epoch \\d+ after current \\d+").unwrap()],
);
}

#[test]
fn _settling_deal_fails_when_deal_update_epoch_is_in_the_future() {
let start_epoch = 50;
let end_epoch = start_epoch + 200 * EPOCHS_IN_DAY;
let sector_expiry = end_epoch + 100;

let rt = setup();

let (deal_id, _) = publish_and_activate_deal(
&rt,
CLIENT_ADDR,
&MinerAddresses::default(),
start_epoch,
end_epoch,
0,
sector_expiry,
);

// update last updated to some time in the future (breaks state invariants)
update_last_updated(&rt, deal_id, end_epoch + 1000);

// set current epoch of the deal to the end epoch so it's picked up for "processing" in the next cron tick.
rt.set_epoch(end_epoch);
let ret = settle_deal_payments(&rt, MinerAddresses::default().provider, vec![deal_id]);
assert_eq!(ret.results.codes(), &[ExitCode::USR_ILLEGAL_STATE]);

check_state_with_expected(
&rt,
Expand All @@ -1407,6 +1441,7 @@ fn fail_when_deal_update_epoch_is_in_the_future() {
}

#[test]
// TODO: remove tests for legacy behaviour: https://github.com/filecoin-project/builtin-actors/issues/1389
fn crontick_for_a_deal_at_its_start_epoch_results_in_zero_payment_and_no_slashing() {
let start_epoch = ChainEpoch::from(50);
let end_epoch = start_epoch + 200 * EPOCHS_IN_DAY;
Expand Down Expand Up @@ -1439,6 +1474,43 @@ fn crontick_for_a_deal_at_its_start_epoch_results_in_zero_payment_and_no_slashin
check_state(&rt);
}

#[test]
fn settling_payments_for_a_deal_at_its_start_epoch_results_in_zero_payment_and_no_slashing() {
let start_epoch = ChainEpoch::from(50);
let end_epoch = start_epoch + 200 * EPOCHS_IN_DAY;
let sector_expiry = end_epoch + 100;

// set start epoch to coincide with processing (0 + 0 % 2880 = 0)
let start_epoch = 0;
let rt = setup();
let (deal_id, _) = publish_and_activate_deal(
&rt,
CLIENT_ADDR,
&MinerAddresses::default(),
start_epoch,
end_epoch,
0,
sector_expiry,
);

// move the current epoch to start
rt.set_epoch(start_epoch);
let (pay, slashed) = settle_deal_payments_and_assert_balances(
&rt,
CLIENT_ADDR,
MinerAddresses::default().provider,
start_epoch,
deal_id,
);
assert_eq!(TokenAmount::zero(), pay);
assert_eq!(TokenAmount::zero(), slashed);

// deal proposal and state should NOT be deleted
get_deal_proposal(&rt, deal_id);
get_deal_state(&rt, deal_id);
check_state(&rt);
}

#[test]
fn slash_a_deal_and_make_payment_for_another_deal_in_the_same_epoch() {
let start_epoch = ChainEpoch::from(50);
Expand Down

0 comments on commit 03c23a5

Please sign in to comment.