From 9ff3db5ca84f9603da5db0078ea79ee5500159aa Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Wed, 22 Jan 2025 19:07:34 +1100 Subject: [PATCH] feat(miner): make precommit HAMT & AMT CIDs nullable --- actors/miner/src/bitfield_queue.rs | 10 +- actors/miner/src/deadline_state.rs | 11 +- actors/miner/src/partition_state.rs | 4 +- actors/miner/src/state.rs | 231 ++++++++++-------- actors/miner/src/testing.rs | 87 ++++--- .../tests/miner_actor_test_bitfield_queue.rs | 2 +- .../tests/miner_actor_test_construction.rs | 3 +- .../tests/miner_actor_test_partitions.rs | 12 +- actors/miner/tests/state_harness.rs | 7 +- actors/miner/tests/util.rs | 30 +-- 10 files changed, 221 insertions(+), 176 deletions(-) diff --git a/actors/miner/src/bitfield_queue.rs b/actors/miner/src/bitfield_queue.rs index 673f7ee90..61d86dc42 100644 --- a/actors/miner/src/bitfield_queue.rs +++ b/actors/miner/src/bitfield_queue.rs @@ -12,6 +12,7 @@ use fvm_shared::clock::ChainEpoch; use itertools::Itertools; use super::QuantSpec; +use super::PRECOMMIT_EXPIRY_AMT_BITWIDTH; /// Wrapper for working with an AMT[ChainEpoch]*Bitfield functioning as a queue, bucketed by epoch. /// Keys in the queue are quantized (upwards), modulo some offset, to reduce the cardinality of keys. @@ -21,7 +22,14 @@ pub struct BitFieldQueue<'db, BS> { } impl<'db, BS: Blockstore> BitFieldQueue<'db, BS> { - pub fn new(store: &'db BS, root: &Cid, quant: QuantSpec) -> Result { + pub fn new(store: &'db BS, quant: QuantSpec) -> Self { + Self { + amt: Array::::new_with_bit_width(store, PRECOMMIT_EXPIRY_AMT_BITWIDTH), + quant, + } + } + + pub fn load(store: &'db BS, root: &Cid, quant: QuantSpec) -> Result { Ok(Self { amt: Array::load(root, store)?, quant }) } diff --git a/actors/miner/src/deadline_state.rs b/actors/miner/src/deadline_state.rs index bf9160dca..1b26036ea 100644 --- a/actors/miner/src/deadline_state.rs +++ b/actors/miner/src/deadline_state.rs @@ -314,7 +314,7 @@ impl Deadline { return Ok(()); } - let mut queue = BitFieldQueue::new(store, &self.expirations_epochs, quant) + let mut queue = BitFieldQueue::load(store, &self.expirations_epochs, quant) .map_err(|e| e.downcast_wrap("failed to load expiration queue"))?; queue .add_to_queue_values(expiration_epoch, partitions.iter().copied()) @@ -475,9 +475,8 @@ impl Deadline { self.partitions = partitions.flush()?; // Next, update the expiration queue. - let mut deadline_expirations = - BitFieldQueue::new(store, &self.expirations_epochs, quant) - .map_err(|e| e.downcast_wrap("failed to load expiration epochs"))?; + let mut deadline_expirations = BitFieldQueue::load(store, &self.expirations_epochs, quant) + .map_err(|e| e.downcast_wrap("failed to load expiration epochs"))?; deadline_expirations .add_many_to_queue_values(partition_deadline_updates.iter().copied()) .map_err(|e| e.downcast_wrap("failed to add expirations for new deadlines"))?; @@ -552,7 +551,7 @@ impl Deadline { until: ChainEpoch, quant: QuantSpec, ) -> anyhow::Result<(BitField, bool)> { - let mut expirations = BitFieldQueue::new(store, &self.expirations_epochs, quant)?; + let mut expirations = BitFieldQueue::load(store, &self.expirations_epochs, quant)?; let (popped, modified) = expirations .pop_until(until) .map_err(|e| e.downcast_wrap("failed to pop expiring partitions"))?; @@ -741,7 +740,7 @@ impl Deadline { self.total_sectors -= removed_live_sectors + removed_dead_sectors; // Update expiration bitfields. - let mut expiration_epochs = BitFieldQueue::new(store, &self.expirations_epochs, quant) + let mut expiration_epochs = BitFieldQueue::load(store, &self.expirations_epochs, quant) .map_err(|e| e.downcast_wrap("failed to load expiration queue"))?; expiration_epochs.cut(to_remove).map_err(|e| { diff --git a/actors/miner/src/partition_state.rs b/actors/miner/src/partition_state.rs index 1eb2b6824..9904f6a9f 100644 --- a/actors/miner/src/partition_state.rs +++ b/actors/miner/src/partition_state.rs @@ -458,7 +458,7 @@ impl Partition { sectors: &BitField, ) -> anyhow::Result<()> { let mut early_termination_queue = - BitFieldQueue::new(store, &self.early_terminated, NO_QUANTIZATION) + BitFieldQueue::load(store, &self.early_terminated, NO_QUANTIZATION) .map_err(|e| e.downcast_wrap("failed to load early termination queue"))?; early_termination_queue @@ -644,7 +644,7 @@ impl Partition { ) -> anyhow::Result<(TerminationResult, /* has more */ bool)> { // Load early terminations. let mut early_terminated_queue = - BitFieldQueue::new(store, &self.early_terminated, NO_QUANTIZATION)?; + BitFieldQueue::load(store, &self.early_terminated, NO_QUANTIZATION)?; let mut processed = Vec::::new(); let mut remaining: Option<(BitField, ChainEpoch)> = None; diff --git a/actors/miner/src/state.rs b/actors/miner/src/state.rs index 0ba88729a..73f6fae3c 100644 --- a/actors/miner/src/state.rs +++ b/actors/miner/src/state.rs @@ -42,7 +42,7 @@ use super::{ pub type PreCommitMap = Map2; pub const PRECOMMIT_CONFIG: Config = Config { bit_width: HAMT_BIT_WIDTH, ..DEFAULT_HAMT_CONFIG }; -const PRECOMMIT_EXPIRY_AMT_BITWIDTH: u32 = 6; +pub const PRECOMMIT_EXPIRY_AMT_BITWIDTH: u32 = 6; pub const SECTORS_AMT_BITWIDTH: u32 = 5; /// Balance of Miner Actor should be greater than or equal to @@ -74,10 +74,10 @@ pub struct State { /// Sectors that have been pre-committed but not yet proven. /// Map, HAMT - pub pre_committed_sectors: Cid, + pub pre_committed_sectors: Option, // PreCommittedSectorsCleanUp maintains the state required to cleanup expired PreCommittedSectors. - pub pre_committed_sectors_cleanup: Cid, // BitFieldQueue (AMT[Epoch]*BitField) + pub pre_committed_sectors_cleanup: Option, // BitFieldQueue (AMT[Epoch]*BitField) /// Allocated sector IDs. Sector IDs can never be reused once allocated. pub allocated_sectors: Cid, // BitField @@ -129,18 +129,6 @@ impl State { period_start: ChainEpoch, deadline_idx: u64, ) -> Result { - let empty_precommit_map = - PreCommitMap::empty(store, PRECOMMIT_CONFIG, "precommits").flush()?; - - let empty_precommits_cleanup_array = - Array::::new_with_bit_width(store, PRECOMMIT_EXPIRY_AMT_BITWIDTH) - .flush() - .map_err(|e| { - e.downcast_default( - ExitCode::USR_ILLEGAL_STATE, - "failed to construct empty precommits array", - ) - })?; let empty_sectors_array = Array::::new_with_bit_width(store, SECTORS_AMT_BITWIDTH) .flush() @@ -180,7 +168,7 @@ impl State { initial_pledge: TokenAmount::default(), fee_debt: TokenAmount::default(), - pre_committed_sectors: empty_precommit_map, + pre_committed_sectors: None, allocated_sectors: empty_bitfield, sectors: empty_sectors_array, proving_period_start: period_start, @@ -188,7 +176,7 @@ impl State { deadlines: empty_deadlines, early_terminations: BitField::new(), deadline_cron_active: false, - pre_committed_sectors_cleanup: empty_precommits_cleanup_array, + pre_committed_sectors_cleanup: None, }) } @@ -289,19 +277,22 @@ impl State { store: &BS, precommits: Vec, ) -> anyhow::Result<()> { - let mut precommitted = - PreCommitMap::load(store, &self.pre_committed_sectors, PRECOMMIT_CONFIG, "precommits")?; + let mut precommitted = match self.pre_committed_sectors { + Some(cid) => PreCommitMap::load(store, &cid, PRECOMMIT_CONFIG, "precommits")?, + None => PreCommitMap::empty(store, PRECOMMIT_CONFIG, "precommits"), + }; + for precommit in precommits.into_iter() { let sector_no = precommit.info.sector_number; let modified = precommitted .set_if_absent(§or_no, precommit) .with_context(|| format!("storing precommit for {}", sector_no))?; if !modified { - return Err(anyhow!("sector {} already pre-commited", sector_no)); + return Err(anyhow!("sector {} already pre-committed", sector_no)); } } - self.pre_committed_sectors = precommitted.flush()?; + self.pre_committed_sectors = Some(precommitted.flush()?); Ok(()) } @@ -310,9 +301,13 @@ impl State { store: &BS, sector_num: SectorNumber, ) -> Result, ActorError> { - let precommitted = - PreCommitMap::load(store, &self.pre_committed_sectors, PRECOMMIT_CONFIG, "precommits")?; - Ok(precommitted.get(§or_num)?.cloned()) + match &self.pre_committed_sectors { + Some(cid) => { + let precommitted = PreCommitMap::load(store, cid, PRECOMMIT_CONFIG, "precommits")?; + Ok(precommitted.get(§or_num)?.cloned()) + } + None => Ok(None), + } } /// Gets and returns the requested pre-committed sectors, skipping missing sectors. @@ -321,23 +316,27 @@ impl State { store: &BS, sector_numbers: &[SectorNumber], ) -> anyhow::Result> { - let precommitted = - PreCommitMap::load(store, &self.pre_committed_sectors, PRECOMMIT_CONFIG, "precommits")?; - let mut result = Vec::with_capacity(sector_numbers.len()); - - for §or_number in sector_numbers { - let info = match precommitted - .get(§or_number) - .with_context(|| format!("loading precommit {}", sector_number))? - { - Some(info) => info.clone(), - None => continue, - }; - - result.push(info); + match &self.pre_committed_sectors { + Some(cid) => { + let precommitted = PreCommitMap::load(store, cid, PRECOMMIT_CONFIG, "precommits")?; + let mut result = Vec::with_capacity(sector_numbers.len()); + + for §or_number in sector_numbers { + let info = match precommitted + .get(§or_number) + .with_context(|| format!("loading precommit {}", sector_number))? + { + Some(info) => info.clone(), + None => continue, + }; + + result.push(info); + } + + Ok(result) + } + None => Ok(Vec::new()), } - - Ok(result) } pub fn delete_precommitted_sectors( @@ -345,17 +344,28 @@ impl State { store: &BS, sector_nums: &[SectorNumber], ) -> Result<(), ActorError> { - let mut precommitted = - PreCommitMap::load(store, &self.pre_committed_sectors, PRECOMMIT_CONFIG, "precommits")?; - for §or_num in sector_nums { - let prev_entry = precommitted.delete(§or_num)?; - if prev_entry.is_none() { - return Err(actor_error!(illegal_state, "sector {} not pre-committed", sector_num)); + match &self.pre_committed_sectors { + Some(cid) => { + let mut precommitted = + PreCommitMap::load(store, cid, PRECOMMIT_CONFIG, "precommits")?; + for §or_num in sector_nums { + let prev_entry = precommitted.delete(§or_num)?; + if prev_entry.is_none() { + return Err(actor_error!( + illegal_state, + "sector {} not pre-committed", + sector_num + )); + } + } + match precommitted.is_empty() { + true => self.pre_committed_sectors = None, + false => self.pre_committed_sectors = Some(precommitted.flush()?), + } + Ok(()) } + None => Err(actor_error!(illegal_state, "no pre-committed sectors to delete")), } - - self.pre_committed_sectors = precommitted.flush()?; - Ok(()) } pub fn has_sector_number( @@ -1059,12 +1069,14 @@ impl State { ) -> anyhow::Result<()> { // Load BitField Queue for sector expiry let quant = self.quant_spec_every_deadline(policy); - let mut queue = - super::BitFieldQueue::new(store, &self.pre_committed_sectors_cleanup, quant) - .map_err(|e| e.downcast_wrap("failed to load pre-commit clean up queue"))?; + let mut queue = match self.pre_committed_sectors_cleanup { + Some(ref cid) => BitFieldQueue::load(store, cid, quant) + .map_err(|e| e.downcast_wrap("failed to load pre-commit clean up queue"))?, + None => BitFieldQueue::new(store, quant), + }; queue.add_many_to_queue_values(cleanup_events.into_iter())?; - self.pre_committed_sectors_cleanup = queue.amt.flush()?; + self.pre_committed_sectors_cleanup = Some(queue.amt.flush()?); Ok(()) } @@ -1076,50 +1088,55 @@ impl State { ) -> anyhow::Result { let mut deposit_to_burn = TokenAmount::zero(); - // cleanup expired pre-committed sectors - let mut cleanup_queue = BitFieldQueue::new( - store, - &self.pre_committed_sectors_cleanup, - self.quant_spec_every_deadline(policy), - )?; + if let Some(ref cleanup_cid) = self.pre_committed_sectors_cleanup { + // cleanup expired pre-committed sectors + let mut cleanup_queue = + BitFieldQueue::load(store, cleanup_cid, self.quant_spec_every_deadline(policy))?; - let (sectors, modified) = cleanup_queue.pop_until(current_epoch)?; + let (sectors, modified) = cleanup_queue.pop_until(current_epoch)?; - if modified { - self.pre_committed_sectors_cleanup = cleanup_queue.amt.flush()?; - } - - let mut precommits_to_delete = Vec::new(); - let precommitted = - PreCommitMap::load(store, &self.pre_committed_sectors, PRECOMMIT_CONFIG, "precommits")?; - - for i in sectors.iter() { - let sector_number = i as SectorNumber; - let sector: SectorPreCommitOnChainInfo = - match precommitted.get(§or_number)?.cloned() { - Some(sector) => sector, - // already committed/deleted - None => continue, - }; - - // mark it for deletion - precommits_to_delete.push(sector_number); - - // increment deposit to burn - deposit_to_burn += sector.pre_commit_deposit; - } - - // Actually delete it. - if !precommits_to_delete.is_empty() { - self.delete_precommitted_sectors(store, &precommits_to_delete)?; - } + if modified { + if cleanup_queue.amt.count() == 0 { + self.pre_committed_sectors_cleanup = None; + } else { + self.pre_committed_sectors_cleanup = Some(cleanup_queue.amt.flush()?); + } + } - self.pre_commit_deposits -= &deposit_to_burn; - if self.pre_commit_deposits.is_negative() { - return Err(anyhow!( - "pre-commit clean up caused negative deposits: {}", - self.pre_commit_deposits - )); + if let Some(ref sectors_cid) = self.pre_committed_sectors { + let mut precommits_to_delete = Vec::new(); + let precommitted = + PreCommitMap::load(store, sectors_cid, PRECOMMIT_CONFIG, "precommits")?; + + for i in sectors.iter() { + let sector_number = i as SectorNumber; + let sector: SectorPreCommitOnChainInfo = + match precommitted.get(§or_number)?.cloned() { + Some(sector) => sector, + // already committed/deleted + None => continue, + }; + + // mark it for deletion + precommits_to_delete.push(sector_number); + + // increment deposit to burn + deposit_to_burn += sector.pre_commit_deposit; + } + + // Actually delete it. + if !precommits_to_delete.is_empty() { + self.delete_precommitted_sectors(store, &precommits_to_delete)?; + } + + self.pre_commit_deposits -= &deposit_to_burn; + if self.pre_commit_deposits.is_negative() { + return Err(anyhow!( + "pre-commit clean up caused negative deposits: {}", + self.pre_commit_deposits + )); + } + } } Ok(deposit_to_burn) @@ -1216,18 +1233,22 @@ impl State { sector_nos: impl IntoIterator>, ) -> Result, ActorError> { let mut precommits = Vec::new(); - let precommitted = - PreCommitMap::load(store, &self.pre_committed_sectors, PRECOMMIT_CONFIG, "precommits")?; - for sector_no in sector_nos.into_iter() { - let sector_no = *sector_no.borrow(); - if sector_no > MAX_SECTOR_NUMBER { - return Err(actor_error!(illegal_argument; "sector number greater than maximum")); + if let Some(ref sectors_cid) = self.pre_committed_sectors { + let precommitted = + PreCommitMap::load(store, sectors_cid, PRECOMMIT_CONFIG, "precommits")?; + for sector_no in sector_nos.into_iter() { + let sector_no = *sector_no.borrow(); + if sector_no > MAX_SECTOR_NUMBER { + return Err( + actor_error!(illegal_argument; "sector number greater than maximum"), + ); + } + let info: &SectorPreCommitOnChainInfo = precommitted + .get(§or_no) + .exit_code(ExitCode::USR_ILLEGAL_STATE)? + .ok_or_else(|| actor_error!(not_found, "sector {} not found", sector_no))?; + precommits.push(info.clone()); } - let info: &SectorPreCommitOnChainInfo = precommitted - .get(§or_no) - .exit_code(ExitCode::USR_ILLEGAL_STATE)? - .ok_or_else(|| actor_error!(not_found, "sector {} not found", sector_no))?; - precommits.push(info.clone()); } Ok(precommits) } diff --git a/actors/miner/src/testing.rs b/actors/miner/src/testing.rs index 64beb603a..5f188675b 100644 --- a/actors/miner/src/testing.rs +++ b/actors/miner/src/testing.rs @@ -323,51 +323,60 @@ fn check_precommits( // invert pre-commit clean up queue into a lookup by sector number let mut cleanup_epochs: BTreeMap = BTreeMap::new(); - match BitFieldQueue::new(store, &state.pre_committed_sectors_cleanup, quant) { - Ok(queue) => { - let ret = queue.amt.for_each(|epoch, expiration_bitfield| { - let epoch = epoch as ChainEpoch; - let quantized = quant.quantize_up(epoch); - acc.require( - quantized == epoch, - format!("pre-commit expiration {epoch} is not quantized"), - ); + if let Some(cleanup_cid) = &state.pre_committed_sectors_cleanup { + match BitFieldQueue::load(store, cleanup_cid, quant) { + Ok(queue) => { + let ret = queue.amt.for_each(|epoch, expiration_bitfield| { + let epoch = epoch as ChainEpoch; + let quantized = quant.quantize_up(epoch); + acc.require( + quantized == epoch, + format!("pre-commit expiration {epoch} is not quantized"), + ); - expiration_bitfield.iter().for_each(|sector_number| { - cleanup_epochs.insert(sector_number, epoch); + expiration_bitfield.iter().for_each(|sector_number| { + cleanup_epochs.insert(sector_number, epoch); + }); + Ok(()) }); - Ok(()) - }); - acc.require_no_error(ret, "error iterating pre-commit clean-up queue"); - } - Err(e) => { - acc.add(format!("error loading pre-commit clean-up queue: {e}")); + acc.require_no_error(ret, "error iterating pre-commit clean-up queue"); + } + Err(e) => { + acc.add(format!("error loading pre-commit clean-up queue: {e}")); + } } }; let mut precommit_total = TokenAmount::zero(); - let precommited_sectors = - PreCommitMap::load(store, &state.pre_committed_sectors, PRECOMMIT_CONFIG, "precommits"); - match precommited_sectors { - Ok(precommited_sectors) => { - let ret = precommited_sectors.for_each(|sector_number, precommit| { - acc.require( - allocated_sectors.contains(§or_number), - format!("pre-commited sector number has not been allocated {sector_number}"), - ); + if let Some(sectors_cid) = &state.pre_committed_sectors { + let precommited_sectors = + PreCommitMap::load(store, sectors_cid, PRECOMMIT_CONFIG, "precommits"); + match precommited_sectors { + Ok(precommited_sectors) => { + let ret = precommited_sectors.for_each(|sector_number, precommit| { + acc.require( + allocated_sectors.contains(§or_number), + format!( + "pre-commited sector number has not been allocated {sector_number}" + ), + ); - acc.require( - cleanup_epochs.contains_key(§or_number), - format!("no clean-up epoch for pre-commit at {}", precommit.pre_commit_epoch), - ); - precommit_total += &precommit.pre_commit_deposit; - Ok(()) - }); - acc.require_no_error(ret, "error iterating pre-commited sectors"); - } - Err(e) => { - acc.add(format!("error loading precommited_sectors: {e}")); + acc.require( + cleanup_epochs.contains_key(§or_number), + format!( + "no clean-up epoch for pre-commit at {}", + precommit.pre_commit_epoch + ), + ); + precommit_total += &precommit.pre_commit_deposit; + Ok(()) + }); + acc.require_no_error(ret, "error iterating pre-commited sectors"); + } + Err(e) => { + acc.add(format!("error loading precommited_sectors: {e}")); + } } }; @@ -561,7 +570,7 @@ impl PartitionStateSummary { // validate the early termination queue let early_termination_count = - match BitFieldQueue::new(store, &partition.early_terminated, NO_QUANTIZATION) { + match BitFieldQueue::load(store, &partition.early_terminated, NO_QUANTIZATION) { Ok(queue) => check_early_termination_queue(queue, &partition.terminated, acc), Err(err) => { acc.add(format!("error loading early termination queue: {err}")); @@ -959,7 +968,7 @@ pub fn check_deadline_state_invariants( // Validate partition expiration queue contains an entry for each partition and epoch with an expiration. // The queue may be a superset of the partitions that have expirations because we never remove from it. - match BitFieldQueue::new(store, &deadline.expirations_epochs, quant) { + match BitFieldQueue::load(store, &deadline.expirations_epochs, quant) { Ok(expiration_queue) => { for (epoch, expiring_idx) in partitions_with_expirations { match expiration_queue.amt.get(epoch as u64) { diff --git a/actors/miner/tests/miner_actor_test_bitfield_queue.rs b/actors/miner/tests/miner_actor_test_bitfield_queue.rs index 6604de5fd..8e3628563 100644 --- a/actors/miner/tests/miner_actor_test_bitfield_queue.rs +++ b/actors/miner/tests/miner_actor_test_bitfield_queue.rs @@ -229,7 +229,7 @@ fn empty_bitfield_queue_with_quantizing( ) -> BitFieldQueue { let cid = Amt::<(), _>::new_with_bit_width(&rt.store, bitwidth).flush().unwrap(); - BitFieldQueue::new(&*rt.store, &cid, quant).unwrap() + BitFieldQueue::load(&*rt.store, &cid, quant).unwrap() } fn empty_bitfield_queue(rt: &MockRuntime, bitwidth: u32) -> BitFieldQueue { diff --git a/actors/miner/tests/miner_actor_test_construction.rs b/actors/miner/tests/miner_actor_test_construction.rs index 332a54eca..160e70de1 100644 --- a/actors/miner/tests/miner_actor_test_construction.rs +++ b/actors/miner/tests/miner_actor_test_construction.rs @@ -101,7 +101,8 @@ fn simple_construction() { assert_eq!(TokenAmount::zero(), state.pre_commit_deposits); assert_eq!(TokenAmount::zero(), state.locked_funds); - assert_ne!(Cid::default(), state.pre_committed_sectors); + assert!(state.pre_committed_sectors.is_none()); + assert!(state.pre_committed_sectors_cleanup.is_none()); assert_ne!(Cid::default(), state.sectors); // according to original specs-actors test, this is set by running the code; magic... diff --git a/actors/miner/tests/miner_actor_test_partitions.rs b/actors/miner/tests/miner_actor_test_partitions.rs index 2d406a0e8..1703f5a37 100644 --- a/actors/miner/tests/miner_actor_test_partitions.rs +++ b/actors/miner/tests/miner_actor_test_partitions.rs @@ -642,7 +642,8 @@ mod miner_actor_test_partitions { ); // sectors should be added to early termination bitfield queue - let queue = BitFieldQueue::new(&rt.store, &partition.early_terminated, QUANT_SPEC).unwrap(); + let queue = + BitFieldQueue::load(&rt.store, &partition.early_terminated, QUANT_SPEC).unwrap(); BitFieldQueueExpectation::default().add(termination_epoch, &[1, 3, 5, 7]).equals(&queue); } @@ -794,7 +795,8 @@ mod miner_actor_test_partitions { ); // sectors should be added to early termination bitfield queue - let queue = BitFieldQueue::new(&rt.store, &partition.early_terminated, QUANT_SPEC).unwrap(); + let queue = + BitFieldQueue::load(&rt.store, &partition.early_terminated, QUANT_SPEC).unwrap(); // only early termination appears in bitfield queue BitFieldQueueExpectation::default().add(expire_epoch, &[4]).equals(&queue); @@ -944,7 +946,8 @@ mod miner_actor_test_partitions { assert!(has_more); // expect terminations to still contain 3 and 5 - let queue = BitFieldQueue::new(&rt.store, &partition.early_terminated, QUANT_SPEC).unwrap(); + let queue = + BitFieldQueue::load(&rt.store, &partition.early_terminated, QUANT_SPEC).unwrap(); // only early termination appears in bitfield queue BitFieldQueueExpectation::default().add(termination_epoch, &[3, 5]).equals(&queue); @@ -959,7 +962,8 @@ mod miner_actor_test_partitions { assert!(!has_more); // expect early terminations to be empty - let queue = BitFieldQueue::new(&rt.store, &partition.early_terminated, QUANT_SPEC).unwrap(); + let queue = + BitFieldQueue::load(&rt.store, &partition.early_terminated, QUANT_SPEC).unwrap(); BitFieldQueueExpectation::default().equals(&queue); } diff --git a/actors/miner/tests/state_harness.rs b/actors/miner/tests/state_harness.rs index dc9cb1f05..ea261eacb 100644 --- a/actors/miner/tests/state_harness.rs +++ b/actors/miner/tests/state_harness.rs @@ -87,9 +87,10 @@ impl StateHarness { policy: &Policy, ) -> BitFieldQueue<'db, MemoryBlockstore> { let quant = self.st.quant_spec_every_deadline(policy); - let queue = - BitFieldQueue::new(&self.store, &self.st.pre_committed_sectors_cleanup, quant).unwrap(); - queue + match &self.st.pre_committed_sectors_cleanup { + Some(cid) => BitFieldQueue::load(&self.store, cid, quant).unwrap(), + None => BitFieldQueue::new(&self.store, quant), + } } #[allow(dead_code)] diff --git a/actors/miner/tests/util.rs b/actors/miner/tests/util.rs index fdbceb349..c7e52f9ca 100644 --- a/actors/miner/tests/util.rs +++ b/actors/miner/tests/util.rs @@ -2297,20 +2297,22 @@ impl ActorHarness { rt: &MockRuntime, st: &State, ) -> HashMap> { - let quant = st.quant_spec_every_deadline(&rt.policy); - let queue = BitFieldQueue::new(&rt.store, &st.pre_committed_sectors_cleanup, quant) - .map_err(|e| e.downcast_wrap("failed to load pre-commit clean up queue")) - .unwrap(); let mut expirations: HashMap> = HashMap::new(); - queue - .amt - .for_each(|epoch, bf| { - let expanded: Vec = - bf.bounded_iter(rt.policy.addressed_sectors_max).unwrap().collect(); - expirations.insert(epoch.try_into().unwrap(), expanded); - Ok(()) - }) - .unwrap(); + if let Some(sectors_cid) = &st.pre_committed_sectors_cleanup { + let quant = st.quant_spec_every_deadline(&rt.policy); + let queue = BitFieldQueue::load(&rt.store, sectors_cid, quant) + .map_err(|e| e.downcast_wrap("failed to load pre-commit clean up queue")) + .unwrap(); + queue + .amt + .for_each(|epoch, bf| { + let expanded: Vec = + bf.bounded_iter(rt.policy.addressed_sectors_max).unwrap().collect(); + expirations.insert(epoch.try_into().unwrap(), expanded); + Ok(()) + }) + .unwrap(); + } expirations } @@ -2419,7 +2421,7 @@ impl ActorHarness { deadline: &Deadline, ) -> HashMap> { let queue = - BitFieldQueue::new(&rt.store, &deadline.expirations_epochs, NO_QUANTIZATION).unwrap(); + BitFieldQueue::load(&rt.store, &deadline.expirations_epochs, NO_QUANTIZATION).unwrap(); let mut expirations = HashMap::new(); queue .amt