/* 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; use std::{fs::File, io::Write}; use darkfi::{ blockchain::{ blockstore::{BlockOrderStore, BlockStore, HeaderStore}, txstore::TxStore, Blockchain, }, consensus::{ block::{Block, BlockProposal, Header, ProposalChain}, metadata::Metadata, participant::Participant, state::{ConsensusState, ValidatorState}, TESTNET_GENESIS_HASH_BYTES, }, node::Client, tx::Transaction, util::{path::expand_path, time::Timestamp}, wallet::walletdb::init_wallet, Result, }; use darkfi_sdk::crypto::MerkleNode; use darkfi_serial::serialize; // TODO: Add missing fields #[derive(Debug)] struct ParticipantInfo { _address: String, } impl ParticipantInfo { pub fn new(participant: &Participant) -> ParticipantInfo { let _address = participant.address.to_string(); ParticipantInfo { _address } } } #[derive(Debug)] struct MetadataInfo { _address: String, _participants: Vec, } impl MetadataInfo { pub fn new(metadata: &Metadata) -> MetadataInfo { let _address = metadata.address.to_string(); let mut _participants = Vec::new(); for participant in &metadata.participants { _participants.push(ParticipantInfo::new(&participant)); } MetadataInfo { _address, _participants } } } #[derive(Debug)] struct ProposalInfo { _block: BlockInfo, } impl ProposalInfo { pub fn new(proposal: &BlockProposal) -> ProposalInfo { let _header = proposal.block.header.headerhash(); let mut _txs = vec![]; for tx in &proposal.block.txs { let hash = blake3::hash(&serialize(tx)); _txs.push(hash); } let _metadata = MetadataInfo::new(&proposal.block.metadata); let _block = BlockInfo { _hash: _header, _magic: proposal.block.magic, _header, _txs, _metadata }; ProposalInfo { _block } } } #[derive(Debug)] struct ProposalInfoChain { _proposals: Vec, } impl ProposalInfoChain { pub fn new(proposals: &ProposalChain) -> ProposalInfoChain { let mut _proposals = Vec::new(); for proposal in &proposals.proposals { _proposals.push(ProposalInfo::new(&proposal)); } ProposalInfoChain { _proposals } } } #[derive(Debug)] struct ConsensusInfo { _genesis_ts: Timestamp, _proposals: Vec, } impl ConsensusInfo { pub fn new(consensus: &ConsensusState) -> ConsensusInfo { let _genesis_ts = consensus.genesis_ts.clone(); let mut _proposals = Vec::new(); for proposal in &consensus.proposals { _proposals.push(ProposalInfoChain::new(&proposal)); } ConsensusInfo { _genesis_ts, _proposals } } } #[derive(Debug)] struct HeaderInfo { _hash: blake3::Hash, _version: u8, _previous: blake3::Hash, _epoch: u64, _slot: u64, _timestamp: Timestamp, _root: MerkleNode, } impl HeaderInfo { pub fn new(_hash: blake3::Hash, header: &Header) -> HeaderInfo { let _version = header.version; let _previous = header.previous; let _epoch = header.epoch; let _slot = header.slot; let _timestamp = header.timestamp; let _root = header.root; HeaderInfo { _hash, _version, _previous, _epoch, _slot, _timestamp, _root } } } #[derive(Debug)] struct HeaderStoreInfo { _headers: Vec, } impl HeaderStoreInfo { pub fn new(headerstore: &HeaderStore) -> HeaderStoreInfo { let mut _headers = Vec::new(); let result = headerstore.get_all(); match result { Ok(iter) => { for (hash, header) in iter.iter() { _headers.push(HeaderInfo::new(hash.clone(), &header)); } } Err(e) => println!("Error: {:?}", e), } HeaderStoreInfo { _headers } } } #[derive(Debug)] struct BlockInfo { _hash: blake3::Hash, _magic: [u8; 4], _header: blake3::Hash, _txs: Vec, _metadata: MetadataInfo, } impl BlockInfo { pub fn new(_hash: blake3::Hash, block: &Block) -> BlockInfo { let _magic = block.magic; let _header = block.header; let _txs = block.txs.clone(); let _metadata = MetadataInfo::new(&block.metadata); BlockInfo { _hash, _magic, _header, _txs, _metadata } } } #[derive(Debug)] struct BlockInfoChain { _blocks: Vec, } impl BlockInfoChain { pub fn new(blockstore: &BlockStore) -> BlockInfoChain { let mut _blocks = Vec::new(); let result = blockstore.get_all(); match result { Ok(iter) => { for (hash, block) in iter.iter() { _blocks.push(BlockInfo::new(hash.clone(), &block)); } } Err(e) => println!("Error: {:?}", e), } BlockInfoChain { _blocks } } } #[derive(Debug)] struct OrderInfo { _slot: u64, _hash: blake3::Hash, } impl OrderInfo { pub fn new(_slot: u64, _hash: blake3::Hash) -> OrderInfo { OrderInfo { _slot, _hash } } } #[derive(Debug)] struct BlockOrderStoreInfo { _order: Vec, } impl BlockOrderStoreInfo { pub fn new(orderstore: &BlockOrderStore) -> BlockOrderStoreInfo { let mut _order = Vec::new(); let result = orderstore.get_all(); match result { Ok(iter) => { for (slot, hash) in iter.iter() { _order.push(OrderInfo::new(slot.clone(), hash.clone())); } } Err(e) => println!("Error: {:?}", e), } BlockOrderStoreInfo { _order } } } #[derive(Debug)] struct TxInfo { _hash: blake3::Hash, _payload: Transaction, } impl TxInfo { pub fn new(_hash: blake3::Hash, tx: &Transaction) -> TxInfo { let _payload = tx.clone(); TxInfo { _hash, _payload } } } #[derive(Debug)] struct TxStoreInfo { _transactions: Vec, } impl TxStoreInfo { pub fn new(txstore: &TxStore) -> TxStoreInfo { let mut _transactions = Vec::new(); let result = txstore.get_all(); match result { Ok(iter) => { for (hash, tx) in iter.iter() { _transactions.push(TxInfo::new(hash.clone(), &tx)); } } Err(e) => println!("Error: {:?}", e), } TxStoreInfo { _transactions } } } #[derive(Debug)] struct BlockchainInfo { _headers: HeaderStoreInfo, _blocks: BlockInfoChain, _order: BlockOrderStoreInfo, _transactions: TxStoreInfo, } impl BlockchainInfo { pub fn new(blockchain: &Blockchain) -> BlockchainInfo { let _headers = HeaderStoreInfo::new(&blockchain.headers); let _blocks = BlockInfoChain::new(&blockchain.blocks); let _order = BlockOrderStoreInfo::new(&blockchain.order); let _transactions = TxStoreInfo::new(&blockchain.transactions); BlockchainInfo { _headers, _blocks, _order, _transactions } } } #[derive(Debug)] struct StateInfo { _address: String, _consensus: ConsensusInfo, _blockchain: BlockchainInfo, } impl StateInfo { pub fn new(state: &ValidatorState) -> StateInfo { let _address = state.address.to_string(); let _consensus = ConsensusInfo::new(&state.consensus); let _blockchain = BlockchainInfo::new(&state.blockchain); StateInfo { _address, _consensus, _blockchain } } } async fn generate(name: &str, folder: &str) -> Result<()> { let genesis_ts = Timestamp(1648383795); let genesis_data = *TESTNET_GENESIS_HASH_BYTES; let pass = "changeme"; // Initialize or load 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?; // Initialize or load sled database let path = folder.to_owned() + "/blockchain/testnet"; let db_path = expand_path(&path).unwrap(); let sled_db = sled::open(&db_path)?; // Data export println!("Exporting data for {:?} - {:?}", name, address.to_string()); let state = ValidatorState::new(&sled_db, genesis_ts, genesis_data, client, vec![], vec![]).await?; let info = StateInfo::new(&*state.read().await); let info_string = format!("{:#?}", info); let path = name.to_owned() + "_testnet_db"; let mut file = File::create(path)?; file.write(info_string.as_bytes())?; drop(sled_db); Ok(()) } #[async_std::main] async fn main() -> Result<()> { // darkfid0 generate("darkfid0", "../../../contrib/localnet/darkfid/darkfid0").await?; // darkfid1 generate("darkfid1", "../../../contrib/localnet/darkfid/darkfid1").await?; // darkfid2 generate("darkfid2", "../../../contrib/localnet/darkfid/darkfid2").await?; // faucetd generate("faucetd", "../../../contrib/localnet/darkfid/faucetd").await?; Ok(()) }