use async_std::sync::{Arc, Mutex}; use incrementalmerkletree::bridgetree::BridgeTree; use lazy_init::Lazy; use pasta_curves::{group::ff::Field, pallas::Base}; use rand::rngs::OsRng; use serde::ser::{Serialize, SerializeStruct, Serializer}; use darkfi::{ blockchain::Blockchain, consensus::{TESTNET_GENESIS_HASH_BYTES, TESTNET_GENESIS_TIMESTAMP}, crypto::{ constants::MERKLE_DEPTH, keypair::{PublicKey, SecretKey}, merkle_node::MerkleNode, }, node::{ state::{state_transition, ProgramState}, Client, MemoryState, State, }, util::{cli::progress_bar, expand_path}, wallet::walletdb::init_wallet, }; // Auxiliary struct to Serialize BridgeTree struct BridgeTreeWrapper { tree: BridgeTree, } impl Serialize for BridgeTreeWrapper { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut state = serializer.serialize_struct("BridgeTreeWrapper", 1)?; state.serialize_field("tree", &self.tree)?; state.end() } } pub fn bridge_tree_usage(prefix: &str, tree: BridgeTree) { let wrapper = BridgeTreeWrapper { tree }; let encoded: Vec = bincode::serialize(&wrapper).unwrap(); let size = ::std::mem::size_of_val(&*encoded); println!(" {} size: {:?} Bytes", prefix, size); } #[async_std::main] async fn main() -> darkfi::Result<()> { // Config let folder = "~/.config/darkfi/merkle_testing"; let genesis_ts = *TESTNET_GENESIS_TIMESTAMP; let genesis_data = *TESTNET_GENESIS_HASH_BYTES; let pass = "changeme"; // Initialize let pb = progress_bar("Initializing wallet..."); let path = folder.to_owned() + "/wallet.db"; let wallet = init_wallet(&path, &pass).await?; let client = Arc::new(Client::new(wallet.clone()).await?); let address = wallet.get_default_address().await?; let pubkey = PublicKey::try_from(address)?; pb.finish(); let pb = progress_bar("Initializing sled database..."); let path = folder.to_owned() + "/blockchain/testnet"; let db_path = expand_path(&path).unwrap(); let sled_db = sled::open(&db_path)?; pb.finish(); let pb = progress_bar("Generating state machine..."); let blockchain = Blockchain::new(&sled_db, genesis_ts, genesis_data)?; let state_machine = State { tree: client.get_tree().await?, merkle_roots: blockchain.merkle_roots.clone(), nullifiers: blockchain.nullifiers.clone(), cashier_pubkeys: vec![], faucet_pubkeys: vec![pubkey.clone()], mint_vk: Lazy::new(), burn_vk: Lazy::new(), }; pb.finish(); let pb = progress_bar("Creating zk proof verification keys..."); let _ = state_machine.mint_vk(); let _ = state_machine.burn_vk(); pb.finish(); let pb = progress_bar("Generating memory state and secret keys..."); let canon_state_clone = state_machine.clone(); let mut state = state_machine; let mut mem_state = MemoryState::new(canon_state_clone); let state_arc = Arc::new(Mutex::new(state.clone())); let secret_keys: Vec = client.get_keypairs().await?.iter().map(|x| x.secret).collect(); pb.finish(); // Initial size bridge_tree_usage("Original state", state.tree.clone()); // Create txs token let token_id = Base::random(&mut OsRng); let amount = 1; // Generating and applying transactions let txs = 5; println!(" Applying {} transactions...", txs); for i in 0..txs { println!(" tx {}", i); let tx = match client.build_transaction(pubkey, amount, token_id, true, state_arc.clone()).await { Ok(v) => v, Err(e) => { println!("Failed building transaction: {}", e); return Err(e.into()) } }; let update = match state_transition(&mem_state, tx.clone()) { Ok(v) => v, Err(e) => { println!("validate_state_transition(): Failed for tx {}: {}", i, e); return Err(e.into()) } }; mem_state.apply(update.clone()); state.apply(update, secret_keys.clone(), None, client.wallet.clone()).await?; } // Final size bridge_tree_usage("Final state", state.tree); Ok(()) }