Skip to content

Commit d85759f

Browse files
anortharajasek
authored andcommitted
Exported API method for market actor escrow/locked balance (#812)
1 parent 0f22685 commit d85759f

File tree

6 files changed

+151
-125
lines changed

6 files changed

+151
-125
lines changed

actors/market/src/lib.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use log::info;
2626
use num_derive::FromPrimitive;
2727
use num_traits::{FromPrimitive, Zero};
2828

29+
use crate::balance_table::BalanceTable;
2930
use fil_actors_runtime::cbor::{deserialize, serialize, serialize_vec};
3031
use fil_actors_runtime::runtime::builtins::Type;
3132
use fil_actors_runtime::runtime::{ActorCode, Policy, Runtime};
@@ -72,9 +73,10 @@ pub enum Method {
7273
OnMinerSectorsTerminate = 7,
7374
ComputeDataCommitment = 8,
7475
CronTick = 9,
75-
// Method numbers derived from FRC-XXXX standards
76+
// Method numbers derived from FRC-0042 standards
7677
AddBalanceExported = frc42_dispatch::method_hash!("AddBalance"),
7778
WithdrawBalanceExported = frc42_dispatch::method_hash!("WithdrawBalance"),
79+
GetBalanceExported = frc42_dispatch::method_hash!("GetBalance"),
7880
}
7981

8082
/// Market Actor
@@ -185,6 +187,33 @@ impl Actor {
185187
Ok(WithdrawBalanceReturn { amount_withdrawn: amount_extracted })
186188
}
187189

190+
/// Returns the escrow balance and locked amount for an address.
191+
fn get_balance(
192+
rt: &mut impl Runtime,
193+
account: Address,
194+
) -> Result<GetBalanceReturn, ActorError> {
195+
rt.validate_immediate_caller_accept_any()?;
196+
let nominal = rt.resolve_address(&account).ok_or_else(|| {
197+
actor_error!(illegal_argument, "failed to resolve address {}", account)
198+
})?;
199+
let account = Address::new_id(nominal);
200+
201+
let store = rt.store();
202+
let st: State = rt.state()?;
203+
let balances = BalanceTable::from_root(store, &st.escrow_table)
204+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load escrow table")?;
205+
let locks = BalanceTable::from_root(store, &st.locked_table)
206+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load locked table")?;
207+
let balance = balances
208+
.get(&account)
209+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to get escrow balance")?;
210+
let locked = locks
211+
.get(&account)
212+
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to get locked balance")?;
213+
214+
Ok(GetBalanceReturn { balance, locked })
215+
}
216+
188217
/// Publish a new set of storage deals (not yet included in a sector).
189218
fn publish_storage_deals(
190219
rt: &mut impl Runtime,
@@ -1431,6 +1460,10 @@ impl ActorCode for Actor {
14311460
Self::cron_tick(rt)?;
14321461
Ok(RawBytes::default())
14331462
}
1463+
Some(Method::GetBalanceExported) => {
1464+
let res = Self::get_balance(rt, cbor::deserialize_params(params)?)?;
1465+
Ok(RawBytes::serialize(res)?)
1466+
}
14341467
None => Err(actor_error!(unhandled_message, "Invalid method")),
14351468
}
14361469
}

actors/market/src/types.rs

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,41 +22,40 @@ use super::deal::{ClientDealProposal, DealProposal, DealState};
2222
pub const PROPOSALS_AMT_BITWIDTH: u32 = 5;
2323
pub const STATES_AMT_BITWIDTH: u32 = 6;
2424

25-
#[derive(Serialize_tuple, Deserialize_tuple)]
25+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
2626
pub struct WithdrawBalanceParams {
2727
pub provider_or_client: Address,
2828
pub amount: TokenAmount,
2929
}
3030

3131
impl Cbor for WithdrawBalanceParams {}
3232

33-
#[derive(Serialize_tuple, Deserialize_tuple)]
33+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
3434
#[serde(transparent)]
3535
pub struct WithdrawBalanceReturn {
3636
pub amount_withdrawn: TokenAmount,
3737
}
3838

39-
#[derive(Serialize_tuple, Deserialize_tuple)]
40-
pub struct OnMinerSectorsTerminateParams {
41-
pub epoch: ChainEpoch,
42-
pub deal_ids: Vec<DealID>,
39+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
40+
pub struct GetBalanceReturn {
41+
pub balance: TokenAmount,
42+
pub locked: TokenAmount,
4343
}
4444

45-
#[derive(Serialize_tuple)]
46-
47-
pub struct OnMinerSectorsTerminateParamsRef<'a> {
45+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
46+
pub struct OnMinerSectorsTerminateParams {
4847
pub epoch: ChainEpoch,
49-
pub deal_ids: &'a [DealID],
48+
pub deal_ids: Vec<DealID>,
5049
}
5150

52-
#[derive(Serialize_tuple, Deserialize_tuple)]
51+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
5352
pub struct PublishStorageDealsParams {
5453
pub deals: Vec<ClientDealProposal>,
5554
}
5655

5756
impl Cbor for PublishStorageDealsParams {}
5857

59-
#[derive(Serialize_tuple, Deserialize_tuple, Debug)]
58+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, PartialEq)] // Add Eq when BitField does
6059
pub struct PublishStorageDealsReturn {
6160
pub ids: Vec<DealID>,
6261
pub valid_deals: BitField,
@@ -65,73 +64,63 @@ pub struct PublishStorageDealsReturn {
6564
// Changed since V2:
6665
// - Array of Sectors rather than just one
6766
// - Removed SectorStart
68-
#[derive(Serialize_tuple, Deserialize_tuple)]
67+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
6968
pub struct VerifyDealsForActivationParams {
7069
pub sectors: Vec<SectorDeals>,
7170
}
7271

73-
#[derive(Serialize_tuple, Deserialize_tuple)]
72+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
7473
pub struct SectorDeals {
7574
pub sector_type: RegisteredSealProof,
7675
pub sector_expiry: ChainEpoch,
7776
pub deal_ids: Vec<DealID>,
7877
}
7978

80-
#[derive(Serialize_tuple)]
81-
pub struct VerifyDealsForActivationParamsRef<'a> {
82-
pub sectors: &'a [SectorDeals],
83-
}
84-
85-
#[derive(Serialize_tuple, Deserialize_tuple, Default)]
79+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
8680
pub struct VerifyDealsForActivationReturn {
8781
pub sectors: Vec<SectorDealData>,
8882
}
8983

90-
#[derive(Serialize_tuple, Deserialize_tuple, Default, Clone)]
84+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq, Default)]
9185
pub struct SectorDealData {
9286
/// Option::None signifies commitment to empty sector, meaning no deals.
9387
pub commd: Option<Cid>,
9488
}
9589

96-
#[derive(Serialize_tuple, Deserialize_tuple)]
90+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
9791
pub struct ActivateDealsParams {
9892
pub deal_ids: Vec<DealID>,
9993
pub sector_expiry: ChainEpoch,
10094
}
10195

102-
#[derive(Serialize_tuple, Deserialize_tuple, Clone)]
96+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
10397
pub struct VerifiedDealInfo {
10498
pub client: ActorID,
10599
pub allocation_id: AllocationID,
106100
pub data: Cid,
107101
pub size: PaddedPieceSize,
108102
}
109103

110-
#[derive(Serialize_tuple, Deserialize_tuple)]
104+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
111105
pub struct ActivateDealsResult {
112106
#[serde(with = "bigint_ser")]
113107
pub nonverified_deal_space: BigInt,
114108
pub verified_infos: Vec<VerifiedDealInfo>,
115109
}
116-
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Default)]
110+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
117111
pub struct DealSpaces {
118112
#[serde(with = "bigint_ser")]
119113
pub deal_space: BigInt,
120114
#[serde(with = "bigint_ser")]
121115
pub verified_deal_space: BigInt,
122116
}
123117

124-
#[derive(Serialize_tuple, Deserialize_tuple)]
118+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
125119
pub struct ComputeDataCommitmentParams {
126120
pub inputs: Vec<SectorDataSpec>,
127121
}
128122

129-
#[derive(Serialize_tuple)]
130-
pub struct ComputeDataCommitmentParamsRef<'a> {
131-
pub inputs: &'a [SectorDataSpec],
132-
}
133-
134-
#[derive(Serialize_tuple, Deserialize_tuple)]
123+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
135124
pub struct ComputeDataCommitmentReturn {
136125
pub commds: Vec<Cid>,
137126
}
@@ -142,7 +131,7 @@ pub type DealArray<'bs, BS> = Array<'bs, DealProposal, BS>;
142131
/// A specialization of a array to deals.
143132
pub type DealMetaArray<'bs, BS> = Array<'bs, DealState, BS>;
144133

145-
#[derive(Serialize_tuple, Deserialize_tuple)]
134+
#[derive(Serialize_tuple, Deserialize_tuple, Debug, Clone, Eq, PartialEq)]
146135
pub struct SectorDataSpec {
147136
pub deal_ids: Vec<DealID>,
148137
pub sector_type: RegisteredSealProof,

actors/market/tests/cron_tick_deal_expiry.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ fn expired_deal_should_unlock_the_remaining_client_and_provider_locked_balance_a
163163
);
164164
let deal_proposal = get_deal_proposal(&mut rt, deal_id);
165165

166-
let c_escrow = get_escrow_balance(&rt, &CLIENT_ADDR).unwrap();
167-
let p_escrow = get_escrow_balance(&rt, &PROVIDER_ADDR).unwrap();
166+
let c_escrow = get_balance(&mut rt, &CLIENT_ADDR).balance;
167+
let p_escrow = get_balance(&mut rt, &PROVIDER_ADDR).balance;
168168

169169
// move the current epoch so that deal is expired
170170
rt.set_epoch(END_EPOCH + 1000);
@@ -173,11 +173,13 @@ fn expired_deal_should_unlock_the_remaining_client_and_provider_locked_balance_a
173173
// assert balances
174174
let payment = deal_proposal.total_storage_fee();
175175

176-
assert_eq!(c_escrow - &payment, get_escrow_balance(&rt, &CLIENT_ADDR).unwrap());
177-
assert!(get_locked_balance(&mut rt, CLIENT_ADDR).is_zero());
176+
let client_acct = get_balance(&mut rt, &CLIENT_ADDR);
177+
assert_eq!(c_escrow - &payment, client_acct.balance);
178+
assert!(client_acct.locked.is_zero());
178179

179-
assert_eq!(p_escrow + &payment, get_escrow_balance(&rt, &PROVIDER_ADDR).unwrap());
180-
assert!(get_locked_balance(&mut rt, PROVIDER_ADDR).is_zero());
180+
let provider_acct = get_balance(&mut rt, &PROVIDER_ADDR);
181+
assert_eq!(p_escrow + &payment, provider_acct.balance);
182+
assert!(provider_acct.locked.is_zero());
181183

182184
// deal should be deleted
183185
assert_deal_deleted(&mut rt, deal_id, deal_proposal);
@@ -201,7 +203,7 @@ fn all_payments_are_made_for_a_deal_client_withdraws_collateral_and_client_accou
201203
// move the current epoch so that deal is expired
202204
rt.set_epoch(END_EPOCH + 100);
203205
cron_tick(&mut rt);
204-
assert_eq!(deal_proposal.client_collateral, get_escrow_balance(&rt, &CLIENT_ADDR).unwrap());
206+
assert_eq!(deal_proposal.client_collateral, get_balance(&mut rt, &CLIENT_ADDR).balance);
205207

206208
// client withdraws collateral -> account should be removed as it now has zero balance
207209
withdraw_client_balance(

actors/market/tests/cron_tick_timedout_deals.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ fn timed_out_deal_is_slashed_and_deleted() {
3636
);
3737
let deal_proposal = get_deal_proposal(&mut rt, deal_id);
3838

39-
let c_escrow = get_escrow_balance(&rt, &CLIENT_ADDR).unwrap();
39+
let c_escrow = get_balance(&mut rt, &CLIENT_ADDR).balance;
4040

4141
// do a cron tick for it -> should time out and get slashed
4242
rt.set_epoch(process_epoch(START_EPOCH, deal_id));
@@ -50,8 +50,9 @@ fn timed_out_deal_is_slashed_and_deleted() {
5050
);
5151
cron_tick(&mut rt);
5252

53-
assert_eq!(c_escrow, get_escrow_balance(&rt, &CLIENT_ADDR).unwrap());
54-
assert!(get_locked_balance(&mut rt, CLIENT_ADDR).is_zero());
53+
let client_acct = get_balance(&mut rt, &CLIENT_ADDR);
54+
assert_eq!(c_escrow, client_acct.balance);
55+
assert!(client_acct.locked.is_zero());
5556
assert_account_zero(&mut rt, PROVIDER_ADDR);
5657
assert_deal_deleted(&mut rt, deal_id, deal_proposal);
5758
check_state(&rt);

0 commit comments

Comments
 (0)