Skip to content

Commit

Permalink
Tests for ProveCommitSectors2 for cases that abort entirely (#1414)
Browse files Browse the repository at this point in the history
  • Loading branch information
anorth committed Jan 22, 2024
1 parent ff66f79 commit a108360
Show file tree
Hide file tree
Showing 5 changed files with 362 additions and 61 deletions.
17 changes: 8 additions & 9 deletions actors/miner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1767,17 +1767,16 @@ impl Actor {
proven_batch_gen.add_success();
} else {
proven_batch_gen.add_fail(ExitCode::USR_ILLEGAL_ARGUMENT);
if params.require_activation_success {
return Err(actor_error!(
illegal_argument,
"invalid proof for sector {} while requiring activation success: {:?}",
precommit.info.sector_number,
res
));
}
}
}
if params.require_activation_success
&& proven_activation_inputs.len() != params.sector_activations.len()
{
return Err(actor_error!(
illegal_argument,
"invalid proof while requiring activation success: {:?}",
res
));
}
} else {
// Verify a single aggregate proof.
verify_aggregate_seal(
Expand Down
251 changes: 251 additions & 0 deletions actors/miner/tests/prove_commit2_failures_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
use fvm_ipld_encoding::RawBytes;
use fvm_shared::address::Address;
use fvm_shared::deal::DealID;
use fvm_shared::error::ExitCode;
use fvm_shared::sector::SectorNumber;
use fvm_shared::{bigint::Zero, clock::ChainEpoch, econ::TokenAmount, ActorID};

use fil_actor_miner::ext::verifreg::AllocationID;
use fil_actor_miner::{
ProveCommitSectors2Params, SectorActivationManifest, ERR_NOTIFICATION_RECEIVER_ABORTED,
ERR_NOTIFICATION_REJECTED,
};
use fil_actors_runtime::test_utils::{expect_abort_contains_message, MockRuntime};
use fil_actors_runtime::EPOCHS_IN_DAY;
use util::*;

mod util;

// Tests for ProveCommitSectors2 where the request fails completely

const CLIENT_ID: ActorID = 1000;
const DEFAULT_SECTOR_EXPIRATION_DAYS: ChainEpoch = 220;
const FIRST_SECTOR_NUMBER: SectorNumber = 100;

#[test]
fn reject_unauthorized_caller() {
let (h, rt, activations) = setup_precommits(&[(0, 0, 0)]);
let cfg = ProveCommitSectors2Config {
caller: Some(Address::new_id(CLIENT_ID)),
..Default::default()
};
expect_abort_contains_message(
ExitCode::USR_FORBIDDEN,
"caller",
h.prove_commit_sectors2(&rt, &activations, false, false, false, cfg),
);
h.check_state(&rt);
}

#[test]
fn reject_no_proof_types() {
let (h, rt, activations) = setup_precommits(&[(0, 0, 0)]);
let cfg = ProveCommitSectors2Config {
param_twiddle: Some(Box::new(|p: &mut ProveCommitSectors2Params| {
p.sector_proofs = vec![];
p.aggregate_proof = RawBytes::default();
})),
..Default::default()
};
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"exactly one of sector proofs or aggregate proof must be non-empty",
h.prove_commit_sectors2(&rt, &activations, false, false, false, cfg),
);
h.check_state(&rt);
}

#[test]
fn reject_both_proof_types() {
let (h, rt, activations) = setup_precommits(&[(0, 0, 0)]);
let cfg = ProveCommitSectors2Config {
param_twiddle: Some(Box::new(|p: &mut ProveCommitSectors2Params| {
p.sector_proofs = vec![RawBytes::new(vec![1, 2, 3, 4])];
p.aggregate_proof = RawBytes::new(vec![1, 2, 3, 4])
})),
..Default::default()
};
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"exactly one of sector proofs or aggregate proof must be non-empty",
h.prove_commit_sectors2(&rt, &activations, false, false, false, cfg),
);
h.check_state(&rt);
}

#[test]
fn reject_mismatched_proof_len() {
let (h, rt, activations) = setup_precommits(&[(0, 0, 0)]);
let cfg = ProveCommitSectors2Config {
param_twiddle: Some(Box::new(|p: &mut ProveCommitSectors2Params| {
p.sector_proofs.push(RawBytes::new(vec![1, 2, 3, 4]));
})),
..Default::default()
};
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"mismatched lengths",
h.prove_commit_sectors2(&rt, &activations, false, false, false, cfg),
);
h.check_state(&rt);
}

#[test]
fn reject_expired_precommit() {
let (h, rt, activations) = setup_precommits(&[(0, 0, 0)]);
let epoch = *rt.epoch.borrow();
rt.set_epoch(epoch + 31 * EPOCHS_IN_DAY); // Expired.
let cfg = ProveCommitSectors2Config::default();
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"no valid precommits",
h.prove_commit_sectors2(&rt, &activations, false, false, false, cfg),
);
h.check_state(&rt);
}

#[test]
fn reject_precommit_deals() {
let (h, rt) = setup_basic();

// Precommit sectors, one with a deal
let precommit_epoch = *rt.epoch.borrow();
let sector_expiry = precommit_epoch + DEFAULT_SECTOR_EXPIRATION_DAYS * EPOCHS_IN_DAY;
let mut precommits =
make_fake_commd_precommits(&h, FIRST_SECTOR_NUMBER, precommit_epoch - 1, sector_expiry, 2);
precommits[0].deal_ids.push(1);
h.pre_commit_sector_batch_v2(&rt, &precommits, true, &TokenAmount::zero()).unwrap();
rt.set_epoch(precommit_epoch + rt.policy.pre_commit_challenge_delay + 1);

let piece_size = h.sector_size as u64;
let manifests: Vec<SectorActivationManifest> = precommits
.iter()
.map(|s| make_activation_manifest(s.sector_number, &[(piece_size, 0, 0, 0)]))
.collect();

let cfg = ProveCommitSectors2Config { validation_failure: vec![0], ..Default::default() };
// Single bad precommit aborts with require_activation_success=true.
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"invalid pre-commit 0 while requiring activation success",
h.prove_commit_sectors2(&rt, &manifests, true, false, false, cfg),
);
h.check_state(&rt);
}

#[test]
fn reject_all_proofs_fail() {
let (h, rt, activations) = setup_precommits(&[(0, 0, 0), (0, 0, 0)]);
let cfg = ProveCommitSectors2Config { proof_failure: vec![0, 1], ..Default::default() };
// If all proofs fail, no need for require_activation_success=true.
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"no valid proofs",
h.prove_commit_sectors2(&rt, &activations, false, false, false, cfg),
);
h.check_state(&rt);
}

#[test]
fn reject_aggregate_proof_fails() {
let (h, rt, activations) = setup_precommits(&[(0, 0, 0); 4]);
let cfg = ProveCommitSectors2Config { proof_failure: vec![0], ..Default::default() };
// If aggregate proof fails, no need for require_activation_success=true.
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"invalid aggregate proof",
h.prove_commit_sectors2(&rt, &activations, false, false, true, cfg),
);
h.check_state(&rt);
}

#[test]
fn reject_required_proof_failure() {
let (h, rt, activations) = setup_precommits(&[(0, 0, 0); 4]);
let cfg = ProveCommitSectors2Config { proof_failure: vec![0], ..Default::default() };
// Single proof failure aborts with require_activation_success=true.
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"invalid proof for sector 100 while requiring activation success",
h.prove_commit_sectors2(&rt, &activations, true, false, false, cfg),
);
h.check_state(&rt);
}

#[test]
fn reject_required_claim_failure() {
let (h, rt, activations) = setup_precommits(&[(0, 0, 0), (CLIENT_ID, 1, 0)]);
let cfg = ProveCommitSectors2Config { claim_failure: vec![0], ..Default::default() };
// Single claim failure aborts with require_activation_success=true.
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"error claiming allocations",
h.prove_commit_sectors2(&rt, &activations, true, false, false, cfg),
);
h.check_state(&rt);
}

#[test]
fn required_notification_abort() {
let deal_id = 2000;
let (h, rt, activations) = setup_precommits(&[(0, 0, deal_id)]);
let cfg = ProveCommitSectors2Config {
notification_result: Some(ExitCode::USR_ILLEGAL_ARGUMENT),
..Default::default()
};
expect_abort_contains_message(
ERR_NOTIFICATION_RECEIVER_ABORTED,
"receiver aborted",
h.prove_commit_sectors2(&rt, &activations, true, true, false, cfg),
);
h.check_state(&rt);
}

#[test]
fn require_notification_rejected() {
let deal_id = 2000;
let (h, rt, activations) = setup_precommits(&[(0, 0, deal_id)]);
let cfg = ProveCommitSectors2Config { notification_rejected: true, ..Default::default() };
// Require notification success.
expect_abort_contains_message(
ERR_NOTIFICATION_REJECTED,
"sector change rejected",
h.prove_commit_sectors2(&rt, &activations, true, true, false, cfg),
);
h.check_state(&rt);
}

fn setup_basic() -> (ActorHarness, MockRuntime) {
let h = ActorHarness::new_with_options(HarnessOptions::default());
let rt = h.new_runtime();
rt.set_balance(BIG_BALANCE.clone());
h.construct_and_verify(&rt);
(h, rt)
}

fn setup_precommits(
confs: &[(ActorID, AllocationID, DealID)],
) -> (ActorHarness, MockRuntime, Vec<SectorActivationManifest>) {
let (h, rt) = setup_basic();

// Precommit sectors
let precommit_epoch = *rt.epoch.borrow();
let sector_expiry = *rt.epoch.borrow() + DEFAULT_SECTOR_EXPIRATION_DAYS * EPOCHS_IN_DAY;
let precommits = make_fake_commd_precommits(
&h,
FIRST_SECTOR_NUMBER,
precommit_epoch - 1,
sector_expiry,
confs.len(),
);
h.pre_commit_sector_batch_v2(&rt, &precommits, true, &TokenAmount::zero()).unwrap();
rt.set_epoch(precommit_epoch + rt.policy.pre_commit_challenge_delay + 1);

let piece_size = h.sector_size as u64;
let manifests = precommits
.iter()
.zip(confs)
.map(|(s, c)| make_activation_manifest(s.sector_number, &[(piece_size, c.0, c.1, c.2)]))
.collect();
(h, rt, manifests)
}
3 changes: 2 additions & 1 deletion actors/miner/tests/prove_commit2_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ fn prove_commit2_basic() {
];

rt.set_epoch(precommit_epoch + rt.policy.pre_commit_challenge_delay + 1);
let result = h.prove_commit_sectors2(&rt, &sector_activations, true, true, false).unwrap();
let cfg = ProveCommitSectors2Config::default();
let result = h.prove_commit_sectors2(&rt, &sector_activations, true, true, false, cfg).unwrap();
assert_eq!(
ProveCommitSectors2Return { activation_results: BatchReturn::ok(precommits.len() as u32) },
result
Expand Down
5 changes: 1 addition & 4 deletions actors/miner/tests/prove_replica_failures_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,7 @@ fn reject_required_proof_failure() {
#[test]
fn reject_required_claim_failure() {
let (h, rt, sector_updates) = setup(2, CLIENT_ID, 1, 0);
let cfg = ProveReplicaUpdatesConfig {
verfied_claim_result: Some(ExitCode::USR_ILLEGAL_ARGUMENT),
..Default::default()
};
let cfg = ProveReplicaUpdatesConfig { claim_failure: vec![0], ..Default::default() };
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"error claiming allocations",
Expand Down
Loading

0 comments on commit a108360

Please sign in to comment.