,
+ /// Transaction pool instance.
+ pub pool: Arc,
+ /// Whether to deny unsafe calls
+ pub deny_unsafe: DenyUnsafe,
+}
+
+/// Instantiate all full RPC extensions.
+pub fn create_full(
+ deps: FullDeps,
+) -> jsonrpc_core::IoHandler where
+ C: ProvideRuntimeApi,
+ C: HeaderBackend + HeaderMetadata + 'static,
+ C: Send + Sync + 'static,
+ C::Api: substrate_frame_rpc_system::AccountNonceApi,
+ C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi,
+ C::Api: BlockBuilder,
+ P: TransactionPool + 'static,
+{
+ use substrate_frame_rpc_system::{FullSystem, SystemApi};
+ use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApi};
+
+ let mut io = jsonrpc_core::IoHandler::default();
+ let FullDeps {
+ client,
+ pool,
+ deny_unsafe,
+ } = deps;
+
+ io.extend_with(
+ SystemApi::to_delegate(FullSystem::new(client.clone(), pool, deny_unsafe))
+ );
+
+ io.extend_with(
+ TransactionPaymentApi::to_delegate(TransactionPayment::new(client.clone()))
+ );
+
+ // Extend this RPC with a custom API by using the following syntax.
+ // `YourRpcStruct` should have a reference to a client, which is needed
+ // to call into the runtime.
+ // `io.extend_with(YourRpcTrait::to_delegate(YourRpcStruct::new(ReferenceToClient, ...)));`
+
+ io
+}
diff --git a/bin/node-template/node/src/service.rs b/bin/node-template/node/src/service.rs
index 7c4a574f6be04c823e182671b1b7930bfdb5394d..3de31dc61ab5175a36838bc01bf3c500619d647b 100644
--- a/bin/node-template/node/src/service.rs
+++ b/bin/node-template/node/src/service.rs
@@ -2,128 +2,180 @@
use std::sync::Arc;
use std::time::Duration;
-use sc_client::LongestChain;
-use sc_client_api::ExecutorProvider;
+use sc_client_api::{ExecutorProvider, RemoteBackend};
use node_template_runtime::{self, opaque::Block, RuntimeApi};
-use sc_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder};
+use sc_service::{error::Error as ServiceError, Configuration, TaskManager};
use sp_inherents::InherentDataProviders;
use sc_executor::native_executor_instance;
pub use sc_executor::NativeExecutor;
use sp_consensus_aura::sr25519::{AuthorityPair as AuraPair};
-use sc_finality_grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider, StorageAndProofProvider};
+use sc_finality_grandpa::{FinalityProofProvider as GrandpaFinalityProofProvider, SharedVoterState};
// Our native executor instance.
native_executor_instance!(
pub Executor,
node_template_runtime::api::dispatch,
node_template_runtime::native_version,
+ frame_benchmarking::benchmarking::HostFunctions,
);
-/// Starts a `ServiceBuilder` for a full service.
-///
-/// Use this macro if you don't actually need the full service, but just the builder in order to
-/// be able to perform chain operations.
-macro_rules! new_full_start {
- ($config:expr) => {{
- use std::sync::Arc;
- let mut import_setup = None;
- let inherent_data_providers = sp_inherents::InherentDataProviders::new();
-
- let builder = sc_service::ServiceBuilder::new_full::<
- node_template_runtime::opaque::Block, node_template_runtime::RuntimeApi, crate::service::Executor
- >($config)?
- .with_select_chain(|_config, backend| {
- Ok(sc_client::LongestChain::new(backend.clone()))
- })?
- .with_transaction_pool(|config, client, _fetcher| {
- let pool_api = sc_transaction_pool::FullChainApi::new(client.clone());
- Ok(sc_transaction_pool::BasicPool::new(config, std::sync::Arc::new(pool_api)))
- })?
- .with_import_queue(|_config, client, mut select_chain, _transaction_pool| {
- let select_chain = select_chain.take()
- .ok_or_else(|| sc_service::Error::SelectChainRequired)?;
-
- let (grandpa_block_import, grandpa_link) =
- sc_finality_grandpa::block_import(client.clone(), &(client.clone() as Arc<_>), select_chain)?;
-
- let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(
- grandpa_block_import.clone(), client.clone(),
- );
-
- let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>(
- sc_consensus_aura::slot_duration(&*client)?,
- aura_block_import,
- Some(Box::new(grandpa_block_import.clone())),
- None,
- client,
- inherent_data_providers.clone(),
- )?;
-
- import_setup = Some((grandpa_block_import, grandpa_link));
-
- Ok(import_queue)
- })?;
-
- (builder, import_setup, inherent_data_providers)
- }}
+type FullClient = sc_service::TFullClient;
+type FullBackend = sc_service::TFullBackend;
+type FullSelectChain = sc_consensus::LongestChain;
+
+pub fn new_partial(config: &Configuration) -> Result,
+ sc_transaction_pool::FullPool,
+ (
+ sc_consensus_aura::AuraBlockImport<
+ Block,
+ FullClient,
+ sc_finality_grandpa::GrandpaBlockImport,
+ AuraPair
+ >,
+ sc_finality_grandpa::LinkHalf
+ )
+>, ServiceError> {
+ let inherent_data_providers = sp_inherents::InherentDataProviders::new();
+
+ let (client, backend, keystore, task_manager) =
+ sc_service::new_full_parts::(&config)?;
+ let client = Arc::new(client);
+
+ let select_chain = sc_consensus::LongestChain::new(backend.clone());
+
+ let transaction_pool = sc_transaction_pool::BasicPool::new_full(
+ config.transaction_pool.clone(),
+ config.prometheus_registry(),
+ task_manager.spawn_handle(),
+ client.clone(),
+ );
+
+ let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import(
+ client.clone(), &(client.clone() as Arc<_>), select_chain.clone(),
+ )?;
+
+ let aura_block_import = sc_consensus_aura::AuraBlockImport::<_, _, _, AuraPair>::new(
+ grandpa_block_import.clone(), client.clone(),
+ );
+
+ let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>(
+ sc_consensus_aura::slot_duration(&*client)?,
+ aura_block_import.clone(),
+ Some(Box::new(grandpa_block_import.clone())),
+ None,
+ client.clone(),
+ inherent_data_providers.clone(),
+ &task_manager.spawn_handle(),
+ config.prometheus_registry(),
+ sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()),
+ )?;
+
+ Ok(sc_service::PartialComponents {
+ client, backend, task_manager, import_queue, keystore, select_chain, transaction_pool,
+ inherent_data_providers,
+ other: (aura_block_import, grandpa_link),
+ })
}
/// Builds a new service for a full client.
-pub fn new_full(config: Configuration)
- -> Result
-{
+pub fn new_full(config: Configuration) -> Result {
+ let sc_service::PartialComponents {
+ client, backend, mut task_manager, import_queue, keystore, select_chain, transaction_pool,
+ inherent_data_providers,
+ other: (block_import, grandpa_link),
+ } = new_partial(&config)?;
+
+ let finality_proof_provider =
+ GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone());
+
+ let (network, network_status_sinks, system_rpc_tx, network_starter) =
+ sc_service::build_network(sc_service::BuildNetworkParams {
+ config: &config,
+ client: client.clone(),
+ transaction_pool: transaction_pool.clone(),
+ spawn_handle: task_manager.spawn_handle(),
+ import_queue,
+ on_demand: None,
+ block_announce_validator_builder: None,
+ finality_proof_request_builder: None,
+ finality_proof_provider: Some(finality_proof_provider.clone()),
+ })?;
+
+ if config.offchain_worker.enabled {
+ sc_service::build_offchain_workers(
+ &config, backend.clone(), task_manager.spawn_handle(), client.clone(), network.clone(),
+ );
+ }
+
let role = config.role.clone();
let force_authoring = config.force_authoring;
let name = config.network.node_name.clone();
- let disable_grandpa = config.disable_grandpa;
+ let enable_grandpa = !config.disable_grandpa;
+ let prometheus_registry = config.prometheus_registry().cloned();
+ let telemetry_connection_sinks = sc_service::TelemetryConnectionSinks::default();
- let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config);
+ let rpc_extensions_builder = {
+ let client = client.clone();
+ let pool = transaction_pool.clone();
- let (block_import, grandpa_link) =
- import_setup.take()
- .expect("Link Half and Block Import are present for Full Services or setup failed before. qed");
+ Box::new(move |deny_unsafe, _| {
+ let deps = crate::rpc::FullDeps {
+ client: client.clone(),
+ pool: pool.clone(),
+ deny_unsafe,
+ };
- let service = builder
- .with_finality_proof_provider(|client, backend| {
- // GenesisAuthoritySetProvider is implemented for StorageAndProofProvider
- let provider = client as Arc>;
- Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
- })?
- .build()?;
+ crate::rpc::create_full(deps)
+ })
+ };
- if role.is_authority() {
- let proposer =
- sc_basic_authorship::ProposerFactory::new(service.client(), service.transaction_pool());
+ sc_service::spawn_tasks(sc_service::SpawnTasksParams {
+ network: network.clone(),
+ client: client.clone(),
+ keystore: keystore.clone(),
+ task_manager: &mut task_manager,
+ transaction_pool: transaction_pool.clone(),
+ telemetry_connection_sinks: telemetry_connection_sinks.clone(),
+ rpc_extensions_builder: rpc_extensions_builder,
+ on_demand: None,
+ remote_blockchain: None,
+ backend, network_status_sinks, system_rpc_tx, config,
+ })?;
- let client = service.client();
- let select_chain = service.select_chain()
- .ok_or(ServiceError::SelectChainRequired)?;
+ if role.is_authority() {
+ let proposer = sc_basic_authorship::ProposerFactory::new(
+ client.clone(),
+ transaction_pool,
+ prometheus_registry.as_ref(),
+ );
let can_author_with =
sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone());
let aura = sc_consensus_aura::start_aura::<_, _, _, _, _, AuraPair, _, _, _>(
sc_consensus_aura::slot_duration(&*client)?,
- client,
+ client.clone(),
select_chain,
block_import,
proposer,
- service.network(),
+ network.clone(),
inherent_data_providers.clone(),
force_authoring,
- service.keystore(),
+ keystore.clone(),
can_author_with,
)?;
// the AURA authoring task is considered essential, i.e. if it
// fails we take down the service with it.
- service.spawn_essential_task("aura", aura);
+ task_manager.spawn_essential_handle().spawn_blocking("aura", aura);
}
// if the node isn't actively participating in consensus then it doesn't
// need a keystore, regardless of which protocol we use below.
let keystore = if role.is_authority() {
- Some(service.keystore())
+ Some(keystore as sp_core::traits::BareCryptoStorePtr)
} else {
None
};
@@ -138,7 +190,6 @@ pub fn new_full(config: Configuration)
is_authority: role.is_network_authority(),
};
- let enable_grandpa = !disable_grandpa;
if enable_grandpa {
// start the full GRANDPA voter
// NOTE: non-authorities could run the GRANDPA observer protocol, but at
@@ -149,79 +200,104 @@ pub fn new_full(config: Configuration)
let grandpa_config = sc_finality_grandpa::GrandpaParams {
config: grandpa_config,
link: grandpa_link,
- network: service.network(),
- inherent_data_providers: inherent_data_providers.clone(),
- telemetry_on_connect: Some(service.telemetry_on_connect_stream()),
+ network,
+ inherent_data_providers,
+ telemetry_on_connect: Some(telemetry_connection_sinks.on_connect_stream()),
voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(),
- prometheus_registry: service.prometheus_registry()
+ prometheus_registry,
+ shared_voter_state: SharedVoterState::empty(),
};
// the GRANDPA voter task is considered infallible, i.e.
// if it fails we take down the service with it.
- service.spawn_essential_task(
+ task_manager.spawn_essential_handle().spawn_blocking(
"grandpa-voter",
sc_finality_grandpa::run_grandpa_voter(grandpa_config)?
);
} else {
sc_finality_grandpa::setup_disabled_grandpa(
- service.client(),
+ client,
&inherent_data_providers,
- service.network(),
+ network,
)?;
}
- Ok(service)
+ network_starter.start_network();
+ Ok(task_manager)
}
/// Builds a new service for a light client.
-pub fn new_light(config: Configuration)
- -> Result
-{
- let inherent_data_providers = InherentDataProviders::new();
-
- ServiceBuilder::new_light::(config)?
- .with_select_chain(|_config, backend| {
- Ok(LongestChain::new(backend.clone()))
- })?
- .with_transaction_pool(|config, client, fetcher| {
- let fetcher = fetcher
- .ok_or_else(|| "Trying to start light transaction pool without active fetcher")?;
-
- let pool_api = sc_transaction_pool::LightChainApi::new(client.clone(), fetcher.clone());
- let pool = sc_transaction_pool::BasicPool::with_revalidation_type(
- config, Arc::new(pool_api), sc_transaction_pool::RevalidationType::Light,
- );
- Ok(pool)
- })?
- .with_import_queue_and_fprb(|_config, client, backend, fetcher, _select_chain, _tx_pool| {
- let fetch_checker = fetcher
- .map(|fetcher| fetcher.checker().clone())
- .ok_or_else(|| "Trying to start light import queue without active fetch checker")?;
- let grandpa_block_import = sc_finality_grandpa::light_block_import(
- client.clone(),
- backend,
- &(client.clone() as Arc<_>),
- Arc::new(fetch_checker),
- )?;
- let finality_proof_import = grandpa_block_import.clone();
- let finality_proof_request_builder =
- finality_proof_import.create_finality_proof_request_builder();
-
- let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair>(
- sc_consensus_aura::slot_duration(&*client)?,
- grandpa_block_import,
- None,
- Some(Box::new(finality_proof_import)),
- client,
- inherent_data_providers.clone(),
- )?;
-
- Ok((import_queue, finality_proof_request_builder))
- })?
- .with_finality_proof_provider(|client, backend| {
- // GenesisAuthoritySetProvider is implemented for StorageAndProofProvider
- let provider = client as Arc>;
- Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, provider)) as _)
- })?
- .build()
+pub fn new_light(config: Configuration) -> Result {
+ let (client, backend, keystore, mut task_manager, on_demand) =
+ sc_service::new_light_parts::(&config)?;
+
+ let transaction_pool = Arc::new(sc_transaction_pool::BasicPool::new_light(
+ config.transaction_pool.clone(),
+ config.prometheus_registry(),
+ task_manager.spawn_handle(),
+ client.clone(),
+ on_demand.clone(),
+ ));
+
+ let grandpa_block_import = sc_finality_grandpa::light_block_import(
+ client.clone(), backend.clone(), &(client.clone() as Arc<_>),
+ Arc::new(on_demand.checker().clone()) as Arc<_>,
+ )?;
+ let finality_proof_import = grandpa_block_import.clone();
+ let finality_proof_request_builder =
+ finality_proof_import.create_finality_proof_request_builder();
+
+ let import_queue = sc_consensus_aura::import_queue::<_, _, _, AuraPair, _, _>(
+ sc_consensus_aura::slot_duration(&*client)?,
+ grandpa_block_import,
+ None,
+ Some(Box::new(finality_proof_import)),
+ client.clone(),
+ InherentDataProviders::new(),
+ &task_manager.spawn_handle(),
+ config.prometheus_registry(),
+ sp_consensus::NeverCanAuthor,
+ )?;
+
+ let finality_proof_provider =
+ GrandpaFinalityProofProvider::new_for_service(backend.clone(), client.clone());
+
+ let (network, network_status_sinks, system_rpc_tx, network_starter) =
+ sc_service::build_network(sc_service::BuildNetworkParams {
+ config: &config,
+ client: client.clone(),
+ transaction_pool: transaction_pool.clone(),
+ spawn_handle: task_manager.spawn_handle(),
+ import_queue,
+ on_demand: Some(on_demand.clone()),
+ block_announce_validator_builder: None,
+ finality_proof_request_builder: Some(finality_proof_request_builder),
+ finality_proof_provider: Some(finality_proof_provider),
+ })?;
+
+ if config.offchain_worker.enabled {
+ sc_service::build_offchain_workers(
+ &config, backend.clone(), task_manager.spawn_handle(), client.clone(), network.clone(),
+ );
+ }
+
+ sc_service::spawn_tasks(sc_service::SpawnTasksParams {
+ remote_blockchain: Some(backend.remote_blockchain()),
+ transaction_pool,
+ task_manager: &mut task_manager,
+ on_demand: Some(on_demand),
+ rpc_extensions_builder: Box::new(|_, _| ()),
+ telemetry_connection_sinks: sc_service::TelemetryConnectionSinks::default(),
+ config,
+ client,
+ keystore,
+ backend,
+ network,
+ network_status_sinks,
+ system_rpc_tx,
+ })?;
+
+ network_starter.start_network();
+
+ Ok(task_manager)
}
diff --git a/bin/node-template/pallets/template/Cargo.toml b/bin/node-template/pallets/template/Cargo.toml
index 69fcd843526806c9fe9a0b6e684a292fcbfe778b..106e4af37a8f858c7dd56f9bf6dfcf14070c63b7 100644
--- a/bin/node-template/pallets/template/Cargo.toml
+++ b/bin/node-template/pallets/template/Cargo.toml
@@ -2,37 +2,41 @@
authors = ['Anonymous']
edition = '2018'
name = 'pallet-template'
-version = "2.0.0-alpha.5"
+version = "2.0.0-rc6"
license = "Unlicense"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/substrate/"
-description = "FRAME pallet template"
+description = "FRAME pallet template for defining custom runtime logic."
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
-codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] }
+codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false, features = ["derive"] }
[dependencies.frame-support]
default-features = false
-version = "2.0.0-alpha.5"
+version = "2.0.0-rc6"
path = "../../../../frame/support"
[dependencies.frame-system]
default-features = false
-version = "2.0.0-alpha.5"
+version = "2.0.0-rc6"
path = "../../../../frame/system"
+
[dev-dependencies.sp-core]
default-features = false
-version = "2.0.0-alpha.5"
+version = "2.0.0-rc6"
path = "../../../../primitives/core"
[dev-dependencies.sp-io]
default-features = false
-version = "2.0.0-alpha.5"
+version = "2.0.0-rc6"
path = "../../../../primitives/io"
[dev-dependencies.sp-runtime]
default-features = false
-version = "2.0.0-alpha.5"
+version = "2.0.0-rc6"
path = "../../../../primitives/runtime"
@@ -43,6 +47,3 @@ std = [
'frame-support/std',
'frame-system/std'
]
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/bin/node-template/pallets/template/README.md b/bin/node-template/pallets/template/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8d751a42207ddd3f2d4d361248077a468b64f36a
--- /dev/null
+++ b/bin/node-template/pallets/template/README.md
@@ -0,0 +1 @@
+License: Unlicense
\ No newline at end of file
diff --git a/bin/node-template/pallets/template/src/lib.rs b/bin/node-template/pallets/template/src/lib.rs
index a0daecfb72c9a14ffa7e7819400f0345c542b5b8..729a71278aa9f1c2f37760274b547253799871fb 100644
--- a/bin/node-template/pallets/template/src/lib.rs
+++ b/bin/node-template/pallets/template/src/lib.rs
@@ -1,16 +1,11 @@
#![cfg_attr(not(feature = "std"), no_std)]
-/// A FRAME pallet template with necessary imports
+/// Edit this file to define custom logic or remove it if it is not needed.
+/// Learn more about FRAME and the core library of Substrate FRAME pallets:
+/// https://substrate.dev/docs/en/knowledgebase/runtime/frame
-/// Feel free to remove or edit this file as needed.
-/// If you change the name of this file, make sure to update its references in runtime/src/lib.rs
-/// If you remove this file, you can remove those references
-
-/// For more guidance on Substrate FRAME, see the example pallet
-/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs
-
-use frame_support::{decl_module, decl_storage, decl_event, decl_error, dispatch};
-use frame_system::{self as system, ensure_signed};
+use frame_support::{decl_module, decl_storage, decl_event, decl_error, dispatch, traits::Get};
+use frame_system::ensure_signed;
#[cfg(test)]
mod mock;
@@ -18,88 +13,87 @@ mod mock;
#[cfg(test)]
mod tests;
-/// The pallet's configuration trait.
-pub trait Trait: system::Trait {
- // Add other types and constants required to configure this pallet.
-
- /// The overarching event type.
- type Event: From> + Into<::Event>;
+/// Configure the pallet by specifying the parameters and types on which it depends.
+pub trait Trait: frame_system::Trait {
+ /// Because this pallet emits events, it depends on the runtime's definition of an event.
+ type Event: From> + Into<::Event>;
}
-// This pallet's storage items.
+// The pallet's runtime storage items.
+// https://substrate.dev/docs/en/knowledgebase/runtime/storage
decl_storage! {
- // It is important to update your storage name so that your pallet's
- // storage items are isolated from other pallets.
+ // A unique name is used to ensure that the pallet's storage items are isolated.
+ // This name may be updated, but each pallet in the runtime must use a unique name.
// ---------------------------------vvvvvvvvvvvvvv
trait Store for Module as TemplateModule {
- // Just a dummy storage item.
- // Here we are declaring a StorageValue, `Something` as a Option
- // `get(fn something)` is the default getter which returns either the stored `u32` or `None` if nothing stored
+ // Learn more about declaring storage items:
+ // https://substrate.dev/docs/en/knowledgebase/runtime/storage#declaring-storage-items
Something get(fn something): Option;
}
}
-// The pallet's events
+// Pallets use events to inform users when important changes are made.
+// https://substrate.dev/docs/en/knowledgebase/runtime/events
decl_event!(
- pub enum Event where AccountId = ::AccountId {
- /// Just a dummy event.
- /// Event `Something` is declared with a parameter of the type `u32` and `AccountId`
- /// To emit this event, we call the deposit function, from our runtime functions
+ pub enum Event where AccountId = ::AccountId {
+ /// Event documentation should end with an array that provides descriptive names for event
+ /// parameters. [something, who]
SomethingStored(u32, AccountId),
}
);
-// The pallet's errors
+// Errors inform users that something went wrong.
decl_error! {
pub enum Error for Module {
- /// Value was None
+ /// Error names should be descriptive.
NoneValue,
- /// Value reached maximum and cannot be incremented further
+ /// Errors should have helpful documentation associated with them.
StorageOverflow,
}
}
-// The pallet's dispatchable functions.
+// Dispatchable functions allows users to interact with the pallet and invoke state changes.
+// These functions materialize as "extrinsics", which are often compared to transactions.
+// Dispatchable functions must be annotated with a weight and must return a DispatchResult.
decl_module! {
- /// The module declaration.
pub struct Module for enum Call where origin: T::Origin {
- // Initializing errors
- // this includes information about your errors in the node's metadata.
- // it is needed only if you are using errors in your pallet
+ // Errors must be initialized if they are used by the pallet.
type Error = Error;
- // Initializing events
- // this is needed only if you are using events in your pallet
+ // Events must be initialized if they are used by the pallet.
fn deposit_event() = default;
- /// Just a dummy entry point.
- /// function that can be called by the external world as an extrinsics call
- /// takes a parameter of the type `AccountId`, stores it, and emits an event
- #[weight = frame_support::weights::SimpleDispatchInfo::default()]
+ /// An example dispatchable that takes a singles value as a parameter, writes the value to
+ /// storage and emits an event. This function must be dispatched by a signed extrinsic.
+ #[weight = 10_000 + T::DbWeight::get().writes(1)]
pub fn do_something(origin, something: u32) -> dispatch::DispatchResult {
- // Check it was signed and get the signer. See also: ensure_root and ensure_none
+ // Check that the extrinsic was signed and get the signer.
+ // This function will return an error if the extrinsic is not signed.
+ // https://substrate.dev/docs/en/knowledgebase/runtime/origin
let who = ensure_signed(origin)?;
- // Code to execute when something calls this.
- // For example: the following line stores the passed in u32 in the storage
+ // Update storage.
Something::put(something);
- // Here we are raising the Something event
+ // Emit an event.
Self::deposit_event(RawEvent::SomethingStored(something, who));
+ // Return a successful DispatchResult
Ok(())
}
- /// Another dummy entry point.
- /// takes no parameters, attempts to increment storage value, and possibly throws an error
- #[weight = frame_support::weights::SimpleDispatchInfo::default()]
+ /// An example dispatchable that may throw a custom error.
+ #[weight = 10_000 + T::DbWeight::get().reads_writes(1,1)]
pub fn cause_error(origin) -> dispatch::DispatchResult {
- // Check it was signed and get the signer. See also: ensure_root and ensure_none
let _who = ensure_signed(origin)?;
+ // Read a value from storage.
match Something::get() {
+ // Return an error if the value has not been set.
None => Err(Error::::NoneValue)?,
Some(old) => {
+ // Increment the value read from storage; will error in the event of overflow.
let new = old.checked_add(1).ok_or(Error::::StorageOverflow)?;
+ // Update the value in storage with the incremented result.
Something::put(new);
Ok(())
},
diff --git a/bin/node-template/pallets/template/src/mock.rs b/bin/node-template/pallets/template/src/mock.rs
index a93ac0359e3a2f2b8f4e0e558a0b254e33eb1c7e..8c3bf2b40473c81b2fa946b3fae86d250f448c3f 100644
--- a/bin/node-template/pallets/template/src/mock.rs
+++ b/bin/node-template/pallets/template/src/mock.rs
@@ -1,5 +1,3 @@
-// Creating mock runtime here
-
use crate::{Module, Trait};
use sp_core::H256;
use frame_support::{impl_outer_origin, parameter_types, weights::Weight};
@@ -12,9 +10,8 @@ impl_outer_origin! {
pub enum Origin for Test {}
}
-// For testing the pallet, we construct most of a mock runtime. This means
-// first constructing a configuration type (`Test`) which `impl`s each of the
-// configuration traits of pallets we want to use.
+// Configure a mock runtime to test the pallet.
+
#[derive(Clone, Eq, PartialEq)]
pub struct Test;
parameter_types! {
@@ -23,7 +20,9 @@ parameter_types! {
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
}
+
impl system::Trait for Test {
+ type BaseCallFilter = ();
type Origin = Origin;
type Call = ();
type Index = u64;
@@ -36,6 +35,10 @@ impl system::Trait for Test {
type Event = ();
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
+ type DbWeight = ();
+ type BlockExecutionWeight = ();
+ type ExtrinsicBaseWeight = ();
+ type MaximumExtrinsicWeight = MaximumBlockWeight;
type MaximumBlockLength = MaximumBlockLength;
type AvailableBlockRatio = AvailableBlockRatio;
type Version = ();
@@ -43,14 +46,16 @@ impl system::Trait for Test {
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
+ type SystemWeightInfo = ();
}
+
impl Trait for Test {
type Event = ();
}
+
pub type TemplateModule = Module;
-// This function basically just builds a genesis storage key/value store according to
-// our desired mockup.
+// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> sp_io::TestExternalities {
system::GenesisConfig::default().build_storage::().unwrap().into()
}
diff --git a/bin/node-template/pallets/template/src/tests.rs b/bin/node-template/pallets/template/src/tests.rs
index ec123a50c7cc984f15c8f80983ed300d95ecdccf..3356b29ff35980d08d751b4eca01aac403df8380 100644
--- a/bin/node-template/pallets/template/src/tests.rs
+++ b/bin/node-template/pallets/template/src/tests.rs
@@ -1,15 +1,12 @@
-// Tests to be written here
-
use crate::{Error, mock::*};
use frame_support::{assert_ok, assert_noop};
#[test]
fn it_works_for_default_value() {
new_test_ext().execute_with(|| {
- // Just a dummy test for the dummy function `do_something`
- // calling the `do_something` function with a value 42
+ // Dispatch a signed extrinsic.
assert_ok!(TemplateModule::do_something(Origin::signed(1), 42));
- // asserting that the stored value is equal to what we stored
+ // Read pallet storage and assert an expected result.
assert_eq!(TemplateModule::something(), Some(42));
});
}
@@ -17,7 +14,7 @@ fn it_works_for_default_value() {
#[test]
fn correct_error_for_none_value() {
new_test_ext().execute_with(|| {
- // Ensure the correct error is thrown on None value
+ // Ensure the expected error is thrown when no value is present.
assert_noop!(
TemplateModule::cause_error(Origin::signed(1)),
Error::::NoneValue
diff --git a/bin/node-template/runtime/Cargo.toml b/bin/node-template/runtime/Cargo.toml
index e8653e6df70e82e503a54e79c638e9a796e41913..09b46f4a56fa96d2efd0a6c7c095b2abc09073ff 100644
--- a/bin/node-template/runtime/Cargo.toml
+++ b/bin/node-template/runtime/Cargo.toml
@@ -1,40 +1,51 @@
[package]
name = "node-template-runtime"
-version = "2.0.0-alpha.5"
+version = "2.0.0-rc6"
authors = ["Anonymous"]
edition = "2018"
license = "Unlicense"
homepage = "https://substrate.dev"
repository = "https://github.com/paritytech/substrate/"
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+
[dependencies]
-codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] }
+codec = { package = "parity-scale-codec", version = "1.3.4", default-features = false, features = ["derive"] }
-aura = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-aura", path = "../../../frame/aura" }
-balances = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-balances", path = "../../../frame/balances" }
-frame-support = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/support" }
-grandpa = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-grandpa", path = "../../../frame/grandpa" }
-randomness-collective-flip = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-randomness-collective-flip", path = "../../../frame/randomness-collective-flip" }
-sudo = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-sudo", path = "../../../frame/sudo" }
-system = { version = "2.0.0-alpha.5", default-features = false, package = "frame-system", path = "../../../frame/system" }
-timestamp = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-timestamp", path = "../../../frame/timestamp" }
-transaction-payment = { version = "2.0.0-alpha.5", default-features = false, package = "pallet-transaction-payment", path = "../../../frame/transaction-payment" }
-frame-executive = { version = "2.0.0-alpha.5", default-features = false, path = "../../../frame/executive" }
+pallet-aura = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/aura" }
+pallet-balances = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/balances" }
+frame-support = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/support" }
+pallet-grandpa = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/grandpa" }
+pallet-randomness-collective-flip = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/randomness-collective-flip" }
+pallet-sudo = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/sudo" }
+frame-system = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/system" }
+pallet-timestamp = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/timestamp" }
+pallet-transaction-payment = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/transaction-payment" }
+frame-executive = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/executive" }
serde = { version = "1.0.101", optional = true, features = ["derive"] }
-sp-api = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/api" }
-sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "2.0.0-alpha.5"}
-sp-consensus-aura = { version = "0.8.0-alpha.5", default-features = false, path = "../../../primitives/consensus/aura" }
-sp-core = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/core" }
-sp-inherents = { path = "../../../primitives/inherents", default-features = false, version = "2.0.0-alpha.5"}
-sp-io = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/io" }
-sp-offchain = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/offchain" }
-sp-runtime = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/runtime" }
-sp-session = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/session" }
-sp-std = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/std" }
-sp-transaction-pool = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/transaction-pool" }
-sp-version = { version = "2.0.0-alpha.5", default-features = false, path = "../../../primitives/version" }
+sp-api = { version = "2.0.0-rc6", default-features = false, path = "../../../primitives/api" }
+sp-block-builder = { path = "../../../primitives/block-builder", default-features = false, version = "2.0.0-rc6"}
+sp-consensus-aura = { version = "0.8.0-rc6", default-features = false, path = "../../../primitives/consensus/aura" }
+sp-core = { version = "2.0.0-rc6", default-features = false, path = "../../../primitives/core" }
+sp-inherents = { path = "../../../primitives/inherents", default-features = false, version = "2.0.0-rc6"}
+sp-offchain = { version = "2.0.0-rc6", default-features = false, path = "../../../primitives/offchain" }
+sp-runtime = { version = "2.0.0-rc6", default-features = false, path = "../../../primitives/runtime" }
+sp-session = { version = "2.0.0-rc6", default-features = false, path = "../../../primitives/session" }
+sp-std = { version = "2.0.0-rc6", default-features = false, path = "../../../primitives/std" }
+sp-transaction-pool = { version = "2.0.0-rc6", default-features = false, path = "../../../primitives/transaction-pool" }
+sp-version = { version = "2.0.0-rc6", default-features = false, path = "../../../primitives/version" }
+
+# Used for the node template's RPCs
+frame-system-rpc-runtime-api = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/system/rpc/runtime-api/" }
+pallet-transaction-payment-rpc-runtime-api = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" }
+
+# Used for runtime benchmarking
+frame-benchmarking = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/benchmarking", optional = true }
+frame-system-benchmarking = { version = "2.0.0-rc6", default-features = false, path = "../../../frame/system/benchmarking", optional = true }
+hex-literal = { version = "0.3.1", optional = true }
-template = { version = "2.0.0-alpha.5", default-features = false, path = "../pallets/template", package = "pallet-template" }
+template = { version = "2.0.0-rc6", default-features = false, path = "../pallets/template", package = "pallet-template" }
[build-dependencies]
wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-runner", path = "../../../utils/wasm-builder-runner" }
@@ -42,32 +53,40 @@ wasm-builder-runner = { version = "1.0.5", package = "substrate-wasm-builder-run
[features]
default = ["std"]
std = [
- "aura/std",
- "balances/std",
"codec/std",
"frame-executive/std",
"frame-support/std",
- "grandpa/std",
- "randomness-collective-flip/std",
+ "pallet-aura/std",
+ "pallet-balances/std",
+ "pallet-grandpa/std",
+ "pallet-randomness-collective-flip/std",
+ "pallet-sudo/std",
+ "pallet-timestamp/std",
+ "pallet-transaction-payment/std",
+ "pallet-transaction-payment-rpc-runtime-api/std",
"serde",
"sp-api/std",
"sp-block-builder/std",
"sp-consensus-aura/std",
"sp-core/std",
"sp-inherents/std",
- "sp-io/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
"sp-std/std",
"sp-transaction-pool/std",
"sp-version/std",
- "sudo/std",
- "system/std",
- "timestamp/std",
- "transaction-payment/std",
+ "frame-system/std",
+ "frame-system-rpc-runtime-api/std",
"template/std",
]
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
+runtime-benchmarks = [
+ "sp-runtime/runtime-benchmarks",
+ "frame-benchmarking",
+ "frame-support/runtime-benchmarks",
+ "frame-system-benchmarking",
+ "hex-literal",
+ "frame-system/runtime-benchmarks",
+ "pallet-balances/runtime-benchmarks",
+ "pallet-timestamp/runtime-benchmarks",
+]
diff --git a/bin/node-template/runtime/build.rs b/bin/node-template/runtime/build.rs
index 39f7f56feb0b1730d7f2c9a7daa898fe54bfd052..52705043a2019c43604f4af498af2f785d5a8555 100644
--- a/bin/node-template/runtime/build.rs
+++ b/bin/node-template/runtime/build.rs
@@ -3,7 +3,7 @@ use wasm_builder_runner::WasmBuilder;
fn main() {
WasmBuilder::new()
.with_current_project()
- .with_wasm_builder_from_crates("1.0.9")
+ .with_wasm_builder_from_crates("2.0.0")
.export_heap_base()
.import_memory()
.build()
diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs
index 94f033fd8f58ee231f412e7a2cf6f7f53f77d49a..9612394cc7fbf88e2abb5e735248df74886d6b72 100644
--- a/bin/node-template/runtime/src/lib.rs
+++ b/bin/node-template/runtime/src/lib.rs
@@ -1,5 +1,3 @@
-//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.
-
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit="256"]
@@ -9,18 +7,18 @@
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
use sp_std::prelude::*;
-use sp_core::OpaqueMetadata;
+use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
ApplyExtrinsicResult, generic, create_runtime_str, impl_opaque_keys, MultiSignature,
transaction_validity::{TransactionValidity, TransactionSource},
};
use sp_runtime::traits::{
- BlakeTwo256, Block as BlockT, IdentityLookup, Verify, ConvertInto, IdentifyAccount
+ BlakeTwo256, Block as BlockT, IdentityLookup, Verify, IdentifyAccount, NumberFor, Saturating,
};
use sp_api::impl_runtime_apis;
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
-use grandpa::AuthorityList as GrandpaAuthorityList;
-use grandpa::fg_primitives;
+use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
+use pallet_grandpa::fg_primitives;
use sp_version::RuntimeVersion;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
@@ -28,16 +26,19 @@ use sp_version::NativeVersion;
// A few exports that help ease life for downstream crates.
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
-pub use timestamp::Call as TimestampCall;
-pub use balances::Call as BalancesCall;
+pub use pallet_timestamp::Call as TimestampCall;
+pub use pallet_balances::Call as BalancesCall;
pub use sp_runtime::{Permill, Perbill};
pub use frame_support::{
- StorageValue, construct_runtime, parameter_types,
- traits::Randomness,
- weights::Weight,
+ construct_runtime, parameter_types, StorageValue,
+ traits::{KeyOwnerProofSystem, Randomness},
+ weights::{
+ Weight, IdentityFee,
+ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
+ },
};
-/// Importing a template pallet
+/// Import the template pallet.
pub use template;
/// An index to a block.
@@ -90,7 +91,6 @@ pub mod opaque {
}
}
-/// This runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("node-template"),
impl_name: create_runtime_str!("node-template"),
@@ -98,13 +98,14 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_version: 1,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
+ transaction_version: 1,
};
pub const MILLISECS_PER_BLOCK: u64 = 6000;
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
-// These time units are defined in number of blocks.
+// Time is measured by number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
@@ -119,14 +120,22 @@ pub fn native_version() -> NativeVersion {
}
parameter_types! {
- pub const BlockHashCount: BlockNumber = 250;
- pub const MaximumBlockWeight: Weight = 1_000_000_000;
+ pub const BlockHashCount: BlockNumber = 2400;
+ /// We allow for 2 seconds of compute with a 6 second average block time.
+ pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND;
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
+ /// Assume 10% of weight for average on_initialize calls.
+ pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get()
+ .saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get();
pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
pub const Version: RuntimeVersion = VERSION;
}
-impl system::Trait for Runtime {
+// Configure FRAME pallets to include in runtime.
+
+impl frame_system::Trait for Runtime {
+ /// The basic call filter to use in dispatchable.
+ type BaseCallFilter = ();
/// The identifier used to distinguish between accounts.
type AccountId = AccountId;
/// The aggregated dispatch type that is available for extrinsics.
@@ -151,6 +160,18 @@ impl system::Trait for Runtime {
type BlockHashCount = BlockHashCount;
/// Maximum weight of each block.
type MaximumBlockWeight = MaximumBlockWeight;
+ /// The weight of database operations that the runtime can invoke.
+ type DbWeight = RocksDbWeight;
+ /// The weight of the overhead invoked on the block import process, independent of the
+ /// extrinsics included in that block.
+ type BlockExecutionWeight = BlockExecutionWeight;
+ /// The base weight of any extrinsic processed by the runtime, independent of the
+ /// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...)
+ type ExtrinsicBaseWeight = ExtrinsicBaseWeight;
+ /// The maximum weight that a single extrinsic of `Normal` dispatch class can have,
+ /// idependent of the logic of that extrinsics. (Roughly max block weight - average on
+ /// initialize cost).
+ type MaximumExtrinsicWeight = MaximumExtrinsicWeight;
/// Maximum size of all encoded transactions (in bytes) that are allowed in one block.
type MaximumBlockLength = MaximumBlockLength;
/// Portion of the block weight that is available to all normal transactions.
@@ -166,33 +187,51 @@ impl system::Trait for Runtime {
/// What to do if an account is fully reaped from the system.
type OnKilledAccount = ();
/// The data to be stored in an account.
- type AccountData = balances::AccountData;
+ type AccountData = pallet_balances::AccountData;
+ /// Weight information for the extrinsics of this pallet.
+ type SystemWeightInfo = ();
}
-impl aura::Trait for Runtime {
+impl pallet_aura::Trait for Runtime {
type AuthorityId = AuraId;
}
-impl grandpa::Trait for Runtime {
+impl pallet_grandpa::Trait for Runtime {
type Event = Event;
+ type Call = Call;
+
+ type KeyOwnerProofSystem = ();
+
+ type KeyOwnerProof =
+ >::Proof;
+
+ type KeyOwnerIdentification = >::IdentificationTuple;
+
+ type HandleEquivocation = ();
}
parameter_types! {
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
}
-impl timestamp::Trait for Runtime {
+impl pallet_timestamp::Trait for Runtime {
/// A timestamp: milliseconds since the unix epoch.
type Moment = u64;
type OnTimestampSet = Aura;
type MinimumPeriod = MinimumPeriod;
+ type WeightInfo = ();
}
parameter_types! {
pub const ExistentialDeposit: u128 = 500;
+ pub const MaxLocks: u32 = 50;
}
-impl balances::Trait for Runtime {
+impl pallet_balances::Trait for Runtime {
+ type MaxLocks = MaxLocks;
/// The type for recording an account's balance.
type Balance = Balance;
/// The ubiquitous event type.
@@ -200,47 +239,47 @@ impl balances::Trait for Runtime {
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
+ type WeightInfo = ();
}
parameter_types! {
- pub const TransactionBaseFee: Balance = 0;
pub const TransactionByteFee: Balance = 1;
}
-impl transaction_payment::Trait for Runtime {
- type Currency = balances::Module;
+impl pallet_transaction_payment::Trait for Runtime {
+ type Currency = Balances;
type OnTransactionPayment = ();
- type TransactionBaseFee = TransactionBaseFee;
type TransactionByteFee = TransactionByteFee;
- type WeightToFee = ConvertInto;
+ type WeightToFee = IdentityFee;
type FeeMultiplierUpdate = ();
}
-impl sudo::Trait for Runtime {
+impl pallet_sudo::Trait for Runtime {
type Event = Event;
type Call = Call;
}
-/// Used for the module template in `./template.rs`
+/// Configure the pallet template in pallets/template.
impl template::Trait for Runtime {
type Event = Event;
}
+// Create the runtime by composing the FRAME pallets that were previously configured.
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
- System: system::{Module, Call, Config, Storage, Event},
- RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage},
- Timestamp: timestamp::{Module, Call, Storage, Inherent},
- Aura: aura::{Module, Config, Inherent(Timestamp)},
- Grandpa: grandpa::{Module, Call, Storage, Config, Event},
- Balances: balances::{Module, Call, Storage, Config, Event},
- TransactionPayment: transaction_payment::{Module, Storage},
- Sudo: sudo::{Module, Call, Config, Storage, Event},
- // Used for the module template in `./template.rs`
+ System: frame_system::{Module, Call, Config, Storage, Event},
+ RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},
+ Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},
+ Aura: pallet_aura::{Module, Config, Inherent},
+ Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event},
+ Balances: pallet_balances::{Module, Call, Storage, Config, Event},
+ TransactionPayment: pallet_transaction_payment::{Module, Storage},
+ Sudo: pallet_sudo::{Module, Call, Config, Storage, Event},
+ // Include the custom logic from the template pallet in the runtime.
TemplateModule: template::{Module, Call, Storage, Event},
}
);
@@ -257,19 +296,26 @@ pub type SignedBlock = generic::SignedBlock;
pub type BlockId = generic::BlockId;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
- system::CheckVersion,
- system::CheckGenesis,
- system::CheckEra,
- system::CheckNonce,
- system::CheckWeight,
- transaction_payment::ChargeTransactionPayment
+ frame_system::CheckSpecVersion,
+ frame_system::CheckTxVersion,
+ frame_system::CheckGenesis,
+ frame_system::CheckEra,
+ frame_system::CheckNonce,
+ frame_system::CheckWeight,
+ pallet_transaction_payment::ChargeTransactionPayment
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic;
/// Executive: handles dispatch to the various modules.
-pub type Executive = frame_executive::Executive, Runtime, AllModules>;
+pub type Executive = frame_executive::Executive<
+ Runtime,
+ Block,
+ frame_system::ChainContext,
+ Runtime,
+ AllModules,
+>;
impl_runtime_apis! {
impl sp_api::Core for Runtime {
@@ -349,7 +395,7 @@ impl_runtime_apis! {
fn decode_session_keys(
encoded: Vec,
- ) -> Option, sp_core::crypto::KeyTypeId)>> {
+ ) -> Option, KeyTypeId)>> {
opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
}
}
@@ -358,5 +404,75 @@ impl_runtime_apis! {
fn grandpa_authorities() -> GrandpaAuthorityList {
Grandpa::grandpa_authorities()
}
+
+ fn submit_report_equivocation_unsigned_extrinsic(
+ _equivocation_proof: fg_primitives::EquivocationProof<
+ ::Hash,
+ NumberFor,
+ >,
+ _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,
+ ) -> Option<()> {
+ None
+ }
+
+ fn generate_key_ownership_proof(
+ _set_id: fg_primitives::SetId,
+ _authority_id: GrandpaId,
+ ) -> Option {
+ // NOTE: this is the only implementation possible since we've
+ // defined our key owner proof type as a bottom type (i.e. a type
+ // with no values).
+ None
+ }
+ }
+
+ impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime {
+ fn account_nonce(account: AccountId) -> Index {
+ System::account_nonce(account)
+ }
+ }
+
+ impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime {
+ fn query_info(
+ uxt: ::Extrinsic,
+ len: u32,
+ ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo {
+ TransactionPayment::query_info(uxt, len)
+ }
+ }
+
+ #[cfg(feature = "runtime-benchmarks")]
+ impl frame_benchmarking::Benchmark for Runtime {
+ fn dispatch_benchmark(
+ config: frame_benchmarking::BenchmarkConfig
+ ) -> Result, sp_runtime::RuntimeString> {
+ use frame_benchmarking::{Benchmarking, BenchmarkBatch, add_benchmark, TrackedStorageKey};
+
+ use frame_system_benchmarking::Module as SystemBench;
+ impl frame_system_benchmarking::Trait for Runtime {}
+
+ let whitelist: Vec = vec![
+ // Block Number
+ hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(),
+ // Total Issuance
+ hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(),
+ // Execution Phase
+ hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(),
+ // Event Count
+ hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(),
+ // System Events
+ hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(),
+ ];
+
+ let mut batches = Vec::::new();
+ let params = (&config, &whitelist);
+
+ add_benchmark!(params, batches, frame_system, SystemBench::);
+ add_benchmark!(params, batches, pallet_balances, Balances);
+ add_benchmark!(params, batches, pallet_timestamp, Timestamp);
+
+ if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) }
+ Ok(batches)
+ }
}
}
diff --git a/bin/node/bench/Cargo.toml b/bin/node/bench/Cargo.toml
index 22e7fe51d848e1f44ca0c34eddb57d39ca0d0c32..ec797e32de3f2e99795c13d40116bec50e53a5d4 100644
--- a/bin/node/bench/Cargo.toml
+++ b/bin/node/bench/Cargo.toml
@@ -1,20 +1,44 @@
[package]
name = "node-bench"
-version = "0.8.0-alpha.5"
+version = "0.8.0-rc6"
authors = ["Parity Technologies "]
description = "Substrate node integration benchmarks."
edition = "2018"
-license = "GPL-3.0"
+license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0.4.8"
-node-primitives = { version = "2.0.0-alpha.5", path = "../primitives" }
-node-testing = { version = "2.0.0-alpha.5", path = "../testing" }
-sc-cli = { version = "0.8.0-alpha.5", path = "../../../client/cli" }
-sc-client-api = { version = "2.0.0-alpha.5", path = "../../../client/api/" }
-sp-runtime = { version = "2.0.0-alpha.5", path = "../../../primitives/runtime" }
+node-primitives = { version = "2.0.0-rc6", path = "../primitives" }
+node-testing = { version = "2.0.0-rc6", path = "../testing" }
+node-runtime = { version = "2.0.0-rc6", path = "../runtime" }
+sc-cli = { version = "0.8.0-rc6", path = "../../../client/cli" }
+sc-client-api = { version = "2.0.0-rc6", path = "../../../client/api/" }
+sp-runtime = { version = "2.0.0-rc6", path = "../../../primitives/runtime" }
+sp-state-machine = { version = "0.8.0-rc6", path = "../../../primitives/state-machine" }
serde = "1.0.101"
serde_json = "1.0.41"
-structopt = "0.3"
\ No newline at end of file
+structopt = "0.3"
+derive_more = "0.99.2"
+kvdb = "0.7"
+kvdb-rocksdb = "0.9.1"
+sp-trie = { version = "2.0.0-rc6", path = "../../../primitives/trie" }
+sp-core = { version = "2.0.0-rc6", path = "../../../primitives/core" }
+sp-consensus = { version = "0.8.0-rc6", path = "../../../primitives/consensus/common" }
+sp-transaction-pool = { version = "2.0.0-rc6", path = "../../../primitives/transaction-pool" }
+sc-basic-authorship = { version = "0.8.0-rc6", path = "../../../client/basic-authorship" }
+sp-inherents = { version = "2.0.0-rc6", path = "../../../primitives/inherents" }
+sp-finality-tracker = { version = "2.0.0-rc6", default-features = false, path = "../../../primitives/finality-tracker" }
+sp-timestamp = { version = "2.0.0-rc6", default-features = false, path = "../../../primitives/timestamp" }
+sp-tracing = { version = "2.0.0-rc6", path = "../../../primitives/tracing" }
+hash-db = "0.15.2"
+tempfile = "3.1.0"
+fs_extra = "1"
+hex = "0.4.0"
+rand = { version = "0.7.2", features = ["small_rng"] }
+lazy_static = "1.4.0"
+parity-util-mem = { version = "0.7.0", default-features = false, features = ["primitive-types"] }
+parity-db = { version = "0.1.2" }
+sc-transaction-pool = { version = "2.0.0-rc6", path = "../../../client/transaction-pool" }
+futures = { version = "0.3.4", features = ["thread-pool"] }
diff --git a/bin/node/bench/src/common.rs b/bin/node/bench/src/common.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2637d6e9bd04d809af5b374790adcc6e5207993f
--- /dev/null
+++ b/bin/node/bench/src/common.rs
@@ -0,0 +1,48 @@
+
+// This file is part of Substrate.
+
+// Copyright (C) 2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#[derive(Clone, Copy, Debug, derive_more::Display)]
+pub enum SizeType {
+ #[display(fmt = "empty")]
+ Empty,
+ #[display(fmt = "small")]
+ Small,
+ #[display(fmt = "medium")]
+ Medium,
+ #[display(fmt = "large")]
+ Large,
+ #[display(fmt = "full")]
+ Full,
+ #[display(fmt = "custom")]
+ Custom(usize),
+}
+
+impl SizeType {
+ pub fn transactions(&self) -> Option {
+ match self {
+ SizeType::Empty => Some(0),
+ SizeType::Small => Some(10),
+ SizeType::Medium => Some(100),
+ SizeType::Large => Some(500),
+ SizeType::Full => None,
+ // Custom SizeType will use the `--transactions` input parameter
+ SizeType::Custom(val) => Some(*val),
+ }
+ }
+}
\ No newline at end of file
diff --git a/bin/node/bench/src/construct.rs b/bin/node/bench/src/construct.rs
new file mode 100644
index 0000000000000000000000000000000000000000..e23594dd4364a1de30d65096fe69ab1627599a36
--- /dev/null
+++ b/bin/node/bench/src/construct.rs
@@ -0,0 +1,296 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+//! Block construction benchmark.
+//!
+//! This benchmark is expected to measure block construction.
+//! We want to protect against cold-cache attacks, and so this
+//! benchmark should not rely on any caching (except those entries that
+//! DO NOT depend on user input). Thus transaction generation should be
+//! based on randomized data.
+
+use std::{
+ borrow::Cow,
+ collections::HashMap,
+ pin::Pin,
+ sync::Arc,
+};
+use futures::Future;
+
+use node_primitives::Block;
+use node_testing::bench::{BenchDb, Profile, BlockType, KeyTypes, DatabaseType};
+use sp_runtime::{
+ generic::BlockId,
+ traits::NumberFor,
+ OpaqueExtrinsic,
+};
+use sp_transaction_pool::{
+ ImportNotificationStream,
+ PoolFuture,
+ PoolStatus,
+ TransactionFor,
+ TransactionSource,
+ TransactionStatusStreamFor,
+ TxHash,
+};
+use sp_consensus::{Environment, Proposer, RecordProof};
+
+use crate::{
+ common::SizeType,
+ core::{self, Path, Mode},
+};
+
+pub struct ConstructionBenchmarkDescription {
+ pub profile: Profile,
+ pub key_types: KeyTypes,
+ pub block_type: BlockType,
+ pub size: SizeType,
+ pub database_type: DatabaseType,
+}
+
+pub struct ConstructionBenchmark {
+ profile: Profile,
+ database: BenchDb,
+ transactions: Transactions,
+}
+
+impl core::BenchmarkDescription for ConstructionBenchmarkDescription {
+ fn path(&self) -> Path {
+
+ let mut path = Path::new(&["node", "proposer"]);
+
+ match self.profile {
+ Profile::Wasm => path.push("wasm"),
+ Profile::Native => path.push("native"),
+ }
+
+ match self.key_types {
+ KeyTypes::Sr25519 => path.push("sr25519"),
+ KeyTypes::Ed25519 => path.push("ed25519"),
+ }
+
+ match self.block_type {
+ BlockType::RandomTransfersKeepAlive => path.push("transfer"),
+ BlockType::RandomTransfersReaping => path.push("transfer_reaping"),
+ BlockType::Noop => path.push("noop"),
+ }
+
+ match self.database_type {
+ DatabaseType::RocksDb => path.push("rocksdb"),
+ DatabaseType::ParityDb => path.push("paritydb"),
+ }
+
+ path.push(&format!("{}", self.size));
+
+ path
+ }
+
+ fn setup(self: Box) -> Box {
+ let mut extrinsics: Vec> = Vec::new();
+
+ let mut bench_db = BenchDb::with_key_types(
+ self.database_type,
+ 50_000,
+ self.key_types
+ );
+
+ let client = bench_db.client();
+
+ let content_type = self.block_type.to_content(self.size.transactions());
+ for transaction in bench_db.block_content(content_type, &client) {
+ extrinsics.push(Arc::new(transaction.into()));
+ }
+
+ Box::new(ConstructionBenchmark {
+ profile: self.profile,
+ database: bench_db,
+ transactions: Transactions(extrinsics),
+ })
+ }
+
+ fn name(&self) -> Cow<'static, str> {
+ format!(
+ "Block construction ({:?}/{}, {:?}, {:?} backend)",
+ self.block_type,
+ self.size,
+ self.profile,
+ self.database_type,
+ ).into()
+ }
+}
+
+impl core::Benchmark for ConstructionBenchmark {
+ fn run(&mut self, mode: Mode) -> std::time::Duration {
+ let context = self.database.create_context(self.profile);
+
+ let _ = context.client.runtime_version_at(&BlockId::Number(0))
+ .expect("Failed to get runtime version")
+ .spec_version;
+
+ if mode == Mode::Profile {
+ std::thread::park_timeout(std::time::Duration::from_secs(3));
+ }
+
+ let mut proposer_factory = sc_basic_authorship::ProposerFactory::new(
+ context.client.clone(),
+ self.transactions.clone().into(),
+ None,
+ );
+ let inherent_data_providers = sp_inherents::InherentDataProviders::new();
+ inherent_data_providers
+ .register_provider(sp_timestamp::InherentDataProvider)
+ .expect("Failed to register timestamp data provider");
+
+ let start = std::time::Instant::now();
+
+ let proposer = futures::executor::block_on(proposer_factory.init(
+ &context.client.header(&BlockId::number(0))
+ .expect("Database error querying block #0")
+ .expect("Block #0 should exist"),
+ )).expect("Proposer initialization failed");
+
+ let _block = futures::executor::block_on(
+ proposer.propose(
+ inherent_data_providers.create_inherent_data().expect("Create inherent data failed"),
+ Default::default(),
+ std::time::Duration::from_secs(20),
+ RecordProof::Yes,
+ ),
+ ).map(|r| r.block).expect("Proposing failed");
+
+ let elapsed = start.elapsed();
+
+ if mode == Mode::Profile {
+ std::thread::park_timeout(std::time::Duration::from_secs(1));
+ }
+
+ elapsed
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct PoolTransaction {
+ data: OpaqueExtrinsic,
+ hash: node_primitives::Hash,
+}
+
+impl From for PoolTransaction {
+ fn from(e: OpaqueExtrinsic) -> Self {
+ PoolTransaction {
+ data: e,
+ hash: node_primitives::Hash::zero(),
+ }
+ }
+}
+
+impl sp_transaction_pool::InPoolTransaction for PoolTransaction {
+ type Transaction = OpaqueExtrinsic;
+ type Hash = node_primitives::Hash;
+
+ fn data(&self) -> &Self::Transaction {
+ &self.data
+ }
+
+ fn hash(&self) -> &Self::Hash {
+ &self.hash
+ }
+
+ fn priority(&self) -> &u64 { unimplemented!() }
+
+ fn longevity(&self) -> &u64 { unimplemented!() }
+
+ fn requires(&self) -> &[Vec] { unimplemented!() }
+
+ fn provides(&self) -> &[Vec] { unimplemented!() }
+
+ fn is_propagable(&self) -> bool { unimplemented!() }
+}
+
+#[derive(Clone, Debug)]
+pub struct Transactions(Vec>);
+
+impl sp_transaction_pool::TransactionPool for Transactions {
+ type Block = Block;
+ type Hash = node_primitives::Hash;
+ type InPoolTransaction = PoolTransaction;
+ type Error = sp_transaction_pool::error::Error;
+
+ /// Returns a future that imports a bunch of unverified transactions to the pool.
+ fn submit_at(
+ &self,
+ _at: &BlockId,
+ _source: TransactionSource,
+ _xts: Vec>,
+ ) -> PoolFuture>, Self::Error> {
+ unimplemented!()
+ }
+
+ /// Returns a future that imports one unverified transaction to the pool.
+ fn submit_one(
+ &self,
+ _at: &BlockId,
+ _source: TransactionSource,
+ _xt: TransactionFor,
+ ) -> PoolFuture, Self::Error> {
+ unimplemented!()
+ }
+
+ fn submit_and_watch(
+ &self,
+ _at: &BlockId,
+ _source: TransactionSource,
+ _xt: TransactionFor,
+ ) -> PoolFuture>, Self::Error> {
+ unimplemented!()
+ }
+
+ fn ready_at(&self, _at: NumberFor)
+ -> Pin> + Send>> + Send>>
+ {
+ let iter: Box> + Send> = Box::new(self.0.clone().into_iter());
+ Box::pin(futures::future::ready(iter))
+ }
+
+ fn ready(&self) -> Box> + Send> {
+ unimplemented!()
+ }
+
+ fn remove_invalid(&self, _hashes: &[TxHash]) -> Vec> {
+ Default::default()
+ }
+
+ fn status(&self) -> PoolStatus {
+ unimplemented!()
+ }
+
+ fn import_notification_stream(&self) -> ImportNotificationStream> {
+ unimplemented!()
+ }
+
+ fn on_broadcasted(&self, _propagations: HashMap, Vec>) {
+ unimplemented!()
+ }
+
+ fn hash_of(&self, _xt: &TransactionFor) -> TxHash {
+ unimplemented!()
+ }
+
+ fn ready_transaction(&self, _hash: &TxHash) -> Option> {
+ unimplemented!()
+ }
+}
\ No newline at end of file
diff --git a/bin/node/bench/src/core.rs b/bin/node/bench/src/core.rs
index a8164db75a53833855ad996cd1aceaa24e232123..6faa7b72721f495ac6a481f3f48dd0b86e9efd3a 100644
--- a/bin/node/bench/src/core.rs
+++ b/bin/node/bench/src/core.rs
@@ -1,18 +1,20 @@
-// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
-// Substrate is free software: you can redistribute it and/or modify
+// Copyright (C) 2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-// Substrate is distributed in the hope that it will be useful,
+// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
-// along with Substrate. If not, see .
+// along with this program. If not, see .
use std::{fmt, borrow::{Cow, ToOwned}};
use serde::Serialize;
@@ -48,7 +50,7 @@ pub trait BenchmarkDescription {
}
pub trait Benchmark {
- fn run(&mut self) -> std::time::Duration;
+ fn run(&mut self, mode: Mode) -> std::time::Duration;
}
#[derive(Debug, Clone, Serialize)]
@@ -58,7 +60,7 @@ pub struct BenchmarkOutput {
average: u64,
}
-struct NsFormatter(u64);
+pub struct NsFormatter(pub u64);
impl fmt::Display for NsFormatter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -68,41 +70,61 @@ impl fmt::Display for NsFormatter {
return write!(f, "{} ns", v)
}
- if self.0 < 10_000 {
+ if self.0 < 100_000 {
return write!(f, "{:.1} µs", v as f64 / 1000.0)
}
if self.0 < 1_000_000 {
- return write!(f, "{:.1} ms", v as f64 / 1_000_000.0)
+ return write!(f, "{:.4} ms", v as f64 / 1_000_000.0)
}
if self.0 < 100_000_000 {
- return write!(f, "{} ms", v as f64 / 1_000_000.0)
+ return write!(f, "{:.1} ms", v as f64 / 1_000_000.0)
}
- write!(f, "{:.2} s", v as f64 / 1_000_000_000.0)
+ write!(f, "{:.4} s", v as f64 / 1_000_000_000.0)
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum Mode {
+ Regular,
+ Profile,
+}
+
+impl std::str::FromStr for Mode {
+ type Err = &'static str;
+ fn from_str(day: &str) -> Result {
+ match day {
+ "regular" => Ok(Mode::Regular),
+ "profile" => Ok(Mode::Profile),
+ _ => Err("Could not parse mode"),
+ }
}
}
impl fmt::Display for BenchmarkOutput {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
f,
- "({}: avg {}, w_avg {})",
+ "{}: avg {}, w_avg {}",
self.name,
NsFormatter(self.raw_average),
NsFormatter(self.average),
)
- }
+ }
}
-pub fn run_benchmark(benchmark: Box) -> BenchmarkOutput {
+pub fn run_benchmark(
+ benchmark: Box,
+ mode: Mode,
+) -> BenchmarkOutput {
let name = benchmark.name().to_owned();
let mut benchmark = benchmark.setup();
let mut durations: Vec = vec![];
for _ in 0..50 {
- let duration = benchmark.run();
+ let duration = benchmark.run(mode);
durations.push(duration.as_nanos());
}
@@ -119,10 +141,10 @@ pub fn run_benchmark(benchmark: Box) -> BenchmarkOutpu
}
macro_rules! matrix(
- ( $var:ident in $over:expr => $tt:expr, $( $rest:tt )* ) => {
+ ( $var:tt in $over:expr => $tt:expr, $( $rest:tt )* ) => {
{
let mut res = Vec::>::new();
- for $var in $over.iter() {
+ for $var in $over {
res.push(Box::new($tt));
}
res.extend(matrix!( $($rest)* ));
@@ -137,4 +159,4 @@ macro_rules! matrix(
}
};
() => { vec![] }
-);
\ No newline at end of file
+);
diff --git a/bin/node/bench/src/generator.rs b/bin/node/bench/src/generator.rs
new file mode 100644
index 0000000000000000000000000000000000000000..759a4299c72758f540e92349de6a25591c506d39
--- /dev/null
+++ b/bin/node/bench/src/generator.rs
@@ -0,0 +1,66 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use std::{collections::HashMap, sync::Arc};
+
+use kvdb::KeyValueDB;
+use node_primitives::Hash;
+use sp_trie::{trie_types::TrieDBMut, TrieMut};
+
+use crate::simple_trie::SimpleTrie;
+
+/// Generate trie from given `key_values`.
+///
+/// Will fill your database `db` with trie data from `key_values` and
+/// return root.
+pub fn generate_trie(
+ db: Arc,
+ key_values: impl IntoIterator- , Vec)>,
+) -> Hash {
+ let mut root = Hash::default();
+
+ let (db, overlay) = {
+ let mut overlay = HashMap::new();
+ overlay.insert(
+ hex::decode("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").expect("null key is valid"),
+ Some(vec![0]),
+ );
+ let mut trie = SimpleTrie { db, overlay: &mut overlay };
+ {
+ let mut trie_db = TrieDBMut::new(&mut trie, &mut root);
+
+ for (key, value) in key_values {
+ trie_db.insert(&key, &value).expect("trie insertion failed");
+ }
+
+ trie_db.commit();
+ }
+ ( trie.db, overlay )
+ };
+
+ let mut transaction = db.transaction();
+ for (key, value) in overlay.into_iter() {
+ match value {
+ Some(value) => transaction.put(0, &key[..], &value[..]),
+ None => transaction.delete(0, &key[..]),
+ }
+ }
+ db.write(transaction).expect("Failed to write transaction");
+
+ root
+}
diff --git a/bin/node/bench/src/import.rs b/bin/node/bench/src/import.rs
index 20181bf4c7f7de816226ab76701d2c9339d56fa8..e49a359fb6af16fc26a7f252ca759442c35bbe1a 100644
--- a/bin/node/bench/src/import.rs
+++ b/bin/node/bench/src/import.rs
@@ -1,18 +1,20 @@
-// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
-// Substrate is free software: you can redistribute it and/or modify
+// Copyright (C) 2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-// Substrate is distributed in the hope that it will be useful,
+// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
-// along with Substrate. If not, see .
+// along with this program. If not, see .
//! Block import benchmark.
//!
@@ -30,36 +32,30 @@
use std::borrow::Cow;
-use node_testing::bench::{BenchDb, Profile, BlockType, KeyTypes};
+use node_testing::bench::{BenchDb, Profile, BlockType, KeyTypes, DatabaseType};
use node_primitives::Block;
use sc_client_api::backend::Backend;
use sp_runtime::generic::BlockId;
+use sp_state_machine::InspectState;
-use crate::core::{self, Path};
-
-#[derive(Clone, Copy, Debug)]
-pub enum SizeType { Small, Medium, Large }
-
-impl SizeType {
- fn transactions(&self) -> usize {
- match self {
- SizeType::Small => 10,
- SizeType::Medium => 100,
- SizeType::Large => 500,
- }
- }
-}
+use crate::{
+ common::SizeType,
+ core::{self, Path, Mode},
+};
pub struct ImportBenchmarkDescription {
pub profile: Profile,
pub key_types: KeyTypes,
+ pub block_type: BlockType,
pub size: SizeType,
+ pub database_type: DatabaseType,
}
pub struct ImportBenchmark {
profile: Profile,
database: BenchDb,
block: Block,
+ block_type: BlockType,
}
impl core::BenchmarkDescription for ImportBenchmarkDescription {
@@ -77,46 +73,104 @@ impl core::BenchmarkDescription for ImportBenchmarkDescription {
KeyTypes::Ed25519 => path.push("ed25519"),
}
- match self.size {
- SizeType::Small => path.push("small"),
- SizeType::Medium => path.push("medium"),
- SizeType::Large => path.push("large"),
+ match self.block_type {
+ BlockType::RandomTransfersKeepAlive => path.push("transfer_keep_alive"),
+ BlockType::RandomTransfersReaping => path.push("transfer_reaping"),
+ BlockType::Noop => path.push("noop"),
+ }
+
+ match self.database_type {
+ DatabaseType::RocksDb => path.push("rocksdb"),
+ DatabaseType::ParityDb => path.push("paritydb"),
}
+ path.push(&format!("{}", self.size));
+
path
}
fn setup(self: Box) -> Box {
let profile = self.profile;
- let mut bench_db = BenchDb::with_key_types(self.size.transactions(), self.key_types);
- let block = bench_db.generate_block(BlockType::RandomTransfers(self.size.transactions()));
+ let mut bench_db = BenchDb::with_key_types(
+ self.database_type,
+ 50_000,
+ self.key_types
+ );
+ let block = bench_db.generate_block(self.block_type.to_content(self.size.transactions()));
Box::new(ImportBenchmark {
database: bench_db,
+ block_type: self.block_type,
block,
profile,
})
}
fn name(&self) -> Cow<'static, str> {
- match self.profile {
- Profile::Wasm => "Import benchmark (random transfers, wasm)".into(),
- Profile::Native => "Import benchmark (random transfers, native)".into(),
- }
+ format!(
+ "Block import ({:?}/{}, {:?}, {:?} backend)",
+ self.block_type,
+ self.size,
+ self.profile,
+ self.database_type,
+ ).into()
}
}
impl core::Benchmark for ImportBenchmark {
- fn run(&mut self) -> std::time::Duration {
+ fn run(&mut self, mode: Mode) -> std::time::Duration {
let mut context = self.database.create_context(self.profile);
let _ = context.client.runtime_version_at(&BlockId::Number(0))
.expect("Failed to get runtime version")
.spec_version;
+ if mode == Mode::Profile {
+ std::thread::park_timeout(std::time::Duration::from_secs(3));
+ }
+
let start = std::time::Instant::now();
context.import_block(self.block.clone());
let elapsed = start.elapsed();
+ // Sanity checks.
+ context.client.state_at(&BlockId::number(1)).expect("state_at failed for block#1")
+ .inspect_with(|| {
+ match self.block_type {
+ BlockType::RandomTransfersKeepAlive => {
+ // should be 5 per signed extrinsic + 1 per unsigned
+ // we have 1 unsigned and the rest are signed in the block
+ // those 5 events per signed are:
+ // - new account (RawEvent::NewAccount) as we always transfer fund to non-existant account
+ // - endowed (RawEvent::Endowed) for this new account
+ // - successful transfer (RawEvent::Transfer) for this transfer operation
+ // - deposit event for charging transaction fee
+ // - extrinsic success
+ assert_eq!(
+ node_runtime::System::events().len(),
+ (self.block.extrinsics.len() - 1) * 5 + 1,
+ );
+ },
+ BlockType::Noop => {
+ assert_eq!(
+ node_runtime::System::events().len(),
+
+ // should be 2 per signed extrinsic + 1 per unsigned
+ // we have 1 unsigned and the rest are signed in the block
+ // those 2 events per signed are:
+ // - deposit event for charging transaction fee
+ // - extrinsic success
+ (self.block.extrinsics.len() - 1) * 2 + 1,
+ );
+ },
+ _ => {},
+ }
+ }
+ );
+
+ if mode == Mode::Profile {
+ std::thread::park_timeout(std::time::Duration::from_secs(1));
+ }
+
log::info!(
target: "bench-logistics",
"imported block with {} tx, took: {:#?}",
@@ -133,4 +187,4 @@ impl core::Benchmark for ImportBenchmark {
elapsed
}
-}
\ No newline at end of file
+}
diff --git a/bin/node/bench/src/main.rs b/bin/node/bench/src/main.rs
index 8f045465262856fcb907f9aa5dfee68f7f05fc88..46b659dd88387e94c2d493e3d5975df3e7c28fab 100644
--- a/bin/node/bench/src/main.rs
+++ b/bin/node/bench/src/main.rs
@@ -1,27 +1,46 @@
-// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
-// Substrate is free software: you can redistribute it and/or modify
+// Copyright (C) 2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
-// Substrate is distributed in the hope that it will be useful,
+// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
-// along with Substrate. If not, see .
+// along with this program. If not, see .
+mod common;
+mod construct;
#[macro_use] mod core;
mod import;
+mod generator;
+mod simple_trie;
+mod state_sizes;
+mod tempdb;
+mod trie;
+mod txpool;
-use crate::core::run_benchmark;
-use import::{ImportBenchmarkDescription, SizeType};
-use node_testing::bench::{Profile, KeyTypes};
use structopt::StructOpt;
+use node_testing::bench::{Profile, KeyTypes, BlockType, DatabaseType as BenchDataBaseType};
+
+use crate::{
+ common::SizeType,
+ core::{run_benchmark, Mode as BenchmarkMode},
+ tempdb::DatabaseType,
+ import::ImportBenchmarkDescription,
+ trie::{TrieReadBenchmarkDescription, TrieWriteBenchmarkDescription, DatabaseSize},
+ construct::ConstructionBenchmarkDescription,
+ txpool::PoolBenchmarkDescription,
+};
+
#[derive(Debug, StructOpt)]
#[structopt(name = "node-bench", about = "Node integration benchmarks")]
struct Opt {
@@ -41,38 +60,108 @@ struct Opt {
///
/// Run with `--list` for the hint of what to filter.
filter: Option,
+
+ /// Number of transactions for block import with `custom` size.
+ #[structopt(long)]
+ transactions: Option,
+
+ /// Mode
+ ///
+ /// "regular" for regular benchmark
+ ///
+ /// "profile" mode adds pauses between measurable runs,
+ /// so that actual interval can be selected in the profiler of choice.
+ #[structopt(short, long, default_value = "regular")]
+ mode: BenchmarkMode,
}
fn main() {
let opt = Opt::from_args();
if !opt.json {
- sc_cli::init_logger("");
+ sp_tracing::try_init_simple();
+ }
+
+ let mut import_benchmarks = Vec::new();
+
+ for profile in [Profile::Wasm, Profile::Native].iter() {
+ for size in [
+ SizeType::Empty,
+ SizeType::Small,
+ SizeType::Medium,
+ SizeType::Large,
+ SizeType::Full,
+ SizeType::Custom(opt.transactions.unwrap_or(0)),
+ ].iter() {
+ for block_type in [
+ BlockType::RandomTransfersKeepAlive,
+ BlockType::RandomTransfersReaping,
+ BlockType::Noop,
+ ].iter() {
+ for database_type in [BenchDataBaseType::RocksDb, BenchDataBaseType::ParityDb].iter() {
+ import_benchmarks.push((profile, size.clone(), block_type.clone(), database_type));
+ }
+ }
+ }
}
let benchmarks = matrix!(
- profile in [Profile::Wasm, Profile::Native] =>
+ (profile, size, block_type, database_type) in import_benchmarks.into_iter() =>
ImportBenchmarkDescription {
profile: *profile,
key_types: KeyTypes::Sr25519,
- size: SizeType::Medium,
+ size: size,
+ block_type: block_type,
+ database_type: *database_type,
},
- ImportBenchmarkDescription {
- profile: Profile::Native,
- key_types: KeyTypes::Ed25519,
+ (size, db_type) in
+ [
+ DatabaseSize::Empty, DatabaseSize::Smallest, DatabaseSize::Small,
+ DatabaseSize::Medium, DatabaseSize::Large, DatabaseSize::Huge,
+ ]
+ .iter().flat_map(|size|
+ [
+ DatabaseType::RocksDb, DatabaseType::ParityDb
+ ]
+ .iter().map(move |db_type| (size, db_type)))
+ => TrieReadBenchmarkDescription { database_size: *size, database_type: *db_type },
+ (size, db_type) in
+ [
+ DatabaseSize::Empty, DatabaseSize::Smallest, DatabaseSize::Small,
+ DatabaseSize::Medium, DatabaseSize::Large, DatabaseSize::Huge,
+ ]
+ .iter().flat_map(|size|
+ [
+ DatabaseType::RocksDb, DatabaseType::ParityDb
+ ]
+ .iter().map(move |db_type| (size, db_type)))
+ => TrieWriteBenchmarkDescription { database_size: *size, database_type: *db_type },
+ ConstructionBenchmarkDescription {
+ profile: Profile::Wasm,
+ key_types: KeyTypes::Sr25519,
+ block_type: BlockType::RandomTransfersKeepAlive,
size: SizeType::Medium,
+ database_type: BenchDataBaseType::RocksDb,
},
- size in [SizeType::Small, SizeType::Large] =>
- ImportBenchmarkDescription {
- profile: Profile::Native,
- key_types: KeyTypes::Sr25519,
- size: *size,
- },
+ ConstructionBenchmarkDescription {
+ profile: Profile::Wasm,
+ key_types: KeyTypes::Sr25519,
+ block_type: BlockType::RandomTransfersKeepAlive,
+ size: SizeType::Large,
+ database_type: BenchDataBaseType::RocksDb,
+ },
+ PoolBenchmarkDescription { database_type: BenchDataBaseType::RocksDb },
);
if opt.list {
+ println!("Available benchmarks:");
+ if let Some(filter) = opt.filter.as_ref() {
+ println!("\t(filtered by \"{}\")", filter);
+ }
for benchmark in benchmarks.iter() {
- log::info!("{}: {}", benchmark.name(), benchmark.path().full())
+ if opt.filter.as_ref().map(|f| benchmark.path().has(f)).unwrap_or(true) {
+ println!("{}: {}", benchmark.name(), benchmark.path().full())
+ }
}
return;
}
@@ -81,15 +170,20 @@ fn main() {
for benchmark in benchmarks {
if opt.filter.as_ref().map(|f| benchmark.path().has(f)).unwrap_or(true) {
log::info!("Starting {}", benchmark.name());
- let result = run_benchmark(benchmark);
+ let result = run_benchmark(benchmark, opt.mode);
log::info!("{}", result);
results.push(result);
}
}
+ if results.is_empty() {
+ eprintln!("No benchmark was found for query");
+ std::process::exit(1);
+ }
+
if opt.json {
let json_result: String = serde_json::to_string(&results).expect("Failed to construct json");
println!("{}", json_result);
}
-}
\ No newline at end of file
+}
diff --git a/bin/node/bench/src/simple_trie.rs b/bin/node/bench/src/simple_trie.rs
new file mode 100644
index 0000000000000000000000000000000000000000..3cfd7ddb300a9101b22d55a2d460526a283fa0e2
--- /dev/null
+++ b/bin/node/bench/src/simple_trie.rs
@@ -0,0 +1,70 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use std::{collections::HashMap, sync::Arc};
+
+use kvdb::KeyValueDB;
+use node_primitives::Hash;
+use sp_trie::DBValue;
+use hash_db::{HashDB, AsHashDB, Prefix, Hasher as _};
+
+pub type Hasher = sp_core::Blake2Hasher;
+
+/// Immutable generated trie database with root.
+pub struct SimpleTrie<'a> {
+ pub db: Arc,
+ pub overlay: &'a mut HashMap, Option>>,
+}
+
+impl<'a> AsHashDB for SimpleTrie<'a> {
+ fn as_hash_db(&self) -> &dyn hash_db::HashDB { &*self }
+
+ fn as_hash_db_mut<'b>(&'b mut self) -> &'b mut (dyn HashDB + 'b) {
+ &mut *self
+ }
+}
+
+impl<'a> HashDB for SimpleTrie<'a> {
+ fn get(&self, key: &Hash, prefix: Prefix) -> Option {
+ let key = sp_trie::prefixed_key::(key, prefix);
+ if let Some(value) = self.overlay.get(&key) {
+ return value.clone();
+ }
+ self.db.get(0, &key).expect("Database backend error")
+ }
+
+ fn contains(&self, hash: &Hash, prefix: Prefix) -> bool {
+ self.get(hash, prefix).is_some()
+ }
+
+ fn insert(&mut self, prefix: Prefix, value: &[u8]) -> Hash {
+ let key = Hasher::hash(value);
+ self.emplace(key, prefix, value.to_vec());
+ key
+ }
+
+ fn emplace(&mut self, key: Hash, prefix: Prefix, value: DBValue) {
+ let key = sp_trie::prefixed_key::(&key, prefix);
+ self.overlay.insert(key, Some(value));
+ }
+
+ fn remove(&mut self, key: &Hash, prefix: Prefix) {
+ let key = sp_trie::prefixed_key::(key, prefix);
+ self.overlay.insert(key, None);
+ }
+}
diff --git a/bin/node/bench/src/state_sizes.rs b/bin/node/bench/src/state_sizes.rs
new file mode 100644
index 0000000000000000000000000000000000000000..d35989f61be3467960c0870fca1bd5969d571081
--- /dev/null
+++ b/bin/node/bench/src/state_sizes.rs
@@ -0,0 +1,4756 @@
+// Copyright 2015-2020 Parity Technologies (UK) Ltd.
+// This file is part of Parity.
+
+// Parity is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Parity is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Parity. If not, see .
+
+/// Kusama value size distribution
+pub const KUSAMA_STATE_DISTRIBUTION: &'static[(u32, u32)] = &[
+ (32, 35),
+ (33, 20035),
+ (34, 5369),
+ (35, 184),
+ (36, 54599),
+ (37, 1515056),
+ (38, 885),
+ (39, 69965),
+ (41, 210754),
+ (42, 467),
+ (43, 3241),
+ (44, 32660),
+ (45, 231141),
+ (46, 220016),
+ (47, 248931),
+ (48, 157232),
+ (49, 143236),
+ (50, 2428),
+ (51, 1476159),
+ (52, 31),
+ (53, 112),
+ (54, 711),
+ (55, 1934),
+ (56, 39),
+ (57, 407),
+ (58, 6929),
+ (59, 6568),
+ (60, 26),
+ (61, 268673),
+ (62, 118137),
+ (63, 84640),
+ (64, 193232),
+ (65, 2584210),
+ (66, 1002),
+ (67, 2993),
+ (68, 4266),
+ (69, 5633381),
+ (70, 277369),
+ (71, 5106),
+ (72, 722),
+ (73, 1882),
+ (74, 8178),
+ (75, 4045),
+ (76, 1596),
+ (77, 5335),
+ (78, 14591),
+ (79, 9645),
+ (80, 44171),
+ (81, 13474),
+ (82, 51090),
+ (83, 2595),
+ (84, 6276),
+ (85, 382195),
+ (86, 1062),
+ (87, 3846),
+ (88, 5663),
+ (89, 3811),
+ (90, 1580),
+ (91, 5729),
+ (92, 19144),
+ (93, 197),
+ (94, 235),
+ (95, 545),
+ (96, 54914),
+ (97, 3858),
+ (98, 1610),
+ (99, 635),
+ (100, 2481),
+ (101, 6457),
+ (102, 3753951),
+ (103, 11821),
+ (104, 11114),
+ (105, 2601),
+ (106, 2518),
+ (107, 521925),
+ (108, 297),
+ (109, 411),
+ (110, 668),
+ (111, 4500),
+ (112, 704),
+ (113, 316),
+ (114, 59),
+ (115, 291),
+ (116, 1727),
+ (117, 6010),
+ (118, 51874),
+ (119, 13969),
+ (120, 9496),
+ (121, 274),
+ (122, 810),
+ (123, 643),
+ (124, 69),
+ (125, 41),
+ (126, 329),
+ (127, 175435),
+ (128, 2641),
+ (129, 2658),
+ (130, 415277),
+ (131, 2705),
+ (132, 2314),
+ (133, 4290),
+ (134, 693),
+ (135, 1957478),
+ (136, 1111),
+ (137, 1474503),
+ (138, 3656),
+ (139, 940),
+ (140, 1755692),
+ (141, 61),
+ (142, 4140),
+ (143, 47),
+ (144, 6725),
+ (145, 610),
+ (146, 250),
+ (147, 48),
+ (148, 28),
+ (149, 132),
+ (150, 123489),
+ (151, 7476),
+ (152, 55),
+ (153, 68),
+ (154, 170),
+ (155, 566),
+ (156, 8110),
+ (157, 1243),
+ (158, 1445),
+ (159, 2569),
+ (160, 1096),
+ (161, 865),
+ (162, 634),
+ (163, 372411),
+ (164, 685),
+ (165, 3481),
+ (166, 1467),
+ (167, 2146),
+ (168, 556539),
+ (169, 566),
+ (170, 5080),
+ (171, 202),
+ (172, 123),
+ (173, 100750),
+ (174, 667),
+ (175, 433),
+ (176, 737),
+ (177, 315),
+ (178, 317),
+ (179, 656),
+ (180, 2522),
+ (181, 315),
+ (182, 406),
+ (183, 4680),
+ (184, 4941),
+ (185, 828),
+ (186, 782),
+ (187, 565),
+ (188, 584),
+ (189, 376),
+ (190, 321),
+ (191, 418),
+ (192, 167),
+ (193, 362),
+ (194, 2198),
+ (195, 180),
+ (196, 787),
+ (197, 2680),
+ (198, 501),
+ (199, 843),
+ (200, 287),
+ (201, 608362),
+ (202, 1157),
+ (203, 959),
+ (204, 1683623),
+ (205, 440),
+ (206, 756),
+ (207, 812),
+ (208, 1147),
+ (209, 723),
+ (210, 856),
+ (211, 496),
+ (212, 916),
+ (213, 615),
+ (214, 488),
+ (215, 522),
+ (216, 8265),
+ (217, 32574),
+ (218, 417),
+ (219, 247),
+ (220, 579),
+ (221, 68),
+ (222, 126),
+ (223, 306),
+ (224, 310),
+ (225, 24),
+ (226, 37),
+ (227, 160),
+ (228, 11),
+ (229, 3288),
+ (230, 349),
+ (231, 23),
+ (232, 14),
+ (233, 45),
+ (234, 452840),
+ (235, 118),
+ (236, 741),
+ (237, 390),
+ (238, 517),
+ (239, 694),
+ (240, 765),
+ (241, 542),
+ (242, 417),
+ (243, 617),
+ (244, 1307),
+ (245, 583),
+ (246, 1640),
+ (247, 735),
+ (248, 478),
+ (249, 4312),
+ (250, 5426),
+ (251, 1067),
+ (252, 435),
+ (253, 202),
+ (254, 122),
+ (255, 486),
+ (256, 180),
+ (257, 279),
+ (258, 406),
+ (259, 160),
+ (260, 2759),
+ (261, 2600),
+ (262, 686),
+ (263, 95),
+ (264, 164),
+ (265, 150),
+ (266, 1013),
+ (267, 552618),
+ (268, 217),
+ (269, 188),
+ (270, 284),
+ (271, 416),
+ (272, 453),
+ (273, 95),
+ (274, 42),
+ (275, 68),
+ (276, 90),
+ (277, 123),
+ (278, 340),
+ (279, 98),
+ (280, 2795),
+ (281, 261),
+ (282, 7370),
+ (283, 5768),
+ (284, 3285),
+ (285, 461),
+ (286, 363),
+ (287, 456),
+ (288, 1475),
+ (289, 211),
+ (290, 153),
+ (291, 282),
+ (292, 241),
+ (293, 2924),
+ (294, 261),
+ (295, 1070),
+ (296, 1301),
+ (297, 688),
+ (298, 592),
+ (299, 95),
+ (300, 686447),
+ (301, 42),
+ (302, 385),
+ (303, 24),
+ (304, 931),
+ (305, 49),
+ (306, 23),
+ (307, 67),
+ (308, 32),
+ (309, 38),
+ (310, 2),
+ (311, 7),
+ (312, 198),
+ (313, 11),
+ (314, 38),
+ (315, 3704),
+ (316, 7406),
+ (317, 116),
+ (318, 229),
+ (319, 100),
+ (320, 437),
+ (321, 244),
+ (322, 285),
+ (323, 433),
+ (324, 382),
+ (325, 3171),
+ (326, 761),
+ (327, 324),
+ (328, 2264),
+ (329, 340),
+ (330, 353),
+ (331, 110),
+ (332, 403),
+ (333, 731366),
+ (334, 223),
+ (335, 350),
+ (336, 600),
+ (337, 219),
+ (338, 112),
+ (339, 10),
+ (340, 761),
+ (341, 35),
+ (342, 99),
+ (343, 83),
+ (344, 136),
+ (345, 7),
+ (346, 836),
+ (347, 11),
+ (348, 10832),
+ (349, 8931),
+ (350, 33),
+ (351, 64),
+ (352, 66),
+ (353, 54),
+ (354, 78),
+ (355, 198),
+ (356, 722),
+ (357, 2647),
+ (358, 64),
+ (359, 71),
+ (360, 2242),
+ (361, 1462),
+ (362, 505),
+ (363, 444),
+ (364, 597),
+ (365, 372),
+ (366, 664852),
+ (367, 464),
+ (368, 605),
+ (369, 123),
+ (370, 64),
+ (371, 117),
+ (372, 328),
+ (373, 123),
+ (374, 227),
+ (375, 151),
+ (376, 881),
+ (377, 111),
+ (378, 30),
+ (379, 73),
+ (380, 2126),
+ (381, 3662),
+ (382, 9107),
+ (383, 18),
+ (384, 294),
+ (385, 12),
+ (386, 262),
+ (387, 127),
+ (388, 269),
+ (389, 2566),
+ (390, 14),
+ (391, 17),
+ (392, 80),
+ (393, 67),
+ (394, 1470),
+ (395, 25),
+ (396, 220),
+ (397, 131),
+ (398, 225),
+ (399, 484755),
+ (400, 597),
+ (401, 300),
+ (402, 253),
+ (403, 359),
+ (404, 523),
+ (405, 311),
+ (406, 238),
+ (407, 999),
+ (408, 424),
+ (409, 165),
+ (410, 96),
+ (411, 248),
+ (412, 1771),
+ (413, 139),
+ (414, 7374),
+ (415, 11186),
+ (416, 1355),
+ (417, 1283666),
+ (418, 9),
+ (419, 116),
+ (420, 3897),
+ (421, 2554),
+ (422, 1),
+ (423, 1),
+ (424, 16878),
+ (425, 3198212),
+ (426, 335),
+ (427, 1676),
+ (428, 80),
+ (429, 19),
+ (430, 47),
+ (431, 495),
+ (432, 421946),
+ (433, 73),
+ (434, 95),
+ (435, 105),
+ (436, 184),
+ (437, 56903),
+ (438, 132),
+ (439, 87),
+ (440, 207411),
+ (441, 230),
+ (442, 372),
+ (443, 361),
+ (444, 387),
+ (445, 299),
+ (446, 175),
+ (447, 7487),
+ (448, 16346),
+ (449, 37),
+ (450, 98313),
+ (451, 307),
+ (452, 304),
+ (453, 2675),
+ (454, 229),
+ (455, 130),
+ (456, 134),
+ (457, 50),
+ (458, 238),
+ (459, 2),
+ (460, 2267),
+ (461, 7),
+ (462, 1),
+ (463, 8),
+ (464, 395),
+ (465, 1279781),
+ (466, 9),
+ (467, 12),
+ (468, 633),
+ (469, 37),
+ (470, 13),
+ (471, 54),
+ (472, 247),
+ (473, 82),
+ (474, 119),
+ (475, 114),
+ (476, 332),
+ (477, 79),
+ (478, 116),
+ (479, 128),
+ (480, 4206),
+ (481, 20732),
+ (482, 311),
+ (483, 343),
+ (484, 527),
+ (485, 2750),
+ (486, 76),
+ (487, 152),
+ (488, 510),
+ (489, 63),
+ (490, 257),
+ (491, 79),
+ (492, 825),
+ (493, 4198),
+ (494, 389),
+ (495, 72),
+ (496, 1547),
+ (497, 34),
+ (498, 631996),
+ (499, 5),
+ (500, 2334),
+ (501, 34),
+ (502, 7),
+ (503, 7),
+ (504, 7682),
+ (505, 6),
+ (506, 26),
+ (507, 22),
+ (508, 461),
+ (509, 95),
+ (510, 36),
+ (511, 46),
+ (512, 2741),
+ (513, 38455),
+ (514, 29678),
+ (515, 179),
+ (516, 1637),
+ (517, 2597),
+ (518, 166),
+ (519, 230),
+ (520, 2736),
+ (521, 187),
+ (522, 361),
+ (523, 310),
+ (524, 3327),
+ (525, 76),
+ (526, 8070),
+ (527, 35),
+ (528, 3310),
+ (529, 118),
+ (530, 167),
+ (531, 214180),
+ (532, 4597),
+ (533, 153),
+ (534, 126),
+ (535, 23),
+ (536, 13920),
+ (537, 10),
+ (538, 11),
+ (539, 50),
+ (540, 50739),
+ (541, 8),
+ (542, 347),
+ (543, 77),
+ (544, 451575),
+ (545, 16),
+ (546, 218814),
+ (547, 1859026),
+ (548, 303),
+ (549, 2511),
+ (550, 27),
+ (551, 28),
+ (552, 188),
+ (553, 46),
+ (554, 216),
+ (555, 63),
+ (556, 202),
+ (557, 192),
+ (558, 257),
+ (559, 170377),
+ (560, 902),
+ (561, 424),
+ (562, 186),
+ (563, 145),
+ (564, 342),
+ (565, 76),
+ (566, 41),
+ (567, 26),
+ (568, 136),
+ (569, 1336),
+ (570, 988),
+ (571, 131),
+ (572, 766),
+ (573, 95),
+ (574, 57),
+ (575, 16),
+ (576, 47),
+ (577, 63),
+ (578, 5),
+ (579, 140),
+ (580, 1263808),
+ (581, 2498),
+ (583, 2),
+ (584, 706),
+ (585, 49),
+ (586, 502),
+ (587, 16),
+ (588, 115),
+ (589, 25),
+ (590, 31),
+ (591, 34),
+ (592, 818),
+ (593, 60),
+ (594, 84),
+ (595, 116),
+ (596, 446),
+ (597, 111),
+ (598, 151),
+ (599, 153),
+ (600, 1408),
+ (601, 165),
+ (602, 575),
+ (603, 163),
+ (604, 309),
+ (605, 52),
+ (606, 40),
+ (607, 116),
+ (608, 749),
+ (609, 231),
+ (610, 171),
+ (611, 218),
+ (612, 1145),
+ (613, 2572),
+ (614, 27),
+ (615, 26),
+ (616, 2060),
+ (617, 173),
+ (618, 1094),
+ (619, 66),
+ (620, 14235),
+ (622, 294),
+ (623, 2),
+ (624, 79374),
+ (625, 1),
+ (626, 3),
+ (627, 7),
+ (628, 335),
+ (629, 27),
+ (630, 47),
+ (631, 113),
+ (632, 589),
+ (633, 56),
+ (634, 75),
+ (635, 85),
+ (636, 740),
+ (637, 118),
+ (638, 180),
+ (639, 149),
+ (640, 1169),
+ (641, 135),
+ (642, 169),
+ (643, 170),
+ (644, 1802),
+ (645, 2481),
+ (646, 28),
+ (647, 78),
+ (648, 5585),
+ (649, 173),
+ (650, 135),
+ (651, 177),
+ (652, 6553),
+ (653, 129),
+ (654, 55),
+ (655, 6),
+ (656, 13250),
+ (657, 5),
+ (658, 15),
+ (659, 3),
+ (660, 39892),
+ (661, 28),
+ (663, 1),
+ (664, 575061),
+ (665, 1),
+ (666, 5),
+ (667, 73),
+ (668, 39),
+ (669, 62),
+ (670, 50),
+ (671, 27),
+ (672, 33),
+ (673, 48),
+ (674, 44),
+ (675, 151),
+ (676, 70),
+ (677, 2540),
+ (678, 150),
+ (679, 109),
+ (680, 117),
+ (681, 95),
+ (682, 80),
+ (683, 44),
+ (684, 34),
+ (685, 31),
+ (686, 125),
+ (687, 146),
+ (688, 423),
+ (689, 142),
+ (690, 154),
+ (691, 135),
+ (692, 194),
+ (693, 48),
+ (694, 6),
+ (695, 141),
+ (696, 47),
+ (697, 9),
+ (699, 1),
+ (701, 1),
+ (702, 2),
+ (703, 81),
+ (704, 3),
+ (705, 4),
+ (706, 23),
+ (707, 131),
+ (708, 31),
+ (709, 2458),
+ (710, 346),
+ (711, 43),
+ (712, 46),
+ (713, 48),
+ (714, 85),
+ (715, 119),
+ (716, 89),
+ (717, 97),
+ (718, 95),
+ (719, 137),
+ (720, 437),
+ (721, 64),
+ (722, 28),
+ (723, 29),
+ (724, 121),
+ (725, 162),
+ (726, 241),
+ (727, 219),
+ (728, 143),
+ (729, 92),
+ (730, 100),
+ (731, 42),
+ (732, 38),
+ (733, 60),
+ (734, 2),
+ (735, 71),
+ (736, 12),
+ (737, 9),
+ (738, 7),
+ (739, 193),
+ (740, 2),
+ (741, 2404),
+ (742, 3),
+ (743, 11),
+ (744, 5),
+ (745, 5),
+ (746, 9),
+ (747, 16),
+ (748, 27),
+ (749, 32),
+ (750, 57),
+ (751, 54),
+ (752, 383),
+ (753, 61),
+ (754, 48),
+ (755, 84),
+ (756, 108),
+ (757, 134),
+ (758, 121),
+ (759, 160),
+ (760, 80),
+ (761, 68),
+ (762, 192),
+ (763, 107),
+ (764, 270),
+ (765, 58),
+ (766, 125),
+ (767, 151),
+ (768, 75),
+ (769, 94),
+ (770, 91),
+ (771, 187),
+ (772, 57),
+ (773, 2371),
+ (774, 8),
+ (775, 93),
+ (776, 107),
+ (777, 20),
+ (779, 1),
+ (780, 22),
+ (781, 1),
+ (783, 6),
+ (784, 318),
+ (785, 25),
+ (786, 31),
+ (787, 23),
+ (788, 28),
+ (789, 62),
+ (790, 53),
+ (791, 41),
+ (792, 68),
+ (793, 60),
+ (794, 88),
+ (795, 108),
+ (796, 63),
+ (797, 100),
+ (798, 68),
+ (799, 72),
+ (800, 83),
+ (801, 46),
+ (802, 36),
+ (803, 157),
+ (804, 139),
+ (805, 2439),
+ (806, 73),
+ (807, 81),
+ (808, 99),
+ (809, 66),
+ (810, 45),
+ (811, 98),
+ (812, 1),
+ (814, 31),
+ (815, 1),
+ (816, 312),
+ (818, 155),
+ (819, 2),
+ (820, 12),
+ (821, 27),
+ (822, 97),
+ (823, 23),
+ (824, 7),
+ (825, 15),
+ (826, 37),
+ (827, 39),
+ (828, 28),
+ (829, 33),
+ (830, 53),
+ (831, 101),
+ (832, 189),
+ (833, 94),
+ (834, 66),
+ (835, 173),
+ (836, 74),
+ (837, 2402),
+ (838, 64),
+ (839, 28),
+ (840, 20),
+ (841, 13),
+ (842, 32),
+ (843, 72),
+ (844, 68),
+ (845, 50),
+ (846, 41),
+ (847, 114),
+ (848, 345),
+ (849, 33),
+ (850, 17),
+ (851, 6),
+ (852, 61),
+ (853, 101),
+ (854, 123),
+ (855, 28),
+ (856, 3),
+ (857, 3),
+ (858, 30),
+ (859, 12),
+ (860, 28),
+ (861, 16),
+ (862, 20),
+ (863, 7),
+ (864, 23),
+ (865, 28),
+ (866, 40),
+ (867, 159),
+ (868, 40),
+ (869, 2361),
+ (870, 92),
+ (871, 88),
+ (872, 193),
+ (873, 61),
+ (874, 58),
+ (875, 67),
+ (876, 65),
+ (877, 46),
+ (878, 55),
+ (879, 30),
+ (880, 334),
+ (881, 74),
+ (882, 121),
+ (883, 107),
+ (884, 36),
+ (885, 66),
+ (886, 22),
+ (887, 25),
+ (888, 24),
+ (889, 10),
+ (890, 44),
+ (891, 5),
+ (892, 84),
+ (893, 4),
+ (894, 1),
+ (895, 7),
+ (896, 3),
+ (897, 8),
+ (898, 3),
+ (899, 126),
+ (900, 13),
+ (901, 2280),
+ (902, 74),
+ (903, 36),
+ (904, 46),
+ (905, 52),
+ (906, 24),
+ (907, 23),
+ (908, 43),
+ (909, 31),
+ (910, 66),
+ (911, 65),
+ (912, 376),
+ (913, 77),
+ (914, 85),
+ (915, 60),
+ (916, 29),
+ (917, 64),
+ (918, 48),
+ (919, 135),
+ (920, 21),
+ (921, 34),
+ (922, 26),
+ (923, 22),
+ (924, 52),
+ (925, 28),
+ (926, 142),
+ (927, 18),
+ (928, 14),
+ (929, 30),
+ (930, 56),
+ (931, 113),
+ (933, 2264),
+ (934, 14),
+ (935, 4),
+ (936, 10),
+ (937, 18),
+ (938, 2),
+ (939, 30),
+ (940, 9),
+ (941, 29),
+ (942, 10),
+ (943, 17),
+ (944, 296),
+ (945, 31),
+ (946, 40),
+ (947, 26),
+ (948, 70),
+ (949, 66),
+ (950, 44),
+ (951, 57),
+ (952, 55),
+ (953, 56),
+ (954, 51),
+ (955, 133),
+ (956, 39),
+ (957, 49),
+ (958, 45),
+ (959, 26),
+ (960, 30),
+ (961, 35),
+ (962, 40),
+ (963, 148),
+ (964, 34),
+ (965, 2264),
+ (966, 50),
+ (967, 21),
+ (968, 2),
+ (970, 24),
+ (972, 45),
+ (973, 8),
+ (974, 11),
+ (975, 20),
+ (976, 287),
+ (977, 20),
+ (978, 6),
+ (979, 9),
+ (980, 99),
+ (981, 32),
+ (982, 10),
+ (983, 13),
+ (984, 26),
+ (985, 30),
+ (986, 31),
+ (987, 38),
+ (988, 25),
+ (989, 32),
+ (990, 44),
+ (991, 125),
+ (992, 58),
+ (993, 44),
+ (994, 25),
+ (995, 140),
+ (996, 25),
+ (997, 2222),
+ (998, 16),
+ (999, 25),
+ (1000, 38),
+ (1001, 66),
+ (1002, 31),
+ (1003, 38),
+ (1004, 38),
+ (1005, 10),
+ (1006, 7),
+ (1008, 283),
+ (1009, 3),
+ (1010, 1),
+ (1011, 17),
+ (1012, 4),
+ (1013, 51),
+ (1014, 1),
+ (1015, 1),
+ (1016, 3),
+ (1017, 12),
+ (1018, 11),
+ (1019, 21),
+ (1020, 31),
+ (1021, 14),
+ (1022, 14),
+ (1023, 23),
+ (1024, 25),
+ (1025, 42),
+ (1026, 39),
+ (1027, 220),
+ (1028, 33),
+ (1029, 2206),
+ (1030, 24),
+ (1031, 64),
+ (1032, 36),
+ (1033, 61),
+ (1034, 123),
+ (1035, 32),
+ (1036, 20),
+ (1037, 15),
+ (1038, 11),
+ (1039, 33),
+ (1040, 311),
+ (1041, 58),
+ (1042, 80),
+ (1043, 29),
+ (1044, 10),
+ (1045, 48),
+ (1046, 18),
+ (1047, 22),
+ (1048, 3),
+ (1049, 17),
+ (1050, 1),
+ (1051, 2),
+ (1052, 5),
+ (1053, 4),
+ (1054, 4),
+ (1055, 1),
+ (1056, 4),
+ (1057, 15),
+ (1058, 11),
+ (1059, 135),
+ (1060, 59),
+ (1061, 2132),
+ (1062, 32),
+ (1063, 116),
+ (1064, 37),
+ (1065, 44),
+ (1066, 42),
+ (1067, 28),
+ (1068, 10),
+ (1069, 36),
+ (1070, 59),
+ (1071, 48),
+ (1072, 332),
+ (1073, 59),
+ (1074, 43),
+ (1075, 19),
+ (1076, 19),
+ (1077, 31),
+ (1078, 31),
+ (1079, 20),
+ (1080, 38),
+ (1081, 58),
+ (1082, 37),
+ (1083, 47),
+ (1084, 19),
+ (1085, 24),
+ (1086, 12),
+ (1087, 26),
+ (1088, 89),
+ (1089, 3),
+ (1091, 108),
+ (1093, 2112),
+ (1094, 13),
+ (1095, 4),
+ (1096, 4),
+ (1097, 17),
+ (1098, 7),
+ (1099, 105),
+ (1100, 12),
+ (1101, 10),
+ (1102, 17),
+ (1103, 19),
+ (1104, 329),
+ (1105, 28),
+ (1106, 58),
+ (1107, 21),
+ (1108, 22),
+ (1109, 63),
+ (1110, 29),
+ (1111, 53),
+ (1112, 84),
+ (1113, 28),
+ (1114, 30),
+ (1115, 22),
+ (1116, 40),
+ (1117, 16),
+ (1118, 20),
+ (1119, 75),
+ (1120, 43),
+ (1121, 49),
+ (1122, 25),
+ (1123, 118),
+ (1124, 8),
+ (1125, 2083),
+ (1126, 21),
+ (1127, 3),
+ (1128, 43),
+ (1129, 1),
+ (1130, 1),
+ (1132, 3),
+ (1133, 1),
+ (1134, 3),
+ (1135, 83),
+ (1136, 266),
+ (1137, 7),
+ (1138, 22),
+ (1139, 14),
+ (1140, 30),
+ (1141, 54),
+ (1142, 125),
+ (1143, 44),
+ (1144, 34),
+ (1145, 19),
+ (1146, 21),
+ (1147, 19),
+ (1148, 46),
+ (1149, 45),
+ (1150, 54),
+ (1151, 22),
+ (1152, 30),
+ (1153, 20),
+ (1154, 7),
+ (1155, 143),
+ (1156, 23),
+ (1157, 2078),
+ (1158, 30),
+ (1159, 23),
+ (1160, 12),
+ (1161, 18),
+ (1162, 6),
+ (1164, 5),
+ (1165, 1),
+ (1168, 254),
+ (1169, 1),
+ (1170, 3),
+ (1171, 95),
+ (1172, 37),
+ (1173, 23),
+ (1174, 7),
+ (1175, 11),
+ (1176, 5),
+ (1177, 14),
+ (1178, 15),
+ (1179, 19),
+ (1180, 10),
+ (1181, 28),
+ (1182, 87),
+ (1183, 35),
+ (1184, 30),
+ (1185, 30),
+ (1186, 38),
+ (1187, 148),
+ (1188, 49),
+ (1189, 2056),
+ (1190, 42),
+ (1191, 41),
+ (1192, 14),
+ (1193, 36),
+ (1194, 37),
+ (1195, 22),
+ (1196, 108),
+ (1197, 62),
+ (1198, 55),
+ (1199, 43),
+ (1200, 261),
+ (1201, 16),
+ (1202, 1),
+ (1203, 9),
+ (1204, 3),
+ (1205, 32),
+ (1207, 81),
+ (1208, 3),
+ (1210, 3),
+ (1212, 4),
+ (1213, 9),
+ (1214, 5),
+ (1215, 6),
+ (1216, 4),
+ (1217, 8),
+ (1218, 13),
+ (1219, 120),
+ (1220, 11),
+ (1221, 1989),
+ (1222, 11),
+ (1223, 20),
+ (1224, 15),
+ (1225, 21),
+ (1226, 23),
+ (1227, 50),
+ (1228, 37),
+ (1229, 51),
+ (1230, 37),
+ (1231, 21),
+ (1232, 256),
+ (1233, 26),
+ (1234, 25),
+ (1235, 21),
+ (1236, 79),
+ (1237, 50),
+ (1238, 21),
+ (1239, 2),
+ (1240, 6),
+ (1241, 8),
+ (1243, 95),
+ (1244, 1),
+ (1247, 1),
+ (1248, 1),
+ (1249, 1),
+ (1250, 96),
+ (1251, 112),
+ (1252, 43),
+ (1253, 1960),
+ (1254, 7),
+ (1255, 13),
+ (1256, 16),
+ (1257, 20),
+ (1258, 19),
+ (1259, 17),
+ (1260, 12),
+ (1261, 5),
+ (1262, 12),
+ (1263, 29),
+ (1264, 272),
+ (1265, 63),
+ (1266, 37),
+ (1267, 36),
+ (1268, 25),
+ (1269, 55),
+ (1270, 38),
+ (1271, 7),
+ (1272, 37),
+ (1273, 10),
+ (1274, 16),
+ (1275, 28),
+ (1276, 18),
+ (1277, 11),
+ (1278, 8),
+ (1279, 91),
+ (1280, 1),
+ (1282, 1),
+ (1283, 110),
+ (1284, 20),
+ (1285, 1923),
+ (1287, 3),
+ (1288, 1),
+ (1290, 23),
+ (1291, 4),
+ (1292, 4),
+ (1293, 12),
+ (1294, 19),
+ (1295, 8),
+ (1296, 248),
+ (1297, 21),
+ (1298, 12),
+ (1299, 31),
+ (1300, 10),
+ (1301, 60),
+ (1302, 1),
+ (1303, 8),
+ (1304, 99),
+ (1305, 29),
+ (1306, 29),
+ (1307, 28),
+ (1308, 33),
+ (1309, 19),
+ (1310, 8),
+ (1311, 1),
+ (1313, 11),
+ (1314, 12),
+ (1315, 236),
+ (1316, 18),
+ (1317, 1891),
+ (1318, 2),
+ (1322, 21),
+ (1324, 1),
+ (1326, 8),
+ (1327, 3),
+ (1328, 235),
+ (1329, 4),
+ (1330, 1),
+ (1331, 2),
+ (1332, 5),
+ (1333, 38),
+ (1334, 2),
+ (1335, 30),
+ (1336, 18),
+ (1337, 31),
+ (1338, 8),
+ (1339, 5),
+ (1340, 11),
+ (1341, 9),
+ (1342, 12),
+ (1343, 11),
+ (1344, 79),
+ (1345, 37),
+ (1346, 19),
+ (1347, 136),
+ (1348, 9),
+ (1349, 1861),
+ (1350, 8),
+ (1351, 112),
+ (1352, 10),
+ (1353, 3),
+ (1354, 16),
+ (1355, 4),
+ (1356, 12),
+ (1357, 18),
+ (1358, 67),
+ (1359, 6),
+ (1360, 229),
+ (1361, 1),
+ (1362, 1),
+ (1364, 1),
+ (1365, 27),
+ (1366, 6),
+ (1368, 14),
+ (1370, 8),
+ (1371, 29),
+ (1372, 3),
+ (1373, 21),
+ (1374, 8),
+ (1375, 6),
+ (1376, 3),
+ (1377, 9),
+ (1378, 9),
+ (1379, 120),
+ (1380, 5),
+ (1381, 1833),
+ (1382, 45),
+ (1383, 35),
+ (1384, 23),
+ (1385, 25),
+ (1386, 26),
+ (1387, 159),
+ (1388, 24),
+ (1389, 16),
+ (1390, 16),
+ (1391, 14),
+ (1392, 273),
+ (1393, 17),
+ (1394, 9),
+ (1395, 5),
+ (1396, 14),
+ (1397, 24),
+ (1398, 27),
+ (1400, 2),
+ (1404, 5),
+ (1405, 8),
+ (1406, 3),
+ (1407, 25),
+ (1408, 2),
+ (1409, 22),
+ (1410, 10),
+ (1411, 111),
+ (1412, 89),
+ (1413, 1793),
+ (1414, 4),
+ (1415, 9),
+ (1416, 16),
+ (1417, 13),
+ (1418, 13),
+ (1419, 13),
+ (1420, 15),
+ (1421, 19),
+ (1422, 26),
+ (1423, 110),
+ (1424, 229),
+ (1425, 11),
+ (1426, 10),
+ (1427, 7),
+ (1428, 7),
+ (1429, 28),
+ (1430, 12),
+ (1431, 11),
+ (1432, 14),
+ (1433, 2),
+ (1434, 2),
+ (1436, 1),
+ (1437, 1),
+ (1438, 13),
+ (1439, 1),
+ (1440, 1),
+ (1441, 1),
+ (1442, 2),
+ (1443, 132),
+ (1444, 5),
+ (1445, 1795),
+ (1448, 11),
+ (1449, 10),
+ (1450, 11),
+ (1451, 8),
+ (1452, 47),
+ (1453, 6),
+ (1454, 8),
+ (1455, 12),
+ (1456, 229),
+ (1457, 15),
+ (1458, 12),
+ (1459, 121),
+ (1460, 15),
+ (1461, 48),
+ (1462, 49),
+ (1463, 22),
+ (1464, 11),
+ (1465, 9),
+ (1466, 81),
+ (1467, 1),
+ (1468, 1),
+ (1469, 6),
+ (1470, 6),
+ (1471, 6),
+ (1472, 9),
+ (1473, 12),
+ (1474, 2),
+ (1475, 109),
+ (1476, 5),
+ (1477, 1721),
+ (1478, 1),
+ (1479, 28),
+ (1480, 7),
+ (1481, 23),
+ (1482, 2),
+ (1483, 12),
+ (1484, 5),
+ (1485, 3),
+ (1486, 2),
+ (1487, 4),
+ (1488, 219),
+ (1489, 7),
+ (1490, 8),
+ (1491, 10),
+ (1492, 16),
+ (1493, 32),
+ (1494, 25),
+ (1495, 96),
+ (1496, 13),
+ (1497, 15),
+ (1498, 16),
+ (1499, 12),
+ (1500, 14),
+ (1501, 19),
+ (1502, 7),
+ (1503, 11),
+ (1504, 3),
+ (1505, 8),
+ (1506, 41),
+ (1507, 108),
+ (1508, 25),
+ (1509, 1719),
+ (1510, 8),
+ (1511, 10),
+ (1514, 2),
+ (1515, 25),
+ (1516, 2),
+ (1517, 32),
+ (1518, 6),
+ (1519, 7),
+ (1520, 273),
+ (1521, 2),
+ (1522, 6),
+ (1523, 5),
+ (1524, 6),
+ (1525, 36),
+ (1526, 3),
+ (1527, 12),
+ (1528, 7),
+ (1529, 9),
+ (1530, 12),
+ (1531, 107),
+ (1532, 44),
+ (1533, 17),
+ (1534, 12),
+ (1535, 18),
+ (1536, 12),
+ (1537, 26),
+ (1538, 35),
+ (1539, 131),
+ (1540, 15),
+ (1541, 1693),
+ (1542, 11),
+ (1543, 7),
+ (1544, 2),
+ (1545, 6),
+ (1546, 14),
+ (1547, 6),
+ (1548, 2),
+ (1549, 24),
+ (1550, 2),
+ (1551, 33),
+ (1552, 206),
+ (1553, 18),
+ (1555, 1),
+ (1556, 7),
+ (1557, 38),
+ (1558, 6),
+ (1559, 3),
+ (1560, 21),
+ (1562, 2),
+ (1563, 5),
+ (1564, 7),
+ (1565, 5),
+ (1566, 6),
+ (1567, 110),
+ (1568, 9),
+ (1569, 16),
+ (1570, 13),
+ (1571, 109),
+ (1572, 6),
+ (1573, 1664),
+ (1574, 53),
+ (1575, 14),
+ (1576, 21),
+ (1577, 31),
+ (1578, 42),
+ (1579, 13),
+ (1580, 10),
+ (1581, 12),
+ (1582, 11),
+ (1583, 85),
+ (1584, 202),
+ (1585, 7),
+ (1586, 6),
+ (1587, 25),
+ (1588, 5),
+ (1589, 41),
+ (1590, 4),
+ (1591, 5),
+ (1593, 1),
+ (1595, 5),
+ (1596, 11),
+ (1598, 1),
+ (1599, 1),
+ (1600, 1),
+ (1601, 4),
+ (1602, 19),
+ (1603, 200),
+ (1604, 10),
+ (1605, 1640),
+ (1606, 15),
+ (1607, 14),
+ (1608, 7),
+ (1609, 12),
+ (1610, 5),
+ (1611, 2),
+ (1612, 3),
+ (1613, 7),
+ (1614, 37),
+ (1615, 4),
+ (1616, 203),
+ (1617, 13),
+ (1618, 3),
+ (1619, 12),
+ (1620, 38),
+ (1621, 22),
+ (1622, 12),
+ (1623, 43),
+ (1624, 19),
+ (1625, 35),
+ (1626, 15),
+ (1627, 26),
+ (1628, 43),
+ (1629, 2),
+ (1630, 10),
+ (1631, 1),
+ (1633, 1),
+ (1634, 1),
+ (1635, 110),
+ (1637, 1612),
+ (1638, 1),
+ (1639, 107),
+ (1640, 1),
+ (1641, 2),
+ (1643, 7),
+ (1644, 9),
+ (1645, 8),
+ (1646, 3),
+ (1647, 19),
+ (1648, 206),
+ (1649, 2),
+ (1650, 9),
+ (1651, 8),
+ (1652, 19),
+ (1653, 22),
+ (1654, 4),
+ (1655, 13),
+ (1656, 3),
+ (1657, 5),
+ (1658, 5),
+ (1659, 35),
+ (1660, 10),
+ (1661, 26),
+ (1662, 8),
+ (1663, 10),
+ (1664, 7),
+ (1665, 4),
+ (1666, 2),
+ (1667, 110),
+ (1668, 12),
+ (1669, 1594),
+ (1670, 1),
+ (1671, 2),
+ (1672, 15),
+ (1673, 4),
+ (1674, 2),
+ (1675, 303),
+ (1676, 12),
+ (1678, 1),
+ (1680, 194),
+ (1681, 1),
+ (1682, 40),
+ (1683, 2),
+ (1684, 2),
+ (1685, 19),
+ (1686, 16),
+ (1687, 2),
+ (1688, 6),
+ (1689, 9),
+ (1690, 18),
+ (1691, 15),
+ (1692, 5),
+ (1693, 7),
+ (1694, 6),
+ (1695, 32),
+ (1696, 4),
+ (1697, 34),
+ (1698, 1),
+ (1699, 117),
+ (1700, 5),
+ (1701, 1590),
+ (1702, 20),
+ (1703, 4),
+ (1704, 6),
+ (1705, 20),
+ (1707, 2),
+ (1710, 3),
+ (1711, 89),
+ (1712, 195),
+ (1713, 4),
+ (1714, 2),
+ (1715, 1),
+ (1716, 3),
+ (1717, 16),
+ (1718, 9),
+ (1719, 2),
+ (1720, 3),
+ (1723, 18),
+ (1724, 1),
+ (1725, 2),
+ (1726, 3),
+ (1727, 3),
+ (1728, 9),
+ (1729, 5),
+ (1730, 7),
+ (1731, 132),
+ (1732, 28),
+ (1733, 1585),
+ (1734, 5),
+ (1735, 3),
+ (1736, 5),
+ (1737, 27),
+ (1738, 4),
+ (1739, 19),
+ (1740, 15),
+ (1741, 4),
+ (1742, 15),
+ (1743, 9),
+ (1744, 183),
+ (1745, 12),
+ (1747, 119),
+ (1748, 1),
+ (1749, 15),
+ (1750, 5),
+ (1754, 1),
+ (1757, 2),
+ (1758, 8),
+ (1759, 7),
+ (1760, 7),
+ (1761, 2),
+ (1762, 13),
+ (1763, 113),
+ (1764, 8),
+ (1765, 1547),
+ (1766, 7),
+ (1767, 21),
+ (1768, 3),
+ (1769, 34),
+ (1770, 5),
+ (1772, 6),
+ (1773, 7),
+ (1774, 12),
+ (1775, 9),
+ (1776, 189),
+ (1777, 25),
+ (1778, 10),
+ (1779, 4),
+ (1780, 1),
+ (1781, 21),
+ (1782, 3),
+ (1783, 186),
+ (1784, 2),
+ (1787, 1),
+ (1788, 10),
+ (1789, 8),
+ (1790, 1),
+ (1791, 34),
+ (1792, 1),
+ (1793, 1),
+ (1794, 1),
+ (1795, 108),
+ (1796, 4),
+ (1797, 1519),
+ (1798, 9),
+ (1799, 9),
+ (1800, 3),
+ (1801, 6),
+ (1802, 4),
+ (1803, 35),
+ (1804, 15),
+ (1805, 30),
+ (1806, 5),
+ (1807, 7),
+ (1808, 192),
+ (1809, 8),
+ (1811, 4),
+ (1812, 24),
+ (1813, 36),
+ (1814, 4),
+ (1815, 14),
+ (1816, 2),
+ (1817, 2),
+ (1818, 4),
+ (1819, 72),
+ (1820, 3),
+ (1822, 1),
+ (1823, 4),
+ (1825, 1),
+ (1826, 5),
+ (1827, 104),
+ (1828, 1),
+ (1829, 1494),
+ (1830, 11),
+ (1831, 5),
+ (1832, 2),
+ (1833, 2),
+ (1834, 2),
+ (1835, 4),
+ (1836, 9),
+ (1837, 1),
+ (1838, 14),
+ (1839, 33),
+ (1840, 188),
+ (1841, 27),
+ (1842, 13),
+ (1843, 10),
+ (1844, 28),
+ (1845, 52),
+ (1846, 17),
+ (1847, 40),
+ (1848, 35),
+ (1849, 6),
+ (1850, 6),
+ (1851, 2),
+ (1853, 4),
+ (1854, 6),
+ (1855, 77),
+ (1856, 1),
+ (1859, 106),
+ (1860, 2),
+ (1861, 1466),
+ (1863, 2),
+ (1866, 1),
+ (1869, 1),
+ (1870, 2),
+ (1872, 179),
+ (1873, 1),
+ (1874, 9),
+ (1875, 29),
+ (1876, 15),
+ (1877, 43),
+ (1878, 2),
+ (1880, 8),
+ (1881, 13),
+ (1882, 18),
+ (1883, 12),
+ (1884, 14),
+ (1885, 18),
+ (1886, 16),
+ (1887, 6),
+ (1888, 2),
+ (1889, 3),
+ (1890, 9),
+ (1891, 196),
+ (1892, 13),
+ (1893, 1456),
+ (1894, 14),
+ (1895, 8),
+ (1896, 2),
+ (1898, 1),
+ (1899, 17),
+ (1900, 5),
+ (1901, 1),
+ (1904, 175),
+ (1905, 1),
+ (1906, 2),
+ (1907, 3),
+ (1908, 6),
+ (1909, 10),
+ (1910, 3),
+ (1911, 22),
+ (1912, 6),
+ (1913, 22),
+ (1914, 6),
+ (1915, 10),
+ (1916, 5),
+ (1917, 2),
+ (1918, 6),
+ (1919, 4),
+ (1920, 7),
+ (1921, 14),
+ (1922, 4),
+ (1923, 107),
+ (1924, 10),
+ (1925, 1434),
+ (1926, 7),
+ (1927, 76),
+ (1928, 4),
+ (1929, 7),
+ (1930, 10),
+ (1931, 14),
+ (1932, 6),
+ (1933, 15),
+ (1934, 4),
+ (1935, 2),
+ (1936, 182),
+ (1937, 2),
+ (1939, 11),
+ (1940, 1),
+ (1941, 4),
+ (1942, 2),
+ (1943, 9),
+ (1944, 1),
+ (1947, 24),
+ (1949, 22),
+ (1952, 15),
+ (1953, 14),
+ (1954, 5),
+ (1955, 111),
+ (1956, 11),
+ (1957, 1435),
+ (1958, 5),
+ (1959, 5),
+ (1960, 10),
+ (1961, 6),
+ (1962, 11),
+ (1963, 95),
+ (1964, 11),
+ (1965, 7),
+ (1966, 7),
+ (1967, 2),
+ (1968, 182),
+ (1969, 6),
+ (1970, 15),
+ (1972, 7),
+ (1973, 11),
+ (1974, 6),
+ (1975, 2),
+ (1976, 6),
+ (1977, 3),
+ (1978, 2),
+ (1983, 24),
+ (1985, 26),
+ (1986, 3),
+ (1987, 109),
+ (1988, 3),
+ (1989, 1421),
+ (1990, 1),
+ (1991, 3),
+ (1992, 8),
+ (1993, 4),
+ (1994, 6),
+ (1995, 5),
+ (1996, 13),
+ (1997, 6),
+ (1998, 10),
+ (1999, 92),
+ (2000, 181),
+ (2001, 5),
+ (2002, 5),
+ (2003, 1),
+ (2004, 1),
+ (2005, 14),
+ (2006, 12),
+ (2007, 10),
+ (2008, 7),
+ (2009, 9),
+ (2010, 6),
+ (2011, 8),
+ (2012, 13),
+ (2013, 2),
+ (2014, 2),
+ (2018, 1),
+ (2019, 128),
+ (2021, 1429),
+ (2022, 4),
+ (2026, 2),
+ (2027, 2),
+ (2030, 7),
+ (2032, 175),
+ (2033, 1),
+ (2035, 90),
+ (2036, 3),
+ (2037, 11),
+ (2038, 2),
+ (2039, 4),
+ (2040, 3),
+ (2041, 2),
+ (2042, 1),
+ (2043, 2),
+ (2044, 5),
+ (2045, 1),
+ (2046, 3),
+ (2047, 21),
+ (2048, 5),
+ (2050, 16),
+ (2051, 120),
+ (2053, 1403),
+ (2054, 4),
+ (2055, 29),
+ (2057, 26),
+ (2058, 3),
+ (2059, 4),
+ (2060, 4),
+ (2061, 7),
+ (2063, 1),
+ (2065, 170),
+ (2066, 3),
+ (2067, 2),
+ (2068, 7),
+ (2069, 13),
+ (2071, 77),
+ (2072, 1),
+ (2075, 4),
+ (2077, 1),
+ (2078, 2),
+ (2079, 5),
+ (2080, 4),
+ (2081, 3),
+ (2082, 3),
+ (2083, 2),
+ (2084, 293),
+ (2085, 6),
+ (2086, 1395),
+ (2087, 2),
+ (2089, 4),
+ (2090, 10),
+ (2091, 26),
+ (2092, 14),
+ (2093, 25),
+ (2097, 170),
+ (2099, 2),
+ (2100, 1),
+ (2101, 8),
+ (2102, 5),
+ (2104, 2),
+ (2105, 2),
+ (2107, 90),
+ (2108, 1),
+ (2110, 15),
+ (2112, 1),
+ (2113, 1),
+ (2114, 3),
+ (2115, 8),
+ (2116, 3),
+ (2117, 5),
+ (2118, 1380),
+ (2119, 4),
+ (2120, 1),
+ (2121, 3),
+ (2122, 1),
+ (2123, 6),
+ (2124, 24),
+ (2125, 1),
+ (2127, 33),
+ (2128, 4),
+ (2129, 197),
+ (2132, 1),
+ (2133, 3),
+ (2134, 8),
+ (2141, 1),
+ (2143, 95),
+ (2144, 6),
+ (2146, 1),
+ (2147, 1),
+ (2148, 3),
+ (2150, 1369),
+ (2152, 1),
+ (2153, 1),
+ (2155, 5),
+ (2156, 7),
+ (2157, 12),
+ (2158, 2),
+ (2159, 6),
+ (2160, 7),
+ (2161, 174),
+ (2162, 22),
+ (2163, 27),
+ (2164, 5),
+ (2165, 24),
+ (2166, 6),
+ (2169, 8),
+ (2170, 2),
+ (2171, 1),
+ (2172, 1),
+ (2174, 8),
+ (2175, 10),
+ (2176, 2),
+ (2177, 3),
+ (2179, 72),
+ (2180, 4),
+ (2181, 1),
+ (2182, 1366),
+ (2183, 2),
+ (2184, 5),
+ (2185, 4),
+ (2188, 3),
+ (2191, 1),
+ (2192, 2),
+ (2193, 169),
+ (2198, 7),
+ (2199, 27),
+ (2201, 28),
+ (2205, 2),
+ (2206, 2),
+ (2209, 9),
+ (2213, 8),
+ (2214, 1364),
+ (2215, 95),
+ (2216, 1),
+ (2217, 2),
+ (2218, 1),
+ (2219, 1),
+ (2220, 3),
+ (2221, 2),
+ (2222, 3),
+ (2223, 41),
+ (2225, 168),
+ (2228, 1),
+ (2229, 6),
+ (2230, 8),
+ (2231, 1),
+ (2232, 2),
+ (2233, 6),
+ (2234, 1),
+ (2235, 41),
+ (2236, 2),
+ (2237, 17),
+ (2240, 7),
+ (2242, 6),
+ (2244, 1),
+ (2246, 1350),
+ (2249, 2),
+ (2250, 4),
+ (2251, 89),
+ (2252, 1),
+ (2257, 167),
+ (2260, 4),
+ (2261, 3),
+ (2262, 6),
+ (2265, 1),
+ (2269, 2),
+ (2270, 4),
+ (2271, 32),
+ (2273, 21),
+ (2274, 1),
+ (2275, 3),
+ (2276, 1),
+ (2277, 2),
+ (2278, 1344),
+ (2279, 2),
+ (2280, 1),
+ (2281, 1),
+ (2284, 1),
+ (2287, 98),
+ (2288, 2),
+ (2289, 168),
+ (2292, 3),
+ (2293, 3),
+ (2294, 4),
+ (2298, 3),
+ (2303, 9),
+ (2307, 26),
+ (2308, 1),
+ (2309, 30),
+ (2310, 1344),
+ (2314, 1),
+ (2318, 1),
+ (2321, 164),
+ (2323, 1),
+ (2324, 82),
+ (2325, 1),
+ (2326, 5),
+ (2327, 1),
+ (2334, 6),
+ (2338, 1),
+ (2339, 1),
+ (2340, 1),
+ (2342, 1337),
+ (2343, 55),
+ (2344, 27),
+ (2345, 6),
+ (2346, 25),
+ (2347, 1),
+ (2348, 18),
+ (2350, 1),
+ (2351, 3),
+ (2352, 2),
+ (2353, 166),
+ (2358, 6),
+ (2360, 87),
+ (2361, 3),
+ (2362, 1),
+ (2373, 9),
+ (2374, 1330),
+ (2376, 1),
+ (2377, 1),
+ (2378, 11),
+ (2379, 4),
+ (2380, 28),
+ (2382, 29),
+ (2383, 2),
+ (2384, 8),
+ (2385, 169),
+ (2386, 4),
+ (2387, 9),
+ (2388, 8),
+ (2389, 4),
+ (2390, 15),
+ (2392, 1),
+ (2396, 117),
+ (2397, 4),
+ (2399, 1),
+ (2406, 1330),
+ (2410, 1),
+ (2414, 1),
+ (2415, 4),
+ (2416, 26),
+ (2417, 164),
+ (2418, 31),
+ (2421, 3),
+ (2422, 4),
+ (2424, 6),
+ (2425, 3),
+ (2426, 3),
+ (2427, 5),
+ (2428, 1),
+ (2429, 2),
+ (2432, 100),
+ (2433, 1),
+ (2435, 1),
+ (2436, 1),
+ (2438, 1328),
+ (2441, 10),
+ (2443, 11),
+ (2448, 2),
+ (2449, 163),
+ (2451, 1),
+ (2452, 27),
+ (2453, 8),
+ (2454, 24),
+ (2455, 1),
+ (2456, 2),
+ (2457, 2),
+ (2460, 4),
+ (2465, 5),
+ (2466, 3),
+ (2468, 95),
+ (2469, 6),
+ (2470, 1324),
+ (2471, 1),
+ (2472, 1),
+ (2476, 2),
+ (2477, 2),
+ (2478, 2),
+ (2479, 4),
+ (2481, 163),
+ (2484, 2),
+ (2485, 6),
+ (2486, 2),
+ (2488, 23),
+ (2489, 1),
+ (2490, 26),
+ (2491, 1),
+ (2493, 1),
+ (2494, 1),
+ (2495, 3),
+ (2496, 1),
+ (2500, 3),
+ (2502, 1327),
+ (2503, 1),
+ (2504, 93),
+ (2505, 2),
+ (2506, 1),
+ (2511, 4),
+ (2513, 166),
+ (2516, 3),
+ (2517, 5),
+ (2518, 8),
+ (2519, 2),
+ (2521, 1),
+ (2524, 27),
+ (2526, 20),
+ (2532, 1),
+ (2534, 1320),
+ (2535, 1),
+ (2540, 114),
+ (2541, 1),
+ (2543, 1),
+ (2545, 163),
+ (2550, 3),
+ (2555, 3),
+ (2557, 4),
+ (2558, 3),
+ (2559, 2),
+ (2560, 26),
+ (2561, 6),
+ (2562, 26),
+ (2564, 5),
+ (2565, 1),
+ (2566, 1325),
+ (2567, 5),
+ (2568, 9),
+ (2569, 10),
+ (2570, 2),
+ (2571, 1),
+ (2576, 97),
+ (2577, 165),
+ (2582, 3),
+ (2583, 5),
+ (2593, 2),
+ (2596, 42),
+ (2597, 1),
+ (2598, 1336),
+ (2602, 1),
+ (2609, 163),
+ (2612, 97),
+ (2613, 1),
+ (2614, 2),
+ (2619, 1),
+ (2621, 2),
+ (2624, 2),
+ (2628, 2),
+ (2630, 1684946),
+ (2632, 27),
+ (2633, 2),
+ (2634, 25),
+ (2635, 1),
+ (2637, 4),
+ (2639, 1),
+ (2640, 1),
+ (2641, 163),
+ (2644, 1),
+ (2645, 3),
+ (2646, 2),
+ (2648, 112),
+ (2649, 1),
+ (2653, 5),
+ (2659, 3),
+ (2660, 1),
+ (2661, 1),
+ (2662, 1315),
+ (2664, 1),
+ (2668, 30),
+ (2669, 1),
+ (2670, 26),
+ (2673, 163),
+ (2674, 2),
+ (2675, 1),
+ (2678, 7),
+ (2679, 1),
+ (2680, 1),
+ (2684, 90),
+ (2685, 1),
+ (2686, 1),
+ (2694, 1315),
+ (2699, 1),
+ (2701, 1),
+ (2704, 30),
+ (2705, 163),
+ (2706, 27),
+ (2710, 2),
+ (2712, 1),
+ (2720, 112),
+ (2721, 2),
+ (2723, 5),
+ (2726, 1316),
+ (2736, 1),
+ (2737, 165),
+ (2738, 2),
+ (2740, 25),
+ (2742, 33),
+ (2745, 1),
+ (2756, 97),
+ (2757, 1),
+ (2758, 1315),
+ (2769, 163),
+ (2774, 3),
+ (2776, 32),
+ (2778, 34),
+ (2781, 1),
+ (2782, 1),
+ (2784, 1),
+ (2790, 1313),
+ (2792, 94),
+ (2793, 12),
+ (2796, 1),
+ (2800, 1),
+ (2801, 163),
+ (2804, 2),
+ (2805, 6),
+ (2806, 2),
+ (2807, 2),
+ (2809, 1),
+ (2810, 1),
+ (2812, 23),
+ (2814, 33),
+ (2815, 3),
+ (2816, 1),
+ (2820, 2),
+ (2821, 1),
+ (2822, 1314),
+ (2824, 1),
+ (2828, 104),
+ (2829, 1),
+ (2833, 163),
+ (2837, 6),
+ (2838, 4),
+ (2839, 1),
+ (2848, 32),
+ (2849, 4),
+ (2850, 32),
+ (2852, 4),
+ (2853, 1),
+ (2854, 1312),
+ (2861, 1),
+ (2863, 52),
+ (2864, 111),
+ (2865, 164),
+ (2868, 2),
+ (2869, 15),
+ (2870, 2),
+ (2871, 1),
+ (2884, 30),
+ (2886, 1333),
+ (2890, 2),
+ (2891, 2),
+ (2892, 3),
+ (2893, 4),
+ (2894, 2),
+ (2897, 163),
+ (2899, 3),
+ (2900, 230),
+ (2901, 1),
+ (2902, 2),
+ (2908, 2),
+ (2911, 1),
+ (2918, 1312),
+ (2920, 42),
+ (2922, 25),
+ (2923, 1),
+ (2925, 1),
+ (2929, 165),
+ (2930, 2),
+ (2931, 5),
+ (2932, 4),
+ (2933, 8),
+ (2934, 2),
+ (2936, 110),
+ (2937, 1),
+ (2938, 1),
+ (2939, 1),
+ (2948, 1),
+ (2950, 1313),
+ (2956, 38),
+ (2958, 32),
+ (2961, 163),
+ (2964, 1),
+ (2966, 4),
+ (2967, 2),
+ (2969, 1),
+ (2971, 1),
+ (2972, 151),
+ (2973, 1),
+ (2975, 3),
+ (2976, 4),
+ (2977, 3),
+ (2978, 1),
+ (2979, 1),
+ (2980, 1),
+ (2982, 1312),
+ (2992, 28),
+ (2993, 163),
+ (2994, 29),
+ (2998, 2),
+ (3006, 1),
+ (3007, 2),
+ (3008, 188),
+ (3009, 2),
+ (3014, 1311),
+ (3015, 5),
+ (3016, 9),
+ (3017, 1),
+ (3020, 1),
+ (3025, 164),
+ (3028, 27),
+ (3030, 31),
+ (3044, 223),
+ (3045, 1),
+ (3046, 1311),
+ (3048, 1),
+ (3057, 163),
+ (3061, 2),
+ (3062, 4),
+ (3064, 41),
+ (3066, 35),
+ (3076, 2),
+ (3078, 1310),
+ (3080, 151),
+ (3081, 2),
+ (3089, 163),
+ (3094, 2),
+ (3100, 35),
+ (3101, 2),
+ (3102, 38),
+ (3104, 2),
+ (3110, 1310),
+ (3116, 106),
+ (3117, 2),
+ (3121, 163),
+ (3125, 5),
+ (3126, 2),
+ (3132, 2),
+ (3136, 36),
+ (3138, 39),
+ (3140, 2),
+ (3141, 1),
+ (3142, 1309),
+ (3143, 1),
+ (3144, 1),
+ (3152, 120),
+ (3153, 164),
+ (3155, 1),
+ (3157, 1),
+ (3158, 2),
+ (3163, 1),
+ (3164, 1),
+ (3172, 34),
+ (3174, 1343),
+ (3185, 163),
+ (3188, 136),
+ (3189, 1),
+ (3190, 2),
+ (3203, 1),
+ (3204, 1),
+ (3206, 1308),
+ (3208, 53),
+ (3210, 52),
+ (3217, 163),
+ (3220, 38),
+ (3221, 114),
+ (3222, 2),
+ (3224, 141),
+ (3225, 5),
+ (3230, 1),
+ (3236, 38),
+ (3238, 1308),
+ (3244, 35),
+ (3246, 46),
+ (3249, 163),
+ (3254, 2),
+ (3260, 105),
+ (3261, 4),
+ (3263, 1),
+ (3270, 1308),
+ (3280, 38),
+ (3281, 163),
+ (3282, 28),
+ (3286, 3),
+ (3292, 1),
+ (3296, 138),
+ (3297, 1),
+ (3301, 1),
+ (3302, 1308),
+ (3304, 1),
+ (3313, 163),
+ (3316, 33),
+ (3318, 34),
+ (3329, 1),
+ (3331, 1),
+ (3332, 120),
+ (3333, 1),
+ (3334, 1309),
+ (3345, 163),
+ (3350, 3),
+ (3352, 34),
+ (3354, 31),
+ (3357, 1),
+ (3366, 1307),
+ (3368, 230),
+ (3369, 6),
+ (3377, 163),
+ (3382, 2),
+ (3388, 37),
+ (3390, 45),
+ (3398, 1307),
+ (3404, 3128),
+ (3405, 2),
+ (3409, 163),
+ (3414, 2),
+ (3424, 40),
+ (3426, 23),
+ (3430, 1307),
+ (3440, 117),
+ (3441, 164),
+ (3446, 2),
+ (3460, 30),
+ (3462, 1344),
+ (3469, 1),
+ (3473, 163),
+ (3476, 116),
+ (3477, 1),
+ (3478, 3),
+ (3494, 1305),
+ (3496, 36),
+ (3498, 38),
+ (3501, 2),
+ (3504, 2),
+ (3505, 163),
+ (3510, 2),
+ (3512, 124),
+ (3513, 4),
+ (3515, 1),
+ (3525, 1),
+ (3526, 1305),
+ (3532, 27),
+ (3534, 33),
+ (3537, 165),
+ (3541, 2),
+ (3542, 2),
+ (3544, 2),
+ (3548, 119),
+ (3549, 1),
+ (3558, 1305),
+ (3568, 29),
+ (3569, 163),
+ (3570, 53),
+ (3574, 2),
+ (3581, 6),
+ (3584, 115),
+ (3585, 2),
+ (3590, 1306),
+ (3601, 163),
+ (3604, 39),
+ (3606, 45),
+ (3620, 107),
+ (3621, 1),
+ (3622, 1304),
+ (3633, 163),
+ (3634, 1),
+ (3637, 1),
+ (3638, 2),
+ (3640, 43),
+ (3642, 35),
+ (3654, 1305),
+ (3656, 126),
+ (3657, 2),
+ (3661, 1),
+ (3664, 1),
+ (3665, 163),
+ (3670, 3),
+ (3676, 32),
+ (3678, 48),
+ (3679, 1),
+ (3686, 1303),
+ (3692, 128),
+ (3693, 2),
+ (3697, 163),
+ (3702, 3),
+ (3712, 33),
+ (3714, 28),
+ (3718, 1302),
+ (3728, 137),
+ (3729, 165),
+ (3734, 2),
+ (3748, 54),
+ (3749, 1),
+ (3750, 1333),
+ (3758, 1),
+ (3761, 163),
+ (3764, 125),
+ (3765, 2),
+ (3766, 3),
+ (3782, 1301),
+ (3784, 32),
+ (3786, 50),
+ (3793, 163),
+ (3798, 2),
+ (3800, 123),
+ (3801, 3),
+ (3805, 1),
+ (3814, 1301),
+ (3820, 53),
+ (3822, 30),
+ (3825, 163),
+ (3830, 2),
+ (3833, 1),
+ (3836, 109),
+ (3837, 3),
+ (3846, 1301),
+ (3856, 35),
+ (3857, 163),
+ (3858, 54),
+ (3860, 20),
+ (3861, 51),
+ (3862, 2),
+ (3872, 124),
+ (3873, 2),
+ (3876, 17),
+ (3878, 1302),
+ (3882, 1),
+ (3889, 163),
+ (3892, 45),
+ (3894, 47),
+ (3901, 2),
+ (3903, 1),
+ (3904, 2),
+ (3908, 138),
+ (3909, 2),
+ (3910, 1300),
+ (3917, 2),
+ (3921, 163),
+ (3926, 2),
+ (3928, 38),
+ (3930, 37),
+ (3942, 1300),
+ (3944, 137),
+ (3945, 2),
+ (3953, 163),
+ (3958, 2),
+ (3964, 66),
+ (3966, 37),
+ (3971, 1),
+ (3974, 1300),
+ (3980, 166),
+ (3981, 1),
+ (3985, 163),
+ (3990, 2),
+ (4000, 35),
+ (4002, 54),
+ (4006, 1300),
+ (4016, 150),
+ (4017, 164),
+ (4021, 38),
+ (4022, 2),
+ (4024, 38),
+ (4036, 47),
+ (4038, 1347),
+ (4049, 163),
+ (4052, 134),
+ (4053, 10),
+ (4054, 2),
+ (4068, 1),
+ (4070, 1300),
+ (4072, 52),
+ (4074, 40),
+ (4075, 1),
+ (4081, 163),
+ (4085, 7),
+ (4086, 2),
+ (4088, 123),
+ (4089, 4),
+ (4100, 2),
+ (4102, 1300),
+ (4108, 38),
+ (4110, 43),
+ (4113, 163),
+ (4118, 2),
+ (4119, 2),
+ (4124, 159),
+ (4125, 3),
+ (4128, 1),
+ (4134, 1299),
+ (4141, 1),
+ (4144, 51),
+ (4145, 163),
+ (4146, 41),
+ (4150, 2),
+ (4152, 30),
+ (4160, 153),
+ (4161, 1),
+ (4164, 2),
+ (4166, 1299),
+ (4177, 163),
+ (4180, 225),
+ (4181, 596),
+ (4182, 50),
+ (4187, 1),
+ (4196, 373),
+ (4197, 3),
+ (4198, 1299),
+ (4209, 163),
+ (4214, 2),
+ (4216, 66),
+ (4217, 3),
+ (4218, 69),
+ (4221, 1),
+ (4230, 1299),
+ (4232, 158),
+ (4233, 2),
+ (4241, 163),
+ (4246, 2),
+ (4252, 45),
+ (4253, 1),
+ (4254, 48),
+ (4262, 1300),
+ (4267, 2),
+ (4268, 145),
+ (4269, 3),
+ (4270, 1),
+ (4271, 1),
+ (4273, 163),
+ (4278, 3),
+ (4288, 75),
+ (4290, 36),
+ (4294, 1298),
+ (4301, 1),
+ (4304, 173),
+ (4305, 166),
+ (4309, 2),
+ (4310, 2),
+ (4324, 52),
+ (4326, 1359),
+ (4337, 163),
+ (4340, 195),
+ (4341, 2),
+ (4342, 3),
+ (4358, 1297),
+ (4360, 76),
+ (4362, 56),
+ (4365, 2),
+ (4369, 163),
+ (4374, 2),
+ (4376, 171),
+ (4377, 1),
+ (4390, 1298),
+ (4396, 52),
+ (4398, 49),
+ (4401, 163),
+ (4406, 3),
+ (4407, 2),
+ (4412, 170),
+ (4413, 2),
+ (4421, 1),
+ (4422, 1296),
+ (4432, 57),
+ (4433, 163),
+ (4434, 51),
+ (4436, 1),
+ (4438, 2),
+ (4448, 481),
+ (4449, 2),
+ (4451, 1),
+ (4454, 1295),
+ (4463, 1),
+ (4465, 163),
+ (4468, 74),
+ (4470, 92),
+ (4484, 448),
+ (4485, 3),
+ (4486, 1295),
+ (4487, 1),
+ (4497, 163),
+ (4502, 2),
+ (4504, 52),
+ (4506, 65),
+ (4518, 1295),
+ (4519, 2),
+ (4520, 631),
+ (4521, 3),
+ (4529, 164),
+ (4530, 1),
+ (4532, 1),
+ (4533, 3),
+ (4534, 2),
+ (4540, 55),
+ (4542, 48),
+ (4550, 1294),
+ (4556, 2358),
+ (4557, 3),
+ (4561, 163),
+ (4562, 1),
+ (4566, 2),
+ (4576, 58),
+ (4578, 74),
+ (4582, 1294),
+ (4592, 193),
+ (4593, 167),
+ (4598, 2),
+ (4612, 66),
+ (4614, 1363),
+ (4621, 2),
+ (4625, 163),
+ (4628, 218),
+ (4629, 3),
+ (4630, 2),
+ (4635, 3),
+ (4640, 1),
+ (4645, 1),
+ (4646, 1295),
+ (4648, 57),
+ (4650, 90),
+ (4657, 163),
+ (4662, 3),
+ (4664, 194),
+ (4665, 1),
+ (4678, 1295),
+ (4684, 49),
+ (4685, 1),
+ (4686, 85),
+ (4689, 163),
+ (4694, 4),
+ (4700, 183),
+ (4701, 3),
+ (4710, 1291),
+ (4720, 61),
+ (4721, 163),
+ (4722, 75),
+ (4726, 3),
+ (4736, 175),
+ (4737, 4),
+ (4742, 1291),
+ (4753, 163),
+ (4756, 84),
+ (4758, 53),
+ (4772, 210),
+ (4773, 4),
+ (4774, 1291),
+ (4785, 163),
+ (4790, 2),
+ (4792, 54),
+ (4794, 66),
+ (4799, 2),
+ (4806, 1292),
+ (4808, 180),
+ (4809, 6),
+ (4817, 164),
+ (4820, 32),
+ (4821, 132),
+ (4822, 3),
+ (4824, 17),
+ (4828, 70),
+ (4830, 62),
+ (4836, 42),
+ (4838, 1290),
+ (4844, 199),
+ (4845, 3),
+ (4849, 163),
+ (4854, 2),
+ (4864, 104),
+ (4866, 98),
+ (4870, 1290),
+ (4873, 1),
+ (4880, 184),
+ (4881, 164),
+ (4886, 2),
+ (4900, 88),
+ (4902, 1387),
+ (4909, 1),
+ (4913, 163),
+ (4916, 187),
+ (4917, 6),
+ (4918, 2),
+ (4934, 1290),
+ (4936, 65),
+ (4938, 59),
+ (4945, 163),
+ (4948, 1),
+ (4950, 2),
+ (4952, 198),
+ (4953, 3),
+ (4966, 1290),
+ (4972, 64),
+ (4974, 108),
+ (4977, 163),
+ (4982, 2),
+ (4988, 199),
+ (4989, 8),
+ (4998, 1290),
+ (5008, 82),
+ (5009, 163),
+ (5010, 113),
+ (5012, 3),
+ (5013, 9),
+ (5014, 2),
+ (5017, 1),
+ (5024, 228),
+ (5025, 2),
+ (5028, 4),
+ (5030, 1290),
+ (5041, 162),
+ (5044, 96),
+ (5046, 71),
+ (5060, 275),
+ (5061, 6),
+ (5062, 1291),
+ (5064, 1),
+ (5070, 1),
+ (5073, 162),
+ (5078, 3),
+ (5080, 66),
+ (5082, 153),
+ (5094, 1289),
+ (5096, 272),
+ (5097, 10),
+ (5101, 2),
+ (5104, 2),
+ (5105, 162),
+ (5110, 2),
+ (5116, 87),
+ (5118, 80),
+ (5126, 1289),
+ (5132, 266),
+ (5133, 5),
+ (5135, 1),
+ (5137, 162),
+ (5140, 190),
+ (5141, 681),
+ (5142, 2),
+ (5152, 104),
+ (5154, 184),
+ (5156, 238),
+ (5158, 1289),
+ (5168, 257),
+ (5169, 165),
+ (5174, 2),
+ (5188, 99),
+ (5190, 1435),
+ (5201, 162),
+ (5204, 228),
+ (5205, 6),
+ (5206, 2),
+ (5221, 206),
+ (5222, 1289),
+ (5224, 312),
+ (5226, 110),
+ (5231, 1),
+ (5233, 162),
+ (5238, 2),
+ (5240, 266),
+ (5241, 7),
+ (5254, 1289),
+ (5260, 87),
+ (5262, 243),
+ (5265, 162),
+ (5270, 2),
+ (5274, 8),
+ (5276, 318),
+ (5277, 7),
+ (5286, 1289),
+ (5288, 86),
+ (5296, 88),
+ (5297, 162),
+ (5298, 123),
+ (5302, 3),
+ (5312, 351),
+ (5313, 1),
+ (5318, 1289),
+ (5329, 162),
+ (5332, 115),
+ (5334, 173),
+ (5339, 6),
+ (5344, 1),
+ (5348, 313),
+ (5349, 3),
+ (5350, 1289),
+ (5352, 24),
+ (5353, 14),
+ (5361, 162),
+ (5366, 3),
+ (5368, 157),
+ (5370, 107),
+ (5374, 1),
+ (5382, 1289),
+ (5384, 293),
+ (5385, 4),
+ (5388, 4),
+ (5393, 162),
+ (5396, 1),
+ (5398, 2),
+ (5404, 142),
+ (5406, 201),
+ (5407, 1),
+ (5414, 1289),
+ (5417, 3),
+ (5420, 285),
+ (5421, 5),
+ (5423, 1),
+ (5425, 162),
+ (5430, 2),
+ (5436, 1),
+ (5440, 142),
+ (5442, 210),
+ (5444, 1),
+ (5446, 1294),
+ (5456, 318),
+ (5457, 166),
+ (5462, 3),
+ (5476, 123),
+ (5478, 1608),
+ (5482, 2),
+ (5489, 162),
+ (5492, 329),
+ (5493, 2),
+ (5494, 2),
+ (5504, 1),
+ (5506, 1),
+ (5510, 1289),
+ (5511, 1),
+ (5512, 165),
+ (5514, 167),
+ (5521, 163),
+ (5522, 1),
+ (5526, 2),
+ (5528, 367),
+ (5529, 8),
+ (5542, 1289),
+ (5548, 192),
+ (5550, 291),
+ (5553, 162),
+ (5558, 2),
+ (5564, 399),
+ (5565, 13),
+ (5574, 1289),
+ (5584, 188),
+ (5585, 163),
+ (5586, 356),
+ (5590, 2),
+ (5592, 1),
+ (5599, 1),
+ (5600, 375),
+ (5601, 3),
+ (5606, 1290),
+ (5608, 1),
+ (5617, 162),
+ (5618, 1),
+ (5620, 261),
+ (5622, 667),
+ (5623, 1),
+ (5626, 1),
+ (5633, 1),
+ (5636, 406),
+ (5637, 4),
+ (5638, 1289),
+ (5639, 1),
+ (5649, 162),
+ (5654, 2),
+ (5656, 468),
+ (5658, 1159),
+ (5662, 1),
+ (5670, 1289),
+ (5671, 1),
+ (5672, 349),
+ (5673, 8),
+ (5675, 1),
+ (5681, 162),
+ (5686, 2),
+ (5692, 321),
+ (5694, 3067),
+ (5702, 1289),
+ (5706, 1),
+ (5708, 443),
+ (5709, 7),
+ (5713, 162),
+ (5718, 2),
+ (5728, 496),
+ (5730, 4577),
+ (5734, 1289),
+ (5744, 383),
+ (5745, 165),
+ (5750, 3),
+ (5756, 1),
+ (5758, 1),
+ (5764, 5847),
+ (5766, 8966),
+ (5775, 1),
+ (5777, 162),
+ (5780, 616),
+ (5781, 240),
+ (5782, 2),
+ (5784, 1),
+ (5788, 1),
+ (5796, 81),
+ (5798, 1289),
+ (5799, 1),
+ (5800, 5543),
+ (5802, 13287),
+ (5809, 162),
+ (5814, 2),
+ (5816, 409),
+ (5817, 3),
+ (5830, 1289),
+ (5833, 1),
+ (5836, 123),
+ (5838, 59),
+ (5841, 162),
+ (5846, 2),
+ (5852, 480),
+ (5853, 10),
+ (5862, 1289),
+ (5872, 191),
+ (5873, 162),
+ (5874, 38),
+ (5878, 2),
+ (5888, 616),
+ (5889, 12),
+ (5894, 1289),
+ (5905, 162),
+ (5908, 139),
+ (5910, 54),
+ (5922, 1),
+ (5924, 675),
+ (5925, 9),
+ (5926, 1289),
+ (5937, 162),
+ (5942, 2),
+ (5944, 153),
+ (5946, 48),
+ (5958, 1289),
+ (5960, 614),
+ (5961, 33),
+ (5969, 162),
+ (5974, 2),
+ (5980, 140),
+ (5982, 95),
+ (5990, 1289),
+ (5996, 628),
+ (5997, 10),
+ (6001, 162),
+ (6006, 2),
+ (6016, 155),
+ (6018, 67),
+ (6021, 42),
+ (6022, 1289),
+ (6024, 42),
+ (6032, 772),
+ (6033, 177),
+ (6038, 2),
+ (6049, 1),
+ (6052, 109),
+ (6054, 1340),
+ (6065, 162),
+ (6068, 749),
+ (6069, 11),
+ (6070, 2),
+ (6086, 1289),
+ (6088, 364),
+ (6090, 49),
+ (6096, 1),
+ (6097, 162),
+ (6102, 2),
+ (6104, 975),
+ (6105, 4),
+ (6106, 1),
+ (6118, 1289),
+ (6124, 273),
+ (6126, 58),
+ (6129, 162),
+ (6134, 2),
+ (6138, 1),
+ (6140, 1053),
+ (6141, 13),
+ (6150, 1289),
+ (6152, 1),
+ (6153, 2),
+ (6160, 372),
+ (6161, 162),
+ (6162, 70),
+ (6164, 1),
+ (6166, 2),
+ (6172, 1),
+ (6176, 1088),
+ (6177, 96),
+ (6178, 1),
+ (6182, 1290),
+ (6188, 4),
+ (6193, 162),
+ (6194, 1),
+ (6196, 346),
+ (6198, 101),
+ (6206, 1),
+ (6212, 1352),
+ (6213, 4),
+ (6214, 1290),
+ (6219, 2),
+ (6223, 1),
+ (6225, 162),
+ (6230, 1),
+ (6232, 321),
+ (6234, 170),
+ (6246, 1290),
+ (6248, 1755),
+ (6249, 4),
+ (6257, 162),
+ (6261, 4),
+ (6262, 1),
+ (6264, 4),
+ (6268, 616),
+ (6270, 141),
+ (6275, 1),
+ (6278, 1289),
+ (6280, 1),
+ (6281, 1),
+ (6284, 2516),
+ (6285, 73),
+ (6289, 162),
+ (6294, 1),
+ (6304, 409),
+ (6306, 163),
+ (6310, 1289),
+ (6314, 2),
+ (6320, 2276),
+ (6321, 210),
+ (6326, 1),
+ (6340, 445),
+ (6342, 1437),
+ (6353, 162),
+ (6356, 4090),
+ (6357, 55),
+ (6358, 1),
+ (6364, 1),
+ (6374, 1290),
+ (6376, 929),
+ (6378, 270),
+ (6385, 162),
+ (6390, 1),
+ (6392, 6135),
+ (6393, 16),
+ (6400, 1),
+ (6406, 1289),
+ (6412, 607),
+ (6414, 386),
+ (6417, 162),
+ (6420, 1),
+ (6421, 238),
+ (6422, 1),
+ (6424, 238),
+ (6428, 15189),
+ (6429, 227),
+ (6438, 1289),
+ (6443, 1),
+ (6448, 1211),
+ (6449, 162),
+ (6450, 1135),
+ (6453, 2),
+ (6454, 1),
+ (6464, 66588),
+ (6465, 77),
+ (6470, 1289),
+ (6474, 31),
+ (6481, 162),
+ (6484, 21001),
+ (6486, 9926),
+ (6488, 95),
+ (6498, 1),
+ (6500, 51017),
+ (6501, 2547),
+ (6502, 1289),
+ (6513, 162),
+ (6518, 1),
+ (6520, 11978),
+ (6522, 2546),
+ (6534, 1289),
+ (6536, 1),
+ (6537, 4),
+ (6539, 7),
+ (6545, 162),
+ (6546, 1),
+ (6550, 1),
+ (6553, 27),
+ (6566, 1289),
+ (6572, 1),
+ (6573, 2),
+ (6574, 1),
+ (6577, 163),
+ (6582, 2),
+ (6587, 1),
+ (6588, 17),
+ (6598, 1289),
+ (6600, 1),
+ (6603, 1),
+ (6605, 1),
+ (6606, 2),
+ (6608, 1),
+ (6609, 163),
+ (6610, 1),
+ (6614, 1),
+ (6623, 4),
+ (6630, 1289),
+ (6631, 1),
+ (6633, 1),
+ (6635, 1),
+ (6640, 1),
+ (6641, 162),
+ (6644, 1),
+ (6645, 2),
+ (6646, 2),
+ (6662, 1289),
+ (6666, 1),
+ (6670, 1),
+ (6673, 162),
+ (6678, 1),
+ (6679, 1),
+ (6680, 1),
+ (6681, 5),
+ (6686, 1),
+ (6694, 1289),
+ (6705, 162),
+ (6710, 1),
+ (6711, 1),
+ (6714, 1),
+ (6716, 1),
+ (6717, 10),
+ (6726, 1289),
+ (6734, 1),
+ (6737, 163),
+ (6738, 1),
+ (6740, 2),
+ (6742, 1),
+ (6752, 1),
+ (6753, 1),
+ (6757, 1),
+ (6758, 1289),
+ (6769, 162),
+ (6770, 1),
+ (6774, 1),
+ (6775, 1),
+ (6788, 1),
+ (6789, 3),
+ (6790, 1289),
+ (6797, 1),
+ (6801, 162),
+ (6802, 1),
+ (6803, 1),
+ (6806, 1),
+ (6818, 1),
+ (6819, 1),
+ (6822, 1289),
+ (6824, 1),
+ (6825, 5),
+ (6833, 162),
+ (6834, 1),
+ (6837, 1),
+ (6838, 1),
+ (6844, 2),
+ (6854, 1289),
+ (6860, 1),
+ (6861, 5),
+ (6865, 163),
+ (6869, 1),
+ (6870, 1),
+ (6872, 1),
+ (6875, 1),
+ (6881, 3),
+ (6886, 1289),
+ (6896, 1),
+ (6897, 166),
+ (6902, 1),
+ (6915, 1),
+ (6918, 1289),
+ (6929, 162),
+ (6932, 2),
+ (6933, 1),
+ (6934, 1),
+ (6947, 1),
+ (6950, 1290),
+ (6961, 162),
+ (6966, 1),
+ (6969, 2),
+ (6982, 1289),
+ (6993, 162),
+ (6998, 1),
+ (7004, 1),
+ (7005, 1),
+ (7014, 1289),
+ (7025, 162),
+ (7030, 1),
+ (7032, 1),
+ (7034, 1),
+ (7040, 1),
+ (7041, 1),
+ (7046, 1289),
+ (7057, 162),
+ (7058, 1),
+ (7059, 1),
+ (7062, 1),
+ (7070, 1),
+ (7076, 1),
+ (7077, 3),
+ (7078, 1289),
+ (7084, 1),
+ (7089, 162),
+ (7094, 1),
+ (7110, 1289),
+ (7112, 1),
+ (7113, 5),
+ (7121, 162),
+ (7124, 1),
+ (7126, 1),
+ (7133, 1),
+ (7142, 1289),
+ (7148, 1),
+ (7149, 12),
+ (7153, 162),
+ (7158, 1),
+ (7174, 1289),
+ (7184, 1),
+ (7185, 170),
+ (7190, 1),
+ (7206, 1289),
+ (7217, 162),
+ (7220, 1),
+ (7221, 82),
+ (7222, 1),
+ (7224, 81),
+ (7229, 1),
+ (7237, 1),
+ (7238, 1289),
+ (7242, 1),
+ (7243, 1),
+ (7248, 1),
+ (7249, 162),
+ (7254, 1),
+ (7256, 1),
+ (7257, 1),
+ (7266, 4),
+ (7270, 1289),
+ (7274, 13),
+ (7280, 20),
+ (7281, 162),
+ (7286, 1),
+ (7288, 12),
+ (7292, 1),
+ (7293, 5),
+ (7296, 1),
+ (7302, 1289),
+ (7308, 1),
+ (7313, 162),
+ (7315, 1),
+ (7318, 1),
+ (7328, 1),
+ (7329, 1),
+ (7334, 1290),
+ (7345, 162),
+ (7349, 1),
+ (7350, 1),
+ (7353, 1),
+ (7364, 1),
+ (7365, 1),
+ (7366, 1290),
+ (7377, 162),
+ (7382, 1),
+ (7392, 1),
+ (7398, 1289),
+ (7400, 1),
+ (7401, 4),
+ (7406, 1),
+ (7409, 162),
+ (7411, 1),
+ (7414, 1),
+ (7430, 1289),
+ (7431, 3),
+ (7436, 1),
+ (7437, 2),
+ (7441, 162),
+ (7445, 5),
+ (7446, 1),
+ (7448, 1),
+ (7460, 1),
+ (7462, 1289),
+ (7472, 1),
+ (7473, 166),
+ (7474, 1),
+ (7478, 1),
+ (7494, 1289),
+ (7505, 162),
+ (7508, 3),
+ (7509, 2),
+ (7510, 2),
+ (7525, 1),
+ (7526, 1289),
+ (7532, 1),
+ (7537, 162),
+ (7542, 1),
+ (7544, 1),
+ (7545, 9),
+ (7546, 1),
+ (7558, 1289),
+ (7569, 162),
+ (7574, 1),
+ (7580, 1),
+ (7581, 6),
+ (7590, 1289),
+ (7601, 162),
+ (7606, 1),
+ (7616, 1),
+ (7617, 6),
+ (7622, 1289),
+ (7623, 1),
+ (7625, 1),
+ (7633, 162),
+ (7638, 1),
+ (7652, 1),
+ (7653, 11),
+ (7654, 1289),
+ (7657, 1),
+ (7665, 162),
+ (7670, 1),
+ (7686, 1289),
+ (7688, 1),
+ (7689, 1),
+ (7697, 162),
+ (7702, 1),
+ (7708, 1),
+ (7715, 1),
+ (7717, 2),
+ (7718, 1289),
+ (7724, 1),
+ (7725, 3),
+ (7729, 162),
+ (7734, 1),
+ (7746, 1),
+ (7750, 1289),
+ (7760, 1),
+ (7761, 167),
+ (7766, 1),
+ (7782, 1289),
+ (7793, 162),
+ (7794, 1),
+ (7796, 1),
+ (7797, 1),
+ (7798, 1),
+ (7814, 1289),
+ (7820, 1),
+ (7825, 162),
+ (7826, 1),
+ (7830, 1),
+ (7832, 1),
+ (7833, 14),
+ (7842, 1),
+ (7846, 1289),
+ (7857, 162),
+ (7862, 1),
+ (7863, 1),
+ (7868, 1),
+ (7869, 4),
+ (7878, 1289),
+ (7885, 1),
+ (7889, 162),
+ (7894, 1),
+ (7904, 1),
+ (7905, 2),
+ (7910, 1289),
+ (7921, 162),
+ (7926, 1),
+ (7929, 1),
+ (7940, 1),
+ (7941, 2),
+ (7942, 1289),
+ (7953, 162),
+ (7958, 1),
+ (7963, 1),
+ (7973, 1),
+ (7974, 1289),
+ (7976, 1),
+ (7977, 16),
+ (7985, 162),
+ (7989, 1),
+ (7990, 1),
+ (7991, 1),
+ (7997, 1),
+ (8000, 1),
+ (8006, 1289),
+ (8012, 1),
+ (8013, 14),
+ (8017, 162),
+ (8022, 1),
+ (8038, 1289),
+ (8048, 1),
+ (8049, 185),
+ (8054, 2),
+ (8070, 1289),
+ (8081, 162),
+ (8084, 1),
+ (8085, 24),
+ (8086, 1),
+ (8102, 1289),
+ (8113, 162),
+ (8118, 1),
+ (8119, 1),
+ (8120, 1),
+ (8121, 1),
+ (8126, 1),
+ (8134, 1289),
+ (8140, 1),
+ (8145, 162),
+ (8150, 1),
+ (8157, 20),
+ (8166, 1289),
+ (8177, 162),
+ (8182, 1),
+ (8192, 1),
+ (8193, 1),
+ (8198, 1289),
+ (8209, 162),
+ (8214, 1),
+ (8228, 1),
+ (8229, 32),
+ (8230, 1290),
+ (8246, 1),
+ (8264, 1),
+ (8265, 27),
+ (8269, 1),
+ (8276, 1),
+ (8282, 1),
+ (8300, 1),
+ (8301, 133),
+ (8336, 2),
+ (8337, 60),
+ (8348, 3),
+ (8356, 1),
+ (8358, 1),
+ (8372, 1),
+ (8373, 196),
+ (8408, 1),
+ (8444, 1),
+ (8468, 1),
+ (8480, 1),
+ (8499, 1),
+ (8516, 1),
+ (8552, 1),
+ (8555, 1),
+ (8588, 1),
+ (8624, 1),
+ (8660, 3),
+ (8675, 1),
+ (8696, 1),
+ (8704, 1),
+ (8724, 1),
+ (8732, 1),
+ (8768, 1),
+ (8779, 1),
+ (8804, 1),
+ (8840, 1),
+ (8852, 2),
+ (8876, 1),
+ (8912, 1),
+ (8948, 1),
+ (8984, 1),
+ (9020, 1),
+ (9128, 1),
+ (9164, 1),
+ (9192, 1),
+ (9200, 2),
+ (9236, 1),
+ (9272, 1),
+ (9308, 1),
+ (9344, 1),
+ (9380, 1),
+ (9416, 1),
+ (9452, 1),
+ (9524, 1),
+ (9560, 1),
+ (9589, 1),
+ (9632, 1),
+ (9642, 1),
+ (9704, 1),
+ (9776, 1),
+ (9848, 1),
+ (9992, 1),
+ (10064, 1),
+ (10100, 1),
+ (10136, 1),
+ (10172, 1),
+ (10208, 1),
+ (10244, 1),
+ (10280, 1),
+ (10316, 1),
+ (10388, 1),
+ (10532, 1),
+ (10572, 1),
+ (10620, 1),
+ (10640, 1),
+ (10669, 1),
+ (10748, 1),
+ (10856, 1),
+ (10964, 1),
+ (11067, 1),
+ (11072, 1),
+ (11180, 1),
+ (11216, 1),
+ (11252, 1),
+ (11288, 1),
+ (11324, 1),
+ (11348, 2),
+ (11360, 1),
+ (11396, 1),
+ (11432, 1),
+ (11468, 1),
+ (11504, 1),
+ (11540, 1),
+ (11576, 1),
+ (11612, 1),
+ (11648, 1),
+ (11756, 1),
+ (11792, 1),
+ (11828, 1),
+ (11864, 1),
+ (11936, 1),
+ (12008, 1),
+ (12080, 1),
+ (12152, 1),
+ (12188, 1),
+ (12224, 1),
+ (12260, 1),
+ (12296, 1),
+ (12332, 1),
+ (12360, 1),
+ (12368, 1),
+ (12404, 1),
+ (12440, 1),
+ (12476, 1),
+ (12501, 2),
+ (12512, 1),
+ (12548, 1),
+ (12584, 1),
+ (12620, 1),
+ (12656, 1),
+ (12693, 1),
+ (12728, 1),
+ (12885, 1),
+ (13123, 1),
+ (13269, 1),
+ (13461, 1),
+ (13653, 1),
+ (13664, 1),
+ (13740, 1),
+ (13872, 1),
+ (13946, 1),
+ (14109, 1),
+ (14613, 2),
+ (14805, 2),
+ (14945, 1),
+ (14997, 1),
+ (15176, 1),
+ (15276, 1),
+ (15384, 1),
+ (15492, 1),
+ (15600, 1),
+ (15708, 1),
+ (15716, 1),
+ (15765, 1),
+ (15816, 1),
+ (15924, 1),
+ (16068, 1),
+ (16104, 1),
+ (16140, 1),
+ (16176, 1),
+ (16212, 1),
+ (16248, 1),
+ (16284, 1),
+ (16320, 1),
+ (16356, 1),
+ (16392, 1),
+ (16430, 1),
+ (16468, 1),
+ (16504, 1),
+ (16540, 1),
+ (16727, 2),
+ (16728, 1),
+ (16919, 2),
+ (16921, 1),
+ (16938, 1),
+ (17111, 6),
+ (17413, 1),
+ (17430, 1),
+ (17495, 1),
+ (17880, 1),
+ (18647, 2),
+ (18672, 1),
+ (19223, 38),
+ (19680, 1),
+ (20436, 1),
+ (21156, 1),
+ (21732, 1),
+ (22380, 1),
+ (22992, 1),
+ (23063, 17),
+ (23244, 1),
+ (23532, 1),
+ (23892, 1),
+ (24108, 1),
+ (24215, 1),
+ (24324, 1),
+ (24407, 2),
+ (24504, 1),
+ (24720, 1),
+ (24900, 1),
+ (24983, 205),
+ (25440, 1),
+ (25620, 1),
+ (26088, 1),
+ (26268, 1),
+ (26448, 1),
+ (26664, 1),
+ (26988, 1),
+ (27276, 1),
+ (27492, 1),
+ (27744, 1),
+ (28032, 1),
+ (28284, 1),
+ (28536, 1),
+ (28823, 42),
+ (28896, 1),
+ (29184, 1),
+ (29292, 1),
+ (29400, 1),
+ (29796, 1),
+ (29975, 4),
+ (30156, 1),
+ (30228, 1),
+ (30743, 238),
+ (30768, 1),
+ (31056, 1),
+ (31092, 1),
+ (31416, 1),
+ (32100, 1),
+ (32712, 1),
+ (33144, 1),
+ (33324, 1),
+ (33792, 1),
+ (34008, 1),
+ (34440, 1),
+ (34583, 81),
+ (34656, 1),
+ (34872, 1),
+ (34944, 1),
+ (35160, 1),
+ (35304, 1),
+ (35376, 1),
+ (35412, 1),
+ (35556, 1),
+ (35628, 1),
+ (35664, 1),
+ (35808, 1),
+ (36204, 1),
+ (36744, 1),
+ (37788, 1),
+ (39372, 1),
+ (40956, 1),
+ (41640, 1),
+ (41892, 1),
+ (42144, 1),
+ (42576, 1),
+ (42936, 1),
+ (43476, 1),
+ (45096, 1),
+ (47256, 1),
+ (47760, 1),
+ (47796, 1),
+ (47868, 1),
+ (48228, 1),
+ (48948, 1),
+ (49128, 1),
+ (49452, 1),
+ (49560, 1),
+ (49668, 1),
+ (49776, 1),
+ (50352, 1),
+ (50964, 1),
+ (52008, 1),
+ (53880, 1),
+ (55284, 1),
+ (55860, 1),
+ (56040, 1),
+ (56400, 1),
+ (56904, 1),
+ (57444, 1),
+ (59424, 1),
+ (60156, 1),
+ (60626, 1),
+ (60641, 1),
+ (61260, 1),
+ (62520, 1),
+ (64392, 1),
+ (65976, 1),
+ (67308, 1),
+ (68064, 1),
+ (68748, 1),
+ (69216, 1),
+ (69504, 1),
+ (69648, 1),
+ (69684, 1),
+ (69720, 1),
+ (69756, 1),
+ (69792, 1),
+ (69828, 1),
+ (70224, 1),
+ (70620, 1),
+ (71016, 1),
+ (71412, 1),
+ (71772, 1),
+ (71952, 1),
+ (72024, 1),
+ (72096, 1),
+ (72168, 1),
+ (72240, 1),
+ (72312, 1),
+ (72348, 1),
+ (72420, 1),
+ (72492, 1),
+ (72600, 1),
+ (72672, 1),
+ (72780, 1),
+ (72996, 1),
+ (73320, 1),
+ (73356, 1),
+ (73500, 1),
+ (73536, 1),
+ (73572, 1),
+ (73608, 1),
+ (73680, 1),
+ (73716, 1),
+ (73788, 1),
+ (73896, 1),
+ (74040, 1),
+ (74112, 1),
+ (74170, 1),
+ (74184, 1),
+ (74185, 1),
+ (74220, 1),
+ (74256, 1),
+ (74292, 1),
+ (74328, 1),
+ (74364, 1),
+ (74400, 1),
+ (74436, 1),
+ (74472, 1),
+ (74616, 1),
+ (74976, 1),
+ (75156, 1),
+ (75228, 1),
+ (75336, 1),
+ (75408, 1),
+ (75588, 1),
+ (75696, 1),
+ (75804, 1),
+ (75984, 1),
+ (76056, 1),
+ (76164, 1),
+ (76308, 1),
+ (76452, 1),
+ (76560, 1),
+ (76776, 1),
+ (76920, 1),
+ (77064, 1),
+ (77208, 1),
+ (77316, 1),
+ (77532, 1),
+ (77676, 1),
+ (77748, 1),
+ (77820, 1),
+ (77928, 1),
+ (78000, 1),
+ (78036, 1),
+ (78072, 1),
+ (78108, 1),
+ (78180, 1),
+ (78324, 1),
+ (78396, 1),
+ (78576, 1),
+ (78684, 1),
+ (78828, 1),
+ (78864, 1),
+ (78900, 1),
+ (78972, 1),
+ (79080, 1),
+ (79116, 1),
+ (79152, 1),
+ (79512, 1),
+ (79872, 1),
+ (80268, 1),
+ (80592, 1),
+ (80700, 1),
+ (80916, 1),
+ (81168, 1),
+ (81276, 1),
+ (81528, 1),
+ (81708, 1),
+ (81816, 1),
+ (81888, 1),
+ (82068, 1),
+ (82176, 1),
+ (82284, 1),
+ (82356, 1),
+ (82716, 1),
+ (83004, 1),
+ (83312, 1),
+ (83436, 1),
+ (83688, 1),
+ (83904, 1),
+ (84012, 1),
+ (84408, 1),
+ (84660, 1),
+ (85056, 1),
+ (85488, 1),
+ (85776, 1),
+ (85992, 1),
+ (86172, 1),
+ (86424, 1),
+ (86615, 1),
+ (86640, 1),
+ (86928, 1),
+ (87072, 1),
+ (87288, 1),
+ (87576, 1),
+ (87684, 1),
+ (87756, 1),
+ (87972, 1),
+ (88044, 1),
+ (88152, 1),
+ (88368, 1),
+ (88728, 1),
+ (88836, 1),
+ (88944, 1),
+ (89088, 1),
+ (89448, 1),
+ (89592, 1),
+ (89700, 1),
+ (89808, 1),
+ (89952, 1),
+ (90060, 1),
+ (90204, 1),
+ (90348, 1),
+ (90528, 1),
+ (90636, 1),
+ (90744, 1),
+ (90816, 1),
+ (91032, 1),
+ (91068, 1),
+ (91140, 1),
+ (91212, 1),
+ (91284, 1),
+ (91860, 1),
+ (92112, 1),
+ (92292, 1),
+ (92400, 1),
+ (92544, 1),
+ (92652, 1),
+ (92796, 1),
+ (92904, 1),
+ (92976, 1),
+ (93192, 1),
+ (93300, 1),
+ (93444, 1),
+ (93516, 1),
+ (93624, 1),
+ (93696, 1),
+ (93840, 1),
+ (93984, 1),
+ (94056, 1),
+ (94128, 1),
+ (94164, 1),
+ (94200, 1),
+ (94236, 1),
+ (94272, 1),
+ (94344, 1),
+ (94452, 1),
+ (94524, 1),
+ (94596, 1),
+ (94704, 1),
+ (94776, 1),
+ (94884, 1),
+ (94956, 1),
+ (95172, 1),
+ (95244, 1),
+ (95280, 1),
+ (95316, 1),
+ (95352, 1),
+ (95388, 1),
+ (95424, 1),
+ (95460, 1),
+ (95496, 1),
+ (95604, 1),
+ (95676, 1),
+ (95784, 1),
+ (95856, 1),
+ (95928, 1),
+ (96000, 1),
+ (96036, 1),
+ (96072, 1),
+ (96108, 1),
+ (96144, 1),
+ (96180, 1),
+ (96216, 1),
+ (96288, 1),
+ (96576, 1),
+ (98029, 1),
+ (98304, 1),
+ (98527, 1),
+ (98628, 1),
+ (99276, 1),
+ (99528, 1),
+ (99780, 1),
+ (99996, 1),
+ (100212, 1),
+ (100428, 1),
+ (100680, 1),
+ (100752, 1),
+ (100788, 1),
+ (100860, 1),
+ (100932, 1),
+ (101004, 1),
+ (101076, 1),
+ (101148, 1),
+ (101220, 1),
+ (101256, 1),
+ (101328, 1),
+ (101364, 1),
+ (101400, 1),
+ (101436, 1),
+ (101472, 1),
+ (101508, 1),
+ (101544, 1),
+ (101616, 1),
+ (101652, 1),
+ (101724, 1),
+ (101832, 1),
+ (101904, 1),
+ (101940, 1),
+ (101976, 1),
+ (102012, 1),
+ (102048, 1),
+ (102084, 1),
+ (102120, 1),
+ (102264, 1),
+ (102516, 1),
+ (102588, 1),
+ (102624, 1),
+ (102660, 1),
+ (102696, 1),
+ (102732, 1),
+ (102768, 1),
+ (102804, 1),
+ (102840, 1),
+ (102876, 1),
+ (102912, 1),
+ (102948, 1),
+ (102984, 1),
+ (103056, 1),
+ (103092, 1),
+ (103128, 1),
+ (103164, 1),
+ (103200, 1),
+ (103236, 1),
+ (103272, 1),
+ (103308, 1),
+ (103344, 1),
+ (103380, 1),
+ (103452, 1),
+ (103560, 1),
+ (103596, 1),
+ (103632, 1),
+ (103668, 1),
+ (103704, 1),
+ (103740, 1),
+ (103776, 1),
+ (103848, 1),
+ (103920, 1),
+ (103956, 1),
+ (104028, 1),
+ (104100, 1),
+ (104136, 1),
+ (104208, 1),
+ (104244, 1),
+ (104316, 1),
+ (104352, 1),
+ (104388, 1),
+ (104424, 1),
+ (104460, 1),
+ (104496, 1),
+ (104532, 1),
+ (104568, 1),
+ (104604, 1),
+ (104676, 1),
+ (104712, 1),
+ (104748, 1),
+ (104784, 1),
+ (104820, 1),
+ (104856, 1),
+ (104892, 1),
+ (104928, 1),
+ (104964, 1),
+ (105000, 1),
+ (105036, 1),
+ (105072, 1),
+ (105108, 1),
+ (105216, 1),
+ (105324, 1),
+ (105360, 1),
+ (105396, 1),
+ (105432, 1),
+ (105468, 1),
+ (105504, 1),
+ (105540, 1),
+ (105576, 1),
+ (105612, 1),
+ (105648, 1),
+ (105684, 1),
+ (105720, 1),
+ (105756, 1),
+ (105792, 1),
+ (105828, 1),
+ (105864, 1),
+ (105900, 1),
+ (105936, 1),
+ (110580, 1),
+ (115224, 1),
+ (118788, 1),
+ (121056, 1),
+ (121452, 1),
+ (121848, 1),
+ (122244, 1),
+ (122604, 1),
+ (122928, 1),
+ (123252, 1),
+ (123288, 1),
+ (123360, 1),
+ (123432, 1),
+ (123468, 1),
+ (123504, 1),
+ (123540, 1),
+ (123612, 1),
+ (123684, 1),
+ (123756, 1),
+ (123828, 1),
+ (123900, 1),
+ (123972, 1),
+ (124080, 1),
+ (124188, 1),
+ (124296, 1),
+ (124404, 1),
+ (124548, 1),
+ (124764, 1),
+ (124872, 1),
+ (124980, 1),
+ (125088, 1),
+ (125196, 1),
+ (125304, 1),
+ (125412, 1),
+ (125448, 1),
+ (125520, 1),
+ (125628, 1),
+ (125700, 1),
+ (125772, 1),
+ (125844, 1),
+ (125880, 1),
+ (125916, 1),
+ (125952, 1),
+ (125988, 1),
+ (126024, 1),
+ (126060, 1),
+ (126096, 1),
+ (126168, 1),
+ (126276, 1),
+ (126312, 1),
+ (126348, 1),
+ (126420, 1),
+ (126492, 1),
+ (126564, 1),
+ (126636, 1),
+ (126708, 1),
+ (126780, 1),
+ (126852, 1),
+ (126960, 1),
+ (127068, 1),
+ (127176, 1),
+ (127212, 1),
+ (127248, 1),
+ (127284, 1),
+ (127320, 1),
+ (127356, 1),
+ (127392, 1),
+ (127464, 1),
+ (127536, 1),
+ (127608, 1),
+ (127644, 1),
+ (127680, 1),
+ (127716, 1),
+ (127788, 1),
+ (127860, 1),
+ (127932, 1),
+ (128004, 1),
+ (128076, 1),
+ (128148, 1),
+ (128220, 1),
+ (128256, 1),
+ (128292, 1),
+ (128328, 1),
+ (128364, 1),
+ (128400, 1),
+ (128436, 1),
+ (128472, 1),
+ (128508, 1),
+ (128544, 1),
+ (128580, 1),
+ (128616, 1),
+ (128652, 1),
+ (128688, 1),
+ (128724, 1),
+ (128760, 1),
+ (128832, 1),
+ (128904, 1),
+ (128976, 1),
+ (129048, 1),
+ (129120, 1),
+ (129192, 1),
+ (129228, 1),
+ (129264, 1),
+ (129300, 1),
+ (129372, 1),
+ (129408, 1),
+ (129444, 1),
+ (129480, 1),
+ (129516, 1),
+ (129552, 1),
+ (129588, 1),
+ (129660, 1),
+ (129732, 1),
+ (129768, 1),
+ (129804, 1),
+ (129840, 1),
+ (129876, 1),
+ (129912, 1),
+ (129948, 1),
+ (129984, 1),
+ (130020, 1),
+ (130056, 1),
+ (130128, 1),
+ (130200, 1),
+ (130236, 1),
+ (130272, 1),
+ (130308, 1),
+ (130380, 1),
+ (130452, 1),
+ (130524, 1),
+ (130560, 1),
+ (130596, 1),
+ (130632, 1),
+ (130668, 1),
+ (130704, 1),
+ (130776, 1),
+ (130812, 1),
+ (130848, 1),
+ (130920, 1),
+ (130992, 1),
+ (131064, 1),
+ (131136, 1),
+ (131172, 1),
+ (131208, 1),
+ (131244, 1),
+ (131316, 1),
+ (131388, 1),
+ (131424, 1),
+ (131532, 1),
+ (131640, 1),
+ (131784, 1),
+ (131892, 1),
+ (131964, 1),
+ (132036, 1),
+ (132108, 1),
+ (132180, 1),
+ (132252, 1),
+ (132324, 1),
+ (132360, 1),
+ (132432, 1),
+ (132504, 1),
+ (132576, 1),
+ (132684, 1),
+ (132792, 1),
+ (132900, 1),
+ (132972, 1),
+ (133044, 1),
+ (133116, 1),
+ (133188, 1),
+ (133260, 1),
+ (133332, 1),
+ (133368, 1),
+ (133404, 1),
+ (133440, 1),
+ (133476, 1),
+ (133512, 1),
+ (133548, 1),
+ (133620, 1),
+ (133692, 1),
+ (133764, 1),
+ (133836, 1),
+ (133908, 1),
+ (133980, 1),
+ (134016, 1),
+ (134052, 1),
+ (134088, 1),
+ (134124, 1),
+ (134160, 1),
+ (134196, 1),
+ (134232, 1),
+ (134268, 1),
+ (134304, 1),
+ (134340, 1),
+ (134376, 1),
+ (134412, 1),
+ (134484, 1),
+ (134592, 1),
+ (134700, 1),
+ (134808, 1),
+ (134916, 1),
+ (134988, 1),
+ (135024, 1),
+ (135060, 1),
+ (135096, 1),
+ (135132, 1),
+ (135168, 1),
+ (135204, 1),
+ (135240, 1),
+ (135276, 1),
+ (135312, 1),
+ (135348, 1),
+ (135384, 1),
+ (135456, 1),
+ (135492, 1),
+ (135528, 1),
+ (135564, 1),
+ (135600, 1),
+ (135636, 1),
+ (135672, 1),
+ (135708, 1),
+ (135744, 1),
+ (135780, 1),
+ (135816, 1),
+ (135852, 1),
+ (135888, 1),
+ (135924, 1),
+ (135960, 1),
+ (135996, 1),
+ (136032, 1),
+ (136068, 1),
+ (136140, 1),
+ (136212, 1),
+ (136284, 1),
+ (136356, 1),
+ (136428, 1),
+ (136500, 1),
+ (136572, 1),
+ (136608, 1),
+ (136644, 1),
+ (136680, 1),
+ (136716, 1),
+ (136752, 1),
+ (136788, 1),
+ (136824, 1),
+ (136860, 1),
+ (136896, 1),
+ (136932, 1),
+ (136968, 1),
+ (137004, 1),
+ (137040, 1),
+ (137076, 1),
+ (137112, 1),
+ (137148, 1),
+ (137184, 1),
+ (137256, 1),
+ (137328, 1),
+ (137400, 1),
+ (137472, 1),
+ (137544, 1),
+ (137580, 1),
+ (137616, 1),
+ (137652, 1),
+ (137688, 1),
+ (137724, 1),
+ (137796, 1),
+ (137832, 1),
+ (137868, 1),
+ (137904, 1),
+ (137940, 1),
+ (137976, 1),
+ (138012, 1),
+ (138048, 1),
+ (138084, 1),
+ (138120, 1),
+ (138228, 1),
+ (138300, 1),
+ (138336, 1),
+ (138372, 1),
+ (138408, 1),
+ (138444, 1),
+ (138480, 1),
+ (138516, 1),
+ (138552, 1),
+ (138588, 1),
+ (138624, 1),
+ (138696, 1),
+ (138768, 1),
+ (138840, 1),
+ (138912, 1),
+ (138948, 1),
+ (138984, 1),
+ (139020, 1),
+ (139056, 1),
+ (139092, 1),
+ (139128, 1),
+ (139164, 1),
+ (139200, 1),
+ (139272, 1),
+ (139308, 1),
+ (139380, 1),
+ (139452, 1),
+ (139488, 1),
+ (139524, 1),
+ (139596, 1),
+ (139632, 1),
+ (139668, 1),
+ (139704, 1),
+ (139740, 1),
+ (139776, 1),
+ (139848, 1),
+ (139884, 1),
+ (139920, 1),
+ (139956, 1),
+ (139992, 1),
+ (140028, 1),
+ (140064, 1),
+ (140136, 1),
+ (140172, 1),
+ (140208, 1),
+ (140244, 1),
+ (140280, 1),
+ (140316, 1),
+ (140352, 1),
+ (140424, 1),
+ (140460, 1),
+ (140496, 1),
+ (140532, 1),
+ (140604, 1),
+ (140640, 1),
+ (140676, 1),
+ (140712, 1),
+ (140748, 1),
+ (140784, 1),
+ (140820, 1),
+ (140856, 1),
+ (140928, 1),
+ (141036, 1),
+ (141072, 1),
+ (141108, 1),
+ (141144, 1),
+ (141180, 1),
+ (141216, 1),
+ (141252, 1),
+ (141324, 1),
+ (141396, 1),
+ (141432, 1),
+ (141468, 1),
+ (141504, 1),
+ (141612, 1),
+ (142152, 1),
+ (142188, 1),
+ (142260, 1),
+ (142296, 1),
+ (142800, 1),
+ (143304, 1),
+ (143376, 1),
+ (143448, 1),
+ (143520, 1),
+ (143592, 1),
+ (143664, 1),
+ (143700, 1),
+ (143736, 1),
+ (143772, 1),
+ (143808, 1),
+ (143844, 1),
+ (143880, 1),
+ (143952, 1),
+ (144096, 1),
+ (144240, 1),
+ (144348, 1),
+ (144456, 1),
+ (144564, 1),
+ (144672, 1),
+ (144708, 1),
+ (144744, 1),
+ (144780, 1),
+ (144816, 1),
+ (144852, 1),
+ (144888, 1),
+ (144924, 1),
+ (144960, 1),
+ (144996, 1),
+ (145032, 1),
+ (145068, 1),
+ (145104, 1),
+ (145140, 1),
+ (145176, 1),
+ (145212, 1),
+ (145248, 1),
+ (145284, 1),
+ (145320, 1),
+ (145356, 1),
+ (145392, 1),
+ (145464, 1),
+ (145500, 1),
+ (145536, 1),
+ (145572, 1),
+ (145644, 1),
+ (145716, 1),
+ (145752, 1),
+ (145788, 1),
+ (145824, 1),
+ (145860, 1),
+ (145896, 1),
+ (145932, 1),
+ (145968, 1),
+ (146004, 1),
+ (146040, 1),
+ (146076, 1),
+ (146112, 1),
+ (146148, 1),
+ (146184, 1),
+ (146220, 1),
+ (146256, 1),
+ (146292, 1),
+ (146328, 1),
+ (146364, 1),
+ (146400, 1),
+ (146436, 1),
+ (146472, 1),
+ (146508, 1),
+ (146544, 1),
+ (146580, 1),
+ (146616, 1),
+ (146652, 1),
+ (146688, 1),
+ (146724, 1),
+ (146760, 1),
+ (146796, 1),
+ (146832, 1),
+ (146868, 1),
+ (146940, 1),
+ (146976, 1),
+ (147012, 1),
+ (147048, 1),
+ (147084, 1),
+ (147120, 1),
+ (147156, 1),
+ (147192, 1),
+ (147228, 1),
+ (147264, 1),
+ (147300, 1),
+ (147336, 1),
+ (147372, 1),
+ (147408, 1),
+ (147444, 1),
+ (147480, 1),
+ (147516, 1),
+ (147552, 1),
+ (147588, 1),
+ (147624, 1),
+ (147660, 1),
+ (147732, 1),
+ (147768, 1),
+ (147804, 1),
+ (147840, 1),
+ (147876, 1),
+ (147912, 1),
+ (147948, 1),
+ (147984, 1),
+ (148020, 1),
+ (148056, 1),
+ (148092, 1),
+ (148128, 1),
+ (148164, 1),
+ (148200, 1),
+ (148236, 1),
+ (148272, 1),
+ (1070556, 1),
+ (1079378, 1),
+ (1085421, 1),
+ (1086835, 1),
+ (1121118, 1),
+ (1121208, 1),
+ (1124515, 1),
+ (1128287, 1),
+ (1128379, 1),
+ (1153308, 1),
+ (1153342, 4),
+ (1153344, 5),
+ (1153398, 1),
+ (1153571, 1),
+ (1153663, 1),
+ (1153670, 1),
+ (1153672, 3),
+ (1153688, 3),
+ (1154504, 1),
+ (1154538, 5),
+ (1154540, 6),
+ (1154596, 1),
+ (1164963, 1),
+ (1165053, 1),
+ (1166494, 1),
+ (1166586, 1),
+ (1175528, 1),
+ (1175636, 1),
+ (1177016, 1),
+ (1193653, 1),
+ (1193743, 1),
+ (1205060, 1),
+ (1205152, 1),
+ (1323322, 1),
+ (1323414, 1),
+ (1336354, 1),
+ (1336444, 1),
+ (1348925, 1),
+ (1349015, 1),
+ (1353326, 1),
+ (1353418, 1),
+ (1426757, 1),
+ (1426845, 1),
+ (1426847, 1),
+ (1426937, 1),
+ (1476463, 1),
+ (1476553, 1),
+ (1516580, 1),
+ (1516670, 1),
+ (1605731, 1),
+ (1605821, 1),
+];
\ No newline at end of file
diff --git a/bin/node/bench/src/tempdb.rs b/bin/node/bench/src/tempdb.rs
new file mode 100644
index 0000000000000000000000000000000000000000..4020fd1029368209c71c2a1d5ce59bc6a0c140a3
--- /dev/null
+++ b/bin/node/bench/src/tempdb.rs
@@ -0,0 +1,136 @@
+// This file is part of Substrate.
+
+// Copyright (C) 2020 Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use std::{io, sync::Arc};
+use kvdb::{KeyValueDB, DBTransaction};
+use kvdb_rocksdb::{DatabaseConfig, Database};
+
+#[derive(Debug, Clone, Copy, derive_more::Display)]
+pub enum DatabaseType {
+ RocksDb,
+ ParityDb,
+}
+
+pub struct TempDatabase(tempfile::TempDir);
+
+struct ParityDbWrapper(parity_db::Db);
+parity_util_mem::malloc_size_of_is_0!(ParityDbWrapper);
+
+impl KeyValueDB for ParityDbWrapper {
+ /// Get a value by key.
+ fn get(&self, col: u32, key: &[u8]) -> io::Result