-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement 3 CronTickTimedoutDeals tests. (#310)
- Loading branch information
Showing
1 changed file
with
216 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
// Copyright 2019-2022 ChainSafe Systems | ||
// SPDX-License-Identifier: Apache-2.0, MIT | ||
|
||
use fil_actor_market::ext::verifreg::RestoreBytesParams; | ||
use fil_actor_market::{ | ||
ext, Actor as MarketActor, ClientDealProposal, Method, PublishStorageDealsParams, | ||
}; | ||
use fil_actors_runtime::network::EPOCHS_IN_DAY; | ||
use fil_actors_runtime::test_utils::*; | ||
use fil_actors_runtime::{BURNT_FUNDS_ACTOR_ADDR, VERIFIED_REGISTRY_ACTOR_ADDR}; | ||
use fvm_ipld_encoding::RawBytes; | ||
use fvm_shared::clock::ChainEpoch; | ||
use fvm_shared::crypto::signature::Signature; | ||
use fvm_shared::econ::TokenAmount; | ||
use fvm_shared::error::ExitCode; | ||
use fvm_shared::sector::StoragePower; | ||
use fvm_shared::METHOD_SEND; | ||
|
||
use num_traits::Zero; | ||
|
||
mod harness; | ||
use harness::*; | ||
|
||
const START_EPOCH: ChainEpoch = 50; | ||
const END_EPOCH: ChainEpoch = START_EPOCH + 200 * EPOCHS_IN_DAY; | ||
|
||
#[test] | ||
fn timed_out_deal_is_slashed_and_deleted() { | ||
let mut rt = setup(); | ||
let deal_id = generate_and_publish_deal( | ||
&mut rt, | ||
CLIENT_ADDR, | ||
&MinerAddresses::default(), | ||
START_EPOCH, | ||
END_EPOCH, | ||
); | ||
let deal_proposal = get_deal_proposal(&mut rt, deal_id); | ||
|
||
let c_escrow = get_escrow_balance(&rt, &CLIENT_ADDR).unwrap(); | ||
|
||
// do a cron tick for it -> should time out and get slashed | ||
rt.set_epoch(process_epoch(START_EPOCH, deal_id)); | ||
rt.expect_send( | ||
*BURNT_FUNDS_ACTOR_ADDR, | ||
METHOD_SEND, | ||
RawBytes::default(), | ||
deal_proposal.provider_collateral.clone(), | ||
RawBytes::default(), | ||
ExitCode::OK, | ||
); | ||
cron_tick(&mut rt); | ||
|
||
assert_eq!(c_escrow, get_escrow_balance(&rt, &CLIENT_ADDR).unwrap()); | ||
assert!(get_locked_balance(&mut rt, CLIENT_ADDR).is_zero()); | ||
assert_account_zero(&mut rt, PROVIDER_ADDR); | ||
assert_deal_deleted(&mut rt, deal_id, deal_proposal); | ||
check_state(&rt); | ||
} | ||
|
||
#[test] | ||
fn publishing_timed_out_deal_again_should_work_after_cron_tick_as_it_should_no_longer_be_pending() { | ||
const START_EPOCH: ChainEpoch = 0; | ||
let mut rt = setup(); | ||
let deal_id = generate_and_publish_deal( | ||
&mut rt, | ||
CLIENT_ADDR, | ||
&MinerAddresses::default(), | ||
START_EPOCH, | ||
END_EPOCH, | ||
); | ||
let deal_proposal = get_deal_proposal(&mut rt, deal_id); | ||
|
||
// publishing will fail as it will be in pending | ||
let deal_proposal2 = generate_deal_and_add_funds( | ||
&mut rt, | ||
CLIENT_ADDR, | ||
&MinerAddresses::default(), | ||
START_EPOCH, | ||
END_EPOCH, | ||
); | ||
let buf = RawBytes::serialize(deal_proposal2.clone()).expect("failed to marshal deal proposal"); | ||
let sig = Signature::new_bls("does not matter".as_bytes().to_vec()); | ||
let client_deal_proposal = | ||
ClientDealProposal { proposal: deal_proposal2.clone(), client_signature: sig.clone() }; | ||
let params = PublishStorageDealsParams { deals: vec![client_deal_proposal] }; | ||
rt.expect_validate_caller_type(vec![*ACCOUNT_ACTOR_CODE_ID, *MULTISIG_ACTOR_CODE_ID]); | ||
expect_provider_control_address(&mut rt, PROVIDER_ADDR, OWNER_ADDR, WORKER_ADDR); | ||
expect_query_network_info(&mut rt); | ||
rt.set_caller(*ACCOUNT_ACTOR_CODE_ID, WORKER_ADDR); | ||
rt.expect_verify_signature(ExpectedVerifySig { | ||
sig, | ||
signer: deal_proposal2.client, | ||
plaintext: buf.to_vec(), | ||
result: Ok(()), | ||
}); | ||
expect_abort( | ||
ExitCode::USR_ILLEGAL_ARGUMENT, | ||
rt.call::<MarketActor>( | ||
Method::PublishStorageDeals as u64, | ||
&RawBytes::serialize(params).unwrap(), | ||
), | ||
); | ||
rt.verify(); | ||
|
||
// do a cron tick for it -> should time out and get slashed | ||
rt.set_epoch(process_epoch(START_EPOCH, deal_id)); | ||
rt.expect_send( | ||
*BURNT_FUNDS_ACTOR_ADDR, | ||
METHOD_SEND, | ||
RawBytes::default(), | ||
deal_proposal.provider_collateral.clone(), | ||
RawBytes::default(), | ||
ExitCode::OK, | ||
); | ||
cron_tick(&mut rt); | ||
assert_deal_deleted(&mut rt, deal_id, deal_proposal); | ||
|
||
// now publishing should work | ||
generate_and_publish_deal( | ||
&mut rt, | ||
CLIENT_ADDR, | ||
&MinerAddresses::default(), | ||
START_EPOCH, | ||
END_EPOCH, | ||
); | ||
check_state(&rt); | ||
} | ||
|
||
#[test] | ||
fn timed_out_and_verified_deals_are_slashed_deleted_and_sent_to_the_registry_actor() { | ||
let mut rt = setup(); | ||
let mut deal1 = generate_deal_and_add_funds( | ||
&mut rt, | ||
CLIENT_ADDR, | ||
&MinerAddresses::default(), | ||
START_EPOCH, | ||
END_EPOCH, | ||
); | ||
deal1.verified_deal = true; | ||
let mut deal2 = generate_deal_and_add_funds( | ||
&mut rt, | ||
CLIENT_ADDR, | ||
&MinerAddresses::default(), | ||
START_EPOCH, | ||
END_EPOCH + 1, | ||
); | ||
deal2.verified_deal = true; | ||
|
||
// deal3 is NOT verified | ||
let deal3 = generate_deal_and_add_funds( | ||
&mut rt, | ||
CLIENT_ADDR, | ||
&MinerAddresses::default(), | ||
START_EPOCH, | ||
END_EPOCH + 2, | ||
); | ||
|
||
// publishing verified deals | ||
rt.set_caller(*ACCOUNT_ACTOR_CODE_ID, WORKER_ADDR); | ||
let deal_ids = publish_deals( | ||
&mut rt, | ||
&MinerAddresses::default(), | ||
&[deal1.clone(), deal2.clone(), deal3.clone()], | ||
); | ||
|
||
// do a cron tick for it -> all should time out and get slashed | ||
// ONLY deal1 and deal2 should be sent to the Registry actor | ||
rt.set_epoch(process_epoch(START_EPOCH, *deal_ids.last().unwrap())); | ||
|
||
// expected sends to the registry actor | ||
let param1 = RestoreBytesParams { | ||
address: deal1.client, | ||
deal_size: StoragePower::from(deal1.piece_size.0), | ||
}; | ||
let param2 = RestoreBytesParams { | ||
address: deal2.client, | ||
deal_size: StoragePower::from(deal2.piece_size.0), | ||
}; | ||
|
||
rt.expect_send( | ||
*VERIFIED_REGISTRY_ACTOR_ADDR, | ||
ext::verifreg::RESTORE_BYTES_METHOD as u64, | ||
RawBytes::serialize(param1).unwrap(), | ||
TokenAmount::zero(), | ||
RawBytes::default(), | ||
ExitCode::OK, | ||
); | ||
rt.expect_send( | ||
*VERIFIED_REGISTRY_ACTOR_ADDR, | ||
ext::verifreg::RESTORE_BYTES_METHOD as u64, | ||
RawBytes::serialize(param2).unwrap(), | ||
TokenAmount::zero(), | ||
RawBytes::default(), | ||
ExitCode::OK, | ||
); | ||
|
||
let expected_burn = 3 * &deal1.provider_collateral; | ||
rt.expect_send( | ||
*BURNT_FUNDS_ACTOR_ADDR, | ||
METHOD_SEND, | ||
RawBytes::default(), | ||
expected_burn, | ||
RawBytes::default(), | ||
ExitCode::OK, | ||
); | ||
cron_tick(&mut rt); | ||
|
||
// a second cron tick for the same epoch should not change anything | ||
cron_tick_no_change(&mut rt, CLIENT_ADDR, PROVIDER_ADDR); | ||
|
||
assert_account_zero(&mut rt, PROVIDER_ADDR); | ||
assert_deal_deleted(&mut rt, deal_ids[0], deal1); | ||
assert_deal_deleted(&mut rt, deal_ids[1], deal2); | ||
assert_deal_deleted(&mut rt, deal_ids[2], deal3); | ||
check_state(&rt); | ||
} |