Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Claim verifreg allocations from miner actor #715

Merged
merged 1 commit into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions actors/market/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,9 +538,7 @@ impl Actor {

Ok(VerifyDealsForActivationReturn { sectors: sectors_data })
}
/// Activate a set of deals, returning the combined deal weights.
/// The weight is defined as the sum, over all deals in the set, of the product of deal size
/// and duration.
/// Activate a set of deals, returning the combined deal space and extra info for verified deals.
fn activate_deals<BS, RT>(
rt: &mut RT,
params: ActivateDealsParams,
Expand Down Expand Up @@ -571,6 +569,7 @@ impl Actor {
};

// Update deal states
let mut verified_infos = Vec::new();
rt.transaction(|st: &mut State, rt| {
let mut msm = st.mutator(rt.store());
msm.with_deal_states(Permission::Write)
Expand Down Expand Up @@ -639,7 +638,17 @@ impl Actor {
.delete(&deal_id_key(deal_id))
.with_context_code(ExitCode::USR_ILLEGAL_STATE, || {
format!("failed to remove allocation id for deal {}", deal_id)
})?;
})?
.unwrap_or((BytesKey(vec![]), NO_ALLOCATION_ID))
.1;
if allocation != NO_ALLOCATION_ID {
verified_infos.push(VerifiedDealInfo {
client: proposal.client.id().unwrap(),
allocation_id: allocation,
data: proposal.piece_cid,
size: proposal.piece_size,
})
}
msm.deal_states
.as_mut()
.unwrap()
Expand All @@ -649,9 +658,7 @@ impl Actor {
sector_start_epoch: curr_epoch,
last_updated_epoch: EPOCH_UNDEFINED,
slash_epoch: EPOCH_UNDEFINED,
verified_claim: allocation
.unwrap_or((BytesKey(vec![]), NO_ALLOCATION_ID))
.1,
verified_claim: allocation,
},
)
.with_context_code(ExitCode::USR_ILLEGAL_STATE, || {
Expand All @@ -663,7 +670,7 @@ impl Actor {
Ok(())
})?;

Ok(ActivateDealsResult { spaces: deal_spaces })
Ok(ActivateDealsResult { nonverified_deal_space: deal_spaces.deal_space, verified_infos })
}

/// Terminate a set of deals in response to their containing sector being terminated.
Expand Down
17 changes: 15 additions & 2 deletions actors/market/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2019-2022 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use super::ext::verifreg::AllocationID;
use cid::Cid;
use fil_actors_runtime::Array;
use fvm_ipld_bitfield::BitField;
Expand All @@ -11,6 +12,9 @@ use fvm_shared::bigint::{bigint_ser, BigInt};
use fvm_shared::clock::ChainEpoch;
use fvm_shared::deal::DealID;
use fvm_shared::econ::TokenAmount;
use fvm_shared::piece::PaddedPieceSize;
use fvm_shared::ActorID;

use fvm_shared::sector::RegisteredSealProof;

use super::deal::{ClientDealProposal, DealProposal, DealState};
Expand Down Expand Up @@ -95,11 +99,20 @@ pub struct ActivateDealsParams {
pub sector_expiry: ChainEpoch,
}

#[derive(Serialize_tuple, Deserialize_tuple, Clone)]
pub struct VerifiedDealInfo {
pub client: ActorID,
pub allocation_id: AllocationID,
pub data: Cid,
pub size: PaddedPieceSize,
}

#[derive(Serialize_tuple, Deserialize_tuple)]
pub struct ActivateDealsResult {
pub spaces: DealSpaces,
#[serde(with = "bigint_ser")]
pub nonverified_deal_space: BigInt,
pub verified_infos: Vec<VerifiedDealInfo>,
}

#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Default)]
pub struct DealSpaces {
#[serde(with = "bigint_ser")]
Expand Down
22 changes: 15 additions & 7 deletions actors/market/tests/verify_deals_for_activation_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,23 @@ fn verify_deal_and_activate_to_get_deal_space_for_unverified_deal_proposal() {
let a_response = activate_deals(&mut rt, SECTOR_EXPIRY, PROVIDER_ADDR, CURR_EPOCH, &[deal_id]);
assert_eq!(1, v_response.sectors.len());
assert_eq!(Some(make_piece_cid("1".as_bytes())), v_response.sectors[0].commd);
assert_eq!(BigInt::zero(), a_response.spaces.verified_deal_space);
assert_eq!(BigInt::from(deal_proposal.piece_size.0), a_response.spaces.deal_space);
assert!(a_response.verified_infos.is_empty());
assert_eq!(BigInt::from(deal_proposal.piece_size.0), a_response.nonverified_deal_space);

check_state(&rt);
}

#[test]
fn verify_deal_and_activate_to_get_deal_space_for_verified_deal_proposal() {
let mut rt = setup();
let next_allocation_id = 1;
let deal_id = generate_and_publish_verified_deal(
&mut rt,
CLIENT_ADDR,
&MINER_ADDRESSES,
START_EPOCH,
END_EPOCH,
1,
next_allocation_id,
);
let deal_proposal = get_deal_proposal(&mut rt, deal_id);

Expand All @@ -85,8 +86,13 @@ fn verify_deal_and_activate_to_get_deal_space_for_verified_deal_proposal() {

assert_eq!(1, response.sectors.len());
assert_eq!(Some(make_piece_cid("1".as_bytes())), response.sectors[0].commd);
assert_eq!(BigInt::from(deal_proposal.piece_size.0), a_response.spaces.verified_deal_space);
assert_eq!(BigInt::zero(), a_response.spaces.deal_space);
assert_eq!(1, a_response.verified_infos.len());
assert_eq!(deal_proposal.piece_size, a_response.verified_infos[0].size);
assert_eq!(deal_proposal.client.id().unwrap(), a_response.verified_infos[0].client);
assert_eq!(deal_proposal.piece_cid, a_response.verified_infos[0].data);
assert_eq!(next_allocation_id, a_response.verified_infos[0].allocation_id);

assert_eq!(BigInt::zero(), a_response.nonverified_deal_space);

check_state(&rt);
}
Expand Down Expand Up @@ -145,8 +151,10 @@ fn verification_and_weights_for_verified_and_unverified_deals() {
let a_response = activate_deals(&mut rt, SECTOR_EXPIRY, PROVIDER_ADDR, CURR_EPOCH, &deal_ids);

assert_eq!(1, response.sectors.len());
assert_eq!(verified_space, a_response.spaces.verified_deal_space);
assert_eq!(unverified_space, a_response.spaces.deal_space);
let returned_verified_space: BigInt =
a_response.verified_infos.iter().map(|info| BigInt::from(info.size.0)).sum();
assert_eq!(verified_space, returned_verified_space);
assert_eq!(unverified_space, a_response.nonverified_deal_space);

check_state(&rt);
}
Expand Down
48 changes: 47 additions & 1 deletion actors/miner/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,30 @@ pub mod market {
pub sector_expiry: ChainEpoch,
}

#[derive(Serialize_tuple, Deserialize_tuple, Clone)]
pub struct VerifiedDealInfo {
pub client: ActorID,
pub allocation_id: u64,
pub data: Cid,
pub size: PaddedPieceSize,
}

impl Default for VerifiedDealInfo {
fn default() -> VerifiedDealInfo {
VerifiedDealInfo {
size: PaddedPieceSize(0),
client: 0,
allocation_id: 0,
data: Default::default(),
}
}
}

#[derive(Serialize_tuple, Deserialize_tuple)]
pub struct ActivateDealsResult {
pub spaces: DealSpaces,
#[serde(with = "bigint_ser")]
pub nonverified_deal_space: BigInt,
pub verified_infos: Vec<VerifiedDealInfo>,
}

#[derive(Serialize_tuple, Deserialize_tuple, Clone, Default)]
Expand Down Expand Up @@ -138,8 +159,11 @@ pub mod verifreg {
use super::*;

pub const GET_CLAIMS_METHOD: u64 = 10;
pub const CLAIM_ALLOCATIONS_METHOD: u64 = 9;

pub type ClaimID = u64;
pub type AllocationID = u64;

#[derive(Serialize_tuple, Deserialize_tuple, Clone, Debug, PartialEq, Eq)]
pub struct Claim {
// The provider storing the data (from allocation).
Expand Down Expand Up @@ -170,4 +194,26 @@ pub mod verifreg {
pub batch_info: BatchReturn,
pub claims: Vec<Claim>,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
pub struct SectorAllocationClaim {
pub client: ActorID,
pub allocation_id: AllocationID,
pub data: Cid,
pub size: PaddedPieceSize,
pub sector: SectorNumber,
pub sector_expiry: ChainEpoch,
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
pub struct ClaimAllocationsParams {
pub sectors: Vec<SectorAllocationClaim>,
pub all_or_nothing: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
pub struct ClaimAllocationsReturn {
pub batch_info: BatchReturn,
#[serde(with = "bigint_ser")]
pub claimed_space: BigInt,
}
}
146 changes: 100 additions & 46 deletions actors/miner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1052,25 +1052,20 @@ impl Actor {
continue;
}

let res = rt.send(
&STORAGE_MARKET_ACTOR_ADDR,
ext::market::ACTIVATE_DEALS_METHOD,
RawBytes::serialize(ext::market::ActivateDealsParams {
deal_ids: update.deals.clone(),
sector_expiry: sector_info.expiration,
})?,
TokenAmount::zero(),
);
let deal_spaces = if let Ok(res) = res {
// Erroring in this case as it means something went really wrong
let activate_ret: ext::market::ActivateDealsResult = res.deserialize()?;
activate_ret.spaces
} else {
info!(
"failed to activate deals on sector {0}, skipping sector {0}",
update.sector_number,
);
continue;
let deal_spaces = match activate_deals_and_claim_allocations(
rt,
update.deals.clone(),
sector_info.expiration,
sector_info.sector_number,
)? {
Some(deal_spaces) => deal_spaces,
None => {
info!(
"failed to activate deals on sector {}, skipping from replica update set",
update.sector_number
);
continue;
}
};

let expiration = sector_info.expiration;
Expand Down Expand Up @@ -4787,35 +4782,21 @@ where
let mut valid_pre_commits = Vec::default();

for pre_commit in pre_commits {
let deal_spaces = if !pre_commit.info.deal_ids.is_empty() {
// Check (and activate) storage deals associated to sector. Abort if checks failed.
let res = rt.send(
&STORAGE_MARKET_ACTOR_ADDR,
ext::market::ACTIVATE_DEALS_METHOD,
RawBytes::serialize(ext::market::ActivateDealsParams {
deal_ids: pre_commit.info.deal_ids.clone(),
sector_expiry: pre_commit.info.expiration,
})?,
TokenAmount::zero(),
);
match res {
Ok(res) => {
let activate_res: ext::market::ActivateDealsResult = res.deserialize()?;
activate_res.spaces
}
Err(e) => {
info!(
"failed to activate deals on sector {}, dropping from prove commit set: {}",
pre_commit.info.sector_number,
e.msg()
);
continue;
}
match activate_deals_and_claim_allocations(
rt,
pre_commit.clone().info.deal_ids,
pre_commit.info.expiration,
pre_commit.info.sector_number,
)? {
None => {
info!(
"failed to activate deals on sector {}, dropping from prove commit set",
pre_commit.info.sector_number,
);
continue;
}
} else {
ext::market::DealSpaces::default()
Some(deal_spaces) => valid_pre_commits.push((pre_commit, deal_spaces)),
};
valid_pre_commits.push((pre_commit, deal_spaces));
}

// When all prove commits have failed abort early
Expand Down Expand Up @@ -4964,6 +4945,79 @@ where
Ok(())
}

// activate deals with builtin market and claim allocations with verified registry actor
// returns an error in case of a fatal programmer error
// returns Ok(None) in case deal activation or verified allocation claim fails
fn activate_deals_and_claim_allocations<RT, BS>(
rt: &mut RT,
deal_ids: Vec<DealID>,
sector_expiry: ChainEpoch,
sector_number: SectorNumber,
) -> Result<Option<crate::ext::market::DealSpaces>, ActorError>
where
BS: Blockstore,
RT: Runtime<BS>,
{
if deal_ids.is_empty() {
return Ok(Some(ext::market::DealSpaces::default()));
}
// Check (and activate) storage deals associated to sector. Abort if checks failed.
let activate_raw = rt.send(
&STORAGE_MARKET_ACTOR_ADDR,
ext::market::ACTIVATE_DEALS_METHOD,
RawBytes::serialize(ext::market::ActivateDealsParams { deal_ids, sector_expiry })?,
TokenAmount::zero(),
);
let activate_res: ext::market::ActivateDealsResult = match activate_raw {
Ok(res) => res.deserialize()?,
Err(e) => {
info!("error activating deals on sector {}: {}", sector_number, e.msg());
return Ok(None);
}
};

// If deal activation includes verified deals claim allocations
if activate_res.verified_infos.is_empty() {
return Ok(Some(ext::market::DealSpaces {
deal_space: activate_res.nonverified_deal_space,
..Default::default()
}));
}
let sector_claims = activate_res
.verified_infos
.iter()
.map(|info| ext::verifreg::SectorAllocationClaim {
client: info.client,
allocation_id: info.allocation_id,
data: info.data,
size: info.size,
sector: sector_number,
sector_expiry,
})
.collect();

let claim_raw = rt.send(
&VERIFIED_REGISTRY_ACTOR_ADDR,
ext::verifreg::CLAIM_ALLOCATIONS_METHOD,
RawBytes::serialize(ext::verifreg::ClaimAllocationsParams {
sectors: sector_claims,
all_or_nothing: true,
})?,
TokenAmount::zero(),
);
let claim_res: ext::verifreg::ClaimAllocationsReturn = match claim_raw {
Ok(res) => res.deserialize()?,
Err(e) => {
info!("error claiming allocation on sector {}: {}", sector_number, e.msg());
return Ok(None);
}
};
Ok(Some(ext::market::DealSpaces {
deal_space: activate_res.nonverified_deal_space,
verified_deal_space: claim_res.claimed_space,
}))
}

// XXX: probably better to push this one level down into state
fn balance_invariants_broken(e: Error) -> ActorError {
ActorError::unchecked(
Expand Down
Loading