/* This file is part of DarkFi (https://dark.fi) * * Copyright (C) 2020-2022 Dyne.org foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ 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, path::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::serde::encode_to_vec(&wrapper, bincode::config::legacy()).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(()) }