From e53c78a1b795be9daf1d7836aa283a3db27823af Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Fri, 19 Feb 2021 02:14:00 -0500 Subject: [PATCH 01/35] update deadline_state --- vm/actor/src/builtin/miner/bitfield_queue.rs | 7 +- vm/actor/src/builtin/miner/deadline_state.rs | 333 ++++++++++++++++-- vm/actor/src/builtin/miner/partition_state.rs | 2 +- 3 files changed, 302 insertions(+), 40 deletions(-) diff --git a/vm/actor/src/builtin/miner/bitfield_queue.rs b/vm/actor/src/builtin/miner/bitfield_queue.rs index 676ea9eb3f29..d256f90b010c 100644 --- a/vm/actor/src/builtin/miner/bitfield_queue.rs +++ b/vm/actor/src/builtin/miner/bitfield_queue.rs @@ -101,14 +101,17 @@ impl<'db, BS: BlockStore> BitFieldQueue<'db, BS> { // Pre-quantize to reduce the number of updates. let mut quantized_values = HashMap::>::with_capacity(values.len()); - let mut updated_epochs = Vec::::with_capacity(values.len()); for (&raw_epoch, entries) in values { let epoch = self.quant.quantize_up(raw_epoch); - updated_epochs.push(epoch); quantized_values.entry(epoch).or_default().extend(entries); } + // Update each epoch in order to be deterministic. + let mut updated_epochs = Vec::with_capacity(quantized_values.len()); + for epoch in quantized_values.keys() { + updated_epochs.push(*epoch); + } updated_epochs.sort_unstable(); for epoch in updated_epochs { diff --git a/vm/actor/src/builtin/miner/deadline_state.rs b/vm/actor/src/builtin/miner/deadline_state.rs index 8df7caf1aecb..6a6437730b6f 100644 --- a/vm/actor/src/builtin/miner/deadline_state.rs +++ b/vm/actor/src/builtin/miner/deadline_state.rs @@ -10,12 +10,20 @@ use bitfield::BitField; use cid::{Cid, Code::Blake2b256}; use clock::ChainEpoch; use encoding::tuple::*; -use fil_types::{deadlines::QuantSpec, SectorSize}; +use fil_types::{deadlines::QuantSpec, PoStProof, SectorSize}; use ipld_amt::Amt; use ipld_blockstore::BlockStore; use num_traits::{Signed, Zero}; use std::{cmp, collections::HashMap, collections::HashSet, error::Error as StdError}; +// Bitwidth of AMTs determined empirically from mutation patterns and projections of mainnet data. +const DEADLINE_PARTITIONS_AMT_BITWIDTH: usize = 3; // Usually a small array +const DEADLINE_EXPIRATIONS_AMT_BITWIDTH: usize = 5; + +// Given that 4 partitions can be proven in one post, this AMT's height will +// only exceed the partition AMT's height at ~0.75EiB of storage. +const DEADLINE_OPTIMISTIC_POST_SUBMISSIONS_AMT_BITWIDTH: usize = 2; + /// Deadlines contains Deadline objects, describing the sectors due at the given /// deadline and their state (faulty, terminated, recovering, etc.). #[derive(Serialize_tuple, Deserialize_tuple)] @@ -107,8 +115,13 @@ pub struct Deadline { /// recovered, and this queue will not be updated at that time. pub expirations_epochs: Cid, // AMT[ChainEpoch]BitField - /// Partitions numbers with PoSt submissions since the proving period started. - pub post_submissions: BitField, + // Partitions that have been proved by window PoSts so far during the + // current challenge window. + // NOTE: This bitfield includes both partitions whose proofs + // were optimistically accepted and stored in + // OptimisticPoStSubmissions, and those whose proofs were + // verified on-chain. + pub partitions_posted: BitField, /// Partitions with sectors that terminated early. pub early_terminations: BitField, @@ -121,27 +134,103 @@ pub struct Deadline { /// Memoized sum of faulty power in partitions. pub faulty_power: PowerPair, + + // AMT of optimistically accepted WindowPoSt proofs, submitted during + // the current challenge window. At the end of the challenge window, + // this AMT will be moved to PoStSubmissionsSnapshot. WindowPoSt proofs + // verified on-chain do not appear in this AMT + pub optimistic_post_submissions: Cid, + + // Snapshot of partition state at the end of the previous challenge + // window for this deadline. + partitions_snapshot: Cid, + + // Snapshot of the proofs submitted by the end of the previous challenge + // window for this deadline. + // + // These proofs may be disputed via DisputeWindowedPoSt. Successfully + // disputed window PoSts are removed from the snapshot. + optimistic_post_submissions_snapshot: Cid, +} +#[derive(Serialize_tuple, Deserialize_tuple)] +pub struct WindowedPoSt { + // Partitions proved by this WindowedPoSt. + partitions: BitField, + + // Array of proofs, one per distinct registered proof type present in + // the sectors being proven. In the usual case of a single proof type, + // this array will always have a single element (independent of number + // of partitions). + proofs: Vec, +} + +#[derive(Serialize_tuple, Deserialize_tuple)] +pub struct DisputeInfo { + all_sector_nos: BitField, + ignored_sector_nos: BitField, + disputed_sectors: PartitionSectorMap, + disputed_power: PowerPair, } impl Deadline { - pub fn new(empty_array_cid: Cid) -> Self { - Self { - partitions: empty_array_cid, - expirations_epochs: empty_array_cid, - post_submissions: BitField::new(), + pub fn new(store: &BS) -> Result> { + let empty_partitions_array = + Amt::<(), BS>::new_with_bit_width(store, DEADLINE_PARTITIONS_AMT_BITWIDTH) + .flush() + .map_err(|e| format!("Failed to create empty states array: {}", e))?; + let empty_deadline_expiration_array = + Amt::<(), BS>::new_with_bit_width(store, DEADLINE_EXPIRATIONS_AMT_BITWIDTH) + .flush() + .map_err(|e| format!("Failed to create empty states array: {}", e))?; + let empty_post_submissions_array = Amt::<(), BS>::new_with_bit_width( + store, + DEADLINE_OPTIMISTIC_POST_SUBMISSIONS_AMT_BITWIDTH, + ) + .flush() + .map_err(|e| format!("Failed to create empty states array: {}", e))?; + Ok(Self { + partitions: empty_partitions_array, + expirations_epochs: empty_deadline_expiration_array, early_terminations: BitField::new(), live_sectors: 0, total_sectors: 0, faulty_power: PowerPair::zero(), - } + partitions_posted: BitField::new(), + optimistic_post_submissions: empty_post_submissions_array, + partitions_snapshot: empty_partitions_array, + optimistic_post_submissions_snapshot: empty_post_submissions_array, + }) } pub fn partitions_amt<'db, BS: BlockStore>( &self, store: &'db BS, - ) -> Result, ActorError> { - Amt::load(&self.partitions, store) - .map_err(|e| e.downcast_default(ExitCode::ErrIllegalState, "failed to load partitions")) + ) -> Result, Box> { + Ok(Amt::load(&self.partitions, store)?) + } + + pub fn optimistic_proofs_amt<'db, BS: BlockStore>( + &self, + store: &'db BS, + ) -> Result, Box> { + Ok(Amt::load(&self.optimistic_post_submissions, store)?) + } + + pub fn partitions_snapshot_amt<'db, BS: BlockStore>( + &self, + store: &'db BS, + ) -> Result, Box> { + Ok(Amt::load(&self.partitions_snapshot, store)?) + } + + pub fn optimistic_proofs_snapshot_amt<'db, BS: BlockStore>( + &self, + store: &'db BS, + ) -> Result, Box> { + Ok(Amt::load( + &self.optimistic_post_submissions_snapshot, + store, + )?) } pub fn load_partition( @@ -164,6 +253,26 @@ impl Deadline { Ok(partition.clone()) } + pub fn load_partition_snapshot( + &self, + store: &BS, + partition_idx: usize, + ) -> Result> { + let partitions = Amt::::load(&self.partitions_snapshot, store)?; + + let partition = partitions + .get(partition_idx) + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + format!("failed to lookup partition snapshot {}", partition_idx), + ) + })? + .ok_or_else(|| actor_error!(ErrNotFound, "no partition snapshot {}", partition_idx))?; + + Ok(partition.clone()) + } + /// Adds some partition numbers to the set expiring at an epoch. pub fn add_expiration_partitions( &mut self, @@ -284,13 +393,13 @@ impl Deadline { sector_size: SectorSize, quant: QuantSpec, ) -> Result> { + let mut total_power = PowerPair::zero(); if sectors.is_empty() { - return Ok(PowerPair::zero()); + return Ok(total_power); } // First update partitions, consuming the sectors let mut partition_deadline_updates = HashMap::>::new(); - let mut activated_power = PowerPair::zero(); self.live_sectors += sectors.len() as u64; self.total_sectors += sectors.len() as u64; @@ -326,9 +435,9 @@ impl Deadline { sectors = §ors[size..]; // Add sectors to partition. - let partition_activated_power = + let partition_power = partition.add_sectors(store, proven, partition_new_sectors, sector_size, quant)?; - activated_power += &partition_activated_power; + total_power += &partition_power; // Save partition back. partitions.set(partition_idx, partition)?; @@ -356,7 +465,7 @@ impl Deadline { .map_err(|e| e.downcast_wrap("failed to add expirations for new deadlines"))?; self.expirations_epochs = deadline_expirations.amt.flush()?; - Ok(activated_power) + Ok(total_power) } pub fn pop_early_terminations( @@ -545,7 +654,8 @@ impl Deadline { return Err("cannot remove partitions from deadline with early terminations".into()); } - let mut new_partitions = Amt::::new(store); + let mut new_partitions = + Amt::::new_with_bit_width(store, DEADLINE_PARTITIONS_AMT_BITWIDTH); let mut all_dead_sectors = Vec::::with_capacity(to_remove_set.len()); let mut all_live_sectors = Vec::::with_capacity(to_remove_set.len()); let mut removed_power = PowerPair::zero(); @@ -624,7 +734,7 @@ impl Deadline { Ok((live, dead, removed_power)) } - pub fn declare_faults( + pub fn record_faults( &mut self, store: &BS, sectors: &Sectors<'_, BS>, @@ -653,7 +763,7 @@ impl Deadline { .clone(); let (new_faults, partition_power_delta, partition_new_faulty_power) = partition - .declare_faults( + .record_faults( store, sectors, sector_numbers, @@ -762,7 +872,7 @@ impl Deadline { let mut power_delta = PowerPair::zero(); let mut penalized_power = PowerPair::zero(); for partition_idx in 0..partitions.count() { - let proven = self.post_submissions.get(partition_idx); + let proven = self.partitions_posted.get(partition_idx); if proven { continue; @@ -844,7 +954,20 @@ impl Deadline { })?; // Reset PoSt submissions. - self.post_submissions = BitField::new(); + self.partitions_posted = BitField::new(); + self.partitions_snapshot = self.partitions; + self.optimistic_post_submissions_snapshot = self.optimistic_post_submissions; + self.optimistic_post_submissions = Amt::<(), BS>::new_with_bit_width( + store, + DEADLINE_OPTIMISTIC_POST_SUBMISSIONS_AMT_BITWIDTH, + ) + .flush() + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to clear pending proofs array", + ) + })?; Ok((power_delta, penalized_power)) } pub fn for_each( @@ -867,6 +990,81 @@ impl Deadline { Ok(()) } + + pub fn load_partitions_for_dispute( + &self, + store: &BS, + partitions: BitField, + ) -> Result> { + let partitions_snapshot = self + .partitions_snapshot_amt(store) + .map_err(|e| e.downcast_wrap("failed to load partitions {}"))?; + + let mut all_sectors = Vec::new(); + let mut all_ignored = Vec::new(); + let mut disputed_sectors = PartitionSectorMap::default(); + let mut disputed_power = PowerPair::zero(); + for part_idx in partitions.iter() { + let partition_snapshot = partitions_snapshot + .get(part_idx)? + .ok_or_else(|| format!("failed to find partition {}", part_idx))?; + + // Record sectors for proof verification + all_sectors.push(partition_snapshot.sectors); + all_ignored.push(partition_snapshot.faults); + all_ignored.push(partition_snapshot.terminated); + all_ignored.push(partition_snapshot.unproven); + + // Record active sectors for marking faults. + let active = partition_snapshot.active_sectors(); + disputed_sectors.add(part_idx, active.into())?; + + // Record disputed power for penalties. + // + // NOTE: This also includes power that was + // activated at the end of the last challenge + // window, and power from sectors that have since + // expired. + disputed_power += &partition_snapshot.active_power(); + } + + let all_sector_nos = BitField::union(&all_sectors); + let all_ignored_nos = BitField::union(&all_ignored); + + Ok(DisputeInfo { + all_sector_nos: all_sector_nos, + disputed_sectors: disputed_sectors, + disputed_power: disputed_power, + ignored_sector_nos: all_ignored_nos, + }) + } + + pub fn is_live(&self) -> bool { + if self.live_sectors > 0 { + return true; + } + + let has_no_proofs = self.partitions_posted.is_empty(); + if !has_no_proofs { + // _This_ case should be impossible, but there's no good way to log from here. We + // might as well just process the deadline end and move on. + return true; + } + + // If the partitions have changed, we may have work to do. We should at least update the + // partitions snapshot one last time. + if self.partitions != self.partitions_snapshot { + return true; + } + + // If we don't have any proofs, and the proofs snapshot isn't the same as the current proofs + // snapshot (which should be empty), we should update the deadline one last time to empty + // the proofs snapshot. + if self.optimistic_post_submissions != self.optimistic_post_submissions_snapshot { + return true; + } + return false; + } } pub struct PoStResult { @@ -879,13 +1077,8 @@ pub struct PoStResult { pub sectors: BitField, /// A subset of `sectors` that should be ignored. pub ignored_sectors: BitField, -} - -impl PoStResult { - /// The power from this PoSt that should be penalized. - pub fn penalty_power(&self) -> PowerPair { - &self.new_faulty_power + &self.retracted_recovery_power - } + // Bitfield of partitions that were proven. + pub partitions: BitField, } impl Deadline { @@ -908,6 +1101,26 @@ impl Deadline { fault_expiration: ChainEpoch, post_partitions: &mut [PoStPartition], ) -> Result> { + let partition_indexes = BitField::new(); + for p in post_partitions.iter() { + partition_indexes.set(p.index); + } + + let num_partitions = partition_indexes.len(); + if num_partitions != post_partitions.len() { + return Err(Box::new(actor_error!( + ErrIllegalArgument, + "duplicate partitions proven" + ))); + } + + // First check to see if we're proving any already proven partitions. + // This is faster than checking one by one. + let already_proven = &self.partitions_posted & &partition_indexes; + if already_proven.len() == 0 { + return Err(format!("parition already proven: {:?}", already_proven).into()); + } + let mut partitions = self.partitions_amt(store)?; let mut all_sectors = Vec::::with_capacity(post_partitions.len()); @@ -920,13 +1133,6 @@ impl Deadline { // Accumulate sectors info for proof verification. for post in post_partitions { - let already_proven = self.post_submissions.get(post.index); - - if already_proven { - // Skip partitions already proven for this deadline. - continue; - } - let mut partition = partitions .get(post.index) .map_err(|e| e.downcast_wrap(format!("failed to load partition {}", post.index)))? @@ -991,7 +1197,7 @@ impl Deadline { power_delta += &recovered_power; // Record the post. - self.post_submissions.set(post.index as usize); + self.partitions_posted.set(post.index as usize); } self.add_expiration_partitions(store, fault_expiration, &rescheduled_partitions, quant) @@ -1021,9 +1227,62 @@ impl Deadline { sectors: all_sector_numbers, power_delta, ignored_sectors: all_ignored_sector_numbers, + partitions: partition_indexes, }) } + // RecordPoStProofs records a set of optimistically accepted PoSt proofs + // (usually one), associating them with the given partitions. + pub fn record_post_proofs( + &mut self, + store: &BS, + partitions: BitField, + proofs: Vec, + ) -> Result<(), Box> { + let proof_arr = self + .optimistic_proofs_amt(store) + .map_err(|e| e.downcast_wrap("failed to load post proofs"))?; + proof_arr + .set( + proof_arr.len(), + WindowedPoSt { + partitions: partitions, + proofs: proofs, + }, + ) + .map_err(|e| e.downcast_wrap("failed to store proof"))?; + let root = proof_arr + .flush() + .map_err(|e| e.downcast_wrap("failed to save proofs"))?; + self.optimistic_post_submissions = root; + Ok(()) + } + + // TakePoStProofs removes and returns a PoSt proof by index, along with the + // associated partitions. This method takes the PoSt from the PoSt submissions + // snapshot. + pub fn take_post_proofs( + &mut self, + store: &BS, + idx: u64, + ) -> Result<(BitField, Vec), Box> { + let proof_arr = self + .optimistic_proofs_snapshot_amt(store) + .map_err(|e| e.downcast_wrap("failed to load post proofs snapshot amt"))?; + // Extract and remove the proof from the proofs array, leaving a hole. + // This will not affect concurrent attempts to refute other proofs. + let post = proof_arr + .delete(idx as usize) + .map_err(|e| e.downcast_wrap(format!("failed to retrieve proof {}", idx)))? + .ok_or_else(|| Box::new(actor_error!(ErrIllegalArgument, "proof {} not found", idx)))?; + + let root = proof_arr + .flush() + .map_err(|e| e.downcast_wrap("failed to save proofs"))?; + self.optimistic_post_submissions_snapshot = root; + Ok((post.partitions, post.proofs)) + } + /// RescheduleSectorExpirations reschedules the expirations of the given sectors /// to the target epoch, skipping any sectors it can't find. /// diff --git a/vm/actor/src/builtin/miner/partition_state.rs b/vm/actor/src/builtin/miner/partition_state.rs index 1d7729b236cb..8fc70ae5c46b 100644 --- a/vm/actor/src/builtin/miner/partition_state.rs +++ b/vm/actor/src/builtin/miner/partition_state.rs @@ -200,7 +200,7 @@ impl Partition { /// - The sectors' expirations are rescheduled to the fault expiration epoch, as "early" (if not expiring earlier). /// /// Returns the power of the now-faulty sectors. - pub fn declare_faults( + pub fn record_faults( &mut self, store: &BS, sectors: &Sectors<'_, BS>, From efba4ea1e2aa645f8467f73e5c3248c079f1cb74 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Mon, 22 Feb 2021 13:00:54 -0500 Subject: [PATCH 02/35] deadlines --- vm/actor/src/builtin/miner/deadlines.rs | 40 +++++++++++++++++++++++++ vm/actor/src/builtin/miner/policy.rs | 3 ++ 2 files changed, 43 insertions(+) diff --git a/vm/actor/src/builtin/miner/deadlines.rs b/vm/actor/src/builtin/miner/deadlines.rs index cfb6728cdec0..2c47e6945098 100644 --- a/vm/actor/src/builtin/miner/deadlines.rs +++ b/vm/actor/src/builtin/miner/deadlines.rs @@ -84,3 +84,43 @@ pub fn quant_spec_for_deadline(di: &DeadlineInfo) -> QuantSpec { offset: di.last(), } } + +// Returns true if optimistically accepted posts submitted to the given deadline +// may be disputed. Specifically, this ensures that: +// +// 1. Optimistic PoSts may not be disputed while the challenge window is open. +// 2. Optimistic PoSts may not be disputed after the miner could have compacted the deadline. +pub fn deadline_available_for_optimistic_post_dispute( + proving_period_start: ChainEpoch, + deadline_idx: usize, + current_epoch: ChainEpoch, +) -> bool { + if proving_period_start > current_epoch { + return false; + } + let dl_info = + new_deadline_info(proving_period_start, deadline_idx, current_epoch).next_not_elapsed(); + + return !dl_info.is_open() + && current_epoch < (dl_info.close - WPOST_PROVING_PERIOD) + WPOST_DISPUTE_WINDOW; +} + +// Returns true if the given deadline may compacted in the current epoch. +// Deadlines may not be compacted when: +// +// 1. The deadline is currently being challenged. +// 2. The deadline is to be challenged next. +// 3. Optimistically accepted posts from the deadline's last challenge window +// can currently be disputed. +pub fn deadline_available_for_compaction( + proving_period_start: ChainEpoch, + deadline_idx: usize, + current_epoch: ChainEpoch, +) -> bool { + return deadline_is_mutable(proving_period_start, deadline_idx, current_epoch) + && !deadline_available_for_optimistic_post_dispute( + proving_period_start, + deadline_idx, + current_epoch, + ); +} diff --git a/vm/actor/src/builtin/miner/policy.rs b/vm/actor/src/builtin/miner/policy.rs index 384af472af20..9a8a2eb5812d 100644 --- a/vm/actor/src/builtin/miner/policy.rs +++ b/vm/actor/src/builtin/miner/policy.rs @@ -19,6 +19,9 @@ pub const WPOST_CHALLENGE_WINDOW: ChainEpoch = 30 * 60 / EPOCH_DURATION_SECONDS; pub const WPOST_PERIOD_DEADLINES: u64 = 48; /// The maximum distance back that a valid Window PoSt must commit to the current chain. pub const WPOST_MAX_CHAIN_COMMIT_AGE: ChainEpoch = WPOST_CHALLENGE_WINDOW; +// WPoStDisputeWindow is the period after a challenge window ends during which +// PoSts submitted during that period may be disputed. +pub const WPOST_DISPUTE_WINDOW: ChainEpoch = 2 * CHAIN_FINALITY; /// The maximum number of sectors that a miner can have simultaneously active. /// This also bounds the number of faults that can be declared, etc. From 6662c87b1d565464189bbe3b7f28beb90cc022ea Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Mon, 22 Feb 2021 23:42:02 -0500 Subject: [PATCH 03/35] miner state update --- vm/actor/src/builtin/miner/mod.rs | 85 +++--------- vm/actor/src/builtin/miner/state.rs | 204 +++++++++++++++++++--------- 2 files changed, 160 insertions(+), 129 deletions(-) diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index ac3141b1f7ef..863f12cc018c 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -148,59 +148,6 @@ impl Actor { .map(|address| resolve_control_address(rt, address)) .collect::>()?; - let empty_map = make_empty_map::<_, ()>(rt.store(), HAMT_BIT_WIDTH) - .flush() - .map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - "failed to construct initial state", - ) - })?; - - let empty_array = Amt::::new(rt.store()).flush().map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - "failed to construct initial state", - ) - })?; - - let empty_bitfield_cid = rt.store().put(&BitField::new(), Blake2b256).map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - "failed to construct illegal state", - ) - })?; - - let empty_deadline_cid = rt - .store() - .put(&Deadline::new(empty_array), Blake2b256) - .map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - "failed to construct illegal state", - ) - })?; - - let empty_deadlines_cid = rt - .store() - .put(&Deadlines::new(empty_deadline_cid), Blake2b256) - .map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - "failed to construct illegal state", - ) - })?; - - let empty_vesting_funds_cid = - rt.store() - .put(&VestingFunds::new(), Blake2b256) - .map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - "failed to construct illegal state", - ) - })?; - let current_epoch = rt.curr_epoch(); let blake2b = |b: &[u8]| rt.hash_blake2b(b); let offset = assign_proving_period_offset(*rt.message().receiver(), current_epoch, blake2b) @@ -212,8 +159,23 @@ impl Actor { })?; let period_start = current_proving_period_start(current_epoch, offset); + if period_start > current_epoch { + return Err(actor_error!( + ErrIllegalState, + "computed proving period start {} after current epoch {}", + period_start, + current_epoch + )); + } + let deadline_idx = current_deadline_index(current_epoch, period_start); - assert!(deadline_idx < WPOST_PERIOD_DEADLINES as usize); + if deadline_idx >= WPOST_PERIOD_DEADLINES as usize { + return Err(actor_error!( + ErrIllegalState, + "computed proving deadline index {} invalid", + deadline_idx + )); + } let info = MinerInfo::new( owner, @@ -225,7 +187,7 @@ impl Actor { ) .map_err(|e| { actor_error!( - ErrIllegalArgument, + ErrIllegalState, "failed to construct initial miner info: {}", e ) @@ -237,16 +199,9 @@ impl Actor { ) })?; - let st = State::new( - info_cid, - period_start, - deadline_idx, - empty_bitfield_cid, - empty_array, - empty_map, - empty_deadlines_cid, - empty_vesting_funds_cid, - ); + let st = State::new(rt.store(), info_cid, period_start, deadline_idx).map_err(|e| { + e.downcast_default(ExitCode::ErrIllegalState, "failed to construct state") + })?; rt.create(&st)?; // Register first cron callback for epoch before the next deadline starts. diff --git a/vm/actor/src/builtin/miner/state.rs b/vm/actor/src/builtin/miner/state.rs index bd663472350a..c6e84ff6299a 100644 --- a/vm/actor/src/builtin/miner/state.rs +++ b/vm/actor/src/builtin/miner/state.rs @@ -6,7 +6,9 @@ use super::{ quant_spec_for_deadline, types::*, BitFieldQueue, Deadline, DeadlineSectorMap, Deadlines, PowerPair, Sectors, TerminationResult, VestingFunds, }; -use crate::{make_map_with_root, u64_key, ActorDowncast}; +use crate::{ + make_empty_map, make_map_with_root, make_map_with_root_and_bitwidth, u64_key, ActorDowncast, +}; use address::Address; use bitfield::BitField; use cid::{Cid, Code::Blake2b256}; @@ -14,9 +16,9 @@ use clock::{ChainEpoch, EPOCH_UNDEFINED}; use encoding::{serde_bytes, tuple::*, BytesDe, Cbor}; use fil_types::{ deadlines::{DeadlineInfo, QuantSpec}, - RegisteredPoStProof, SectorNumber, SectorSize, MAX_SECTOR_NUMBER, + RegisteredPoStProof, SectorNumber, SectorSize, HAMT_BIT_WIDTH, MAX_SECTOR_NUMBER, }; -use ipld_amt::Error as AmtError; +use ipld_amt::{Amt, Error as AmtError}; use ipld_blockstore::BlockStore; use ipld_hamt::Error as HamtError; use num_bigint::bigint_ser; @@ -25,6 +27,9 @@ use std::ops::Neg; use std::{cmp, error::Error as StdError}; use vm::{actor_error, ActorError, ExitCode, TokenAmount}; +const PRECOMMIT_EXPIRY_AMT_BITWIDTH: usize = 6; +const SECTORS_AMT_BITWIDTH: usize = 5; + /// Balance of Miner Actor should be greater than or equal to /// the sum of PreCommitDeposits and LockedFunds. /// It is possible for balance to fall below the sum of PCD, LF and @@ -99,17 +104,68 @@ impl Cbor for State {} impl State { #[allow(clippy::too_many_arguments)] - pub fn new( + pub fn new( + store: &BS, info_cid: Cid, period_start: ChainEpoch, - current_deadline: usize, - empty_bitfield_cid: Cid, - empty_array_cid: Cid, - empty_map_cid: Cid, - empty_deadlines_cid: Cid, - empty_vesting_funds_cid: Cid, - ) -> Self { - Self { + deadline_idx: usize, + ) -> Result> { + let empty_precommit_map = make_empty_map::<_, ()>(store, HAMT_BIT_WIDTH) + .flush() + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to construct empty precommit map", + ) + })?; + let empty_precommits_expiry_array = + Amt::<_, BS>::new_with_bit_width(store, PRECOMMIT_EXPIRY_AMT_BITWIDTH) + .flush() + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to construct empty precommits array", + ) + })?; + let empty_sectors_array = Amt::<_, BS>::new_with_bit_width(store, SECTORS_AMT_BITWIDTH) + .flush() + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to construct sectors array", + ) + })?; + let empty_bitfield = store.put(&BitField::new(), Blake2b256).map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to construct empty bitfield", + ) + })?; + let deadline = Deadline::new(store)?; + let empty_deadline = store.put(&deadline, Blake2b256).map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to construct illegal state", + ) + })?; + + let empty_deadlines = store + .put(&Deadlines::new(empty_deadline), Blake2b256) + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to construct illegal state", + ) + })?; + + let empty_vesting_funds_cid = store.put(&VestingFunds::new(), Blake2b256).map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to construct illegal state", + ) + })?; + + Ok(Self { info: info_cid, pre_commit_deposits: TokenAmount::default(), @@ -120,15 +176,15 @@ impl State { initial_pledge: TokenAmount::default(), fee_debt: TokenAmount::default(), - pre_committed_sectors: empty_map_cid, - pre_committed_sectors_expiry: empty_array_cid, - allocated_sectors: empty_bitfield_cid, - sectors: empty_array_cid, + pre_committed_sectors: empty_precommit_map, + pre_committed_sectors_expiry: empty_precommits_expiry_array, + allocated_sectors: empty_bitfield, + sectors: empty_sectors_array, proving_period_start: period_start, - current_deadline, - deadlines: empty_deadlines_cid, + current_deadline: deadline_idx, + deadlines: empty_deadlines, early_terminations: BitField::new(), - } + }) } pub fn get_info(&self, store: &BS) -> Result> { @@ -250,14 +306,25 @@ impl State { Ok(()) } + /// Stores a pre-committed sector info, failing if the sector number is already present. pub fn put_precommitted_sector( &mut self, store: &BS, info: SectorPreCommitOnChainInfo, - ) -> Result<(), HamtError> { - let mut precommitted = make_map_with_root(&self.pre_committed_sectors, store)?; - precommitted.set(u64_key(info.info.sector_number), info)?; - + ) -> Result<(), Box> { + let mut precommitted = + make_map_with_root_and_bitwidth(&self.pre_committed_sectors, store, HAMT_BIT_WIDTH)?; + let modified = precommitted + .set_if_absent(u64_key(info.info.sector_number), info) + .map_err(|e| { + e.downcast_wrap(format!("failed to store pre-commitment for {:?}", info)) + })?; + if !modified { + // TODO: FIX + return Err(Box::new( + format!("sector {} already pre-commited", info.info.sector_number).into(), + )); + } self.pre_committed_sectors = precommitted.flush()?; Ok(()) } @@ -267,7 +334,8 @@ impl State { store: &BS, sector_num: SectorNumber, ) -> Result, HamtError> { - let precommitted = make_map_with_root(&self.pre_committed_sectors, store)?; + let precommitted = + make_map_with_root_and_bitwidth(&self.pre_committed_sectors, store, HAMT_BIT_WIDTH)?; Ok(precommitted.get(&u64_key(sector_num))?.cloned()) } @@ -277,9 +345,10 @@ impl State { store: &BS, sector_numbers: &[SectorNumber], ) -> Result, Box> { - let precommitted = make_map_with_root::<_, SectorPreCommitOnChainInfo>( + let precommitted = make_map_with_root_and_bitwidth::<_, SectorPreCommitOnChainInfo>( &self.pre_committed_sectors, store, + HAMT_BIT_WIDTH, )?; let mut result = Vec::with_capacity(sector_numbers.len()); @@ -305,9 +374,10 @@ impl State { store: &BS, sector_nums: &[SectorNumber], ) -> Result<(), HamtError> { - let mut precommitted = make_map_with_root::<_, SectorPreCommitOnChainInfo>( + let mut precommitted = make_map_with_root_and_bitwidth::<_, SectorPreCommitOnChainInfo>( &self.pre_committed_sectors, store, + HAMT_BIT_WIDTH, )?; for §or_num in sector_nums { @@ -447,7 +517,7 @@ impl State { mut sectors: Vec, partition_size: u64, sector_size: SectorSize, - ) -> Result> { + ) -> Result<(), Box> { let mut deadlines = self.load_deadlines(store)?; // Sort sectors by number to get better runs in partition bitfields. @@ -465,7 +535,6 @@ impl State { Ok(()) })?; - let mut activated_power = PowerPair::zero(); let deadline_to_sectors = assign_deadlines( MAX_PARTITIONS_PER_DEADLINE, partition_size, @@ -481,23 +550,23 @@ impl State { let quant = self.quant_spec_for_deadline(deadline_idx); let deadline = deadline_vec[deadline_idx].as_mut().unwrap(); - let deadline_activated_power = deadline.add_sectors( + // The power returned from AddSectors is ignored because it's not activated (proven) yet. + let mut proven = false; + deadline.add_sectors( store, partition_size, - false, - &deadline_sectors, + proven, + deadline_sectors, sector_size, quant, )?; - activated_power += &deadline_activated_power; - deadlines.update_deadline(store, deadline_idx, deadline)?; } self.save_deadlines(store, deadlines)?; - Ok(activated_power) + Ok(()) } /// Pops up to `max_sectors` early terminated sectors from all deadlines. @@ -666,27 +735,26 @@ impl State { // Funds and vesting // - pub fn add_pre_commit_deposit(&mut self, amount: &TokenAmount) { + pub fn add_pre_commit_deposit(&mut self, amount: &TokenAmount) -> Result<(), String> { let new_total = &self.pre_commit_deposits + amount; - assert!( - !new_total.is_negative(), - "negative pre-commit deposit {} after adding {} to prior {}", - new_total, - amount, - self.pre_commit_deposits - ); + if new_total.is_negative() { + return Err(format!( + "negative pre-commit deposit {} after adding {} to prior {}", + new_total, amount, self.pre_commit_deposits + )); + } self.pre_commit_deposits = new_total; + Ok(()) } - pub fn add_initial_pledge(&mut self, amount: &TokenAmount) { + pub fn add_initial_pledge(&mut self, amount: &TokenAmount) -> Result<(), String> { let new_total = &self.initial_pledge + amount; - assert!( - !new_total.is_negative(), - "negative initial pledge requirement {} after adding {} to prior {}", - new_total, - amount, - self.initial_pledge - ); + if new_total.is_negative() { + return Err(format!( + "negative initial pledge requirement {} after adding {} to prior {}", + new_total, amount, self.initial_pledge + )); + } self.initial_pledge = new_total; } @@ -707,19 +775,21 @@ impl State { vesting_sum: &TokenAmount, spec: &VestSpec, ) -> Result> { - assert!( - !vesting_sum.is_negative(), - "negative vesting sum {}", - vesting_sum - ); + if vesting_sum.is_negative() { + return Err(Box::new(format!("negative vesting sum {}", vesting_sum))); + } let mut vesting_funds = self.load_vesting_funds(store)?; // unlock vested funds first let amount_unlocked = vesting_funds.unlock_vested_funds(current_epoch); self.locked_funds -= &amount_unlocked; - assert!(!self.locked_funds.is_negative()); - + if self.locked_funds.is_negative() { + return Err(Box::new(format!( + "negative locked funds {} after unlocking {}", + self.locked_funds, amount_unlocked + ))); + } // add locked funds now vesting_funds.add_locked_funds(current_epoch, vesting_sum, self.proving_period_start, spec); self.locked_funds += vesting_sum; @@ -752,10 +822,11 @@ impl State { let from_vesting = self.unlock_unvested_funds(store, current_epoch, &fee_debt)?; // * It may be possible the go implementation catches a potential panic here - assert!( - from_vesting <= self.fee_debt, - "should never unlock more than the debt we need to repay" - ); + if from_vesting > self.fee_debt { + return Err(Box::new( + "should never unlock more than the debt we need to repay", + )); + } self.fee_debt -= &from_vesting; let from_balance = cmp::min(&unlocked_balance, &self.fee_debt).clone(); @@ -801,7 +872,12 @@ impl State { let mut vesting_funds = self.load_vesting_funds(store)?; let amount_unlocked = vesting_funds.unlock_unvested_funds(current_epoch, target); self.locked_funds -= &amount_unlocked; - assert!(!self.locked_funds.is_negative()); + if self.locked_funds.is_negative() { + return Err(Box::new(format!( + "negative locked funds {} after unlocking {}", + self.locked_funds, amount_unlocked + ))); + } self.save_vesting_funds(store, &vesting_funds)?; Ok(amount_unlocked) @@ -1006,7 +1082,7 @@ impl State { let previously_faulty_power = deadline.faulty_power.clone(); - if deadline.live_sectors == 0 { + if !deadline.is_live() { return Ok(AdvanceDeadlineResult { pledge_delta, power_delta: PowerPair::zero(), @@ -1035,7 +1111,7 @@ impl State { // Pledge for the sectors expiring early is retained to support the termination fee that // will be assessed when the early termination is processed. pledge_delta -= &expired.on_time_pledge; - self.add_initial_pledge(&expired.on_time_pledge.neg()); + self.add_initial_pledge(&expired.on_time_pledge.neg())?; // Record reduction in power of the amount of expiring active power. // Faulty power has already been lost, so the amount expiring can be excluded from the delta. From f6c69ae0fa6837954c0ca3540b278b3a110e9242 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Mon, 22 Feb 2021 23:57:11 -0500 Subject: [PATCH 04/35] monies --- vm/actor/src/builtin/miner/monies.rs | 33 +++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/vm/actor/src/builtin/miner/monies.rs b/vm/actor/src/builtin/miner/monies.rs index 9921f8eddc24..6b3d9502e973 100644 --- a/vm/actor/src/builtin/miner/monies.rs +++ b/vm/actor/src/builtin/miner/monies.rs @@ -9,7 +9,7 @@ use crate::{ TokenAmount, EXPECTED_LEADERS_PER_EPOCH, }; use clock::ChainEpoch; -use fil_types::{NetworkVersion, StoragePower}; +use fil_types::{NetworkVersion, StoragePower, FILECOIN_PRECISION}; use num_bigint::{BigInt, Integer}; use num_traits::Zero; use std::cmp; @@ -43,7 +43,18 @@ lazy_static! { /// This does not divide evenly, so the result is fractionally smaller. static ref INITIAL_PLEDGE_MAX_PER_BYTE: BigInt = BigInt::from(10_u64.pow(18) / (32 << 30)); + + /// Base reward for successfully disputing a window posts proofs. + static ref BASE_REWARD_FOR_DISPUTED_WINDOW_POST: BigInt = + BigInt::from(4 * FILECOIN_PRECISION); + + /// Base penalty for a successful disputed window post proof. + static ref BASE_PENALTY_FOR_DISPUTED_WINDOW_POST: BigInt = + BigInt::from(20 * FILECOIN_PRECISION); } +// FF + 2BR +const INVALID_WINDOW_POST_PROJECTION_PERIOD: ChainEpoch = + CONTINUED_FAULT_PROJECTION_PERIOD + 2 * EPOCHS_IN_DAY; // Projection period of expected daily sector block reward penalised when a fault is continued after initial detection. // This guarantees that a miner pays back at least the expected block reward earned since the last successful PoSt. @@ -159,6 +170,20 @@ pub fn pledge_penalty_for_termination( ) } +// The penalty for optimistically proving a sector with an invalid window PoSt. +pub fn pledge_penalty_for_invalid_windowpost( + reward_estimate: &FilterEstimate, + network_qa_power_estimate: &FilterEstimate, + qa_sector_power: &StoragePower, +) -> TokenAmount { + expected_reward_for_power( + reward_estimate, + network_qa_power_estimate, + qa_sector_power, + INVALID_WINDOW_POST_PROJECTION_PERIOD, + ) + BASE_PENALTY_FOR_DISPUTED_WINDOW_POST +} + /// Computes the PreCommit deposit given sector qa weight and current network conditions. /// PreCommit Deposit = BR(PreCommitDepositProjectionPeriod) pub fn pre_commit_deposit_for_power( @@ -224,10 +249,6 @@ pub fn locked_reward_from_reward( reward: TokenAmount, nv: NetworkVersion, ) -> (TokenAmount, &'static VestSpec) { - let lock_amount = if nv >= NetworkVersion::V6 { - (reward * &*LOCKED_REWARD_FACTOR_NUM).div_floor(&*LOCKED_REWARD_FACTOR_DENOM) - } else { - reward - }; + let lock_amount = (reward * &*LOCKED_REWARD_FACTOR_NUM).div_floor(&*LOCKED_REWARD_FACTOR_DENOM); (lock_amount, &REWARD_VESTING_SPEC) } From 13ebdaf02efcc5a0b9d748054bdd2cd6c68b4a62 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Tue, 23 Feb 2021 00:21:30 -0500 Subject: [PATCH 05/35] partition state --- vm/actor/src/builtin/miner/partition_state.rs | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/vm/actor/src/builtin/miner/partition_state.rs b/vm/actor/src/builtin/miner/partition_state.rs index 8fc70ae5c46b..d73943ccb4d6 100644 --- a/vm/actor/src/builtin/miner/partition_state.rs +++ b/vm/actor/src/builtin/miner/partition_state.rs @@ -14,6 +14,7 @@ use fil_types::{ deadlines::{QuantSpec, NO_QUANTIZATION}, SectorSize, StoragePower, }; +use ipld_amt::Amt; use ipld_blockstore::BlockStore; use num_bigint::bigint_ser; use num_traits::{Signed, Zero}; @@ -23,6 +24,10 @@ use std::{ }; use vm::{ActorError, ExitCode, TokenAmount}; +// Bitwidth of AMTs determined empirically from mutation patterns and projections of mainnet data. +const PARTITION_EXPIRATION_AMT_BITWIDTH: usize = 4; +const PARTITION_EARLY_TERMINATION_ARRAY_AMT_BITWIDTH: usize = 3; + #[derive(Serialize_tuple, Deserialize_tuple, Clone)] pub struct Partition { /// Sector numbers in this partition, including faulty, unproven and terminated sectors. @@ -61,20 +66,28 @@ pub struct Partition { } impl Partition { - pub fn new(empty_array_cid: Cid) -> Self { - Self { + pub fn new(store: &BS) -> Result> { + let empty_expiration_array = + Amt::::new_with_bit_width(store, PARTITION_EXPIRATION_AMT_BITWIDTH).flush()?; + let empty_early_termination_array = Amt::::new_with_bit_width( + store, + PARTITION_EARLY_TERMINATION_ARRAY_AMT_BITWIDTH, + ) + .flush()?; + + Ok(Self { sectors: BitField::new(), unproven: BitField::new(), faults: BitField::new(), recoveries: BitField::new(), terminated: BitField::new(), - expirations_epochs: empty_array_cid, - early_terminated: empty_array_cid, + expirations_epochs: empty_expiration_array, + early_terminated: empty_early_termination_array, live_power: PowerPair::zero(), unproven_power: PowerPair::zero(), faulty_power: PowerPair::zero(), recovering_power: PowerPair::zero(), - } + }) } /// Live sectors are those that are not terminated (but may be faulty). @@ -124,22 +137,17 @@ impl Partition { self.sectors |= §or_numbers; self.live_power += &power; - let proven_power = if !proven { + if !proven { self.unproven_power += &power; self.unproven |= §or_numbers; - - // Only return the power if proven. - PowerPair::default() - } else { - power - }; + } // check invariants self.validate_state()?; // No change to faults, recoveries, or terminations. // No change to faulty or recovering power. - Ok(proven_power) + Ok(power) } /// marks a set of sectors faulty From 107d8ad1f7c2ac622e0ad548829fb103ac840ea1 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 24 Feb 2021 00:13:42 -0500 Subject: [PATCH 06/35] precommit sector --- vm/actor/src/builtin/market/types.rs | 4 +- vm/actor/src/builtin/miner/deadline_state.rs | 12 +- vm/actor/src/builtin/miner/mod.rs | 284 ++++++++----------- vm/actor/src/builtin/miner/monies.rs | 2 +- vm/actor/src/builtin/miner/sector_map.rs | 3 +- vm/actor/src/builtin/miner/state.rs | 26 +- 6 files changed, 148 insertions(+), 183 deletions(-) diff --git a/vm/actor/src/builtin/market/types.rs b/vm/actor/src/builtin/market/types.rs index 9ce2c8861ee3..25058174dce8 100644 --- a/vm/actor/src/builtin/market/types.rs +++ b/vm/actor/src/builtin/market/types.rs @@ -59,9 +59,7 @@ pub struct SectorDeals { #[derive(Serialize_tuple)] pub struct VerifyDealsForActivationParamsRef<'a> { - pub deal_ids: &'a [DealID], - pub sector_expiry: ChainEpoch, - pub sector_start: ChainEpoch, + pub sectors: &'a [SectorDeals], } #[derive(Serialize_tuple, Deserialize_tuple, Default)] diff --git a/vm/actor/src/builtin/miner/deadline_state.rs b/vm/actor/src/builtin/miner/deadline_state.rs index 6a6437730b6f..e20ecd88c5ac 100644 --- a/vm/actor/src/builtin/miner/deadline_state.rs +++ b/vm/actor/src/builtin/miner/deadline_state.rs @@ -418,7 +418,7 @@ impl Deadline { // This case will usually happen zero times. // It would require adding more than a full partition in one go // to happen more than once. - Partition::new(Amt::::new(store).flush()?) + Partition::new(&Amt::::new(&store).flush()?)? } }; @@ -628,7 +628,7 @@ impl Deadline { > { let old_partitions = self .partitions_amt(store) - .map_err(|e| e.wrap("failed to load partitions"))?; + .map_err(|e| e.downcast_wrap("failed to load partitions"))?; let partition_count = old_partitions.count(); let to_remove_set: HashSet<_> = to_remove @@ -863,9 +863,9 @@ impl Deadline { quant: QuantSpec, fault_expiration_epoch: ChainEpoch, ) -> Result<(PowerPair, PowerPair), ActorError> { - let mut partitions = self - .partitions_amt(store) - .map_err(|e| e.wrap("failed to load partitions"))?; + let mut partitions = self.partitions_amt(store).map_err(|e| { + e.downcast_default(ExitCode::ErrIllegalState, "failed to load partitions") + })?; let mut detected_any = false; let mut rescheduled_partitions = Vec::::new(); @@ -1244,7 +1244,7 @@ impl Deadline { .map_err(|e| e.downcast_wrap("failed to load post proofs"))?; proof_arr .set( - proof_arr.len(), + proof_arr.count(), WindowedPoSt { partitions: partitions, proofs: proofs, diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 863f12cc018c..54aaea892237 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -32,7 +32,9 @@ pub use types::*; pub use vesting_state::*; use crate::{ - account::Method as AccountMethod, actor_error, make_empty_map, market::ActivateDealsParams, + account::Method as AccountMethod, + actor_error, make_empty_map, + market::{self, ActivateDealsParams}, power::MAX_MINER_PROVE_COMMITS_PER_EPOCH, }; use crate::{ @@ -417,7 +419,6 @@ impl Actor { RT: Runtime, { let current_epoch = rt.curr_epoch(); - let network_version = rt.network_version(); if params.deadline >= WPOST_PERIOD_DEADLINES as usize { return Err(actor_error!( @@ -439,15 +440,11 @@ impl Actor { // )); // } - let mut partition_indexes = BitField::new(); - if network_version >= NetworkVersion::V7 { - for partition in params.partitions.iter() { - partition_indexes.set(partition.index as usize); - } - } - let post_result = rt.transaction(|state: &mut State, rt| { let info = get_miner_info(rt.store(), state)?; + // TODO: NEED TO ACTUALLY HANDLE THIS PROPERLY IN CASE OF DIFFERENT PROOF SIZE + // let proof_size = info.window_post_proof_type; + let max_proof_size = 192; rt.validate_immediate_caller_is( info.control_addresses @@ -460,27 +457,13 @@ impl Actor { // // This can be 0 if the miner isn't actually proving anything, // just skipping all sectors. - // TODO: FIX ME FOR v3 - // let window_post_proof_type = info - // .seal_proof_type - // .registered_window_post_proof() - // .map_err(|e| { - // actor_error!( - // ErrIllegalState, - // "failed to determine window PoSt type: {}", - // e - // ) - // })?; - let window_post_proof_type = 2349; if let Some(proof) = params.proofs.get(0) { - if proof.post_proof - != fil_types::RegisteredPoStProof::Invalid(window_post_proof_type) - { + if proof.post_proof != info.window_post_proof_type { return Err(actor_error!( ErrIllegalArgument, "expected proof of type {:?}, got {:?}", proof.post_proof, - window_post_proof_type + info.window_post_proof_type )); } } else { @@ -490,6 +473,15 @@ impl Actor { params.proofs.len() )); } + // Make sure the proof size doesn't exceed the max. We could probably check for an exact match, but this is safer. + let max_size = max_proof_size * params.partitions.len(); + if params.proofs.get(0).unwrap().proof_bytes.len() > max_size { + return Err(actor_error!( + ErrIllegalArgument, + "expect proof to be smaller than {} bytes", + max_size + )); + } // Validate that the miner didn't try to prove too many partitions at once. let submission_partition_limit = @@ -574,25 +566,15 @@ impl Actor { .load_deadline(rt.store(), params.deadline) .map_err(|e| e.wrap(format!("failed to load deadline {}", params.deadline)))?; - if network_version >= NetworkVersion::V7 { - let already_proven = &deadline.post_submissions & &partition_indexes; - if !already_proven.is_empty() { - return Err(actor_error!( - ErrIllegalArgument, - "partition already proven: {:?}", - already_proven - )); - } - } - // Record proven sectors/partitions, returning updates to power and the final set of sectors // proven/skipped. // - // NOTE: This function does not actually check the proofs but does assume that they'll be - // successfully validated. The actual proof verification is done below in verifyWindowedPost. + // NOTE: This function does not actually check the proofs but does assume that they're correct. Instead, + // it snapshots the deadline's state and the submitted proofs at the end of the challenge window and + // allows third-parties to dispute these proofs. // - // If proof verification fails, the this deadline MUST NOT be saved and this function should - // be aborted. + // While we could perform _all_ operations at the end of challenge window, we do as we can here to avoid + // overloading cron. let fault_expiration = current_deadline.last() + FAULT_MAX_AGE; let post_result = deadline .record_proven_sectors( @@ -613,24 +595,9 @@ impl Actor { ) })?; - // Skipped sectors (including retracted recoveries) pay nothing at Window PoSt, - // but will incur the "ongoing" fault fee at deadline end. - - // Validate proofs - - // Load sector infos for proof, substituting a known-good sector for known-faulty sectors. - // Note: this is slightly sub-optimal, loading info for the recovering sectors again after they were already - // loaded above. - let sector_infos = sectors - .load_for_proof(&post_result.sectors, &post_result.ignored_sectors) - .map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - "failed to load proven sector info", - ) - })?; - - if sector_infos.is_empty() { + // Make sure we actually proved something. + let proven_sectors = &post_result.sectors - &post_result.ignored_sectors; + if proven_sectors.len() == 0 { // Abort verification if all sectors are (now) faults. There's nothing to prove. // It's not rational for a miner to submit a Window PoSt marking *all* non-faulty sectors as skipped, // since that will just cause them to pay a penalty at deadline end that would otherwise be zero @@ -641,9 +608,38 @@ impl Actor { )); } - // Verify the proof. - // A failed verification doesn't immediately cause a penalty; the miner can try again. - verify_windowed_post(rt, current_deadline.challenge, §or_infos, params.proofs)?; + // If we're not recovering power, record the proof for optimistic verification. + if post_result.recovered_power.is_zero() { + deadline + .record_post_proofs(rt.store(), post_result.partitions, params.proofs) + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to record proof for optimistic verification", + ) + })? + } else { + // Load sector infos for proof, substituting a known-good sector for known-faulty sectors. + // Note: this is slightly sub-optimal, loading info for the recovering sectors again after they were already + // loaded above. + let sector_infos = sectors + .load_for_proof(&post_result.sectors, post_result.ignored_sectors) + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to load sectors for post verification", + ) + })?; + verify_windowed_post( + &rt, + current_deadline.challenge, + §or_infos, + params.proofs, + ) + .map_err(|e| { + e.downcast_default(ExitCode::ErrIllegalArgument, "window post failed") + })?; + } let deadline_idx = params.deadline; deadlines @@ -769,21 +765,19 @@ impl Actor { let reward_stats = request_current_epoch_block_reward(rt)?; let power_total = request_current_total_power(rt)?; - let deal_weight = - request_deal_weight(rt, ¶ms.deal_ids, rt.curr_epoch(), params.expiration)?; - + let deal_weights = request_deal_weights( + rt, + &[market::SectorDeals { + sector_expiry: params.expiration, + deal_ids: params.deal_ids, + }], + rt.curr_epoch(), + params.expiration, + )?; + let deal_weight = deal_weights.sectors[0]; let mut fee_to_burn = TokenAmount::from(0); let newly_vested = rt.transaction(|state: &mut State, rt| { - // Stop vesting funds as of version 7. Its computationally expensive and unlikely to release any funds. - let newly_vested = if rt.network_version() < NetworkVersion::V7 { - state - .unlock_vested_funds(rt.store(), rt.curr_epoch()) - .map_err(|e| { - e.downcast_default(ExitCode::ErrIllegalState, "failed to vest funds") - })? - } else { - TokenAmount::from(0) - }; + let newly_vested = TokenAmount::from(0); // available balance already accounts for fee debt so it is correct to call // this before RepayDebts. We would have to @@ -814,56 +808,30 @@ impl Actor { )); } - if rt.network_version() < NetworkVersion::V7 { - // TODO: FIX ME FOR v3 - if params.seal_proof != fil_types::RegisteredSealProof::Invalid(2349) { - return Err(actor_error!( - ErrIllegalArgument, - "sector seal proof {:?} must match miner seal proof type {:?}", - params.seal_proof, - info.window_post_proof_type - )); - } - } else { - // From network version 7, the pre-commit seal type must have the same Window PoSt proof type as the miner's - // recorded seal type has, rather than be exactly the same seal type. - // This permits a transition window from V1 to V1_1 seal types (which share Window PoSt proof type). - // TODO: FIX ME FOR v3 - // let miner_wpost_proof = info - // .seal_proof_type - // .registered_window_post_proof() - // .map_err(|e| { - // actor_error!( - // ErrIllegalState, - // "failed to lookup window PoSt proof type for miner seal proof {:?}: {}", - // info.seal_proof_type, - // e - // ) - // })?; - let miner_wpost_proof = 2349; - let sector_wpost_proof = - params - .seal_proof - .registered_window_post_proof() - .map_err(|e| { - actor_error!( - ErrIllegalState, - "failed to lookup window PoSt proof type \ - for sector seal proof {:?}: {}", - params.seal_proof, - e - ) - })?; - if sector_wpost_proof != fil_types::RegisteredPoStProof::Invalid(miner_wpost_proof) - { - return Err(actor_error!( - ErrIllegalArgument, - "sector window PoSt proof type {:?} must match miner \ - window PoSt proof type {:?}", - sector_wpost_proof, - miner_wpost_proof - )); - } + // From network version 7, the pre-commit seal type must have the same Window PoSt proof type as the miner's + // recorded seal type has, rather than be exactly the same seal type. + // This permits a transition window from V1 to V1_1 seal types (which share Window PoSt proof type). + let sector_wpost_proof = + params + .seal_proof + .registered_window_post_proof() + .map_err(|e| { + actor_error!( + ErrIllegalState, + "failed to lookup window PoSt proof type \ + for sector seal proof {:?}: {}", + params.seal_proof, + e + ) + })?; + if sector_wpost_proof != info.window_post_proof_type { + return Err(actor_error!( + ErrIllegalArgument, + "sector window PoSt proof type {:?} must match miner \ + window PoSt proof type {:?}", + sector_wpost_proof, + info.window_post_proof_type + )); } let store = rt.store(); @@ -879,11 +847,11 @@ impl Actor { } // Ensure total deal space does not exceed sector size. - if deal_weight.sectors[0].deal_space > info.sector_size as u64 { + if deal_weight.deal_space > info.sector_size as u64 { return Err(actor_error!( ErrIllegalArgument, "deal size too large to fit in sector {} > {}", - deal_weight.sectors[0].deal_space, + deal_weight.deal_space, info.sector_size )); } @@ -897,26 +865,7 @@ impl Actor { )) })?; - // The following two checks shouldn't be necessary, but it can't - // hurt to double-check (unless it's really just too - // expensive?). - let sector = state - .get_precommitted_sector(store, params.sector_number) - .map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - format!("failed to check pre-commit {}", params.sector_number), - ) - })?; - - if sector.is_some() { - return Err(actor_error!( - ErrIllegalState, - "sector {} already pre-committed", - params.sector_number - )); - } - + // This sector check is redundant given the allocated sectors bitfield, but remains for safety. let sector_found = state .has_sector_number(store, params.sector_number) .map_err(|e| { @@ -943,8 +892,8 @@ impl Actor { let sector_weight = qa_power_for_weight( info.sector_size, duration, - &deal_weight.sectors[0].deal_weight, - &deal_weight.sectors[0].verified_deal_weight, + &deal_weight.deal_weight, + &deal_weight.verified_deal_weight, ); let deposit_req = pre_commit_deposit_for_power( @@ -961,7 +910,14 @@ impl Actor { )); } - state.add_pre_commit_deposit(&deposit_req); + state.add_pre_commit_deposit(&deposit_req).map_err(|e| { + actor_error!( + ErrIllegalState, + "failed to add pre-commit deposit {}: {}", + deposit_req, + e + ) + })?; let seal_proof = params.seal_proof; let sector_number = params.sector_number; @@ -3343,9 +3299,9 @@ where Ok(unsealed_cid) } -fn request_deal_weight( +fn request_deal_weights( rt: &mut RT, - deal_ids: &[DealID], + sectors: &[market::SectorDeals], sector_start: ChainEpoch, sector_expiry: ChainEpoch, ) -> Result @@ -3353,18 +3309,28 @@ where BS: BlockStore, RT: Runtime, { - if deal_ids.is_empty() { - return Ok(VerifyDealsForActivationReturn::default()); + // Short-circuit if there are no deals in any of the sectors. + let mut deal_count = 0; + for sector in sectors { + deal_count += sector.deal_ids.len(); + } + if deal_count == 0 { + let mut empty_result = VerifyDealsForActivationReturn { + sectors: Vec::with_capacity(sectors.len()), + }; + for i in 0..sectors.len() { + empty_result.sectors.push(market::SectorWeights { + deal_space: 0, + deal_weight: 0.into(), + verified_deal_weight: 0.into(), + }); + } + return Ok(empty_result); } - let serialized = rt.send( *STORAGE_MARKET_ACTOR_ADDR, MarketMethod::VerifyDealsForActivation as u64, - Serialized::serialize(VerifyDealsForActivationParamsRef { - deal_ids, - sector_start, - sector_expiry, - })?, + Serialized::serialize(VerifyDealsForActivationParamsRef { sectors: sectors })?, TokenAmount::zero(), )?; diff --git a/vm/actor/src/builtin/miner/monies.rs b/vm/actor/src/builtin/miner/monies.rs index 6b3d9502e973..fe0bd1dc6032 100644 --- a/vm/actor/src/builtin/miner/monies.rs +++ b/vm/actor/src/builtin/miner/monies.rs @@ -181,7 +181,7 @@ pub fn pledge_penalty_for_invalid_windowpost( network_qa_power_estimate, qa_sector_power, INVALID_WINDOW_POST_PROJECTION_PERIOD, - ) + BASE_PENALTY_FOR_DISPUTED_WINDOW_POST + ) + &*BASE_PENALTY_FOR_DISPUTED_WINDOW_POST } /// Computes the PreCommit deposit given sector qa weight and current network conditions. diff --git a/vm/actor/src/builtin/miner/sector_map.rs b/vm/actor/src/builtin/miner/sector_map.rs index 86d0e09d0f6c..c45d9afae3f8 100644 --- a/vm/actor/src/builtin/miner/sector_map.rs +++ b/vm/actor/src/builtin/miner/sector_map.rs @@ -3,6 +3,7 @@ use super::WPOST_PERIOD_DEADLINES; use bitfield::{BitField, UnvalidatedBitField, Validate}; +use serde::{Deserialize, Serialize}; use std::collections::HashMap; /// Maps deadlines to partition maps. @@ -110,7 +111,7 @@ impl DeadlineSectorMap { } /// Maps partitions to sector bitfields. -#[derive(Default)] +#[derive(Default, Serialize, Deserialize)] pub struct PartitionSectorMap(HashMap); impl PartitionSectorMap { diff --git a/vm/actor/src/builtin/miner/state.rs b/vm/actor/src/builtin/miner/state.rs index c6e84ff6299a..1372a05d8dbf 100644 --- a/vm/actor/src/builtin/miner/state.rs +++ b/vm/actor/src/builtin/miner/state.rs @@ -320,10 +320,7 @@ impl State { e.downcast_wrap(format!("failed to store pre-commitment for {:?}", info)) })?; if !modified { - // TODO: FIX - return Err(Box::new( - format!("sector {} already pre-commited", info.info.sector_number).into(), - )); + return Err(format!("sector {} already pre-commited", info.info.sector_number).into()); } self.pre_committed_sectors = precommitted.flush()?; Ok(()) @@ -556,7 +553,7 @@ impl State { store, partition_size, proven, - deadline_sectors, + &deadline_sectors, sector_size, quant, )?; @@ -756,6 +753,7 @@ impl State { )); } self.initial_pledge = new_total; + Ok(()) } pub fn apply_penalty(&mut self, penalty: &TokenAmount) -> Result<(), String> { @@ -776,7 +774,7 @@ impl State { spec: &VestSpec, ) -> Result> { if vesting_sum.is_negative() { - return Err(Box::new(format!("negative vesting sum {}", vesting_sum))); + return Err(format!("negative vesting sum {}", vesting_sum).into()); } let mut vesting_funds = self.load_vesting_funds(store)?; @@ -785,10 +783,11 @@ impl State { let amount_unlocked = vesting_funds.unlock_vested_funds(current_epoch); self.locked_funds -= &amount_unlocked; if self.locked_funds.is_negative() { - return Err(Box::new(format!( + return Err(format!( "negative locked funds {} after unlocking {}", self.locked_funds, amount_unlocked - ))); + ) + .into()); } // add locked funds now vesting_funds.add_locked_funds(current_epoch, vesting_sum, self.proving_period_start, spec); @@ -823,9 +822,9 @@ impl State { // * It may be possible the go implementation catches a potential panic here if from_vesting > self.fee_debt { - return Err(Box::new( - "should never unlock more than the debt we need to repay", - )); + return Err("should never unlock more than the debt we need to repay" + .to_owned() + .into()); } self.fee_debt -= &from_vesting; @@ -873,10 +872,11 @@ impl State { let amount_unlocked = vesting_funds.unlock_unvested_funds(current_epoch, target); self.locked_funds -= &amount_unlocked; if self.locked_funds.is_negative() { - return Err(Box::new(format!( + return Err(format!( "negative locked funds {} after unlocking {}", self.locked_funds, amount_unlocked - ))); + ) + .into()); } self.save_vesting_funds(store, &vesting_funds)?; From d929cc71292fbc77b5ec5e9e43233ee96b0ecf80 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 24 Feb 2021 00:46:58 -0500 Subject: [PATCH 07/35] prove commit sector and confirm sector proofs valid --- vm/actor/src/builtin/miner/mod.rs | 96 +++++++++++++------------------ 1 file changed, 41 insertions(+), 55 deletions(-) diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 54aaea892237..73bb85dcc87b 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -623,22 +623,17 @@ impl Actor { // Note: this is slightly sub-optimal, loading info for the recovering sectors again after they were already // loaded above. let sector_infos = sectors - .load_for_proof(&post_result.sectors, post_result.ignored_sectors) + .load_for_proof(&post_result.sectors, &post_result.ignored_sectors) .map_err(|e| { e.downcast_default( ExitCode::ErrIllegalState, "failed to load sectors for post verification", ) })?; - verify_windowed_post( - &rt, - current_deadline.challenge, - §or_infos, - params.proofs, - ) - .map_err(|e| { - e.downcast_default(ExitCode::ErrIllegalArgument, "window post failed") - })?; + verify_windowed_post(rt, current_deadline.challenge, §or_infos, params.proofs) + .map_err(|e| { + e.downcast_default(ExitCode::ErrIllegalArgument, "window post failed") + })?; } let deadline_idx = params.deadline; @@ -929,8 +924,8 @@ impl Actor { info: params, pre_commit_deposit: deposit_req, pre_commit_epoch: rt.curr_epoch(), - deal_weight: deal_weight.sectors[0].deal_weight.clone(), - verified_deal_weight: deal_weight.sectors[0].deal_weight.clone(), + deal_weight: deal_weight.deal_weight.clone(), + verified_deal_weight: deal_weight.deal_weight.clone(), }, ) .map_err(|e| { @@ -993,7 +988,6 @@ impl Actor { RT: Runtime, { rt.validate_immediate_caller_accept_any()?; - let nv = rt.network_version(); if params.sector_number > MAX_SECTOR_NUMBER { return Err(actor_error!( @@ -1002,12 +996,23 @@ impl Actor { )); } - let max_proof_size = if nv >= NetworkVersion::V5 { - MAX_PROVE_COMMIT_SIZE_V5 - } else { - MAX_PROVE_COMMIT_SIZE_V4 - }; + let sector_number = params.sector_number; + let st: State = rt.state()?; + let precommit = st + .get_precommitted_sector(rt.store(), sector_number) + .map_err(|e| { + actor_error!( + ErrIllegalState, + "failed to load pre-committed sector {}", + sector_number + ) + })? + .ok_or_else(|| actor_error!(ErrNotFound, "no pre-commited sector {}", sector_number))?; + + // TODO: NEED TO ACTUALLY IMPLEMENT THE PROOFSIZE FUNCTION + // let max_proof_size = precommit.info.seal_proof.proof_size() + let max_proof_size = 192; if params.proof.len() > max_proof_size { return Err(actor_error!( ErrIllegalArgument, @@ -1017,23 +1022,6 @@ impl Actor { )); } - let sector_number = params.sector_number; - let precommit = rt.transaction(|state: &mut State, rt| { - let precommit = state - .get_precommitted_sector(rt.store(), sector_number) - .map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - format!("failed to load precommitted sector: {}", sector_number), - ) - })? - .ok_or_else(|| { - actor_error!(ErrNotFound, "no pre-committed sector: {}", sector_number) - })?; - - Ok(precommit) - })?; - let msd = max_prove_commit_duration(precommit.info.seal_proof).ok_or_else(|| { actor_error!( ErrIllegalState, @@ -1185,7 +1173,7 @@ impl Actor { )); } - let (new_power, total_pledge, newly_vested) = rt.transaction(|state: &mut State, rt| { + let (total_pledge, newly_vested) = rt.transaction(|state: &mut State, rt| { let store = rt.store(); // Schedule expiration for replaced sectors to the end of their next deadline window. @@ -1305,7 +1293,7 @@ impl Actor { ) })?; - let new_power = state + state .assign_sectors_to_deadlines( store, rt.curr_epoch(), @@ -1320,22 +1308,18 @@ impl Actor { ) })?; - // Stop unlocking funds as of version 7. It's computationally expensive and unlikely to actually unlock anything. - let newly_vested = if rt.network_version() < NetworkVersion::V7 { - state - .unlock_vested_funds(store, rt.curr_epoch()) - .map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - "failed to assign new sectors to deadlines", - ) - })? - } else { - TokenAmount::zero() - }; + let newly_vested = TokenAmount::zero(); // Unlock deposit for successful proofs, make it available for lock-up as initial pledge. - state.add_pre_commit_deposit(&(-deposit_to_unlock)); + state + .add_pre_commit_deposit(&(-deposit_to_unlock)) + .map_err(|e| { + actor_error!( + ErrIllegalState, + "failed to calculate unlocked balance: {}", + e + ) + })?; let unlocked_balance = state @@ -1356,7 +1340,10 @@ impl Actor { )); } - state.add_initial_pledge(&total_pledge); + state.add_initial_pledge(&total_pledge).map_err(|e| { + actor_error!(ErrIllegalState, "failed to add initial pledge: {}", e) + })?; + state .check_balance_invariants(&rt.current_balance()?) .map_err(|e| { @@ -1366,11 +1353,10 @@ impl Actor { ) })?; - Ok((new_power, total_pledge, newly_vested)) + Ok((total_pledge, newly_vested)) })?; - // Request power and pledge update for activated sector. - request_update_power(rt, new_power)?; + // Request pledge update for activated sector. notify_pledge_changed(rt, &(total_pledge - newly_vested))?; Ok(()) From 0010816c41839e5810cf83fbc92352b65de58bc6 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 24 Feb 2021 01:07:38 -0500 Subject: [PATCH 08/35] confirm sector proofs valid --- vm/actor/src/builtin/miner/mod.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 73bb85dcc87b..fde21256f157 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -1314,11 +1314,7 @@ impl Actor { state .add_pre_commit_deposit(&(-deposit_to_unlock)) .map_err(|e| { - actor_error!( - ErrIllegalState, - "failed to calculate unlocked balance: {}", - e - ) + actor_error!(ErrIllegalState, "failed to add precommit deposit: {}", e) })?; let unlocked_balance = From 88304f9dffe57f9ddf752e63d75d20beff4e4541 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 24 Feb 2021 01:11:44 -0500 Subject: [PATCH 09/35] extend sector expiration --- vm/actor/src/builtin/miner/mod.rs | 27 ++++++++++++--------------- vm/actor/src/builtin/miner/policy.rs | 8 ++------ 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index fde21256f157..05aa330dcc6d 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -1404,7 +1404,6 @@ impl Actor { BS: BlockStore, RT: Runtime, { - let nv = rt.network_version(); if params.extensions.len() as u64 > DELCARATIONS_MAX { return Err(actor_error!( ErrIllegalArgument, @@ -1539,7 +1538,7 @@ impl Actor { let new_sectors: Vec = old_sectors .iter() .map(|sector| { - if !can_extend_seal_proof_type(sector.seal_proof, nv) { + if !can_extend_seal_proof_type(sector.seal_proof) { return Err(actor_error!( ErrForbidden, "cannot extend expiration for sector {} with unsupported \ @@ -1613,19 +1612,17 @@ impl Actor { // Record the new partition expiration epoch for setting outside this loop // over declarations. - if nv >= NetworkVersion::V7 { - let prev_epoch_partitions = - partitions_by_new_epoch.entry(decl.new_expiration); - let not_exists = matches!(prev_epoch_partitions, Entry::Vacant(_)); - - // Add declaration partition - prev_epoch_partitions - .or_insert_with(Vec::new) - .push(decl.partition); - if not_exists { - // reschedule epoch if the partition for new epoch didn't already exist - epochs_to_reschedule.push(decl.new_expiration); - } + let prev_epoch_partitions = + partitions_by_new_epoch.entry(decl.new_expiration); + let not_exists = matches!(prev_epoch_partitions, Entry::Vacant(_)); + + // Add declaration partition + prev_epoch_partitions + .or_insert_with(Vec::new) + .push(decl.partition); + if not_exists { + // reschedule epoch if the partition for new epoch didn't already exist + epochs_to_reschedule.push(decl.new_expiration); } } diff --git a/vm/actor/src/builtin/miner/policy.rs b/vm/actor/src/builtin/miner/policy.rs index 9a8a2eb5812d..2026a7673428 100644 --- a/vm/actor/src/builtin/miner/policy.rs +++ b/vm/actor/src/builtin/miner/policy.rs @@ -106,14 +106,10 @@ pub fn can_pre_commit_seal_proof(proof: RegisteredSealProof, nv: NetworkVersion) } /// Checks whether a seal proof type is supported for new miners and sectors. -pub fn can_extend_seal_proof_type(proof: RegisteredSealProof, nv: NetworkVersion) -> bool { +pub fn can_extend_seal_proof_type(proof: RegisteredSealProof) -> bool { use RegisteredSealProof::*; - if nv >= NetworkVersion::V7 { - matches!(proof, StackedDRG32GiBV1P1 | StackedDRG64GiBV1P1) - } else { - matches!(proof, StackedDRG32GiBV1 | StackedDRG64GiBV1) - } + matches!(proof, StackedDRG32GiBV1P1 | StackedDRG64GiBV1P1) } /// Maximum duration to allow for the sealing process for seal algorithms. From c98374ea0bb2ae633625881a4b458eeaf0fdc94f Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 24 Feb 2021 01:12:36 -0500 Subject: [PATCH 10/35] extend sector expiration --- vm/actor/src/builtin/miner/mod.rs | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 05aa330dcc6d..c0c450819a99 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -1612,8 +1612,7 @@ impl Actor { // Record the new partition expiration epoch for setting outside this loop // over declarations. - let prev_epoch_partitions = - partitions_by_new_epoch.entry(decl.new_expiration); + let prev_epoch_partitions = partitions_by_new_epoch.entry(decl.new_expiration); let not_exists = matches!(prev_epoch_partitions, Entry::Vacant(_)); // Add declaration partition @@ -1634,22 +1633,20 @@ impl Actor { })?; // Record partitions in deadline expiration queue - if nv >= NetworkVersion::V7 { - for epoch in epochs_to_reschedule { - let p_idxs = partitions_by_new_epoch.get(&epoch).unwrap(); - deadline - .add_expiration_partitions(store, epoch, p_idxs, quant) - .map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - format!( - "failed to add expiration partitions to \ + for epoch in epochs_to_reschedule { + let p_idxs = partitions_by_new_epoch.get(&epoch).unwrap(); + deadline + .add_expiration_partitions(store, epoch, p_idxs, quant) + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + format!( + "failed to add expiration partitions to \ deadline {} epoch {}", - deadline_idx, epoch - ), - ) - })?; - } + deadline_idx, epoch + ), + ) + })?; } deadlines From a75adb07f13df4de819b890d69ee5496bef5a170 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 24 Feb 2021 01:20:59 -0500 Subject: [PATCH 11/35] terminate sector --- vm/actor/src/builtin/miner/mod.rs | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index c0c450819a99..fd8c2a075a85 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -1689,9 +1689,8 @@ impl Actor { /// AddressedPartitionsMax per epoch until the queue is empty. /// /// The sectors are immediately ignored for Window PoSt proofs, and should be - /// masked in the same way as faulty sectors. A miner terminating sectors in the - /// current deadline must be careful to compute an appropriate Window PoSt proof - /// for the sectors that will be active at the time the PoSt is submitted. + /// masked in the same way as faulty sectors. A miner may not terminate sectors in the + /// current deadline or the next deadline to be proven. /// /// This function may be invoked with no new sectors to explicitly process the /// next batch of sectors. @@ -1770,6 +1769,16 @@ impl Actor { })?; for (deadline_idx, partition_sectors) in to_process.iter() { + // If the deadline the current or next deadline to prove, don't allow terminating sectors. + // We assume that deadlines are immutable when being proven. + if !deadline_is_mutable(state.proving_period_start, deadline_idx, curr_epoch) { + return Err(actor_error!( + ErrIllegalArgument, + "cannot terminate sectors in immutable deadline {}", + deadline_idx + )); + } + let quant = state.quant_spec_for_deadline(deadline_idx); let mut deadline = deadlines .load_deadline(store, deadline_idx) @@ -1822,6 +1831,15 @@ impl Actor { // jobs. However, in practice, that shouldn't be all that bad. schedule_early_termination_work(rt)?; } + let state: State = rt.state()?; + state + .check_balance_invariants(&rt.current_balance()?) + .map_err(|e| { + ActorError::new( + ErrBalanceInvariantBroken, + format!("balance invariant broken: {}", e), + ) + })?; request_update_power(rt, power_delta)?; Ok(TerminateSectorsReturn { done: !more }) From f71d17e1985e061a61da4140b0ded10fa87ae4c4 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 24 Feb 2021 10:07:35 -0500 Subject: [PATCH 12/35] everything done except new method --- vm/actor/src/builtin/miner/mod.rs | 171 ++++++++++++++++----------- vm/actor/src/builtin/miner/monies.rs | 5 +- 2 files changed, 106 insertions(+), 70 deletions(-) diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index fd8c2a075a85..ba37f8c2b79b 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -879,7 +879,7 @@ impl Actor { } if params.replace_capacity { - validate_replace_sector(state, store, ¶ms, rt.network_version())?; + validate_replace_sector(state, store, ¶ms)?; } let duration = params.expiration - rt.curr_epoch(); @@ -1940,7 +1940,7 @@ impl Actor { let fault_expiration_epoch = target_deadline.last() + FAULT_MAX_AGE; let deadline_power_delta = deadline - .declare_faults( + .record_faults( store, §ors, info.sector_size, @@ -2173,12 +2173,18 @@ impl Actor { let store = rt.store(); - if !deadline_is_mutable(state.proving_period_start, params_deadline, rt.curr_epoch()) { + if !deadline_available_for_compaction( + state.proving_period_start, + params_deadline, + rt.curr_epoch(), + ) { return Err(actor_error!( ErrForbidden, - "cannot compact deadline {} during its challenge window or \ - the prior challenge window", - params_deadline + "cannot compact deadline {} during its challenge window, \ + or the prior challenge window, + or before {} epochs have passed since its last challenge window ended", + params_deadline, + WPOST_DISPUTE_WINDOW )); } @@ -2221,12 +2227,12 @@ impl Actor { let sectors = state.load_sector_infos(store, &live).map_err(|e| { e.downcast_default(ExitCode::ErrIllegalState, "failed to load moved sectors") })?; - - let new_power = deadline + let proven = true; + let added_power = deadline .add_sectors( store, info.window_post_partition_sectors, - true, + proven, §ors, info.sector_size, quant, @@ -2238,12 +2244,12 @@ impl Actor { ) })?; - if removed_power != new_power { + if removed_power != added_power { return Err(actor_error!( ErrIllegalState, "power changed when compacting partitions: was {:?}, is now {:?}", removed_power, - new_power + added_power )); } @@ -2340,15 +2346,13 @@ impl Actor { )); } - let nv = rt.network_version(); - let (pledge_delta_total, to_burn) = rt.transaction(|st: &mut State, rt| { let mut pledge_delta_total = TokenAmount::zero(); rt.validate_immediate_caller_is(std::iter::once(&*REWARD_ACTOR_ADDR))?; let (reward_to_lock, locked_reward_vesting_spec) = - locked_reward_from_reward(params.reward, nv); + locked_reward_from_reward(params.reward); // This ensures the miner has sufficient funds to lock up amountToLock. // This should always be true if reward actor sends reward funds with the message. @@ -2408,6 +2412,14 @@ impl Actor { notify_pledge_changed(rt, &pledge_delta_total)?; burn_funds(rt, to_burn)?; + let st: State = rt.state()?; + st.check_balance_invariants(&rt.current_balance()?) + .map_err(|e| { + ActorError::new( + ErrBalanceInvariantBroken, + format!("balance invariants broken: {}", e), + ) + })?; Ok(()) } @@ -2419,8 +2431,9 @@ impl Actor { BS: BlockStore, RT: Runtime, { - // Note: only the first reporter of any fault is rewarded. - // Subsequent invocations fail because the target miner has been removed. + // Note: only the first report of any fault is processed because it sets the + // ConsensusFaultElapsed state variable to an epoch after the fault, and reports prior to + // that epoch are no longer valid rt.validate_immediate_caller_type(CALLER_TYPES_SIGNABLE.iter())?; let reporter = *rt.message().caller(); @@ -2428,6 +2441,14 @@ impl Actor { .verify_consensus_fault(¶ms.header1, ¶ms.header2, ¶ms.header_extra) .map_err(|e| e.downcast_default(ExitCode::ErrIllegalArgument, "fault not verified"))? .ok_or_else(|| actor_error!(ErrIllegalArgument, "No consensus fault found"))?; + if fault.target != *rt.message().receiver() { + return Err(actor_error!( + ErrIllegalArgument, + "fault by {} reported to miner {}", + fault.target, + rt.message().receiver() + )); + } // Elapsed since the fault (i.e. since the higher of the two blocks) let fault_age = rt.curr_epoch() - fault.epoch; @@ -2451,7 +2472,7 @@ impl Actor { let mut pledge_delta = TokenAmount::from(0); - let (burn_amount, reward_amount) = rt.transaction(|st: &mut State, rt| { + let (burn_amount, reward_amount, state) = rt.transaction(|st: &mut State, rt| { let mut info = get_miner_info(rt.store(), &st)?; // Verify miner hasn't already been faulted @@ -2490,7 +2511,7 @@ impl Actor { e.downcast_default(ExitCode::ErrSerialization, "failed to save miner info") })?; - Ok((burn_amount, reward_amount)) + Ok((burn_amount, reward_amount, st.clone())) })?; if let Err(e) = rt.send(reporter, METHOD_SEND, Serialized::default(), reward_amount) { @@ -2500,7 +2521,6 @@ impl Actor { burn_funds(rt, burn_amount)?; notify_pledge_changed(rt, &pledge_delta)?; - let state: State = rt.state()?; state .check_balance_invariants(&rt.current_balance()?) .map_err(|e| { @@ -2581,6 +2601,21 @@ impl Actor { let amount_withdrawn = std::cmp::min(available_balance, params.amount_requested); assert!(!amount_withdrawn.is_negative()); + if amount_withdrawn.is_negative() { + return Err(actor_error!( + ErrIllegalState, + "negative amount to withdraw: {}", + amount_withdrawn + )); + } + if amount_withdrawn > available_balance { + return Err(actor_error!( + ErrIllegalState, + "amount to withdraw {} < available {}", + amount_withdrawn, + available_balance + )); + } if amount_withdrawn.is_positive() { rt.send( @@ -2666,7 +2701,15 @@ impl Actor { } _ => {} }; - + let state: State = rt.state()?; + state + .check_balance_invariants(&rt.current_balance()?) + .map_err(|e| { + ActorError::new( + ErrBalanceInvariantBroken, + format!("balance invariants broken: {}", e), + ) + })?; Ok(()) } } @@ -2746,7 +2789,13 @@ where // Remove pledge requirement. let mut pledge_delta = -total_initial_pledge; - state.add_initial_pledge(&pledge_delta); + state.add_initial_pledge(&pledge_delta).map_err(|e| { + actor_error!( + ErrIllegalState, + "failed to add initial pledge {}", + pledge_delta + ) + }); // Use unlocked pledge to pay down outstanding fee debt let (penalty_from_vesting, penalty_from_balance) = state @@ -2970,7 +3019,6 @@ fn validate_replace_sector( state: &State, store: &BS, params: &SectorPreCommitInfo, - nv: NetworkVersion, ) -> Result<(), ActorError> where BS: BlockStore, @@ -2999,52 +3047,40 @@ where )); } - if nv < NetworkVersion::V7 { - if params.seal_proof != replace_sector.seal_proof { - return Err(actor_error!( + // From network version 7, the new sector's seal type must have the same Window PoSt proof type as the one + // being replaced, rather than be exactly the same seal type. + // This permits replacing sectors with V1 seal types with V1_1 seal types. + let replace_w_post_proof = replace_sector + .seal_proof + .registered_window_post_proof() + .map_err(|e| { + actor_error!( + ErrIllegalState, + "failed to lookup Window PoSt proof type for sector seal proof {:?}: {}", + replace_sector.seal_proof, + e + ) + })?; + let new_w_post_proof = params + .seal_proof + .registered_window_post_proof() + .map_err(|e| { + actor_error!( ErrIllegalArgument, - "cannot replace sector {} seal proof {:?} with seal proof {:?}", - params.replace_sector_number, + "failed to lookup Window PoSt proof type for new seal proof {:?}: {}", replace_sector.seal_proof, - params.seal_proof - )); - } - } else { - // From network version 7, the new sector's seal type must have the same Window PoSt proof type as the one - // being replaced, rather than be exactly the same seal type. - // This permits replacing sectors with V1 seal types with V1_1 seal types. - let replace_w_post_proof = replace_sector - .seal_proof - .registered_window_post_proof() - .map_err(|e| { - actor_error!( - ErrIllegalState, - "failed to lookup Window PoSt proof type for sector seal proof {:?}: {}", - replace_sector.seal_proof, - e - ) - })?; - let new_w_post_proof = params - .seal_proof - .registered_window_post_proof() - .map_err(|e| { - actor_error!( - ErrIllegalArgument, - "failed to lookup Window PoSt proof type for new seal proof {:?}: {}", - replace_sector.seal_proof, - e - ) - })?; + e + ) + })?; - if replace_w_post_proof != new_w_post_proof { - return Err(actor_error!( + if replace_w_post_proof != new_w_post_proof { + return Err(actor_error!( ErrIllegalArgument, "new sector window PoSt proof type {:?} must match replaced proof type {:?} (seal proof type {:?})", replace_w_post_proof, new_w_post_proof, params.seal_proof )); - } } if params.expiration < replace_sector.expiration { @@ -3183,7 +3219,11 @@ where let miner_actor_id: u64 = if let Payload::ID(i) = rt.message().receiver().payload() { *i } else { - panic!("could not provide ID address"); + return Err(actor_error!( + ErrIllegalState, + "runtime provided bad receiver address {}", + rt.message().receiver() + )); }; // Regenerate challenge randomness, which must match that generated for the proof. @@ -3241,7 +3281,11 @@ where let miner_actor_id: u64 = if let Payload::ID(i) = rt.message().receiver().payload() { *i } else { - panic!("could not provide ID address"); + return Err(actor_error!( + ErrIllegalState, + "runtime provided non ID receiver address {}", + rt.message().receiver() + )); }; let entropy = rt.message().receiver().marshal_cbor().map_err(|e| { @@ -3387,7 +3431,6 @@ where let resolved = rt .resolve_address(&raw)? .ok_or_else(|| actor_error!(ErrIllegalArgument, "unable to resolve address: {}", raw))?; - assert!(resolved.protocol() == Protocol::ID); let owner_code = rt .get_actor_code_cid(&resolved)? @@ -3413,7 +3456,6 @@ where let resolved = rt .resolve_address(&raw)? .ok_or_else(|| actor_error!(ErrIllegalArgument, "unable to resolve address: {}", raw))?; - assert!(resolved.protocol() == Protocol::ID); let worker_code = rt .get_actor_code_cid(&resolved)? @@ -3512,13 +3554,10 @@ fn current_proving_period_start(current_epoch: ChainEpoch, offset: ChainEpoch) - }; let period_start = current_epoch - period_progress; - assert!(period_start <= current_epoch); period_start } fn current_deadline_index(current_epoch: ChainEpoch, period_start: ChainEpoch) -> usize { - assert!(current_epoch >= period_start); - ((current_epoch - period_start) / WPOST_CHALLENGE_WINDOW) as usize } diff --git a/vm/actor/src/builtin/miner/monies.rs b/vm/actor/src/builtin/miner/monies.rs index fe0bd1dc6032..89f9980a7af5 100644 --- a/vm/actor/src/builtin/miner/monies.rs +++ b/vm/actor/src/builtin/miner/monies.rs @@ -245,10 +245,7 @@ pub fn consensus_fault_penalty(this_epoch_reward: TokenAmount) -> TokenAmount { } /// Returns the amount of a reward to vest, and the vesting schedule, for a reward amount. -pub fn locked_reward_from_reward( - reward: TokenAmount, - nv: NetworkVersion, -) -> (TokenAmount, &'static VestSpec) { +pub fn locked_reward_from_reward(reward: TokenAmount) -> (TokenAmount, &'static VestSpec) { let lock_amount = (reward * &*LOCKED_REWARD_FACTOR_NUM).div_floor(&*LOCKED_REWARD_FACTOR_DENOM); (lock_amount, &REWARD_VESTING_SPEC) } From 4f8e14e853d24a0346a777a681fc6b2d1ea7f272 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 24 Feb 2021 10:53:17 -0500 Subject: [PATCH 13/35] fmt and compile --- vm/actor/src/builtin/miner/deadline_state.rs | 25 +++++++++-------- vm/actor/src/builtin/miner/mod.rs | 24 ++++++++-------- vm/actor/src/builtin/miner/state.rs | 29 ++++++++++++-------- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/vm/actor/src/builtin/miner/deadline_state.rs b/vm/actor/src/builtin/miner/deadline_state.rs index e20ecd88c5ac..d3e31372dffd 100644 --- a/vm/actor/src/builtin/miner/deadline_state.rs +++ b/vm/actor/src/builtin/miner/deadline_state.rs @@ -418,7 +418,7 @@ impl Deadline { // This case will usually happen zero times. // It would require adding more than a full partition in one go // to happen more than once. - Partition::new(&Amt::::new(&store).flush()?)? + Partition::new(store)? } }; @@ -1010,10 +1010,10 @@ impl Deadline { .ok_or_else(|| format!("failed to find partition {}", part_idx))?; // Record sectors for proof verification - all_sectors.push(partition_snapshot.sectors); - all_ignored.push(partition_snapshot.faults); - all_ignored.push(partition_snapshot.terminated); - all_ignored.push(partition_snapshot.unproven); + all_sectors.push(partition_snapshot.sectors.clone()); + all_ignored.push(partition_snapshot.faults.clone()); + all_ignored.push(partition_snapshot.terminated.clone()); + all_ignored.push(partition_snapshot.unproven.clone()); // Record active sectors for marking faults. let active = partition_snapshot.active_sectors(); @@ -1101,7 +1101,7 @@ impl Deadline { fault_expiration: ChainEpoch, post_partitions: &mut [PoStPartition], ) -> Result> { - let partition_indexes = BitField::new(); + let mut partition_indexes = BitField::new(); for p in post_partitions.iter() { partition_indexes.set(p.index); } @@ -1236,18 +1236,19 @@ impl Deadline { pub fn record_post_proofs( &mut self, store: &BS, - partitions: BitField, - proofs: Vec, + partitions: &BitField, + proofs: &[PoStProof], ) -> Result<(), Box> { - let proof_arr = self + let mut proof_arr = self .optimistic_proofs_amt(store) .map_err(|e| e.downcast_wrap("failed to load post proofs"))?; proof_arr .set( proof_arr.count(), + // TODO: Can we do this with out cloning? WindowedPoSt { - partitions: partitions, - proofs: proofs, + partitions: partitions.clone(), + proofs: proofs.to_vec(), }, ) .map_err(|e| e.downcast_wrap("failed to store proof"))?; @@ -1266,7 +1267,7 @@ impl Deadline { store: &BS, idx: u64, ) -> Result<(BitField, Vec), Box> { - let proof_arr = self + let mut proof_arr = self .optimistic_proofs_snapshot_amt(store) .map_err(|e| e.downcast_wrap("failed to load post proofs snapshot amt"))?; // Extract and remove the proof from the proofs array, leaving a hole. diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index ba37f8c2b79b..7577ccd51293 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -611,7 +611,7 @@ impl Actor { // If we're not recovering power, record the proof for optimistic verification. if post_result.recovered_power.is_zero() { deadline - .record_post_proofs(rt.store(), post_result.partitions, params.proofs) + .record_post_proofs(rt.store(), &post_result.partitions, ¶ms.proofs) .map_err(|e| { e.downcast_default( ExitCode::ErrIllegalState, @@ -631,9 +631,7 @@ impl Actor { ) })?; verify_windowed_post(rt, current_deadline.challenge, §or_infos, params.proofs) - .map_err(|e| { - e.downcast_default(ExitCode::ErrIllegalArgument, "window post failed") - })?; + .map_err(|e| e.wrap("window post failed"))?; } let deadline_idx = params.deadline; @@ -764,12 +762,12 @@ impl Actor { rt, &[market::SectorDeals { sector_expiry: params.expiration, - deal_ids: params.deal_ids, + deal_ids: params.deal_ids.clone(), }], rt.curr_epoch(), params.expiration, )?; - let deal_weight = deal_weights.sectors[0]; + let deal_weight = &deal_weights.sectors[0]; let mut fee_to_burn = TokenAmount::from(0); let newly_vested = rt.transaction(|state: &mut State, rt| { let newly_vested = TokenAmount::from(0); @@ -1502,10 +1500,10 @@ impl Actor { .map_err(|e| e.wrap(format!("failed to load deadline {}", deadline_idx)))?; let mut partitions = deadline.partitions_amt(store).map_err(|e| { - e.wrap(format!( - "failed to load partitions for deadline {}", - deadline_idx - )) + e.downcast_default( + ExitCode::ErrIllegalState, + format!("failed to load partitions for deadline {}", deadline_idx), + ) })?; let quant = state.quant_spec_for_deadline(deadline_idx); @@ -2599,7 +2597,7 @@ impl Actor { )) })?; - let amount_withdrawn = std::cmp::min(available_balance, params.amount_requested); + let amount_withdrawn = std::cmp::min(&available_balance, ¶ms.amount_requested); assert!(!amount_withdrawn.is_negative()); if amount_withdrawn.is_negative() { return Err(actor_error!( @@ -2608,7 +2606,7 @@ impl Actor { amount_withdrawn )); } - if amount_withdrawn > available_balance { + if amount_withdrawn > &available_balance { return Err(actor_error!( ErrIllegalState, "amount to withdraw {} < available {}", @@ -2622,7 +2620,7 @@ impl Actor { info.owner, METHOD_SEND, Serialized::default(), - amount_withdrawn, + amount_withdrawn.clone(), )?; } diff --git a/vm/actor/src/builtin/miner/state.rs b/vm/actor/src/builtin/miner/state.rs index 1372a05d8dbf..6f322d5d5669 100644 --- a/vm/actor/src/builtin/miner/state.rs +++ b/vm/actor/src/builtin/miner/state.rs @@ -119,7 +119,7 @@ impl State { ) })?; let empty_precommits_expiry_array = - Amt::<_, BS>::new_with_bit_width(store, PRECOMMIT_EXPIRY_AMT_BITWIDTH) + Amt::::new_with_bit_width(store, PRECOMMIT_EXPIRY_AMT_BITWIDTH) .flush() .map_err(|e| { e.downcast_default( @@ -127,14 +127,15 @@ impl State { "failed to construct empty precommits array", ) })?; - let empty_sectors_array = Amt::<_, BS>::new_with_bit_width(store, SECTORS_AMT_BITWIDTH) - .flush() - .map_err(|e| { - e.downcast_default( - ExitCode::ErrIllegalState, - "failed to construct sectors array", - ) - })?; + let empty_sectors_array = + Amt::::new_with_bit_width(store, SECTORS_AMT_BITWIDTH) + .flush() + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to construct sectors array", + ) + })?; let empty_bitfield = store.put(&BitField::new(), Blake2b256).map_err(|e| { e.downcast_default( ExitCode::ErrIllegalState, @@ -314,13 +315,17 @@ impl State { ) -> Result<(), Box> { let mut precommitted = make_map_with_root_and_bitwidth(&self.pre_committed_sectors, store, HAMT_BIT_WIDTH)?; + let sector_number = info.info.sector_number; let modified = precommitted - .set_if_absent(u64_key(info.info.sector_number), info) + .set_if_absent(u64_key(sector_number), info) .map_err(|e| { - e.downcast_wrap(format!("failed to store pre-commitment for {:?}", info)) + e.downcast_wrap(format!( + "failed to store pre-commitment for {:?}", + sector_number + )) })?; if !modified { - return Err(format!("sector {} already pre-commited", info.info.sector_number).into()); + return Err(format!("sector {} already pre-commited", sector_number).into()); } self.pre_committed_sectors = precommitted.flush()?; Ok(()) From 9c3b2db781f0c9defde64d540cd41d87be85f29d Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 24 Feb 2021 10:59:06 -0500 Subject: [PATCH 14/35] setup dispute windows post params --- vm/actor/src/builtin/miner/mod.rs | 11 +++++++++++ vm/actor/src/builtin/miner/types.rs | 8 +++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 7577ccd51293..8b291e7ed650 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -670,6 +670,17 @@ impl Actor { Ok(()) } + fn dispute_windowed_post( + rt: &mut RT, + params: DisputeWindowedPoStParams, + ) -> Result<(), ActorError> + where + BS: BlockStore, + RT: Runtime, + { + todo!() + } + /// Proposals must be posted on chain via sma.PublishStorageDeals before PreCommitSector. /// Optimization: PreCommitSector could contain a list of deals that are not published yet. /// TODO: This should NOT WORK. Changes made here are solely to get the Market Actor updated an compiling diff --git a/vm/actor/src/builtin/miner/types.rs b/vm/actor/src/builtin/miner/types.rs index 87966084d1ae..a8b62e755b63 100644 --- a/vm/actor/src/builtin/miner/types.rs +++ b/vm/actor/src/builtin/miner/types.rs @@ -273,7 +273,7 @@ pub struct SectorOnChainInfo { pub replaced_day_reward: TokenAmount, } -#[derive(Debug, PartialEq, Clone, Serialize_tuple, Deserialize_tuple)] +#[derive(Debug, PartialEq, Copy, Clone, Serialize_tuple, Deserialize_tuple)] pub struct Fault { pub miner: Address, pub fault: ChainEpoch, @@ -287,3 +287,9 @@ pub struct ApplyRewardParams { #[serde(with = "bigint_ser")] pub penalty: TokenAmount, } + +#[derive(Debug, PartialEq, Clone, Copy, Serialize_tuple, Deserialize_tuple)] +pub struct DisputeWindowedPoStParams { + deadline: u64, + post_index: u64, // only one is allowed at a time to avoid loading too many sector infos. +} From 8bc4e7b50b97456a1eaa33a01b7ab8032109d07f Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 25 Feb 2021 01:09:07 -0500 Subject: [PATCH 15/35] dispute windowed post --- vm/actor/src/builtin/miner/deadline_state.rs | 8 +- vm/actor/src/builtin/miner/mod.rs | 219 ++++++++++++++++++- vm/actor/src/builtin/miner/monies.rs | 4 +- vm/actor/src/builtin/miner/policy.rs | 16 +- vm/actor/src/builtin/miner/types.rs | 4 +- 5 files changed, 239 insertions(+), 12 deletions(-) diff --git a/vm/actor/src/builtin/miner/deadline_state.rs b/vm/actor/src/builtin/miner/deadline_state.rs index d3e31372dffd..c6d9cd141d2c 100644 --- a/vm/actor/src/builtin/miner/deadline_state.rs +++ b/vm/actor/src/builtin/miner/deadline_state.rs @@ -166,10 +166,10 @@ pub struct WindowedPoSt { #[derive(Serialize_tuple, Deserialize_tuple)] pub struct DisputeInfo { - all_sector_nos: BitField, - ignored_sector_nos: BitField, - disputed_sectors: PartitionSectorMap, - disputed_power: PowerPair, + pub all_sector_nos: BitField, + pub ignored_sector_nos: BitField, + pub disputed_sectors: PartitionSectorMap, + pub disputed_power: PowerPair, } impl Deadline { diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 8b291e7ed650..117835e23fec 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -121,6 +121,7 @@ pub enum Method { ConfirmUpdateWorkerKey = 21, RepayDebt = 22, ChangeOwnerAddress = 23, + DisputeWindowedPoSt = 24, } /// Miner Actor @@ -678,7 +679,217 @@ impl Actor { BS: BlockStore, RT: Runtime, { - todo!() + rt.validate_immediate_caller_type(CALLER_TYPES_SIGNABLE.iter())?; + let reporter = *rt.message().caller(); + + if params.deadline >= WPOST_PERIOD_DEADLINES as usize { + return Err(actor_error!( + ErrIllegalArgument, + "invalid deadline {} of {}", + params.deadline, + WPOST_PERIOD_DEADLINES + )); + } + let current_epoch = rt.curr_epoch(); + + // Note: these are going to be slightly inaccurate as time + // will have moved on from when the post was actually + // submitted. + // + // However, these are estimates _anyways_. + let epoch_reward = request_current_epoch_block_reward(rt)?; + let power_total = request_current_total_power(rt)?; + + let (pledge_delta, mut to_burn, power_delta, to_reward) = + rt.transaction(|st: &mut State, rt| { + if !deadline_available_for_optimistic_post_dispute( + st.proving_period_start, + params.deadline, + current_epoch, + ) { + return Err(actor_error!( + ErrIllegalState, + "can only dispute window posts during the dispute window\ + ({} epochs after the challenge window closes)", + WPOST_DISPUTE_WINDOW + )); + } + + let info = get_miner_info(rt.store(), st)?; + let mut penalized_power = PowerPair::zero(); + + // --- check proof --- + + // Find the proving period start for the deadline in question. + let mut pp_start = st.proving_period_start; + if st.current_deadline < params.deadline { + pp_start -= WPOST_PROVING_PERIOD + } + let target_deadline = new_deadline_info(pp_start, params.deadline, current_epoch); + // Load the target deadline + let mut deadlines_current = st + .load_deadlines(rt.store()) + .map_err(|e| e.wrap("failed to load deadlines"))?; + + let mut dl_current = deadlines_current + .load_deadline(rt.store(), params.deadline) + .map_err(|e| e.wrap("failed to load deadline"))?; + + // Take the post from the snapshot for dispute. + // This operation REMOVES the PoSt from the snapshot so + // it can't be disputed again. If this method fails, + // this operation must be rolled back. + let (partitions, proofs) = dl_current + .take_post_proofs(rt.store(), params.post_index) + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to load proof for dispute", + ) + })?; + + // Load the partition info we need for the dispute. + let mut dispute_info = dl_current + .load_partitions_for_dispute(rt.store(), partitions) + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to load partition for dispute", + ) + })?; + + // This includes power that is no longer active (e.g., due to sector terminations). + // It must only be used for penalty calculations, not power adjustments. + let penalised_power = dispute_info.disputed_power.clone(); + + // Load sectors for the dispute. + let sectors = Sectors::load(rt.store(), &st.sectors).map_err(|e| { + e.downcast_default(ExitCode::ErrIllegalState, "failed to load sectors array") + })?; + let sector_infos = sectors + .load_for_proof( + &dispute_info.all_sector_nos, + &dispute_info.ignored_sector_nos, + ) + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + "failed to load sectors to dispute window post", + ) + })?; + + // Check proof, we fail if validation succeeds. + verify_windowed_post(rt, target_deadline.challenge, §or_infos, proofs) + .map_err(|e| { + actor_error!(ErrIllegalArgument, "failed to dispute valid post") + })?; + + // Ok, now we record faults. This always works because + // we don't allow compaction/moving sectors during the + // challenge window. + // + // However, some of these sectors may have been + // terminated. That's fine, we'll skip them. + let fault_expiration_epoch = target_deadline.last() + FAULT_MAX_AGE; + let power_delta = dl_current + .record_faults( + rt.store(), + §ors, + info.sector_size, + quant_spec_for_deadline(&target_deadline), + fault_expiration_epoch, + &mut dispute_info.disputed_sectors, + ) + .map_err(|e| { + e.downcast_default(ExitCode::ErrIllegalState, "failed to declare faults") + })?; + + deadlines_current + .update_deadline(rt.store(), params.deadline, &dl_current) + .map_err(|e| { + e.downcast_default( + ExitCode::ErrIllegalState, + format!("failed to update deadline {}", params.deadline), + ) + })?; + + st.save_deadlines(rt.store(), deadlines_current) + .map_err(|e| { + e.downcast_default(ExitCode::ErrIllegalState, "failed to save deadlines") + })?; + + // --- penalties --- + + // Calculate the base penalty. + let penalty_base = pledge_penalty_for_invalid_windowpost( + &epoch_reward.this_epoch_reward_smoothed, + &power_total.quality_adj_power_smoothed, + &penalized_power.qa, + ); + + // Calculate the target reward. + let reward_target = + reward_for_disputed_window_post(info.window_post_proof_type, penalized_power); + + // Compute the target penalty by adding the + // base penalty to the target reward. We don't + // take reward out of the penalty as the miner + // could end up receiving a substantial + // portion of their fee back as a reward. + let penalty_target = &penalty_base + &reward_target; + st.apply_penalty(&penalty_target) + .map_err(|e| actor_error!(ErrIllegalState, "failed to apply penalty {}", e))?; + let (penalty_from_vesting, penalty_from_balance) = st + .repay_partial_debt_in_priority_order( + rt.store(), + current_epoch, + &rt.current_balance()?, + ) + .map_err(|e| { + e.downcast_default(ExitCode::ErrIllegalState, format!("failed to pay debt")) + })?; + + let to_burn = &penalty_from_vesting + &penalty_from_balance; + + // Now, move as much of the target reward as + // we can from the burn to the reward. + let to_reward = std::cmp::min(&to_burn, &reward_target); + let to_burn = &to_burn - to_reward; + let pledge_delta = -penalty_from_vesting; + + Ok(( + pledge_delta, + to_burn.clone(), + power_delta, + to_reward.clone(), + )) + })?; + + request_update_power(rt, power_delta)?; + if !to_reward.is_zero() { + if let Err(e) = rt.send( + reporter, + METHOD_SEND, + Serialized::default(), + to_reward.clone(), + ) { + log::error!("failed to send reward"); + to_burn += to_reward; + } + } + + burn_funds(rt, to_burn)?; + notify_pledge_changed(rt, &pledge_delta)?; + + let st: State = rt.state()?; + st.check_balance_invariants(&rt.current_balance()?) + .map_err(|e| { + ActorError::new( + ErrBalanceInvariantBroken, + format!("balance invariants broken: {}", e), + ) + })?; + Ok(()) } /// Proposals must be posted on chain via sma.PublishStorageDeals before PreCommitSector. @@ -2804,7 +3015,7 @@ where "failed to add initial pledge {}", pledge_delta ) - }); + })?; // Use unlocked pledge to pay down outstanding fee debt let (penalty_from_vesting, penalty_from_balance) = state @@ -3904,6 +4115,10 @@ impl ActorCode for Actor { Self::change_owner_address(rt, rt.deserialize_params(params)?)?; Ok(Serialized::default()) } + Some(Method::DisputeWindowedPoSt) => { + Self::dispute_windowed_post(rt, rt.deserialize_params(params)?)?; + Ok(Serialized::default()) + } None => Err(actor_error!(SysErrInvalidMethod, "Invalid method")), } } diff --git a/vm/actor/src/builtin/miner/monies.rs b/vm/actor/src/builtin/miner/monies.rs index 89f9980a7af5..ca2cdf14b984 100644 --- a/vm/actor/src/builtin/miner/monies.rs +++ b/vm/actor/src/builtin/miner/monies.rs @@ -45,11 +45,11 @@ lazy_static! { BigInt::from(10_u64.pow(18) / (32 << 30)); /// Base reward for successfully disputing a window posts proofs. - static ref BASE_REWARD_FOR_DISPUTED_WINDOW_POST: BigInt = + pub static ref BASE_REWARD_FOR_DISPUTED_WINDOW_POST: BigInt = BigInt::from(4 * FILECOIN_PRECISION); /// Base penalty for a successful disputed window post proof. - static ref BASE_PENALTY_FOR_DISPUTED_WINDOW_POST: BigInt = + pub static ref BASE_PENALTY_FOR_DISPUTED_WINDOW_POST: BigInt = BigInt::from(20 * FILECOIN_PRECISION); } // FF + 2BR diff --git a/vm/actor/src/builtin/miner/policy.rs b/vm/actor/src/builtin/miner/policy.rs index 2026a7673428..fee67f3f6574 100644 --- a/vm/actor/src/builtin/miner/policy.rs +++ b/vm/actor/src/builtin/miner/policy.rs @@ -1,10 +1,13 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use super::types::SectorOnChainInfo; +use super::{types::SectorOnChainInfo, PowerPair, BASE_REWARD_FOR_DISPUTED_WINDOW_POST}; use crate::{network::*, DealWeight}; use clock::ChainEpoch; -use fil_types::{NetworkVersion, RegisteredSealProof, SectorQuality, SectorSize, StoragePower}; +use fil_types::{ + NetworkVersion, RegisteredPoStProof, RegisteredSealProof, SectorQuality, SectorSize, + StoragePower, +}; use num_bigint::BigUint; use num_bigint::{BigInt, Integer}; use num_traits::Pow; @@ -298,3 +301,12 @@ pub fn reward_for_consensus_slash_report( (collateral * max_reporter_share.numerator).div_floor(&max_reporter_share.denominator), ) } + +// The reward given for successfully disputing a window post. +pub fn reward_for_disputed_window_post( + _proof_type: RegisteredPoStProof, + _disputed_power: PowerPair, +) -> TokenAmount { + // This is currently just the base. In the future, the fee may scale based on the disputed power. + return BASE_REWARD_FOR_DISPUTED_WINDOW_POST.clone(); +} diff --git a/vm/actor/src/builtin/miner/types.rs b/vm/actor/src/builtin/miner/types.rs index a8b62e755b63..11fa0bcba8d7 100644 --- a/vm/actor/src/builtin/miner/types.rs +++ b/vm/actor/src/builtin/miner/types.rs @@ -290,6 +290,6 @@ pub struct ApplyRewardParams { #[derive(Debug, PartialEq, Clone, Copy, Serialize_tuple, Deserialize_tuple)] pub struct DisputeWindowedPoStParams { - deadline: u64, - post_index: u64, // only one is allowed at a time to avoid loading too many sector infos. + pub deadline: usize, + pub post_index: u64, // only one is allowed at a time to avoid loading too many sector infos. } From 06b858d08b004c744adede93b4de4eb53bd21146 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 25 Feb 2021 01:15:12 -0500 Subject: [PATCH 16/35] some warnings --- vm/actor/src/builtin/miner/mod.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 117835e23fec..24c307f84e05 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -716,7 +716,7 @@ impl Actor { } let info = get_miner_info(rt.store(), st)?; - let mut penalized_power = PowerPair::zero(); + let mut penalised_power = PowerPair::zero(); // --- check proof --- @@ -760,7 +760,7 @@ impl Actor { // This includes power that is no longer active (e.g., due to sector terminations). // It must only be used for penalty calculations, not power adjustments. - let penalised_power = dispute_info.disputed_power.clone(); + penalised_power = dispute_info.disputed_power.clone(); // Load sectors for the dispute. let sectors = Sectors::load(rt.store(), &st.sectors).map_err(|e| { @@ -824,12 +824,12 @@ impl Actor { let penalty_base = pledge_penalty_for_invalid_windowpost( &epoch_reward.this_epoch_reward_smoothed, &power_total.quality_adj_power_smoothed, - &penalized_power.qa, + &penalised_power.qa, ); // Calculate the target reward. let reward_target = - reward_for_disputed_window_post(info.window_post_proof_type, penalized_power); + reward_for_disputed_window_post(info.window_post_proof_type, penalised_power); // Compute the target penalty by adding the // base penalty to the target reward. We don't @@ -873,7 +873,7 @@ impl Actor { Serialized::default(), to_reward.clone(), ) { - log::error!("failed to send reward"); + log::error!("failed to send reward: {}", e); to_burn += to_reward; } } @@ -1222,10 +1222,9 @@ impl Actor { let precommit = st .get_precommitted_sector(rt.store(), sector_number) .map_err(|e| { - actor_error!( - ErrIllegalState, - "failed to load pre-committed sector {}", - sector_number + e.downcast_default( + ExitCode::ErrIllegalState, + format!("failed to load pre-committed sector {}", sector_number), ) })? .ok_or_else(|| actor_error!(ErrNotFound, "no pre-commited sector {}", sector_number))?; @@ -3576,7 +3575,7 @@ where let mut empty_result = VerifyDealsForActivationReturn { sectors: Vec::with_capacity(sectors.len()), }; - for i in 0..sectors.len() { + for _ in 0..sectors.len() { empty_result.sectors.push(market::SectorWeights { deal_space: 0, deal_weight: 0.into(), From a00ac6aa0dd56ebded1ef0cfb8ca9ed8ac950585 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 25 Feb 2021 15:25:14 -0500 Subject: [PATCH 17/35] cleanup --- types/src/sector/registered_proof.rs | 44 +++++++++++++++++++++++++ vm/actor/src/builtin/miner/mod.rs | 48 +++++++++++++++------------- vm/actor/src/builtin/miner/monies.rs | 2 +- vm/actor/src/builtin/miner/state.rs | 18 ++++++----- 4 files changed, 80 insertions(+), 32 deletions(-) diff --git a/types/src/sector/registered_proof.rs b/types/src/sector/registered_proof.rs index b0fd49117f2b..32e9e312b694 100644 --- a/types/src/sector/registered_proof.rs +++ b/types/src/sector/registered_proof.rs @@ -66,6 +66,19 @@ impl RegisteredSealProof { let epochs_per_year = 1_262_277; 5 * epochs_per_year } + + pub fn proof_size(self) -> Result { + use RegisteredSealProof::*; + match self { + StackedDRG2KiBV1 | StackedDRG512MiBV1 | StackedDRG8MiBV1 | StackedDRG2KiBV1P1 + | StackedDRG512MiBV1P1 | StackedDRG8MiBV1P1 => Ok(192), + + StackedDRG32GiBV1 | StackedDRG64GiBV1 | StackedDRG32GiBV1P1 | StackedDRG64GiBV1P1 => { + Ok(1920) + } + Invalid(i) => Err(format!("unsupported proof type: {}", i)), + } + } } /// Proof of spacetime type, indicating version and sector size of the proof. @@ -121,6 +134,37 @@ impl RegisteredPoStProof { Invalid(i) => Err(format!("unsupported proof type: {}", i)), } } + + pub fn proof_size(self) -> Result { + use RegisteredPoStProof::*; + match self { + StackedDRGWinning2KiBV1 + | StackedDRGWinning8MiBV1 + | StackedDRGWinning512MiBV1 + | StackedDRGWinning32GiBV1 + | StackedDRGWinning64GiBV1 + | StackedDRGWindow2KiBV1 + | StackedDRGWindow8MiBV1 + | StackedDRGWindow512MiBV1 + | StackedDRGWindow32GiBV1 + | StackedDRGWindow64GiBV1 => Ok(192), + Invalid(i) => Err(format!("unsupported proof type: {}", i)), + } + } + /// Returns the partition size, in sectors, associated with a proof type. + /// The partition size is the number of sectors proven in a single PoSt proof. + pub fn window_post_partitions_sector(self) -> Result { + // Resolve to post proof and then compute size from that. + use RegisteredPoStProof::*; + match self { + StackedDRGWinning64GiBV1 | StackedDRGWindow64GiBV1 => Ok(2300), + StackedDRGWinning32GiBV1 | StackedDRGWindow32GiBV1 => Ok(2349), + StackedDRGWinning2KiBV1 | StackedDRGWindow2KiBV1 => Ok(2), + StackedDRGWinning8MiBV1 | StackedDRGWindow8MiBV1 => Ok(2), + StackedDRGWinning512MiBV1 | StackedDRGWindow512MiBV1 => Ok(2), + Invalid(i) => Err(format!("unsupported proof type: {}", i)), + } + } } impl RegisteredSealProof { diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 24c307f84e05..7ade78b4cfbb 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -33,7 +33,7 @@ pub use vesting_state::*; use crate::{ account::Method as AccountMethod, - actor_error, make_empty_map, + actor_error, market::{self, ActivateDealsParams}, power::MAX_MINER_PROVE_COMMITS_PER_EPOCH, }; @@ -56,7 +56,7 @@ use crate::{ ActorDowncast, }; use address::{Address, Payload, Protocol}; -use bitfield::{BitField, UnvalidatedBitField, Validate}; +use bitfield::{UnvalidatedBitField, Validate}; use byteorder::{BigEndian, ByteOrder, WriteBytesExt}; use cid::{Cid, Code::Blake2b256, Prefix}; use clock::ChainEpoch; @@ -65,11 +65,10 @@ use crypto::DomainSeparationTag::{ }; use encoding::{BytesDe, Cbor}; use fil_types::{ - deadlines::DeadlineInfo, InteractiveSealRandomness, NetworkVersion, PoStProof, PoStRandomness, + deadlines::DeadlineInfo, InteractiveSealRandomness, PoStProof, PoStRandomness, RegisteredSealProof, SealRandomness as SealRandom, SealVerifyInfo, SealVerifyParams, SectorID, - SectorInfo, SectorNumber, SectorSize, WindowPoStVerifyInfo, HAMT_BIT_WIDTH, MAX_SECTOR_NUMBER, + SectorInfo, SectorNumber, SectorSize, WindowPoStVerifyInfo, MAX_SECTOR_NUMBER, }; -use ipld_amt::Amt; use ipld_blockstore::BlockStore; use num_bigint::bigint_ser::BigIntSer; use num_bigint::BigInt; @@ -125,7 +124,6 @@ pub enum Method { } /// Miner Actor -/// TODO: This is now broken and not v3 ready because of the changes that needed to be made /// here in order to update the Power Actor to v3. pub struct Actor; @@ -443,9 +441,14 @@ impl Actor { let post_result = rt.transaction(|state: &mut State, rt| { let info = get_miner_info(rt.store(), state)?; - // TODO: NEED TO ACTUALLY HANDLE THIS PROPERLY IN CASE OF DIFFERENT PROOF SIZE - // let proof_size = info.window_post_proof_type; - let max_proof_size = 192; + + let max_proof_size = info.window_post_proof_type.proof_size().map_err(|e| { + actor_error!( + ErrIllegalState, + "failed to determine max window post proof size: {}", + e + ) + })?; rt.validate_immediate_caller_is( info.control_addresses @@ -716,8 +719,6 @@ impl Actor { } let info = get_miner_info(rt.store(), st)?; - let mut penalised_power = PowerPair::zero(); - // --- check proof --- // Find the proving period start for the deadline in question. @@ -760,7 +761,7 @@ impl Actor { // This includes power that is no longer active (e.g., due to sector terminations). // It must only be used for penalty calculations, not power adjustments. - penalised_power = dispute_info.disputed_power.clone(); + let penalised_power = dispute_info.disputed_power.clone(); // Load sectors for the dispute. let sectors = Sectors::load(rt.store(), &st.sectors).map_err(|e| { @@ -780,7 +781,7 @@ impl Actor { // Check proof, we fail if validation succeeds. verify_windowed_post(rt, target_deadline.challenge, §or_infos, proofs) - .map_err(|e| { + .map_err(|_e| { actor_error!(ErrIllegalArgument, "failed to dispute valid post") })?; @@ -894,7 +895,6 @@ impl Actor { /// Proposals must be posted on chain via sma.PublishStorageDeals before PreCommitSector. /// Optimization: PreCommitSector could contain a list of deals that are not published yet. - /// TODO: This should NOT WORK. Changes made here are solely to get the Market Actor updated an compiling fn pre_commit_sector( rt: &mut RT, params: PreCommitSectorParams, @@ -986,8 +986,6 @@ impl Actor { sector_expiry: params.expiration, deal_ids: params.deal_ids.clone(), }], - rt.curr_epoch(), - params.expiration, )?; let deal_weight = &deal_weights.sectors[0]; let mut fee_to_burn = TokenAmount::from(0); @@ -1229,9 +1227,14 @@ impl Actor { })? .ok_or_else(|| actor_error!(ErrNotFound, "no pre-commited sector {}", sector_number))?; - // TODO: NEED TO ACTUALLY IMPLEMENT THE PROOFSIZE FUNCTION - // let max_proof_size = precommit.info.seal_proof.proof_size() - let max_proof_size = 192; + let max_proof_size = precommit.info.seal_proof.proof_size().map_err(|e| { + actor_error!( + ErrIllegalState, + "failed to determine max proof size for sector {}: {}", + sector_number, + e + ) + })?; if params.proof.len() > max_proof_size { return Err(actor_error!( ErrIllegalArgument, @@ -3011,8 +3014,9 @@ where state.add_initial_pledge(&pledge_delta).map_err(|e| { actor_error!( ErrIllegalState, - "failed to add initial pledge {}", - pledge_delta + "failed to add initial pledge {}: {}", + pledge_delta, + e ) })?; @@ -3559,8 +3563,6 @@ where fn request_deal_weights( rt: &mut RT, sectors: &[market::SectorDeals], - sector_start: ChainEpoch, - sector_expiry: ChainEpoch, ) -> Result where BS: BlockStore, diff --git a/vm/actor/src/builtin/miner/monies.rs b/vm/actor/src/builtin/miner/monies.rs index ca2cdf14b984..908ab758963b 100644 --- a/vm/actor/src/builtin/miner/monies.rs +++ b/vm/actor/src/builtin/miner/monies.rs @@ -9,7 +9,7 @@ use crate::{ TokenAmount, EXPECTED_LEADERS_PER_EPOCH, }; use clock::ChainEpoch; -use fil_types::{NetworkVersion, StoragePower, FILECOIN_PRECISION}; +use fil_types::{StoragePower, FILECOIN_PRECISION}; use num_bigint::{BigInt, Integer}; use num_traits::Zero; use std::cmp; diff --git a/vm/actor/src/builtin/miner/state.rs b/vm/actor/src/builtin/miner/state.rs index 6f322d5d5669..9a58bfccd738 100644 --- a/vm/actor/src/builtin/miner/state.rs +++ b/vm/actor/src/builtin/miner/state.rs @@ -6,9 +6,7 @@ use super::{ quant_spec_for_deadline, types::*, BitFieldQueue, Deadline, DeadlineSectorMap, Deadlines, PowerPair, Sectors, TerminationResult, VestingFunds, }; -use crate::{ - make_empty_map, make_map_with_root, make_map_with_root_and_bitwidth, u64_key, ActorDowncast, -}; +use crate::{make_empty_map, make_map_with_root_and_bitwidth, u64_key, ActorDowncast}; use address::Address; use bitfield::BitField; use cid::{Cid, Code::Blake2b256}; @@ -553,7 +551,7 @@ impl State { let deadline = deadline_vec[deadline_idx].as_mut().unwrap(); // The power returned from AddSectors is ignored because it's not activated (proven) yet. - let mut proven = false; + let proven = false; deadline.add_sectors( store, partition_size, @@ -1208,10 +1206,14 @@ impl MinerInfo { peer_id: Vec, multi_address: Vec, window_post_proof_type: RegisteredPoStProof, - ) -> Result { - let sector_size = window_post_proof_type.sector_size()?; - // TODO: THIS NEEDS TO BE UPDATED WHEN UPDATING V3 ACTORS - let window_post_partition_sectors = 2349; + ) -> Result { + let sector_size = window_post_proof_type + .sector_size() + .map_err(|e| actor_error!(ErrIllegalArgument, "invalid sector size: {}", e))?; + + let window_post_partition_sectors = window_post_proof_type + .window_post_partitions_sector() + .map_err(|e| actor_error!(ErrIllegalArgument, "invalid sector size: {}", e))?; Ok(Self { owner, From 1b849b4f76453028112b8e7e2ed69116cd55fc90 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 25 Feb 2021 15:47:16 -0500 Subject: [PATCH 18/35] fini --- vm/actor/src/builtin/miner/deadline_state.rs | 10 +++++----- vm/actor/src/builtin/miner/deadlines.rs | 8 ++++---- vm/actor/src/builtin/miner/mod.rs | 16 +++++----------- vm/actor/src/builtin/miner/monies.rs | 2 +- vm/actor/src/builtin/miner/policy.rs | 2 +- 5 files changed, 16 insertions(+), 22 deletions(-) diff --git a/vm/actor/src/builtin/miner/deadline_state.rs b/vm/actor/src/builtin/miner/deadline_state.rs index c6d9cd141d2c..eadaba14b937 100644 --- a/vm/actor/src/builtin/miner/deadline_state.rs +++ b/vm/actor/src/builtin/miner/deadline_state.rs @@ -1032,9 +1032,9 @@ impl Deadline { let all_ignored_nos = BitField::union(&all_ignored); Ok(DisputeInfo { - all_sector_nos: all_sector_nos, - disputed_sectors: disputed_sectors, - disputed_power: disputed_power, + all_sector_nos, + disputed_sectors, + disputed_power, ignored_sector_nos: all_ignored_nos, }) } @@ -1063,7 +1063,7 @@ impl Deadline { if self.optimistic_post_submissions != self.optimistic_post_submissions_snapshot { return true; } - return false; + false } } @@ -1117,7 +1117,7 @@ impl Deadline { // First check to see if we're proving any already proven partitions. // This is faster than checking one by one. let already_proven = &self.partitions_posted & &partition_indexes; - if already_proven.len() == 0 { + if already_proven.is_empty() { return Err(format!("parition already proven: {:?}", already_proven).into()); } diff --git a/vm/actor/src/builtin/miner/deadlines.rs b/vm/actor/src/builtin/miner/deadlines.rs index 2c47e6945098..dd13ab7a8f76 100644 --- a/vm/actor/src/builtin/miner/deadlines.rs +++ b/vm/actor/src/builtin/miner/deadlines.rs @@ -101,8 +101,8 @@ pub fn deadline_available_for_optimistic_post_dispute( let dl_info = new_deadline_info(proving_period_start, deadline_idx, current_epoch).next_not_elapsed(); - return !dl_info.is_open() - && current_epoch < (dl_info.close - WPOST_PROVING_PERIOD) + WPOST_DISPUTE_WINDOW; + !dl_info.is_open() + && current_epoch < (dl_info.close - WPOST_PROVING_PERIOD) + WPOST_DISPUTE_WINDOW } // Returns true if the given deadline may compacted in the current epoch. @@ -117,10 +117,10 @@ pub fn deadline_available_for_compaction( deadline_idx: usize, current_epoch: ChainEpoch, ) -> bool { - return deadline_is_mutable(proving_period_start, deadline_idx, current_epoch) + deadline_is_mutable(proving_period_start, deadline_idx, current_epoch) && !deadline_available_for_optimistic_post_dispute( proving_period_start, deadline_idx, current_epoch, - ); + ) } diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 7ade78b4cfbb..60f86b31e935 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -601,7 +601,7 @@ impl Actor { // Make sure we actually proved something. let proven_sectors = &post_result.sectors - &post_result.ignored_sectors; - if proven_sectors.len() == 0 { + if proven_sectors.is_empty() { // Abort verification if all sectors are (now) faults. There's nothing to prove. // It's not rational for a miner to submit a Window PoSt marking *all* non-faulty sectors as skipped, // since that will just cause them to pay a penalty at deadline end that would otherwise be zero @@ -847,7 +847,7 @@ impl Actor { &rt.current_balance()?, ) .map_err(|e| { - e.downcast_default(ExitCode::ErrIllegalState, format!("failed to pay debt")) + e.downcast_default(ExitCode::ErrIllegalState, "failed to pay debt") })?; let to_burn = &penalty_from_vesting + &penalty_from_balance; @@ -858,12 +858,7 @@ impl Actor { let to_burn = &to_burn - to_reward; let pledge_delta = -penalty_from_vesting; - Ok(( - pledge_delta, - to_burn.clone(), - power_delta, - to_reward.clone(), - )) + Ok((pledge_delta, to_burn, power_delta, to_reward.clone())) })?; request_update_power(rt, power_delta)?; @@ -3589,7 +3584,7 @@ where let serialized = rt.send( *STORAGE_MARKET_ACTOR_ADDR, MarketMethod::VerifyDealsForActivation as u64, - Serialized::serialize(VerifyDealsForActivationParamsRef { sectors: sectors })?, + Serialized::serialize(VerifyDealsForActivationParamsRef { sectors })?, TokenAmount::zero(), )?; @@ -3774,8 +3769,7 @@ fn current_proving_period_start(current_epoch: ChainEpoch, offset: ChainEpoch) - WPOST_PROVING_PERIOD - (offset - curr_modulus) }; - let period_start = current_epoch - period_progress; - period_start + current_epoch - period_progress } fn current_deadline_index(current_epoch: ChainEpoch, period_start: ChainEpoch) -> usize { diff --git a/vm/actor/src/builtin/miner/monies.rs b/vm/actor/src/builtin/miner/monies.rs index 908ab758963b..8a71c14fc007 100644 --- a/vm/actor/src/builtin/miner/monies.rs +++ b/vm/actor/src/builtin/miner/monies.rs @@ -50,7 +50,7 @@ lazy_static! { /// Base penalty for a successful disputed window post proof. pub static ref BASE_PENALTY_FOR_DISPUTED_WINDOW_POST: BigInt = - BigInt::from(20 * FILECOIN_PRECISION); + BigInt::from(FILECOIN_PRECISION) * 20; } // FF + 2BR const INVALID_WINDOW_POST_PROJECTION_PERIOD: ChainEpoch = diff --git a/vm/actor/src/builtin/miner/policy.rs b/vm/actor/src/builtin/miner/policy.rs index fee67f3f6574..19aea2f3fddd 100644 --- a/vm/actor/src/builtin/miner/policy.rs +++ b/vm/actor/src/builtin/miner/policy.rs @@ -308,5 +308,5 @@ pub fn reward_for_disputed_window_post( _disputed_power: PowerPair, ) -> TokenAmount { // This is currently just the base. In the future, the fee may scale based on the disputed power. - return BASE_REWARD_FOR_DISPUTED_WINDOW_POST.clone(); + BASE_REWARD_FOR_DISPUTED_WINDOW_POST.clone() } From e75a655d2b7843e1fa5ef8bb0a36206445e78e95 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 25 Feb 2021 16:05:19 -0500 Subject: [PATCH 19/35] update actors v2 --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f93e02bcacdc..29f6097e3fa1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ "fil_clock", "fil_types", "forest_actor 0.1.5", - "forest_actor 1.0.0", + "forest_actor 1.0.2", "forest_actor 2.0.0", "forest_address", "forest_bigint", @@ -2261,9 +2261,9 @@ dependencies = [ [[package]] name = "forest_actor" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "772779d4eca15c0ce0da8e22543a2d9eca384bb31c3a0d762137eed46f5fcb10" +checksum = "1bbded62add26ba31c27e565b663802ca77ad669df593fa1209df868ef3caa74" dependencies = [ "ahash 0.6.2", "base64 0.13.0", From 442a5aac7248343d58c69fab512075fd20afad8c Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Mon, 1 Mar 2021 13:14:33 -0500 Subject: [PATCH 20/35] update to v3 --- vm/actor/src/builtin/paych/mod.rs | 10 ++++++---- vm/actor/src/builtin/paych/types.rs | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/vm/actor/src/builtin/paych/mod.rs b/vm/actor/src/builtin/paych/mod.rs index 1438cff7f71d..1f815b6e4aa0 100644 --- a/vm/actor/src/builtin/paych/mod.rs +++ b/vm/actor/src/builtin/paych/mod.rs @@ -25,7 +25,7 @@ use vm::{ // TODO rename to actor exit code to be used ambiguously (requires new releases) use vm::ExitCode::ErrTooManyProveCommits as ErrChannelStateUpdateAfterSettled; -// * Updated to specs-actors commit: e195950ba98adb8ce362030356bf4a3809b7ec77 (v2.3.2) +// * Updated to specs-actors commit: f47f461b0588e9f0c20c999f6f129c85d669a7aa (v3.0.2) /// Payment Channel actor methods available #[derive(FromPrimitive)] @@ -55,9 +55,11 @@ impl Actor { let from = Self::resolve_account(rt, ¶ms.from)?; - let empty_arr_cid = Amt::<(), _>::new(rt.store()).flush().map_err(|e| { - e.downcast_default(ExitCode::ErrIllegalState, "failed to create empty AMT") - })?; + let empty_arr_cid = Amt::<(), _>::new_with_bit_width(rt.store(), LANE_STATES_AMT_BITWIDTH) + .flush() + .map_err(|e| { + e.downcast_default(ExitCode::ErrIllegalState, "failed to create empty AMT") + })?; rt.create(&State::new(from, to, empty_arr_cid))?; Ok(()) diff --git a/vm/actor/src/builtin/paych/types.rs b/vm/actor/src/builtin/paych/types.rs index d8f6decbc6ce..1953d7a58c64 100644 --- a/vm/actor/src/builtin/paych/types.rs +++ b/vm/actor/src/builtin/paych/types.rs @@ -18,6 +18,7 @@ pub const SETTLE_DELAY: ChainEpoch = EPOCHS_IN_HOUR * 12; // Maximum byte length of a secret that can be submitted with a payment channel update. pub const MAX_SECRET_SIZE: usize = 256; +pub const LANE_STATES_AMT_BITWIDTH: usize = 3; /// Constructor parameters for payment channel actor #[derive(Serialize_tuple, Deserialize_tuple)] pub struct ConstructorParams { From 00daafb05df8e232c5ec845289bfc69e883a160c Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 3 Mar 2021 12:05:36 -0500 Subject: [PATCH 21/35] gettin ready for testing --- types/networks/src/mainnet/mod.rs | 8 +++++--- vm/interpreter/src/vm.rs | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/types/networks/src/mainnet/mod.rs b/types/networks/src/mainnet/mod.rs index c47f58f94a51..e448a9768a1f 100644 --- a/types/networks/src/mainnet/mod.rs +++ b/types/networks/src/mainnet/mod.rs @@ -33,11 +33,13 @@ pub const UPGRADE_PERSIAN_HEIGHT: ChainEpoch = 272400; pub const UPGRADE_ORANGE_HEIGHT: ChainEpoch = 336458; /// Remove burn on window PoSt fork pub const UPGRADE_CLAUS_HEIGHT: ChainEpoch = 343200; -/// V10 network upgrade height TBD -pub const UPGRADE_ACTORS_V3_HEIGHT: ChainEpoch = 999999999; +/// V10 network upgrade height +pub const UPGRADE_ACTORS_V3_HEIGHT: ChainEpoch = 550321; + +pub const UPGRADE_PLACEHOLDER_HEIGHT: ChainEpoch = 9999999; /// Current network version for the network -pub const NEWEST_NETWORK_VERSION: NetworkVersion = NetworkVersion::V9; +pub const NEWEST_NETWORK_VERSION: NetworkVersion = NetworkVersion::V10; /// Bootstrap peer ids pub const DEFAULT_BOOTSTRAP: &[&str] = &[ diff --git a/vm/interpreter/src/vm.rs b/vm/interpreter/src/vm.rs index 5fd5ec5c9a62..b2845e186cc9 100644 --- a/vm/interpreter/src/vm.rs +++ b/vm/interpreter/src/vm.rs @@ -20,7 +20,7 @@ use forest_encoding::Cbor; use ipld_blockstore::BlockStore; use log::debug; use message::{ChainMessage, Message, MessageReceipt, UnsignedMessage}; -use networks::{UPGRADE_ACTORS_V3_HEIGHT, UPGRADE_CLAUS_HEIGHT}; +use networks::{UPGRADE_CLAUS_HEIGHT, UPGRADE_PLACEHOLDER_HEIGHT}; use num_bigint::{BigInt, Sign}; use num_traits::Zero; use state_tree::StateTree; @@ -174,7 +174,7 @@ where #[allow(unreachable_code, unused_variables)] pub fn migrate_state(&mut self, epoch: ChainEpoch) -> Result, Box> { match epoch { - x if x == UPGRADE_ACTORS_V3_HEIGHT => { + x if x == UPGRADE_PLACEHOLDER_HEIGHT => { // need to flush since we run_cron before the migration let prev_state = self.flush()?; // new_state is new state root we can from calling the migration function From c87385b2d37969e36aa084713f930b511881844c Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 3 Mar 2021 15:14:05 -0500 Subject: [PATCH 22/35] log --- blockchain/chain_sync/src/sync_worker.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/blockchain/chain_sync/src/sync_worker.rs b/blockchain/chain_sync/src/sync_worker.rs index db00bf045d24..8fbf9c436c46 100644 --- a/blockchain/chain_sync/src/sync_worker.rs +++ b/blockchain/chain_sync/src/sync_worker.rs @@ -410,6 +410,7 @@ where } let epoch = fts.epoch(); + let fts_key = fts.key().clone(); let mut validations = FuturesUnordered::new(); for b in fts.into_blocks() { @@ -435,7 +436,7 @@ where } } } - info!("Successfully validated tipset at epoch: {}", epoch); + info!("Successfully validated tipset {:?} at epoch: {}", fts_key, epoch); Ok(()) } From c32575d3baf063e3db99dacf8da68c4a45c90a64 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 3 Mar 2021 17:17:05 -0500 Subject: [PATCH 23/35] log worker id and task --- blockchain/chain/src/store/chain_store.rs | 2 +- blockchain/chain_sync/src/sync.rs | 8 ++++---- blockchain/chain_sync/src/sync_worker.rs | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/blockchain/chain/src/store/chain_store.rs b/blockchain/chain/src/store/chain_store.rs index f4edc3f11bba..1e6fe4a31ac8 100644 --- a/blockchain/chain/src/store/chain_store.rs +++ b/blockchain/chain/src/store/chain_store.rs @@ -211,7 +211,7 @@ where let curr_weight = heaviest?; if new_weight > curr_weight { // TODO potentially need to deal with re-orgs here - info!("New heaviest tipset"); + info!("New heaviest tipset: {:?}", ts.key()); self.set_heaviest_tipset(ts).await?; } } diff --git a/blockchain/chain_sync/src/sync.rs b/blockchain/chain_sync/src/sync.rs index 9ea2c8551ccb..4fd9919ed26e 100644 --- a/blockchain/chain_sync/src/sync.rs +++ b/blockchain/chain_sync/src/sync.rs @@ -317,8 +317,8 @@ where /// Spawns a network handler and begins the syncing process. pub async fn start(mut self, worker_tx: Sender>, worker_rx: Receiver>) { - for _ in 0..self.sync_config.worker_tasks { - self.spawn_worker(worker_rx.clone()).await; + for i in 0..self.sync_config.worker_tasks { + self.spawn_worker(worker_rx.clone(), i).await; } // Channels to handle fetching hello tipsets in separate task and return tipset. @@ -410,7 +410,7 @@ where } /// Spawns a new sync worker and pushes the state to the `ChainSyncer` - async fn spawn_worker(&mut self, channel: Receiver>) -> JoinHandle<()> { + async fn spawn_worker(&mut self, channel: Receiver>, id: usize) -> JoinHandle<()> { let state = Arc::new(RwLock::new(SyncState::default())); // push state to managed states in Syncer. @@ -425,7 +425,7 @@ where verifier: PhantomData::::default(), req_window: self.sync_config.req_window, } - .spawn(channel, Arc::clone(&self.state)) + .spawn(channel, Arc::clone(&self.state), id) .await } diff --git a/blockchain/chain_sync/src/sync_worker.rs b/blockchain/chain_sync/src/sync_worker.rs index 8fbf9c436c46..e46816b55961 100644 --- a/blockchain/chain_sync/src/sync_worker.rs +++ b/blockchain/chain_sync/src/sync_worker.rs @@ -85,9 +85,11 @@ where self, mut inbound_channel: Receiver>, state: Arc>, + id: usize, ) -> JoinHandle<()> { task::spawn(async move { while let Some(ts) = inbound_channel.next().await { + info!("Worker #{} starting work on: {:?}", id, ts.key()); match self.sync(ts).await { Ok(()) => *state.lock().await = ChainSyncState::Follow, Err(e) => { From fab62813a79bcf63fc5c5aa6bb51f050aba19317 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 3 Mar 2021 23:30:21 -0500 Subject: [PATCH 24/35] update interface --- blockchain/state_manager/src/lib.rs | 8 +- blockchain/state_manager/src/utils.rs | 29 +-- node/rpc/src/state_api.rs | 82 ++++---- vm/actor_interface/src/builtin/cron/mod.rs | 4 +- vm/actor_interface/src/builtin/init/mod.rs | 11 +- vm/actor_interface/src/builtin/market/mod.rs | 68 ++++++ vm/actor_interface/src/builtin/miner/mod.rs | 199 ++++++++++++------ vm/actor_interface/src/builtin/mod.rs | 9 + .../src/builtin/multisig/mod.rs | 7 + vm/actor_interface/src/builtin/power/mod.rs | 41 +++- vm/actor_interface/src/builtin/reward/mod.rs | 26 +++ vm/interpreter/src/default_runtime.rs | 8 +- 12 files changed, 369 insertions(+), 123 deletions(-) diff --git a/blockchain/state_manager/src/lib.rs b/blockchain/state_manager/src/lib.rs index 2904c3da939a..d1b8c12f8474 100644 --- a/blockchain/state_manager/src/lib.rs +++ b/blockchain/state_manager/src/lib.rs @@ -171,7 +171,7 @@ where let info = ms.info(self.blockstore()).map_err(|e| e.to_string())?; - let addr = resolve_to_key_addr(&state, self.blockstore(), &info.worker) + let addr = resolve_to_key_addr(&state, self.blockstore(), &info.worker()) .map_err(|e| Error::Other(format!("Failed to resolve key address; error: {}", e)))?; Ok(addr) } @@ -611,7 +611,7 @@ where } // No active consensus faults. - if base_tipset.epoch() <= miner_state.info(self.blockstore())?.consensus_fault_elapsed { + if base_tipset.epoch() <= miner_state.info(self.blockstore())?.consensus_fault_elapsed() { return Ok(false); } @@ -680,7 +680,7 @@ where let (st, _) = self.tipset_state::(&lbts).await?; let state = StateTree::new_from_root(self.blockstore(), &st)?; - let worker_key = resolve_to_key_addr(&state, self.blockstore(), &info.worker)?; + let worker_key = resolve_to_key_addr(&state, self.blockstore(), &info.worker())?; let eligible = self.eligible_to_mine(&address, &tipset.as_ref(), &lbts)?; @@ -689,7 +689,7 @@ where network_power: Some(tpow.quality_adj_power), sectors, worker_key, - sector_size: info.sector_size, + sector_size: info.sector_size(), prev_beacon_entry: prev, beacon_entries: entries, eligible_for_mining: eligible, diff --git a/blockchain/state_manager/src/utils.rs b/blockchain/state_manager/src/utils.rs index 9436da83f6b8..4e88c1c456aa 100644 --- a/blockchain/state_manager/src/utils.rs +++ b/blockchain/state_manager/src/utils.rs @@ -79,7 +79,7 @@ where let info = mas.info(store)?; - let spt = RegisteredSealProof::from_sector_size(info.sector_size, nv); + let spt = RegisteredSealProof::from_sector_size(info.sector_size(), nv); let wpt = spt.registered_winning_post_proof()?; @@ -200,18 +200,19 @@ where where V: ProofVerifier, { - let actor = self - .get_actor(address, tipset.parent_state())? - .ok_or_else(|| Error::State("Power actor address could not be resolved".to_string()))?; - let mas = miner::State::load(self.blockstore(), &actor)?; - let mut out = Vec::with_capacity(mas.num_deadlines() as usize); - mas.for_each_deadline(self.blockstore(), |_, dl| { - let post_submissions = dl.into_post_submissions(); - - out.push(Deadline { post_submissions }); - Ok(()) - })?; - Ok(out) + todo!(); + // let actor = self + // .get_actor(address, tipset.parent_state())? + // .ok_or_else(|| Error::State("Power actor address could not be resolved".to_string()))?; + // let mas = miner::State::load(self.blockstore(), &actor)?; + // let mut out = Vec::with_capacity(mas.num_deadlines() as usize); + // mas.for_each_deadline(self.blockstore(), |_, dl| { + // let post_submissions = dl.into_post_submissions(); + + // out.push(Deadline { post_submissions }); + // Ok(()) + // })?; + // Ok(out) } fn for_each_deadline_partition( @@ -311,7 +312,7 @@ where err )) })?; - resolve_to_key_addr(&st, self.blockstore(), &info.worker).map_err(|e| { + resolve_to_key_addr(&st, self.blockstore(), &info.worker()).map_err(|e| { Error::State(format!( "(get miner worker raw) failed to resolve key addr: {}", e diff --git a/node/rpc/src/state_api.rs b/node/rpc/src/state_api.rs index 3fea4ad12d64..0ec103f12492 100644 --- a/node/rpc/src/state_api.rs +++ b/node/rpc/src/state_api.rs @@ -134,25 +134,26 @@ pub(crate) async fn state_miner_deadlines< data: Data>, Params(params): Params<(AddressJson, TipsetKeysJson)>, ) -> Result, JsonRpcError> { - let (actor, key) = params; - let actor = actor.into(); - let mas = data - .state_manager - .chain_store() - .miner_load_actor_tsk(&actor, &key.into()) - .await - .map_err(|e| format!("Could not load miner {:?}", e))?; - - let mut out = Vec::with_capacity(mas.num_deadlines() as usize); - mas.for_each_deadline(data.state_manager.blockstore(), |_, dl| { - let ps = dl.into_post_submissions(); - out.push(Deadline { - post_submissions: BitFieldJson(ps), - }); - Ok(()) - })?; - - Ok(out) + todo!(); + // let (actor, key) = params; + // let actor = actor.into(); + // let mas = data + // .state_manager + // .chain_store() + // .miner_load_actor_tsk(&actor, &key.into()) + // .await + // .map_err(|e| format!("Could not load miner {:?}", e))?; + + // let mut out = Vec::with_capacity(mas.num_deadlines() as usize); + // mas.for_each_deadline(data.state_manager.blockstore(), |_, dl| { + // let ps = dl.into_post_submissions(); + // out.push(Deadline { + // post_submissions: BitFieldJson(ps), + // }); + // Ok(()) + // })?; + + // Ok(out) } /// returns the PreCommit info for the specified miner's sector @@ -186,28 +187,29 @@ pub async fn state_miner_info< data: Data>, Params(params): Params<(AddressJson, TipsetKeysJson)>, ) -> Result { - let state_manager = &data.state_manager; - let store = state_manager.blockstore(); - let (AddressJson(addr), TipsetKeysJson(key)) = params; + todo!() + // let state_manager = &data.state_manager; + // let store = state_manager.blockstore(); + // let (AddressJson(addr), TipsetKeysJson(key)) = params; - let ts = data.chain_store.tipset_from_keys(&key).await?; - let actor = data - .state_manager - .get_actor(&addr, ts.parent_state()) - .map_err(|e| format!("Could not load miner {}: {:?}", addr, e))? - .ok_or_else(|| format!("miner {} does not exist", addr))?; + // let ts = data.chain_store.tipset_from_keys(&key).await?; + // let actor = data + // .state_manager + // .get_actor(&addr, ts.parent_state()) + // .map_err(|e| format!("Could not load miner {}: {:?}", addr, e))? + // .ok_or_else(|| format!("miner {} does not exist", addr))?; - let miner_state = miner::State::load(store, &actor)?; + // let miner_state = miner::State::load(store, &actor)?; - let mut miner_info = miner_state - .info(store) - .map_err(|e| format!("Could not get info {:?}", e))?; + // let mut miner_info = miner_state + // .info(store) + // .map_err(|e| format!("Could not get info {:?}", e))?; - // TODO revisit better way of handling (Lotus does here as well) - if get_network_version_default(ts.epoch()) >= NetworkVersion::V7 { - miner_info.seal_proof_type.update_to_v1(); - } - Ok(miner_info) + // // TODO revisit better way of handling (Lotus does here as well) + // if get_network_version_default(ts.epoch()) >= NetworkVersion::V7 { + // miner_info.seal_proof_type.update_to_v1(); + // } + // Ok(miner_info) } /// returns the on-chain info for the specified miner's sector @@ -805,6 +807,12 @@ pub(crate) async fn state_miner_sector_allocated< .get::(&m.allocated_sectors)? .ok_or("allocated sectors bitfield not found")? .get(sector_num as usize), + miner::State::V3(m) => data + .chain_store + .db + .get::(&m.allocated_sectors)? + .ok_or("allocated sectors bitfield not found")? + .get(sector_num as usize), }; Ok(allocated_sectors) diff --git a/vm/actor_interface/src/builtin/cron/mod.rs b/vm/actor_interface/src/builtin/cron/mod.rs index a6bb6a345f15..214dcbe267cf 100644 --- a/vm/actor_interface/src/builtin/cron/mod.rs +++ b/vm/actor_interface/src/builtin/cron/mod.rs @@ -7,10 +7,10 @@ use std::error::Error; use vm::ActorState; /// Cron actor address. -pub static ADDRESS: &actorv2::CRON_ACTOR_ADDR = &actorv2::CRON_ACTOR_ADDR; +pub static ADDRESS: &actorv3::CRON_ACTOR_ADDR = &actorv3::CRON_ACTOR_ADDR; /// Cron actor method. -pub type Method = actorv2::cron::Method; +pub type Method = actorv3::cron::Method; /// Cron actor state. #[derive(Serialize)] diff --git a/vm/actor_interface/src/builtin/init/mod.rs b/vm/actor_interface/src/builtin/init/mod.rs index 7782801aa75d..375953d5e609 100644 --- a/vm/actor_interface/src/builtin/init/mod.rs +++ b/vm/actor_interface/src/builtin/init/mod.rs @@ -8,7 +8,7 @@ use std::error::Error; use vm::ActorState; /// Init actor address. -pub static ADDRESS: &actorv2::INIT_ACTOR_ADDR = &actorv2::INIT_ACTOR_ADDR; +pub static ADDRESS: &actorv3::INIT_ACTOR_ADDR = &actorv3::INIT_ACTOR_ADDR; /// Init actor method. pub type Method = actorv2::init::Method; @@ -19,6 +19,7 @@ pub type Method = actorv2::init::Method; pub enum State { V0(actorv0::init::State), V2(actorv2::init::State), + V3(actorv3::init::State), } impl State { @@ -36,6 +37,11 @@ impl State { .get(&actor.state)? .map(State::V2) .ok_or("Actor state doesn't exist in store")?) + } else if actor.code == *actorv3::INIT_ACTOR_CODE_ID { + Ok(store + .get(&actor.state)? + .map(State::V3) + .ok_or("Actor state doesn't exist in store")?) } else { Err(format!("Unknown actor code {}", actor.code).into()) } @@ -51,6 +57,7 @@ impl State { match self { State::V0(st) => Ok(st.map_address_to_new_id(store, addr)?), State::V2(st) => Ok(st.map_address_to_new_id(store, addr)?), + State::V3(st) => Ok(st.map_address_to_new_id(store, addr)?), } } @@ -72,6 +79,7 @@ impl State { match self { State::V0(st) => st.resolve_address(store, addr), State::V2(st) => st.resolve_address(store, addr), + State::V3(st) => st.resolve_address(store, addr), } } @@ -79,6 +87,7 @@ impl State { match self { State::V0(st) => st.network_name, State::V2(st) => st.network_name, + State::V3(st) => st.network_name, } } } diff --git a/vm/actor_interface/src/builtin/market/mod.rs b/vm/actor_interface/src/builtin/market/mod.rs index cd20044b2655..5ccbfc2ebc68 100644 --- a/vm/actor_interface/src/builtin/market/mod.rs +++ b/vm/actor_interface/src/builtin/market/mod.rs @@ -1,6 +1,7 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT +use actorv0::market; use address::Address; use cid::Cid; use clock::ChainEpoch; @@ -23,6 +24,7 @@ pub type Method = actorv2::market::Method; pub enum State { V0(actorv0::market::State), V2(actorv2::market::State), + V3(actorv3::market::State), } impl State { @@ -40,6 +42,11 @@ impl State { .get(&actor.state)? .map(State::V2) .ok_or("Actor state doesn't exist in store")?) + } else if actor.code == *actorv3::MARKET_ACTOR_CODE_ID { + Ok(store + .get(&actor.state)? + .map(State::V3) + .ok_or("Actor state doesn't exist in store")?) } else { Err(format!("Unknown actor code {}", actor.code).into()) } @@ -62,6 +69,10 @@ impl State { Ok(actorv2::BalanceTable::from_root(store, &st.escrow_table) .map(BalanceTable::V2)?) } + State::V3(st) => { + Ok(actorv3::BalanceTable::from_root(store, &st.escrow_table) + .map(BalanceTable::V3)?) + } } } @@ -82,6 +93,10 @@ impl State { Ok(actorv2::BalanceTable::from_root(store, &st.locked_table) .map(BalanceTable::V2)?) } + State::V3(st) => { + Ok(actorv3::BalanceTable::from_root(store, &st.locked_table) + .map(BalanceTable::V3)?) + } } } @@ -100,6 +115,9 @@ impl State { State::V2(st) => Ok( actorv2::market::DealArray::load(&st.proposals, store).map(DealProposals::V2)? ), + State::V3(st) => Ok( + actorv3::market::DealArray::load(&st.proposals, store).map(DealProposals::V3)? + ), } } @@ -115,6 +133,9 @@ impl State { State::V2(st) => { Ok(actorv2::market::DealMetaArray::load(&st.states, store).map(DealStates::V2)?) } + State::V3(st) => { + Ok(actorv3::market::DealMetaArray::load(&st.states, store).map(DealStates::V3)?) + } } } @@ -123,6 +144,7 @@ impl State { match self { State::V0(st) => st.total_locked(), State::V2(st) => st.total_locked(), + State::V3(st) => st.total_locked(), } } @@ -157,6 +179,15 @@ impl State { curr_epoch, ) .map(|(deal_st, verified_st, _)| (deal_st, verified_st)), + State::V3(st) => actorv3::market::validate_deals_for_activation( + &st, + store, + deal_ids, + miner_addr, + sector_expiry, + curr_epoch, + ) + .map(|(deal_st, verified_st, _)| (deal_st, verified_st)), } } } @@ -164,11 +195,13 @@ impl State { pub enum BalanceTable<'a, BS> { V0(actorv0::BalanceTable<'a, BS>), V2(actorv2::BalanceTable<'a, BS>), + V3(actorv3::BalanceTable<'a, BS>), } pub enum DealProposals<'a, BS> { V0(actorv0::market::DealArray<'a, BS>), V2(actorv2::market::DealArray<'a, BS>), + V3(actorv3::market::DealArray<'a, BS>), } impl DealProposals<'_, BS> { @@ -186,6 +219,9 @@ impl DealProposals<'_, BS> { DealProposals::V2(dp) => { dp.for_each(|idx, proposal| f(idx, DealProposal::from(proposal.clone()))) } + DealProposals::V3(dp) => { + dp.for_each(|idx, proposal| f(idx as u64, DealProposal::from(proposal.clone()))) + } } } } @@ -249,9 +285,28 @@ impl From for DealProposal { } } +impl From for DealProposal { + fn from(d: actorv3::market::DealProposal) -> Self { + Self { + piece_cid: d.piece_cid, + piece_size: d.piece_size, + verified_deal: d.verified_deal, + client: d.client, + provider: d.client, + label: d.label, + start_epoch: d.start_epoch, + end_epoch: d.end_epoch, + storage_price_per_epoch: d.storage_price_per_epoch, + provider_collateral: d.provider_collateral, + client_collateral: d.client_collateral, + } + } +} + pub enum DealStates<'a, BS> { V0(actorv0::market::DealMetaArray<'a, BS>), V2(actorv2::market::DealMetaArray<'a, BS>), + V3(actorv3::market::DealMetaArray<'a, BS>), } impl DealStates<'_, BS> @@ -262,6 +317,7 @@ where match self { DealStates::V0(bt) => Ok(bt.get(key)?.cloned().map(From::from)), DealStates::V2(bt) => Ok(bt.get(key)?.cloned().map(From::from)), + DealStates::V3(bt) => Ok(bt.get(key as usize)?.cloned().map(From::from)), } } } @@ -294,6 +350,17 @@ impl From for DealState { } } +impl From for DealState { + fn from(d: actorv3::market::DealState) -> Self { + Self { + sector_start_epoch: d.sector_start_epoch, + last_updated_epoch: d.last_updated_epoch, + slash_epoch: d.slash_epoch, + } + } +} + + impl BalanceTable<'_, BS> where BS: BlockStore, @@ -302,6 +369,7 @@ where match self { BalanceTable::V0(bt) => bt.get(key), BalanceTable::V2(bt) => bt.get(key), + BalanceTable::V3(bt) => bt.get(key), } } } diff --git a/vm/actor_interface/src/builtin/miner/mod.rs b/vm/actor_interface/src/builtin/miner/mod.rs index 387e1f7d379f..6c3e8d215725 100644 --- a/vm/actor_interface/src/builtin/miner/mod.rs +++ b/vm/actor_interface/src/builtin/miner/mod.rs @@ -24,6 +24,7 @@ pub type Method = actorv2::miner::Method; pub enum State { V0(actorv0::miner::State), V2(actorv2::miner::State), + V3(actorv3::miner::State), } impl State { @@ -50,49 +51,23 @@ impl State { match self { State::V0(st) => { let info = st.get_info(store)?; + Ok(MinerInfo::V0(info)) + } + State::V2(st) => { + let info = st.get_info(store)?; // Deserialize into peer id if valid, `None` if not. - let peer_id = PeerId::from_bytes(&info.peer_id).ok(); - - Ok(MinerInfo { - owner: info.owner, - worker: info.worker, - control_addresses: info.control_addresses, - new_worker: info.pending_worker_key.as_ref().map(|k| k.new_worker), - worker_change_epoch: info - .pending_worker_key - .map(|k| k.effective_at) - .unwrap_or(-1), - peer_id, - multiaddrs: info.multi_address, - seal_proof_type: info.seal_proof_type, - sector_size: info.sector_size, - window_post_partition_sectors: info.window_post_partition_sectors, - consensus_fault_elapsed: -1, - }) + // let peer_id = PeerId::from_bytes(&info.peer_id).ok(); + + Ok(MinerInfo::V2(info)) } - State::V2(st) => { + State::V3(st) => { let info = st.get_info(store)?; // Deserialize into peer id if valid, `None` if not. - let peer_id = PeerId::from_bytes(&info.peer_id).ok(); - - Ok(MinerInfo { - owner: info.owner, - worker: info.worker, - control_addresses: info.control_addresses, - new_worker: info.pending_worker_key.as_ref().map(|k| k.new_worker), - worker_change_epoch: info - .pending_worker_key - .map(|k| k.effective_at) - .unwrap_or(-1), - peer_id, - multiaddrs: info.multi_address, - seal_proof_type: info.seal_proof_type, - sector_size: info.sector_size, - window_post_partition_sectors: info.window_post_partition_sectors, - consensus_fault_elapsed: info.consensus_fault_elapsed, - }) + // let peer_id = PeerId::from_bytes(&info.peer_id).ok(); + + Ok(MinerInfo::V3(info)) } } } @@ -110,6 +85,9 @@ impl State { State::V2(st) => st .load_deadlines(store)? .for_each(store, |idx, dl| f(idx, Deadline::V2(dl))), + State::V3(st) => st + .load_deadlines(store)? + .for_each(store, |idx, dl| f(idx as u64, Deadline::V3(dl))), } } @@ -128,6 +106,10 @@ impl State { .load_deadlines(store)? .load_deadline(store, idx) .map(Deadline::V2)?), + State::V3(st) => Ok(st + .load_deadlines(store)? + .load_deadline(store, idx as usize) + .map(Deadline::V3)?), } } @@ -172,6 +154,23 @@ impl State { Ok(infos) } } + State::V3(st) => { + if let Some(sectors) = sectors { + Ok(st + .load_sector_infos(store, sectors)? + .into_iter() + .map(From::from) + .collect()) + } else { + let sectors = actorv3::miner::Sectors::load(store, &st.sectors)?; + let mut infos = Vec::with_capacity(sectors.amt.count() as usize); + sectors.amt.for_each(|_, info| { + infos.push(SectorOnChainInfo::from(info.clone())); + Ok(()) + })?; + Ok(infos) + } + } } } @@ -188,6 +187,9 @@ impl State { State::V2(st) => Ok(st .get_precommitted_sector(store, sector_num)? .map(From::from)), + State::V3(st) => Ok(st + .get_precommitted_sector(store, sector_num)? + .map(From::from)), } } @@ -200,6 +202,7 @@ impl State { match self { State::V0(st) => Ok(st.get_sector(store, sector_num)?.map(From::from)), State::V2(st) => Ok(st.get_sector(store, sector_num)?.map(From::from)), + State::V3(st) => Ok(st.get_sector(store, sector_num)?.map(From::from)), } } @@ -208,6 +211,7 @@ impl State { match self { State::V0(st) => st.deadline_info(epoch), State::V2(st) => st.deadline_info(epoch), + State::V3(st) => st.deadline_info(epoch), } } @@ -216,6 +220,7 @@ impl State { match self { State::V0(_) => TokenAmount::from(0), State::V2(st) => st.fee_debt.clone(), + State::V3(st) => st.fee_debt.clone(), } } @@ -224,46 +229,61 @@ impl State { match self { State::V0(_) => actorv0::miner::WPOST_PERIOD_DEADLINES, State::V2(_) => actorv2::miner::WPOST_PERIOD_DEADLINES, + State::V3(_) => actorv2::miner::WPOST_PERIOD_DEADLINES, } } } /// Static information about miner #[derive(Debug, PartialEq, Serialize)] -#[serde(rename_all = "PascalCase")] -pub struct MinerInfo { - #[serde(with = "address::json")] - pub owner: Address, - #[serde(with = "address::json")] - pub worker: Address, - #[serde(with = "address::json::opt")] - pub new_worker: Option
, - #[serde(with = "address::json::vec")] - pub control_addresses: Vec
, // Must all be ID addresses. - pub worker_change_epoch: ChainEpoch, - #[serde(with = "peer_id_json")] - pub peer_id: Option, - pub multiaddrs: Vec, - pub seal_proof_type: RegisteredSealProof, - pub sector_size: SectorSize, - pub window_post_partition_sectors: u64, - pub consensus_fault_elapsed: ChainEpoch, +pub enum MinerInfo { + V0(actorv0::miner::MinerInfo), + V2(actorv2::miner::MinerInfo), + V3(actorv3::miner::MinerInfo), +} + +impl MinerInfo { + pub fn worker(&self) -> Address { + match self { + Self::V0(info) => info.worker, + Self::V2(info) => info.worker, + Self::V3(info) => info.worker, + } + } + + pub fn sector_size(&self) -> SectorSize { + match self { + Self::V0(info) => info.sector_size, + Self::V2(info) => info.sector_size, + Self::V3(info) => info.sector_size, + } + } + + pub fn consensus_fault_elapsed(&self) -> ChainEpoch { + match self { + Self::V0(info) => -1, + Self::V2(info) => info.consensus_fault_elapsed, + Self::V3(info) => info.consensus_fault_elapsed, + } + } } /// Deadline holds the state for all sectors due at a specific deadline. pub enum Deadline { V0(actorv0::miner::Deadline), V2(actorv2::miner::Deadline), + V3(actorv3::miner::Deadline), } impl Deadline { /// Consume state to return the deadline post submissions - pub fn into_post_submissions(self) -> BitField { - match self { - Deadline::V0(dl) => dl.post_submissions, - Deadline::V2(dl) => dl.post_submissions, - } - } + // pub fn into_post_submissions(self) -> BitField { + // match self { + // Deadline::V0(dl) => dl.post_submissions, + // Deadline::V2(dl) => dl.post_submissions, + // Deadline::V3(dl) => dl.post_submissions, + // } + // } /// For each partition of the deadline pub fn for_each( @@ -278,6 +298,9 @@ impl Deadline { Deadline::V2(dl) => dl.for_each(store, |idx, part| { f(idx, Partition::V2(Cow::Borrowed(part))) }), + Deadline::V3(dl) => dl.for_each(store, |idx, part| { + f(idx as u64, Partition::V3(Cow::Borrowed(part))) + }), } } } @@ -286,6 +309,7 @@ impl Deadline { pub enum Partition<'a> { V0(Cow<'a, actorv0::miner::Partition>), V2(Cow<'a, actorv2::miner::Partition>), + V3(Cow<'a, actorv3::miner::Partition>), } impl Partition<'_> { @@ -293,30 +317,35 @@ impl Partition<'_> { match self { Partition::V0(dl) => &dl.sectors, Partition::V2(dl) => &dl.sectors, + Partition::V3(dl) => &dl.sectors, } } pub fn faulty_sectors(&self) -> &BitField { match self { Partition::V0(dl) => &dl.faults, Partition::V2(dl) => &dl.faults, + Partition::V3(dl) => &dl.faults, } } pub fn recovering_sectors(&self) -> &BitField { match self { Partition::V0(dl) => &dl.recoveries, Partition::V2(dl) => &dl.recoveries, + Partition::V3(dl) => &dl.recoveries, } } pub fn live_sectors(&self) -> BitField { match self { Partition::V0(dl) => dl.live_sectors(), Partition::V2(dl) => dl.live_sectors(), + Partition::V3(dl) => dl.live_sectors(), } } pub fn active_sectors(&self) -> BitField { match self { Partition::V0(dl) => dl.active_sectors(), Partition::V2(dl) => dl.active_sectors(), + Partition::V3(dl) => dl.active_sectors(), } } } @@ -400,6 +429,24 @@ impl From for SectorOnChainInfo { } } +impl From for SectorOnChainInfo { + fn from(info: actorv3::miner::SectorOnChainInfo) -> Self { + Self { + sector_number: info.sector_number, + seal_proof: info.seal_proof, + sealed_cid: info.sealed_cid, + deal_ids: info.deal_ids, + activation: info.activation, + expiration: info.expiration, + deal_weight: info.deal_weight, + verified_deal_weight: info.verified_deal_weight, + initial_pledge: info.initial_pledge, + expected_day_reward: info.expected_day_reward, + expected_storage_pledge: info.expected_storage_pledge, + } + } +} + #[derive(Serialize)] #[serde(rename_all = "PascalCase")] pub struct SectorPreCommitOnChainInfo { @@ -439,6 +486,18 @@ impl From for SectorPreCommitOnChain } } +impl From for SectorPreCommitOnChainInfo { + fn from(spc: actorv3::miner::SectorPreCommitOnChainInfo) -> Self { + Self { + info: spc.info.into(), + pre_commit_deposit: spc.pre_commit_deposit, + pre_commit_epoch: spc.pre_commit_epoch, + deal_weight: spc.deal_weight, + verified_deal_weight: spc.verified_deal_weight, + } + } +} + #[derive(Serialize, Deserialize)] #[serde(rename_all = "PascalCase")] pub struct SectorPreCommitInfo { @@ -492,3 +551,21 @@ impl From for SectorPreCommitInfo { } } } + +impl From for SectorPreCommitInfo { + fn from(spc: actorv3::miner::SectorPreCommitInfo) -> Self { + Self { + seal_proof: spc.seal_proof, + sector_number: spc.sector_number, + sealed_cid: spc.sealed_cid, + seal_rand_epoch: spc.seal_rand_epoch, + deal_ids: spc.deal_ids, + expiration: spc.expiration, + replace_capacity: spc.replace_capacity, + replace_sector_deadline: spc.replace_sector_deadline as u64, + replace_sector_partition: spc.replace_sector_partition as u64, + replace_sector_number: spc.replace_sector_number, + } + } +} + diff --git a/vm/actor_interface/src/builtin/mod.rs b/vm/actor_interface/src/builtin/mod.rs index a50d06624bca..5170beed6aeb 100644 --- a/vm/actor_interface/src/builtin/mod.rs +++ b/vm/actor_interface/src/builtin/mod.rs @@ -74,3 +74,12 @@ impl From for FilterEstimate { } } } + +impl From for FilterEstimate { + fn from(filter_est: actorv3::util::smooth::FilterEstimate) -> Self { + Self { + position: filter_est.position, + velocity: filter_est.velocity, + } + } +} \ No newline at end of file diff --git a/vm/actor_interface/src/builtin/multisig/mod.rs b/vm/actor_interface/src/builtin/multisig/mod.rs index 1da2859b19c1..f70d5848a51d 100644 --- a/vm/actor_interface/src/builtin/multisig/mod.rs +++ b/vm/actor_interface/src/builtin/multisig/mod.rs @@ -15,6 +15,7 @@ pub type Method = actorv2::multisig::Method; pub enum State { V0(actorv0::multisig::State), V2(actorv2::multisig::State), + V3(actorv2::multisig::State), } impl State { @@ -32,6 +33,12 @@ impl State { .get(&actor.state)? .map(State::V2) .ok_or("Actor state doesn't exist in store")?) + } + else if actor.code == *actorv3::MULTISIG_ACTOR_CODE_ID { + Ok(store + .get(&actor.state)? + .map(State::V3) + .ok_or("Actor state doesn't exist in store")?) } else { Err(format!("Unknown actor code {}", actor.code).into()) } diff --git a/vm/actor_interface/src/builtin/power/mod.rs b/vm/actor_interface/src/builtin/power/mod.rs index 4d4048b3bdc2..4a17aada4f45 100644 --- a/vm/actor_interface/src/builtin/power/mod.rs +++ b/vm/actor_interface/src/builtin/power/mod.rs @@ -11,10 +11,12 @@ use std::error::Error; use vm::{ActorState, TokenAmount}; /// Power actor address. -pub static ADDRESS: &actorv2::STORAGE_POWER_ACTOR_ADDR = &actorv2::STORAGE_POWER_ACTOR_ADDR; +/// TODO: Select based on actors version +pub static ADDRESS: &actorv3::STORAGE_POWER_ACTOR_ADDR = &actorv3::STORAGE_POWER_ACTOR_ADDR; /// Power actor method. -pub type Method = actorv2::power::Method; +/// TODO: Select based on actor version +pub type Method = actorv3::power::Method; /// Power actor state. #[derive(Serialize)] @@ -22,6 +24,7 @@ pub type Method = actorv2::power::Method; pub enum State { V0(actorv0::power::State), V2(actorv2::power::State), + V3(actorv3::power::State), } impl State { @@ -39,6 +42,11 @@ impl State { .get(&actor.state)? .map(State::V2) .ok_or("Actor state doesn't exist in store")?) + } else if actor.code == *actorv3::POWER_ACTOR_CODE_ID { + Ok(store + .get(&actor.state)? + .map(State::V3) + .ok_or("Actor state doesn't exist in store")?) } else { Err(format!("Unknown actor code {}", actor.code).into()) } @@ -49,6 +57,7 @@ impl State { match self { State::V0(st) => st.total_quality_adj_power, State::V2(st) => st.total_quality_adj_power, + State::V3(st) => st.total_quality_adj_power, } } @@ -63,6 +72,10 @@ impl State { raw_byte_power: st.total_raw_byte_power.clone(), quality_adj_power: st.total_quality_adj_power.clone(), }, + State::V3(st) => Claim { + raw_byte_power: st.total_raw_byte_power.clone(), + quality_adj_power: st.total_quality_adj_power.clone(), + }, } } @@ -71,6 +84,7 @@ impl State { match self { State::V0(st) => st.into_total_locked(), State::V2(st) => st.into_total_locked(), + State::V3(st) => st.into_total_locked(), } } @@ -83,6 +97,7 @@ impl State { match self { State::V0(st) => Ok(st.miner_power(s, miner)?.map(From::from)), State::V2(st) => Ok(st.miner_power(s, miner)?.map(From::from)), + State::V3(st) => Ok(st.miner_power(s, miner)?.map(From::from)), } } @@ -107,6 +122,16 @@ impl State { Ok(()) })?; + Ok(miners) + } + State::V3(st) => { + let claims = actorv2::make_map_with_root(&st.claims, s)?; + let mut miners = Vec::new(); + claims.for_each(|k, _: &actorv3::power::Claim| { + miners.push(Address::from_bytes(&k.0)?); + Ok(()) + })?; + Ok(miners) } } @@ -121,6 +146,7 @@ impl State { match self { State::V0(st) => st.miner_nominal_power_meets_consensus_minimum(s, miner), State::V2(st) => st.miner_nominal_power_meets_consensus_minimum(s, miner), + State::V3(st) => st.miner_nominal_power_meets_consensus_minimum(s, miner), } } @@ -129,6 +155,7 @@ impl State { match self { State::V0(st) => st.this_epoch_qa_power_smoothed.clone().into(), State::V2(st) => st.this_epoch_qa_power_smoothed.clone().into(), + State::V3(st) => st.this_epoch_qa_power_smoothed.clone().into(), } } @@ -137,6 +164,7 @@ impl State { match self { State::V0(st) => st.total_pledge_collateral.clone(), State::V2(st) => st.total_pledge_collateral.clone(), + State::V3(st) => st.total_pledge_collateral.clone(), } } } @@ -168,3 +196,12 @@ impl From for Claim { } } } + +impl From for Claim { + fn from(cl: actorv3::power::Claim) -> Self { + Self { + raw_byte_power: cl.raw_byte_power, + quality_adj_power: cl.quality_adj_power, + } + } +} diff --git a/vm/actor_interface/src/builtin/reward/mod.rs b/vm/actor_interface/src/builtin/reward/mod.rs index 6dc8b876bb3b..f4dbd4b8cbd7 100644 --- a/vm/actor_interface/src/builtin/reward/mod.rs +++ b/vm/actor_interface/src/builtin/reward/mod.rs @@ -20,6 +20,7 @@ pub type Method = actorv2::reward::Method; pub enum State { V0(actorv0::reward::State), V2(actorv2::reward::State), + V3(actorv3::reward::State), } impl State { @@ -37,6 +38,12 @@ impl State { .get(&actor.state)? .map(State::V2) .ok_or("Actor state doesn't exist in store")?) + } + else if actor.code == *actorv3::REWARD_ACTOR_CODE_ID { + Ok(store + .get(&actor.state)? + .map(State::V3) + .ok_or("Actor state doesn't exist in store")?) } else { Err(format!("Unknown actor code {}", actor.code).into()) } @@ -47,6 +54,7 @@ impl State { match self { State::V0(st) => st.into_total_storage_power_reward(), State::V2(st) => st.into_total_storage_power_reward(), + State::V3(st) => st.into_total_storage_power_reward(), } } @@ -72,6 +80,14 @@ impl State { }, sector_weight, ), + State::V3(st) => actorv3::miner::pre_commit_deposit_for_power( + &st.this_epoch_reward_smoothed, + &actorv3::util::smooth::FilterEstimate { + position: network_qa_power.position, + velocity: network_qa_power.velocity, + }, + sector_weight, + ), } } @@ -103,6 +119,16 @@ impl State { }, circ_supply, ), + State::V3(st) => actorv3::miner::initial_pledge_for_power( + sector_weight, + &st.this_epoch_baseline_power, + &st.this_epoch_reward_smoothed, + &actorv3::util::smooth::FilterEstimate { + position: network_qa_power.position, + velocity: network_qa_power.velocity, + }, + circ_supply, + ), } } } diff --git a/vm/interpreter/src/default_runtime.rs b/vm/interpreter/src/default_runtime.rs index 69c999b05bf0..285fd9c3cccf 100644 --- a/vm/interpreter/src/default_runtime.rs +++ b/vm/interpreter/src/default_runtime.rs @@ -522,9 +522,13 @@ where let ms = actor::miner::State::load(self.store(), &actor)?; - let info = ms.info(&self.store)?; + let worker = match ms.info(&self.store)? { + actor::miner::MinerInfo::V0(info) => info.worker, + actor::miner::MinerInfo::V2(info) => info.worker, + actor::miner::MinerInfo::V3(info) => info.worker, + }; - resolve_to_key_addr(&self.state, &self.store, &info.worker) + resolve_to_key_addr(&self.state, &self.store, &worker) } } From cf0f08648776bf238f3a39eeb0212438dcac1ade Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 3 Mar 2021 23:43:17 -0500 Subject: [PATCH 25/35] fix more interface stuff --- vm/actor_interface/src/builtin/account/mod.rs | 2 +- vm/actor_interface/src/builtin/init/mod.rs | 2 +- vm/actor_interface/src/builtin/market/mod.rs | 4 ++-- vm/actor_interface/src/builtin/miner/mod.rs | 2 +- vm/actor_interface/src/builtin/multisig/mod.rs | 2 +- vm/actor_interface/src/builtin/reward/mod.rs | 4 ++-- vm/actor_interface/src/builtin/system/mod.rs | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/vm/actor_interface/src/builtin/account/mod.rs b/vm/actor_interface/src/builtin/account/mod.rs index 407cee8e76d5..39f80fd87d16 100644 --- a/vm/actor_interface/src/builtin/account/mod.rs +++ b/vm/actor_interface/src/builtin/account/mod.rs @@ -8,7 +8,7 @@ use std::error::Error; use vm::ActorState; /// Account actor method. -pub type Method = actorv2::account::Method; +pub type Method = actorv3::account::Method; /// Account actor state. #[derive(Serialize)] diff --git a/vm/actor_interface/src/builtin/init/mod.rs b/vm/actor_interface/src/builtin/init/mod.rs index 375953d5e609..798f5bc73864 100644 --- a/vm/actor_interface/src/builtin/init/mod.rs +++ b/vm/actor_interface/src/builtin/init/mod.rs @@ -11,7 +11,7 @@ use vm::ActorState; pub static ADDRESS: &actorv3::INIT_ACTOR_ADDR = &actorv3::INIT_ACTOR_ADDR; /// Init actor method. -pub type Method = actorv2::init::Method; +pub type Method = actorv3::init::Method; /// Init actor state. #[derive(Serialize)] diff --git a/vm/actor_interface/src/builtin/market/mod.rs b/vm/actor_interface/src/builtin/market/mod.rs index 5ccbfc2ebc68..3389c11e206b 100644 --- a/vm/actor_interface/src/builtin/market/mod.rs +++ b/vm/actor_interface/src/builtin/market/mod.rs @@ -13,10 +13,10 @@ use std::error::Error; use vm::{ActorState, TokenAmount}; /// Market actor address. -pub static ADDRESS: &actorv2::STORAGE_MARKET_ACTOR_ADDR = &actorv2::STORAGE_MARKET_ACTOR_ADDR; +pub static ADDRESS: &actorv3::STORAGE_MARKET_ACTOR_ADDR = &actorv2::STORAGE_MARKET_ACTOR_ADDR; /// Market actor method. -pub type Method = actorv2::market::Method; +pub type Method = actorv3::market::Method; /// Market actor state. #[derive(Serialize)] diff --git a/vm/actor_interface/src/builtin/miner/mod.rs b/vm/actor_interface/src/builtin/miner/mod.rs index 6c3e8d215725..6ea977b9c49d 100644 --- a/vm/actor_interface/src/builtin/miner/mod.rs +++ b/vm/actor_interface/src/builtin/miner/mod.rs @@ -16,7 +16,7 @@ use std::borrow::Cow; use std::error::Error; use vm::{ActorState, DealID, TokenAmount}; /// Miner actor method. -pub type Method = actorv2::miner::Method; +pub type Method = actorv3::miner::Method; /// Miner actor state. #[derive(Serialize)] diff --git a/vm/actor_interface/src/builtin/multisig/mod.rs b/vm/actor_interface/src/builtin/multisig/mod.rs index f70d5848a51d..5ec7d944301c 100644 --- a/vm/actor_interface/src/builtin/multisig/mod.rs +++ b/vm/actor_interface/src/builtin/multisig/mod.rs @@ -7,7 +7,7 @@ use std::error::Error; use vm::ActorState; /// Multisig actor method. -pub type Method = actorv2::multisig::Method; +pub type Method = actorv3::multisig::Method; /// Multisig actor state. #[derive(Serialize)] diff --git a/vm/actor_interface/src/builtin/reward/mod.rs b/vm/actor_interface/src/builtin/reward/mod.rs index f4dbd4b8cbd7..025d7e2e4d55 100644 --- a/vm/actor_interface/src/builtin/reward/mod.rs +++ b/vm/actor_interface/src/builtin/reward/mod.rs @@ -9,10 +9,10 @@ use std::error::Error; use vm::{ActorState, TokenAmount}; /// Reward actor address. -pub static ADDRESS: &actorv2::REWARD_ACTOR_ADDR = &actorv2::REWARD_ACTOR_ADDR; +pub static ADDRESS: &actorv3::REWARD_ACTOR_ADDR = &actorv2::REWARD_ACTOR_ADDR; /// Reward actor method. -pub type Method = actorv2::reward::Method; +pub type Method = actorv3::reward::Method; /// Reward actor state. #[derive(Serialize)] diff --git a/vm/actor_interface/src/builtin/system/mod.rs b/vm/actor_interface/src/builtin/system/mod.rs index b929c7d09962..24ede35f3b6a 100644 --- a/vm/actor_interface/src/builtin/system/mod.rs +++ b/vm/actor_interface/src/builtin/system/mod.rs @@ -7,10 +7,10 @@ use std::error::Error; use vm::ActorState; /// System actor address. -pub static ADDRESS: &actorv2::SYSTEM_ACTOR_ADDR = &actorv2::SYSTEM_ACTOR_ADDR; +pub static ADDRESS: &actorv3::SYSTEM_ACTOR_ADDR = &actorv2::SYSTEM_ACTOR_ADDR; /// System actor method. -pub type Method = actorv2::system::Method; +pub type Method = actorv3::system::Method; /// System actor state. #[derive(Serialize)] From 52ac1aa196ad2cad9348fa9f449821e6c6aee878 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Wed, 3 Mar 2021 23:47:19 -0500 Subject: [PATCH 26/35] compiles --- vm/actor_interface/src/builtin/market/mod.rs | 2 +- vm/actor_interface/src/builtin/reward/mod.rs | 2 +- vm/actor_interface/src/builtin/system/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/vm/actor_interface/src/builtin/market/mod.rs b/vm/actor_interface/src/builtin/market/mod.rs index 3389c11e206b..652ef4bc89f3 100644 --- a/vm/actor_interface/src/builtin/market/mod.rs +++ b/vm/actor_interface/src/builtin/market/mod.rs @@ -13,7 +13,7 @@ use std::error::Error; use vm::{ActorState, TokenAmount}; /// Market actor address. -pub static ADDRESS: &actorv3::STORAGE_MARKET_ACTOR_ADDR = &actorv2::STORAGE_MARKET_ACTOR_ADDR; +pub static ADDRESS: &actorv3::STORAGE_MARKET_ACTOR_ADDR = &actorv3::STORAGE_MARKET_ACTOR_ADDR; /// Market actor method. pub type Method = actorv3::market::Method; diff --git a/vm/actor_interface/src/builtin/reward/mod.rs b/vm/actor_interface/src/builtin/reward/mod.rs index 025d7e2e4d55..31d6a55bb227 100644 --- a/vm/actor_interface/src/builtin/reward/mod.rs +++ b/vm/actor_interface/src/builtin/reward/mod.rs @@ -9,7 +9,7 @@ use std::error::Error; use vm::{ActorState, TokenAmount}; /// Reward actor address. -pub static ADDRESS: &actorv3::REWARD_ACTOR_ADDR = &actorv2::REWARD_ACTOR_ADDR; +pub static ADDRESS: &actorv3::REWARD_ACTOR_ADDR = &actorv3::REWARD_ACTOR_ADDR; /// Reward actor method. pub type Method = actorv3::reward::Method; diff --git a/vm/actor_interface/src/builtin/system/mod.rs b/vm/actor_interface/src/builtin/system/mod.rs index 24ede35f3b6a..2a52ec7511e2 100644 --- a/vm/actor_interface/src/builtin/system/mod.rs +++ b/vm/actor_interface/src/builtin/system/mod.rs @@ -7,7 +7,7 @@ use std::error::Error; use vm::ActorState; /// System actor address. -pub static ADDRESS: &actorv3::SYSTEM_ACTOR_ADDR = &actorv2::SYSTEM_ACTOR_ADDR; +pub static ADDRESS: &actorv3::SYSTEM_ACTOR_ADDR = &actorv3::SYSTEM_ACTOR_ADDR; /// System actor method. pub type Method = actorv3::system::Method; From 349fb698f2d5e06f58c2068aeb32843afa49cb94 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Mar 2021 00:07:52 -0500 Subject: [PATCH 27/35] quick miner actor fix --- vm/actor/src/builtin/miner/deadline_state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vm/actor/src/builtin/miner/deadline_state.rs b/vm/actor/src/builtin/miner/deadline_state.rs index eadaba14b937..0458423d7896 100644 --- a/vm/actor/src/builtin/miner/deadline_state.rs +++ b/vm/actor/src/builtin/miner/deadline_state.rs @@ -1117,7 +1117,7 @@ impl Deadline { // First check to see if we're proving any already proven partitions. // This is faster than checking one by one. let already_proven = &self.partitions_posted & &partition_indexes; - if already_proven.is_empty() { + if !already_proven.is_empty() { return Err(format!("parition already proven: {:?}", already_proven).into()); } From 48bb693b6279c73b4e05272fb75c394d074bc0dc Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Mar 2021 00:09:01 -0500 Subject: [PATCH 28/35] return right code in record_proven_sectors --- vm/actor/src/builtin/miner/deadline_state.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vm/actor/src/builtin/miner/deadline_state.rs b/vm/actor/src/builtin/miner/deadline_state.rs index 0458423d7896..a6863bc1f4ad 100644 --- a/vm/actor/src/builtin/miner/deadline_state.rs +++ b/vm/actor/src/builtin/miner/deadline_state.rs @@ -1118,7 +1118,10 @@ impl Deadline { // This is faster than checking one by one. let already_proven = &self.partitions_posted & &partition_indexes; if !already_proven.is_empty() { - return Err(format!("parition already proven: {:?}", already_proven).into()); + return Err(Box::new(actor_error!( + ErrIllegalArgument, + "parition already proven: {:?}", already_proven + ))); } let mut partitions = self.partitions_amt(store)?; From 501d7f87d287ce4b59d73802fb43d80eec2f0d72 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Thu, 4 Mar 2021 00:30:03 -0500 Subject: [PATCH 29/35] match miner code id for v3 in interface when loading state --- vm/actor_interface/src/builtin/miner/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vm/actor_interface/src/builtin/miner/mod.rs b/vm/actor_interface/src/builtin/miner/mod.rs index 6ea977b9c49d..86cb04bb12a1 100644 --- a/vm/actor_interface/src/builtin/miner/mod.rs +++ b/vm/actor_interface/src/builtin/miner/mod.rs @@ -42,6 +42,11 @@ impl State { .get(&actor.state)? .map(State::V2) .ok_or("Actor state doesn't exist in store")?) + } else if actor.code == *actorv3::MINER_ACTOR_CODE_ID { + Ok(store + .get(&actor.state)? + .map(State::V3) + .ok_or("Actor state doesn't exist in store")?) } else { Err(format!("Unknown actor code {}", actor.code).into()) } From 63c58e2b6319c540daa80bc646154833c047e6d1 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Sun, 7 Mar 2021 00:50:47 -0500 Subject: [PATCH 30/35] fix a few consensus issues --- vm/actor/src/builtin/miner/deadline_state.rs | 2 +- vm/actor/src/builtin/miner/mod.rs | 18 +++++++++++------- vm/actor/src/builtin/miner/partition_state.rs | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/vm/actor/src/builtin/miner/deadline_state.rs b/vm/actor/src/builtin/miner/deadline_state.rs index a6863bc1f4ad..e0f92773355e 100644 --- a/vm/actor/src/builtin/miner/deadline_state.rs +++ b/vm/actor/src/builtin/miner/deadline_state.rs @@ -1278,7 +1278,7 @@ impl Deadline { let post = proof_arr .delete(idx as usize) .map_err(|e| e.downcast_wrap(format!("failed to retrieve proof {}", idx)))? - .ok_or_else(|| Box::new(actor_error!(ErrIllegalArgument, "proof {} not found", idx)))?; + .ok_or_else(|| actor_error!(ErrIllegalArgument, "proof {} not found", idx))?; let root = proof_arr .flush() diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 60f86b31e935..40a974b4a414 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -711,7 +711,7 @@ impl Actor { current_epoch, ) { return Err(actor_error!( - ErrIllegalState, + ErrForbidden, "can only dispute window posts during the dispute window\ ({} epochs after the challenge window closes)", WPOST_DISPUTE_WINDOW @@ -780,10 +780,14 @@ impl Actor { })?; // Check proof, we fail if validation succeeds. - verify_windowed_post(rt, target_deadline.challenge, §or_infos, proofs) - .map_err(|_e| { - actor_error!(ErrIllegalArgument, "failed to dispute valid post") - })?; + match verify_windowed_post(rt, target_deadline.challenge, §or_infos, proofs) { + Ok(()) => { + return Err(actor_error!(ErrIllegalArgument, "failed to dispute valid post")); + } + Err(e) => { + log::info!("Successfully disputed: {}",e); + } + } // Ok, now we record faults. This always works because // we don't allow compaction/moving sectors during the @@ -856,7 +860,7 @@ impl Actor { // we can from the burn to the reward. let to_reward = std::cmp::min(&to_burn, &reward_target); let to_burn = &to_burn - to_reward; - let pledge_delta = -penalty_from_vesting; + let pledge_delta = penalty_from_vesting.neg(); Ok((pledge_delta, to_burn, power_delta, to_reward.clone())) })?; @@ -1138,7 +1142,7 @@ impl Actor { pre_commit_deposit: deposit_req, pre_commit_epoch: rt.curr_epoch(), deal_weight: deal_weight.deal_weight.clone(), - verified_deal_weight: deal_weight.deal_weight.clone(), + verified_deal_weight: deal_weight.verified_deal_weight.clone(), }, ) .map_err(|e| { diff --git a/vm/actor/src/builtin/miner/partition_state.rs b/vm/actor/src/builtin/miner/partition_state.rs index d73943ccb4d6..cd614ed3dfab 100644 --- a/vm/actor/src/builtin/miner/partition_state.rs +++ b/vm/actor/src/builtin/miner/partition_state.rs @@ -237,7 +237,7 @@ impl Partition { .load_sector(&new_faults) .map_err(|e| e.wrap("failed to load fault sectors"))?; - let (new_faulty_power, power_delta) = if !new_fault_sectors.is_empty() { + let (power_delta, new_faulty_power) = if !new_fault_sectors.is_empty() { self.add_faults( store, &new_faults, From 260d659c70d1a7e115fe84436315c3fcc79a7845 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Sun, 7 Mar 2021 22:29:27 -0500 Subject: [PATCH 31/35] should sync same weight --- blockchain/chain_sync/src/sync.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockchain/chain_sync/src/sync.rs b/blockchain/chain_sync/src/sync.rs index 4fd9919ed26e..14839509068f 100644 --- a/blockchain/chain_sync/src/sync.rs +++ b/blockchain/chain_sync/src/sync.rs @@ -459,7 +459,7 @@ where .await // TODO we should be able to queue a tipset with the same weight on a different chain. // Currently needed to go GT because equal tipsets are attempted to be synced. - .map(|heaviest| ts.weight() > heaviest.weight()) + .map(|heaviest| ts.weight() >= heaviest.weight()) .unwrap_or(true); if candidate_ts { // Check message meta after all other checks (expensive) From 60bb6ed9fdbeecc48f4e32d2f1ce82d20151909f Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Mon, 8 Mar 2021 08:01:02 -0500 Subject: [PATCH 32/35] lint --- vm/actor_interface/src/builtin/market/mod.rs | 1 - vm/actor_interface/src/builtin/miner/mod.rs | 10 +--------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/vm/actor_interface/src/builtin/market/mod.rs b/vm/actor_interface/src/builtin/market/mod.rs index 652ef4bc89f3..3cd59fd149da 100644 --- a/vm/actor_interface/src/builtin/market/mod.rs +++ b/vm/actor_interface/src/builtin/market/mod.rs @@ -1,7 +1,6 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -use actorv0::market; use address::Address; use cid::Cid; use clock::ChainEpoch; diff --git a/vm/actor_interface/src/builtin/miner/mod.rs b/vm/actor_interface/src/builtin/miner/mod.rs index 86cb04bb12a1..94c5475dea72 100644 --- a/vm/actor_interface/src/builtin/miner/mod.rs +++ b/vm/actor_interface/src/builtin/miner/mod.rs @@ -60,18 +60,10 @@ impl State { } State::V2(st) => { let info = st.get_info(store)?; - - // Deserialize into peer id if valid, `None` if not. - // let peer_id = PeerId::from_bytes(&info.peer_id).ok(); - Ok(MinerInfo::V2(info)) } State::V3(st) => { let info = st.get_info(store)?; - - // Deserialize into peer id if valid, `None` if not. - // let peer_id = PeerId::from_bytes(&info.peer_id).ok(); - Ok(MinerInfo::V3(info)) } } @@ -266,7 +258,7 @@ impl MinerInfo { pub fn consensus_fault_elapsed(&self) -> ChainEpoch { match self { - Self::V0(info) => -1, + Self::V0(_info) => -1, Self::V2(info) => info.consensus_fault_elapsed, Self::V3(info) => info.consensus_fault_elapsed, } From ed0e829c985d90b0fdd6750d15a902d1c093c89f Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Mon, 8 Mar 2021 08:45:37 -0500 Subject: [PATCH 33/35] lint --- blockchain/chain_sync/src/sync_worker.rs | 5 +- blockchain/state_manager/src/lib.rs | 2 +- blockchain/state_manager/src/utils.rs | 24 --- node/rpc/src/state_api.rs | 74 ++++----- types/networks/src/interopnet/mod.rs | 2 + vm/actor/src/builtin/miner/deadline_state.rs | 3 +- vm/actor/src/builtin/miner/mod.rs | 7 +- vm/actor_interface/src/builtin/market/mod.rs | 1 - vm/actor_interface/src/builtin/miner/mod.rs | 148 +++++++++++++----- vm/actor_interface/src/builtin/mod.rs | 2 +- .../src/builtin/multisig/mod.rs | 3 +- vm/actor_interface/src/builtin/reward/mod.rs | 3 +- vm/interpreter/src/default_runtime.rs | 6 +- 13 files changed, 159 insertions(+), 121 deletions(-) diff --git a/blockchain/chain_sync/src/sync_worker.rs b/blockchain/chain_sync/src/sync_worker.rs index e46816b55961..e998d12db307 100644 --- a/blockchain/chain_sync/src/sync_worker.rs +++ b/blockchain/chain_sync/src/sync_worker.rs @@ -438,7 +438,10 @@ where } } } - info!("Successfully validated tipset {:?} at epoch: {}", fts_key, epoch); + info!( + "Successfully validated tipset {:?} at epoch: {}", + fts_key, epoch + ); Ok(()) } diff --git a/blockchain/state_manager/src/lib.rs b/blockchain/state_manager/src/lib.rs index d1b8c12f8474..6ae69280a719 100644 --- a/blockchain/state_manager/src/lib.rs +++ b/blockchain/state_manager/src/lib.rs @@ -611,7 +611,7 @@ where } // No active consensus faults. - if base_tipset.epoch() <= miner_state.info(self.blockstore())?.consensus_fault_elapsed() { + if base_tipset.epoch() <= miner_state.info(self.blockstore())?.consensus_fault_elapsed { return Ok(false); } diff --git a/blockchain/state_manager/src/utils.rs b/blockchain/state_manager/src/utils.rs index 4e88c1c456aa..ed556d787693 100644 --- a/blockchain/state_manager/src/utils.rs +++ b/blockchain/state_manager/src/utils.rs @@ -191,30 +191,6 @@ where mas.info(self.blockstore()) } - /// Get all deadlines for a miner. - pub fn get_miner_deadlines( - &self, - tipset: &Tipset, - address: &Address, - ) -> Result, Error> - where - V: ProofVerifier, - { - todo!(); - // let actor = self - // .get_actor(address, tipset.parent_state())? - // .ok_or_else(|| Error::State("Power actor address could not be resolved".to_string()))?; - // let mas = miner::State::load(self.blockstore(), &actor)?; - // let mut out = Vec::with_capacity(mas.num_deadlines() as usize); - // mas.for_each_deadline(self.blockstore(), |_, dl| { - // let post_submissions = dl.into_post_submissions(); - - // out.push(Deadline { post_submissions }); - // Ok(()) - // })?; - // Ok(out) - } - fn for_each_deadline_partition( &self, tipset: &Tipset, diff --git a/node/rpc/src/state_api.rs b/node/rpc/src/state_api.rs index 0ec103f12492..9d42d2156d81 100644 --- a/node/rpc/src/state_api.rs +++ b/node/rpc/src/state_api.rs @@ -39,7 +39,6 @@ use message::{ signed_message::{json::SignedMessageJson, SignedMessage}, unsigned_message::{json::UnsignedMessageJson, UnsignedMessage}, }; -use networks::get_network_version_default; use num_bigint::{bigint_ser, BigInt}; use serde::{Deserialize, Serialize}; use state_manager::{InvocResult, MarketBalance, MiningBaseInfo, StateManager}; @@ -123,6 +122,7 @@ pub(crate) async fn state_call< #[serde(rename_all = "PascalCase")] pub(crate) struct Deadline { post_submissions: BitFieldJson, + disputable_proof_count: usize, } /// returns all the proving deadlines for the given miner @@ -134,26 +134,25 @@ pub(crate) async fn state_miner_deadlines< data: Data>, Params(params): Params<(AddressJson, TipsetKeysJson)>, ) -> Result, JsonRpcError> { - todo!(); - // let (actor, key) = params; - // let actor = actor.into(); - // let mas = data - // .state_manager - // .chain_store() - // .miner_load_actor_tsk(&actor, &key.into()) - // .await - // .map_err(|e| format!("Could not load miner {:?}", e))?; - - // let mut out = Vec::with_capacity(mas.num_deadlines() as usize); - // mas.for_each_deadline(data.state_manager.blockstore(), |_, dl| { - // let ps = dl.into_post_submissions(); - // out.push(Deadline { - // post_submissions: BitFieldJson(ps), - // }); - // Ok(()) - // })?; - - // Ok(out) + let (actor, key) = params; + let actor = actor.into(); + let mas = data + .state_manager + .chain_store() + .miner_load_actor_tsk(&actor, &key.into()) + .await + .map_err(|e| format!("Could not load miner {:?}", e))?; + + let mut out = Vec::with_capacity(mas.num_deadlines() as usize); + mas.for_each_deadline(data.state_manager.blockstore(), |_, dl| { + out.push(Deadline { + post_submissions: dl.partitions_posted().clone().into(), + disputable_proof_count: dl.disputable_proof_count(data.state_manager.blockstore())?, + }); + Ok(()) + })?; + + Ok(out) } /// returns the PreCommit info for the specified miner's sector @@ -187,29 +186,24 @@ pub async fn state_miner_info< data: Data>, Params(params): Params<(AddressJson, TipsetKeysJson)>, ) -> Result { - todo!() - // let state_manager = &data.state_manager; - // let store = state_manager.blockstore(); - // let (AddressJson(addr), TipsetKeysJson(key)) = params; + let state_manager = &data.state_manager; + let store = state_manager.blockstore(); + let (AddressJson(addr), TipsetKeysJson(key)) = params; - // let ts = data.chain_store.tipset_from_keys(&key).await?; - // let actor = data - // .state_manager - // .get_actor(&addr, ts.parent_state()) - // .map_err(|e| format!("Could not load miner {}: {:?}", addr, e))? - // .ok_or_else(|| format!("miner {} does not exist", addr))?; + let ts = data.chain_store.tipset_from_keys(&key).await?; + let actor = data + .state_manager + .get_actor(&addr, ts.parent_state()) + .map_err(|e| format!("Could not load miner {}: {:?}", addr, e))? + .ok_or_else(|| format!("miner {} does not exist", addr))?; - // let miner_state = miner::State::load(store, &actor)?; + let miner_state = miner::State::load(store, &actor)?; - // let mut miner_info = miner_state - // .info(store) - // .map_err(|e| format!("Could not get info {:?}", e))?; + let miner_info = miner_state + .info(store) + .map_err(|e| format!("Could not get info {:?}", e))?; - // // TODO revisit better way of handling (Lotus does here as well) - // if get_network_version_default(ts.epoch()) >= NetworkVersion::V7 { - // miner_info.seal_proof_type.update_to_v1(); - // } - // Ok(miner_info) + Ok(miner_info) } /// returns the on-chain info for the specified miner's sector diff --git a/types/networks/src/interopnet/mod.rs b/types/networks/src/interopnet/mod.rs index 23792f3d3003..ba1fd834cef1 100644 --- a/types/networks/src/interopnet/mod.rs +++ b/types/networks/src/interopnet/mod.rs @@ -32,6 +32,8 @@ pub const UPGRADE_ORANGE_HEIGHT: ChainEpoch = 180; pub const UPGRADE_CLAUS_HEIGHT: ChainEpoch = 210; /// V10 network upgrade height TBD pub const UPGRADE_ACTORS_V3_HEIGHT: ChainEpoch = 999999999; +pub const UPGRADE_PLACEHOLDER_HEIGHT: ChainEpoch = 9999999; + /// Current network version for the network pub const NEWEST_NETWORK_VERSION: NetworkVersion = NetworkVersion::V9; diff --git a/vm/actor/src/builtin/miner/deadline_state.rs b/vm/actor/src/builtin/miner/deadline_state.rs index e0f92773355e..463e963758f3 100644 --- a/vm/actor/src/builtin/miner/deadline_state.rs +++ b/vm/actor/src/builtin/miner/deadline_state.rs @@ -1120,7 +1120,8 @@ impl Deadline { if !already_proven.is_empty() { return Err(Box::new(actor_error!( ErrIllegalArgument, - "parition already proven: {:?}", already_proven + "parition already proven: {:?}", + already_proven ))); } diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index 40a974b4a414..4847f1e04b5f 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -782,10 +782,13 @@ impl Actor { // Check proof, we fail if validation succeeds. match verify_windowed_post(rt, target_deadline.challenge, §or_infos, proofs) { Ok(()) => { - return Err(actor_error!(ErrIllegalArgument, "failed to dispute valid post")); + return Err(actor_error!( + ErrIllegalArgument, + "failed to dispute valid post" + )); } Err(e) => { - log::info!("Successfully disputed: {}",e); + log::info!("Successfully disputed: {}", e); } } diff --git a/vm/actor_interface/src/builtin/market/mod.rs b/vm/actor_interface/src/builtin/market/mod.rs index 3cd59fd149da..ee04c3dc4e71 100644 --- a/vm/actor_interface/src/builtin/market/mod.rs +++ b/vm/actor_interface/src/builtin/market/mod.rs @@ -359,7 +359,6 @@ impl From for DealState { } } - impl BalanceTable<'_, BS> where BS: BlockStore, diff --git a/vm/actor_interface/src/builtin/miner/mod.rs b/vm/actor_interface/src/builtin/miner/mod.rs index 94c5475dea72..a8132df6b027 100644 --- a/vm/actor_interface/src/builtin/miner/mod.rs +++ b/vm/actor_interface/src/builtin/miner/mod.rs @@ -5,7 +5,9 @@ use address::Address; use cid::Cid; use clock::ChainEpoch; use encoding::BytesDe; -use fil_types::{deadlines::DeadlineInfo, RegisteredSealProof, SectorNumber, SectorSize}; +use fil_types::{ + deadlines::DeadlineInfo, RegisteredPoStProof, RegisteredSealProof, SectorNumber, SectorSize, +}; use forest_bitfield::BitField; use forest_json_utils::go_vec_visitor; use ipld_blockstore::BlockStore; @@ -56,15 +58,72 @@ impl State { match self { State::V0(st) => { let info = st.get_info(store)?; - Ok(MinerInfo::V0(info)) + + // Deserialize into peer id if valid, `None` if not. + let peer_id = PeerId::from_bytes(&info.peer_id).ok(); + + Ok(MinerInfo { + owner: info.owner, + worker: info.worker, + control_addresses: info.control_addresses, + new_worker: info.pending_worker_key.as_ref().map(|k| k.new_worker), + worker_change_epoch: info + .pending_worker_key + .map(|k| k.effective_at) + .unwrap_or(-1), + peer_id, + multiaddrs: info.multi_address, + window_post_proof_type: info.seal_proof_type.registered_window_post_proof()?, + sector_size: info.sector_size, + window_post_partition_sectors: info.window_post_partition_sectors, + consensus_fault_elapsed: -1, + }) } State::V2(st) => { let info = st.get_info(store)?; - Ok(MinerInfo::V2(info)) + + // Deserialize into peer id if valid, `None` if not. + let peer_id = PeerId::from_bytes(&info.peer_id).ok(); + + Ok(MinerInfo { + owner: info.owner, + worker: info.worker, + control_addresses: info.control_addresses, + new_worker: info.pending_worker_key.as_ref().map(|k| k.new_worker), + worker_change_epoch: info + .pending_worker_key + .map(|k| k.effective_at) + .unwrap_or(-1), + peer_id, + multiaddrs: info.multi_address, + window_post_proof_type: info.seal_proof_type.registered_window_post_proof()?, + sector_size: info.sector_size, + window_post_partition_sectors: info.window_post_partition_sectors, + consensus_fault_elapsed: info.consensus_fault_elapsed, + }) } State::V3(st) => { let info = st.get_info(store)?; - Ok(MinerInfo::V3(info)) + + // Deserialize into peer id if valid, `None` if not. + let peer_id = PeerId::from_bytes(&info.peer_id).ok(); + + Ok(MinerInfo { + owner: info.owner, + worker: info.worker, + control_addresses: info.control_addresses, + new_worker: info.pending_worker_key.as_ref().map(|k| k.new_worker), + worker_change_epoch: info + .pending_worker_key + .map(|k| k.effective_at) + .unwrap_or(-1), + peer_id, + multiaddrs: info.multi_address, + window_post_proof_type: info.window_post_proof_type, + sector_size: info.sector_size, + window_post_partition_sectors: info.window_post_partition_sectors, + consensus_fault_elapsed: info.consensus_fault_elapsed, + }) } } } @@ -104,9 +163,9 @@ impl State { .load_deadline(store, idx) .map(Deadline::V2)?), State::V3(st) => Ok(st - .load_deadlines(store)? - .load_deadline(store, idx as usize) - .map(Deadline::V3)?), + .load_deadlines(store)? + .load_deadline(store, idx as usize) + .map(Deadline::V3)?), } } @@ -185,8 +244,8 @@ impl State { .get_precommitted_sector(store, sector_num)? .map(From::from)), State::V3(st) => Ok(st - .get_precommitted_sector(store, sector_num)? - .map(From::from)), + .get_precommitted_sector(store, sector_num)? + .map(From::from)), } } @@ -233,35 +292,33 @@ impl State { /// Static information about miner #[derive(Debug, PartialEq, Serialize)] -pub enum MinerInfo { - V0(actorv0::miner::MinerInfo), - V2(actorv2::miner::MinerInfo), - V3(actorv3::miner::MinerInfo), +#[serde(rename_all = "PascalCase")] +pub struct MinerInfo { + #[serde(with = "address::json")] + pub owner: Address, + #[serde(with = "address::json")] + pub worker: Address, + #[serde(with = "address::json::opt")] + pub new_worker: Option
, + #[serde(with = "address::json::vec")] + pub control_addresses: Vec
, // Must all be ID addresses. + pub worker_change_epoch: ChainEpoch, + #[serde(with = "peer_id_json")] + pub peer_id: Option, + pub multiaddrs: Vec, + pub window_post_proof_type: RegisteredPoStProof, + pub sector_size: SectorSize, + pub window_post_partition_sectors: u64, + pub consensus_fault_elapsed: ChainEpoch, } impl MinerInfo { pub fn worker(&self) -> Address { - match self { - Self::V0(info) => info.worker, - Self::V2(info) => info.worker, - Self::V3(info) => info.worker, - } + self.worker } pub fn sector_size(&self) -> SectorSize { - match self { - Self::V0(info) => info.sector_size, - Self::V2(info) => info.sector_size, - Self::V3(info) => info.sector_size, - } - } - - pub fn consensus_fault_elapsed(&self) -> ChainEpoch { - match self { - Self::V0(_info) => -1, - Self::V2(info) => info.consensus_fault_elapsed, - Self::V3(info) => info.consensus_fault_elapsed, - } + self.sector_size } } @@ -273,15 +330,6 @@ pub enum Deadline { } impl Deadline { - /// Consume state to return the deadline post submissions - // pub fn into_post_submissions(self) -> BitField { - // match self { - // Deadline::V0(dl) => dl.post_submissions, - // Deadline::V2(dl) => dl.post_submissions, - // Deadline::V3(dl) => dl.post_submissions, - // } - // } - /// For each partition of the deadline pub fn for_each( &self, @@ -300,6 +348,25 @@ impl Deadline { }), } } + + pub fn disputable_proof_count( + &self, + store: &BS, + ) -> Result> { + Ok(match self { + // Field did not exist in v0 or v2 + Deadline::V0(_) | Deadline::V2(_) => 0, + Deadline::V3(dl) => dl.optimistic_proofs_snapshot_amt(store)?.count(), + }) + } + + pub fn partitions_posted(&self) -> &BitField { + match self { + Deadline::V0(dl) => &dl.post_submissions, + Deadline::V2(dl) => &dl.post_submissions, + Deadline::V3(dl) => &dl.partitions_posted, + } + } } #[allow(clippy::large_enum_variant)] @@ -565,4 +632,3 @@ impl From for SectorPreCommitInfo { } } } - diff --git a/vm/actor_interface/src/builtin/mod.rs b/vm/actor_interface/src/builtin/mod.rs index 5170beed6aeb..959c5a6068d8 100644 --- a/vm/actor_interface/src/builtin/mod.rs +++ b/vm/actor_interface/src/builtin/mod.rs @@ -82,4 +82,4 @@ impl From for FilterEstimate { velocity: filter_est.velocity, } } -} \ No newline at end of file +} diff --git a/vm/actor_interface/src/builtin/multisig/mod.rs b/vm/actor_interface/src/builtin/multisig/mod.rs index 5ec7d944301c..6e78d8919460 100644 --- a/vm/actor_interface/src/builtin/multisig/mod.rs +++ b/vm/actor_interface/src/builtin/multisig/mod.rs @@ -33,8 +33,7 @@ impl State { .get(&actor.state)? .map(State::V2) .ok_or("Actor state doesn't exist in store")?) - } - else if actor.code == *actorv3::MULTISIG_ACTOR_CODE_ID { + } else if actor.code == *actorv3::MULTISIG_ACTOR_CODE_ID { Ok(store .get(&actor.state)? .map(State::V3) diff --git a/vm/actor_interface/src/builtin/reward/mod.rs b/vm/actor_interface/src/builtin/reward/mod.rs index 31d6a55bb227..06d5b920eded 100644 --- a/vm/actor_interface/src/builtin/reward/mod.rs +++ b/vm/actor_interface/src/builtin/reward/mod.rs @@ -38,8 +38,7 @@ impl State { .get(&actor.state)? .map(State::V2) .ok_or("Actor state doesn't exist in store")?) - } - else if actor.code == *actorv3::REWARD_ACTOR_CODE_ID { + } else if actor.code == *actorv3::REWARD_ACTOR_CODE_ID { Ok(store .get(&actor.state)? .map(State::V3) diff --git a/vm/interpreter/src/default_runtime.rs b/vm/interpreter/src/default_runtime.rs index 285fd9c3cccf..15f27904da97 100644 --- a/vm/interpreter/src/default_runtime.rs +++ b/vm/interpreter/src/default_runtime.rs @@ -522,11 +522,7 @@ where let ms = actor::miner::State::load(self.store(), &actor)?; - let worker = match ms.info(&self.store)? { - actor::miner::MinerInfo::V0(info) => info.worker, - actor::miner::MinerInfo::V2(info) => info.worker, - actor::miner::MinerInfo::V3(info) => info.worker, - }; + let worker = ms.info(self.store())?.worker; resolve_to_key_addr(&self.state, &self.store, &worker) } From f0ffc742c657f490ecd1e52932da56f3acb42233 Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Mon, 8 Mar 2021 09:26:24 -0500 Subject: [PATCH 34/35] Cargo Audit Patch --- Cargo.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29f6097e3fa1..0f6a26f31132 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -727,7 +727,7 @@ dependencies = [ "block-padding 0.1.5", "byte-tools", "byteorder 1.4.2", - "generic-array 0.12.3", + "generic-array 0.12.4", ] [[package]] @@ -1493,7 +1493,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" dependencies = [ - "generic-array 0.12.3", + "generic-array 0.12.4", "subtle 1.0.0", ] @@ -1741,7 +1741,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array 0.12.3", + "generic-array 0.12.4", ] [[package]] @@ -2808,18 +2808,18 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ "typenum", ] [[package]] name = "generic-array" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed1e761351b56f54eb9dcd0cfaca9fd0daecf93918e1cfc01c8a3d26ee7adcd" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" dependencies = [ "typenum", ] @@ -3070,7 +3070,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" dependencies = [ "digest 0.8.1", - "generic-array 0.12.3", + "generic-array 0.12.4", "hmac 0.7.1", ] @@ -4454,7 +4454,7 @@ checksum = "0abb021006c01b126a936a8dd1351e0720d83995f4fc942d0d426c654f990745" dependencies = [ "alga", "approx", - "generic-array 0.13.2", + "generic-array 0.13.3", "matrixmultiply", "num-complex 0.2.4", "num-rational 0.2.4", @@ -5406,7 +5406,7 @@ checksum = "c24fcd450d3fa2b592732565aa4f17a27a61c65ece4726353e000939b0edee34" dependencies = [ "libc", "rand_chacha 0.3.0", - "rand_core 0.6.1", + "rand_core 0.6.2", "rand_hc 0.3.0", ] @@ -5427,7 +5427,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ "ppv-lite86", - "rand_core 0.6.1", + "rand_core 0.6.2", ] [[package]] @@ -5456,9 +5456,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" dependencies = [ "getrandom 0.2.1", ] @@ -5497,7 +5497,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" dependencies = [ - "rand_core 0.6.1", + "rand_core 0.6.2", ] [[package]] From ca6c2f39ff5a5f3532d58815e91717a8f11f249c Mon Sep 17 00:00:00 2001 From: Eric Tu Date: Mon, 8 Mar 2021 09:34:52 -0500 Subject: [PATCH 35/35] fil-ocl 0.19.6 --- Cargo.lock | 59 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f6a26f31132..26bf40795daa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1972,9 +1972,9 @@ dependencies = [ [[package]] name = "fil-ocl" -version = "0.19.4" +version = "0.19.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae7dbdc8d931f2cc59e41062ea9caa57a57e0e05a8f844d62d303191f4cc4283" +checksum = "1cb95c3c684138f2522dbedb070c27e6223999b775120936ea7f90b38a823d07" dependencies = [ "failure", "fil-ocl-core", @@ -1986,9 +1986,9 @@ dependencies = [ [[package]] name = "fil-ocl-core" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd0aa5895d05824d7eaa38b999c91e9071acb74b304488220e8f8bb555d1ad1" +checksum = "827ceba5f0c5dc932509a9c097f7f1f671b179c64bc224cffbdf6e39827c0ffc" dependencies = [ "bitflags 1.2.1", "cl-sys", @@ -1997,7 +1997,7 @@ dependencies = [ "num-complex 0.1.43", "num-traits 0.2.14", "ocl-core-vector", - "rustc_version 0.1.7", + "rustc_version 0.3.3", ] [[package]] @@ -4977,6 +4977,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + [[package]] name = "petgraph" version = "0.5.1" @@ -5800,20 +5809,20 @@ checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" [[package]] name = "rustc_version" -version = "0.1.7" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver 0.1.20", + "semver 0.9.0", ] [[package]] name = "rustc_version" -version = "0.2.3" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "semver 0.9.0", + "semver 0.11.0", ] [[package]] @@ -5919,17 +5928,20 @@ dependencies = [ [[package]] name = "semver" -version = "0.1.20" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser 0.7.0", +] [[package]] name = "semver" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "semver-parser", + "semver-parser 0.10.2", ] [[package]] @@ -5938,6 +5950,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + [[package]] name = "serde" version = "1.0.118" @@ -7075,6 +7096,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + [[package]] name = "uint" version = "0.9.0"