2016-11-30 05:51:36 +03:00
|
|
|
// Copyright 2016 The Grin Developers
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2017-11-01 02:32:33 +03:00
|
|
|
#[macro_use]
|
|
|
|
extern crate router;
|
|
|
|
|
|
|
|
extern crate grin_api as api;
|
|
|
|
extern crate grin_chain as chain;
|
2016-11-30 05:51:36 +03:00
|
|
|
extern crate grin_core as core;
|
2017-11-01 02:32:33 +03:00
|
|
|
extern crate grin_grin as grin;
|
2016-11-30 05:51:36 +03:00
|
|
|
extern crate grin_p2p as p2p;
|
2017-08-22 21:23:54 +03:00
|
|
|
extern crate grin_pow as pow;
|
2017-10-22 10:11:45 +03:00
|
|
|
extern crate grin_util as util;
|
2017-11-01 02:32:33 +03:00
|
|
|
extern crate grin_wallet as wallet;
|
2016-12-15 03:10:39 +03:00
|
|
|
|
|
|
|
extern crate futures;
|
|
|
|
extern crate tokio_core;
|
2017-02-19 05:42:34 +03:00
|
|
|
extern crate tokio_timer;
|
2016-11-30 05:51:36 +03:00
|
|
|
|
2017-06-27 05:09:01 +03:00
|
|
|
mod framework;
|
|
|
|
|
2016-12-14 06:21:49 +03:00
|
|
|
use std::thread;
|
2016-11-30 05:51:36 +03:00
|
|
|
use std::time;
|
2017-02-19 05:42:34 +03:00
|
|
|
use std::default::Default;
|
2016-11-30 05:51:36 +03:00
|
|
|
|
2017-11-01 02:32:33 +03:00
|
|
|
use futures::{Async, Future, Poll};
|
2017-08-10 03:54:10 +03:00
|
|
|
use futures::task::current;
|
2016-12-15 03:10:39 +03:00
|
|
|
use tokio_core::reactor;
|
2017-02-19 05:42:34 +03:00
|
|
|
use tokio_timer::Timer;
|
2016-12-15 03:10:39 +03:00
|
|
|
|
2017-06-19 18:59:56 +03:00
|
|
|
use core::consensus;
|
2017-08-09 19:40:23 +03:00
|
|
|
use core::global;
|
2017-11-16 00:49:15 +03:00
|
|
|
use core::global::ChainTypes;
|
2017-06-16 19:47:29 +03:00
|
|
|
use wallet::WalletConfig;
|
|
|
|
|
2017-11-01 02:32:33 +03:00
|
|
|
use framework::{LocalServerContainer, LocalServerContainerConfig, LocalServerContainerPool,
|
|
|
|
LocalServerContainerPoolConfig};
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-06-27 05:09:01 +03:00
|
|
|
/// Testing the frameworks by starting a fresh server, creating a genesis
|
|
|
|
/// Block and mining into a wallet for a bit
|
|
|
|
#[test]
|
2017-08-09 19:40:23 +03:00
|
|
|
fn basic_genesis_mine() {
|
2017-11-16 00:49:15 +03:00
|
|
|
global::set_mining_mode(ChainTypes::AutomatedTesting);
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
let test_name_dir = "genesis_mine";
|
|
|
|
framework::clean_all_output(test_name_dir);
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// Create a server pool
|
|
|
|
let mut pool_config = LocalServerContainerPoolConfig::default();
|
|
|
|
pool_config.base_name = String::from(test_name_dir);
|
|
|
|
pool_config.run_length_in_seconds = 5;
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
pool_config.base_api_port = 30000;
|
|
|
|
pool_config.base_p2p_port = 31000;
|
|
|
|
pool_config.base_wallet_port = 32000;
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
let mut pool = LocalServerContainerPool::new(pool_config);
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// Create a server to add into the pool
|
|
|
|
let mut server_config = LocalServerContainerConfig::default();
|
|
|
|
server_config.start_miner = true;
|
|
|
|
server_config.start_wallet = true;
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
pool.create_server(&mut server_config);
|
|
|
|
pool.run_all_servers();
|
2017-06-16 19:47:29 +03:00
|
|
|
}
|
|
|
|
|
2017-06-27 05:09:01 +03:00
|
|
|
/// Creates 5 servers, first being a seed and check that through peer address
|
|
|
|
/// messages they all end up connected.
|
|
|
|
#[test]
|
2017-08-09 19:40:23 +03:00
|
|
|
fn simulate_seeding() {
|
2017-11-16 00:49:15 +03:00
|
|
|
global::set_mining_mode(ChainTypes::AutomatedTesting);
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
let test_name_dir = "simulate_seeding";
|
|
|
|
framework::clean_all_output(test_name_dir);
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// Create a server pool
|
|
|
|
let mut pool_config = LocalServerContainerPoolConfig::default();
|
|
|
|
pool_config.base_name = String::from(test_name_dir);
|
|
|
|
pool_config.run_length_in_seconds = 30;
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-12-18 16:17:11 +03:00
|
|
|
// have to use different ports because of tests being run in parallel
|
2017-08-09 19:40:23 +03:00
|
|
|
pool_config.base_api_port = 30020;
|
|
|
|
pool_config.base_p2p_port = 31020;
|
|
|
|
pool_config.base_wallet_port = 32020;
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
let mut pool = LocalServerContainerPool::new(pool_config);
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// Create a first seed server to add into the pool
|
|
|
|
let mut server_config = LocalServerContainerConfig::default();
|
|
|
|
// server_config.start_miner = true;
|
|
|
|
server_config.start_wallet = true;
|
|
|
|
server_config.is_seeding = true;
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
pool.create_server(&mut server_config);
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// point next servers at first seed
|
|
|
|
server_config.is_seeding = false;
|
|
|
|
server_config.seed_addr = String::from(format!(
|
|
|
|
"{}:{}",
|
|
|
|
server_config.base_addr,
|
|
|
|
server_config.p2p_server_port
|
|
|
|
));
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-09-26 20:58:56 +03:00
|
|
|
for _ in 0..4 {
|
|
|
|
pool.create_server(&mut server_config);
|
|
|
|
}
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
pool.connect_all_peers();
|
2017-06-27 05:09:01 +03:00
|
|
|
|
2017-09-26 20:58:56 +03:00
|
|
|
let _ = pool.run_all_servers();
|
2017-06-16 19:47:29 +03:00
|
|
|
}
|
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
/// Create 1 server, start it mining, then connect 4 other peers mining and
|
|
|
|
/// using the first
|
|
|
|
/// as a seed. Meant to test the evolution of mining difficulty with miners
|
|
|
|
/// running at
|
2017-06-27 05:09:01 +03:00
|
|
|
/// different rates
|
2017-08-09 19:40:23 +03:00
|
|
|
// Just going to comment this out as an automatically run test for the time
|
|
|
|
// being,
|
|
|
|
// As it's more for actively testing and hurts CI a lot
|
2017-07-11 20:11:03 +03:00
|
|
|
//#[test]
|
2017-08-10 03:54:10 +03:00
|
|
|
#[allow(dead_code)]
|
2017-08-09 19:40:23 +03:00
|
|
|
fn simulate_parallel_mining() {
|
2017-11-16 00:49:15 +03:00
|
|
|
global::set_mining_mode(ChainTypes::AutomatedTesting);
|
2017-06-27 05:09:01 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
let test_name_dir = "simulate_parallel_mining";
|
|
|
|
// framework::clean_all_output(test_name_dir);
|
2017-06-27 05:09:01 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// Create a server pool
|
|
|
|
let mut pool_config = LocalServerContainerPoolConfig::default();
|
|
|
|
pool_config.base_name = String::from(test_name_dir);
|
|
|
|
pool_config.run_length_in_seconds = 60;
|
2017-12-18 16:17:11 +03:00
|
|
|
// have to use different ports because of tests being run in parallel
|
2017-08-09 19:40:23 +03:00
|
|
|
pool_config.base_api_port = 30040;
|
|
|
|
pool_config.base_p2p_port = 31040;
|
|
|
|
pool_config.base_wallet_port = 32040;
|
2017-06-27 05:09:01 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
let mut pool = LocalServerContainerPool::new(pool_config);
|
2017-06-27 05:09:01 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// Create a first seed server to add into the pool
|
|
|
|
let mut server_config = LocalServerContainerConfig::default();
|
|
|
|
server_config.start_miner = true;
|
|
|
|
server_config.start_wallet = true;
|
|
|
|
server_config.is_seeding = true;
|
2017-06-27 05:09:01 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
pool.create_server(&mut server_config);
|
2017-06-27 05:09:01 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// point next servers at first seed
|
|
|
|
server_config.is_seeding = false;
|
|
|
|
server_config.seed_addr = String::from(format!(
|
|
|
|
"{}:{}",
|
|
|
|
server_config.base_addr,
|
|
|
|
server_config.p2p_server_port
|
|
|
|
));
|
2017-06-27 05:09:01 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// And create 4 more, then let them run for a while
|
|
|
|
for i in 1..4 {
|
|
|
|
// fudge in some slowdown
|
|
|
|
server_config.miner_slowdown_in_millis = i * 2;
|
|
|
|
pool.create_server(&mut server_config);
|
|
|
|
}
|
2017-06-16 19:47:29 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
pool.connect_all_peers();
|
2017-06-27 05:09:01 +03:00
|
|
|
|
2017-09-26 20:58:56 +03:00
|
|
|
let _ = pool.run_all_servers();
|
2017-06-27 05:09:01 +03:00
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// Check mining difficulty here?, though I'd think it's more valuable
|
2017-11-01 02:32:33 +03:00
|
|
|
// to simply output it. Can at least see the evolution of the difficulty target
|
|
|
|
// in the debug log output for now
|
2017-06-16 19:47:29 +03:00
|
|
|
}
|
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// TODO: Convert these tests to newer framework format
|
2017-02-19 05:42:34 +03:00
|
|
|
/// Create a network of 5 servers and mine a block, verifying that the block
|
|
|
|
/// gets propagated to all.
|
2016-11-30 05:51:36 +03:00
|
|
|
#[test]
|
2017-08-03 19:57:55 +03:00
|
|
|
fn a_simulate_block_propagation() {
|
2017-11-01 02:32:33 +03:00
|
|
|
util::init_test_logger();
|
2017-12-04 22:16:57 +03:00
|
|
|
|
|
|
|
// we actually set the chain_type in the ServerConfig below
|
|
|
|
// TODO - avoid needing to set it in two places?
|
2017-11-16 00:49:15 +03:00
|
|
|
global::set_mining_mode(ChainTypes::AutomatedTesting);
|
2017-08-09 19:40:23 +03:00
|
|
|
|
|
|
|
let test_name_dir = "grin-prop";
|
|
|
|
framework::clean_all_output(test_name_dir);
|
|
|
|
let mut evtlp = reactor::Core::new().unwrap();
|
|
|
|
let handle = evtlp.handle();
|
|
|
|
|
2017-09-26 20:58:56 +03:00
|
|
|
let mut plugin_config = pow::types::CuckooMinerPluginConfig::default();
|
|
|
|
let mut plugin_config_vec: Vec<pow::types::CuckooMinerPluginConfig> = Vec::new();
|
|
|
|
plugin_config.type_filter = String::from("mean_cpu");
|
|
|
|
plugin_config_vec.push(plugin_config);
|
|
|
|
|
2017-08-22 21:23:54 +03:00
|
|
|
let miner_config = pow::types::MinerConfig {
|
2017-08-09 19:40:23 +03:00
|
|
|
enable_mining: true,
|
|
|
|
burn_reward: true,
|
|
|
|
use_cuckoo_miner: false,
|
|
|
|
cuckoo_miner_async_mode: None,
|
|
|
|
cuckoo_miner_plugin_dir: Some(String::from("../target/debug/deps")),
|
2017-09-26 20:58:56 +03:00
|
|
|
cuckoo_miner_plugin_config: Some(plugin_config_vec),
|
2017-08-09 19:40:23 +03:00
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
|
|
|
|
// instantiates 5 servers on different ports
|
|
|
|
let mut servers = vec![];
|
|
|
|
for n in 0..5 {
|
|
|
|
let s = grin::Server::future(
|
|
|
|
grin::ServerConfig {
|
|
|
|
api_http_addr: format!("127.0.0.1:{}", 19000 + n),
|
|
|
|
db_root: format!("target/{}/grin-prop-{}", test_name_dir, n),
|
|
|
|
p2p_config: Some(p2p::P2PConfig {
|
|
|
|
port: 18000 + n,
|
|
|
|
..p2p::P2PConfig::default()
|
|
|
|
}),
|
2017-11-14 21:57:16 +03:00
|
|
|
seeding_type: grin::Seeding::List,
|
|
|
|
seeds: Some(vec!["127.0.0.1:18000".to_string()]),
|
2017-12-04 22:16:57 +03:00
|
|
|
chain_type: core::global::ChainTypes::AutomatedTesting,
|
2017-08-09 19:40:23 +03:00
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
&handle,
|
|
|
|
).unwrap();
|
|
|
|
servers.push(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
// start mining
|
|
|
|
servers[0].start_miner(miner_config);
|
|
|
|
let original_height = servers[0].head().height;
|
|
|
|
|
|
|
|
// monitor for a change of head on a different server and check whether
|
2017-11-14 21:57:16 +03:00
|
|
|
// chain height has changed
|
2017-08-09 19:40:23 +03:00
|
|
|
evtlp.run(change(&servers[4]).and_then(|tip| {
|
|
|
|
assert!(tip.height == original_height + 1);
|
|
|
|
Ok(())
|
|
|
|
}));
|
2016-12-23 23:15:36 +03:00
|
|
|
}
|
|
|
|
|
2017-02-19 05:42:34 +03:00
|
|
|
/// Creates 2 different disconnected servers, mine a few blocks on one, connect
|
|
|
|
/// them and check that the 2nd gets all the blocks
|
2017-02-08 00:52:17 +03:00
|
|
|
#[test]
|
|
|
|
fn simulate_full_sync() {
|
2017-10-22 10:11:45 +03:00
|
|
|
util::init_test_logger();
|
2017-12-04 22:16:57 +03:00
|
|
|
|
|
|
|
// we actually set the chain_type in the ServerConfig below
|
|
|
|
// TODO - avoid needing to set it in two places?
|
2017-11-16 00:49:15 +03:00
|
|
|
global::set_mining_mode(ChainTypes::AutomatedTesting);
|
2017-08-09 19:40:23 +03:00
|
|
|
|
|
|
|
let test_name_dir = "grin-sync";
|
|
|
|
framework::clean_all_output(test_name_dir);
|
|
|
|
|
|
|
|
let mut evtlp = reactor::Core::new().unwrap();
|
|
|
|
let handle = evtlp.handle();
|
|
|
|
|
2017-09-26 20:58:56 +03:00
|
|
|
let mut plugin_config = pow::types::CuckooMinerPluginConfig::default();
|
|
|
|
let mut plugin_config_vec: Vec<pow::types::CuckooMinerPluginConfig> = Vec::new();
|
|
|
|
plugin_config.type_filter = String::from("mean_cpu");
|
|
|
|
plugin_config_vec.push(plugin_config);
|
|
|
|
|
2017-08-22 21:23:54 +03:00
|
|
|
let miner_config = pow::types::MinerConfig {
|
2017-08-09 19:40:23 +03:00
|
|
|
enable_mining: true,
|
|
|
|
burn_reward: true,
|
|
|
|
use_cuckoo_miner: false,
|
|
|
|
cuckoo_miner_async_mode: Some(false),
|
|
|
|
cuckoo_miner_plugin_dir: Some(String::from("../target/debug/deps")),
|
2017-09-26 20:58:56 +03:00
|
|
|
cuckoo_miner_plugin_config: Some(plugin_config_vec),
|
2017-08-09 19:40:23 +03:00
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
|
|
|
|
// instantiates 2 servers on different ports
|
|
|
|
let mut servers = vec![];
|
|
|
|
for n in 0..2 {
|
2017-10-22 12:44:27 +03:00
|
|
|
let mut config = grin::ServerConfig {
|
2017-11-14 21:57:16 +03:00
|
|
|
api_http_addr: format!("127.0.0.1:{}", 19000 + n),
|
2017-10-22 10:11:45 +03:00
|
|
|
db_root: format!("target/{}/grin-sync-{}", test_name_dir, n),
|
|
|
|
p2p_config: Some(p2p::P2PConfig {
|
|
|
|
port: 11000 + n,
|
|
|
|
..p2p::P2PConfig::default()
|
|
|
|
}),
|
2017-11-14 21:57:16 +03:00
|
|
|
seeding_type: grin::Seeding::List,
|
|
|
|
seeds: Some(vec!["127.0.0.1:11000".to_string()]),
|
2017-12-04 22:16:57 +03:00
|
|
|
chain_type: core::global::ChainTypes::AutomatedTesting,
|
2017-10-22 10:11:45 +03:00
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
let s = grin::Server::future(config, &handle).unwrap();
|
2017-08-09 19:40:23 +03:00
|
|
|
servers.push(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
// mine a few blocks on server 1
|
|
|
|
servers[0].start_miner(miner_config);
|
|
|
|
thread::sleep(time::Duration::from_secs(5));
|
|
|
|
|
|
|
|
// 2 should get blocks
|
|
|
|
evtlp.run(change(&servers[1]));
|
2017-02-08 00:52:17 +03:00
|
|
|
}
|
|
|
|
|
2017-08-09 19:40:23 +03:00
|
|
|
// Builds the change future, monitoring for a change of head on the provided
|
|
|
|
// server
|
2016-12-23 23:15:36 +03:00
|
|
|
fn change<'a>(s: &'a grin::Server) -> HeadChange<'a> {
|
2017-08-09 19:40:23 +03:00
|
|
|
let start_head = s.head();
|
|
|
|
HeadChange {
|
|
|
|
server: s,
|
|
|
|
original: start_head,
|
|
|
|
}
|
2016-12-23 23:15:36 +03:00
|
|
|
}
|
|
|
|
|
2017-01-24 01:34:02 +03:00
|
|
|
/// Future that monitors when a server has had its head updated. Current
|
|
|
|
/// implementation isn't optimized, only use for tests.
|
2016-12-23 23:15:36 +03:00
|
|
|
struct HeadChange<'a> {
|
2017-08-09 19:40:23 +03:00
|
|
|
server: &'a grin::Server,
|
|
|
|
original: chain::Tip,
|
2016-12-23 23:15:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Future for HeadChange<'a> {
|
2017-08-09 19:40:23 +03:00
|
|
|
type Item = chain::Tip;
|
|
|
|
type Error = ();
|
|
|
|
|
|
|
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
|
|
let new_head = self.server.head();
|
|
|
|
if new_head.last_block_h != self.original.last_block_h {
|
|
|
|
Ok(Async::Ready(new_head))
|
|
|
|
} else {
|
|
|
|
// egregious polling, asking the task to schedule us every iteration
|
2017-08-10 03:54:10 +03:00
|
|
|
current().notify();
|
2017-08-09 19:40:23 +03:00
|
|
|
Ok(Async::NotReady)
|
|
|
|
}
|
|
|
|
}
|
2016-11-30 05:51:36 +03:00
|
|
|
}
|