Skip to content

Commit e701cdb

Browse files
authored
Simplify pledge update on sector upgrade (#1267)
* Simplify pledge update on sector upgrade This is a small pre-factor for FIP0056 because I'm handling the pledge the same way there. Basically, instead of checking if we have enough funds to cover the pledge each time we update a sector, do so once at the end (and check the balance invariants). This will save a _bit_ of gas, but, more importantly, it avoids using two different "pledge deltas". * cargo fmt
1 parent 1e80389 commit e701cdb

File tree

1 file changed

+113
-103
lines changed

1 file changed

+113
-103
lines changed

actors/miner/src/lib.rs

Lines changed: 113 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2019-2022 ChainSafe Systems
22
// SPDX-License-Identifier: Apache-2.0, MIT
33

4+
use std::cmp::max;
45
use std::collections::btree_map::Entry;
56
use std::collections::BTreeMap;
67
use std::iter;
@@ -1216,65 +1217,62 @@ impl Actor {
12161217

12171218
let rew = request_current_epoch_block_reward(rt)?;
12181219
let pow = request_current_total_power(rt)?;
1220+
let circulating_supply = rt.total_fil_circ_supply();
12191221

12201222
let succeeded_sectors = rt.transaction(|state: &mut State, rt| {
12211223
let mut succeeded = Vec::new();
1222-
let mut deadlines = state
1223-
.load_deadlines(rt.store())?;
1224+
let mut deadlines = state.load_deadlines(rt.store())?;
12241225

12251226
let mut new_sectors = Vec::with_capacity(validated_updates.len());
12261227
for &dl_idx in deadlines_to_load.iter() {
1227-
let mut deadline = deadlines
1228-
.load_deadline(rt.policy(), rt.store(), dl_idx)
1229-
.map_err(|e|
1228+
let mut deadline =
1229+
deadlines.load_deadline(rt.policy(), rt.store(), dl_idx).map_err(|e| {
12301230
e.downcast_default(
12311231
ExitCode::USR_ILLEGAL_STATE,
12321232
format!("failed to load deadline {}", dl_idx),
12331233
)
1234-
)?;
1234+
})?;
12351235

1236-
let mut partitions = deadline
1237-
.partitions_amt(rt.store())
1238-
.map_err(|e|
1239-
e.downcast_default(
1240-
ExitCode::USR_ILLEGAL_STATE,
1241-
format!("failed to load partitions for deadline {}", dl_idx),
1242-
)
1243-
)?;
1236+
let mut partitions = deadline.partitions_amt(rt.store()).map_err(|e| {
1237+
e.downcast_default(
1238+
ExitCode::USR_ILLEGAL_STATE,
1239+
format!("failed to load partitions for deadline {}", dl_idx),
1240+
)
1241+
})?;
12441242

12451243
let quant = state.quant_spec_for_deadline(rt.policy(), dl_idx);
12461244

12471245
for with_details in &decls_by_deadline[&dl_idx] {
1248-
let update_proof_type = with_details.sector_info.seal_proof
1249-
.registered_update_proof()
1250-
.map_err(|_|
1251-
actor_error!(
1252-
illegal_state,
1253-
"couldn't load update proof type"
1254-
)
1246+
let update_proof_type =
1247+
with_details.sector_info.seal_proof.registered_update_proof().map_err(
1248+
|_| actor_error!(illegal_state, "couldn't load update proof type"),
12551249
)?;
12561250
if with_details.update.update_proof_type != update_proof_type {
12571251
return Err(actor_error!(
12581252
illegal_argument,
1259-
format!("unsupported update proof type {}", i64::from(with_details.update.update_proof_type))
1253+
format!(
1254+
"unsupported update proof type {}",
1255+
i64::from(with_details.update.update_proof_type)
1256+
)
12601257
));
12611258
}
12621259

1263-
rt.verify_replica_update(
1264-
&ReplicaUpdateInfo {
1265-
update_proof_type,
1266-
new_sealed_cid: with_details.update.new_sealed_cid,
1267-
old_sealed_cid: with_details.sector_info.sealed_cid,
1268-
new_unsealed_cid: with_details.full_unsealed_cid,
1269-
proof: with_details.update.replica_proof.clone(),
1270-
}
1271-
)
1272-
.map_err(|e|
1273-
e.downcast_default(
1274-
ExitCode::USR_ILLEGAL_ARGUMENT,
1275-
format!("failed to verify replica proof for sector {}", with_details.sector_info.sector_number),
1276-
)
1277-
)?;
1260+
rt.verify_replica_update(&ReplicaUpdateInfo {
1261+
update_proof_type,
1262+
new_sealed_cid: with_details.update.new_sealed_cid,
1263+
old_sealed_cid: with_details.sector_info.sealed_cid,
1264+
new_unsealed_cid: with_details.full_unsealed_cid,
1265+
proof: with_details.update.replica_proof.clone(),
1266+
})
1267+
.map_err(|e| {
1268+
e.downcast_default(
1269+
ExitCode::USR_ILLEGAL_ARGUMENT,
1270+
format!(
1271+
"failed to verify replica proof for sector {}",
1272+
with_details.sector_info.sector_number
1273+
),
1274+
)
1275+
})?;
12781276

12791277
let mut new_sector_info = with_details.sector_info.clone();
12801278

@@ -1291,8 +1289,10 @@ impl Actor {
12911289

12921290
let duration = new_sector_info.expiration - new_sector_info.activation;
12931291

1294-
new_sector_info.deal_weight = with_details.deal_spaces.deal_space.clone() * duration;
1295-
new_sector_info.verified_deal_weight = with_details.deal_spaces.verified_deal_space.clone() * duration;
1292+
new_sector_info.deal_weight =
1293+
with_details.deal_spaces.deal_space.clone() * duration;
1294+
new_sector_info.verified_deal_weight =
1295+
with_details.deal_spaces.verified_deal_space.clone() * duration;
12961296

12971297
// compute initial pledge
12981298
let qa_pow = qa_power_for_weight(
@@ -1302,7 +1302,8 @@ impl Actor {
13021302
&new_sector_info.verified_deal_weight,
13031303
);
13041304

1305-
new_sector_info.replaced_day_reward = with_details.sector_info.expected_day_reward.clone();
1305+
new_sector_info.replaced_day_reward =
1306+
with_details.sector_info.expected_day_reward.clone();
13061307
new_sector_info.expected_day_reward = expected_reward_for_power(
13071308
&rew.this_epoch_reward_smoothed,
13081309
&pow.quality_adj_power_smoothed,
@@ -1318,78 +1319,68 @@ impl Actor {
13181319
new_sector_info.replaced_sector_age =
13191320
ChainEpoch::max(0, rt.curr_epoch() - with_details.sector_info.activation);
13201321

1321-
let initial_pledge_at_upgrade = initial_pledge_for_power(
1322-
&qa_pow,
1323-
&rew.this_epoch_baseline_power,
1324-
&rew.this_epoch_reward_smoothed,
1325-
&pow.quality_adj_power_smoothed,
1326-
&rt.total_fil_circ_supply(),
1322+
new_sector_info.initial_pledge = max(
1323+
new_sector_info.initial_pledge,
1324+
initial_pledge_for_power(
1325+
&qa_pow,
1326+
&rew.this_epoch_baseline_power,
1327+
&rew.this_epoch_reward_smoothed,
1328+
&pow.quality_adj_power_smoothed,
1329+
&circulating_supply,
1330+
),
13271331
);
13281332

1329-
if initial_pledge_at_upgrade > with_details.sector_info.initial_pledge {
1330-
let deficit = &initial_pledge_at_upgrade - &with_details.sector_info.initial_pledge;
1331-
1332-
let unlocked_balance = state
1333-
.get_unlocked_balance(&rt.current_balance())
1334-
.map_err(|_|
1335-
actor_error!(illegal_state, "failed to calculate unlocked balance")
1336-
)?;
1337-
if unlocked_balance < deficit {
1338-
return Err(actor_error!(
1339-
insufficient_funds,
1340-
"insufficient funds for new initial pledge requirement {}, available: {}, skipping sector {}",
1341-
deficit,
1342-
unlocked_balance,
1343-
with_details.sector_info.sector_number
1344-
));
1345-
}
1346-
1347-
state.add_initial_pledge(&deficit).map_err(|_e|
1348-
actor_error!(
1349-
illegal_state,
1350-
"failed to add initial pledge"
1351-
)
1352-
)?;
1353-
1354-
new_sector_info.initial_pledge = initial_pledge_at_upgrade;
1355-
}
1356-
13571333
let mut partition = partitions
13581334
.get(with_details.update.partition)
1359-
.map_err(|e|
1335+
.map_err(|e| {
13601336
e.downcast_default(
13611337
ExitCode::USR_ILLEGAL_STATE,
1362-
format!("failed to load deadline {} partition {}", with_details.update.deadline, with_details.update.partition),
1338+
format!(
1339+
"failed to load deadline {} partition {}",
1340+
with_details.update.deadline, with_details.update.partition
1341+
),
13631342
)
1364-
)?
1343+
})?
13651344
.cloned()
1366-
.ok_or_else(|| actor_error!(not_found, "no such deadline {} partition {}", dl_idx, with_details.update.partition))?;
1345+
.ok_or_else(|| {
1346+
actor_error!(
1347+
not_found,
1348+
"no such deadline {} partition {}",
1349+
dl_idx,
1350+
with_details.update.partition
1351+
)
1352+
})?;
13671353

13681354
let (partition_power_delta, partition_pledge_delta) = partition
1369-
.replace_sectors(rt.store(),
1370-
&[with_details.sector_info.clone()],
1371-
&[new_sector_info.clone()],
1372-
info.sector_size,
1373-
quant,
1355+
.replace_sectors(
1356+
rt.store(),
1357+
&[with_details.sector_info.clone()],
1358+
&[new_sector_info.clone()],
1359+
info.sector_size,
1360+
quant,
13741361
)
13751362
.map_err(|e| {
13761363
e.downcast_default(
13771364
ExitCode::USR_ILLEGAL_STATE,
1378-
format!("failed to replace sector at deadline {} partition {}", with_details.update.deadline, with_details.update.partition),
1365+
format!(
1366+
"failed to replace sector at deadline {} partition {}",
1367+
with_details.update.deadline, with_details.update.partition
1368+
),
13791369
)
13801370
})?;
13811371

13821372
power_delta += &partition_power_delta;
13831373
pledge_delta += &partition_pledge_delta;
13841374

1385-
partitions
1386-
.set(with_details.update.partition, partition)
1387-
.map_err(|e| {
1388-
e.downcast_default(
1389-
ExitCode::USR_ILLEGAL_STATE,
1390-
format!("failed to save deadline {} partition {}", with_details.update.deadline, with_details.update.partition),
1391-
)
1392-
})?;
1375+
partitions.set(with_details.update.partition, partition).map_err(|e| {
1376+
e.downcast_default(
1377+
ExitCode::USR_ILLEGAL_STATE,
1378+
format!(
1379+
"failed to save deadline {} partition {}",
1380+
with_details.update.deadline, with_details.update.partition
1381+
),
1382+
)
1383+
})?;
13931384

13941385
succeeded.push(new_sector_info.sector_number);
13951386
new_sectors.push(new_sector_info);
@@ -1402,14 +1393,14 @@ impl Actor {
14021393
)
14031394
})?;
14041395

1405-
deadlines
1406-
.update_deadline(rt.policy(), rt.store(), dl_idx, &deadline)
1407-
.map_err(|e| {
1396+
deadlines.update_deadline(rt.policy(), rt.store(), dl_idx, &deadline).map_err(
1397+
|e| {
14081398
e.downcast_default(
14091399
ExitCode::USR_ILLEGAL_STATE,
14101400
format!("failed to save deadline {}", dl_idx),
14111401
)
1412-
})?;
1402+
},
1403+
)?;
14131404
}
14141405

14151406
let success_len = succeeded.len();
@@ -1432,10 +1423,7 @@ impl Actor {
14321423

14331424
// Overwrite sector infos.
14341425
sectors.store(new_sectors).map_err(|e| {
1435-
e.downcast_default(
1436-
ExitCode::USR_ILLEGAL_STATE,
1437-
"failed to update sector infos",
1438-
)
1426+
e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to update sector infos")
14391427
})?;
14401428

14411429
state.sectors = sectors.amt.flush().map_err(|e| {
@@ -1445,9 +1433,31 @@ impl Actor {
14451433
e.downcast_default(ExitCode::USR_ILLEGAL_STATE, "failed to save deadlines")
14461434
})?;
14471435

1448-
BitField::try_from_bits(succeeded).map_err(|_| {
1449-
actor_error!(illegal_argument; "invalid sector number")
1450-
})
1436+
// Update pledge.
1437+
let current_balance = rt.current_balance();
1438+
if pledge_delta.is_positive() {
1439+
let unlocked_balance =
1440+
state.get_unlocked_balance(&current_balance).map_err(|e| {
1441+
actor_error!(illegal_state, "failed to calculate unlocked balance: {}", e)
1442+
})?;
1443+
if unlocked_balance < pledge_delta {
1444+
return Err(actor_error!(
1445+
insufficient_funds,
1446+
"insufficient funds for aggregate initial pledge requirement {}, available: {}",
1447+
pledge_delta,
1448+
unlocked_balance
1449+
));
1450+
}
1451+
}
1452+
1453+
state
1454+
.add_initial_pledge(&pledge_delta)
1455+
.map_err(|e| actor_error!(illegal_state, "failed to add initial pledge: {}", e))?;
1456+
1457+
state.check_balance_invariants(&current_balance).map_err(balance_invariants_broken)?;
1458+
1459+
BitField::try_from_bits(succeeded)
1460+
.map_err(|_| actor_error!(illegal_argument; "invalid sector number"))
14511461
})?;
14521462

14531463
notify_pledge_changed(rt, &pledge_delta)?;

0 commit comments

Comments
 (0)