thread local chain type vs global chain type (#3327)

* Introduce GLOBAL_CHAIN_TYPE and make CHAIN_TYPE thread_local.
This makes testing more explicit and significantly more robust.

* set_local_chain_type() in tests

* cleanup - weird

* get pool tests working with explicit local chain_type config

* core tests working with explicit local chain_type

* p2p tests working with explicit local chain_type

* store tests working

* cleanup, feedback
This commit is contained in:
Antioch Peverell
2020-05-22 12:51:58 +01:00
committed by GitHub
parent 096b6924ce
commit 6faa0e8d75
33 changed files with 192 additions and 114 deletions
+3 -1
View File
@@ -142,7 +142,7 @@ pub const TESTING_SECOND_HARD_FORK: u64 = 6;
/// Compute possible block version at a given height, implements
/// 6 months interval scheduled hard forks for the first 2 years.
pub fn header_version(height: u64) -> HeaderVersion {
let chain_type = global::CHAIN_TYPE.read().clone();
let chain_type = global::get_chain_type();
let hf_interval = (1 + height / HARD_FORK_INTERVAL) as u16;
match chain_type {
global::ChainTypes::Mainnet => HeaderVersion(hf_interval),
@@ -383,6 +383,8 @@ mod test {
#[test]
fn test_graph_weight() {
global::set_local_chain_type(global::ChainTypes::Mainnet);
// initial weights
assert_eq!(graph_weight(1, 31), 256 * 31);
assert_eq!(graph_weight(1, 32), 512 * 32);
+3
View File
@@ -272,11 +272,13 @@ pub fn genesis_main() -> core::Block {
mod test {
use super::*;
use crate::core::hash::Hashed;
use crate::global;
use crate::ser::{self, ProtocolVersion};
use util::ToHex;
#[test]
fn floonet_genesis_hash() {
global::set_local_chain_type(global::ChainTypes::Floonet);
let gen_hash = genesis_floo().hash();
println!("floonet genesis hash: {}", gen_hash.to_hex());
let gen_bin = ser::ser_vec(&genesis_floo(), ProtocolVersion(1)).unwrap();
@@ -293,6 +295,7 @@ mod test {
#[test]
fn mainnet_genesis_hash() {
global::set_local_chain_type(global::ChainTypes::Mainnet);
let gen_hash = genesis_main().hash();
println!("mainnet genesis hash: {}", gen_hash.to_hex());
let gen_bin = ser::ser_vec(&genesis_main(), ProtocolVersion(1)).unwrap();
+57 -49
View File
@@ -27,7 +27,8 @@ use crate::pow::{
self, new_cuckaroo_ctx, new_cuckarood_ctx, new_cuckaroom_ctx, new_cuckatoo_ctx, EdgeType,
PoWContext,
};
use util::RwLock;
use std::cell::Cell;
use util::OneTime;
/// An enum collecting sets of parameters used throughout the
/// code wherever mining is needed. This should allow for
@@ -104,7 +105,7 @@ pub const TXHASHSET_ARCHIVE_INTERVAL: u64 = 12 * 60;
/// Types of chain a server can run with, dictates the genesis block and
/// and mining parameters used.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum ChainTypes {
/// For CI testing
AutomatedTesting,
@@ -134,31 +135,43 @@ impl Default for ChainTypes {
}
}
/// PoW test mining and verifier context
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum PoWContextTypes {
/// Classic Cuckoo
Cuckoo,
/// ASIC-friendly Cuckatoo
Cuckatoo,
/// ASIC-resistant Cuckaroo
Cuckaroo,
}
lazy_static! {
/// The mining parameter mode
pub static ref CHAIN_TYPE: RwLock<ChainTypes> =
RwLock::new(ChainTypes::Mainnet);
/// PoW context type to instantiate
pub static ref POW_CONTEXT_TYPE: RwLock<PoWContextTypes> =
RwLock::new(PoWContextTypes::Cuckoo);
/// Global chain_type that must be initialized once on node startup.
/// This is accessed via get_chain_type() which allows the global value
/// to be overridden on a per-thread basis (for testing).
pub static ref GLOBAL_CHAIN_TYPE: OneTime<ChainTypes> = OneTime::new();
}
/// Set the mining mode
pub fn set_mining_mode(mode: ChainTypes) {
let mut param_ref = CHAIN_TYPE.write();
*param_ref = mode;
thread_local! {
/// Mainnet|Floonet|UserTesting|AutomatedTesting
pub static CHAIN_TYPE: Cell<Option<ChainTypes>> = Cell::new(None);
}
/// Set the chain type on a per-thread basis via thread_local storage.
pub fn set_local_chain_type(new_type: ChainTypes) {
CHAIN_TYPE.with(|chain_type| chain_type.set(Some(new_type)))
}
/// Get the chain type via thread_local, fallback to global chain_type.
pub fn get_chain_type() -> ChainTypes {
CHAIN_TYPE.with(|chain_type| match chain_type.get() {
None => {
if GLOBAL_CHAIN_TYPE.is_init() {
let chain_type = GLOBAL_CHAIN_TYPE.borrow();
set_local_chain_type(chain_type);
chain_type
} else {
panic!("GLOBAL_CHAIN_TYPE and CHAIN_TYPE unset. Consider set_local_chain_type() in tests.");
}
}
Some(chain_type) => chain_type,
})
}
/// One time initialization of the global chain_type.
/// Will panic if we attempt to re-initialize this (via OneTime).
pub fn init_global_chain_type(new_type: ChainTypes) {
GLOBAL_CHAIN_TYPE.init(new_type)
}
/// Return either a cuckoo context or a cuckatoo context
@@ -172,7 +185,7 @@ pub fn create_pow_context<T>(
where
T: EdgeType + 'static,
{
let chain_type = CHAIN_TYPE.read().clone();
let chain_type = get_chain_type();
match chain_type {
// Mainnet has Cuckaroo(d)29 for AR and Cuckatoo31+ for AF
ChainTypes::Mainnet if edge_bits > 29 => new_cuckatoo_ctx(edge_bits, proof_size, max_sols),
@@ -201,8 +214,7 @@ where
/// The minimum acceptable edge_bits
pub fn min_edge_bits() -> u8 {
let param_ref = CHAIN_TYPE.read();
match *param_ref {
match get_chain_type() {
ChainTypes::AutomatedTesting => AUTOMATED_TESTING_MIN_EDGE_BITS,
ChainTypes::UserTesting => USER_TESTING_MIN_EDGE_BITS,
_ => DEFAULT_MIN_EDGE_BITS,
@@ -213,8 +225,7 @@ pub fn min_edge_bits() -> u8 {
/// while the min_edge_bits can be changed on a soft fork, changing
/// base_edge_bits is a hard fork.
pub fn base_edge_bits() -> u8 {
let param_ref = CHAIN_TYPE.read();
match *param_ref {
match get_chain_type() {
ChainTypes::AutomatedTesting => AUTOMATED_TESTING_MIN_EDGE_BITS,
ChainTypes::UserTesting => USER_TESTING_MIN_EDGE_BITS,
_ => BASE_EDGE_BITS,
@@ -223,8 +234,7 @@ pub fn base_edge_bits() -> u8 {
/// The proofsize
pub fn proofsize() -> usize {
let param_ref = CHAIN_TYPE.read();
match *param_ref {
match get_chain_type() {
ChainTypes::AutomatedTesting => AUTOMATED_TESTING_PROOF_SIZE,
ChainTypes::UserTesting => USER_TESTING_PROOF_SIZE,
_ => PROOFSIZE,
@@ -233,8 +243,7 @@ pub fn proofsize() -> usize {
/// Coinbase maturity for coinbases to be spent
pub fn coinbase_maturity() -> u64 {
let param_ref = CHAIN_TYPE.read();
match *param_ref {
match get_chain_type() {
ChainTypes::AutomatedTesting => AUTOMATED_TESTING_COINBASE_MATURITY,
ChainTypes::UserTesting => USER_TESTING_COINBASE_MATURITY,
_ => COINBASE_MATURITY,
@@ -243,8 +252,7 @@ pub fn coinbase_maturity() -> u64 {
/// Initial mining difficulty
pub fn initial_block_difficulty() -> u64 {
let param_ref = CHAIN_TYPE.read();
match *param_ref {
match get_chain_type() {
ChainTypes::AutomatedTesting => TESTING_INITIAL_DIFFICULTY,
ChainTypes::UserTesting => TESTING_INITIAL_DIFFICULTY,
ChainTypes::Floonet => INITIAL_DIFFICULTY,
@@ -253,8 +261,7 @@ pub fn initial_block_difficulty() -> u64 {
}
/// Initial mining secondary scale
pub fn initial_graph_weight() -> u32 {
let param_ref = CHAIN_TYPE.read();
match *param_ref {
match get_chain_type() {
ChainTypes::AutomatedTesting => TESTING_INITIAL_GRAPH_WEIGHT,
ChainTypes::UserTesting => TESTING_INITIAL_GRAPH_WEIGHT,
ChainTypes::Floonet => graph_weight(0, SECOND_POW_EDGE_BITS) as u32,
@@ -264,8 +271,7 @@ pub fn initial_graph_weight() -> u32 {
/// Maximum allowed block weight.
pub fn max_block_weight() -> usize {
let param_ref = CHAIN_TYPE.read();
match *param_ref {
match get_chain_type() {
ChainTypes::AutomatedTesting => TESTING_MAX_BLOCK_WEIGHT,
ChainTypes::UserTesting => TESTING_MAX_BLOCK_WEIGHT,
ChainTypes::Floonet => MAX_BLOCK_WEIGHT,
@@ -275,8 +281,7 @@ pub fn max_block_weight() -> usize {
/// Horizon at which we can cut-through and do full local pruning
pub fn cut_through_horizon() -> u32 {
let param_ref = CHAIN_TYPE.read();
match *param_ref {
match get_chain_type() {
ChainTypes::AutomatedTesting => AUTOMATED_TESTING_CUT_THROUGH_HORIZON,
ChainTypes::UserTesting => USER_TESTING_CUT_THROUGH_HORIZON,
_ => CUT_THROUGH_HORIZON,
@@ -285,8 +290,7 @@ pub fn cut_through_horizon() -> u32 {
/// Threshold at which we can request a txhashset (and full blocks from)
pub fn state_sync_threshold() -> u32 {
let param_ref = CHAIN_TYPE.read();
match *param_ref {
match get_chain_type() {
ChainTypes::AutomatedTesting => TESTING_STATE_SYNC_THRESHOLD,
ChainTypes::UserTesting => TESTING_STATE_SYNC_THRESHOLD,
_ => STATE_SYNC_THRESHOLD,
@@ -295,8 +299,7 @@ pub fn state_sync_threshold() -> u32 {
/// Number of blocks to reuse a txhashset zip for.
pub fn txhashset_archive_interval() -> u64 {
let param_ref = CHAIN_TYPE.read();
match *param_ref {
match get_chain_type() {
ChainTypes::AutomatedTesting => TESTING_TXHASHSET_ARCHIVE_INTERVAL,
ChainTypes::UserTesting => TESTING_TXHASHSET_ARCHIVE_INTERVAL,
_ => TXHASHSET_ARCHIVE_INTERVAL,
@@ -306,8 +309,11 @@ pub fn txhashset_archive_interval() -> u64 {
/// Are we in production mode?
/// Production defined as a live public network, testnet[n] or mainnet.
pub fn is_production_mode() -> bool {
let param_ref = CHAIN_TYPE.read();
ChainTypes::Floonet == *param_ref || ChainTypes::Mainnet == *param_ref
match get_chain_type() {
ChainTypes::Floonet => true,
ChainTypes::Mainnet => true,
_ => false,
}
}
/// Are we in floonet?
@@ -315,8 +321,10 @@ pub fn is_production_mode() -> bool {
/// as possible to "mainnet" configuration as possible.
/// We want to avoid missing any mainnet only code paths.
pub fn is_floonet() -> bool {
let param_ref = CHAIN_TYPE.read();
ChainTypes::Floonet == *param_ref
match get_chain_type() {
ChainTypes::Floonet => true,
_ => false,
}
}
/// Converts an iterator of block difficulty data to more a more manageable
+4
View File
@@ -252,6 +252,7 @@ mod test {
use super::*;
use crate::core::transaction::Weighting;
use crate::core::verifier_cache::{LruVerifierCache, VerifierCache};
use crate::global;
use crate::libtx::ProofBuilder;
use keychain::{ExtKeychain, ExtKeychainPath};
@@ -261,6 +262,7 @@ mod test {
#[test]
fn blind_simple_tx() {
global::set_local_chain_type(global::ChainTypes::AutomatedTesting);
let keychain = ExtKeychain::from_random_seed(false).unwrap();
let builder = ProofBuilder::new(&keychain);
let key_id1 = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();
@@ -282,6 +284,7 @@ mod test {
#[test]
fn blind_simple_tx_with_offset() {
global::set_local_chain_type(global::ChainTypes::AutomatedTesting);
let keychain = ExtKeychain::from_random_seed(false).unwrap();
let builder = ProofBuilder::new(&keychain);
let key_id1 = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();
@@ -303,6 +306,7 @@ mod test {
#[test]
fn blind_simpler_tx() {
global::set_local_chain_type(global::ChainTypes::AutomatedTesting);
let keychain = ExtKeychain::from_random_seed(false).unwrap();
let builder = ProofBuilder::new(&keychain);
let key_id1 = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier();
+1 -1
View File
@@ -130,7 +130,7 @@ mod test {
/// We'll be generating genesis blocks differently
#[test]
fn genesis_pow() {
global::set_mining_mode(ChainTypes::UserTesting);
global::set_local_chain_type(ChainTypes::UserTesting);
let mut b = genesis::genesis_dev();
b.header.pow.nonce = 28106;
+1
View File
@@ -170,6 +170,7 @@ mod test {
#[test]
fn cuckaroo19_vectors() {
global::set_local_chain_type(global::ChainTypes::Mainnet);
let mut ctx = new_impl::<u64>(19, 42);
ctx.params.siphash_keys = V1_19_HASH;
assert!(ctx.verify(&Proof::new(V1_19_SOL.to_vec())).is_ok());
+1
View File
@@ -172,6 +172,7 @@ mod test {
#[test]
fn cuckarood19_29_vectors() {
global::set_local_chain_type(global::ChainTypes::Mainnet);
let mut ctx19 = new_impl::<u64>(19, 42);
ctx19.params.siphash_keys = V1_19_HASH;
assert!(ctx19.verify(&Proof::new(V1_19_SOL.to_vec())).is_ok());
+1
View File
@@ -165,6 +165,7 @@ mod test {
#[test]
fn cuckaroom19_29_vectors() {
global::set_local_chain_type(global::ChainTypes::Mainnet);
let mut ctx19 = new_impl::<u64>(19, 42);
ctx19.params.siphash_keys = V1_19_HASH;
assert!(ctx19.verify(&Proof::new(V1_19_SOL.to_vec())).is_ok());
+1
View File
@@ -367,6 +367,7 @@ mod test {
#[test]
fn cuckatoo() {
global::set_local_chain_type(global::ChainTypes::Mainnet);
let ret = basic_solve::<u32>();
if let Err(r) = ret {
panic!("basic_solve u32: Error: {}", r);
+2
View File
@@ -88,10 +88,12 @@ impl Lean {
#[cfg(test)]
mod test {
use super::*;
use crate::global;
use crate::pow::types::PoWContext;
#[test]
fn lean_miner() {
global::set_local_chain_type(global::ChainTypes::Mainnet);
let nonce = 15465723;
let header = [0u8; 84].to_vec(); // with nonce
let edge_bits = 19;
+1
View File
@@ -507,6 +507,7 @@ mod tests {
#[test]
fn test_proof_rw() {
global::set_local_chain_type(global::ChainTypes::Mainnet);
for edge_bits in 10..63 {
let mut proof = Proof::new(gen_proof(edge_bits as u32));
proof.edge_bits = edge_bits;