Runtime benchmarks: start (#136)

* runtime benchmarks: start

* merge tests + benchmarks infrastructure

* fix compilation

* Fix compilation issues with runtime-benchmark feature flag

Mainly involved pulling in correct dependencies and adding some functions
which were called but didn't yet exist.

* Fix broken compilation for tests

* Move header signing methods into trait

* Move signing related test helpers to own module

* Remove comment about feature flag

* Add constants to tests

* Add top level comment for testing utilities

Co-authored-by: Hernando Castano <castano.ha@gmail.com>
This commit is contained in:
Svyatoslav Nikolsky
2020-06-24 23:25:21 +03:00
committed by Bastian Köcher
parent ea45fa8da7
commit e39ca0dc16
20 changed files with 944 additions and 528 deletions
+42 -66
View File
@@ -14,14 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
pub use crate::test_utils::{validator_utils::*, HeaderBuilder, GAS_LIMIT};
pub use primitives::signatures::secret_to_address;
use crate::finality::FinalityVotes;
use crate::validators::{ValidatorsConfiguration, ValidatorsSource};
use crate::{AuraConfiguration, GenesisConfig, HeaderToImport, HeadersByNumber, PruningStrategy, Storage, Trait};
use frame_support::StorageMap;
use crate::{AuraConfiguration, GenesisConfig, HeaderToImport, PruningStrategy, Storage, Trait};
use frame_support::{impl_outer_origin, parameter_types, weights::Weight};
use parity_crypto::publickey::{sign, KeyPair, Secret};
use primitives::{rlp_encode, H520};
use primitives::{Address, Header, H256, U256};
use secp256k1::SecretKey;
use sp_runtime::{
testing::Header as SubstrateHeader,
traits::{BlakeTwo256, IdentityLookup},
@@ -84,8 +85,17 @@ impl Trait for TestRuntime {
type OnHeadersSubmitted = ();
}
/// Step of genesis header.
pub const GENESIS_STEP: u64 = 42;
/// Test context.
pub struct TestContext {
/// Initial (genesis) header.
pub genesis: Header,
/// Number of initial validators.
pub total_validators: usize,
/// Secret keys of validators, ordered by validator index.
pub validators: Vec<SecretKey>,
/// Addresses of validators, ordered by validator index.
pub addresses: Vec<Address>,
}
/// Aura configuration that is used in tests by default.
pub fn test_aura_config() -> AuraConfiguration {
@@ -108,72 +118,38 @@ pub fn test_validators_config() -> ValidatorsConfiguration {
/// Genesis header that is used in tests by default.
pub fn genesis() -> Header {
Header {
seal: vec![vec![GENESIS_STEP as _].into(), vec![].into()],
..Default::default()
}
HeaderBuilder::genesis().sign_by(&validator(0))
}
/// Build default i-th block, using data from runtime storage.
pub fn block_i(number: u64, validators: &[KeyPair]) -> Header {
custom_block_i(number, validators, |_| {})
/// Run test with default genesis header.
pub fn run_test<T>(total_validators: usize, test: impl FnOnce(TestContext) -> T) -> T {
run_test_with_genesis(genesis(), total_validators, test)
}
/// Build custom i-th block, using data from runtime storage.
pub fn custom_block_i(number: u64, validators: &[KeyPair], customize: impl FnOnce(&mut Header)) -> Header {
let validator_index: u8 = (number % (validators.len() as u64)) as _;
let mut header = Header {
number,
parent_hash: HeadersByNumber::get(number - 1).unwrap()[0].clone(),
gas_limit: 0x2000.into(),
author: validator(validator_index).address(),
seal: vec![vec![(number + GENESIS_STEP) as u8].into(), vec![].into()],
difficulty: number.into(),
..Default::default()
};
customize(&mut header);
signed_header(validators, header, number + GENESIS_STEP)
/// Run test with default genesis header.
pub fn run_test_with_genesis<T>(genesis: Header, total_validators: usize, test: impl FnOnce(TestContext) -> T) -> T {
let validators = validators(total_validators);
let addresses = validators_addresses(total_validators);
sp_io::TestExternalities::new(
GenesisConfig {
initial_header: genesis.clone(),
initial_difficulty: 0.into(),
initial_validators: addresses.clone(),
}
.build_storage::<TestRuntime>()
.unwrap(),
)
.execute_with(|| {
test(TestContext {
genesis,
total_validators,
validators,
addresses,
})
})
}
/// Build signed header from given header.
pub fn signed_header(validators: &[KeyPair], mut header: Header, step: u64) -> Header {
let message = header.seal_hash(false).unwrap();
let validator_index = (step % validators.len() as u64) as usize;
let signature = sign(validators[validator_index].secret(), &message.as_fixed_bytes().into()).unwrap();
let signature: [u8; 65] = signature.into();
let signature = H520::from(signature);
header.seal[1] = rlp_encode(&signature);
header
}
/// Return key pair of given test validator.
pub fn validator(index: u8) -> KeyPair {
KeyPair::from_secret(Secret::from([index + 1; 32])).unwrap()
}
/// Return key pairs of all test validators.
pub fn validators(count: u8) -> Vec<KeyPair> {
(0..count).map(validator).collect()
}
/// Return addresses of all test validators.
pub fn validators_addresses(count: u8) -> Vec<Address> {
(0..count).map(|i| validator(i).address()).collect()
}
/// Prepare externalities to start with custom initial header.
pub fn custom_test_ext(initial_header: Header, initial_validators: Vec<Address>) -> sp_io::TestExternalities {
let t = GenesisConfig {
initial_header,
initial_difficulty: 0.into(),
initial_validators,
}
.build_storage::<TestRuntime>()
.unwrap();
sp_io::TestExternalities::new(t)
}
/// Insert header into storage.
/// Insert unverified header into storage.
pub fn insert_header<S: Storage>(storage: &mut S, header: Header) {
storage.insert_header(HeaderToImport {
context: storage.import_context(None, &header.parent_hash).unwrap(),