Skip to content

Commit 8b4a722

Browse files
committed
Add GetDealSector exported API method to market actor
1 parent e49dafc commit 8b4a722

File tree

4 files changed

+81
-37
lines changed

4 files changed

+81
-37
lines changed

actors/market/src/lib.rs

+53-21
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,10 @@ fil_actors_runtime::wasm_trampoline!(Actor);
6262

6363
pub const NO_ALLOCATION_ID: u64 = 0;
6464

65-
// An exit code indicating that information about a past deal is no longer available.
65+
// Indicates that information about a past deal is no longer available.
6666
pub const EX_DEAL_EXPIRED: ExitCode = ExitCode::new(FIRST_ACTOR_SPECIFIC_EXIT_CODE);
67+
// Indicates that information about a deal's activation is not yet available.
68+
pub const EX_DEAL_NOT_ACTIVATED: ExitCode = ExitCode::new(FIRST_ACTOR_SPECIFIC_EXIT_CODE + 1);
6769

6870
/// Market actor methods available
6971
#[derive(FromPrimitive)]
@@ -93,6 +95,7 @@ pub enum Method {
9395
GetDealProviderCollateralExported = frc42_dispatch::method_hash!("GetDealProviderCollateral"),
9496
GetDealVerifiedExported = frc42_dispatch::method_hash!("GetDealVerified"),
9597
GetDealActivationExported = frc42_dispatch::method_hash!("GetDealActivation"),
98+
GetDealSectorExported = frc42_dispatch::method_hash!("GetDealSector"),
9699
SectorContentChangedExported = ext::miner::SECTOR_CONTENT_CHANGED,
97100
}
98101

@@ -1116,28 +1119,56 @@ impl Actor {
11161119
terminated: state.slash_epoch,
11171120
}),
11181121
None => {
1119-
let maybe_proposal = st.find_proposal(rt.store(), params.id)?;
1120-
match maybe_proposal {
1121-
Some(_) => Ok(GetDealActivationReturn {
1122-
// The proposal has been published, but not activated.
1123-
activated: EPOCH_UNDEFINED,
1124-
terminated: EPOCH_UNDEFINED,
1125-
}),
1126-
None => {
1127-
if params.id < st.next_id {
1128-
// If the deal ID has been used, it must have been cleaned up.
1129-
Err(ActorError::unchecked(
1130-
EX_DEAL_EXPIRED,
1131-
format!("deal {} expired", params.id),
1132-
))
1133-
} else {
1134-
// We can't distinguish between failing to activate, or having been
1135-
// cleaned up after completion/termination.
1136-
Err(ActorError::not_found(format!("no such deal {}", params.id)))
1137-
}
1138-
}
1122+
// Pass through exit codes if proposal doesn't exist.
1123+
let _ = st.get_proposal(rt.store(), params.id)?;
1124+
// Proposal was published but never activated.
1125+
Ok(GetDealActivationReturn {
1126+
activated: EPOCH_UNDEFINED,
1127+
terminated: EPOCH_UNDEFINED,
1128+
})
1129+
}
1130+
}
1131+
}
1132+
1133+
/// Fetches the sector in which a deal is stored.
1134+
/// This is available from after a deal is activated until it is finally settled
1135+
/// (either normally or by termination).
1136+
/// Fails with USR_NOT_FOUND if the deal doesn't exist (yet),
1137+
/// EX_DEAL_NOT_ACTIVATED if the deal is published but has not been activated,
1138+
/// or EX_DEAL_EXPIRED if the deal has been removed from state.
1139+
fn get_deal_sector(
1140+
rt: &impl Runtime,
1141+
params: GetDealSectorParams,
1142+
) -> Result<GetDealSectorReturn, ActorError> {
1143+
rt.validate_immediate_caller_accept_any()?;
1144+
let st = rt.state::<State>()?;
1145+
let found = st.find_deal_state(rt.store(), params.id)?;
1146+
match found {
1147+
Some(state) => {
1148+
// The deal has been activated and not yet finally settled.
1149+
if state.slash_epoch != EPOCH_UNDEFINED {
1150+
// The deal has been terminated but not cleaned up.
1151+
// Hide this internal state from caller and fail as if it had been cleaned up.
1152+
// This will become an impossible state when deal termination is
1153+
// processed immediately.
1154+
// Remove with https://github.com/filecoin-project/builtin-actors/issues/1388.
1155+
Err(ActorError::unchecked(
1156+
EX_DEAL_EXPIRED,
1157+
format!("deal {} expired", params.id),
1158+
))
1159+
} else {
1160+
Ok(GetDealSectorReturn { sector: state.sector_number })
11391161
}
11401162
}
1163+
None => {
1164+
// Pass through exit codes if proposal doesn't exist.
1165+
let _ = st.get_proposal(rt.store(), params.id)?;
1166+
// Proposal was published but never activated.
1167+
Err(ActorError::unchecked(
1168+
EX_DEAL_NOT_ACTIVATED,
1169+
format!("deal {} not yet activated", params.id),
1170+
))
1171+
}
11411172
}
11421173
}
11431174
}
@@ -1603,6 +1634,7 @@ impl ActorCode for Actor {
16031634
GetDealProviderCollateralExported => get_deal_provider_collateral,
16041635
GetDealVerifiedExported => get_deal_verified,
16051636
GetDealActivationExported => get_deal_activation,
1637+
GetDealSectorExported => get_deal_sector,
16061638
SectorContentChangedExported => sector_content_changed,
16071639
}
16081640
}

actors/market/src/state.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1086,6 +1086,7 @@ pub fn get_proposal<BS: Blockstore>(
10861086
// If the deal ID has been used, it must have been cleaned up.
10871087
ActorError::unchecked(EX_DEAL_EXPIRED, format!("deal {} expired", id))
10881088
} else {
1089+
// Never been published.
10891090
ActorError::not_found(format!("no such deal {}", id))
10901091
}
10911092
})?;

actors/market/src/types.rs

+9
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,15 @@ pub struct GetDealActivationReturn {
242242
pub terminated: ChainEpoch,
243243
}
244244

245+
pub type GetDealSectorParams = DealQueryParams;
246+
247+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
248+
#[serde(transparent)]
249+
pub struct GetDealSectorReturn {
250+
/// Sector number with the provider that has committed the deal.
251+
pub sector: SectorNumber,
252+
}
253+
245254
// Interface market clients can implement to receive notifications from builtin market
246255
pub const MARKET_NOTIFY_DEAL_METHOD: u64 = frc42_dispatch::method_hash!("MarketNotifyDeal");
247256

actors/market/tests/deal_api_test.rs

+18-16
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,12 @@ use serde::de::DeserializeOwned;
99
use fil_actor_market::{
1010
Actor as MarketActor, DealQueryParams, GetDealActivationReturn, GetDealClientCollateralReturn,
1111
GetDealClientReturn, GetDealDataCommitmentReturn, GetDealLabelReturn,
12-
GetDealProviderCollateralReturn, GetDealProviderReturn, GetDealTermReturn,
13-
GetDealTotalPriceReturn, GetDealVerifiedReturn, Method, EX_DEAL_EXPIRED,
12+
GetDealProviderCollateralReturn, GetDealProviderReturn, GetDealSectorReturn, GetDealTermReturn,
13+
GetDealTotalPriceReturn, GetDealVerifiedReturn, Method, EX_DEAL_EXPIRED, EX_DEAL_NOT_ACTIVATED,
1414
};
1515
use fil_actors_runtime::network::EPOCHS_IN_DAY;
1616
use fil_actors_runtime::runtime::policy_constants::DEAL_UPDATES_INTERVAL;
17-
use fil_actors_runtime::test_utils::{
18-
expect_abort_contains_message, MockRuntime, ACCOUNT_ACTOR_CODE_ID,
19-
};
17+
use fil_actors_runtime::test_utils::{expect_abort, MockRuntime, ACCOUNT_ACTOR_CODE_ID};
2018
use fil_actors_runtime::ActorError;
2119
use fil_actors_runtime::BURNT_FUNDS_ACTOR_ADDR;
2220
use harness::*;
@@ -114,6 +112,7 @@ fn activation() {
114112
query_deal(&rt, Method::GetDealActivationExported, id);
115113
assert_eq!(EPOCH_UNDEFINED, activation.activated);
116114
assert_eq!(EPOCH_UNDEFINED, activation.terminated);
115+
query_deal_fails(&rt, Method::GetDealSectorExported, id, EX_DEAL_NOT_ACTIVATED);
117116

118117
// activate the deal
119118
let activate_epoch = start_epoch - 2;
@@ -124,6 +123,10 @@ fn activation() {
124123
query_deal(&rt, Method::GetDealActivationExported, id);
125124
assert_eq!(activate_epoch, activation.activated);
126125
assert_eq!(EPOCH_UNDEFINED, activation.terminated);
126+
assert_eq!(
127+
GetDealSectorReturn { sector: sector_number },
128+
query_deal(&rt, Method::GetDealSectorExported, id)
129+
);
127130

128131
// terminate early
129132
let terminate_epoch = activate_epoch + 100;
@@ -133,6 +136,7 @@ fn activation() {
133136
query_deal(&rt, Method::GetDealActivationExported, id);
134137
assert_eq!(activate_epoch, activation.activated);
135138
assert_eq!(terminate_epoch, activation.terminated);
139+
query_deal_fails(&rt, Method::GetDealSectorExported, id, EX_DEAL_EXPIRED);
136140

137141
// Clean up state
138142
let clean_epoch = terminate_epoch + DEAL_UPDATES_INTERVAL;
@@ -146,24 +150,22 @@ fn activation() {
146150
ExitCode::OK,
147151
);
148152
cron_tick(&rt);
149-
expect_abort_contains_message(
150-
EX_DEAL_EXPIRED,
151-
"expired",
152-
query_deal_raw(&rt, Method::GetDealActivationExported, id),
153-
);
153+
query_deal_fails(&rt, Method::GetDealActivationExported, id, EX_DEAL_EXPIRED);
154+
query_deal_fails(&rt, Method::GetDealSectorExported, id, EX_DEAL_EXPIRED);
154155

155-
// Non-existent deal is NOT FOUND
156-
expect_abort_contains_message(
157-
ExitCode::USR_NOT_FOUND,
158-
"no such deal",
159-
query_deal_raw(&rt, Method::GetDealActivationExported, id + 1),
160-
);
156+
// Non-existent deal is USR_NOT_FOUND
157+
query_deal_fails(&rt, Method::GetDealActivationExported, id + 1, ExitCode::USR_NOT_FOUND);
158+
query_deal_fails(&rt, Method::GetDealSectorExported, id + 1, ExitCode::USR_NOT_FOUND);
161159
}
162160

163161
fn query_deal<T: DeserializeOwned>(rt: &MockRuntime, method: Method, id: u64) -> T {
164162
query_deal_raw(rt, method, id).unwrap().unwrap().deserialize().unwrap()
165163
}
166164

165+
fn query_deal_fails(rt: &MockRuntime, method: Method, id: u64, expected: ExitCode) {
166+
expect_abort(expected, query_deal_raw(rt, method, id));
167+
}
168+
167169
fn query_deal_raw(
168170
rt: &MockRuntime,
169171
method: Method,

0 commit comments

Comments
 (0)