Skip to content

Commit 5ae11c2

Browse files
committed
[all resource export] add import codes
1 parent 5e7789a commit 5ae11c2

File tree

4 files changed

+114
-1
lines changed

4 files changed

+114
-1
lines changed

Cargo.lock

+3-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/resource-code-exporter/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ serde_json = { workspace = true }
1717
starcoin-crypto = { workspace = true }
1818
starcoin-statedb = { workspace = true }
1919
starcoin-storage = { workspace = true }
20+
starcoin-types = { workspace = true }
21+
tempfile = "3.19.1"
2022

2123

2224
[dev-dependencies]

cmd/resource-code-exporter/src/export.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copyright (c) The Starcoin Core Contributors
2+
// SPDX-License-Identifier: Apache-2.0
3+
14
use clap::Parser;
25
use starcoin_crypto::HashValue;
36
use starcoin_statedb::{ChainStateDB, ChainStateReader};
@@ -106,6 +109,7 @@ mod test {
106109
use starcoin_config::ChainNetwork;
107110
use test_helper::executor::prepare_genesis;
108111
use std::io::Cursor;
112+
use tempfile::TempDir;
109113

110114
#[test]
111115
fn test_export_from_statedb() -> anyhow::Result<()> {
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use starcoin_crypto::HashValue;
2+
use starcoin_statedb::{ChainStateDB, ChainStateReader, ChainStateWriter};
3+
use starcoin_storage::{db_storage::DBStorage, storage::StorageInstance, Storage, StorageVersion};
4+
use starcoin_types::account_address::AccountAddress;
5+
use starcoin_types::state_set::{AccountStateSet, ChainStateSet};
6+
use std::path::Path;
7+
use std::sync::Arc;
8+
9+
/// Import resources and code from CSV file to a new statedb
10+
pub fn import(statedb: &ChainStateDB, csv_path: &Path) -> anyhow::Result<()> {
11+
// Read CSV file
12+
let mut csv_reader = csv::Reader::from_path(csv_path)?;
13+
let mut expected_state_root = None;
14+
let mut state_sets = Vec::new();
15+
16+
for result in csv_reader.records() {
17+
let record = result?;
18+
let address: AccountAddress = serde_json::from_str(&record[0])?;
19+
let state_root: HashValue = serde_json::from_str(&record[1])?;
20+
let account_state: AccountStateSet = serde_json::from_str(&record[2])?;
21+
22+
// Store the first state root as expected
23+
if expected_state_root.is_none() {
24+
expected_state_root = Some(state_root);
25+
}
26+
27+
// Add to state sets
28+
state_sets.push((address, account_state));
29+
}
30+
31+
// Create chain state set and apply it
32+
let chain_state_set = ChainStateSet::new(state_sets);
33+
statedb.apply(chain_state_set)?;
34+
35+
// Get new state root
36+
let new_state_root = statedb.state_root();
37+
38+
// Verify state root matches
39+
if let Some(expected) = expected_state_root {
40+
assert_eq!(
41+
new_state_root, expected,
42+
"Imported state root does not match expected state root"
43+
);
44+
println!("Import successful! State root: {}", new_state_root);
45+
}
46+
Ok(())
47+
}
48+
49+
#[cfg(test)]
50+
mod test {
51+
use super::*;
52+
use crate::export::export_from_statedb;
53+
use std::fs::create_dir_all;
54+
use tempfile::TempDir;
55+
use test_helper::executor::prepare_genesis;
56+
57+
#[test]
58+
fn test_import_from_csv() -> anyhow::Result<()> {
59+
//////////////////////////////////////////////////////
60+
// Step 1: Do Export
61+
// Initialize test storage with genesis
62+
let (export_chain_statedb, _net) = prepare_genesis();
63+
let export_state_root = export_chain_statedb.state_root();
64+
65+
// Create a temporary directory for test files
66+
let temp_dir = TempDir::new()?;
67+
let export_path = temp_dir.path().join("export.csv");
68+
// Export data
69+
{
70+
let mut csv_writer = csv::WriterBuilder::new().from_path(&export_path)?;
71+
export_from_statedb(&export_chain_statedb, export_state_root, &mut csv_writer)?;
72+
}
73+
74+
75+
//////////////////////////////////////////////////////
76+
// Step 2: Do Import
77+
let import_db_path = temp_dir.path().join("import_db");
78+
if !import_db_path.exists() {
79+
create_dir_all(&import_db_path)?;
80+
}
81+
// Create new statedb from imported data
82+
let db_storage = DBStorage::open_with_cfs(
83+
&import_db_path,
84+
StorageVersion::current_version()
85+
.get_column_family_names()
86+
.to_vec(),
87+
false,
88+
Default::default(),
89+
None,
90+
)?;
91+
let storage = Storage::new(StorageInstance::new_db_instance(db_storage))?;
92+
let storage = Arc::new(storage);
93+
let imported_statedb = ChainStateDB::new(storage.clone(), None);
94+
import(&imported_statedb, &export_path)?;
95+
96+
// Verify state root matches
97+
assert_eq!(
98+
imported_statedb.state_root(),
99+
export_state_root,
100+
"Imported state root does not match genesis state root"
101+
);
102+
103+
Ok(())
104+
}
105+
}

0 commit comments

Comments
 (0)