pd/migrate/
mainnet4.rs

1//! Migration for shipping consensus-breaking LQT functionality.
2//!
3//! This migration is a no-op in terms of state. It'll perform the required
4//! APP_VERSION munging for UIP-6, and generate the usual new genesis and validator
5//! watermark files.use cnidarium::{StateDelta, Storage};
6use cnidarium::{StateDelta, Storage};
7use jmt::RootHash;
8use penumbra_sdk_app::app::StateReadExt as _;
9use penumbra_sdk_app::app_version::migrate_app_version;
10use penumbra_sdk_governance::StateWriteExt;
11use penumbra_sdk_sct::component::clock::EpochManager;
12use penumbra_sdk_sct::component::clock::EpochRead;
13use std::path::PathBuf;
14use tracing::instrument;
15
16use crate::network::generate::NetworkConfig;
17
18/// Run the full migration, emitting a new genesis event, representing historical state.
19///
20/// This will have the effect of reinserting packets which had acknowledgements containing
21/// errors, and erroneously removed from state, as if the acknowledgements had contained successes.
22#[instrument]
23pub async fn migrate(
24    storage: Storage,
25    pd_home: PathBuf,
26    genesis_start: Option<tendermint::time::Time>,
27) -> anyhow::Result<()> {
28    // Setup:
29    let initial_state = storage.latest_snapshot();
30    let chain_id = initial_state.get_chain_id().await?;
31    let root_hash = initial_state
32        .root_hash()
33        .await
34        .expect("chain state has a root hash");
35    // We obtain the pre-upgrade hash solely to log it as a result.
36    let pre_upgrade_root_hash: RootHash = root_hash.into();
37    let pre_upgrade_height = initial_state
38        .get_block_height()
39        .await
40        .expect("chain state has a block height");
41    let post_upgrade_height = pre_upgrade_height.wrapping_add(1);
42
43    let mut delta = StateDelta::new(initial_state);
44    let (migration_duration, post_upgrade_root_hash) = {
45        let start_time = std::time::SystemTime::now();
46
47        migrate_app_version(&mut delta, 11).await?;
48
49        // Reset the application height and halt flag.
50        delta.ready_to_start();
51        delta.put_block_height(0u64);
52
53        // Finally, commit the changes to the chain state.
54        let post_upgrade_root_hash = storage.commit_in_place(delta).await?;
55        tracing::info!(?post_upgrade_root_hash, "post-migration root hash");
56
57        (
58            start_time.elapsed().expect("start is set"),
59            post_upgrade_root_hash,
60        )
61    };
62    storage.release().await;
63
64    // The migration is complete, now we need to generate a genesis file. To do this, we need
65    // to lookup a validator view from the chain, and specify the post-upgrade app hash and
66    // initial height.
67    let app_state = penumbra_sdk_app::genesis::Content {
68        chain_id,
69        ..Default::default()
70    };
71    let mut genesis = NetworkConfig::make_genesis(app_state.clone()).expect("can make genesis");
72    genesis.app_hash = post_upgrade_root_hash
73        .0
74        .to_vec()
75        .try_into()
76        .expect("infallible conversion");
77
78    genesis.initial_height = post_upgrade_height as i64;
79    genesis.genesis_time = genesis_start.unwrap_or_else(|| {
80        let now = tendermint::time::Time::now();
81        tracing::info!(%now, "no genesis time provided, detecting a testing setup");
82        now
83    });
84    let checkpoint = post_upgrade_root_hash.0.to_vec();
85    let genesis = NetworkConfig::make_checkpoint(genesis, Some(checkpoint));
86    let genesis_json = serde_json::to_string(&genesis).expect("can serialize genesis");
87    tracing::info!("genesis: {}", genesis_json);
88    let genesis_path = pd_home.join("genesis.json");
89    std::fs::write(genesis_path, genesis_json).expect("can write genesis");
90
91    let validator_state_path = pd_home.join("priv_validator_state.json");
92    let fresh_validator_state = crate::network::generate::NetworkValidator::initial_state();
93    std::fs::write(validator_state_path, fresh_validator_state).expect("can write validator state");
94
95    tracing::info!(
96        pre_upgrade_height,
97        post_upgrade_height,
98        ?pre_upgrade_root_hash,
99        ?post_upgrade_root_hash,
100        duration = migration_duration.as_secs(),
101        "successful migration!"
102    );
103
104    Ok(())
105}