use self::chain::types::NoopAdapter;
use self::chain::types::Options;
use self::chain::Chain;
use self::core::core::hash::Hashed;
use self::core::core::Block;
use self::core::genesis;
use self::core::global::ChainTypes;
use self::core::libtx::{self, reward};
use self::core::pow::PoWType;
use self::core::{consensus, global, pow};
use self::keychain::{ExtKeychainPath, Keychain};
use self::util::RwLock;
use chrono::Duration;
use epic_chain as chain;
use epic_core as core;
use epic_keychain as keychain;
use epic_util as util;
use std::fs;
use std::sync::Arc;
pub fn clean_output_dir(dir_name: &str) {
let _ = fs::remove_dir_all(dir_name);
}
pub fn init_chain(dir_name: &str, genesis: Block) -> Chain {
Chain::init(
dir_name.to_string(),
Arc::new(NoopAdapter {}),
genesis,
pow::verify_size,
false,
)
.unwrap()
}
fn genesis_block<K>(keychain: &K) -> Block
where
K: Keychain,
{
let key_id = keychain::ExtKeychain::derive_key_id(0, 1, 0, 0, 0);
let reward = reward::output(
keychain,
&libtx::ProofBuilder::new(keychain),
&key_id,
0,
false,
0,
)
.unwrap();
genesis::genesis_dev().with_reward(reward.0, reward.1)
}
pub fn mine_chain(dir_name: &str, chain_length: u64) -> Chain {
global::set_mining_mode(ChainTypes::AutomatedTesting);
let keychain = keychain::ExtKeychain::from_random_seed(false).unwrap();
let genesis = genesis_block(&keychain);
let mut chain = init_chain(dir_name, genesis.clone());
mine_some_on_top(&mut chain, chain_length, &keychain);
chain
}
fn mine_some_on_top<K>(chain: &mut Chain, chain_length: u64, keychain: &K)
where
K: Keychain,
{
for n in 1..chain_length {
let prev = chain.head_header().unwrap();
let next_header_info =
consensus::next_difficulty(1, PoWType::Cuckatoo, chain.difficulty_iter().unwrap());
let pk = ExtKeychainPath::new(1, n as u32, 0, 0, 0).to_identifier();
let reward = libtx::reward::output(
keychain,
&libtx::ProofBuilder::new(keychain),
&pk,
0,
false,
n,
)
.unwrap();
let mut b =
core::core::Block::new(&prev, vec![], next_header_info.clone().difficulty, reward)
.unwrap();
b.header.timestamp = prev.timestamp + Duration::seconds(60);
b.header.pow.secondary_scaling = next_header_info.secondary_scaling;
chain.set_txhashset_roots(&mut b).unwrap();
let edge_bits = if n == 2 {
global::min_edge_bits() + 1
} else {
global::min_edge_bits()
};
if let pow::Proof::CuckooProof {
edge_bits: ref mut bits,
..
} = b.header.pow.proof
{
*bits = edge_bits;
}
pow::pow_size(
&mut b.header,
next_header_info.difficulty,
global::proofsize(),
edge_bits,
)
.unwrap();
if let pow::Proof::CuckooProof {
edge_bits: ref mut bits,
..
} = b.header.pow.proof
{
*bits = edge_bits;
}
let bhash = b.hash();
chain.process_block(b, Options::MINE).unwrap();
let head = chain.head().unwrap();
assert_eq!(head.height, n);
assert_eq!(head.last_block_h, bhash);
let header = chain.head_header().unwrap();
assert_eq!(header.height, n);
assert_eq!(header.hash(), bhash);
let block = chain.get_block(&header.hash()).unwrap();
assert_eq!(block.header.height, n);
assert_eq!(block.hash(), bhash);
assert_eq!(block.outputs().len(), 1);
let header_by_height = chain.get_header_by_height(n).unwrap();
assert_eq!(header_by_height.hash(), bhash);
chain.validate(false).unwrap();
}
}