Skip to content

Commit db2aa6c

Browse files
areshandBo Wu
authored andcommitted
make txn output consistent (#185)
Co-authored-by: Bo Wu <[email protected]>
1 parent 19b78ca commit db2aa6c

File tree

13 files changed

+268
-2
lines changed

13 files changed

+268
-2
lines changed

Cargo.lock

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ members = [
252252
"third_party/move/tools/move-unit-test",
253253
"tools/calc-dep-sizes",
254254
"tools/compute-module-expansion-size",
255+
"tools/l1-migration",
255256
"types",
256257
"vm-validator",
257258
]

storage/db-tool/src/replay_on_archive.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,9 @@ impl Opt {
7979
let all_errors = verifier.run()?;
8080
if !all_errors.is_empty() {
8181
error!("{} failed transactions", all_errors.len());
82-
/* errors were printed as found.
8382
for e in all_errors {
8483
error!("Failed: {}", e);
8584
}
86-
*/
8785
process::exit(2);
8886
}
8987
Ok(())

tools/l1-migration/Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[package]
2+
name = "l1-migration"
3+
version = "0.1.0"
4+
5+
authors = { workspace = true }
6+
edition = { workspace = true }
7+
homepage = { workspace = true }
8+
license = { workspace = true }
9+
publish = { workspace = true }
10+
repository = { workspace = true }
11+
rust-version = { workspace = true }
12+
13+
14+
[dependencies]
15+
anyhow = "1.0"
16+
aptos-config = { workspace = true }
17+
aptos-db = { workspace = true }
18+
aptos-storage-interface = { workspace = true }
19+
aptos-types = { workspace = true }
20+
bcs = "0.1"
21+
clap = { version = "4.0", features = ["derive"] }
865 KB
Binary file not shown.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
8740519:1848ea5e9a417e1a90b1bf57f7bf22d0c627da736c5cc884971f9ef5018316d5
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
base:
2+
data_dir: "PATH_TO_YOUR_LOCAL_DB_FOLDER"
3+
role: "full_node"
4+
waypoint:
5+
from_file: "PATH_TO_YOUR_WAYPOINT_FILE"
6+
7+
execution:
8+
genesis_file_location: "PATH_TO_YOUR_GENESIS_BLOB"
9+
10+
# VFN network configuration - connects to both validator and public networks
11+
full_node_networks:
12+
# Public network for other fullnodes
13+
- listen_address: "/ip4/127.0.0.1/tcp/6180"
14+
discovery_method: "onchain"
15+
network_id: "public"
16+
17+
api:
18+
enabled: true
19+
address: 0.0.0.0:8081
20+
21+
storage:
22+
backup_service_address: 0.0.0.0:6186
23+
rocksdb_configs:
24+
enable_storage_sharding: false
25+
26+
state_sync:
27+
state_sync_driver:
28+
bootstrapping_mode: ApplyTransactionOutputsFromGenesis
29+
continuous_syncing_mode: ExecuteTransactionsOrApplyOutputs
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
use anyhow::Result;
2+
use aptos_config::config::{RocksdbConfigs, StorageDirPaths, NO_OP_STORAGE_PRUNER_CONFIG};
3+
use aptos_db::AptosDB;
4+
use aptos_storage_interface::DbReader;
5+
use aptos_types::{transaction::Transaction, waypoint::Waypoint};
6+
use std::path::Path;
7+
use std::fs;
8+
9+
/// Extract genesis transaction and waypoint from an Aptos database
10+
pub fn extract_genesis_and_waypoint(db_path: &str, output_dir: &str) -> Result<()> {
11+
println!("Opening database at: {}", db_path);
12+
13+
// Create storage directory paths
14+
let storage_dir_paths = StorageDirPaths::from_path(Path::new(db_path));
15+
16+
// Open the database with correct API
17+
let db = AptosDB::open(
18+
storage_dir_paths,
19+
true, // readonly
20+
NO_OP_STORAGE_PRUNER_CONFIG, // pruner_config
21+
RocksdbConfigs::default(),
22+
false, // enable_indexer
23+
1, // buffered_state_target_items
24+
10000, // max_num_nodes_per_lru_cache_shard
25+
None, // internal_indexer_db
26+
)?;
27+
28+
println!("Database opened successfully");
29+
30+
// Get the latest version to understand the database state
31+
let latest_version = db.get_synced_version()?;
32+
println!("Latest synced version: {:?}", latest_version);
33+
34+
if latest_version.is_none() {
35+
return Err(anyhow::anyhow!("Database has no synced version"));
36+
}
37+
38+
let latest_ver = latest_version.unwrap();
39+
40+
// Extract genesis transaction
41+
extract_genesis_transaction(&db, latest_ver, output_dir)?;
42+
43+
// Extract waypoint
44+
extract_waypoint(&db, output_dir)?;
45+
46+
println!("✓ Genesis extraction completed successfully!");
47+
println!(" - genesis.blob: Contains the BCS-serialized genesis transaction");
48+
println!(" - waypoint.txt: Contains the initial waypoint for bootstrapping");
49+
50+
Ok(())
51+
}
52+
53+
/// Extract the genesis transaction from the database
54+
fn extract_genesis_transaction(db: &AptosDB, latest_ver: u64, output_dir: &str) -> Result<()> {
55+
println!("Extracting genesis transaction (version 0)...");
56+
let genesis_txn_with_proof = db.get_transaction_by_version(0, latest_ver, false)?;
57+
let genesis_transaction = genesis_txn_with_proof.transaction;
58+
59+
// Serialize the genesis transaction using BCS
60+
let genesis_bytes = bcs::to_bytes(&genesis_transaction)?;
61+
62+
// Write genesis.blob
63+
let genesis_path = format!("{}/genesis.blob", output_dir);
64+
fs::write(&genesis_path, &genesis_bytes)?;
65+
println!("Genesis transaction written to: {}", genesis_path);
66+
println!("Genesis blob size: {} bytes", genesis_bytes.len());
67+
68+
// Print information about the genesis transaction
69+
print_genesis_transaction_info(&genesis_transaction);
70+
71+
Ok(())
72+
}
73+
74+
/// Extract the waypoint from the database using proper waypoint conversion
75+
fn extract_waypoint(db: &AptosDB, output_dir: &str) -> Result<()> {
76+
// Get the ledger info to extract waypoint
77+
let ledger_info_with_sigs = db.get_latest_ledger_info()?;
78+
let ledger_info = ledger_info_with_sigs.ledger_info();
79+
80+
// Generate waypoint using the proper converter
81+
let waypoint = Waypoint::new_any(ledger_info);
82+
83+
// Write waypoint.txt
84+
let waypoint_path = format!("{}/waypoint.txt", output_dir);
85+
fs::write(&waypoint_path, waypoint.to_string())?;
86+
println!("Waypoint written to: {}", waypoint_path);
87+
println!("Waypoint: {}", waypoint);
88+
89+
Ok(())
90+
}
91+
92+
/// Print detailed information about the genesis transaction
93+
fn print_genesis_transaction_info(genesis_transaction: &Transaction) {
94+
match genesis_transaction {
95+
Transaction::GenesisTransaction(genesis_payload) => {
96+
println!("✓ Found GenesisTransaction (WriteSet transaction)");
97+
// Access the payload correctly
98+
match genesis_payload {
99+
aptos_types::transaction::WriteSetPayload::Direct(change_set) => {
100+
println!(" Direct WriteSet payload");
101+
println!(" Change set size: {} bytes", bcs::to_bytes(change_set).unwrap_or_default().len());
102+
},
103+
aptos_types::transaction::WriteSetPayload::Script { .. } => {
104+
println!(" Script-based WriteSet");
105+
},
106+
}
107+
},
108+
Transaction::BlockMetadata(_) => {
109+
println!("⚠ Transaction 0 is BlockMetadata (unexpected for genesis)");
110+
},
111+
Transaction::BlockMetadataExt(_) => {
112+
println!("⚠ Transaction 0 is BlockMetadataExt (unexpected for genesis)");
113+
},
114+
Transaction::BlockEpilogue(_) => {
115+
println!("⚠ Transaction 0 is BlockEpilogue (unexpected for genesis)");
116+
},
117+
Transaction::UserTransaction(_) => {
118+
println!("⚠ Transaction 0 is UserTransaction (unexpected for genesis)");
119+
},
120+
Transaction::StateCheckpoint(_) => {
121+
println!("⚠ Transaction 0 is StateCheckpoint (unexpected for genesis)");
122+
},
123+
Transaction::ValidatorTransaction(_) => {
124+
println!("⚠ Transaction 0 is ValidatorTransaction (unexpected for genesis)");
125+
},
126+
}
127+
}

tools/l1-migration/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod genesis_waypoint_extraction;
2+
3+
pub use genesis_waypoint_extraction::extract_genesis_and_waypoint;

tools/l1-migration/src/main.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use anyhow::Result;
2+
use clap::Parser;
3+
use l1_migration::extract_genesis_and_waypoint;
4+
use std::path::PathBuf;
5+
6+
/// L1 Migration Tool - Extract genesis and waypoint from database
7+
#[derive(Parser)]
8+
#[command(name = "l1-migration")]
9+
#[command(about = "A tool to extract genesis and waypoint data from an Aptos database")]
10+
#[command(version)]
11+
struct Args {
12+
#[command(subcommand)]
13+
command: Commands,
14+
}
15+
16+
#[derive(Parser)]
17+
enum Commands {
18+
/// Generate waypoint and genesis files from database
19+
GenerateWaypointGenesis {
20+
/// Path to the database directory
21+
db_path: PathBuf,
22+
/// Destination directory for extracted files
23+
destination_path: PathBuf,
24+
},
25+
}
26+
27+
fn main() -> Result<()> {
28+
let args = Args::parse();
29+
30+
match args.command {
31+
Commands::GenerateWaypointGenesis { db_path, destination_path } => {
32+
// Validate that the database path exists
33+
if !db_path.exists() {
34+
eprintln!("Error: Database path '{}' does not exist", db_path.display());
35+
std::process::exit(1);
36+
}
37+
38+
// Create destination directory if it doesn't exist
39+
if !destination_path.exists() {
40+
std::fs::create_dir_all(&destination_path)?;
41+
}
42+
43+
// Call the extraction function from the module
44+
let db_path_str = db_path.to_string_lossy();
45+
let destination_path_str = destination_path.to_string_lossy();
46+
47+
extract_genesis_and_waypoint(&db_path_str, &destination_path_str)
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)