diff --git a/.gitignore b/.gitignore index c487282..dd07e58 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ debug/ target/ # Cargo.lock has no effects on the consumers of a library crate -/Cargo.lock +Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk diff --git a/examples/insert/Cargo.toml b/examples/insert/Cargo.toml new file mode 100644 index 0000000..3d375e7 --- /dev/null +++ b/examples/insert/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "insert" +version = "0.1.0" +edition = "2024" + +[dependencies] +alloy-primitives = "1.2.1" +alloy-trie = "0.8.1" +rand = "0.9.1" +triedb = { path = "../.." } + +[profile.release] +debug = true diff --git a/examples/insert/src/main.rs b/examples/insert/src/main.rs new file mode 100644 index 0000000..8d4b615 --- /dev/null +++ b/examples/insert/src/main.rs @@ -0,0 +1,91 @@ +use std::env; + +use alloy_primitives::{Address, StorageKey, StorageValue, U256}; +use alloy_trie::{EMPTY_ROOT_HASH, KECCAK_EMPTY}; +use rand::prelude::*; +use triedb::{ + Database, + account::Account, + path::{AddressPath, StoragePath}, + transaction::TransactionError, +}; + +pub const DEFAULT_SETUP_DB_EOA_SIZE: usize = 1_000_000; +pub const DEFAULT_SETUP_DB_CONTRACT_SIZE: usize = 100_000; +pub const DEFAULT_SETUP_DB_STORAGE_PER_CONTRACT: usize = 10; +const SEED_EOA: u64 = 42; // EOA seeding value +const SEED_CONTRACT: u64 = 43; // contract account seeding value + +pub fn generate_random_address(rng: &mut StdRng) -> AddressPath { + let addr = Address::random_with(rng); + AddressPath::for_address(addr) +} + +pub fn setup_database( + db: &Database, + repeat: usize, + eoa_size: usize, + contract_size: usize, + storage_per_contract: usize, +) -> Result<(), TransactionError> { + // Populate database with initial accounts + let mut eoa_rng = StdRng::seed_from_u64(SEED_EOA); + let mut contract_rng = StdRng::seed_from_u64(SEED_CONTRACT); + for _i in 0..repeat { + let mut tx = db.begin_rw()?; + for i in 1..=eoa_size { + let address = generate_random_address(&mut eoa_rng); + let account = + Account::new(i as u64, U256::from(i as u64), EMPTY_ROOT_HASH, KECCAK_EMPTY); + + tx.set_account(address, Some(account))?; + } + + for i in 1..=contract_size { + let address = generate_random_address(&mut contract_rng); + let account = + Account::new(i as u64, U256::from(i as u64), EMPTY_ROOT_HASH, KECCAK_EMPTY); + + tx.set_account(address.clone(), Some(account))?; + + // add random storage to each account + for key in 1..=storage_per_contract { + let storage_key = StorageKey::from(U256::from(key)); + let storage_path = + StoragePath::for_address_path_and_slot(address.clone(), storage_key); + let storage_value = + StorageValue::from_be_slice(storage_path.get_slot().pack().as_slice()); + + tx.set_storage_slot(storage_path, Some(storage_value))?; + } + } + + tx.commit()?; + } + println!("root hash: {:?}", db.state_root()); + + Ok(()) +} + +fn main() { + let args: Vec = env::args().collect(); + + let db_path = args.get(1).map(|s| s.to_owned()).unwrap_or_else(|| "test.db".to_string()); + let repeat = args.get(2).and_then(|s| s.parse::().ok()).unwrap_or(1); + let eoa_size = + args.get(3).and_then(|s| s.parse::().ok()).unwrap_or(DEFAULT_SETUP_DB_EOA_SIZE); + let contract_size = + args.get(4).and_then(|s| s.parse::().ok()).unwrap_or(DEFAULT_SETUP_DB_CONTRACT_SIZE); + let storage_per_contract = args + .get(5) + .and_then(|s| s.parse::().ok()) + .unwrap_or(DEFAULT_SETUP_DB_STORAGE_PER_CONTRACT); + + let db = Database::options().create(true).wipe(true).open(db_path).unwrap(); + + println!("eoa size: {eoa_size}"); + println!("repeat {repeat} times"); + println!("contract size: {contract_size}, storage per contract: {storage_per_contract}"); + + setup_database(&db, repeat, eoa_size, contract_size, storage_per_contract).unwrap(); +}