diff --git a/Cargo.lock b/Cargo.lock index 2bfeb42a6e59..f1626285d21c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2738,9 +2738,9 @@ checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" [[package]] name = "fil_actor_account_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b524f4c732b747da0d956d27aa739dc411f5c5f60c1f426b6e5e7d41297e6623" +checksum = "0b8d8a278388a502cbe22c7359eaa393eac4451f5accbd977eaee52a28275aaf" dependencies = [ "frc42_macros 3.0.0", "fvm_ipld_encoding", @@ -2754,9 +2754,9 @@ dependencies = [ [[package]] name = "fil_actor_cron_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85163a77783b30e1e8f50acbfa9ce9f9a59b4cfc466e16b267a5391f8090c0eb" +checksum = "6a0601edd6fe61bbcf574371c5502768d7716a55d233234b5e4c1e5693b3c055" dependencies = [ "fvm_ipld_encoding", "fvm_shared 2.6.0", @@ -2769,9 +2769,9 @@ dependencies = [ [[package]] name = "fil_actor_datacap_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e60906336423291085765840056fad664db0a97b27187109c7b45cec101defb2" +checksum = "a3cf2aa6bc17e28a599555d216c2e095aad55cdf0a2e0f66dbd705bf913db5f4" dependencies = [ "fil_actors_shared", "frc42_macros 3.0.0", @@ -2789,9 +2789,9 @@ dependencies = [ [[package]] name = "fil_actor_evm_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60796616a43ccb5eacb61dcd4c7a2f2ef8a7e62eaec9476a55a30c05ebbff82c" +checksum = "58b746a3dad083daf72be0f2757efa82849b3a45601b8e70362d81b5e73fa235" dependencies = [ "cid", "fil_actors_shared", @@ -2809,9 +2809,9 @@ dependencies = [ [[package]] name = "fil_actor_init_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ce9244cbb893e46d586238f71fe6624d16e0c45cc3ea1e5ef7fee63e43be468" +checksum = "84f37e7340dc021d20ef5ea36dfb52f173262d10184b1c924106c328427c5197" dependencies = [ "anyhow", "cid", @@ -2830,9 +2830,9 @@ dependencies = [ [[package]] name = "fil_actor_interface" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24446965e985aaeb427328ae73315740f682bd2a131378cfe774a57ebceee10c" +checksum = "27f5867b4ba96b9c5ff93ed10cfd6b313a5e59862d32599680c6d93daf325049" dependencies = [ "anyhow", "cid", @@ -2868,9 +2868,9 @@ dependencies = [ [[package]] name = "fil_actor_market_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1928a79eff1e7c8f6b12f3c9458132978913ff42827fff605a45f07dffacfc8" +checksum = "f0bc8c9746c93f9b6ac90240ca74f0b060bc78751b16c36f07618913854c0270" dependencies = [ "anyhow", "cid", @@ -2893,9 +2893,9 @@ dependencies = [ [[package]] name = "fil_actor_miner_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3c7aca092651c9f4a1cc9b2d1bd1103acce1fbaaf486a8f4bcb633f9f486644" +checksum = "722f6e09d9114e4b10c5c22299200f34b0b2a82693735b64cb98b13bab9ebca4" dependencies = [ "anyhow", "bitflags 2.4.2", @@ -2923,9 +2923,9 @@ dependencies = [ [[package]] name = "fil_actor_multisig_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a938f4914894f033656f12827a2ac2c6a218d3358ee52133a348b675924031dd" +checksum = "34878068dd52157eb581aa7533cf9a9bfe6f771eeed7b2299a97220b96880701" dependencies = [ "anyhow", "cid", @@ -2946,9 +2946,9 @@ dependencies = [ [[package]] name = "fil_actor_power_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fab1f29798dac7b2a0bac54e9c41abb30de73d480902d596e0db961dfe7d5c4f" +checksum = "7cc4e0b040fea3f81cb0ae1c829ce50024045d75021b582dcb1965f85bc59926" dependencies = [ "anyhow", "cid", @@ -2969,9 +2969,9 @@ dependencies = [ [[package]] name = "fil_actor_reward_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc1d9cd98fffa70097e4ab65e9dfc2027639d2c43ad0d9e2647e594426ca3e2" +checksum = "cdd400b1ef2e5ac539dec5b94d7861747009fdf34fcdfc8e92666d2d5adb852f" dependencies = [ "fvm_ipld_encoding", "fvm_shared 2.6.0", @@ -2985,9 +2985,9 @@ dependencies = [ [[package]] name = "fil_actor_system_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a05e9a431925b3552bb56890ce28d8bfd8b363f0e01c1e5a9b134614ad84327b" +checksum = "70369b47e9e11da6f7cc09edc7b3ec773e706113b83286af0cc2ca5377d6369c" dependencies = [ "cid", "fil_actors_shared", @@ -3002,9 +3002,9 @@ dependencies = [ [[package]] name = "fil_actor_verifreg_state" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc142f12cabce5c349dad96c0895f8e9ab709f5d88a0a41cc00474428174df6c" +checksum = "32259ec6139952b11abbb0a558128cccee44c58a460e1bcb9449e62ac6e9f25f" dependencies = [ "anyhow", "cid", @@ -3015,7 +3015,6 @@ dependencies = [ "fvm_shared 2.6.0", "fvm_shared 3.6.0", "fvm_shared 4.1.2", - "log", "num-derive", "num-traits", "serde", @@ -3023,9 +3022,9 @@ dependencies = [ [[package]] name = "fil_actors_shared" -version = "10.0.0-dev.1" +version = "10.0.0-dev.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57922235170b02269e034ee9b8ab4e09943a56de6a411b9eb5d9b2cae889f8fe" +checksum = "1e8194ff60ad006523bd2b4799c90ff69c2e3e5c719124e310568ac93437bfce" dependencies = [ "anyhow", "cid", diff --git a/Cargo.toml b/Cargo.toml index c571b871d553..4c7655879e03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,18 +52,18 @@ dialoguer = "0.11" digest = "0.10.5" directories = "5" ethereum-types = "0.14.1" -fil_actor_account_state = { version = "10.0.0-dev.1" } -fil_actor_cron_state = { version = "10.0.0-dev.1" } -fil_actor_datacap_state = { version = "10.0.0-dev.1" } -fil_actor_init_state = { version = "10.0.0-dev.1" } -fil_actor_interface = { version = "10.0.0-dev.1" } -fil_actor_market_state = { version = "10.0.0-dev.1" } -fil_actor_miner_state = { version = "10.0.0-dev.1" } -fil_actor_power_state = { version = "10.0.0-dev.1" } -fil_actor_reward_state = { version = "10.0.0-dev.1" } -fil_actor_system_state = { version = "10.0.0-dev.1" } -fil_actor_verifreg_state = { version = "10.0.0-dev.1" } -fil_actors_shared = { version = "10.0.0-dev.1", features = ["json"] } +fil_actor_account_state = { version = "10.0.0-dev.2" } +fil_actor_cron_state = { version = "10.0.0-dev.2" } +fil_actor_datacap_state = { version = "10.0.0-dev.2" } +fil_actor_init_state = { version = "10.0.0-dev.2" } +fil_actor_interface = { version = "10.0.0-dev.2" } +fil_actor_market_state = { version = "10.0.0-dev.2" } +fil_actor_miner_state = { version = "10.0.0-dev.2" } +fil_actor_power_state = { version = "10.0.0-dev.2" } +fil_actor_reward_state = { version = "10.0.0-dev.2" } +fil_actor_system_state = { version = "10.0.0-dev.2" } +fil_actor_verifreg_state = { version = "10.0.0-dev.2" } +fil_actors_shared = { version = "10.0.0-dev.2", features = ["json"] } filecoin-proofs-api = { version = "16.0", default-features = false } flume = "0.11" fs_extra = "1.2" diff --git a/scripts/devnet/.env b/scripts/devnet/.env index 290c497fb5d6..3426aee7ac22 100644 --- a/scripts/devnet/.env +++ b/scripts/devnet/.env @@ -1,4 +1,4 @@ -LOTUS_IMAGE=ghcr.io/chainsafe/lotus-devnet:2024-02-29-a2919fe +LOTUS_IMAGE=lotus-devnet FOREST_DATA_DIR=/forest_data LOTUS_DATA_DIR=/lotus_data FIL_PROOFS_PARAMETER_CACHE=/var/tmp/filecoin-proof-parameters @@ -6,12 +6,12 @@ LOTUS_RPC_PORT=1234 LOTUS_P2P_PORT=1235 MINER_RPC_PORT=2345 FOREST_RPC_PORT=3456 -GENESIS_NETWORK_VERSION=18 -SHARK_HEIGHT=-10 -HYGGE_HEIGHT=-9 -LIGHTNING_HEIGHT=3 -THUNDER_HEIGHT=6 -WATERMELON_HEIGHT=9 -DRAGON_HEIGHT=1000 -DRAND_QUICKNET_HEIGHT=12 -TARGET_HEIGHT=15 +GENESIS_NETWORK_VERSION=21 +SHARK_HEIGHT=-20 +HYGGE_HEIGHT=-22 +LIGHTNING_HEIGHT=-23 +THUNDER_HEIGHT=-24 +WATERMELON_HEIGHT=-1 +DRAGON_HEIGHT=20 +DRAND_QUICKNET_HEIGHT=140 +TARGET_HEIGHT=200 diff --git a/scripts/devnet/lotus.dockerfile b/scripts/devnet/lotus.dockerfile index b4326c1f0d87..26f4112b4b71 100644 --- a/scripts/devnet/lotus.dockerfile +++ b/scripts/devnet/lotus.dockerfile @@ -5,7 +5,7 @@ RUN apt-get update && apt-get install -y ca-certificates build-essential clang o WORKDIR /lotus -RUN git clone --depth 1 --branch v1.25.2 https://github.com/filecoin-project/lotus.git . +RUN git clone --depth 1 --branch asr/migration-nv22 https://github.com/filecoin-project/lotus.git . RUN CGO_CFLAGS_ALLOW="-D__BLST_PORTABLE__" \ CGO_CFLAGS="-D__BLST_PORTABLE__" \ diff --git a/src/networks/actors_bundle.rs b/src/networks/actors_bundle.rs index 9cb05c5007ca..38aa39784f25 100644 --- a/src/networks/actors_bundle.rs +++ b/src/networks/actors_bundle.rs @@ -69,6 +69,7 @@ pub static ACTOR_BUNDLES: Lazy> = Lazy::new(|| { "bafy2bzacedrunxfqta5skb7q7x32lnp4efz2oq7fn226ffm7fu5iqs62jkmvs" @ "v12.0.0-rc.1" for "calibrationnet", "bafy2bzacebl4w5ptfvuw6746w7ev562idkbf5ppq72e6zub22435ws2rukzru" @ "v12.0.0-rc.2" for "calibrationnet", "bafy2bzacednzb3pkrfnbfhmoqtb3bc6dgvxszpqklf3qcc7qzcage4ewzxsca" @ "v12.0.0" for "calibrationnet", + "bafy2bzaceap46ftyyuhninmzelt2ev6kus5itrggszrk5wuhzf2khm47dtrfa" @ "v13.0.0-rc.2" for "calibrationnet", "bafy2bzaceaiy4dsxxus5xp5n5i4tjzkb7sc54mjz7qnk2efhgmsrobjesxnza" @ "v11.0.0" for "butterflynet", "bafy2bzacectxvbk77ntedhztd6sszp2btrtvsmy7lp2ypnrk6yl74zb34t2cq" @ "v12.0.0" for "butterflynet", "bafy2bzacedozk3jh2j4nobqotkbofodq4chbrabioxbfrygpldgoxs3zwgggk" @ "v9.0.3" for "devnet", @@ -80,6 +81,7 @@ pub static ACTOR_BUNDLES: Lazy> = Lazy::new(|| { "bafy2bzacecsuyf7mmvrhkx2evng5gnz5canlnz2fdlzu2lvcgptiq2pzuovos" @ "v10.0.0" for "mainnet", "bafy2bzacecnhaiwcrpyjvzl4uv4q3jzoif26okl3m66q3cijp3dfwlcxwztwo" @ "v11.0.0" for "mainnet", "bafy2bzaceapkgfggvxyllnmuogtwasmsv5qi2qzhc2aybockd6kag2g5lzaio" @ "v12.0.0" for "mainnet", + "bafy2bzacea6f5icdp6t6fs5sexjxmo3q5d2qu4g4ghq6s5eaob6svnmhvltmw" @ "v13.0.0-rc.2" for "mainnet", ]) }); diff --git a/src/networks/calibnet/mod.rs b/src/networks/calibnet/mod.rs index 0790aa6dbc82..c226c8b9c10a 100644 --- a/src/networks/calibnet/mod.rs +++ b/src/networks/calibnet/mod.rs @@ -7,7 +7,10 @@ use libp2p::Multiaddr; use once_cell::sync::Lazy; use std::str::FromStr; -use super::{drand::DRAND_MAINNET, parse_bootstrap_peers, DrandPoint, Height, HeightInfo}; +use super::{ + drand::DRAND_MAINNET, get_upgrade_height_from_env, parse_bootstrap_peers, DrandPoint, Height, + HeightInfo, +}; /// Default genesis car file bytes. pub const DEFAULT_GENESIS: &[u8] = include_bytes!("genesis.car"); @@ -191,10 +194,11 @@ pub static HEIGHT_INFOS: Lazy> = Lazy::new(|| { ), }, ), + // TODO: This shouldn't be modifiable outside of testing ( Height::Dragon, HeightInfo { - epoch: 1_413_574, + epoch: get_upgrade_height_from_env("FOREST_DRAGON_HEIGHT").unwrap_or(1_427_974), bundle: Some( Cid::try_from("bafy2bzaceap46ftyyuhninmzelt2ev6kus5itrggszrk5wuhzf2khm47dtrfa") .unwrap(), diff --git a/src/networks/devnet/mod.rs b/src/networks/devnet/mod.rs index 223d5f11709e..59dc0665e4b1 100644 --- a/src/networks/devnet/mod.rs +++ b/src/networks/devnet/mod.rs @@ -51,14 +51,14 @@ pub static HEIGHT_INFOS: Lazy> = Lazy::new(|| { ( Height::Thunder, HeightInfo { - epoch: get_upgrade_height_from_env("FOREST_THUNDER_HEIGHT").unwrap_or(-1), + epoch: get_upgrade_height_from_env("FOREST_THUNDER_HEIGHT").unwrap_or(-23), bundle: None, }, ), ( Height::Watermelon, HeightInfo { - epoch: get_upgrade_height_from_env("FOREST_WATERMELON_HEIGHT").unwrap_or(10), + epoch: get_upgrade_height_from_env("FOREST_WATERMELON_HEIGHT").unwrap_or(-1), bundle: Some( Cid::try_from("bafy2bzaceasjdukhhyjbegpli247vbf5h64f7uvxhhebdihuqsj2mwisdwa6o") .unwrap(), diff --git a/src/networks/mainnet/mod.rs b/src/networks/mainnet/mod.rs index 4c5443f0b5bb..d479e13383e4 100644 --- a/src/networks/mainnet/mod.rs +++ b/src/networks/mainnet/mod.rs @@ -10,7 +10,7 @@ use std::str::FromStr; use super::{ drand::{DRAND_INCENTINET, DRAND_MAINNET, DRAND_QUICKNET}, - parse_bootstrap_peers, DrandPoint, Height, HeightInfo, + get_upgrade_height_from_env, parse_bootstrap_peers, DrandPoint, Height, HeightInfo, }; const SMOKE_HEIGHT: ChainEpoch = 51000; @@ -202,6 +202,16 @@ pub static HEIGHT_INFOS: Lazy> = Lazy::new(|| { ), }, ), + ( + Height::Dragon, + HeightInfo { + epoch: get_upgrade_height_from_env("FOREST_DRAGON_HEIGHT").unwrap_or(i64::MAX), + bundle: Some( + Cid::try_from("bafy2bzacea6f5icdp6t6fs5sexjxmo3q5d2qu4g4ghq6s5eaob6svnmhvltmw") + .unwrap(), + ), + }, + ), ]) }); diff --git a/src/state_migration/common/mod.rs b/src/state_migration/common/mod.rs index 9fa23061c09b..d7240dbc3c89 100644 --- a/src/state_migration/common/mod.rs +++ b/src/state_migration/common/mod.rs @@ -85,6 +85,12 @@ pub(in crate::state_migration) trait ActorMigration { store: &BS, input: ActorMigrationInput, ) -> anyhow::Result>; + + /// Some migration jobs might need to be deferred to be executed after the regular state migration. + /// These may require some metadata collected during other migrations. + fn is_deferred(&self) -> bool { + false + } } /// Trait that defines the interface for actor migration job to be executed after the state migration. diff --git a/src/state_migration/common/state_migration.rs b/src/state_migration/common/state_migration.rs index 007014eeb908..373aad41f4e1 100644 --- a/src/state_migration/common/state_migration.rs +++ b/src/state_migration/common/state_migration.rs @@ -3,12 +3,14 @@ use std::num::NonZeroUsize; use std::sync::atomic::AtomicU64; +use std::sync::Arc; use crate::cid_collections::CidHashMap; use crate::shim::{clock::ChainEpoch, state_tree::StateTree}; use crate::state_migration::common::MigrationCache; use cid::Cid; use fvm_ipld_blockstore::Blockstore; +use parking_lot::Mutex; use super::PostMigrationCheckArc; use super::{verifier::MigrationVerifier, Migrator, PostMigratorArc}; @@ -78,18 +80,29 @@ impl StateMigration { } let cache = MigrationCache::new(NonZeroUsize::new(10_000).expect("infallible")); + let num_threads = std::env::var("FOREST_STATE_MIGRATION_THREADS") + .ok() + .and_then(|s| s.parse().ok()) + // At least 3 are required to not deadlock the migration. Don't use all CPU, + // otherwise the migration will starve the rest of the system. + .unwrap_or_else(|| 3.max(num_cpus::get() / 2)); + let pool = rayon::ThreadPoolBuilder::new() .thread_name(|id| format!("state migration thread: {id}")) - .num_threads(3) // minimum needed, more doesn't increase performance in any way + .num_threads(num_threads) .build()?; - let (state_tx, state_rx) = crossbeam_channel::bounded(1); - let (job_tx, job_rx) = crossbeam_channel::bounded(1); + let (state_tx, state_rx) = crossbeam_channel::bounded(30); + let (job_tx, job_rx) = crossbeam_channel::bounded(30); let job_counter = AtomicU64::new(0); + let cache_clone = cache.clone(); + + let actors_in = Arc::new(Mutex::new(actors_in)); + let actors_in_clone = actors_in.clone(); pool.scope(|s| { s.spawn(move |_| { - actors_in + actors_in.lock() .for_each(|addr, state| { state_tx .send((addr, state.clone())) @@ -103,7 +116,12 @@ impl StateMigration { while let Ok((address, state)) = state_rx.recv() { let job_tx = job_tx.clone(); let migrator = self.migrations.get(&state.code).cloned().unwrap_or_else(|| panic!("migration failed with state code: {}", state.code)); - let cache_clone = cache.clone(); + + // Deferred migrations should be done at a later time. + if migrator.is_deferred() { + continue; + } + let cache_clone = cache_clone.clone(); scope.spawn(move |_| { let job = MigrationJob { address, @@ -146,6 +164,47 @@ impl StateMigration { } }); + // This is okay to execute even if there are no deferred migrations, as the iteration is + // very cheap; ~200ms on mainnet. The alternative is to collect the deferred migrations + // into a separate collection, which would increase the memory footprint of the migration. + tracing::info!("Processing deferred migrations"); + let mut job_counter = 0; + actors_in_clone.lock().for_each(|address, state| { + job_counter += 1; + let migrator = self + .migrations + .get(&state.code) + .cloned() + .unwrap_or_else(|| panic!("migration failed with state code: {}", state.code)); + + if !migrator.is_deferred() { + return Ok(()); + } + + let job = MigrationJob { + address, + actor_state: state.clone(), + actor_migration: migrator, + }; + let job_output = job.run(store, prior_epoch, cache.clone())?; + if let Some(MigrationJobOutput { + address, + actor_state, + }) = job_output + { + actors_out + .set_actor(&address, actor_state) + .unwrap_or_else(|e| { + panic!( + "Failed setting new actor state at given address: {address}, Reason: {e}" + ) + }); + } + + Ok(()) + })?; + tracing::info!("Processed {job_counter} deferred migrations"); + // execute post migration actions, e.g., create new actors for post_migrator in self.post_migrators.iter() { post_migrator.post_migrate_state(store, &mut actors_out)?; diff --git a/src/state_migration/mod.rs b/src/state_migration/mod.rs index b1580114ef64..2946537d205e 100644 --- a/src/state_migration/mod.rs +++ b/src/state_migration/mod.rs @@ -43,6 +43,7 @@ where (Height::Hygge, nv18::run_migration::), (Height::Lightning, nv19::run_migration::), (Height::Watermelon, nv21::run_migration::), + (Height::Dragon, nv22::run_migration::), ] } NetworkChain::Calibnet => { @@ -53,6 +54,7 @@ where (Height::Watermelon, nv21::run_migration::), (Height::WatermelonFix, nv21fix::run_migration::), (Height::WatermelonFix2, nv21fix2::run_migration::), + (Height::Dragon, nv22::run_migration::), ] } NetworkChain::Butterflynet => { diff --git a/src/state_migration/nv22/market.rs b/src/state_migration/nv22/market.rs index 74a26eee9992..ea3dcb80a0d7 100644 --- a/src/state_migration/nv22/market.rs +++ b/src/state_migration/nv22/market.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2023 ChainSafe Systems +// Copyright 2019-2024 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT //! This module contains the migration logic for the `NV22` upgrade for the @@ -6,39 +6,40 @@ use std::sync::Arc; use crate::shim::econ::TokenAmount; -use crate::{shim::address::Address, utils::db::CborStoreExt}; -use ahash::HashMap; +use crate::utils::db::CborStoreExt; use anyhow::Context; use cid::Cid; use fil_actor_market_state::v12::{ - DealArray as DealArrayOld, DealState as DealStateOld, State as MarketStateOld, + DealProposal, DealState as DealStateOld, State as MarketStateOld, }; use fil_actor_market_state::v13::{ DealState as DealStateNew, ProviderSectorsMap as ProviderSectorsMapNew, SectorDealIDs, SectorDealsMap, State as MarketStateNew, PROVIDER_SECTORS_CONFIG, SECTOR_DEALS_CONFIG, + STATES_AMT_BITWIDTH, }; -use fil_actors_shared::fvm_ipld_amt; + use fil_actors_shared::v12::Array as ArrayOld; use fil_actors_shared::v13::Array as ArrayNew; use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore; -use fvm_shared4::deal::DealID; -use fvm_shared4::sector::SectorNumber; -use fvm_shared4::ActorID; +use fvm_shared4::clock::ChainEpoch; use crate::state_migration::common::{ActorMigration, ActorMigrationInput, ActorMigrationOutput}; use super::miner::ProviderSectors; pub struct MarketMigrator { + upgrade_epoch: ChainEpoch, provider_sectors: Arc, out_cid: Cid, } pub(in crate::state_migration) fn market_migrator( + upgrade_epoch: ChainEpoch, provider_sectors: Arc, out_cid: Cid, ) -> anyhow::Result + Send + Sync>> { Ok(Arc::new(MarketMigrator { + upgrade_epoch, provider_sectors, out_cid, })) @@ -54,12 +55,8 @@ impl ActorMigration for MarketMigrator { .get_cbor(&input.head)? .context("failed to load state")?; - let (provider_sectors, new_states) = self.migrate_provider_sectors_and_states::( - store, - input, - &in_state.states, - &in_state.proposals, - )?; + let (provider_sectors, new_states) = + self.migrate_provider_sectors_and_states(store, &in_state.states, &in_state.proposals)?; let out_state = MarketStateNew { proposals: in_state.proposals, @@ -90,305 +87,64 @@ impl ActorMigration for MarketMigrator { new_head, })) } + + fn is_deferred(&self) -> bool { + true + } } impl MarketMigrator { - fn migrate_provider_sectors_and_states( + fn migrate_provider_sectors_and_states( &self, store: &impl Blockstore, - input: ActorMigrationInput, states: &Cid, proposals: &Cid, ) -> anyhow::Result<(Cid, Cid)> { - let prev_in_states = input - .cache - .get(&market_prev_deal_states_in_key(&input.address)); - - let prev_in_proposals = input - .cache - .get(&market_prev_deal_proposals_in_key(&input.address)); - - let prev_out_states = input - .cache - .get(&market_prev_deal_states_out_key(&input.address)); - - let prev_out_provider_sectors = input - .cache - .get(&market_prev_provider_sectors_out_key(&input.address)); - - let (provider_sectors_root, new_state_array_root) = if let ( - Some(prev_in_states), - Some(prev_in_proposals), - Some(prev_out_states), - Some(prev_out_provider_sectors), - ) = ( - prev_in_states, - prev_in_proposals, - prev_out_states, - prev_out_provider_sectors, - ) { - self.migrate_provider_sectors_and_states_with_diff::( - store, - &prev_in_states, - &prev_in_proposals, - &prev_out_states, - &prev_out_provider_sectors, - states, - )? - } else { - self.migrate_provider_sectors_and_states_with_scratch(store, states)? - }; - - input - .cache - .insert(market_prev_deal_states_in_key(&input.address), *states); - - input.cache.insert( - market_prev_deal_proposals_in_key(&input.address), - *proposals, - ); - - input.cache.insert( - market_prev_deal_states_out_key(&input.address), - new_state_array_root, - ); - - input.cache.insert( - market_prev_provider_sectors_out_key(&input.address), - provider_sectors_root, - ); + //dbg!("running market migration"); + let (provider_sectors_root, new_state_array_root) = + self.migrate_provider_sectors_and_states_with_scratch(store, states, proposals)?; Ok((provider_sectors_root, new_state_array_root)) } - fn migrate_provider_sectors_and_states_with_diff( - &self, - store: &impl Blockstore, - prev_in_states_cid: &Cid, - prev_in_proposals_cid: &Cid, - prev_out_states_cid: &Cid, - prev_out_provider_sectors_cid: &Cid, - in_states_cid: &Cid, - ) -> anyhow::Result<(Cid, Cid)> { - let prev_in_states = ArrayOld::::load(prev_in_states_cid, store)?; - let in_states = ArrayOld::::load(in_states_cid, store)?; - - let mut prev_out_states = ArrayOld::::load(prev_out_states_cid, store)?; - - let mut prev_out_provider_sectors = ProviderSectorsMapNew::load( - store, - prev_out_provider_sectors_cid, - PROVIDER_SECTORS_CONFIG, - "provider sectors", - )?; - - let proposals_array = DealArrayOld::load(prev_in_proposals_cid, store)?; - - // changesets to be applied to `prev_out_provider_sectors` - let mut provider_sectors: HashMap>> = - HashMap::default(); - let mut provider_sectors_remove: HashMap>> = - HashMap::default(); - - let mut add_provider_sector_entry = |deal| -> anyhow::Result { - let deal_to_sector = self.provider_sectors.deal_to_sector.read(); - let sector_id = deal_to_sector - .get(&deal) - .context(format!("deal {deal} not found in provider sectors"))?; - - provider_sectors - .entry(sector_id.miner) - .or_default() - .entry(sector_id.number) - .or_default() - .push(deal); - - Ok(sector_id.number) - }; - - let mut remove_provider_sector_entry = - |deal, mut new_state_prev_state: DealStateNew| -> anyhow::Result { - let sector_number = new_state_prev_state.sector_number; - let proposal = proposals_array.get(deal)?.context("proposal not found")?; - - let provider_id = proposal.provider.id()? as ActorID; - new_state_prev_state.sector_number = 0; - provider_sectors_remove - .entry(provider_id) - .or_default() - .entry(sector_number) - .or_default() - .push(deal); - - Ok(new_state_prev_state) - }; - - let diffs = fvm_ipld_amt::diff(&prev_in_states, &in_states)?; - for change in diffs { - let deal = change.key; - - use fvm_ipld_amt::ChangeType::*; - match change.change_type() { - Add => { - let old_state = change.after.context("missing after state")?; - let sector_number = if old_state.slash_epoch != -1 { - add_provider_sector_entry(deal)? - } else { - 0 - }; - let new_state = DealStateNew { - sector_number, - last_updated_epoch: old_state.last_updated_epoch, - sector_start_epoch: old_state.sector_start_epoch, - slash_epoch: old_state.slash_epoch, - }; - - prev_out_states.set(deal, new_state)?; - } - Remove => { - let prev_out_state = prev_out_states.get(deal)?.context("deal not found")?; - if prev_out_state.slash_epoch != 1 { - // Comment from Go implementation: - // > if the previous OUT state was not slashed then it has a provider sector entry that needs to be removed - remove_provider_sector_entry(deal, *prev_out_state)?; - } - - prev_out_states.delete(deal)?; - } - Modify => { - let prev_old_state = change.before.context("missing before state")?; - let old_state = change.after.context("missing after state")?; - - let mut new_state = *prev_out_states.get(deal)?.context("deal not found")?; - new_state.slash_epoch = old_state.slash_epoch; - new_state.last_updated_epoch = old_state.last_updated_epoch; - new_state.sector_start_epoch = old_state.sector_start_epoch; - - let new_state = - if prev_old_state.slash_epoch != -1 && old_state.slash_epoch != -1 { - remove_provider_sector_entry(deal, new_state)? - } else { - new_state - }; - - prev_out_states.set(deal, new_state)?; - } - } - } - - // process prevOutProviderSectors, first removes, then adds - - for (provider_id, sectors) in provider_sectors_remove.iter() { - let actor_sectors = prev_out_provider_sectors.get(provider_id)?; - - // From Go implementation: - // > this is fine, all sectors of this miner were already not present - // > in ProviderSectors. Sadly because the default value of a non-present - // > sector number in deal state is 0, we can't tell if a sector was - // > removed or if it was never there to begin with, which is why we - // > may occasionally end up here. - let actor_sectors = if let Some(actor_sectors) = actor_sectors { - actor_sectors - } else { - continue; - }; - - let mut actor_sectors = - SectorDealsMap::load(store, actor_sectors, SECTOR_DEALS_CONFIG, "sector deals")?; - - for (sector, deals) in sectors.iter() { - let sector_deals = actor_sectors.get(sector)?; - let sector_deals = if let Some(sector_deals) = sector_deals { - sector_deals - } else { - continue; - }; - - let mut sector_deals = sector_deals.clone(); - for deal in deals.iter() { - if let Some(idx) = sector_deals.deals.iter().position(|d| d == deal) { - sector_deals.deals.remove(idx); - } - } - - if sector_deals.deals.is_empty() { - actor_sectors.delete(sector)?; - } else { - actor_sectors.set(sector, sector_deals)?; - } - } - - if !actor_sectors.is_empty() { - let new_actor_sectors_root = actor_sectors.flush()?; - prev_out_provider_sectors.set(provider_id, new_actor_sectors_root)?; - } else { - prev_out_provider_sectors.delete(provider_id)?; - } - } - - for (provider_id, sectors) in provider_sectors.iter() { - let actor_sectors_root = prev_out_provider_sectors.get(provider_id)?; - let mut actor_sectors = if let Some(actor_sectors_root) = actor_sectors_root { - SectorDealsMap::load( - store, - actor_sectors_root, - SECTOR_DEALS_CONFIG, - "sector deals", - )? - } else { - SectorDealsMap::empty(store, SECTOR_DEALS_CONFIG, "sector deals") - }; - - for (sector, deals) in sectors.iter() { - actor_sectors.set( - sector, - SectorDealIDs { - deals: deals.clone(), - }, - )?; - } - - let new_actor_sectors_root = actor_sectors.flush()?; - prev_out_provider_sectors.set(provider_id, new_actor_sectors_root)?; - } - - let out_provider_sectors_root = prev_out_provider_sectors.flush()?; - let out_states = prev_out_states.flush()?; - - Ok((out_provider_sectors_root, out_states)) - } - + /// This method implements the migration logic as outlined in the [FIP-0076](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0076.md#migration) + // > For each deal state object in the market actor state that has a terminated epoch set to -1: + // > * find the corresponding deal proposal object and extract the provider's actor ID; + // > * in the provider's miner state, find the ID of the sector with the corresponding deal ID in sector metadata; + // > * if such a sector cannot be found, assert that the deal's end epoch has passed and use sector ID 0 [1]; + // > * set the new deal state object's sector number to the sector ID found; + // > * add the deal ID to the ProviderSectors mapping for the provider's actor ID and sector number. + // > For each deal state object in the market actor state that has a terminated epoch set to any other value: + // > * set the deal state object's sector number to 0. fn migrate_provider_sectors_and_states_with_scratch( &self, store: &impl Blockstore, states: &Cid, + proposals: &Cid, ) -> anyhow::Result<(Cid, Cid)> { let old_state_array = ArrayOld::::load(states, store)?; - let mut new_state_array = ArrayNew::::new(store); + let mut new_state_array = + ArrayNew::::new_with_bit_width(store, STATES_AMT_BITWIDTH); - let mut provider_sectors: HashMap>> = - HashMap::default(); + let proposals_array = ArrayOld::::load(proposals, store)?; - // https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0076.md#migration - // FIP-0076: For each deal state object in the market actor state that has a terminated epoch set to -1 old_state_array.for_each(|deal_id, old_state| { - let sector_number = if old_state.slash_epoch == -1 { - // find the corresponding deal proposal object and extract the provider's actor ID; - if let Some(sector_id) = self.provider_sectors.deal_to_sector.read().get(&deal_id) { - provider_sectors - .entry(sector_id.miner) - .or_default() - .entry(sector_id.number) - .or_default() - .push(deal_id); - // set the new deal state object's sector number to the sector ID found - sector_id.number + let proposal = proposals_array + .get(deal_id)? + .context("deal proposal not found")?; + + let sector_number = + if old_state.slash_epoch == -1 && proposal.end_epoch >= self.upgrade_epoch { + // find the corresponding deal proposal object and extract the provider's actor ID; + self.provider_sectors + .deal_to_sector + .read() + .get(&deal_id) + .map(|sector_id| sector_id.number) + .unwrap_or(0) } else { 0 - } - } else { - 0 - }; + }; let new_state = DealStateNew { sector_number, @@ -405,7 +161,7 @@ impl MarketMigrator { let mut out_provider_sectors = ProviderSectorsMapNew::empty(store, PROVIDER_SECTORS_CONFIG, "provider sectors"); - for (miner, sectors) in provider_sectors.iter() { + for (miner, sectors) in self.provider_sectors.miner_to_sector_to_deals.read().iter() { let mut actor_sectors = SectorDealsMap::empty(store, SECTOR_DEALS_CONFIG, "sector deals"); @@ -426,19 +182,3 @@ impl MarketMigrator { Ok((out_provider_sectors_root, new_state_array_root)) } } - -fn market_prev_deal_states_in_key(addr: &Address) -> String { - format!("prev_deal_states_in_{addr}") -} - -fn market_prev_deal_proposals_in_key(addr: &Address) -> String { - format!("prev_deal_proposals_in_{addr}") -} - -fn market_prev_deal_states_out_key(addr: &Address) -> String { - format!("prev_deal_states_out_{addr}") -} - -fn market_prev_provider_sectors_out_key(addr: &Address) -> String { - format!("prev_provider_sectors_out_{addr}") -} diff --git a/src/state_migration/nv22/migration.rs b/src/state_migration/nv22/migration.rs index 14f6a22a28ba..f42f348b814d 100644 --- a/src/state_migration/nv22/migration.rs +++ b/src/state_migration/nv22/migration.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2023 ChainSafe Systems +// Copyright 2019-2024 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT // //! This module contains the migration logic for the `NV22` upgrade. State migration logic @@ -7,18 +7,16 @@ use std::sync::Arc; -use crate::make_butterfly_policy; -use crate::networks::{ChainConfig, Height, NetworkChain}; +use crate::networks::{ChainConfig, Height}; use crate::shim::{ address::Address, clock::ChainEpoch, machine::{BuiltinActor, BuiltinActorManifest}, - sector::{RegisteredPoStProofV3, RegisteredSealProofV3}, state_tree::{StateTree, StateTreeVersion}, }; use anyhow::Context; use cid::Cid; -use fil_actors_shared::v12::runtime::ProofSet; + use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore; @@ -31,8 +29,16 @@ impl StateMigration { store: &Arc, state: &Cid, new_manifest: &BuiltinActorManifest, - chain_config: &ChainConfig, + _chain_config: &ChainConfig, ) -> anyhow::Result<()> { + // TODO: Use the correct epoch for the upgrade once it's fixed in Lotus + //let upgrade_epoch = chain_config + // .height_infos + // .get(&Height::Dragon) + // .context("no height info for network version NV22")? + // .epoch; + let upgrade_epoch = 3654004; + let state_tree = StateTree::new_from_root(store.clone(), state)?; let system_actor = state_tree .get_actor(&Address::new_id(0))? @@ -52,40 +58,6 @@ impl StateMigration { self.add_migrator(code, nil_migrator(new_code)) } - let (policy_old, policy_new) = match &chain_config.network { - NetworkChain::Mainnet => ( - fil_actors_shared::v12::runtime::Policy::mainnet(), - fil_actors_shared::v13::runtime::Policy::mainnet(), - ), - NetworkChain::Calibnet => ( - fil_actors_shared::v12::runtime::Policy::calibnet(), - fil_actors_shared::v13::runtime::Policy::calibnet(), - ), - NetworkChain::Butterflynet => { - (make_butterfly_policy!(v12), make_butterfly_policy!(v13)) - } - NetworkChain::Devnet(_) => { - let mut policy_old = fil_actors_shared::v12::runtime::Policy::mainnet(); - policy_old.minimum_consensus_power = 2048.into(); - policy_old.minimum_verified_allocation_size = 256.into(); - policy_old.pre_commit_challenge_delay = 10; - - let mut proofs = ProofSet::default_seal_proofs(); - proofs.insert(RegisteredSealProofV3::StackedDRG2KiBV1); - proofs.insert(RegisteredSealProofV3::StackedDRG8MiBV1); - policy_old.valid_pre_commit_proof_type = proofs; - - let mut proofs = ProofSet::default_post_proofs(); - proofs.insert(RegisteredPoStProofV3::StackedDRGWindow2KiBV1); - proofs.insert(RegisteredPoStProofV3::StackedDRGWindow8MiBV1); - policy_old.valid_post_proof_type = proofs; - - ( - policy_old, - fil_actors_shared::v13::runtime::Policy::devnet(), - ) - } - }; let miner_old_code = current_manifest.get(BuiltinActor::Miner)?; let miner_new_code = new_manifest.get(BuiltinActor::Miner)?; @@ -96,18 +68,12 @@ impl StateMigration { self.add_migrator( miner_old_code, - miner::miner_migrator( - provider_sectors.clone(), - &policy_old, - &policy_new, - store, - miner_new_code, - )?, + miner::miner_migrator(upgrade_epoch, provider_sectors.clone(), miner_new_code)?, ); self.add_migrator( market_old_code, - market::market_migrator(provider_sectors.clone(), market_new_code)?, + market::market_migrator(upgrade_epoch, provider_sectors.clone(), market_new_code)?, ); self.add_migrator( diff --git a/src/state_migration/nv22/miner.rs b/src/state_migration/nv22/miner.rs index d000b31593b3..3ff1ecdcdc8a 100644 --- a/src/state_migration/nv22/miner.rs +++ b/src/state_migration/nv22/miner.rs @@ -1,54 +1,51 @@ -// Copyright 2019-2023 ChainSafe Systems +// Copyright 2019-2024 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT //! This module contains the migration logic for the `NV22` upgrade for the -//! Miner actor. - -use std::sync::Arc; - -use crate::shim::econ::TokenAmount; -use crate::{ - shim::address::Address, state_migration::common::MigrationCache, utils::db::CborStoreExt, -}; +//! Miner actor. While the `NV22` upgrade does not change the state of the +//! Miner actor, it does change the state of the Market actor, which requires +//! metadata from the Miner actor. +//! +//! As per [FIP-0076](https://github.com/filecoin-project/FIPs/blob/master/FIPS/fip-0076.md#backwards-compatibility) +//! > This proposal requires a state migration to the market actor to add the new ProviderSectors mapping, +//! > and to add a sector number to and remove allocation ID from each DealState. Computing this mapping +//! > requires reading all sector metadata from the miner actor. + +use crate::state_migration::common::{ActorMigration, ActorMigrationInput, ActorMigrationOutput}; use ahash::HashMap; -use anyhow::{bail, Context}; +use anyhow::Context; use cid::Cid; -use fil_actor_miner_state::{v12::State as MinerStateOld, v13::State as MinerStateNew}; -use fil_actors_shared::fvm_ipld_amt; -use fil_actors_shared::v12::{runtime::Policy as PolicyOld, Array as ArrayOld}; -use fil_actors_shared::v13::{runtime::Policy as PolicyNew, Array as ArrayNew}; +use fil_actor_miner_state::v12::State as MinerStateOld; +use fil_actors_shared::v12::Array as ArrayOld; use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::CborStore; +use fvm_shared4::clock::ChainEpoch; use fvm_shared4::deal::DealID; -use fvm_shared4::sector::SectorID; +use fvm_shared4::sector::{SectorID, SectorNumber}; +use fvm_shared4::ActorID; use parking_lot::RwLock; -use tracing::error; - -use crate::state_migration::common::{ - ActorMigration, ActorMigrationInput, ActorMigrationOutput, TypeMigration, TypeMigrator, -}; +use std::sync::Arc; #[derive(Default)] pub struct ProviderSectors { pub deal_to_sector: RwLock>, + pub miner_to_sector_to_deals: RwLock>>>, } pub struct MinerMigrator { + upgrade_epoch: ChainEpoch, provider_sectors: Arc, - policy_new: PolicyNew, out_cid: Cid, } pub(in crate::state_migration) fn miner_migrator( + upgrade_epoch: ChainEpoch, provider_sectors: Arc, - policy_old: &PolicyOld, - policy_new: &PolicyNew, - store: &Arc, out_cid: Cid, ) -> anyhow::Result + Send + Sync>> { Ok(Arc::new(MinerMigrator { + upgrade_epoch, provider_sectors, - policy_new: policy_new.clone(), out_cid, })) } @@ -69,93 +66,31 @@ impl ActorMigration for MinerMigrator { store, )?; - if let Some(prev_sectors_cid) = input.cache.get(&miner_prev_sectors_in_key(&input.address)) - { - let prev_sectors = ArrayOld::::load( - &prev_sectors_cid, - store, - )?; - let diffs = fvm_ipld_amt::diff(&prev_sectors, &in_sectors)?; - - for change in diffs.iter() { - let sector_number = change.key; - match change.change_type() { - fvm_ipld_amt::ChangeType::Add => { - let sector = in_sectors - .get(sector_number)? - .context("Failed to get sector")?; - - if sector.deal_ids.is_empty() { - continue; - } - - let mut sectors = self.provider_sectors.deal_to_sector.write(); - for deal_id in §or.deal_ids { - sectors.insert( - *deal_id, - SectorID { - miner: miner_id, - number: sector_number, - }, - ); - } - } - fvm_ipld_amt::ChangeType::Modify => { - // OhSnap deals - let sector_old = change.before.as_ref().context("Failed to get sector")?; - let sector_new = change.after.as_ref().context("Failed to get sector")?; - - if sector_old.deal_ids.len() != sector_new.deal_ids.len() { - if !sector_old.deal_ids.is_empty() { - error!("old sector: {sector_old:?}, new_sector {sector_new:?}"); - bail!("This is not supported, and should not happen"); - } - - let mut sectors = self.provider_sectors.deal_to_sector.write(); - for deal_id in §or_new.deal_ids { - sectors.insert( - *deal_id, - SectorID { - miner: miner_id, - number: sector_number, - }, - ); - } - } - } - fvm_ipld_amt::ChangeType::Remove => { - // Comment from the Go implementation - // > nothing to do here, market removes deals based on activation/slash status, and can tell what - // > mappings to remove because non-slashed deals already had them - } - }; + in_sectors.for_each(|i, sector| { + if sector.deal_ids.is_empty() || sector.expiration < self.upgrade_epoch { + return Ok(()); } - } else { - // there is no cached migration, so we iterate over all sectors and collect the deal - // ids. - in_sectors.for_each(|_, sector| { - if sector.deal_ids.is_empty() { - return Ok(()); - } - let mut sectors = self.provider_sectors.deal_to_sector.write(); - for (sector_number, deal_id) in sector.deal_ids.iter().enumerate() { - sectors.insert( - *deal_id, - SectorID { - miner: miner_id, - number: sector_number as u64, - }, - ); - } + let mut sectors = self.provider_sectors.deal_to_sector.write(); + for deal_id in sector.deal_ids.iter() { + sectors.insert( + *deal_id, + SectorID { + miner: miner_id, + number: i, + }, + ); + } + drop(sectors); - Ok(()) - })?; - } + let mut sector_deals = self.provider_sectors.miner_to_sector_to_deals.write(); + sector_deals + .entry(miner_id) + .or_default() + .insert(i, sector.deal_ids.clone()); - input - .cache - .insert(miner_prev_sectors_in_key(&input.address), in_state.sectors); + Ok(()) + })?; Ok(Some(ActorMigrationOutput { new_code_cid: self.out_cid, @@ -163,227 +98,3 @@ impl ActorMigration for MinerMigrator { })) } } - -fn miner_prev_sectors_in_key(address: &Address) -> String { - format!("prevSectorsIn-{}", address) -} - -//#[cfg(test)] -//mod tests { -// use super::*; -// use crate::networks::{ChainConfig, Height}; -// use crate::shim::{ -// econ::TokenAmount, -// machine::{BuiltinActor, BuiltinActorManifest}, -// state_tree::{ActorState, StateTree, StateTreeVersion}, -// }; -// use cid::multihash::MultihashDigest; -// use fvm_ipld_encoding::IPLD_RAW; -// use fvm_shared2::bigint::Zero; -// -// #[test] -// fn test_nv21_miner_migration() { -// let store = Arc::new(crate::db::MemoryDB::default()); -// let (mut state_tree_old, manifest_old) = make_input_tree(&store); -// let system_actor_old = state_tree_old -// .get_actor(&fil_actor_interface::system::ADDRESS.into()) -// .unwrap() -// .unwrap(); -// let system_state_old: fil_actor_system_state::v11::State = -// store.get_cbor(&system_actor_old.state).unwrap().unwrap(); -// let manifest_data_cid_old = system_state_old.builtin_actors; -// assert_eq!(manifest_data_cid_old, manifest_old.source_cid()); -// -// let addr_id = 10000; -// let addr = Address::new_id(addr_id); -// let worker_id = addr_id + 100; -// -// // base stuff to create miners -// let miner_cid_old = manifest_old.get(BuiltinActor::Miner).unwrap(); -// let mut miner_state1 = make_base_miner_state(&store, addr_id, worker_id); -// let mut deadline = DeadlineOld::new(&store).unwrap(); -// let mut sectors_snapshot = -// ArrayOld::::new_with_bit_width( -// &store, -// fil_actor_miner_state::v11::SECTORS_AMT_BITWIDTH, -// ); -// sectors_snapshot -// .set( -// 0, -// fil_actor_miner_state::v11::SectorOnChainInfo { -// simple_qa_power: true, -// ..Default::default() -// }, -// ) -// .unwrap(); -// sectors_snapshot -// .set( -// 1, -// fil_actor_miner_state::v11::SectorOnChainInfo { -// simple_qa_power: false, -// ..Default::default() -// }, -// ) -// .unwrap(); -// deadline.sectors_snapshot = sectors_snapshot.flush().unwrap(); -// let deadline_cid = store.put_cbor_default(&deadline).unwrap(); -// let deadlines = DeadlinesOld::new( -// &fil_actors_shared::v11::runtime::Policy::calibnet(), -// deadline_cid, -// ); -// miner_state1.deadlines = store.put_cbor_default(&deadlines).unwrap(); -// -// let miner1_state_cid = store.put_cbor_default(&miner_state1).unwrap(); -// let miner1 = ActorState::new(miner_cid_old, miner1_state_cid, Zero::zero(), 0, None); -// state_tree_old.set_actor(&addr, miner1).unwrap(); -// let tree_root = state_tree_old.flush().unwrap(); -// -// let (new_manifest_cid, _new_manifest) = make_test_manifest(&store, "fil/12/"); -// -// let mut chain_config = ChainConfig::devnet(); -// if let Some(bundle) = &mut chain_config.height_infos[Height::Watermelon as usize].bundle { -// *bundle = new_manifest_cid; -// } -// let new_state_cid = -// super::super::run_migration(&chain_config, &store, &tree_root, 200).unwrap(); -// -// let new_state_cid2 = -// super::super::run_migration(&chain_config, &store, &tree_root, 200).unwrap(); -// -// assert_eq!(new_state_cid, new_state_cid2); -// -// let new_state_tree = StateTree::new_from_root(store.clone(), &new_state_cid).unwrap(); -// let new_miner_state_cid = new_state_tree.get_actor(&addr).unwrap().unwrap().state; -// let new_miner_state: fil_actor_miner_state::v12::State = -// store.get_cbor(&new_miner_state_cid).unwrap().unwrap(); -// let deadlines: fil_actor_miner_state::v12::Deadlines = -// store.get_cbor(&new_miner_state.deadlines).unwrap().unwrap(); -// deadlines -// .for_each(&store, |_, deadline| { -// let sectors_snapshots = -// ArrayNew::::load( -// &deadline.sectors_snapshot, -// &store, -// ) -// .unwrap(); -// assert_eq!( -// sectors_snapshots.get(0).unwrap().unwrap().flags, -// fil_actor_miner_state::v12::SectorOnChainInfoFlags::SIMPLE_QA_POWER -// ); -// assert!(!sectors_snapshots -// .get(1) -// .unwrap() -// .unwrap() -// .flags -// .contains(fil_actor_miner_state::v12::SectorOnChainInfoFlags::SIMPLE_QA_POWER)); -// Ok(()) -// }) -// .unwrap(); -// } -// -// fn make_input_tree(store: &Arc) -> (StateTree, BuiltinActorManifest) { -// let mut tree = StateTree::new(store.clone(), StateTreeVersion::V5).unwrap(); -// -// let (_manifest_cid, manifest) = make_test_manifest(&store, "fil/11/"); -// let system_cid = manifest.get_system(); -// let system_state = fil_actor_system_state::v11::State { -// builtin_actors: manifest.source_cid(), -// }; -// let system_state_cid = store.put_cbor_default(&system_state).unwrap(); -// init_actor( -// &mut tree, -// system_state_cid, -// system_cid, -// &fil_actor_interface::system::ADDRESS.into(), -// Zero::zero(), -// ); -// -// let init_cid = manifest.get_init(); -// let init_state = -// fil_actor_init_state::v11::State::new(&store, "migrationtest".into()).unwrap(); -// let init_state_cid = store.put_cbor_default(&init_state).unwrap(); -// init_actor( -// &mut tree, -// init_state_cid, -// init_cid, -// &fil_actor_interface::init::ADDRESS.into(), -// Zero::zero(), -// ); -// -// tree.flush().unwrap(); -// -// (tree, manifest) -// } -// -// fn init_actor( -// tree: &mut StateTree, -// state: Cid, -// code: Cid, -// addr: &Address, -// balance: TokenAmount, -// ) { -// let actor = ActorState::new(code, state, balance, 0, None); -// tree.set_actor(addr, actor).unwrap(); -// } -// -// fn make_test_manifest(store: &BS, prefix: &str) -> (Cid, BuiltinActorManifest) { -// let mut manifest_data = vec![]; -// for name in [ -// "account", -// "cron", -// "init", -// "storagemarket", -// "storageminer", -// "multisig", -// "paymentchannel", -// "storagepower", -// "reward", -// "system", -// "verifiedregistry", -// "datacap", -// ] { -// let hash = cid::multihash::Code::Identity.digest(format!("{prefix}{name}").as_bytes()); -// let code_cid = Cid::new_v1(IPLD_RAW, hash); -// manifest_data.push((name, code_cid)); -// } -// -// let manifest_cid = store -// .put_cbor_default(&(1, store.put_cbor_default(&manifest_data).unwrap())) -// .unwrap(); -// let manifest = BuiltinActorManifest::load_manifest(store, &manifest_cid).unwrap(); -// -// (manifest_cid, manifest) -// } -// -// fn make_base_miner_state( -// store: &BS, -// owner: fvm_shared3::ActorID, -// worker: fvm_shared3::ActorID, -// ) -> fil_actor_miner_state::v11::State { -// let control_addresses = vec![]; -// let peer_id = vec![]; -// let multi_address = vec![]; -// let window_post_proof_type = -// fvm_shared3::sector::RegisteredPoStProof::StackedDRGWindow2KiBV1; -// let miner_info = fil_actor_miner_state::v11::MinerInfo::new( -// owner, -// worker, -// control_addresses, -// peer_id, -// multi_address, -// window_post_proof_type, -// ) -// .unwrap(); -// -// let miner_info_cid = store.put_cbor_default(&miner_info).unwrap(); -// -// fil_actor_miner_state::v11::State::new( -// &fil_actors_shared::v11::runtime::Policy::calibnet(), -// store, -// miner_info_cid, -// 0, -// 0, -// ) -// .unwrap() -// } -//} diff --git a/src/state_migration/nv22/mod.rs b/src/state_migration/nv22/mod.rs index 7cb1956a3955..2289a0659ce9 100644 --- a/src/state_migration/nv22/mod.rs +++ b/src/state_migration/nv22/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2019-2023 ChainSafe Systems +// Copyright 2019-2024 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT //! This module contains the migration logic for the `NV22` upgrade.