use async_std::sync::Arc; use std::{fs::File, io::Write}; use darkfi::{ blockchain::{ blockstore::{BlockOrderStore, BlockStore, HeaderStore}, metadatastore::StreamletMetadataStore, txstore::TxStore, Blockchain, }, consensus::{ block::{Block, BlockProposal, Header, ProposalChain}, metadata::{Metadata, StreamletMetadata}, participant::Participant, state::{ConsensusState, ValidatorState}, vote::Vote, TESTNET_GENESIS_HASH_BYTES, }, crypto::{merkle_node::MerkleNode, token_list::DrkTokenList}, node::Client, tx::Transaction, util::{expand_path, serial::serialize, time::Timestamp}, wallet::walletdb::init_wallet, Result, }; #[derive(Debug)] struct ParticipantInfo { _address: String, _joined: u64, _voted: Option, _quarantined: Option, } impl ParticipantInfo { pub fn new(participant: &Participant) -> ParticipantInfo { let _address = participant.address.to_string(); let _joined = participant.joined; let _voted = participant.voted; let _quarantined = participant.quarantined; ParticipantInfo { _address, _joined, _voted, _quarantined } } } #[derive(Debug)] struct VoteInfo { _proposal: blake3::Hash, _slot: u64, _address: String, } impl VoteInfo { pub fn new(vote: &Vote) -> VoteInfo { let _proposal = vote.proposal; let _slot = vote.slot; let _address = vote.address.to_string(); VoteInfo { _proposal, _slot, _address } } } #[derive(Debug)] struct StreamletMetadataInfo { _votes: Vec, _notarized: bool, _finalized: bool, _participants: Vec, } impl StreamletMetadataInfo { pub fn new(metadata: &StreamletMetadata) -> StreamletMetadataInfo { let mut _votes = Vec::new(); for vote in &metadata.votes { _votes.push(VoteInfo::new(&vote)); } let _notarized = metadata.notarized; let _finalized = metadata.finalized; let mut _participants = Vec::new(); for participant in &metadata.participants { _participants.push(ParticipantInfo::new(&participant)); } StreamletMetadataInfo { _votes, _notarized, _finalized, _participants } } } #[derive(Debug)] struct MetadataInfo { _address: String, } impl MetadataInfo { pub fn new(metadata: &Metadata) -> MetadataInfo { let _address = metadata.address.to_string(); MetadataInfo { _address } } } #[derive(Debug)] struct ProposalInfo { _block: BlockInfo, _sm: StreamletMetadataInfo, } 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 }; let _sm = StreamletMetadataInfo::new(&proposal.block.sm); ProposalInfo { _block, _sm } } } #[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, _state: 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 _state = header.state; let _epoch = header.epoch; let _slot = header.slot; let _timestamp = header.timestamp; let _root = header.root; HeaderInfo { _hash, _version, _state, _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 HashedMetadataInfo { _block: blake3::Hash, _metadata: StreamletMetadataInfo, } impl HashedMetadataInfo { pub fn new(_block: blake3::Hash, metadata: &StreamletMetadata) -> HashedMetadataInfo { let _metadata = StreamletMetadataInfo::new(&metadata); HashedMetadataInfo { _block, _metadata } } } #[derive(Debug)] struct MetadataStoreInfo { _metadata: Vec, } impl MetadataStoreInfo { pub fn new(metadatastore: &StreamletMetadataStore) -> MetadataStoreInfo { let mut _metadata = Vec::new(); let result = metadatastore.get_all(); match result { Ok(iter) => { for (hash, m) in iter.iter() { _metadata.push(HashedMetadataInfo::new(hash.clone(), &m)); } } Err(e) => println!("Error: {:?}", e), } MetadataStoreInfo { _metadata } } } #[derive(Debug)] struct BlockchainInfo { _headers: HeaderStoreInfo, _blocks: BlockInfoChain, _order: BlockOrderStoreInfo, _transactions: TxStoreInfo, _metadata: MetadataStoreInfo, } 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); let _metadata = MetadataStoreInfo::new(&blockchain.streamlet_metadata); BlockchainInfo { _headers, _blocks, _order, _transactions, _metadata } } } #[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 address = wallet.get_default_address().await?; let tokenlist = Arc::new(DrkTokenList::new(&[ ("drk", include_bytes!("../../../../contrib/token/darkfi_token_list.min.json")), ("btc", include_bytes!("../../../../contrib/token/bitcoin_token_list.min.json")), ("eth", include_bytes!("../../../../contrib/token/erc20_token_list.min.json")), ("sol", include_bytes!("../../../../contrib/token/solana_token_list.min.json")), ])?); let client = Arc::new(Client::new(wallet, tokenlist).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/darkfid0").await?; // darkfid1 generate("darkfid1", "../../../contrib/localnet/darkfid1").await?; // darkfid2 generate("darkfid2", "../../../contrib/localnet/darkfid2").await?; // faucetd generate("faucetd", "../../../contrib/localnet/faucetd").await?; Ok(()) }