Skip to content

Commit

Permalink
Feat/drop claims (#718)
Browse files Browse the repository at this point in the history
* Add claim drop feature
* Add drop claim period to policy

Co-authored-by: zenground0 <[email protected]>
  • Loading branch information
ZenGround0 and ZenGround0 authored Sep 28, 2022
1 parent 2a25e79 commit 22c3256
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 29 deletions.
89 changes: 61 additions & 28 deletions actors/miner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3556,7 +3556,11 @@ enum ExtensionKind {
// ExtendSectorExpiration param
struct ExtendExpirationsInner {
extensions: Vec<ValidatedExpirationExtension>,
claims: Option<BTreeMap<SectorNumber, u64>>,
// Map from sector being extended to (check, maintain)
// `check` is the space of active claims, checked to ensure all claims are checked
// `maintain` is the space of claims to maintain
// maintain <= check with equality in the case no claims are dropped
claims: Option<BTreeMap<SectorNumber, (u64, u64)>>,
}

#[derive(Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -3621,7 +3625,7 @@ where
BS: Blockstore,
RT: Runtime<BS>,
{
let mut claim_space_by_sector = BTreeMap::<SectorNumber, u64>::new();
let mut claim_space_by_sector = BTreeMap::<SectorNumber, (u64, u64)>::new();

for decl in &extensions {
let policy = rt.policy();
Expand All @@ -3635,27 +3639,38 @@ where
}

for sc in &decl.sectors_with_claims {
let claims = get_claims(rt, &sc.maintain_claims)
let mut drop_claims = sc.drop_claims.clone();
let mut all_claim_ids = sc.maintain_claims.clone();
all_claim_ids.append(&mut drop_claims);
let claims = get_claims(rt, &all_claim_ids)
.with_context(|| format!("failed to get claims for sector {}", sc.sector_number))?;
let first_drop = sc.maintain_claims.len();

for (i, claim) in claims.iter().enumerate() {
// check provider and sector matches
if claim.provider != rt.message().receiver().id().unwrap() {
return Err(actor_error!(illegal_argument, "failed to validate declaration sector={}, claim={}, expected claim provider to be {} but found {} ", sc.sector_number, sc.maintain_claims[i], rt.message().receiver().id().unwrap(), claim.provider));
return Err(actor_error!(illegal_argument, "failed to validate declaration sector={}, claim={}, expected claim provider to be {} but found {} ", sc.sector_number, all_claim_ids[i], rt.message().receiver().id().unwrap(), claim.provider));
}
if claim.sector != sc.sector_number {
return Err(actor_error!(illegal_argument, "failed to validate declaration sector={}, claim={} expected claim sector number to be {} but found {} ", sc.sector_number, sc.maintain_claims[i], sc.sector_number, claim.sector));
return Err(actor_error!(illegal_argument, "failed to validate declaration sector={}, claim={} expected claim sector number to be {} but found {} ", sc.sector_number, all_claim_ids[i], sc.sector_number, claim.sector));
}

// check expiration does not exceed term max
if decl.new_expiration > claim.term_start + claim.term_max {
return Err(actor_error!(forbidden, "failed to validate declaration sector={}, claim={} claim only allows extension to {} but declared new expiration is {}", sc.sector_number, sc.maintain_claims[i], claim.term_start + claim.term_max, decl.new_expiration));
// If we are not dropping check expiration does not exceed term max
let mut maintain_delta: u64 = 0;
if i < first_drop {
if decl.new_expiration > claim.term_start + claim.term_max {
return Err(actor_error!(forbidden, "failed to validate declaration sector={}, claim={} claim only allows extension to {} but declared new expiration is {}", sc.sector_number, sc.maintain_claims[i], claim.term_start + claim.term_max, decl.new_expiration));
}
maintain_delta = claim.size.0
}

claim_space_by_sector
.entry(sc.sector_number)
.and_modify(|size| *size += claim.size.0)
.or_insert(claim.size.0);
.and_modify(|(check, maintain)| {
*check += claim.size.0;
*maintain += maintain_delta;
})
.or_insert((claim.size.0, maintain_delta));
}
}
}
Expand All @@ -3670,13 +3685,13 @@ fn extend_sector_committment(
curr_epoch: ChainEpoch,
new_expiration: ChainEpoch,
sector: &SectorOnChainInfo,
claim_space_by_sector: &BTreeMap<SectorNumber, u64>,
claim_space_by_sector: &BTreeMap<SectorNumber, (u64, u64)>,
) -> Result<SectorOnChainInfo, ActorError> {
validate_extended_expiration(policy, curr_epoch, new_expiration, sector)?;

// all simple_qa_power sectors with VerifiedDealWeight > 0 MUST check all claims
if sector.simple_qa_power {
extend_simple_qap_sector(new_expiration, sector, claim_space_by_sector)
extend_simple_qap_sector(policy, new_expiration, curr_epoch, sector, claim_space_by_sector)
} else {
extend_non_simple_qap_sector(new_expiration, curr_epoch, sector)
}
Expand Down Expand Up @@ -3744,33 +3759,51 @@ fn validate_extended_expiration(
}

fn extend_simple_qap_sector(
policy: &Policy,
new_expiration: ChainEpoch,
curr_epoch: ChainEpoch,
sector: &SectorOnChainInfo,
claim_space_by_sector: &BTreeMap<SectorNumber, u64>,
claim_space_by_sector: &BTreeMap<SectorNumber, (u64, u64)>,
) -> Result<SectorOnChainInfo, ActorError> {
let mut new_sector = sector.clone();
if sector.verified_deal_weight > BigInt::zero() {
let old_duration = sector.expiration - sector.activation;
let deal_space = &sector.deal_weight / old_duration;
let verified_deal_space = &sector.verified_deal_weight / old_duration;
let expected_verified_deal_space = match claim_space_by_sector.get(&sector.sector_number) {
None => {
return Err(actor_error!(
illegal_argument,
"claim missing from declaration for sector {}",
sector.sector_number
))
}
Some(space) => space,
};
if BigInt::from(*expected_verified_deal_space as i64) != verified_deal_space {
return Err(actor_error!(illegal_argument, "declared verified deal space in claims ({}) does not match verified deal space ({}) for sector {}", expected_verified_deal_space, verified_deal_space, sector.sector_number));
let old_verified_deal_space = &sector.verified_deal_weight / old_duration;
let (expected_verified_deal_space, new_verified_deal_space) =
match claim_space_by_sector.get(&sector.sector_number) {
None => {
return Err(actor_error!(
illegal_argument,
"claim missing from declaration for sector {} with non-zero verified deal weight {}",
sector.sector_number,
&sector.verified_deal_weight
))
}
Some(space) => space,
};
// claims must be completely accounted for
if BigInt::from(*expected_verified_deal_space as i64) != old_verified_deal_space {
return Err(actor_error!(illegal_argument, "declared verified deal space in claims ({}) does not match verified deal space ({}) for sector {}", expected_verified_deal_space, old_verified_deal_space, sector.sector_number));
}
// claim dropping is restricted to extensions at the end of a sector's life

let dropping_claims = expected_verified_deal_space != new_verified_deal_space;
if dropping_claims && sector.expiration - curr_epoch >= policy.end_of_life_claim_drop_period
{
return Err(actor_error!(
forbidden,
"attempt to drop sectors with {} epochs < end of life claim drop period {} remaining",
sector.expiration - curr_epoch,
policy.end_of_life_claim_drop_period
));
}

new_sector.expiration = new_expiration;
// update deal weights to account for new duration
new_sector.deal_weight = deal_space * (new_sector.expiration - new_sector.activation);
new_sector.verified_deal_weight =
verified_deal_space * (new_sector.expiration - new_sector.activation);
new_sector.verified_deal_weight = BigInt::from(*new_verified_deal_space)
* (new_sector.expiration - new_sector.activation);
} else {
new_sector.expiration = new_expiration
}
Expand Down
1 change: 1 addition & 0 deletions actors/miner/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ impl Cbor for ExtendSectorExpiration2Params {}
pub struct SectorClaim {
pub sector_number: SectorNumber,
pub maintain_claims: Vec<ClaimID>,
pub drop_claims: Vec<ClaimID>,
}

impl Cbor for SectorClaim {}
Expand Down
4 changes: 4 additions & 0 deletions actors/miner/tests/extend_sector_expiration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ fn update_expiration_multiple_claims() {
sectors_with_claims: vec![SectorClaim {
sector_number: old_sector.sector_number,
maintain_claims: claim_ids,
drop_claims: vec![],
}],
}],
};
Expand Down Expand Up @@ -570,6 +571,7 @@ fn update_expiration2_failure_cases() {
sectors_with_claims: vec![SectorClaim {
sector_number: old_sector.sector_number,
maintain_claims: vec![claim_ids[0]],
drop_claims: vec![],
}],
}],
};
Expand Down Expand Up @@ -608,6 +610,7 @@ fn update_expiration2_failure_cases() {
sectors_with_claims: vec![SectorClaim {
sector_number: old_sector.sector_number,
maintain_claims: claim_ids.clone(),
drop_claims: vec![],
}],
}],
};
Expand Down Expand Up @@ -646,6 +649,7 @@ fn update_expiration2_failure_cases() {
sectors_with_claims: vec![SectorClaim {
sector_number: old_sector.sector_number,
maintain_claims: claim_ids,
drop_claims: vec![],
}],
}],
};
Expand Down
5 changes: 4 additions & 1 deletion runtime/src/runtime/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ pub struct Policy {
/// Maximum time a verified allocation can be active without being claimed (epochs).
/// Supports recovery of erroneous allocations and prevents indefinite squatting on datacap.
pub maximum_verified_allocation_expiration: i64,
// Period of time at the end of a sector's life during which claims can be dropped
pub end_of_life_claim_drop_period: ChainEpoch,

// --- market policy ---
/// The number of blocks between payouts for deals
Expand Down Expand Up @@ -240,7 +242,7 @@ impl Default for Policy {
maximum_verified_allocation_term: policy_constants::MAXIMUM_VERIFIED_ALLOCATION_TERM,
maximum_verified_allocation_expiration:
policy_constants::MAXIMUM_VERIFIED_ALLOCATION_EXPIRATION,

end_of_life_claim_drop_period: policy_constants::END_OF_LIFE_CLAIM_DROP_PERIOD,
deal_updates_interval: policy_constants::DEAL_UPDATES_INTERVAL,
prov_collateral_percent_supply_num:
policy_constants::PROV_COLLATERAL_PERCENT_SUPPLY_NUM,
Expand Down Expand Up @@ -387,6 +389,7 @@ pub mod policy_constants {
pub const MINIMUM_VERIFIED_ALLOCATION_TERM: i64 = 180 * EPOCHS_IN_DAY;
pub const MAXIMUM_VERIFIED_ALLOCATION_TERM: i64 = 5 * EPOCHS_IN_YEAR;
pub const MAXIMUM_VERIFIED_ALLOCATION_EXPIRATION: i64 = 60 * EPOCHS_IN_DAY;
pub const END_OF_LIFE_CLAIM_DROP_PERIOD: ChainEpoch = 30 * EPOCHS_IN_DAY;

/// DealUpdatesInterval is the number of blocks between payouts for deals
pub const DEAL_UPDATES_INTERVAL: i64 = EPOCHS_IN_DAY;
Expand Down

0 comments on commit 22c3256

Please sign in to comment.