Skip to content

Commit

Permalink
PRU2 tests that abort the whole method
Browse files Browse the repository at this point in the history
  • Loading branch information
anorth committed Sep 7, 2023
1 parent 3a09efa commit c1f13d5
Show file tree
Hide file tree
Showing 5 changed files with 402 additions and 163 deletions.
5 changes: 3 additions & 2 deletions actors/miner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,9 @@ pub const SECTOR_CONTENT_CHANGED: MethodNum = frc42_dispatch::method_hash!("Sect

pub const ERR_BALANCE_INVARIANTS_BROKEN: ExitCode = ExitCode::new(1000);
pub const ERR_NOTIFICATION_SEND_FAILED: ExitCode = ExitCode::new(1001);
pub const ERR_NOTIFICATION_RESPONSE_INVALID: ExitCode = ExitCode::new(1002);
pub const ERR_NOTIFICATION_REJECTED: ExitCode = ExitCode::new(1003);
pub const ERR_NOTIFICATION_RECEIVER_ABORTED: ExitCode = ExitCode::new(1002);
pub const ERR_NOTIFICATION_RESPONSE_INVALID: ExitCode = ExitCode::new(1003);
pub const ERR_NOTIFICATION_REJECTED: ExitCode = ExitCode::new(1004);

/// Miner Actor
/// here in order to update the Power Actor to v3.
Expand Down
9 changes: 6 additions & 3 deletions actors/miner/src/notifications.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,11 @@ fn send_notification(
))
}
} else {
// Propagate the non-ok exit code from the receiver.
Err(ActorError::checked(r.exit_code, "receiver aborted".to_string(), None))
Err(ActorError::checked(
crate::ERR_NOTIFICATION_RECEIVER_ABORTED,
format!("receiver aborted with {}", r.exit_code),
None,
))
}
}
Err(SendError(e)) => Err(ActorError::checked(
Expand Down Expand Up @@ -167,7 +170,7 @@ fn validate_notification_response(
return Err(ActorError::checked(
crate::ERR_NOTIFICATION_REJECTED,
format!(
"sector change response rejected by {} for sector {} piece {} payload {:?}",
"sector change rejected by {} for sector {} piece {} payload {:?}",
notifee, sreq.sector, nreq.data, nreq.payload
),
None,
Expand Down
208 changes: 208 additions & 0 deletions actors/miner/tests/prove_replica_failures_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
use fvm_ipld_encoding::RawBytes;
use fvm_shared::address::Address;
use fvm_shared::clock::ChainEpoch;
use fvm_shared::deal::DealID;
use fvm_shared::error::ExitCode;
use fvm_shared::sector::SectorNumber;
use fvm_shared::ActorID;

use fil_actor_miner::ext::verifreg::AllocationID;
use fil_actor_miner::{
ProveReplicaUpdates2Params, SectorUpdateManifest, State, ERR_NOTIFICATION_RECEIVER_ABORTED,
ERR_NOTIFICATION_REJECTED,
};
use fil_actors_runtime::runtime::Runtime;
use fil_actors_runtime::test_utils::{expect_abort_contains_message, MockRuntime};
use fil_actors_runtime::EPOCHS_IN_DAY;
use util::*;

mod util;

// Tests for ProveReplicaUpdates2 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, sector_updates) = setup(1, 0, 0, 0);
let cfg = ProveReplicaUpdatesConfig {
caller: Some(Address::new_id(CLIENT_ID)),
..Default::default()
};
expect_abort_contains_message(
ExitCode::USR_FORBIDDEN,
"caller",
h.prove_replica_updates2_batch(&rt, &sector_updates, false, false, cfg),
);
}

#[test]
fn reject_no_proof_types() {
let (h, rt, sector_updates) = setup(1, 0, 0, 0);
let cfg = ProveReplicaUpdatesConfig {
param_twiddle: Some(Box::new(|p: &mut ProveReplicaUpdates2Params| {
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_replica_updates2_batch(&rt, &sector_updates, false, false, cfg),
);
}

#[test]
fn reject_both_proof_types() {
let (h, rt, sector_updates) = setup(1, 0, 0, 0);
let cfg = ProveReplicaUpdatesConfig {
param_twiddle: Some(Box::new(|p: &mut ProveReplicaUpdates2Params| {
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_replica_updates2_batch(&rt, &sector_updates, false, false, cfg),
);
}

#[test]
fn reject_mismatched_proof_len() {
let (h, rt, sector_updates) = setup(1, 0, 0, 0);
let cfg = ProveReplicaUpdatesConfig {
param_twiddle: Some(Box::new(|p: &mut ProveReplicaUpdates2Params| {
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_replica_updates2_batch(&rt, &sector_updates, false, false, cfg),
);
}

#[test]
fn reject_aggregate_proof() {
let (h, rt, sector_updates) = setup(1, 0, 0, 0);
let cfg = ProveReplicaUpdatesConfig {
param_twiddle: Some(Box::new(|p: &mut ProveReplicaUpdates2Params| {
p.sector_proofs = vec![];
p.aggregate_proof = RawBytes::new(vec![1, 2, 3, 4])
})),
..Default::default()
};
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"aggregate update proofs not yet supported",
h.prove_replica_updates2_batch(&rt, &sector_updates, false, false, cfg),
);
}

#[test]
fn reject_all_proofs_fail() {
let (h, rt, sector_updates) = setup(2, 0, 0, 0);
let cfg = ProveReplicaUpdatesConfig { proofs_valid: vec![false, false], ..Default::default() };
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"no valid updates",
h.prove_replica_updates2_batch(&rt, &sector_updates, false, false, cfg),
);
}

#[test]
fn reject_invalid_update() {
let (h, rt, mut sector_updates) = setup(2, 0, 0, 0);
sector_updates[1].sector = sector_updates[0].sector;
let cfg = ProveReplicaUpdatesConfig::default();
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"invalid update 1 while requiring activation success",
h.prove_replica_updates2_batch(&rt, &sector_updates, true, false, cfg),
);
}

#[test]
fn reject_required_proof_failure() {
let (h, rt, sector_updates) = setup(2, 0, 0, 0);
let cfg = ProveReplicaUpdatesConfig { proofs_valid: vec![true, false], ..Default::default() };
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"requiring activation success",
h.prove_replica_updates2_batch(&rt, &sector_updates, true, false, cfg),
);
}

#[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()
};
expect_abort_contains_message(
ExitCode::USR_ILLEGAL_ARGUMENT,
"error claiming allocations",
h.prove_replica_updates2_batch(&rt, &sector_updates, true, false, cfg),
);
}

#[test]
fn reject_required_notification_abort() {
let deal_id = 2000;
let (h, rt, sector_updates) = setup(1, 0, 0, deal_id);

let cfg = ProveReplicaUpdatesConfig {
notification_result: Some(ExitCode::USR_UNSPECIFIED),
..Default::default()
};
expect_abort_contains_message(
ERR_NOTIFICATION_RECEIVER_ABORTED,
"receiver aborted",
h.prove_replica_updates2_batch(&rt, &sector_updates, false, true, cfg),
);
}

#[test]
fn reject_required_notification_rejected() {
let deal_id = 2000;
let (h, rt, sector_updates) = setup(1, 0, 0, deal_id);

let cfg = ProveReplicaUpdatesConfig { notification_rejected: true, ..Default::default() };
expect_abort_contains_message(
ERR_NOTIFICATION_REJECTED,
"sector change rejected",
h.prove_replica_updates2_batch(&rt, &sector_updates, false, true, cfg),
);
}

fn setup(
sector_count: usize,
client: ActorID,
alloc: AllocationID,
deal: DealID,
) -> (ActorHarness, MockRuntime, Vec<SectorUpdateManifest>) {
let h = ActorHarness::new_with_options(HarnessOptions::default());
let rt = h.new_runtime();
rt.set_balance(BIG_BALANCE.clone());
h.construct_and_verify(&rt);

// Onboard empty sectors.
let sector_expiry = *rt.epoch.borrow() + DEFAULT_SECTOR_EXPIRATION_DAYS * EPOCHS_IN_DAY;
let sectors = onboard_empty_sectors(&rt, &h, sector_expiry, FIRST_SECTOR_NUMBER, sector_count);

let st: State = h.get_state(&rt);
let store = rt.store();
let piece_size = h.sector_size as u64;
let sector_updates = sectors
.iter()
.map(|s| make_update_manifest(&st, store, s, &[(piece_size, client, alloc, deal)]))
.collect();
(h, rt, sector_updates)
}
Loading

0 comments on commit c1f13d5

Please sign in to comment.