Skip to content

Commit

Permalink
test: add integration test
Browse files Browse the repository at this point in the history
  • Loading branch information
hunjixin committed Aug 26, 2022
1 parent 8cd5400 commit db0e8b7
Show file tree
Hide file tree
Showing 4 changed files with 490 additions and 5 deletions.
12 changes: 11 additions & 1 deletion actors/miner/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,14 +409,24 @@ pub struct ProveReplicaUpdatesParams2 {

impl Cbor for ProveReplicaUpdatesParams2 {}

#[derive(Debug, Serialize_tuple, Deserialize_tuple)]
#[derive(Debug, Clone, Serialize_tuple, Deserialize_tuple)]
pub struct ChangeBeneficiaryParams {
pub new_beneficiary: Address,
#[serde(with = "bigint_ser")]
pub new_quota: TokenAmount,
pub new_expiration: ChainEpoch,
}

impl ChangeBeneficiaryParams {
pub fn new(beneficiary: Address, quota: TokenAmount, expiration: ChainEpoch) -> Self {
ChangeBeneficiaryParams {
new_beneficiary: beneficiary,
new_quota: quota,
new_expiration: expiration,
}
}
}

impl Cbor for ChangeBeneficiaryParams {}

#[derive(Debug, Serialize_tuple, Deserialize_tuple)]
Expand Down
50 changes: 46 additions & 4 deletions test_vm/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ use fil_actor_market::{
};
use fil_actor_miner::{
aggregate_pre_commit_network_fee, max_prove_commit_duration,
new_deadline_info_from_offset_and_epoch, Deadline, DeadlineInfo, DeclareFaultsRecoveredParams,
Method as MinerMethod, PoStPartition, PowerPair, PreCommitSectorBatchParams,
PreCommitSectorParams, ProveCommitAggregateParams, RecoveryDeclaration, SectorOnChainInfo,
SectorPreCommitOnChainInfo, State as MinerState, SubmitWindowedPoStParams,
new_deadline_info_from_offset_and_epoch, ChangeBeneficiaryParams, Deadline, DeadlineInfo,
DeclareFaultsRecoveredParams, GetBeneficiaryReturn, Method as MinerMethod, PoStPartition,
PowerPair, PreCommitSectorBatchParams, PreCommitSectorParams, ProveCommitAggregateParams,
RecoveryDeclaration, SectorOnChainInfo, SectorPreCommitOnChainInfo, State as MinerState,
SubmitWindowedPoStParams, WithdrawBalanceParams, WithdrawBalanceReturn,
};
use fil_actor_multisig::Method as MultisigMethod;
use fil_actor_multisig::ProposeParams;
Expand Down Expand Up @@ -497,6 +498,47 @@ pub fn submit_windowed_post(
.matches(v.take_invocations().last().unwrap());
}

pub fn change_beneficiary(
v: &VM,
from: Address,
maddr: Address,
beneficiary_change_proposal: &ChangeBeneficiaryParams,
) {
apply_ok(
v,
from,
maddr,
TokenAmount::zero(),
MinerMethod::ChangeBeneficiary as u64,
beneficiary_change_proposal.clone(),
);
}

pub fn get_beneficiary(v: &VM, from: Address, m_addr: Address) -> GetBeneficiaryReturn {
apply_ok(
v,
from,
m_addr,
TokenAmount::zero(),
MinerMethod::GetBeneficiary as u64,
RawBytes::default(),
)
.deserialize()
.unwrap()
}

pub fn withdraw_balance(
v: &VM,
from: Address,
m_addr: Address,
amount_requested: TokenAmount,
) -> WithdrawBalanceReturn {
let params = WithdrawBalanceParams { amount_requested };
apply_ok(v, from, m_addr, TokenAmount::zero(), MinerMethod::WithdrawBalance as u64, params)
.deserialize()
.unwrap()
}

pub fn submit_invalid_post(
v: &VM,
worker: Address,
Expand Down
248 changes: 248 additions & 0 deletions test_vm/tests/change_beneficiary_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
use fil_actor_miner::{
ActiveBeneficiary, ChangeBeneficiaryParams, Method as MinerMethod, PendingBeneficiaryChange,
};
use fvm_ipld_blockstore::MemoryBlockstore;
use fvm_shared::bigint::Zero;
use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ExitCode;
use fvm_shared::sector::RegisteredSealProof;
use test_vm::util::{
apply_code, change_beneficiary, create_accounts, create_miner, get_beneficiary,
withdraw_balance,
};
use test_vm::VM;

#[test]
fn change_beneficiary_success() {
let store = MemoryBlockstore::new();
let mut v = VM::new_with_singletons(&store);
let addrs = create_accounts(&v, 4, TokenAmount::from(10_000e18 as i128));
let seal_proof = RegisteredSealProof::StackedDRG32GiBV1P1;
let (owner, worker, beneficiary, another_beneficiary, query_addr) =
(addrs[0], addrs[0], addrs[1], addrs[2], addrs[3]);

// create miner
let miner_id = create_miner(
&mut v,
owner,
worker,
seal_proof.registered_window_post_proof().unwrap(),
TokenAmount::from(1_000e18 as i128),
)
.0;

//change from owner to beneficiary address
let beneficiary_change_proposal =
ChangeBeneficiaryParams::new(beneficiary, TokenAmount::from(100), 500);
change_beneficiary(&v, owner, miner_id, &beneficiary_change_proposal);
let mut get_beneficiary_return = get_beneficiary(&v, query_addr, miner_id);
let pending_beneficiary_term = get_beneficiary_return.proposed.unwrap();
assert_pending(&beneficiary_change_proposal, &pending_beneficiary_term);
assert!(pending_beneficiary_term.approved_by_beneficiary);
assert!(!pending_beneficiary_term.approved_by_nominee);

change_beneficiary(&v, beneficiary, miner_id, &beneficiary_change_proposal);
get_beneficiary_return = get_beneficiary(&v, query_addr, miner_id);
assert!(get_beneficiary_return.proposed.is_none());
assert_active(&beneficiary_change_proposal, &get_beneficiary_return.active);

//change beneficiary to another address
let change_another_beneificiary_proposal =
ChangeBeneficiaryParams::new(another_beneficiary, TokenAmount::from(100), 500);
change_beneficiary(&v, owner, miner_id, &change_another_beneificiary_proposal);
let mut get_beneficiary_return = get_beneficiary(&v, query_addr, miner_id);
let mut pending_beneficiary_term = get_beneficiary_return.proposed.unwrap();
assert_pending(&change_another_beneificiary_proposal, &pending_beneficiary_term);
assert!(!pending_beneficiary_term.approved_by_beneficiary);
assert!(!pending_beneficiary_term.approved_by_nominee);

change_beneficiary(&v, another_beneficiary, miner_id, &change_another_beneificiary_proposal);
get_beneficiary_return = get_beneficiary(&v, query_addr, miner_id);
pending_beneficiary_term = get_beneficiary_return.proposed.unwrap();
assert_pending(&change_another_beneificiary_proposal, &pending_beneficiary_term);
assert!(!pending_beneficiary_term.approved_by_beneficiary);
assert!(pending_beneficiary_term.approved_by_nominee);

change_beneficiary(&v, beneficiary, miner_id, &change_another_beneificiary_proposal);
get_beneficiary_return = get_beneficiary(&v, query_addr, miner_id);
assert!(get_beneficiary_return.proposed.is_none());
assert_active(&change_another_beneificiary_proposal, &get_beneficiary_return.active);
v.assert_state_invariants();
}

#[test]
fn change_beneficiary_back_owner_success() {
let store = MemoryBlockstore::new();
let mut v = VM::new_with_singletons(&store);
let addrs = create_accounts(&v, 3, TokenAmount::from(10_000e18 as i128));
let seal_proof = RegisteredSealProof::StackedDRG32GiBV1P1;
let (owner, worker, beneficiary, query_addr) = (addrs[0], addrs[0], addrs[1], addrs[2]);

// create miner
let miner_id = create_miner(
&mut v,
owner,
worker,
seal_proof.registered_window_post_proof().unwrap(),
TokenAmount::from(1_000e18 as i128),
)
.0;

let quota = TokenAmount::from(100);
let beneficiary_change_proposal = ChangeBeneficiaryParams::new(beneficiary, quota.clone(), 500);
change_beneficiary(&v, owner, miner_id, &beneficiary_change_proposal);
change_beneficiary(&v, beneficiary, miner_id, &beneficiary_change_proposal);

//case1 need beneficiary(non-main) to confirm
let back_owner_proposal = ChangeBeneficiaryParams::new(owner, TokenAmount::zero(), 0);
change_beneficiary(&v, owner, miner_id, &back_owner_proposal);
change_beneficiary(&v, beneficiary, miner_id, &back_owner_proposal);

let get_beneficiary_return = get_beneficiary(&v, query_addr, miner_id);
assert!(get_beneficiary_return.proposed.is_none());
assert_active(&back_owner_proposal, &get_beneficiary_return.active);

//case2 beneficiary(non-main) used up
change_beneficiary(&v, owner, miner_id, &beneficiary_change_proposal);
change_beneficiary(&v, beneficiary, miner_id, &beneficiary_change_proposal);
let withdraw_return = withdraw_balance(&v, beneficiary, miner_id, quota.clone());
assert_eq!(quota, withdraw_return.amount_withdrawn);

change_beneficiary(&v, owner, miner_id, &back_owner_proposal);
let get_beneficiary_return = get_beneficiary(&v, query_addr, miner_id);
assert!(get_beneficiary_return.proposed.is_none());
assert_active(&back_owner_proposal, &get_beneficiary_return.active);

//case2 beneficiary(non-main) expiration
change_beneficiary(&v, owner, miner_id, &beneficiary_change_proposal);
change_beneficiary(&v, beneficiary, miner_id, &beneficiary_change_proposal);

let v = v.with_epoch(1000);
change_beneficiary(&v, owner, miner_id, &back_owner_proposal);
let get_beneficiary_return = get_beneficiary(&v, query_addr, miner_id);
assert!(get_beneficiary_return.proposed.is_none());
assert_active(&back_owner_proposal, &get_beneficiary_return.active);
}

#[test]
fn change_beneficiary_fail() {
let store = MemoryBlockstore::new();
let mut v = VM::new_with_singletons(&store);
let addrs = create_accounts(&v, 3, TokenAmount::from(10_000e18 as i128));
let seal_proof = RegisteredSealProof::StackedDRG32GiBV1P1;
let (owner, worker, beneficiary, addr) = (addrs[0], addrs[0], addrs[1], addrs[2]);

// create miner
let miner_id = create_miner(
&mut v,
owner,
worker,
seal_proof.registered_window_post_proof().unwrap(),
TokenAmount::from(1_000e18 as i128),
)
.0;

apply_code(
&v,
addr,
miner_id,
TokenAmount::zero(),
MinerMethod::ChangeBeneficiary as u64,
ChangeBeneficiaryParams::new(beneficiary, TokenAmount::from(0), 0),
ExitCode::USR_FORBIDDEN,
);

let beneficiary_change_proposal =
ChangeBeneficiaryParams::new(beneficiary, TokenAmount::from(100), 500);
change_beneficiary(&v, owner, miner_id, &beneficiary_change_proposal);

//argument not match with pending
apply_code(
&v,
beneficiary,
miner_id,
TokenAmount::zero(),
MinerMethod::ChangeBeneficiary as u64,
ChangeBeneficiaryParams::new(beneficiary, TokenAmount::from(100), 400),
ExitCode::USR_ILLEGAL_ARGUMENT,
);

apply_code(
&v,
beneficiary,
miner_id,
TokenAmount::zero(),
MinerMethod::ChangeBeneficiary as u64,
ChangeBeneficiaryParams::new(beneficiary, TokenAmount::from(80), 500),
ExitCode::USR_ILLEGAL_ARGUMENT,
);

apply_code(
&v,
beneficiary,
miner_id,
TokenAmount::zero(),
MinerMethod::ChangeBeneficiary as u64,
ChangeBeneficiaryParams::new(addr, TokenAmount::from(80), 500),
ExitCode::USR_ILLEGAL_ARGUMENT,
);

//message from must be owner/beneficiary/new beneficiary
apply_code(
&v,
addr,
miner_id,
TokenAmount::zero(),
MinerMethod::ChangeBeneficiary as u64,
beneficiary_change_proposal.clone(),
ExitCode::USR_FORBIDDEN,
);
change_beneficiary(&v, beneficiary, miner_id, &beneficiary_change_proposal);

//change back to owner, quota and expiration must be zero
apply_code(
&v,
owner,
miner_id,
TokenAmount::zero(),
MinerMethod::ChangeBeneficiary as u64,
ChangeBeneficiaryParams::new(owner, TokenAmount::from(80), 0),
ExitCode::USR_ILLEGAL_ARGUMENT,
);
apply_code(
&v,
owner,
miner_id,
TokenAmount::zero(),
MinerMethod::ChangeBeneficiary as u64,
ChangeBeneficiaryParams::new(owner, TokenAmount::from(0), 100),
ExitCode::USR_ILLEGAL_ARGUMENT,
);

//success change back to owner
let back_owner_proposal = ChangeBeneficiaryParams::new(owner, TokenAmount::from(0), 0);
change_beneficiary(&v, owner, miner_id, &back_owner_proposal);
change_beneficiary(&v, beneficiary, miner_id, &back_owner_proposal);
v.assert_state_invariants();
}

fn assert_pending(
beneficiary_change_proposal: &ChangeBeneficiaryParams,
pending_beneficiary_term: &PendingBeneficiaryChange,
) {
assert_eq!(
beneficiary_change_proposal.new_beneficiary,
pending_beneficiary_term.new_beneficiary
);
assert_eq!(beneficiary_change_proposal.new_quota, pending_beneficiary_term.new_quota);
assert_eq!(beneficiary_change_proposal.new_expiration, pending_beneficiary_term.new_expiration);
}

fn assert_active(
beneficiary_change_proposal: &ChangeBeneficiaryParams,
active_beneficiary: &ActiveBeneficiary,
) {
assert_eq!(beneficiary_change_proposal.new_beneficiary, active_beneficiary.beneficiary);
assert_eq!(beneficiary_change_proposal.new_quota, active_beneficiary.term.quota);
assert_eq!(beneficiary_change_proposal.new_expiration, active_beneficiary.term.expiration);
}
Loading

0 comments on commit db0e8b7

Please sign in to comment.