pd/migrate/
simple.rs

1//! An example migration script.
2
3use anyhow;
4use cnidarium::{StateDelta, StateWrite, Storage};
5use jmt::RootHash;
6use penumbra_sdk_app::app::StateReadExt as _;
7use penumbra_sdk_sct::component::clock::{EpochManager, EpochRead};
8use std::path::PathBuf;
9
10use crate::network::generate::NetworkConfig;
11pub async fn migrate(
12    storage: Storage,
13    path_to_export: PathBuf,
14    genesis_start: Option<tendermint::time::Time>,
15) -> anyhow::Result<()> {
16    let export_state = storage.latest_snapshot();
17    let root_hash = export_state.root_hash().await.expect("can get root hash");
18    let height = export_state
19        .get_block_height()
20        .await
21        .expect("can get block height");
22    let app_hash_pre_migration: RootHash = root_hash.into();
23    let post_ugprade_height = height.wrapping_add(1);
24
25    /* --------- writing to the jmt  ------------ */
26    tracing::info!(?app_hash_pre_migration, "app hash pre-upgrade");
27    let mut delta = StateDelta::new(export_state);
28    delta.put_raw(
29        "banana".to_string(),
30        "a good fruit (and migration works!)".into(),
31    );
32    delta.put_block_height(0u64);
33    let root_hash = storage.commit_in_place(delta).await?;
34    let app_hash_post_migration: RootHash = root_hash.into();
35    tracing::info!(?app_hash_post_migration, "app hash post upgrade");
36
37    /* --------- collecting genesis data -------- */
38    tracing::info!("generating genesis");
39    let migrated_state = storage.latest_snapshot();
40    let root_hash = migrated_state.root_hash().await.expect("can get root hash");
41    let app_hash: RootHash = root_hash.into();
42    tracing::info!(?root_hash, "root hash from snapshot (post-upgrade)");
43
44    /* ---------- generate genesis ------------  */
45    let chain_id = migrated_state.get_chain_id().await?;
46    let app_state = penumbra_sdk_app::genesis::Content {
47        chain_id,
48        ..Default::default()
49    };
50    let mut genesis = NetworkConfig::make_genesis(app_state.clone()).expect("can make genesis");
51    genesis.app_hash = app_hash
52        .0
53        .to_vec()
54        .try_into()
55        .expect("infaillible conversion");
56    genesis.initial_height = post_ugprade_height as i64;
57    genesis.genesis_time = genesis_start.unwrap_or_else(|| {
58        let now = tendermint::time::Time::now();
59        tracing::info!(%now, "no genesis time provided, detecting a testing setup");
60        now
61    });
62    let checkpoint = app_hash.0.to_vec();
63    let genesis = NetworkConfig::make_checkpoint(genesis, Some(checkpoint));
64
65    let genesis_json = serde_json::to_string(&genesis).expect("can serialize genesis");
66    tracing::info!("genesis: {}", genesis_json);
67    let genesis_path = path_to_export.join("genesis.json");
68    std::fs::write(genesis_path, genesis_json).expect("can write genesis");
69
70    let validator_state_path = path_to_export.join("priv_validator_state.json");
71    let fresh_validator_state = crate::network::generate::NetworkValidator::initial_state();
72    std::fs::write(validator_state_path, fresh_validator_state).expect("can write validator state");
73    Ok(())
74}