Skip to content

Commit

Permalink
[storage] reassemble db restore tool into storage-cli (#304)
Browse files Browse the repository at this point in the history
  • Loading branch information
0o-de-lally committed Aug 14, 2024
1 parent 8164cd2 commit 7c7a82a
Show file tree
Hide file tree
Showing 19 changed files with 449 additions and 61 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ members = [
[workspace.package]
authors = ["libra contributors"]
edition = "2021"
homepage = "https://0l.network/"
homepage = "https://openlibra.io/"
license = "NOASSERTION"
publish = false
repository = "https://github.com/0LNetworkCommunity/libra-framework"
Expand All @@ -44,7 +44,6 @@ libra-tower = { path = "tools/tower" }
libra-types = { path = "types" }
libra-txs = { path = "tools/txs" }
libra-wallet = { path = "tools/wallet" }
# vdf = { git = "https://github.com/0o-de-lally/verifiable_delay.git" }

diem-api-types = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
diem-debugger = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
Expand Down Expand Up @@ -72,6 +71,7 @@ diem-vm = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "re
diem-vm-genesis = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
diem-vm-types = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
diem-executor = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
diem-executor-types = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
diem-framework = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
diem-cached-packages = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
diem-github-client = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
Expand Down Expand Up @@ -257,8 +257,6 @@ serde_json = { version = "1.0.81", features = ["preserve_order"] }
serde_repr = "0.1"
serde_merge = "0.1.3"
serde-name = "0.1.1"
serde-generate = { git = "https://github.com/diem-labs/serde-reflection", rev = "839aed62a20ddccf043c08961cfe74875741ccba" }
serde-reflection = { git = "https://github.com/diem-labs/serde-reflection", rev = "839aed62a20ddccf043c08961cfe74875741ccba" }
serde_yaml = "0.8.24"
shadow-rs = "0.16.2"
smallvec = "1.8.0"
Expand Down Expand Up @@ -321,9 +319,6 @@ serde_with = "^3"
vergen = { version = "8.3.1", features = ["build", "git", "gitcl"] }

######## MOVE DEPENDENCIES ########
# move-abigen = { path = "third_party/move/move-prover/move-abigen" }
# move-binary-format = { path = "third_party/move/move-binary-format" }
# ... see full list in Aptos repo
move-binary-format = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
move-core-types = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
move-command-line-common = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
Expand Down
3 changes: 1 addition & 2 deletions framework/cached-packages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ rust-version = { workspace = true }

[dependencies]
bcs = { workspace = true }
# Note the generated SDK code uses hard coded `diemtypes`
diem-types = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
diem-types = { workspace = true }
move-core-types = { workspace = true }
once_cell = { workspace = true }

Expand Down
6 changes: 2 additions & 4 deletions tools/rescue/tests/diem-proxy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
[workspace]
resolver = "2"

members = [
"diem-node-proxy"
]
members = ["diem-node-proxy"]

[workspace.dependencies]
diem-node = { git = "https://github.com/0LNetworkCommunity/diem.git", branch = "release" }
diem-node = { workspace = true }
5 changes: 5 additions & 0 deletions tools/storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@ anyhow = { workspace = true }
bcs = { workspace = true }
clap = { workspace = true }
diem-backup-cli = { workspace = true }
diem-config = { workspace = true }
diem-db = { workspace = true }
diem-db-tool = { workspace = true }
diem-executor-types = { workspace = true }
diem-logger = { workspace = true }
diem-push-metrics = { workspace = true }
diem-types = { workspace = true }
glob = { workspace = true }
libra-types = { workspace = true }
num_cpus = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }

Expand Down
24 changes: 20 additions & 4 deletions tools/storage/example.makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,40 @@
# you need to use the absolute path of the snapshot files.
ABS_PATH?=`cd "$1"; pwd`
BACKUP_DIR= ${ABS_PATH}/fixtures/v7/
OUTPUT_DB_PATH = ${ABS_PATH}/test_db
# OUTPUT_DB_PATH = ${ABS_PATH}/test_db
OUTPUT_DB_PATH = $HOME/.libra/data/db


# For the epoch restore
EPOCH_MANIFEST = ${BACKUP_DIR}epoch_ending_116-.be9b/epoch_ending.manifest

# For the snapshot restore
STATE_MANIFEST = ${BACKUP_DIR}state_epoch_116_ver_38180075.05af/state.manifest

restore: restore-epoch restore-snapshot

# For the tx restore
TX_MANIFEST = ${BACKUP_DIR}transaction_38100001-.541f/transaction.manifest

TARGET_VERSION = 38180075

restore: restore-epoch restore-snapshot restore-tx

restore-epoch:
libra ops storage db restore oneoff epoch-ending --epoch-ending-manifest ${EPOCH_MANIFEST} --target-db-dir ${OUTPUT_DB_PATH} --local-fs-dir ${BACKUP_DIR}
libra ops storage db restore oneoff epoch-ending --epoch-ending-manifest ${EPOCH_MANIFEST} --target-db-dir ${OUTPUT_DB_PATH} --local-fs-dir ${BACKUP_DIR} --target-version ${TARGET_VERSION}

restore-snapshot:
libra ops storage db restore oneoff state-snapshot --state-manifest ${STATE_MANIFEST} --target-db-dir ${OUTPUT_DB_PATH} --local-fs-dir ${BACKUP_DIR} --restore-mode default --state-into-version 1
libra ops storage db restore oneoff state-snapshot --state-manifest ${STATE_MANIFEST} --target-db-dir ${OUTPUT_DB_PATH} --local-fs-dir ${BACKUP_DIR} --restore-mode default --state-into-version ${TARGET_VERSION} --target-version ${TARGET_VERSION}

restore-tx:
libra ops storage db restore oneoff transaction --transaction-manifest ${TX_MANIFEST} --target-db-dir ${OUTPUT_DB_PATH} --local-fs-dir ${BACKUP_DIR} --target-version ${TARGET_VERSION}


echo:
@echo ${ABS_PATH}
@echo ${BACKUP_DIR}
@echo ${EPOCH_MANIFEST}
@echo ${STATE_MANIFEST}

config:
libra config fullnode-init

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"first_version":38100001,"last_version":38200000,"chunks":[{"first_version":38100001,"last_version":38200000,"transactions":"transaction_38100001-.541f/38100001-.chunk","proof":"transaction_38100001-.541f/38100001-38200000.proof"}]}
Binary file not shown.
139 changes: 139 additions & 0 deletions tools/storage/src/dbtool_init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
//! refactoring the internals of Vendor DBTool::Oneoff
//! source: <diem> storage/db-tool/src/restore.rs
use crate::restore_bundle::RestoreBundle;

use std::{
path::{Path, PathBuf},
sync::Arc,
};

use anyhow::Result;
use diem_backup_cli::{
backup_types::{
epoch_ending::restore::{EpochEndingRestoreController, EpochEndingRestoreOpt},
state_snapshot::restore::{StateSnapshotRestoreController, StateSnapshotRestoreOpt},
transaction::restore::{TransactionRestoreController, TransactionRestoreOpt},
},
storage::{local_fs::LocalFs, BackupStorage},
utils::{GlobalRestoreOptions, RestoreRunMode, TrustedWaypointOpt},
};
use diem_config::config::{
RocksdbConfigs, BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
NO_OP_STORAGE_PRUNER_CONFIG,
};
use diem_db::{state_restore::StateSnapshotRestoreMode, DiemDB, GetRestoreHandler};
use diem_executor_types::VerifyExecutionMode;

/// types of db restore. Note: all of them are necessary for a successful restore.
pub enum RestoreTypes {
Epoch,
Snapshot,
Transaction,
}

pub fn get_backup_storage(local_fs_dir: PathBuf) -> Result<Arc<dyn BackupStorage>> {
Ok(Arc::new(LocalFs::new(local_fs_dir)))
}

pub fn get_global_db_opts(
db_dir: &Path,
bundle: &RestoreBundle,
) -> anyhow::Result<GlobalRestoreOptions> {
let restore_handler = Arc::new(DiemDB::open_kv_only(
db_dir.to_owned(),
false, /* read_only */
NO_OP_STORAGE_PRUNER_CONFIG, /* pruner config */
RocksdbConfigs::default(),
false,
BUFFERED_STATE_TARGET_ITEMS,
DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD,
)?)
.get_restore_handler();

let run_mode = RestoreRunMode::Restore { restore_handler };

let twp = TrustedWaypointOpt {
trust_waypoint: vec![bundle.waypoint.expect("no waypoint")],
};

Ok(GlobalRestoreOptions {
target_version: bundle.version,
trusted_waypoints: Arc::new(twp.verify().expect("cannot verify waypoint")),
run_mode: Arc::new(run_mode),
concurrent_downloads: num_cpus::get(),
replay_concurrency_level: 4,
})
}

pub async fn run_restore(
rtype: RestoreTypes,
db_path: &Path,
bundle: &RestoreBundle,
) -> anyhow::Result<()> {
let global = get_global_db_opts(db_path, bundle)?;

let storage = get_backup_storage(bundle.restore_bundle_dir.to_path_buf())?;

match rtype {
RestoreTypes::Epoch => {
EpochEndingRestoreController::new(
EpochEndingRestoreOpt {
manifest_handle: bundle.epoch_manifest.to_str().unwrap().to_string(),
},
global,
storage,
)
.run(None)
.await?;
}
RestoreTypes::Snapshot => {
StateSnapshotRestoreController::new(
StateSnapshotRestoreOpt {
manifest_handle: bundle.snapshot_manifest.to_str().unwrap().to_string(),
version: bundle.version,
validate_modules: false,
restore_mode: StateSnapshotRestoreMode::Default,
},
global,
storage,
None, /* epoch_history */
)
.run()
.await?;
}
RestoreTypes::Transaction => {
TransactionRestoreController::new(
TransactionRestoreOpt {
manifest_handle: bundle.transaction_manifest.to_str().unwrap().to_string(),
replay_from_version: None,
kv_only_replay: None,
},
global,
storage,
None, /* epoch_history */
VerifyExecutionMode::NoVerify,
)
.run()
.await?;
}
}
Ok(())
}

// TODO: perhaps deprecated since this test is nearly identical to restore::test_full_restore
#[tokio::test]
async fn test_restore() -> anyhow::Result<()> {
let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let mut b = RestoreBundle::new(dir.join("fixtures/v7"));
b.load()?;
let db_temp = diem_temppath::TempPath::new();
db_temp.create_as_dir().unwrap();
run_restore(RestoreTypes::Epoch, db_temp.path(), &b).await?;
run_restore(RestoreTypes::Snapshot, db_temp.path(), &b).await?;
run_restore(RestoreTypes::Transaction, db_temp.path(), &b).await?;

assert!(db_temp.path().join("ledger_db").exists());
assert!(db_temp.path().join("state_merkle_db").exists());
Ok(())
}
3 changes: 3 additions & 0 deletions tools/storage/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
pub mod dbtool_init;
pub mod read_snapshot;
pub mod restore;
pub mod restore_bundle;
pub mod storage_cli;
38 changes: 38 additions & 0 deletions tools/storage/src/restore.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Do a full restoration given a RestoreBundle with verified manifests

use std::path::Path;

use crate::{
dbtool_init::{run_restore, RestoreTypes},
restore_bundle::RestoreBundle,
};

pub async fn full_restore(db_destination: &Path, bundle: &RestoreBundle) -> anyhow::Result<()> {
assert!(
bundle.is_loaded(),
"the restore bundle hasn't been checked yet"
);

run_restore(RestoreTypes::Epoch, db_destination, bundle).await?;
run_restore(RestoreTypes::Snapshot, db_destination, bundle).await?;
run_restore(RestoreTypes::Transaction, db_destination, bundle).await?;

Ok(())
}

#[tokio::test]
async fn test_full_restore() -> anyhow::Result<()> {
use std::path::PathBuf;
let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let mut b = RestoreBundle::new(dir.join("fixtures/v7"));
b.load().unwrap();
let mut db_temp = diem_temppath::TempPath::new();
db_temp.persist();
db_temp.create_as_dir()?;

full_restore(db_temp.path(), &b).await?;

assert!(db_temp.path().join("ledger_db").exists());
assert!(db_temp.path().join("state_merkle_db").exists());
Ok(())
}
Loading

0 comments on commit 7c7a82a

Please sign in to comment.