From 5e9d676a4547a0dceb6d006ed8237184fb0efed7 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 22 Mar 2018 02:17:30 +0100 Subject: [PATCH 01/18] CLI options and keystore integration --- polkadot/cli/src/cli.yml | 43 +++++++++++++++++++--- polkadot/cli/src/lib.rs | 61 +++++++++++++++++++++++++------ polkadot/consensus/src/service.rs | 10 +++-- polkadot/keystore/src/lib.rs | 22 ++++++++++- polkadot/service/src/config.rs | 4 +- polkadot/service/src/error.rs | 7 +--- polkadot/service/src/lib.rs | 30 +++++++++++---- substrate/ed25519/src/lib.rs | 20 +++++++++- 8 files changed, 161 insertions(+), 36 deletions(-) diff --git a/polkadot/cli/src/cli.yml b/polkadot/cli/src/cli.yml index 96679a6835425..6d30326b6b11d 100644 --- a/polkadot/cli/src/cli.yml +++ b/polkadot/cli/src/cli.yml @@ -4,15 +4,48 @@ about: Polkadot Node Rust Implementation args: - log: short: l + long: log value_name: LOG_PATTERN help: Sets a custom logging filter takes_value: true + - base-path: + long: base-path + short: d + value_name: PATH + help: Specify custom base path + takes_value: true - keystore-path: - value_name: KEYSTORE_PATH - help: specify custom keystore path + long: keystore-path + value_name: PATH + help: Specify custom keystore path + takes_value: true + - key: + long: key + value_name: STRING + help: Specify additional key seed takes_value: true -subcommands: - collator: - about: Run collator node + long: collator + help: Enable collator mode + takes_value: false - validator: - about: Run validator node + long: validator + help: Enable validator mode + takes_value: false + - port: + long: port + value_name: PORT + help: Specify p2p protocol TCP port + takes_value: true + - rpc-port: + long: rpc-port + value_name: PORT + help: Specify RPC server TCP port + takes_value: true + - bootnodes: + long: bootnodes + value_name: URL + help: Specify a list of bootnodes + takes_value: true + multiple: true +subcommands: diff --git a/polkadot/cli/src/lib.rs b/polkadot/cli/src/lib.rs index 5c0492af01f0d..72a66b8ef558a 100644 --- a/polkadot/cli/src/lib.rs +++ b/polkadot/cli/src/lib.rs @@ -42,6 +42,7 @@ extern crate log; pub mod error; use std::path::{Path, PathBuf}; +use std::net::SocketAddr; /// Parse command line arguments and start the node. /// @@ -56,7 +57,15 @@ pub fn run(args: I) -> error::Result<()> where T: Into + Clone, { let yaml = load_yaml!("./cli.yml"); - let matches = clap::App::from_yaml(yaml).version(crate_version!()).get_matches_from_safe(args)?; + let matches = match clap::App::from_yaml(yaml).version(crate_version!()).get_matches_from_safe(args) { + Ok(m) => m, + Err(ref e) if e.kind == clap::ErrorKind::VersionDisplayed => return Ok(()), + Err(ref e) if e.kind == clap::ErrorKind::HelpDisplayed || e.kind == clap::ErrorKind::VersionDisplayed => { + let _ = clap::App::from_yaml(yaml).print_long_help(); + return Ok(()); + } + Err(e) => return Err(e.into()), + }; // TODO [ToDr] Split parameters parsing from actual execution. let log_pattern = matches.value_of("log").unwrap_or(""); @@ -64,38 +73,68 @@ pub fn run(args: I) -> error::Result<()> where let mut config = service::Configuration::default(); + let base_path = matches.value_of("base-path") + .map(|x| Path::new(x).to_owned()) + .unwrap_or_else(default_base_path); + config.keystore_path = matches.value_of("keystore") .map(|x| Path::new(x).to_owned()) - .unwrap_or_else(default_keystore_path) + .unwrap_or_else(|| keystore_path(&base_path)) .to_string_lossy() .into(); let mut role = service::Role::FULL; - if let Some(_) = matches.subcommand_matches("collator") { + if matches.is_present("collator") { info!("Starting collator."); role = service::Role::COLLATOR; } - else if let Some(_) = matches.subcommand_matches("validator") { + else if matches.is_present("validator") { info!("Starting validator."); role = service::Role::VALIDATOR; } config.roles = role; + config.network.boot_nodes = matches + .values_of("bootnodes") + .map_or(Default::default(), |v| v.map(|n| n.to_owned()).collect()); + config.network.config_path = Some(network_path(&base_path).to_string_lossy().into()); + config.network.net_config_path = config.network.config_path.clone(); + + let port = match matches.value_of("port") { + Some(port) => port.parse().expect("Invalid p2p port value specified."), + None => 30333, + }; + config.network.listen_address = Some(SocketAddr::new("0.0.0.0".parse().unwrap(), port)); + + config.keys = matches.values_of("key").unwrap_or_default().map(str::to_owned).collect(); let service = service::Service::new(config)?; - let address = "127.0.0.1:9933".parse().unwrap(); + let mut address: SocketAddr = "127.0.0.1:9933".parse().unwrap(); + if let Some(port) = matches.value_of("rpc-port") { + let rpc_port: u16 = port.parse().expect("Invalid RPC port value specified."); + address.set_port(rpc_port); + } let handler = rpc::rpc_handler(service.client()); let server = rpc::start_http(&address, handler)?; server.wait(); - println!("No command given.\n"); - let _ = clap::App::from_yaml(yaml).print_long_help(); - Ok(()) } -fn default_keystore_path() -> PathBuf { +fn keystore_path(base_path: &Path) -> PathBuf { + let mut path = base_path.to_owned(); + path.push("keystore"); + path +} + +fn network_path(base_path: &Path) -> PathBuf { + let mut path = base_path.to_owned(); + path.push("network"); + path +} + +fn default_base_path() -> PathBuf { use app_dirs::{AppInfo, AppDataType}; let app_info = AppInfo { @@ -103,13 +142,11 @@ fn default_keystore_path() -> PathBuf { author: "Parity Technologies", }; - app_dirs::get_app_dir( + app_dirs::get_app_root( AppDataType::UserData, &app_info, - "keystore", ).expect("app directories exist on all supported platforms; qed") } - fn init_logger(pattern: &str) { let mut builder = env_logger::LogBuilder::new(); // Disable info logging by default for some modules: diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index 288f7a7d839a5..d481dd7d1b510 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -26,7 +26,6 @@ use parking_lot::Mutex; use substrate_network as net; use tokio_core::reactor; use client::BlockchainEvents; -use substrate_keyring::Keyring; use primitives::{Hash, AuthorityId}; use primitives::block::{Id as BlockId, HeaderHash, Header}; use polkadot_primitives::parachain::{BlockData, Extrinsic, CandidateReceipt}; @@ -136,14 +135,19 @@ struct Network(Arc); impl Service { /// Create and start a new instance. - pub fn new(client: Arc, network: Arc, transaction_pool: Arc>, best_header: &Header) -> Service + pub fn new( + client: Arc, + network: Arc, + transaction_pool: Arc>, + key: ed25519::Pair, + best_header: &Header) -> Service where C: BlockchainEvents + bft::BlockImport + bft::Authorities + PolkadotApi + Send + Sync + 'static { let best_header = best_header.clone(); let thread = thread::spawn(move || { let mut core = reactor::Core::new().expect("tokio::Core could not be created"); - let key = Arc::new(Keyring::One.into()); + let key = Arc::new(key); let factory = ProposerFactory { client: client.clone(), transaction_pool: transaction_pool.clone(), diff --git a/polkadot/keystore/src/lib.rs b/polkadot/keystore/src/lib.rs index ece74d0021a6e..8bfa703988891 100644 --- a/polkadot/keystore/src/lib.rs +++ b/polkadot/keystore/src/lib.rs @@ -33,6 +33,7 @@ extern crate error_chain; #[cfg(test)] extern crate tempdir; +use std::collections::HashMap; use std::path::PathBuf; use std::fs::{self, File}; use std::io::{self, Write}; @@ -120,16 +121,19 @@ impl EncryptedKey { } } +type Seed = [u8; 32]; + /// Key store. pub struct Store { path: PathBuf, + additional: HashMap, } impl Store { /// Create a new store at the given path. pub fn open(path: PathBuf) -> Result { fs::create_dir_all(&path)?; - Ok(Store { path }) + Ok(Store { path, additional: HashMap::new() }) } /// Generate a new key, placing it into the store. @@ -145,8 +149,22 @@ impl Store { Ok(pair) } + /// Create a new key from seed. Do not place it into the store. + pub fn generate_from_seed(&mut self, seed: &str) -> Result { + let mut s: [u8; 32] = [' ' as u8; 32]; + let len = ::std::cmp::min(32, seed.len()); + &mut s[..len].copy_from_slice(&seed.as_bytes()[..len]); + let pair = Pair::from_seed(&s); + self.additional.insert(pair.public(), s); + Ok(pair) + } + /// Load a key file with given public key. pub fn load(&self, public: &Public, password: &str) -> Result { + if let Some(ref seed) = self.additional.get(public) { + let pair = Pair::from_seed(seed); + return Ok(pair); + } let path = self.key_file_path(public); let file = File::open(path)?; @@ -158,7 +176,7 @@ impl Store { /// Get public keys of all stored keys. pub fn contents(&self) -> Result> { - let mut public_keys = Vec::new(); + let mut public_keys: Vec = self.additional.keys().cloned().collect(); for entry in fs::read_dir(&self.path)? { let entry = entry?; let path = entry.path(); diff --git a/polkadot/service/src/config.rs b/polkadot/service/src/config.rs index 6b87d0e49bacf..bea6b5545703c 100644 --- a/polkadot/service/src/config.rs +++ b/polkadot/service/src/config.rs @@ -30,7 +30,8 @@ pub struct Configuration { pub network: NetworkConfiguration, /// Path to key files. pub keystore_path: String, - // TODO: add more network, client, tx pool configuration options + /// Additional key seeds. + pub keys: Vec, } impl Default for Configuration { @@ -40,6 +41,7 @@ impl Default for Configuration { transaction_pool: Default::default(), network: Default::default(), keystore_path: Default::default(), + keys: Default::default(), } } } diff --git a/polkadot/service/src/error.rs b/polkadot/service/src/error.rs index 58bd8d633bcf0..fbb6981407df8 100644 --- a/polkadot/service/src/error.rs +++ b/polkadot/service/src/error.rs @@ -18,18 +18,15 @@ use client; use network; +use keystore; error_chain! { links { Client(client::error::Error, client::error::ErrorKind) #[doc="Client error"]; Network(network::error::Error, network::error::ErrorKind) #[doc="Network error"]; + Keystore(keystore::Error, keystore::ErrorKind) #[doc="Keystore error"]; } errors { - /// Key store errors - Keystore(e: ::keystore::Error) { - description("Keystore error"), - display("Keystore error: {:?}", e), - } } } diff --git a/polkadot/service/src/lib.rs b/polkadot/service/src/lib.rs index 6bf972878d208..d3daac84ca849 100644 --- a/polkadot/service/src/lib.rs +++ b/polkadot/service/src/lib.rs @@ -56,7 +56,6 @@ use transaction_pool::TransactionPool; use substrate_keyring::Keyring; use substrate_executor::NativeExecutor; use polkadot_executor::Executor as LocalDispatch; -use polkadot_primitives::AccountId; use keystore::Store as Keystore; use polkadot_api::PolkadotApi; use polkadot_runtime::genesismap::{additional_storage_with_genesis, GenesisConfig}; @@ -126,12 +125,27 @@ impl Service { // Create client let executor = polkadot_executor::Executor::new(); let mut storage = Default::default(); - let key: AccountId = Keyring::One.into(); + + let mut keystore = Keystore::open(config.keystore_path.into())?; + for seed in &config.keys { + keystore.generate_from_seed(seed)?; + } + + if keystore.contents()?.is_empty() { + let key = keystore.generate("")?; + info!("Generated a new keypair: {:?}", key.public()); + } let genesis_config = GenesisConfig { - validators: vec![key.clone()], - authorities: vec![key.clone()], - balances: vec![(Keyring::One.into(), 1u64 << 63), (Keyring::Two.into(), 1u64 << 63)].into_iter().collect(), + validators: vec![Keyring::Alice.into(), Keyring::Bob.into(), Keyring::Charlie.into()], + authorities: vec![Keyring::Alice.into(), Keyring::Bob.into(), Keyring::Charlie.into()], + balances: vec![ + (Keyring::One.into(), 1u64 << 63), + (Keyring::Two.into(), 1u64 << 63), + (Keyring::Alice.into(), 1u64 << 63), + (Keyring::Bob.into(), 1u64 << 63), + (Keyring::Charlie.into(), 1u64 << 63), + ].into_iter().collect(), block_time: 5, // 5 second block time. session_length: 720, // that's 1 hour per session. sessions_per_era: 24, // 24 hours per era. @@ -145,7 +159,6 @@ impl Service { (primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect()) }; - let _keystore = Keystore::open(config.keystore_path.into()).map_err(::error::ErrorKind::Keystore)?; let client = Arc::new(client::new_in_mem(executor, prepare_genesis)?); let best_header = client.header(&BlockId::Hash(client.info()?.chain.best_hash))?.expect("Best header always exists; qed"); info!("Starting Polkadot. Best block is #{}", best_header.number); @@ -166,7 +179,10 @@ impl Service { // Spin consensus service if configured let consensus_service = if config.roles & Role::VALIDATOR == Role::VALIDATOR { - Some(consensus::Service::new(client.clone(), network.clone(), transaction_pool, &best_header)) + // Load the first available key. Code above makes sure it exisis. + let key = keystore.load(&keystore.contents()?[0], "")?; + info!("Using authority key {:?}", key.public()); + Some(consensus::Service::new(client.clone(), network.clone(), transaction_pool, key, &best_header)) } else { None }; diff --git a/substrate/ed25519/src/lib.rs b/substrate/ed25519/src/lib.rs index 87085eddbfe87..390caa46c46a0 100644 --- a/substrate/ed25519/src/lib.rs +++ b/substrate/ed25519/src/lib.rs @@ -55,12 +55,18 @@ pub fn verify>(sig: &[u8], message: &[u8], public: P) -> bool { } /// A public key. -#[derive(PartialEq, Eq, Clone, Debug)] +#[derive(PartialEq, Eq, Clone)] pub struct Public(pub [u8; 32]); /// A key pair. pub struct Pair(signature::Ed25519KeyPair); +impl ::std::hash::Hash for Public { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + impl Public { /// A new instance from the given 32-byte `data`. pub fn from_raw(data: [u8; 32]) -> Self { @@ -122,6 +128,18 @@ impl AsRef for Pair { } } +impl ::std::fmt::Display for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", ::primitives::hexdisplay::HexDisplay::from(&self.0)) + } +} + +impl ::std::fmt::Debug for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", ::primitives::hexdisplay::HexDisplay::from(&self.0)) + } +} + impl Pair { /// Generate new secure (random) key pair, yielding it and the corresponding pkcs#8 bytes. pub fn generate_with_pkcs8() -> (Self, [u8; PKCS_LEN]) { From ab02d2cbe10fc880110128a0502216cffe35bf04 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 2 Apr 2018 15:05:30 +0200 Subject: [PATCH 02/18] Replace multiqueue with future::mpsc --- Cargo.lock | 64 +++--------------------------- polkadot/cli/Cargo.toml | 2 +- polkadot/cli/src/lib.rs | 2 +- substrate/client/Cargo.toml | 2 +- substrate/client/src/client.rs | 26 +++++------- substrate/client/src/lib.rs | 2 +- substrate/network/Cargo.toml | 1 - substrate/network/src/consensus.rs | 56 +++++++++++++------------- substrate/network/src/lib.rs | 1 - substrate/network/src/protocol.rs | 7 ++-- substrate/network/src/service.rs | 13 +++--- 11 files changed, 54 insertions(+), 122 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0280232818aa1..ba3b922964920 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,8 +17,8 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "app_dirs" -version = "1.1.1" +name = "app_dirs2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -182,11 +182,6 @@ name = "constant_time_eq" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "crossbeam" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "crossbeam" version = "0.3.2" @@ -954,18 +949,6 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "multiqueue" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "net2" version = "0.2.31" @@ -1010,11 +993,6 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "owning_ref" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "owning_ref" version = "0.3.3" @@ -1043,16 +1021,6 @@ dependencies = [ "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "thread-id 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot" version = "0.4.8" @@ -1144,7 +1112,7 @@ dependencies = [ name = "polkadot-cli" version = "0.1.0" dependencies = [ - "app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "app_dirs2 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519 0.1.0", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1615,11 +1583,6 @@ name = "smallvec" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "smallvec" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "smallvec" version = "0.4.4" @@ -1680,9 +1643,9 @@ version = "0.1.0" dependencies = [ "ed25519 0.1.0", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "multiqueue 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-bft 0.1.0", "substrate-codec 0.1.0", @@ -1757,7 +1720,6 @@ dependencies = [ "ethcore-network 1.9.0 (git+https://github.com/paritytech/parity.git)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "multiqueue 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1953,16 +1915,6 @@ dependencies = [ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread-id" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.3.5" @@ -2256,7 +2208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7d1c0d48a81bbb13043847f957971f4d87c81542d80ece5e84ba3cba4058fd4" +"checksum app_dirs2 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0aa02944d8a100b79057d1619032b1ad39de5eed6567cdeccbd53908b326e082" "checksum arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e772942dccdf11b368c31e044e4fca9189f80a773d2f0808379de65894cbf57" @@ -2276,7 +2228,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b8f59bcebcfe4269b09f71dab0da15b355c75916a8f975d3876ce81561893ee" "checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" @@ -2348,18 +2299,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" "checksum mio 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "7da01a5e23070d92d99b1ecd1cd0af36447c6fd44b0fe283c2db199fa136724f" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum multiqueue 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4059673f3516669cbf7ebb448cb37171559ed22e6d8bc79cf0cf9394cf9e73fd" "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-traits 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "9936036cc70fe4a8b2d338ab665900323290efb03983c86cbe235ae800ad8017" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -"checksum owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d52571ddcb42e9c900c901a18d8d67e393df723fcd51dd59c5b1a85d0acb6cc" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)" = "235801e9531998c4bb307f4ea6833c9f40a4cf132895219ac8c2cd25a9b310f7" "checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693" -"checksum parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fa12d706797d42551663426a45e2db2e0364bd1dbf6aeada87e89c5f981f43e9" "checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" "checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412" "checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8" @@ -2404,7 +2352,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" -"checksum smallvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4f8266519bc1d17d0b5b16f6c21295625d562841c708f6376f49028a43e9c11e" "checksum smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4f357e8cd37bf8822e1b964e96fd39e2cb5a0424f8aaa284ccaccc2162411c" "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" "checksum snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "" @@ -2419,7 +2366,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" -"checksum thread-id 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2af4d6289a69a35c4d3aea737add39685f2784122c28119a7713165a63d68c9d" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0" diff --git a/polkadot/cli/Cargo.toml b/polkadot/cli/Cargo.toml index 232c105f6f7bd..a1ae67c3b62d5 100644 --- a/polkadot/cli/Cargo.toml +++ b/polkadot/cli/Cargo.toml @@ -12,7 +12,7 @@ log = "0.3" hex-literal = "0.1" triehash = "0.1" ed25519 = { path = "../../substrate/ed25519" } -app_dirs = "1.1" +app_dirs2 = "2.0" substrate-client = { path = "../../substrate/client" } substrate-codec = { path = "../../substrate/codec" } substrate-runtime-io = { path = "../../substrate/runtime-io" } diff --git a/polkadot/cli/src/lib.rs b/polkadot/cli/src/lib.rs index 72a66b8ef558a..5b7a49baaebd0 100644 --- a/polkadot/cli/src/lib.rs +++ b/polkadot/cli/src/lib.rs @@ -18,7 +18,7 @@ #![warn(missing_docs)] -extern crate app_dirs; +extern crate app_dirs2 as app_dirs; extern crate env_logger; extern crate ed25519; extern crate triehash; diff --git a/substrate/client/Cargo.toml b/substrate/client/Cargo.toml index e398af6743ab1..5d0f1d45752a3 100644 --- a/substrate/client/Cargo.toml +++ b/substrate/client/Cargo.toml @@ -9,7 +9,7 @@ log = "0.3" parking_lot = "0.4" triehash = "0.1" hex-literal = "0.1" -multiqueue = "0.3" +futures = "0.1.17" ed25519 = { path = "../ed25519" } substrate-bft = { path = "../bft" } substrate-codec = { path = "../codec" } diff --git a/substrate/client/src/client.rs b/substrate/client/src/client.rs index ecdb3690621c1..4b803486c006d 100644 --- a/substrate/client/src/client.rs +++ b/substrate/client/src/client.rs @@ -16,7 +16,7 @@ //! Substrate Client -use multiqueue; +use futures::sync::mpsc; use parking_lot::Mutex; use primitives::{self, block, AuthorityId}; use primitives::block::Id as BlockId; @@ -30,17 +30,13 @@ use blockchain::{self, Info as ChainInfo, Backend as ChainBackend}; use {error, in_mem, block_builder, runtime_io, bft}; /// Type that implements `futures::Stream` of block import events. -pub type BlockchainEventStream = multiqueue::BroadcastFutReceiver; - -//TODO: The queue is preallocated in multiqueue. Make it unbounded -const NOTIFICATION_QUEUE_SIZE: u64 = 1 << 16; +pub type BlockchainEventStream = mpsc::UnboundedReceiver; /// Polkadot Client pub struct Client where B: backend::Backend { backend: B, executor: E, - import_notification_sink: Mutex>, - import_notification_stream: Mutex>, + import_notification_sinks: Mutex>>, } /// A source of blockchain evenets. @@ -165,7 +161,6 @@ impl Client where where F: FnOnce() -> (block::Header, Vec<(Vec, Vec)>) { - let (sink, stream) = multiqueue::broadcast_fut_queue(NOTIFICATION_QUEUE_SIZE); if backend.blockchain().header(BlockId::Number(0))?.is_none() { trace!("Empty database, writing genesis block"); let (genesis_header, genesis_store) = build_genesis(); @@ -177,8 +172,7 @@ impl Client where Ok(Client { backend, executor, - import_notification_sink: Mutex::new(sink), - import_notification_stream: Mutex::new(stream), + import_notification_sinks: Mutex::new(Vec::new()), }) } @@ -212,9 +206,7 @@ impl Client where /// Close notification streams. pub fn stop_notifications(&self) { - let (sink, stream) = multiqueue::broadcast_fut_queue(NOTIFICATION_QUEUE_SIZE); - *self.import_notification_sink.lock() = sink; - *self.import_notification_stream.lock() = stream; + self.import_notification_sinks.lock().clear(); } /// Get the current set of authorities from storage. @@ -325,9 +317,7 @@ impl Client where header: header, is_new_best: is_new_best, }; - if let Err(e) = self.import_notification_sink.lock().try_send(notification) { - warn!("Error queueing block import notification: {:?}", e); - } + self.import_notification_sinks.lock().retain(|sink| !sink.unbounded_send(notification.clone()).is_err()); } Ok(ImportResult::Queued) @@ -424,7 +414,9 @@ impl BlockchainEvents for Client { /// Get block import event stream. fn import_notification_stream(&self) -> BlockchainEventStream { - self.import_notification_stream.lock().add_stream() + let (sink, stream) = mpsc::unbounded(); + self.import_notification_sinks.lock().push(sink); + stream } } diff --git a/substrate/client/src/lib.rs b/substrate/client/src/lib.rs index a5483b8c1398d..7feede0491b0e 100644 --- a/substrate/client/src/lib.rs +++ b/substrate/client/src/lib.rs @@ -31,7 +31,7 @@ extern crate ed25519; extern crate triehash; extern crate parking_lot; -extern crate multiqueue; +extern crate futures; #[cfg(test)] #[macro_use] extern crate hex_literal; #[macro_use] extern crate error_chain; #[macro_use] extern crate log; diff --git a/substrate/network/Cargo.toml b/substrate/network/Cargo.toml index fec62305871ec..162e2d9b8443d 100644 --- a/substrate/network/Cargo.toml +++ b/substrate/network/Cargo.toml @@ -17,7 +17,6 @@ serde = "1.0" serde_derive = "1.0" serde_json = "1.0" futures = "0.1.17" -multiqueue = "0.3" ethcore-network = { git = "https://github.com/paritytech/parity.git" } ethcore-io = { git = "https://github.com/paritytech/parity.git" } ed25519 = { path = "../../substrate/ed25519" } diff --git a/substrate/network/src/consensus.rs b/substrate/network/src/consensus.rs index eb2a1e51a40e1..efff9dbf42cab 100644 --- a/substrate/network/src/consensus.rs +++ b/substrate/network/src/consensus.rs @@ -17,8 +17,7 @@ //! Consensus related bits of the network service. use std::collections::HashMap; -use multiqueue; -use futures::sync::oneshot; +use futures::sync::{oneshot, mpsc}; use io::SyncIo; use protocol::Protocol; use network::PeerId; @@ -26,9 +25,6 @@ use primitives::Hash; use message::{self, Message}; use runtime_support::Hashable; -//TODO: The queue is preallocated in multiqueue. Make it unbounded -const QUEUE_SIZE: u64 = 1 << 16; - struct CandidateRequest { id: message::RequestId, completion: oneshot::Sender>, @@ -43,35 +39,25 @@ struct PeerConsensus { pub struct Consensus { peers: HashMap, our_candidate: Option<(Hash, Vec)>, - statement_sink: multiqueue::BroadcastFutSender, - statement_stream: multiqueue::BroadcastFutReceiver, - bft_message_sink: multiqueue::BroadcastFutSender, - bft_message_stream: multiqueue::BroadcastFutReceiver, + statement_sink: Option>, + bft_message_sink: Option>, } impl Consensus { /// Create a new instance. pub fn new() -> Consensus { - let (statement_sink, statement_stream) = multiqueue::broadcast_fut_queue(QUEUE_SIZE); - let (bft_sink, bft_stream) = multiqueue::broadcast_fut_queue(QUEUE_SIZE); Consensus { peers: HashMap::new(), our_candidate: None, - statement_sink: statement_sink, - statement_stream: statement_stream, - bft_message_sink: bft_sink, - bft_message_stream: bft_stream, + statement_sink: None, + bft_message_sink: None, } } /// Closes all notification streams. pub fn restart(&mut self) { - let (statement_sink, statement_stream) = multiqueue::broadcast_fut_queue(QUEUE_SIZE); - let (bft_sink, bft_stream) = multiqueue::broadcast_fut_queue(QUEUE_SIZE); - self.statement_sink = statement_sink; - self.statement_stream = statement_stream; - self.bft_message_sink = bft_sink; - self.bft_message_stream = bft_stream; + self.statement_sink = None; + self.bft_message_sink = None; } /// Handle new connected peer. @@ -93,31 +79,43 @@ impl Consensus { &message::UnsignedStatement::Available(ref hash) => peer.candidate_available = Some(*hash), &message::UnsignedStatement::Valid(_) | &message::UnsignedStatement::Invalid(_) => (), } - if let Err(e) = self.statement_sink.try_send(statement) { - trace!(target:"sync", "Error broadcasting statement notification: {:?}", e); + if let Some(sink) = self.statement_sink.take() { + if let Err(e) = sink.unbounded_send(statement) { + trace!(target:"sync", "Error broadcasting statement notification: {:?}", e); + } else { + self.statement_sink = Some(sink); + } } } else { trace!(target:"sync", "Ignored statement from unregistered peer {}", peer_id); } } - pub fn statements(&self) -> multiqueue::BroadcastFutReceiver{ - self.statement_stream.add_stream() + pub fn statements(&mut self) -> mpsc::UnboundedReceiver{ + let (sink, stream) = mpsc::unbounded(); + self.statement_sink = Some(sink); + stream } pub fn on_bft_message(&mut self, peer_id: PeerId, message: message::BftMessage) { if self.peers.contains_key(&peer_id) { // TODO: validate signature? - if let Err(e) = self.bft_message_sink.try_send(message) { - trace!(target:"sync", "Error broadcasting BFT message notification: {:?}", e); + if let Some(sink) = self.bft_message_sink.take() { + if let Err(e) = sink.unbounded_send(message) { + trace!(target:"sync", "Error broadcasting BFT message notification: {:?}", e); + } else { + self.bft_message_sink = Some(sink); + } } } else { trace!(target:"sync", "Ignored BFT statement from unregistered peer {}", peer_id); } } - pub fn bft_messages(&self) -> multiqueue::BroadcastFutReceiver{ - self.bft_message_stream.add_stream() + pub fn bft_messages(&mut self) -> mpsc::UnboundedReceiver{ + let (sink, stream) = mpsc::unbounded(); + self.bft_message_sink = Some(sink); + stream } pub fn fetch_candidate(&mut self, io: &mut SyncIo, protocol: &Protocol, hash: &Hash) -> oneshot::Receiver> { diff --git a/substrate/network/src/lib.rs b/substrate/network/src/lib.rs index 1c7fe9fa0e4c4..5a2727938af52 100644 --- a/substrate/network/src/lib.rs +++ b/substrate/network/src/lib.rs @@ -32,7 +32,6 @@ extern crate substrate_bft; extern crate serde; extern crate serde_json; extern crate futures; -extern crate multiqueue; extern crate ed25519; #[macro_use] extern crate serde_derive; #[macro_use] extern crate log; diff --git a/substrate/network/src/protocol.rs b/substrate/network/src/protocol.rs index 35f2ca0549788..7921cc0c5f320 100644 --- a/substrate/network/src/protocol.rs +++ b/substrate/network/src/protocol.rs @@ -19,7 +19,6 @@ use std::{mem, cmp}; use std::sync::Arc; use std::time; use parking_lot::{RwLock, Mutex}; -use multiqueue; use futures::sync::oneshot; use serde_json; use primitives::block::{HeaderHash, TransactionHash, Number as BlockNumber, Header, Id as BlockId}; @@ -29,7 +28,7 @@ use network::{PeerId, NodeId}; use message::{self, Message}; use sync::{ChainSync, Status as SyncStatus, SyncState}; use consensus::Consensus; -use service::{Role, TransactionPool}; +use service::{Role, TransactionPool, StatementStream, BftMessageStream}; use config::ProtocolConfig; use chain::Client; use io::SyncIo; @@ -310,12 +309,12 @@ impl Protocol { } /// See `ConsensusService` trait. - pub fn bft_messages(&self) -> multiqueue::BroadcastFutReceiver { + pub fn bft_messages(&self) -> BftMessageStream { self.consensus.lock().bft_messages() } /// See `ConsensusService` trait. - pub fn statements(&self) -> multiqueue::BroadcastFutReceiver { + pub fn statements(&self) -> StatementStream { self.consensus.lock().statements() } diff --git a/substrate/network/src/service.rs b/substrate/network/src/service.rs index 1688d1e717057..ce5ff0059cb31 100644 --- a/substrate/network/src/service.rs +++ b/substrate/network/src/service.rs @@ -17,8 +17,7 @@ use std::sync::Arc; use std::collections::{BTreeMap}; use std::io; -use multiqueue; -use futures::sync::oneshot; +use futures::sync::{oneshot, mpsc}; use network::{NetworkProtocolHandler, NetworkService, NetworkContext, HostInfo, PeerId, ProtocolId, NetworkConfiguration , NonReservedPeerMode, ErrorKind}; use primitives::block::{TransactionHash, Header}; @@ -37,9 +36,9 @@ pub const DOT_PROTOCOL_ID: ProtocolId = *b"dot"; /// Type that represents fetch completion future. pub type FetchFuture = oneshot::Receiver>; /// Type that represents statement stream. -pub type StatementStream = multiqueue::BroadcastFutReceiver; +pub type StatementStream = mpsc::UnboundedReceiver; /// Type that represents bft messages stream. -pub type BftMessageStream = multiqueue::BroadcastFutReceiver; +pub type BftMessageStream = mpsc::UnboundedReceiver; bitflags! { /// Node roles bitmask. @@ -80,7 +79,7 @@ pub trait TransactionPool: Send + Sync { /// ConsensusService pub trait ConsensusService: Send + Sync { /// Get statement stream. - fn statements(&self) -> multiqueue::BroadcastFutReceiver; + fn statements(&self) -> StatementStream; /// Send out a statement. fn send_statement(&self, statement: Statement); /// Maintain connectivity to given addresses. @@ -92,7 +91,7 @@ pub trait ConsensusService: Send + Sync { fn set_local_candidate(&self, candidate: Option<(Hash, Vec)>); /// Get BFT message stream. - fn bft_messages(&self) -> multiqueue::BroadcastFutReceiver; + fn bft_messages(&self) -> BftMessageStream; /// Send out a BFT message. fn send_bft_message(&self, message: BftMessage); } @@ -228,7 +227,7 @@ impl SyncProvider for Service { /// ConsensusService impl ConsensusService for Service { - fn statements(&self) -> multiqueue::BroadcastFutReceiver { + fn statements(&self) -> StatementStream { self.handler.protocol.statements() } From ae96357d4a3b7cb4e16d65fe3206572a6869867c Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 2 Apr 2018 15:44:31 +0200 Subject: [PATCH 03/18] BFT gossip --- polkadot/consensus/src/service.rs | 1 - substrate/network/src/consensus.rs | 69 ++++++++++++++++++++++++------ substrate/network/src/message.rs | 10 ++--- substrate/network/src/protocol.rs | 20 ++++++--- 4 files changed, 75 insertions(+), 25 deletions(-) diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index d481dd7d1b510..6ef1aa8389217 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -143,7 +143,6 @@ impl Service { best_header: &Header) -> Service where C: BlockchainEvents + bft::BlockImport + bft::Authorities + PolkadotApi + Send + Sync + 'static { - let best_header = best_header.clone(); let thread = thread::spawn(move || { let mut core = reactor::Core::new().expect("tokio::Core could not be created"); diff --git a/substrate/network/src/consensus.rs b/substrate/network/src/consensus.rs index efff9dbf42cab..630506739ca67 100644 --- a/substrate/network/src/consensus.rs +++ b/substrate/network/src/consensus.rs @@ -16,8 +16,10 @@ //! Consensus related bits of the network service. -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use futures::sync::{oneshot, mpsc}; +use std::time::{Instant, Duration}; +use std::collections::hash_map::Entry; use io::SyncIo; use protocol::Protocol; use network::PeerId; @@ -25,6 +27,9 @@ use primitives::Hash; use message::{self, Message}; use runtime_support::Hashable; +// TODO: Add additional spam/DoS attack protection. +const MESSAGE_LIFETIME_SECONDS: u64 = 600; + struct CandidateRequest { id: message::RequestId, completion: oneshot::Sender>, @@ -33,6 +38,7 @@ struct CandidateRequest { struct PeerConsensus { candidate_fetch: Option, candidate_available: Option, + known_messages: HashSet, } /// Consensus network protocol handler. Manages statements and candidate requests. @@ -41,6 +47,7 @@ pub struct Consensus { our_candidate: Option<(Hash, Vec)>, statement_sink: Option>, bft_message_sink: Option>, + message_timestamps: HashMap, } impl Consensus { @@ -51,6 +58,7 @@ impl Consensus { our_candidate: None, statement_sink: None, bft_message_sink: None, + message_timestamps: Default::default(), } } @@ -67,11 +75,26 @@ impl Consensus { self.peers.insert(peer_id, PeerConsensus { candidate_fetch: None, candidate_available: None, + known_messages: Default::default(), }); } } - pub fn on_statement(&mut self, peer_id: PeerId, statement: message::Statement) { + fn propagate(&mut self, io: &mut SyncIo, protocol: &Protocol, message: message::Message, hash: Hash) { + for (id, ref mut peer) in self.peers.iter_mut() { + if peer.known_messages.insert(hash.clone()) { + protocol.send_message(io, *id, message.clone()); + } + } + } + + fn register_message(&mut self, hash: Hash) { + if let Entry::Vacant(entry) = self.message_timestamps.entry(hash) { + entry.insert(Instant::now()); + } + } + + pub fn on_statement(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, statement: message::Statement, hash: Hash) { if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { // TODO: validate signature? match &statement.statement { @@ -79,8 +102,9 @@ impl Consensus { &message::UnsignedStatement::Available(ref hash) => peer.candidate_available = Some(*hash), &message::UnsignedStatement::Valid(_) | &message::UnsignedStatement::Invalid(_) => (), } + peer.known_messages.insert(hash); if let Some(sink) = self.statement_sink.take() { - if let Err(e) = sink.unbounded_send(statement) { + if let Err(e) = sink.unbounded_send(statement.clone()) { trace!(target:"sync", "Error broadcasting statement notification: {:?}", e); } else { self.statement_sink = Some(sink); @@ -88,7 +112,11 @@ impl Consensus { } } else { trace!(target:"sync", "Ignored statement from unregistered peer {}", peer_id); + return; } + self.register_message(hash.clone()); + // Propagate to other peers. + self.propagate(io, protocol, Message::Statement(statement), hash); } pub fn statements(&mut self) -> mpsc::UnboundedReceiver{ @@ -97,11 +125,12 @@ impl Consensus { stream } - pub fn on_bft_message(&mut self, peer_id: PeerId, message: message::BftMessage) { - if self.peers.contains_key(&peer_id) { + pub fn on_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, message: message::BftMessage, hash: Hash) { + if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { + peer.known_messages.insert(hash); // TODO: validate signature? if let Some(sink) = self.bft_message_sink.take() { - if let Err(e) = sink.unbounded_send(message) { + if let Err(e) = sink.unbounded_send(message.clone()) { trace!(target:"sync", "Error broadcasting BFT message notification: {:?}", e); } else { self.bft_message_sink = Some(sink); @@ -109,7 +138,11 @@ impl Consensus { } } else { trace!(target:"sync", "Ignored BFT statement from unregistered peer {}", peer_id); + return; } + self.register_message(hash.clone()); + // Propagate to other peers. + self.propagate(io, protocol, Message::BftMessage(message), hash); } pub fn bft_messages(&mut self) -> mpsc::UnboundedReceiver{ @@ -145,17 +178,19 @@ impl Consensus { pub fn send_statement(&mut self, io: &mut SyncIo, protocol: &Protocol, statement: message::Statement) { // Broadcast statement to all validators. trace!(target:"sync", "Broadcasting statement {:?}", statement); - for peer in self.peers.keys() { - protocol.send_message(io, *peer, Message::Statement(statement.clone())); - } + let message = Message::Statement(statement); + let hash = Protocol::hash_message(&message); + self.register_message(hash.clone()); + self.propagate(io, protocol, message, hash); } pub fn send_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, message: message::BftMessage) { // Broadcast message to all validators. trace!(target:"sync", "Broadcasting BFT message {:?}", message); - for peer in self.peers.keys() { - protocol.send_message(io, *peer, Message::BftMessage(message.clone())); - } + let message = Message::BftMessage(message); + let hash = Protocol::hash_message(&message); + self.register_message(hash.clone()); + self.propagate(io, protocol, message, hash); } pub fn set_local_candidate(&mut self, candidate: Option<(Hash, Vec)>) { @@ -198,4 +233,14 @@ impl Consensus { pub fn peer_disconnected(&mut self, _io: &mut SyncIo, _protocol: &Protocol, peer_id: PeerId) { self.peers.remove(&peer_id); } + + pub fn collect_garbage(&mut self) { + let expiration = Duration::from_secs(MESSAGE_LIFETIME_SECONDS); + let now = Instant::now(); + self.message_timestamps.retain(|_, timestamp| *timestamp + expiration < now); + let timestamps = &self.message_timestamps; + for (_, ref mut peer) in self.peers.iter_mut() { + peer.known_messages.retain(|h| timestamps.contains_key(h)); + } + } } diff --git a/substrate/network/src/message.rs b/substrate/network/src/message.rs index 52c78d95febb1..81d73ac1cb07e 100644 --- a/substrate/network/src/message.rs +++ b/substrate/network/src/message.rs @@ -26,7 +26,7 @@ pub type RequestId = u64; type Bytes = Vec; /// Configured node role. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub enum Role { /// Full relay chain client with no additional responsibilities. Full, @@ -213,7 +213,7 @@ pub enum SignedConsensusMessage { /// A vote. Vote(SignedConsensusVote), } -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] /// A network message. pub enum Message { /// Status packet. @@ -236,7 +236,7 @@ pub enum Message { BftMessage(BftMessage), } -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct Status { /// Protocol version. pub version: u32, @@ -291,7 +291,7 @@ pub struct CandidateResponse { pub data: Option>, } -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] /// Response to `BlockRequest` pub struct BlockResponse { /// Id of a request this response was made for. @@ -300,7 +300,7 @@ pub struct BlockResponse { pub blocks: Vec, } -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] /// Announce a new complete relay chain block on the network. pub struct BlockAnnounce { /// New block header. diff --git a/substrate/network/src/protocol.rs b/substrate/network/src/protocol.rs index 7921cc0c5f320..229d2a2d244be 100644 --- a/substrate/network/src/protocol.rs +++ b/substrate/network/src/protocol.rs @@ -22,7 +22,7 @@ use parking_lot::{RwLock, Mutex}; use futures::sync::oneshot; use serde_json; use primitives::block::{HeaderHash, TransactionHash, Number as BlockNumber, Header, Id as BlockId}; -use primitives::Hash; +use primitives::{Hash, blake2_256}; use network::{PeerId, NodeId}; use message::{self, Message}; @@ -176,10 +176,10 @@ impl Protocol { Message::BlockAnnounce(announce) => { self.on_block_announce(io, peer_id, announce); }, - Message::Statement(s) => self.on_statement(io, peer_id, s), + Message::Statement(s) => self.on_statement(io, peer_id, s, blake2_256(data).into()), Message::CandidateRequest(r) => self.on_candidate_request(io, peer_id, r), Message::CandidateResponse(r) => self.on_candidate_response(io, peer_id, r), - Message::BftMessage(m) => self.on_bft_message(io, peer_id, m), + Message::BftMessage(m) => self.on_bft_message(io, peer_id, m, blake2_256(data).into()), Message::Transactions(m) => self.on_transactions(io, peer_id, m), } } @@ -204,6 +204,11 @@ impl Protocol { } } + pub fn hash_message(message: &Message) -> Hash { + let data = serde_json::to_vec(&message).expect("Serializer is infallible; qed"); + blake2_256(&data).into() + } + /// Called when a new peer is connected pub fn on_peer_connected(&self, io: &mut SyncIo, peer_id: PeerId) { trace!(target: "sync", "Connected {}: {}", peer_id, io.peer_info(peer_id)); @@ -293,14 +298,14 @@ impl Protocol { self.consensus.lock().on_candidate_response(io, self, peer, response); } - fn on_statement(&self, _io: &mut SyncIo, peer: PeerId, statement: message::Statement) { + fn on_statement(&self, io: &mut SyncIo, peer: PeerId, statement: message::Statement, hash: Hash) { trace!(target: "sync", "Statement from {}: {:?}", peer, statement); - self.consensus.lock().on_statement(peer, statement); + self.consensus.lock().on_statement(io, self, peer, statement, hash); } - fn on_bft_message(&self, _io: &mut SyncIo, peer: PeerId, message: message::BftMessage) { + fn on_bft_message(&self, io: &mut SyncIo, peer: PeerId, message: message::BftMessage, hash: Hash) { trace!(target: "sync", "BFT message from {}: {:?}", peer, message); - self.consensus.lock().on_bft_message(peer, message); + self.consensus.lock().on_bft_message(io, self, peer, message, hash); } /// See `ConsensusService` trait. @@ -336,6 +341,7 @@ impl Protocol { /// Perform time based maintenance. pub fn tick(&self, io: &mut SyncIo) { self.maintain_peers(io); + self.consensus.lock().collect_garbage(); } fn maintain_peers(&self, io: &mut SyncIo) { From ae0d1911ae5233e459ce561965fe6c78a582409c Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 3 Apr 2018 13:16:43 +0200 Subject: [PATCH 04/18] Revert to app_dirs --- Cargo.lock | 8 ++++---- polkadot/cli/Cargo.toml | 2 +- polkadot/cli/src/lib.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba3b922964920..995c0525af84c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,8 +17,8 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "app_dirs2" -version = "2.0.3" +name = "app_dirs" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1112,7 +1112,7 @@ dependencies = [ name = "polkadot-cli" version = "0.1.0" dependencies = [ - "app_dirs2 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)", "ed25519 0.1.0", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2208,7 +2208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum app_dirs2 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0aa02944d8a100b79057d1619032b1ad39de5eed6567cdeccbd53908b326e082" +"checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" "checksum arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e772942dccdf11b368c31e044e4fca9189f80a773d2f0808379de65894cbf57" diff --git a/polkadot/cli/Cargo.toml b/polkadot/cli/Cargo.toml index a1ae67c3b62d5..8fa34c3a02eea 100644 --- a/polkadot/cli/Cargo.toml +++ b/polkadot/cli/Cargo.toml @@ -12,7 +12,7 @@ log = "0.3" hex-literal = "0.1" triehash = "0.1" ed25519 = { path = "../../substrate/ed25519" } -app_dirs2 = "2.0" +app_dirs = "1.2" substrate-client = { path = "../../substrate/client" } substrate-codec = { path = "../../substrate/codec" } substrate-runtime-io = { path = "../../substrate/runtime-io" } diff --git a/polkadot/cli/src/lib.rs b/polkadot/cli/src/lib.rs index 5b7a49baaebd0..72a66b8ef558a 100644 --- a/polkadot/cli/src/lib.rs +++ b/polkadot/cli/src/lib.rs @@ -18,7 +18,7 @@ #![warn(missing_docs)] -extern crate app_dirs2 as app_dirs; +extern crate app_dirs; extern crate env_logger; extern crate ed25519; extern crate triehash; From 48754017aa88a7b476c1806eccef466fc49fb7d9 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 3 Apr 2018 13:18:58 +0200 Subject: [PATCH 05/18] generate_from_seed commented --- polkadot/keystore/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/polkadot/keystore/src/lib.rs b/polkadot/keystore/src/lib.rs index 8bfa703988891..d91d986e5650a 100644 --- a/polkadot/keystore/src/lib.rs +++ b/polkadot/keystore/src/lib.rs @@ -150,6 +150,8 @@ impl Store { } /// Create a new key from seed. Do not place it into the store. + /// Only the first 32 bytes of the sead are used. This is meant to be used for testing only. + // TODO: Remove this pub fn generate_from_seed(&mut self, seed: &str) -> Result { let mut s: [u8; 32] = [' ' as u8; 32]; let len = ::std::cmp::min(32, seed.len()); From 3a6bf0ca8fef6be96f0778b661da67dbd34332ed Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 4 Apr 2018 15:21:00 +0200 Subject: [PATCH 06/18] Refactor event loop --- polkadot/consensus/Cargo.toml | 3 +- polkadot/consensus/src/service.rs | 23 +++++++------- substrate/bft/src/lib.rs | 52 +++++++++++++++++-------------- 3 files changed, 42 insertions(+), 36 deletions(-) diff --git a/polkadot/consensus/Cargo.toml b/polkadot/consensus/Cargo.toml index df49b2a1cfdb8..466e65663005c 100644 --- a/polkadot/consensus/Cargo.toml +++ b/polkadot/consensus/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Parity Technologies "] futures = "0.1.17" parking_lot = "0.4" tokio-timer = "0.1.2" +tokio-core = "0.1.12" ed25519 = { path = "../../substrate/ed25519" } error-chain = "0.11" log = "0.4" @@ -19,7 +20,5 @@ substrate-bft = { path = "../../substrate/bft" } substrate-codec = { path = "../../substrate/codec" } substrate-primitives = { path = "../../substrate/primitives" } substrate-network = { path = "../../substrate/network" } - -tokio-core = "0.1.12" substrate-keyring = { path = "../../substrate/keyring" } substrate-client = { path = "../../substrate/client" } diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index 6ef1aa8389217..1d7c900f234eb 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -166,17 +166,18 @@ impl Service { let output = BftSink { network: network.clone(), _e: Default::default() }; Ok(bft_service.build_upon(&header, input, output)?) }; - // Kickstart BFT agreement on start. - if let Err(e) = build_bft(&best_header) - .map_err(|e| debug!("Error creating initial BFT agreement: {:?}", e)) - .and_then(|bft| core.run(bft)) - { - debug!("Error starting initial BFT agreement: {:?}", e); - } - let bft = client.import_notification_stream().and_then(|notification| { - build_bft(¬ification.header).map_err(|e| debug!("BFT agreement error: {:?}", e)) - }).for_each(|f| f); - if let Err(e) = core.run(bft) { + let handle = core.handle(); + let notifications = client.import_notification_stream().for_each(|notification| { + if notification.is_new_best { + match build_bft(¬ification.header) { + Ok(Some(bft)) => handle.spawn(bft), + Ok(None) => {}, + Err(e) => debug!("BFT agreement error: {:?}", e), + } + } + Ok(()) + }); + if let Err(e) = core.run(notifications) { debug!("BFT event loop error {:?}", e); } }); diff --git a/substrate/bft/src/lib.rs b/substrate/bft/src/lib.rs index 110d14ee1b329..dc6929857d66f 100644 --- a/substrate/bft/src/lib.rs +++ b/substrate/bft/src/lib.rs @@ -31,7 +31,7 @@ extern crate futures; #[macro_use] extern crate error_chain; -use std::collections::HashMap; +use std::mem; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; @@ -300,7 +300,7 @@ impl Drop for AgreementHandle { /// is notified of. pub struct BftService { client: Arc, - live_agreements: Mutex>, + live_agreement: Mutex>, timer: Timer, round_timeout_multiplier: u64, key: Arc, // TODO: key changing over time. @@ -317,7 +317,7 @@ impl BftService pub fn new(client: Arc, key: Arc, factory: P) -> BftService { BftService { client: client, - live_agreements: Mutex::new(HashMap::new()), + live_agreement: Mutex::new(None), timer: Timer::default(), round_timeout_multiplier: 4, key: key, // TODO: key changing over time. @@ -329,13 +329,16 @@ impl BftService /// /// If the local signing key is an authority, this will begin the consensus process to build a /// block on top of it. If the executor fails to run the future, an error will be returned. + /// Returns `None` if the agreement on the block with given parent is already in progress. pub fn build_upon(&self, header: &Header, input: InStream, output: OutSink) - -> Result::Proposer, I, InStream, OutSink>, P::Error> where + -> Result::Proposer, I, InStream, OutSink>>, P::Error> where InStream: Stream::Proposer as Proposer>::Error>, OutSink: Sink::Proposer as Proposer>::Error>, { let hash = header.hash(); - let mut _preempted_consensus = None; // defers drop of live to the end. + if self.live_agreement.lock().as_ref().map_or(false, |&(h, _)| h == hash) { + return Ok(None); + } let authorities = self.client.authorities(&BlockId::Hash(hash))?; @@ -345,7 +348,8 @@ impl BftService let local_id = self.key.public().0; if !authorities.contains(&local_id) { - self.live_agreements.lock().remove(&header.parent_hash); + // cancel current agreement + self.live_agreement.lock().take(); Err(From::from(ErrorKind::InvalidAuthority(local_id)))?; } @@ -371,24 +375,26 @@ impl BftService let cancel = Arc::new(AtomicBool::new(false)); let (tx, rx) = oneshot::channel(); - { - let mut live = self.live_agreements.lock(); - live.insert(hash, AgreementHandle { + // cancel current agreement. + // defers drop of live to the end. + let _preempted_consensus = { + mem::replace(&mut *self.live_agreement.lock(), Some((hash, AgreementHandle { task: Some(rx), cancel: cancel.clone(), - }); - - // cancel any agreements attempted to build upon this block's parent - // as clearly agreement has already been reached. - _preempted_consensus = live.remove(&header.parent_hash); - } + }))) + }; - Ok(BftFuture { + Ok(Some(BftFuture { inner: agreement, cancel: cancel, send_task: Some(tx), import: self.client.clone(), - }) + })) + } + + /// Cancel current agreement if any. + pub fn cancel_agreement(&self) { + self.live_agreement.lock().take(); } } @@ -632,7 +638,7 @@ mod tests { { BftService { client: Arc::new(client), - live_agreements: Mutex::new(HashMap::new()), + live_agreement: Mutex::new(None), timer: Timer::default(), round_timeout_multiplier: 4, key: Arc::new(Keyring::One.into()), @@ -671,17 +677,17 @@ mod tests { let second_hash = second.hash(); let bft = service.build_upon(&first, stream::empty(), Output(Default::default())).unwrap(); - assert!(service.live_agreements.lock().contains_key(&first_hash)); + assert!(service.live_agreement.lock().as_ref().unwrap().0 == first_hash); // turn the core so the future gets polled and sends its task to the // service. otherwise it deadlocks. - core.handle().execute(bft).unwrap(); + core.handle().execute(bft.unwrap()).unwrap(); core.turn(Some(::std::time::Duration::from_millis(100))); let bft = service.build_upon(&second, stream::empty(), Output(Default::default())).unwrap(); - assert!(!service.live_agreements.lock().contains_key(&first_hash)); - assert!(service.live_agreements.lock().contains_key(&second_hash)); + assert!(service.live_agreement.lock().as_ref().unwrap().0 != first_hash); + assert!(service.live_agreement.lock().as_ref().unwrap().0 == second_hash); - core.handle().execute(bft).unwrap(); + core.handle().execute(bft.unwrap()).unwrap(); core.turn(Some(::std::time::Duration::from_millis(100))); } From 49d6f41da711792811b12a738eac93cbd1e88163 Mon Sep 17 00:00:00 2001 From: arkpar Date: Wed, 4 Apr 2018 23:02:37 +0200 Subject: [PATCH 07/18] Start consensus by timer --- Cargo.lock | 13 ++++- Cargo.toml | 1 + polkadot/cli/src/lib.rs | 7 +-- polkadot/consensus/Cargo.toml | 1 - polkadot/consensus/src/lib.rs | 1 - polkadot/consensus/src/service.rs | 87 ++++++++++++++++++++++--------- polkadot/service/src/lib.rs | 4 +- polkadot/src/main.rs | 9 +++- substrate/client/src/client.rs | 23 ++++++++ substrate/client/src/lib.rs | 2 +- 10 files changed, 114 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 880e992909336..88d6bf17ba870 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -192,6 +192,16 @@ name = "crunchy" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ctrlc" +version = "1.1.1" +source = "git+https://github.com/paritytech/rust-ctrlc.git#b523017108bb2d571a7a69bd97bc406e63bc7a9d" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "demo-cli" version = "0.1.0" @@ -1108,6 +1118,7 @@ dependencies = [ name = "polkadot" version = "0.1.0" dependencies = [ + "ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-cli 0.1.0", ] @@ -1182,7 +1193,6 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-runtime-support 0.1.0", "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2410,6 +2420,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" +"checksum ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)" = "" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum edit-distance 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3bd26878c3d921f89797a4e1a1711919f999a9f6946bb6f5a4ffda126d297b7e" diff --git a/Cargo.toml b/Cargo.toml index 4c5c69275042e..8b79c0734f5a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ authors = ["Parity Technologies "] [dependencies] error-chain = "0.11" polkadot-cli = { path = "polkadot/cli" } +ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" } [workspace] members = [ diff --git a/polkadot/cli/src/lib.rs b/polkadot/cli/src/lib.rs index 72a66b8ef558a..27ebc867d989d 100644 --- a/polkadot/cli/src/lib.rs +++ b/polkadot/cli/src/lib.rs @@ -43,6 +43,7 @@ pub mod error; use std::path::{Path, PathBuf}; use std::net::SocketAddr; +use std::sync::mpsc; /// Parse command line arguments and start the node. /// @@ -52,7 +53,7 @@ use std::net::SocketAddr; /// 9556-9591 Unassigned /// 9803-9874 Unassigned /// 9926-9949 Unassigned -pub fn run(args: I) -> error::Result<()> where +pub fn run(args: I, exit: mpsc::Receiver<()>) -> error::Result<()> where I: IntoIterator, T: Into + Clone, { @@ -116,9 +117,9 @@ pub fn run(args: I) -> error::Result<()> where address.set_port(rpc_port); } let handler = rpc::rpc_handler(service.client()); - let server = rpc::start_http(&address, handler)?; + let _server = rpc::start_http(&address, handler)?; - server.wait(); + exit.recv().ok(); Ok(()) } diff --git a/polkadot/consensus/Cargo.toml b/polkadot/consensus/Cargo.toml index f19824750d3c0..54f8105fad358 100644 --- a/polkadot/consensus/Cargo.toml +++ b/polkadot/consensus/Cargo.toml @@ -6,7 +6,6 @@ authors = ["Parity Technologies "] [dependencies] futures = "0.1.17" parking_lot = "0.4" -tokio-timer = "0.1.2" tokio-core = "0.1.12" ed25519 = { path = "../../substrate/ed25519" } error-chain = "0.11" diff --git a/polkadot/consensus/src/lib.rs b/polkadot/consensus/src/lib.rs index ba1e05b05e1ff..5663ccdcbe112 100644 --- a/polkadot/consensus/src/lib.rs +++ b/polkadot/consensus/src/lib.rs @@ -32,7 +32,6 @@ extern crate futures; extern crate ed25519; extern crate parking_lot; -extern crate tokio_timer; extern crate polkadot_api; extern crate polkadot_collator as collator; extern crate polkadot_statement_table as table; diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index 0b87e1f7ee8f3..2f4ec89233081 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -20,12 +20,13 @@ /// candidate agreement over the network. use std::thread; +use std::time::{Duration, Instant}; use std::sync::Arc; use futures::{future, Future, Stream, Sink, Async, Canceled}; use parking_lot::Mutex; use substrate_network as net; use tokio_core::reactor; -use client::BlockchainEvents; +use client::{BlockchainEvents, ChainHead}; use runtime_support::Hashable; use primitives::{Hash, AuthorityId}; use primitives::block::{Id as BlockId, HeaderHash, Header}; @@ -35,7 +36,9 @@ use bft::{self, BftService}; use transaction_pool::TransactionPool; use ed25519; use super::{TableRouter, SharedTable, ProposerFactory}; -use error::Error; + +const TIMER_DELAY_MS: u64 = 5000; +const TIMER_INTERVAL_MS: u64 = 500; struct BftSink { network: Arc, @@ -134,17 +137,44 @@ pub struct Service { struct Network(Arc); +fn start_bft(header: &Header, handle: reactor::Handle, client: &bft::Authorities, network: Arc, bft_service: &BftService) + where F: bft::ProposerFactory + 'static, + C: bft::BlockImport + bft::Authorities + 'static, + ::Error: ::std::fmt::Debug, +{ + let hash = header.blake2_256().into(); + let authorities = match client.authorities(&BlockId::Hash(hash)) { + Ok(authorities) => authorities, + Err(e) => { + debug!("Error reading authorities: {:?}", e); + return; + } + }; + let input = network.bft_messages() + .filter_map(move |message| { + process_message(message, &authorities, hash.clone()) + .map_err(|e| debug!("Message validation failed: {:?}", e)) + .ok() + }) + .map_err(|_| bft::InputStreamConcluded.into()); + let output = BftSink { network: network, _e: Default::default() }; + match bft_service.build_upon(&header, input, output) { + Ok(Some(bft)) => handle.spawn(bft), + Ok(None) => {}, + Err(e) => debug!("BFT agreement error: {:?}", e), + } +} + impl Service { /// Create and start a new instance. pub fn new( client: Arc, network: Arc, transaction_pool: Arc>, - key: ed25519::Pair, - best_header: &Header) -> Service - where C: BlockchainEvents + bft::BlockImport + bft::Authorities + PolkadotApi + Send + Sync + 'static + key: ed25519::Pair) + -> Service + where C: BlockchainEvents + ChainHead + bft::BlockImport + bft::Authorities + PolkadotApi + Send + Sync + 'static { - let best_header = best_header.clone(); let thread = thread::spawn(move || { let mut core = reactor::Core::new().expect("tokio::Core could not be created"); let key = Arc::new(key); @@ -153,31 +183,40 @@ impl Service { transaction_pool: transaction_pool.clone(), network: Network(network.clone()), }; - let bft_service = BftService::new(client.clone(), key, factory); - let build_bft = |header: &Header| -> Result<_, Error> { - let hash = header.blake2_256().into(); - let authorities = client.authorities(&BlockId::Hash(hash))?; - let input = network.bft_messages() - .filter_map(move |message| { - process_message(message, &authorities, hash.clone()) - .map_err(|e| debug!("Message validation failed: {:?}", e)) - .ok() - }) - .map_err(|_| bft::InputStreamConcluded.into()); - let output = BftSink { network: network.clone(), _e: Default::default() }; - Ok(bft_service.build_upon(&header, input, output)?) - }; + let bft_service = Arc::new(BftService::new(client.clone(), key, factory)); + let handle = core.handle(); let notifications = client.import_notification_stream().for_each(|notification| { if notification.is_new_best { - match build_bft(¬ification.header) { - Ok(Some(bft)) => handle.spawn(bft), - Ok(None) => {}, - Err(e) => debug!("BFT agreement error: {:?}", e), + start_bft(¬ification.header, handle.clone(), &*client, network.clone(), &*bft_service); + } + Ok(()) + }); + + let interval = reactor::Interval::new_at(Instant::now() + Duration::from_millis(TIMER_DELAY_MS), Duration::from_millis(TIMER_INTERVAL_MS), &handle).unwrap(); + let mut prev_best = match client.best_block_header() { + Ok(header) => header.blake2_256(), + Err(e) => { + warn!("Cant's start consensus service. Error reading best block header: {:?}", e); + return; + } + }; + let c = client.clone(); + let s = bft_service.clone(); + let n = network.clone(); + let handle = core.handle(); + let timed = interval.map_err(|e| debug!("Timer error: {:?}", e)).for_each(move |_| { + if let Ok(best_block) = c.best_block_header() { + let hash = best_block.blake2_256(); + if hash == prev_best { + debug!("Starting consensus round after a timeout"); + start_bft(&best_block, handle.clone(), &*c, n.clone(), &*s); } + prev_best = hash; } Ok(()) }); + core.handle().spawn(timed); if let Err(e) = core.run(notifications) { debug!("BFT event loop error {:?}", e); } diff --git a/polkadot/service/src/lib.rs b/polkadot/service/src/lib.rs index d3daac84ca849..cc2927a43e106 100644 --- a/polkadot/service/src/lib.rs +++ b/polkadot/service/src/lib.rs @@ -160,7 +160,7 @@ impl Service { }; let client = Arc::new(client::new_in_mem(executor, prepare_genesis)?); - let best_header = client.header(&BlockId::Hash(client.info()?.chain.best_hash))?.expect("Best header always exists; qed"); + let best_header = client.best_block_header()?; info!("Starting Polkadot. Best block is #{}", best_header.number); let transaction_pool = Arc::new(Mutex::new(TransactionPool::new(config.transaction_pool))); let transaction_pool_adapter = Arc::new(TransactionPoolAdapter { @@ -182,7 +182,7 @@ impl Service { // Load the first available key. Code above makes sure it exisis. let key = keystore.load(&keystore.contents()?[0], "")?; info!("Using authority key {:?}", key.public()); - Some(consensus::Service::new(client.clone(), network.clone(), transaction_pool, key, &best_header)) + Some(consensus::Service::new(client.clone(), network.clone(), transaction_pool, key)) } else { None }; diff --git a/polkadot/src/main.rs b/polkadot/src/main.rs index 50ff18462e29a..71d0e32f45107 100644 --- a/polkadot/src/main.rs +++ b/polkadot/src/main.rs @@ -22,9 +22,16 @@ extern crate polkadot_cli as cli; #[macro_use] extern crate error_chain; +extern crate ctrlc; + +use std::sync::mpsc; quick_main!(run); fn run() -> cli::error::Result<()> { - cli::run(::std::env::args()) + let (exit_send, exit_receive) = mpsc::channel(); + ctrlc::CtrlC::set_handler(move || { + exit_send.send(()).expect("Error sending exit notification"); + }); + cli::run(::std::env::args(), exit_receive) } diff --git a/substrate/client/src/client.rs b/substrate/client/src/client.rs index a0c54097fa8a2..2ec71480f69d3 100644 --- a/substrate/client/src/client.rs +++ b/substrate/client/src/client.rs @@ -45,6 +45,12 @@ pub trait BlockchainEvents { fn import_notification_stream(&self) -> BlockchainEventStream; } +/// Chain head information. +pub trait ChainHead { + /// Get best block header. + fn best_block_header(&self) -> Result; +} + /// Client info // TODO: split queue info from chain info and amalgamate into single struct. #[derive(Debug)] @@ -377,6 +383,12 @@ impl Client where pub fn justification(&self, id: &BlockId) -> error::Result> { self.backend.blockchain().justification(*id) } + + /// Get best block header. + pub fn best_block_header(&self) -> error::Result { + let info = self.backend.blockchain().info().map_err(|e| error::Error::from_blockchain(Box::new(e)))?; + Ok(self.header(&BlockId::Hash(info.best_hash))?.expect("Best block header must always exist")) + } } impl bft::BlockImport for Client @@ -420,6 +432,17 @@ impl BlockchainEvents for Client } } +impl ChainHead for Client + where + B: backend::Backend, + E: state_machine::CodeExecutor, + error::Error: From<::Error> +{ + fn best_block_header(&self) -> error::Result { + Client::best_block_header(self) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/substrate/client/src/lib.rs b/substrate/client/src/lib.rs index 7feede0491b0e..8690b19f2d3f2 100644 --- a/substrate/client/src/lib.rs +++ b/substrate/client/src/lib.rs @@ -44,6 +44,6 @@ pub mod genesis; pub mod block_builder; mod client; -pub use client::{Client, ClientInfo, CallResult, ImportResult, +pub use client::{Client, ClientInfo, CallResult, ImportResult, ChainHead, BlockStatus, BlockOrigin, new_in_mem, BlockchainEventStream, BlockchainEvents}; pub use blockchain::Info as ChainInfo; From 30fc67c9fc91491b5dfe6004682ec35e047a2d2b Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 5 Apr 2018 17:26:43 +0200 Subject: [PATCH 08/18] Message buffering --- polkadot/consensus/src/service.rs | 167 ++++++++++++++++++++++------- substrate/network/src/consensus.rs | 8 +- substrate/network/src/lib.rs | 2 +- substrate/network/src/message.rs | 14 ++- substrate/network/src/protocol.rs | 4 +- substrate/network/src/service.rs | 8 +- 6 files changed, 154 insertions(+), 49 deletions(-) diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index 2f4ec89233081..837f689596c55 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -22,7 +22,8 @@ use std::thread; use std::time::{Duration, Instant}; use std::sync::Arc; -use futures::{future, Future, Stream, Sink, Async, Canceled}; +use std::collections::{HashMap, VecDeque}; +use futures::{future, Future, Stream, Sink, Async, Canceled, Poll}; use parking_lot::Mutex; use substrate_network as net; use tokio_core::reactor; @@ -36,17 +37,101 @@ use bft::{self, BftService}; use transaction_pool::TransactionPool; use ed25519; use super::{TableRouter, SharedTable, ProposerFactory}; +use error; const TIMER_DELAY_MS: u64 = 5000; const TIMER_INTERVAL_MS: u64 = 500; +const MESSAGE_LIFETIME_SEC: u64 = 10; struct BftSink { network: Arc, + parent_hash: HeaderHash, _e: ::std::marker::PhantomData, } -fn process_message(msg: net::BftMessage, authorities: &[AuthorityId], parent_hash: HeaderHash) -> Result { - Ok(match msg { +#[derive(Clone)] +struct SharedMessageCollection { + /// Messages for consensus over a block with known hash. Also holds timestamp of the first message. + messages: Arc)>>>, +} + +impl SharedMessageCollection { + fn new() -> SharedMessageCollection { + SharedMessageCollection { + messages: Arc::new(Mutex::new(HashMap::new())), + } + } + + fn select(&self, parent_hash: HeaderHash, stream: net::BftMessageStream, authorities: Vec) -> Messages { + Messages { + messages: self.messages.lock().remove(&parent_hash).map(|(_, m)| m).unwrap_or_else(VecDeque::new), + parent_hash, + network_stream: stream, + authorities: authorities, + collection: self.clone(), + } + } + + fn push(&self, message: net::LocalizedBftMessage) { + self.messages.lock() + .entry(message.parent_hash) + .or_insert_with(|| (Instant::now(), VecDeque::new())) + .1.push_back(message); + } + + fn collect_garbage(&self) { + let expiration = Duration::from_secs(MESSAGE_LIFETIME_SEC); + let now = Instant::now(); + self.messages.lock().retain(|_, &mut (timestamp, _)| timestamp + expiration < now); + } +} + +struct Messages { + parent_hash: HeaderHash, + messages: VecDeque, + network_stream: net::BftMessageStream, + authorities: Vec, + collection: SharedMessageCollection, +} + +impl Stream for Messages { + type Item = bft::Communication; + type Error = bft::Error; + + fn poll(&mut self) -> Poll, Self::Error> { + // push buffered messages first + while let Some(message) = self.messages.pop_front() { + match process_message(message, &self.authorities) { + Ok(message) => return Ok(Async::Ready(Some(message))), + Err(e) => debug!("Message validation failed: {:?}", e), + } + } + + // check the network + match self.network_stream.poll() { + Err(_) => Err(bft::InputStreamConcluded.into()), + Ok(Async::NotReady) => Ok(Async::NotReady), + Ok(Async::Ready(None)) => Ok(Async::Ready(None)), + Ok(Async::Ready(Some(message))) => { + if message.parent_hash == self.parent_hash { + match process_message(message, &self.authorities) { + Ok(message) => Ok(Async::Ready(Some(message))), + Err(e) => { + debug!("Message validation failed: {:?}", e); + Ok(Async::NotReady) + } + } + } else { + self.collection.push(message); + Ok(Async::NotReady) + } + } + } + } +} + +fn process_message(msg: net::LocalizedBftMessage, authorities: &[AuthorityId]) -> Result { + Ok(match msg.message { net::BftMessage::Consensus(c) => bft::generic::Communication::Consensus(match c { net::SignedConsensusMessage::Propose(proposal) => bft::generic::LocalizedMessage::Propose({ let proposal = bft::generic::LocalizedProposal { @@ -63,7 +148,7 @@ fn process_message(msg: net::BftMessage, authorities: &[AuthorityId], parent_has signer: ed25519::Public(proposal.sender), } }; - bft::check_proposal(authorities, &parent_hash, &proposal)?; + bft::check_proposal(authorities, &msg.parent_hash, &proposal)?; proposal }), net::SignedConsensusMessage::Vote(vote) => bft::generic::LocalizedMessage::Vote({ @@ -79,14 +164,14 @@ fn process_message(msg: net::BftMessage, authorities: &[AuthorityId], parent_has net::ConsensusVote::AdvanceRound(r) => bft::generic::Vote::AdvanceRound(r as usize), } }; - bft::check_vote(authorities, &parent_hash, &vote)?; + bft::check_vote(authorities, &msg.parent_hash, &vote)?; vote }), }), net::BftMessage::Auxiliary(a) => { let justification = bft::UncheckedJustification::from(a); // TODO: get proper error - let justification: Result<_, bft::Error> = bft::check_prepare_justification(authorities, parent_hash, justification) + let justification: Result<_, bft::Error> = bft::check_prepare_justification(authorities, msg.parent_hash, justification) .map_err(|_| bft::ErrorKind::InvalidJustification.into()); bft::generic::Communication::Auxiliary(justification?) }, @@ -99,27 +184,30 @@ impl Sink for BftSink { type SinkError = E; fn start_send(&mut self, message: bft::Communication) -> ::futures::StartSend { - let network_message = match message { - bft::generic::Communication::Consensus(c) => net::BftMessage::Consensus(match c { - bft::generic::LocalizedMessage::Propose(proposal) => net::SignedConsensusMessage::Propose(net::SignedConsensusProposal { - round_number: proposal.round_number as u32, - proposal: proposal.proposal, - digest: proposal.digest, - sender: proposal.sender, - digest_signature: proposal.digest_signature.signature, - full_signature: proposal.full_signature.signature, + let network_message = net::LocalizedBftMessage { + message: match message { + bft::generic::Communication::Consensus(c) => net::BftMessage::Consensus(match c { + bft::generic::LocalizedMessage::Propose(proposal) => net::SignedConsensusMessage::Propose(net::SignedConsensusProposal { + round_number: proposal.round_number as u32, + proposal: proposal.proposal, + digest: proposal.digest, + sender: proposal.sender, + digest_signature: proposal.digest_signature.signature, + full_signature: proposal.full_signature.signature, + }), + bft::generic::LocalizedMessage::Vote(vote) => net::SignedConsensusMessage::Vote(net::SignedConsensusVote { + sender: vote.sender, + signature: vote.signature.signature, + vote: match vote.vote { + bft::generic::Vote::Prepare(r, h) => net::ConsensusVote::Prepare(r as u32, h), + bft::generic::Vote::Commit(r, h) => net::ConsensusVote::Commit(r as u32, h), + bft::generic::Vote::AdvanceRound(r) => net::ConsensusVote::AdvanceRound(r as u32), + } + }), }), - bft::generic::LocalizedMessage::Vote(vote) => net::SignedConsensusMessage::Vote(net::SignedConsensusVote { - sender: vote.sender, - signature: vote.signature.signature, - vote: match vote.vote { - bft::generic::Vote::Prepare(r, h) => net::ConsensusVote::Prepare(r as u32, h), - bft::generic::Vote::Commit(r, h) => net::ConsensusVote::Commit(r as u32, h), - bft::generic::Vote::AdvanceRound(r) => net::ConsensusVote::AdvanceRound(r as u32), - } - }), - }), - bft::generic::Communication::Auxiliary(justification) => net::BftMessage::Auxiliary(justification.uncheck().into()), + bft::generic::Communication::Auxiliary(justification) => net::BftMessage::Auxiliary(justification.uncheck().into()), + }, + parent_hash: self.parent_hash, }; self.network.send_bft_message(network_message); Ok(::futures::AsyncSink::Ready) @@ -137,10 +225,17 @@ pub struct Service { struct Network(Arc); -fn start_bft(header: &Header, handle: reactor::Handle, client: &bft::Authorities, network: Arc, bft_service: &BftService) +fn start_bft( + header: &Header, + handle: reactor::Handle, + client: &bft::Authorities, + network: Arc, + bft_service: &BftService, + messages: SharedMessageCollection) where F: bft::ProposerFactory + 'static, C: bft::BlockImport + bft::Authorities + 'static, ::Error: ::std::fmt::Debug, + <::Proposer as bft::Proposer>::Error: Into, { let hash = header.blake2_256().into(); let authorities = match client.authorities(&BlockId::Hash(hash)) { @@ -150,14 +245,8 @@ fn start_bft(header: &Header, handle: reactor::Handle, client: &bft::Autho return; } }; - let input = network.bft_messages() - .filter_map(move |message| { - process_message(message, &authorities, hash.clone()) - .map_err(|e| debug!("Message validation failed: {:?}", e)) - .ok() - }) - .map_err(|_| bft::InputStreamConcluded.into()); - let output = BftSink { network: network, _e: Default::default() }; + let input = messages.select(hash, network.bft_messages(), authorities).map_err(|e| e.into()); + let output = BftSink { network: network, parent_hash: hash.clone(), _e: Default::default() }; match bft_service.build_upon(&header, input, output) { Ok(Some(bft)) => handle.spawn(bft), Ok(None) => {}, @@ -183,12 +272,13 @@ impl Service { transaction_pool: transaction_pool.clone(), network: Network(network.clone()), }; + let messages = SharedMessageCollection::new(); let bft_service = Arc::new(BftService::new(client.clone(), key, factory)); let handle = core.handle(); let notifications = client.import_notification_stream().for_each(|notification| { if notification.is_new_best { - start_bft(¬ification.header, handle.clone(), &*client, network.clone(), &*bft_service); + start_bft(¬ification.header, handle.clone(), &*client, network.clone(), &*bft_service, messages.clone()); } Ok(()) }); @@ -204,13 +294,15 @@ impl Service { let c = client.clone(); let s = bft_service.clone(); let n = network.clone(); + let m = messages.clone(); let handle = core.handle(); let timed = interval.map_err(|e| debug!("Timer error: {:?}", e)).for_each(move |_| { if let Ok(best_block) = c.best_block_header() { let hash = best_block.blake2_256(); + m.collect_garbage(); if hash == prev_best { debug!("Starting consensus round after a timeout"); - start_bft(&best_block, handle.clone(), &*c, n.clone(), &*s); + start_bft(&best_block, handle.clone(), &*c, n.clone(), &*s, m.clone()); } prev_best = hash; } @@ -275,3 +367,4 @@ impl TableRouter for Router { future::ok(Extrinsic) } } + diff --git a/substrate/network/src/consensus.rs b/substrate/network/src/consensus.rs index 630506739ca67..006ff83c4378d 100644 --- a/substrate/network/src/consensus.rs +++ b/substrate/network/src/consensus.rs @@ -46,7 +46,7 @@ pub struct Consensus { peers: HashMap, our_candidate: Option<(Hash, Vec)>, statement_sink: Option>, - bft_message_sink: Option>, + bft_message_sink: Option>, message_timestamps: HashMap, } @@ -125,7 +125,7 @@ impl Consensus { stream } - pub fn on_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, message: message::BftMessage, hash: Hash) { + pub fn on_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, message: message::LocalizedBftMessage, hash: Hash) { if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { peer.known_messages.insert(hash); // TODO: validate signature? @@ -145,7 +145,7 @@ impl Consensus { self.propagate(io, protocol, Message::BftMessage(message), hash); } - pub fn bft_messages(&mut self) -> mpsc::UnboundedReceiver{ + pub fn bft_messages(&mut self) -> mpsc::UnboundedReceiver{ let (sink, stream) = mpsc::unbounded(); self.bft_message_sink = Some(sink); stream @@ -184,7 +184,7 @@ impl Consensus { self.propagate(io, protocol, message, hash); } - pub fn send_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, message: message::BftMessage) { + pub fn send_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, message: message::LocalizedBftMessage) { // Broadcast message to all validators. trace!(target:"sync", "Broadcasting BFT message {:?}", message); let message = Message::BftMessage(message); diff --git a/substrate/network/src/lib.rs b/substrate/network/src/lib.rs index 5a2727938af52..1168eaf346908 100644 --- a/substrate/network/src/lib.rs +++ b/substrate/network/src/lib.rs @@ -62,7 +62,7 @@ pub use service::{Service, FetchFuture, StatementStream, ConsensusService, BftMe pub use protocol::{ProtocolStatus}; pub use sync::{Status as SyncStatus, SyncState}; pub use network::{NonReservedPeerMode, ConnectionFilter, ConnectionDirection, NetworkConfiguration}; -pub use message::{Statement, BftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal}; +pub use message::{Statement, BftMessage, LocalizedBftMessage, ConsensusVote, SignedConsensusVote, SignedConsensusMessage, SignedConsensusProposal}; pub use error::Error; pub use config::{Role, ProtocolConfig}; diff --git a/substrate/network/src/message.rs b/substrate/network/src/message.rs index 81d73ac1cb07e..5ab6c2b6a381b 100644 --- a/substrate/network/src/message.rs +++ b/substrate/network/src/message.rs @@ -149,6 +149,8 @@ pub enum UnsignedStatement { /// A signed statement. #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct Statement { + /// Parent relay chain block header hash. + pub parent_hash: HeaderHash, /// The statement. pub statement: UnsignedStatement, /// The signature. @@ -157,6 +159,7 @@ pub struct Statement { pub sender: AuthorityId, } + /// Communication that can occur between participants in consensus. #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub enum BftMessage { @@ -166,6 +169,15 @@ pub enum BftMessage { Auxiliary(Justification), } +/// BFT Consensus message with parent header hash attached to it. +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +pub struct LocalizedBftMessage { + /// Consensus message. + pub message: BftMessage, + /// Parent header hash. + pub parent_hash: HeaderHash, +} + /// A localized proposal message. Contains two signed pieces of data. #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct SignedConsensusProposal { @@ -233,7 +245,7 @@ pub enum Message { /// Candidate response. CandidateResponse(CandidateResponse), /// BFT Consensus statement. - BftMessage(BftMessage), + BftMessage(LocalizedBftMessage), } #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] diff --git a/substrate/network/src/protocol.rs b/substrate/network/src/protocol.rs index 229d2a2d244be..c7e438045f38e 100644 --- a/substrate/network/src/protocol.rs +++ b/substrate/network/src/protocol.rs @@ -303,13 +303,13 @@ impl Protocol { self.consensus.lock().on_statement(io, self, peer, statement, hash); } - fn on_bft_message(&self, io: &mut SyncIo, peer: PeerId, message: message::BftMessage, hash: Hash) { + fn on_bft_message(&self, io: &mut SyncIo, peer: PeerId, message: message::LocalizedBftMessage, hash: Hash) { trace!(target: "sync", "BFT message from {}: {:?}", peer, message); self.consensus.lock().on_bft_message(io, self, peer, message, hash); } /// See `ConsensusService` trait. - pub fn send_bft_message(&self, io: &mut SyncIo, message: message::BftMessage) { + pub fn send_bft_message(&self, io: &mut SyncIo, message: message::LocalizedBftMessage) { self.consensus.lock().send_bft_message(io, self, message) } diff --git a/substrate/network/src/service.rs b/substrate/network/src/service.rs index ce5ff0059cb31..b525683d713f4 100644 --- a/substrate/network/src/service.rs +++ b/substrate/network/src/service.rs @@ -28,7 +28,7 @@ use protocol::{Protocol, ProtocolStatus, PeerInfo as ProtocolPeerInfo, Transacti use config::{ProtocolConfig}; use error::Error; use chain::Client; -use message::{Statement, BftMessage}; +use message::{Statement, LocalizedBftMessage}; /// Polkadot devp2p protocol id pub const DOT_PROTOCOL_ID: ProtocolId = *b"dot"; @@ -38,7 +38,7 @@ pub type FetchFuture = oneshot::Receiver>; /// Type that represents statement stream. pub type StatementStream = mpsc::UnboundedReceiver; /// Type that represents bft messages stream. -pub type BftMessageStream = mpsc::UnboundedReceiver; +pub type BftMessageStream = mpsc::UnboundedReceiver; bitflags! { /// Node roles bitmask. @@ -93,7 +93,7 @@ pub trait ConsensusService: Send + Sync { /// Get BFT message stream. fn bft_messages(&self) -> BftMessageStream; /// Send out a BFT message. - fn send_bft_message(&self, message: BftMessage); + fn send_bft_message(&self, message: LocalizedBftMessage); } /// devp2p Protocol handler @@ -255,7 +255,7 @@ impl ConsensusService for Service { self.handler.protocol.bft_messages() } - fn send_bft_message(&self, message: BftMessage) { + fn send_bft_message(&self, message: LocalizedBftMessage) { self.network.with_context(DOT_PROTOCOL_ID, |context| { self.handler.protocol.send_bft_message(&mut NetSyncIo::new(context), message); }); From 43e2113c3275d956e349c555ede6834cba82185b Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 5 Apr 2018 18:29:18 +0200 Subject: [PATCH 09/18] Minor fixes --- polkadot/runtime/src/parachains.rs | 2 +- polkadot/service/src/lib.rs | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/polkadot/runtime/src/parachains.rs b/polkadot/runtime/src/parachains.rs index 18137427a3e85..ef46a25146e62 100644 --- a/polkadot/runtime/src/parachains.rs +++ b/polkadot/runtime/src/parachains.rs @@ -44,7 +44,7 @@ impl Module { pub fn calculate_duty_roster() -> DutyRoster { let parachain_count = Self::count(); let validator_count = >::validator_count(); - let validators_per_parachain = (validator_count - 1) / parachain_count; + let validators_per_parachain = if parachain_count != 0 { (validator_count - 1) / parachain_count } else { 0 }; let mut roles_val = (0..validator_count).map(|i| match i { i if i < parachain_count * validators_per_parachain => diff --git a/polkadot/service/src/lib.rs b/polkadot/service/src/lib.rs index 620e93566dc59..8e3a21a3db21c 100644 --- a/polkadot/service/src/lib.rs +++ b/polkadot/service/src/lib.rs @@ -142,7 +142,13 @@ impl Service { let god_keys = vec![ hex!["f09c0d1467d6952c92c343672bfb06a24560f400af8cf98b93df7d40b4efe1b6"], - hex!["84718cd2894bcda83beeca3a7842caf269fe93cacde0bdee0e3cbce6de253f0e"] + hex!["84718cd2894bcda83beeca3a7842caf269fe93cacde0bdee0e3cbce6de253f0e"], + ed25519::Pair::from_seed(b"Alice ").public().into(), + ed25519::Pair::from_seed(b"Bob ").public().into(), + ed25519::Pair::from_seed(b"Charlie ").public().into(), + ed25519::Pair::from_seed(b"Dave ").public().into(), + ed25519::Pair::from_seed(b"Eve ").public().into(), + ed25519::Pair::from_seed(b"Ferdie ").public().into(), ]; let genesis_config = GenesisConfig { From 92fdf466501a603bc176528d590d10920e489d91 Mon Sep 17 00:00:00 2001 From: Gav Date: Fri, 6 Apr 2018 10:06:40 +0200 Subject: [PATCH 10/18] Work around duty-roster issue. --- .../release/demo_runtime.compact.wasm | Bin 196909 -> 195836 bytes .../release/demo_runtime.wasm | Bin 212625 -> 211583 bytes polkadot/runtime/wasm/genesis.wasm | Bin 134951 -> 190794 bytes .../release/polkadot_runtime.compact.wasm | Bin 190956 -> 190794 bytes .../release/polkadot_runtime.wasm | Bin 206587 -> 206425 bytes polkadot/service/src/lib.rs | 17 ++++++++--------- substrate/runtime/executive/src/lib.rs | 2 +- substrate/runtime/system/src/lib.rs | 14 +++++++++----- .../substrate_test_runtime.compact.wasm | Bin 16318 -> 16318 bytes .../release/substrate_test_runtime.wasm | Bin 17828 -> 17828 bytes update-genesis.sh | 3 +++ 11 files changed, 21 insertions(+), 15 deletions(-) create mode 100755 update-genesis.sh diff --git a/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm b/demo/runtime/wasm/target/wasm32-unknown-unknown/release/demo_runtime.compact.wasm index 678cce19cb9ae31f9bb6759d50928d0c285e4fa7..84040bcf067929583ebd3d19e3ee19c54e64dd88 100644 GIT binary patch delta 53956 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±IYL- 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 delta 55451 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�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≺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 }xy}Gv1o#p%{!_+@YuL ziUHIs{Z_eG>&4|xrBpvnY(#{=(OFyWIWMN&(sEpHmKO%qO06^y#`NaLfWKtTnNcUf z-f=+E>z$4LYgp>yw(4&!S=65D)MmG}FeooHy47a2`^ec_lpCySetLsuT}&JX+3Z6R zXMHo~FLL4oaiP%D(mGD?O`~bb)fW2Y@*plZTa`w?R;iw=xn}k$hublfD)n3OLZ34I za;e@Nbk5%;e=9T5gKDSLt1S$gonEhW=k#8wRI8;DlU!@|nvH6yd>2KV-Fj~@=r^jh za&w_ks@!?eYP~yXEmYxCu=9SuQoZw{wPwG*(Ct;}aa==))b6}!v)-u3$gXa)7FS`6 z^*b-RP;S)frMO#eG-$HfYurWAMs?6b*ftyeYNx^k-9^z(t_zL_O& z?QAHb4R3Ke?&9L}F`B6pARh^7n{H(Yb#@`!L9bbXq1B+I=Eb+5&PtCwfk2`}- zqu;AkoAqve;k`d}AuO+2@Al*&fE`uN8KdUn^ZODDgye*Mjv1Os%R5~8ZsY$66agZI^zKJg)wI#tx$ za&?z_TW((IG+iApmi#)Nq5AbgWd{8zL%X)iMb;zH3Wa$k3aIkeF#0x zWt|A^tq|>EN_C;9{_#q=Rjbtor7qI1kJdJLcIS4$e2fK;z3s=Zvu-5q7D-?f2!tFK zMP1%rj<=EkU<$KKl`^myEX37LzcJ|aKl*6GYPTV%#l_VQ;{DRI-0utDO1X-!pgdSu zKr!u>Dj$pAxV-x8VBxGnf^o~+=oOcVBBqQ#t-e@tIj&$>H7l)Vtnd zAeg9AeQc`=hDSW8luLuS_d~y&-GeS`<|uuFg~2#Eyl=GY=+nLW5E(uk5B7bx+S$A+ z=gU(&+ZRrE9>x0#lYE3#Yb-BVT-;Sn$O<7D+aUApvOV5^J|1%0rNOdLqT6rvYORG5 z4xviC(80;P49vCOrF+KE%C8TXo3-nyz6dJR0pIB_bdGlPD8`K_y(P7_PP@mH^* z=Tz!1e1D39ttdp}xzdPBwcY~CX$`#YFZ8eO$G8%6z;6ID&c#M7+`CI=T~JX8&sD2i z?$s+b`q`|me19EG^k*r!9UL8{g-W;5D#xq)Imq|zp!IBtJs8`5X}`EyrBiD)6!d|F zs@2Zg9S=9G`rUG-#{wajeyiCm)#6f&CAI$4K0;>SZuP?MnkAP12gm(FzceV7s=c@e z%C|cGjh{{hL4#7AR2QtWy`j&Lk?8O$3ima()UkKL>9$VFx!ou%R=$}~liJgh?8GEm zIQCJeLYSn{E9jT$jgjGk6~K*+k$+um;uZ_ytY5#QAvLV`Fno7Ebw zscNfS-??koPNiC^TzhFBprj|%{EW*ePLJ6hy$cvDt8XS^hSxBro83;6sjc?9FMWPL z6@K5ApRg@Z7e2J3EmMy~Pq1kCk;rxD&Gx3#t>F*@^=s8;w^C|e|H2*j=A&yCHH!P# znoc3R&~{qY<^ChlWkr1+iKH1n5`9D~__ud9<2MB`BKQ>~UT@H=L-Ng+-!i9Qqtiv- zBVyix$dK-T{H`&lyil$Er*9CJFD;a7cz5GY1!KA1>VI-&A52T3d+;3Gfc3)TFKE1&QLp*b7SEtJLR(Q2DoT9R){`2g?(11($Ty~cA+uCS~;wR~|{U@`NNy^rbWcTytB~mKLz_hf|b_VYm zY%bK0H4Bv%;m1;=^7-srq>gkttv=zKa*xm=D|@Ox`c_q3tqkIBe^4q{ddSFD{ZD0m z$UDTME!xC{?`&>~3RtYwMbcm`mO5RA_@}dbV%L_x%PRG&Xw~ed-&~Wv7k8VbZf(#) zb~3wz`k%>quCc2bc7bnbmjwj~43^NsOW=699+&&CW&P5JT?IDS;s`#Y&iG>mmVEIp QOP_GiV3Jq+gmNqYAM`>53;+NC literal 134951 zcmeFa3zS{gdEa*)_ujd4=XGZQ3|NHhn=iHg$3zEBR*97nE$Jvi>fBSpwZ|}2Da{K*vrAd;cKQMDRfAGNv z(+3Y{_E(8S@#Jues2*6D98SqP~WB1&1JZbB3SC4=2*pVYi zN6DQ^{?L)*vGLnJdiU{rk}*B%>Cs)c-+AXfA5OY;#*w=|eAm56GLmuc4|~RhRXK9k zUH3e2WVFcrM~-{Ol#1MYjBakb=DV+PA^Z}y;eKDH|_P>d78|QJ)KTtklewviY zMDK5W*Yf3WzvQj|!OGiukNy7G2mUb6y3l9Iv*oN+?mIdh-=DRLwCt`eXUU*bjF-v& zY@rxGlpe_Yr21==ZS}vm7+=mvFJ}wG_FB=|pCrY2(JotSR=OAZ%=M}ADtZ0Kw(BMeO z`mG6?Db~P5w>-Qy>`o;U6AV$!3{#B`OswR|uy;Ul04OYXyyzXsi&ALXM}w`Ii6og= z&(g66!II5-|LCwQymy7pNdgVX5eF$i7ffVc<~I*pi$eo0rQ7yV%^A-@YTMDP8S{Td zOY_!U&L)R>`QUq}T1EcuDQYosEg;GJd#B*a382&jPG%EjI$(H^2Q4$NMfSeo*y6Aw zObB)4b&hI?DJ41qEo16~#smfUGYn|dWF(VmY`kcJIQr}|V>bHo>6QNeWa2kxvQ~rg z&&(YaiL~MfKzn+5vH-aGePwz*J+;d02FB1f#L`&*Lz9{jVZ3uF{eV9@nDi&}2~`gH z?-%_R6!?(?Ika}`RHj*6SSz!G3A5j5Ob=o~8lb2>SBrYIoONju!cm>Fvo;hcr^gk& zJV|0>;A#jK?LlkpiX^!vrIn(+oScTSyL!Up@^@yfd^i(&J)V>sNq?`U#^ZBx?D?tO z`pboo(2=s}DJ@!8q*WIgM05(mP~+ZF-9^W8fHpLGC^?V|n%zuS)#@(DPVE_D=&5gz z)8_tUma?#AM@VeL1ZuxAgpCZAU&)vK@iU$(JoS{P7CiN&r~00HKC_lO0WML^Uob?M z&-?7bffb&W#q2Sm&DjIZ+4DAi6$L~Jc{m?I6UaXW%8UkERjbM}>dTw0K2NKsM6`kK zAc5E_L_|JqN1`ZC&uyVJWo@OjQ%L&Lb4~=_cGc=>BQ+7|Igr}vx&N<7ZKCWB(jY9` zmnZ$Qd&3mcaDXUtnFuL@Wah^R2kF7tetk|`D0HX$q}qe_}4X`)SqZI-CL4i1rd(yHz9D|50VJOlo1mtSsV zpjX@FV~q?HYr8zr$gq(-+Q>k>Lo$sFbVIv*sLE&~rcw3*(v|%5j7dy~xVs7BR01Uo zPu5BpUZ8fwOLwimM+kX1XI^~VFvxOtA|Iw|OX|oFm9I$|f*gCS-cXFpShlJHkD~n0 zA5!4nNG95(z7ae<^WWE&V1R=v}6SSpk{$>caOqlMo$m7)z><+W=zGsZts^_3Oi z%o(-6WWO2$BM$?dQZLR8QI?M?Mfd{DDMR5@N5Ed5yfjmGAVs=8Go!h)=vj+u6z%e5 zi)%1uW5n(>%_wL}tmLOUGC@pHb)}sKX(|0q2Wk0AdfzbhE-;dAU?l1N_j${hT%o^0 zG0(&<%Mw@NfHW6$IO42-Aes36sjO@$@s0H8@Q}=bL*k)saY*!?D8+2tS{y=$4oWdy zk*aahNl{`|t__wbv`-U0$YH`FU$t~mlrJono&E>O8}J+QyO7^rei!k(nBOJ*mievl zdn><7`CZ2Ea(>^%?+SkV_`Qwa+xfkN-acCu5J&>)Zv~kkgXcdF_ z)Us%!-Dp;&Xrog%t2Wlt1KCM6a@t3?w`f(3D2qleg4`l(%A%2ri%!f^BPVI(a51Q$ z8x|LZ#}^hCHwzv%h-*M=_+AYxLA|s#9212P!dNfBFjsmQ(r;NCjw^j(NT0tp>?yrB zq!-tQ6G~qc(&w!WCzZZ9r1z{1rDjg6PNlDqNPvJt_RQLFm(p(w>FKrMywYzE z>8Z8hZl&K5(vxe$1*NYH>4~-B9;L4e>E7D#Jf-)C^!VCvQRxFkN5R!0du(lZzS7?v z(pVmEQTkv=v;Me1>1&EZmnVNa9sCuA|9Luir^1uz0PeXw`CIAWx=EpgEU^8UwpTUb&9JMEEWe8oLB5uu&206 z!9sDRg5AYC6wDWISFo#in}T++Pr=UO3I#ig?@};VT&`fYxJ*I6xKzPR@m2-X#fpMf zv8-UKxJ1EZaj}Al;vxmTVy}Yn;z9-8VyIxO7!XV#!_u`uk%5Ed>`I9}TS+cybV;$q zLycE4bPXd_46B2&Du#MB6fKpk@(oK%*nN(urIO{U;bIBCb95|~7$}C3rLwo?NLeZ; z)*LTOT3H%umddF$$IenYz2*p7Dlt64+&GEIws@zew zRI+$5tSy!EYmT@jtu73AOIkY^`j*N)YmULC^1L-i;!?S|=6GC^(PF4vD&Ml^*jy?v zSaXCf!R&@p@WL{DsVIu{CKlmES&%FzATGquQc+3|y5s{bOA^>i)#B7+2qu<|-(#}6 z_?`p#$+T3JjWnn?#QQt???@(owVm}F`t1bzZ5I88N|-5TUB}J3jw59{ZdN+3pRKxv zBLz8`hMUe;sd6e=D`v{)t}MI#50X4Xk}|ilX0&G-Kt`SZzfUR1W`>4%{y~wA*)Oxw zlIVooD=QjhvOO}nZtY4sM?q|lXnHKvBH9h2cea>a$?iRn?F#_V;CPY8hk{oP^(rx+ z6=U(CYVJFb-3n`rhrCYF3$bpIHOt+4AiI|y@LtgYj)wS5IkZ1n=?p6ad{f0{2>bLi zQS~!f^)nUQ5W%M6c-j@{itOVIJ0=y*FNxQzF(cK#B;G$A;{B(u?HC`!o5~Vnt7Cl8T-*AypvBvm7HPP(QKU`Bc;*Fg znDJEHmKPqk+VaL0)H267o(?(23FH`8scf|{*Qb_zgR~ec^W%dK(mfMIv?qmtzNeT< zl&My8=6|L*ZJ@jQ=c(nB)M|IeQ2t{ebIisQl_wg-@hMCQr3Q=!AO|j^EOI2+A_zBB>4C<;Oi~^+ z;F6de+rHs|)6lTh(#8W5oBJS^3mZg1s&J3aK+Td~&X$E_e5s(GwYdnA(!T2T$0pOq zq!OV>a}KDes>@-p&*OWCkm8lZ33d|jq~9PfRhN^2Y3&b~NppzcAvd3ltY(_)3lOc~ znQf9g1-#(`3#LK~4irNRvtww%NnzCS?kOA={nlh>GloR$Yvrs^p9acT1C#B|1%=2&&v}@?~|0xjo0p&$n;bta>M!x?y%_Bm*ERIqw2VkucnWSHoQ@Mr9LW6kJD` zEg41-21kz;bcETm<(#{x%}8oc7f{I~CB_{S<9201)LT{oK=7o1tW8N;z%Py66heYy57{)x5O>Jw$>#nOOll&F$bgVsIla!(n!ygrBc`;gtk|bRD3@^ zQEUg3O;QDuLFDSkM&7s0EgV9u90d_+S3fXuT7EOFx^XaHZe(CErsbJNh5`NujSSd1 zEnjM6u!Kv?7aJKimeY+4+wc5Vm0`#ONm77O3ZltOP#_4KAR`yXg)nUmX+l&b6x?=f zXRA)a6g-yIgSD}pXk^&f9&KdU*dA_V*w`LwWZ2l&8yPmXKd!nR9b4a=olvijE!Eh3 zE;?|mkN+oGRw3KU|07u&XnNj;%aLGqZNMI<&E6U=YgF+K2)a%=XY#CkfgX|ap=q@* z{Fr`kMGPv1pmm!=sxoS90|$jbL1*-#w1ech4)kH9{l8JS|%yc;Jv zzBbMSY}@PG#MxD^=Q7D?^iD8%{!&2vg%l7_j_hLu2ZApMe5~KaD915{jrvS+81>ot z99tfmn>T0*t1a~qj4mA|8IF${U0qaf-pA^SdOQYGiVb782mq2k$ojKb5B0gK@!D!GumdT4c8fu!7@WbaRtHL5~2Y zBIzxQh|c83sm$x@gc7|8a>0`e^41`;vo}DVO{H2%q>5_oq9R3VK;!NMXsT;VR43R1 z(8Bcuu%1fFSvhknp#R-?HqkI$Hiqy>;4*9d=sdF*UPwDpe`-f%Ym@If>G8qoHeun+8*C zLUc^z)(~QSOv!$;CuU)EEx!FYu5640M{fm)4dfe*3>(SwjSL&gbBzoe3r0iLh7IQ0 zI&FiwI;NY05v<$8_rV5yc*?7`4Zc5UWEgxeH8Kpo7aJJ{-|0q%!S}63h5`7^DkDG$ zHGys!B+wJB2KWAK+Ak*6iRfR;cXoUw{T$a&Owd`s-+g?(=kv1P9jSn(}9S( z0rCI_GK1AU5z>T$AOJ5ikJ4%qvQtCg!5VT%iC2&!m;@=oUILyJ=B*y|7a5lIRuV(%q>GF>?0~dK$CurHJ*rNP&(HD|V%NePHTP-Q$`A zBEvO82gb#GSEmRKfEVc2)9O%1c-%^$i+AZ1P|*`Y@oG?ld9hVHHiPkgpUn@g;sqd( z3qagAg%CoU5x8;HZDFV~9eH^ipVO39{P?HnV?om)E2d}3or4r`v1rtR9(17$*^pg8 zCW#*DSx2$)o&)Ao1cWy4QI$+el}wGQl1ZdMzKXz})CSI|#C~OQMEI?AIv!LudS z6d4){12f3A@VeLIAJM|#IC1G#A26jf;DusJ98>XJ2J{BPtvOR|L4888S~t43iKt4t zKcsEF(w)ykW#4zS%t~s1NJq=6q_*!-BT85P5T-QvLs*`?)_BZuJvtsUNg#Lw^fkw0 zV$zVk?8q*t1nRH$)IL%sUjxOFmV9-JtCy5vtd(jBBzI-4E^O=#J#7Tn(9?#ChMqQD zH1xDlTM^rHViOHr4a$5?IBlRp{_>^(WdIdbFfDBiBN-9c&=?cRZO7D5m&Ql6HVT7! zp;Av_Mw?pOhSk*CHm;`Dwt+RZwv7z25;SXbXu|!g!P!)s2I$$Ui2&%!jSNG7Q+*qt zP4#VnHr2NQ+Em{LDDr0%Q0!C90Xxd#FT6QXREcvBlX8hAmSR%Kki??xwlNZFQ~LQ1 zq`EyYew;G>VP$H0!IOKVyg(gGUYK$=v9an}hW87YKw(a#go z&+?;&L8`}qGO%a@8co5Rm}^e@nav6CDg8{F_iBdN-B3>?j}IoYpr6O225o};uVE6f zu^McGS23mxF&uos$}mth7;l|cCZy%NYDF$3=%po1-9l5hrKw*_(6!_&7!`DXwgtDL z>eUrd{^xBxEJ#P^CvZLbploj)jBBAcs#Uefgw}498eYy;2e<_Z-(^}1G01CFqA=xM zjWq~Cne^`|W1s9ocB7#-D9j9Vr&A7lnO4Vmc5W`?`e5pYSlj`d|S_bS>(ZVq)&i|-MJ5~0snwJN){N7+Xf-f_sI@JEh%~=9TC!qR5xO~T zCGCT^Ty!oPH0Hq)K$nRDjO0x;1KUn9p4Lmiq=*2)4Xa5X)9DOi8ieLP*?s7bl1(#z5^`Ci=PeqVl z%z|&XhnzR2=}uJ9@jBX@=un{F@t`&Fb6MJ|+||6ujH+psmkjKUPV?&ylk&vxB%Ih) zu9?QLEI!q&{G?W&JiB+8moFyw;vy~|%h#^(R}r)FN3{L;VsiIrev5p(ElK&xZ~WdB zH{iUC_WXIX@` zA^&;ZmgP5L#^vOXG50SilB4}g2MOHSrm~nb`Ab~Y^ZUBEdWw4h9?Y7r$m0tYW#wj+ z@Y*Rd`w-OgL8C19gEGy$6PAdw?AfQEfXud#RwB|;{wC7OMOvJkIwaEiKIqBXSRZ!K zNGJ<;?6n6Skyhskx^e1iiMn!8S1y9yraO8XB-ElF?iNv3r~`Fbor=0PwY8bL{IRGj z7j@-O7q)9aU2lTA{`Pn}RY@&g#GesuU0SZMKZkIWvYsw^VJ=@p(oC1x10)7* z&EM!h747;-&jgD=^*Cjzjju7iFF0Lx@8h}zjF6)PPNK->*f*ReJHLLh%};tnyzN(mX>j|PtIb{bX8lH zj6DvfP5D#-oh0&|Wi%BEl3|8Vk>Zmcc{rHn9K*K*h1Gr|P_W>7Ehx<8KTQ$*jr$1p zF-e=@!uulZOpRg(12SNSQ?52(W7=Tj*|@jE3LPdom>&>bazcTf7){@J1eAFQ$l^4Q zyb0NAzRKDD@mp-dS+;S~UwfWvsG1*{!^{s8<30!NW9p2q(TpYzP6qAlbV4T&;G)sN zCB-_Z93J6Zk+awU!;%FFjJgE@y^`REh9ssBCJ^FaisJTox?JzG3tMJ`DY7{XlMZ_2 z(xBUTzTQ%SoB|mI@ZFTBRftWba%M0oRY$Ys+yk6bJEqoKl*}oaQF2`+Q%YVpn4}yQ zf6+b0uEumZ`M`ZekMde7Qsz2s+1PVrWS8fi_}p`GFHM)%-A7^7fgCiMoC^kd5zV?6 zLk=fH^F)Q_aYyqwCC9w2siIe-Sqq+;R&2)WHX|w{GckXg7)faKCC+Ow5h$|d1wOC9 z{F+Ks{vZKZRtvYl{ZKD24Hg(cSus7($uC0(zCG7C1iT72UQh;7oSqb<;!} z6O4+U9)83klRyMIYf2!dm+{Wvc=_OaXg1TB*xi((hCMP(6re1qQ>`x%sTSNaB@?5! zM%D7y@mw-~jKztmjt*&gw5`+3>W8s2TJQ04%3pUMt@lv$oU!M{X&3|ZRp^#4Q0;4% zSL0MAy)vm9E!FUOsq=J7Nqfe+I$;r(l=;Lg>r-z1;CC^n84ovob~kjVq%T_ zc9=xXRsNcD#qko!rbvj0w27mVgkk~B3q2-pvPY&L0-zOpCEQhJ4}gNo>`7%Zt#%C& zN)cN@lx*<_}L85|7m#E_ux0&x%5_Q}p-$n`=m+VYU zd>$q0I5JYwctR3YxNad)$7o1XG$K*Qk*HltPe@v_JxIyx}neX-)?}ZY%pc|!+bVX@0kj0{%3%55aQ!n5nOin53*I{Q{~z0MeMhr%oD`lduS`sGS_a<+UbD^Kkxe=F;M_f*EMMCHFx z9kbw4*s^QKpvsf;<)Az>Uw$bqPb`!#sc+))4J7`~FMVvSTvql!`AK5EoA1+qu!WqHoe2>e z^7Ggal^CyM_kaD+I{%$Y9zu8L5=~GW!tGG;@Dl^9$0r73LLTBf9VAUOBIdADX-Gm3 zIVs*tOAcwt97rLkvHNt+zg4zwChJ?+4xqO+-A;H*C&vesP$(<^AI_99PrO2c>?MzV zX5~Xjo-H|Sl?A$T+NCd#u$&-uFFF z&fLdr_ikD&v^=+7Gq4SX2$FvnAxTjjU_yESSIonWSEdl4NK7?_r_My5fg2_1Ppf~~ z#253l`=CkP!8oIpKTUV~z$@^{(A1CJos~;N;Hji}8RUi=%IB`j%r9Zur8deKi{sh6 z6euOHO*@w-reb)B2?7&(Z2F{9bPNbJAjIn*3PP&I6c#866GnS>_Q2ZH%>vR_oOY)% z^h6h4mM-cFCz>5=y`zR`+@6dy?h5U-8?PFktQ&44#iPS2cZdPT(Zct{75UdNG zwm}GmLJ;{;7VSs<9krsXtwyveLSy2W#?ww^CY|9_pK?`2USif`C~1Z@Rs<tw^|@&&7l+P}o13pI8m4 z1cF{-kw7qag*W5k03HAoNqQ*Q1PylptwGkUAP{7g8`JaJ7F-LEO0oRIBA_x9i9KQ! z$3hJVP-W2)H7i@CW9Vt|`VHtss0L=SCT%!MNGe3a-3#YPy;DP$vUIuPeZ@JotoVBC zrbXv04&Om|AVZUR8Iuu6FwlfjP)L{qCqW9yxbT_ZOU!3p)aNrV8W^21J(;gfb-bg7~!&a(f?|-%EnIW*=(ygMb z^>yIQg2G!{CZMx@-o{>CN1)cc8y;Lu@>=M(G*0W4FK~wNz2rSdcw_nKTL)?R%!3hx z1&E$!8@zEPJN9ZMO_X^t%vTG{0&GuqCOP0u@LqYuSj7cy)rOnDqsrTmoUtSs96Gp9 z7+)dPi06PRj2`M>$x61FrbypIwhoECL1cEaT58%QUdFnD?z1w3Qh^b~aoAcfUgF5p z)eBgDh*Xyyusbm54lR2Z8$eiQiM*5Y%v(+QbAzg?a{irjsl=$5vqKoGp_It}R8-~~1G7NTl8^h2% zm|Bl6({FlzdT~q`zXeBv^~bbuIhaX{I48oKUI8GGzX3gD6oSl3IZHV}FDeMMqDrEg zmf3&7ac?wcqy~)FhYBfaUw{bP8%j#_5MG&p2XG=PL_V7wqHv%bHk+gx(2C}pBQQKJMglT)jDTu2~DMA_N;YbgwP&;b|Y*}WZ>2B1z% z>mBIg00ZG=`<47^ouyV8k|3vlK{9cFmOhv_cc5s#rQY;n8iAlz--5bwk@5P<_mWCQ|jYkX3OjX6VfY0g9& znjO)GPn$iM)B~pv0U#P{%$X|roEhoaoLPaFr~h<8VYlTCgEAvf&e*-l__u3OE{h?! zm)Ibd6`Pdnf0Exi zD_IDDLMb)frk0fq@+mxUCm{qnSxm_EwkNRlx3GquDnA!g5>;Glj6_rFVo$x*gUb{g zOuoy5E6T52Rq8eem{1ZADUh!u%R{?RGe?Rj#}j%`ga^v9R|Tj-nSOct9c5Bh_e17~ zOf2~`YrO2*Q#_H~_hDJ&2q2qQ6ufzO0aM)r^iBo)lX*{ZJ&Q8WS8y=7z=NgoAqSfC zo~mWCQQ$2^xJQ8QD;Jd5IKVq#y(+w+wFa;(N&$AL>#?begZoE|&ZiG0ADBw|e_bk3 zCnO*c=;>RFqNn~}h0IRA!|zk8B43@#<{Gx`2DG|EB5jApx}GY$CV9xh{mExS`g0+C z)WUCw79I!Pl1nTMUE zrsZgO$j9JLso)n;^$8}$2=pSAFs8 zH46_WKOe$h;0lTJZFG#vM&~0Lb~T76tMM^*jkzA*NqcnIhqtcQR75aCAQg2ge*@IK zaHU^M_t%OY*x(3B0#3p@%vSqN%?L7;CSGGgx(!IT%mg(x$Sv3hf0^OWo>EE^&2@ZS z#Hz^qFvtP>WIC9efH;Z1OJc$fCtBHJuD?s!kEdvCFPUk^6$g`ZDm|yq9LyqS=W_C` z2hJL|$X~GgLyVZzuNftC1iDqE$~CKGj+uzL#hk?qY)t@-VVGbocpaM)yJ(G@DI*#w|UqsI<79~z#H*Hs15YPfIKu!v2`JAEohjN_sqW@86u z&hkup!J;E`szCb`ectrWpbW0@o8#iW!`$*3w3MCP&@15OlW&n21g0vB`WtTvgv?6S z1Oa0y5^uQwev#vi;ytmT#0Kxn;S+@cRpe($==L*9{2U1u?*4=q?}kVkPy9Ry^uN}` zwcPmyGT|3x&VeK&@1{(Fe~jWmYX`E8vQtD#7T2a49e_T>m>xn)$}{<3luUgHAV?Rj zr32Uj-~eg>auayl0EUHBf$;`s!(UVKc^`W1~%+qtjwJAZEbeKrlow| zgDnc`k>1G7pIWMLA0vhgZOi7VjF@DAgqO(3xajjr*<$^2zpT1`d2kJzu8*Gt+pAx` za}Al(FR#N_hcZa>)k61nh1(Rle_jhst`+Son8rx6X#{r7Gl3y3W2klx4x!^d{4lPoI)Z_1!Wcfyl-?Z6atCe|2A#*m1tZe z#oSD>%OG`ZERC{HepnKRlyXrgHnhK{X5>iraWQfs0l?KAquJ}Ji#_#L4=z(6o6LeM zIF%vfnn@-@Q;;tMIjGQxt09qG!6fqs8qz+Wt}S{*0N~qVLFo;E!b*drf^?rB8*O4h zO@S1ar|&~a7%E$GyIKr0zT>f;d|Z}?<=XYwwALJ!$NiqT8wS&w{3ePRf}NC)^RHc1 zn`*r&#xOYuqlvG1Nerw}fJRtKsm$iT!Vyx@dZgh=CjhHq*g{+z3DCqQd@(&U83g{O zFa{2Uu^Gv@h%vkTf}?X-@8oiR$dJYnpFr>O^TfeU11WH|5E~k#CHQ!P4crpF<`aAr zb+Ks@6)N_5RlXZwc@2i(6}E~AxL#F+V`CTjtH&n!_l*E*!p~qv+yE@`9HS%!lslz7 zMh46=y$#tT48lO&!DGXz2f80nHN6rQaa7k8sKogQ2VK~vWSnzg9L zTPq1~085s&un&~u2|eIVENOmLBnRp}H3N>4n=Q%KAvC=J*E0ej9$Avn^-8{asJ9MZ zGl0op%ZHRafx0P0ul$FRSBThx0rORM2Y{?Tm#G3G)HOpF&PZMFsrPvBUIhn}@Acpo zFe>Z`r-Ian&3JE&h;Rv5BVtt#790^$4?I`JWkzTdukqOGnE`+wTa9lwlQ^)NGg*)0 z&Ca9`z*N(@&ZH0g&CVikcruHq{g*?EoQ^(XVA!#(2dJw76WYm$)aDD#@6=fR|cgUPf9GrmaO1C8zp=Et6u zq&r*`v+gNhVz|KXse&hoo={dCq-5!A)!+BeB!RUW!Z#1pjbelOHlpR>zpFIN>iD~*YvBE1C!t$*Wxr`sY zesRb^-Z%A@V$U)~*@ePG$t|ew#(|pgI`|xwGrl#~)rsCc5`VOpvbY{?5y!imU*k7T zoeyzPYH*&8T!kvHQG78LFZ02y4s^bLmGi19Evj%#BM!8^1uz>bs4v?$P3`e94(405}qM0OkEhE@S+wd%08kjRehy|Iw z8so;1V>DUYCoH@sc`T&A6w*H(!mn6(F!`AfeihH%JMeAo(Vg`sIz(YIh9x7uoVxgE zc7MY1#I=>=h(K&|V!q1cM5%zYhzS(g+KJ5ar7@ki+*1}!R~XNi(fI@gTzHN{})+I7@6+EpW`)rjH5 z8)?G6?uc!+t1QDw1+O(CoFKw0RB$XXjECbPabzmF9;ZM;j`t^Q0`NCF$FM_f=&v$l z@2R>nR2}4_87a+@<4ywk5bq!?U^O#WjLTSf8JoL52`%BWYnSVS-L3(8odjCEyVF(@YyOgGtUd>a-q$DF68y{<_yew2xorCGkfgQfCo z+CP-tZaO#^>yX?+wBMVyJKqnG(e4^pWD_kzmY2osyQjK($7ptnlQ~2=K>ygKWgBnv z;uAd1rp7Sr`hQ*J+GekvE6C5i?K=pvea_&VvGd;X48f z4kAsEUS;UN(U#dQrskbfgz{BXYb75YQ z+qob!@SJ{Q-#`f;Cm-KH}iHd0%DblKX#XreQ*y>&Z!+{eC;SIh8k8+j+4KE6}Plc@5w zW!M+Px>(jK{yVYyk~3g*1sw=E%y7`?waK$ZjJ+BeO97cQG7(29a{)ym#vTBws(Y{K+8>kB6V&4Bp}s z)WWeej^)+i7+8uosl*%0I?M0Uu-f%Gyov$(C zx@&ZiMN9SB4>y5rjS6Z28eR z0ODCdQlGByEE=g#S9l{pa$1h?c)o&{gu@!AQ=PAHn0;|opLMB+S)Xhf9bH&e;tB{& zR;$WzID;iGN37#RDY;tb!z`FBK6NQ!fiG?`@ez664lH80+=0QOs>|7P z#(N#fW!QVo{74!hgvv`u;gq#|FTkW$VSW&s)A8{kv%tb7cqr5zb-5Z&lVr1C(#MGT{_i-D--uS?Mq6*EdS%AGTBEtr zd2Rb-jTf+M-aL=RyDka$1ozo`f$;W;DxqWb3X2Muj>2S>k(S@+Ktg!b5&bXgIy|Wg z{)iky+6$mSLK=jO7N9N}!qZ5Ns>uayAuRAsVA1aW5V(h_x7y+mEmq}oxXolGdA za7U3A3!LaFiiICK+P|Ip=Vl~^r3nBv9KE0*iEiFNXANUS_7*zJ>@7mvnv2(QgCmqMSl@wpKSA)pSqXn|%fG&DvoS|H>W z=}OM0(`-EwWC^a(_|)c;mhcCUWJwY@p9EP#17RJn`7~C@sv63o5wzh*7LBmy8?!`O z@Kci~c5UT}-Ohkbp6KC>i-UA0q4{b6V^^_zBnvQhqY)ZSK;gJ~x+n+F z9IqOI8k+?XY2zkKGP_ri;Rl{zBSEph6288 z!=|#8HlZr`sQUou*h&(7gi;l1%Mz#sa~3NRuuF7LF`?JK_UIGP(!adzvyiRYS1QU+ z4(7^YFe{v3qjE?_@33iyxRO|5ufZ7uONSmS>W6+^KGou5S0y!e*P;qowg@3^K923U z!(&t+NG^fK$x)`>B!s4G*gDXwi;DaZzCjkOq-v}1M#)Zxr2d0lgNQaG^ zSu`p>o^XaWHD{Cvv z>ymjotbnnjqlgQ#19r-}E;AX!M&ijO(OZq`$Rk(VwPIR36t9hupF1kbAc}7H>n;>g6;C4vSeRt0^XW0xpV)9^XKf(NBFGmqMS%oSJF(T z+;aA1+y(x8L!Mg+VA;&e*<(mLjmyQg8c^yRv?$jRFn9)L^eI&&d?7T@{}0WsThKTK zt(H~#M9e^5-Y*e$34fY!oKQ-G<-Z&SKSP#m;;$0+82)_0JDs-p#{!@CS7JWMbK`X_ z*TQK4ECm*3Oafe<}?t$sG;e`G^4=R8h4v_4;NojhGQAp>HSp zz?^OJn+r^uz&ve?Xr5gv%=@+uuNqeE*s2XPB%=vHdRQjRR|jCs3{R6>Cv# zJ>rbK+f&CpIIiGe@_+{)XQ;wIP%>0o{6Mt#V#|XCZ6mtBQ465#j*x3v85(WNSxuYg zJM_St9C_h~XF$z2QnrK*tO?b!Z(*$m&|*O3_OiFNGGbh{3OYeN7H z2cOUfFL2=TN)C{2&kK&8`Z$sptUi*YRDCSTnGclM*pwPMo@7>+a^pGfCf9HUXT>Kt z289Bl!`F#w&+q}j#vgqXHZ^CoakuU&+LDQ0#12u>m%mYKgD|;4ZC$RWaW~$J14+vg zCvw;_X~q10qfL&h(Qv<1dwN8l`{?QV~2gsndq}^ zjAVnBOUrh$4FR5I>>(S;k9Py6ja+V-482zgMsc*vX|f7L{rwLK8oSGN#Nk{0%pB=Q7CsZf3@TFTMy;Fp_~_2>_w)hJ=k)vx6#H*xQ%{O zQT*ukcCKgJeri?e>^0eJnmO%TpBcvv zIkUJ%gR7LETh7id`e~}Ua^0M2@ZDVb$BXvHQ_lO5`I$xBOjO!MrSc(mwqCT4O_RgY z$?~h5von^%G5A;p)pTZ2rPL*pJDe$LpO=@0DGSg1=Hc|>(3>mLBH><4o^tF&Z#yKw z$F0j4PRq2xoA#_sv6F6AjziP`fnx6RAWxy}_<{`AsARuZ;A^VvBg!Hj@6{(bmYZ_Rn%@o3}=eS9w0uijEU(hW3Z1cn%WQ zEj*Y!N~jv+4Dey)otaY$>r-p}+sf{%9TS$m^nW&B-e83pa1Za&L08(asi7qwlm2#w zoDoR%>~(Q6t5S+PsXCzO zJnsHQk~8>(F%6PYgn0_ZaCyS}K8zfxn|@uJW;!5jme5@J=#(Bq+Th2BZNsub(cmnL zjd1NkTHb3dah;KH_z7{PVg%xhl)LaHG0}&r>^JPJ|0sN79q)SL-QaJQ&uoJe=wVvW zi4jW}wPMjgAq+1vZJ5Q##y~lzoe~Yn0GTTxa))HDJY`Yi)AAb@7dY%X7+qD=SG8^Z ziz8zWs|y3G%6I|IFo)4sW$ z5|-bfAgw1}6-7b?K9)19waQ%iEYV$Z?alF`Z2lC6TDBTD(zPU@71#BWK3Yl86kLW+ zOWOw3wxj2oy97fxo*DIAR=u38a!bK`(z{;=vNLm7ZP%{Z)ig4dTD+g?>rYEu#+BPz zpju)tV_2bvQmGp+_13;V?wPGh^7GgB^o=xZPd|l5+0##Q#zoEQ3pt`6CmKv^6=F}{ zNJdS(&YnK~!A20D>2>tOGwtDyTVX`T%WUsB^x%*5zfTF5_-7W7^inem{qLuBVlSJy zqqko|sjQT^RRbFxQ#+zlW(goo8A&+t0j|)4qPkIqMH|n{<`FH+r@s*v73c7ob*kl||jW=r`(8+7v5J z>ril}$eYj4a0%TRyGT1c=l<}K=lBQI^C31h&g?P;@f1MQ>RF{A?e%%!d1zjz{q?N_ zgr5{7#v&S8mg&QK{>AyV#xOrm%0`%oyiJGhPd=-1K?Uww>vNd9`A?;uvHikGyIvaV zWiE_mWDq>Ve%=|p8Ghv(b=G+iXFb0QCPBz21w@L!IRE;g$xjY<*f{~-Tz^6=^j=OR zAnH*4CaW_Y7D!n3^6CXs8N@NY`CP+k;+|&L@IVeGXL(>kaOhB({-P}RJ_$;Q0<&dd zxWgF^E_NFP;xN`_bh{J{Em5J}6s3<%0Xn2@}_a-!WR z&!8P_+>pg^<3oojfP%jF;+g`XeSOL$DE1XM_)nUe%}k|AR5LU+Pc5QNe5~^=;j?-x z7+*6gf;rLWw(O=hpAsz>%~8htE5nxh;O$8vD!&PJK;W8~*MwaY$0=jMz}Fd=wxYF& z&Gw_ZEN?~=$dW++d>0ZrN4^YOa&yo0J0QMAC4Q!HTT(qm%k(qvb5KBYj2=QK^75&s z8&cHZn78Jr&dwmcxrpD6FNG;~!edGyJy{S`qNdNc1T~}9jeyN2DbAId)y=$Ly+^hFuaz-3>MFt4uZ;&Ev^ zQ62r_IY4HO0miJvu8m7}5>f*(TTLG55~1pHJBr$x9vlEa^E_=<1MOfco7*d(oPJtd zxd(h>$I2OpuX~sFWwKX;Pag)b+N_`03}sX9`r$O7jscGKOLHx(iZXwIlQ%tw*cht; zoi47#Dp5IGMwVQG#a0P}<$e&mbaX~p0L+DO^`QF|RvG?L24~u5sP9=63|VRsYw$c~ znd-;k8SYhp202guUf$&S!dF7L&e>Z@;ZKF|(;@t^5Iz*b9}nSYLiiIQd^m)k4dLfP_(%vJ4dLfQ_=OOD zaStQZCn8LO^`#4fd4k~LdZj%k|11xwgalbh)*E@oc;ua3a5+iz3{m)tc1%Dbz1(%~ z8JJngNCpfTPxMGK%0$V|?1E5jbeEwxu`%JolDG?myDk8XQ-$k%VQ5V6@Cl0DX zW!|?4Ful>ErXdU*TC1BxfiP~SeI(0BU=-|X)GpBNcASPl_cp5xi5<15j4)~x3?s#| zk9G*WD=*kDYH@}#v^nNcDK>VVz4Fj>aMo6RWfaxzCkXq5uJV!S z4hQ$Em<5X0I+p;Hq22t)w2xfPuLY|$f@=H_C-|9b42n}7R=?ayCLoFM4m)Gnr6b4a zDGpPHemU0LmDMW^GlRaIYWZgjUZ;fsDifMj(`?-%FMSlImatRUOmHJ3k_QabAP<=z zkvw=(lLr_~&fr`!CkLb=c~ zvqHTV8vKOXxi_SP#)B$6#Mwtm~JgOq=F!M0f zM+T$g0wwm|vL4x0J|qfHsI!%P!4t&#iivh)HDy)hN(5LARu&5lj4$2tRo4*v#u`3B z5(+Vgl{Re)xt@dh#u9=)Wzr&6J2%LB=5m%}$HKVmvh6at;h5y8jnvM7x)GwXp6{ZA zb$r!R<&laxcnCrZF~diI;+p-qD*JMG`Nn)f@vYCtvTshiozZf;6pNQ9aTB z_xcB=CvY~+>a7jbyo8l}OvVrV7fW;B!7`9$QAp zL7-c1!&*a}=Y`Qcw5w&7w77z4Aq4j-=JA+b+|u%c35}~Ls_HXAeiiMrd$pb6K-!i% zUR>IcOMb-vBw&Z;e+uBfdH>UF?SGOZlwM@aSbz3TN#%bEM$XHU$lAi4EB{bY?d{H$ ze^lrGaUIp<#0^bZ{BAnFq5?rR5|zmq)1TT?J^FMV{joawP#yj8I{KM9`V)0jz03a) z8~<$m=yP@SkvjTl9sPVA{X!l6VjZRNzUeAdAf2$995H$s6!-a#WMKzK#T)AN^3y;2e zqMs}AXhZ7qBgBSWaFH@A-tRPwTLb`Mx!|B$9()@+1vVI*;S~hlIuMkG$_o(OtwY?S zZ(EWtm@tsPHSjEX2nLKE7qSsKbvn{2(`|IP`kBfx;wr% zqu7N}F8dv)PBDITsEfsk^V$-U zgn>0zIWg{Q*xltxYyqT3ePxAb0Zxyz5m|sxrGSX*)?*f@Qvu2jL+;iDs*(E8vuDxB zcy+eVvuI?pI^?%ojfBIHyY28IjZFD*Jwwbo?a~MzgN@zBBaZd8y4J{sP6}p1kwa47 ztm|1cGFwR}&jJ#5uVcG{Bph)BPn$}rOU6uh;d*)ISpg3tF|DxfOL(Lf7>sb9e~TTSQOHZW-x z(H2qZ>;{$w($NxI&-!ylQ!I=7H5j>f(t)i~==@M9P02XI~e?FoR z=h3p5fOFx$sOO#8Xk;7yYkg<S&va8Y{p2cwHM@cy-vic>3 zyi#A?>LnhB*%ev+CR49kM$|7;TS=h^F|i%NZn6qA1Q=PV!?dBQEQ$TIbYZQI)4 z6RrT*^Td!Zz3K`8_B*J@7F=tpjg8Jah<>`d#xcaWJtxFi(uWwIedUW%695QPKF-+W zpFf%5vKn(hpUg6jjcO}}uae5t%vX7^0pw|aP7rON_B1HjX^c4X5{ns)fPw2R=>6G? zYTJtI8|@6=bo973GRK9S7qh`0dZJgpL7_XPX$ei*f1igmO^X6*8Sn%#V`Y^f6O~Oh z5(UkMN+JjBXe!XWTLj$J#-6QhJBB70j8K+XGc?RsiL`&fg5}i~8)G`CGiGPI3`nW_ zagKN4y{Vy6iwx&+h7*v2DiD6E-L{JDg<%dmL^^f^qThD|f6P@|SS>~_AYFQe*T{k_ zkALX9UhQzB&_xMB&uNvW3GFWofDLWR@42az%Wu3%Fp3rdQhEa&uU4Gz; z)>o`}?L^La&Y&O2CLuhwkLX<7KqlAs(zwQ6y;Pp?X*pXJX+jfTPYMO9m&y~q5tQfzSQHP5PJjW{MgWVCT2=xh;pAI* z&B!477OAM9lkx>pR6MDQ+G9wJ@3eLYY1PT*xC-|*`ahn|x{a0OiQWE1UXh=1T0BF{ z2f6q(FZQNb87uT`&d?wa9UrDJqg-$K0pjuUVWV3Pu8)@wdDLF+J)84N$9VZ9$0*0k zM>${XC;#})?hfUUU*#adEW65hlGB0K-47JwmnTp0v2%B1@`*04SU878x-pzB(#OlM z>B_OTs=Sn*#|T8s2AD?^L)6GVstF(OKtkJl|Qn6OCq68g)If}cBX zjy2|NAgg?^F~>2)Yc8V*qF~(&r@BT_wzV0bq7&Rp6x;EJo9#GWDOr`NCnJLMm`$|? z5!kEn82Z6Rm8zz46%ru>Ek5@t0E3x6Pk?)m63Zr_Ef_c+wn0pQTil%6yqgz zy_S0+@TlYDw$GjwJssb46q^VHapoP>ku2EApO|p*Cw}g$dV+9ap=EXa0GOWWJ=-Ta z<^U-e_nJ>Nk(7XY&33Z{^22OkOCT$-(N65p`ORcGksF`2nm)tG*U&K~mf052^3qn0 z6eu{>2X*U{fb!$R&8le5dwJa3wo6d7?Zjuz2pv-%+SNqzh&?uasI4RA(Ls4wuax0V z-7ILJH}J8xae;AS9)z%+{+NaPlP`tzPlxa;7IKGh2){aCe(mBC@lisKdT$0qBwwB% zPB{M0LZfhjr}XHAJu)^U^X$CKm{R37Un?=rS~^!rf2uCvK;HQC>#FT06z1y04*O#3 zp=7|B3oFB4XsM!4(fvgKJS9P_njy?d2|m8(sp;sDVu4-Y24KFJA#K6)dZFYy zo`En!yvYhy?KK6Tp~Pm$PGsnuoX$pp@K;yw)j3@2M>Evb40UZXQM}}6FU0y8-3xJn zR!rF8frq&|!X`_|(PUZ3WQFukhwv*FGFc(~>W*r%c4)F3vyxKG*^W48k}IQgW{=J? zgs z*QCD`!lx}fnEY}G|859*$pnxOCVwx4zY@Y<4dJsP{QDvNwGjS#2sc9b8zKA$A^gn{ zJ{Q7&7{cEQ;XhIc=dl6W4R0!FzorIBYVCi0&0JUxc+4M~Pk+Tmr1 znyo=H&7kc@vS_7UEkHy^G(aN&6_zX-SMc2nMPbGBl%gt3k4y)|6aj9)X+EFrzQC3(;QPg#J6OoZ2WFCn)cZ$%NQ>XLf2 zu2cQcxf=^k+f0V{s{8u@ zC1}b_CfD64vySQRF+Q>L%*A$)g_&o%P{&MxZ_r9{kv9Iv{CHVut^Gu@w)T_wAPNGw zDMOjh)-7o6eS>zyFi_%j#wVK7>igvSRv~^aHo_V&uk*n*eWl#KyO!bQ(o@K#P@u2y zS?Xd>z14%u6zD5_7F;3wl&F1St{uNew338xBe&rZh|<4}%=iYIz0N%y@*_HIfdPgnM;MLv| zZv^ze*IK}bL-nhNSUfFp32$84-Wo-*z1s2{31!@^-m>>7XC`z4Aih-n8~;DVFi0st z7T?Rzq*$syTePndim%G9wwFzH?F4AuD^?&ZoEs`^b{Zd?T2J|gTur1!^$9uXrhdsE zYpKsv5iIbIe@^p6?ZSLpezc05n`K(i8i4U8&{Y}hy{obX14ecQrTuIL{OQ277=UE>>2OPYf@Wv9O|#Zb?q}3Qz0Vy?Vyg0V~S8m9DYX^e>d&%p3yCid$Q;qf!1? zF&W3ob49m?b!iC}s&6Xc@ztCqC)hWb;OUrWVQxh?A_$FB6vwMbjL%0%@0>Q%qLzn3BJS)7jV_E*Tl(JHIJO2a zJa+k3wmu*!P$UqYhOvESFv5*|b+HA8PrsQKIft|YAkxe8*T(meb*;^nG0`Kzy3W6D zvqFNUoDwz+y)I2>^*InDGW9oCZQgnoUDltfX0(1?uXq*7K@+o;Pd0|25%qhAa-Y zsu2FKNr*rMJnhbYQQCC91hf9kvqFDtck3w>?lb!d2$)+tH8>$CDGSsW(?-T}_K6|y z?okjCDZnRa-jU#Y3YNtQ6djuN=R3o5-%_yW2+keVa~89PAit*8o@1R_mO1#;$_itW z0R060q276e!5Z%cfJEGtpkw@&Hi)$WW`YiQj}NB<6%&3?ZSK!*^?HRcSngz)xJ8I^ zXnZFqR6E9pw+^|IjW-^bvyDpx4<9iFFU#4fkka~YIr~OP$xX(aHX((TPU<;J0mTQo z&B^#@3zl2`fx+y9;*h!>m|x+>rj`vojFwkJKzm_0aNPp)*;Sm4iyC^{a_H(nsyXY>Ix}!g_OENN;fGamE?OmCLwrBFod5D z;g5yzp%DIf2tO0Tp9mrASZn9AA^cnj9|_^3A^dy@zYxMNri^Tsy3&U_@eP-1wU+Q^ zBvI{@=|maPPnc{`3??*5fVP5a<8c(zUQlT~M`dXUuNOI5RduoEzKjDK;;jkO58)b@ zhOP*b-dtVS4SKEBc(e=d4Z(lNEl<0F`Hu(}2>*m|58*3>2+Q(Q?Ao4B_-Vqo5dIk9 z1%y9NxJ39F!h-N82nU3pCA^UEbA)>dA0fPm@biQh6Mlj462dPME~B-2{HAhTHQHj; zIE!AnaNlrR-lZbD7o~0Td5)lUY}mgEMP#LT3Be2WK>?D5ZDiy`XNal-#nBY8v*%*Y zqGmnAx5T;&77l|t$FX|cQE?oqgWCv=`Sv--nVeyoDmf!@X0S;9?hGP9jO&?|yb-f{ z7E*avRnFuN?NxGz0fusw+_7&PhspQ%^BFU&g1VfiNl8bsw+`j&r~v_YR4e7r%9yBN30(yQN3Y}VZ&S0w_srCTFk+v z$Odv`j0_{2&$vxIU5wqrkq^#T-okgjbd-?NoLu1@B$bZtmCQ@`WNdK(D{qOLt|j30 zaIE(!nO{={_YLSSoE3SN3+}_vygyFV_Pkc)_&4#)Vo_+4WhG-tTP%E+(n#b(u74%A zArbzVO5r4xX5PVGMt4W7p)>xmGqc$`^qik*Wh7L7u4PKIid_h zH>VW4P2OVkPO$yQHrYzfRw^eVSV3^zgi5eR{Xmgj#btqb=B~;L-J!{YeTHK+kru0s zh4KG6mQ6Q?eu`x&?=EiH+M)efn1~@Ea0C z+l!bPw&Ku%Cmx@MnrSnwyqTUwyY+iDo<-Z?y9?@EI=eWK9i|CCP{RS7=;-t;niwmh zx6`v|qP`{DnmBCd#b)Gz5g7HiK|G5#devz<&!Ua`fS$D>17j69s9%5dWJV&sUOLQ3 z+D%u7h^^kLu*e$+2p+|_qcg-<8-#@+uh6@N4(CWP2Z4|Onw~qqi8@9(3RNk+5 zAfHSJKw82JI}Pd^1;o*nKM^m znu?dM!Y&0>9;I({-qI5$)M2tnVnEO6+|EY`yN6?aafiEZD|z=XT50b=%rMp`Ex0EhjLKG(b8;}$;gWH+W}NBl?P+K_aKEP^ z>cIY-Q}OcMSYBz$2YKMnDIX3vkE__>!h%(LgL%*ifq=$UF>bF27V2>?X?!X|Th&Z< zD}rR}B0S|dXR{o=tU?O0WxRXgDemNEIobo7vam73mhqW#44B9)R>t6oyDT~~lO2{Y ze*^Foz{BP9Sj@QaMWk;Gvc#v;0`^j137l<-sF7>Fv8#2%Lpdg4_(csC>?!*Du z*}n)o$TisannRm|7`&R35Qllp4Pj% zOx+{t<;j=x;YD=$NGkWl=}DD-N{=TT0~Gty_(wM@^mZuyfc3qSKQ&np&x(t{l3i_~ zUW-(p0R$qD_GBl(cv6v)T^U>JERuk)l!s{R3@;L?EB=(BP)DRxoSXbWrjV+`O3Hb@ zk;C$a9Dj+@%dom3$KT2H9F{iZux(SdgODSK_c^N^);i>{ITUi3fs3H=VFaH8Mfo6A z8NdgUE+*zE_?V`4Zh@LQyd_)7240@zjdtoWk!1Jxc(rj>p`o$Na-JL?Ce~)*NB|+M zb%!6fRz9Vkg{vXQIxZ^gTnM$FYDZ!~teW+Bk;JNsKHi~&toXP(ImLcl(znCX>aqsM zkJyptIOB;E8ctP)&pY5aOy6jYTc>P$a69B4`bxF zV&osi$n!Dsk7MMwW8|O2$Two-zmAdLiILxpkyA19-^9p&8zcWTMqY@Ke-#K^Z|U0Cbgy-f(i2ediQ>!drvDhb|7r*ZS{|LYoF8 zf80l<%u6OE&1wr zB82d%@hoq(J7b2c@);+_U(DkkkA{L=ch>kjo3mXJ{;fu~y82H-+OY}U?o{s6SLwq? zY7eS4as^lKCqvrX)R{Dt5vgeN&Cftmwd&nCvcLTq;Cmbf<>UBV4xtHUU*WXuOnuMf zyG$$ywRQ#^4aE4)1$cLIP)AS~fhmyug_TXfPd37{z;wsT#gR5w( zrm_ZCU7=>h3hDPv;Q}$WjeFxEUMun$BS(`1MUi@O$d?`@--6`|!`lB`@<;OgtXohRlxg72h&{-;|{LMb}U1Bs(UoG^V_7 z*s|x8&DsM$DZVmqj5pcFCS24=th})a3TTkM<~j&_%_G;OQBS4Y>ZwG7b6#+o3v(ix zYbYwz@u;4XsT?UyB-i(eqTHyS5=Uu?;)+y{LvL?tnohC8i1YN#Np>Firt*Ne1MLB5Vqm~LXXpGqNug+K&<3i@UP z?SsF_=3O?EQHnm?>yxwrvg6t*sGsL2qhQ#W1TQ|NK`5lAyO46h0!TF}S~_gC03xwf zBD|Jw3nrtj>0kpiML5i9BHRR=VhuB3L@cO)32+-zZ6>IrtpdC=WNSD5{;9D^T&qqw zo7B{~+JEI^SK*SU$;tq%`AP<0930(kQCD!59-9z1ePxK=!dYs*)>Rc}Au~ots%e(8 z`u?eI7$)l1H3a6`)2@H^C%^2GYm#4yk!L+}F!{9@`Sr>2o9Fwu7>>&epDjcmy(G`n zTFMo%WGZ9Pyjp>$tbom)@*TY@>S6)lQ9Hb6^xzFsOH^pCr6HOHvap552U>L_)=^R_ z^fZc&p;-Kv6_;0n{9kG0Kii1^n&SU2d+!2gS9RU@pZl0Qk2^EEqtRnVGt!)Ukw5~3 z-WoA7Mn^VajCmx+kN5>b8bBieQUzqQUj_uQEg58KVB=^yEHXRp1_KKrruT5GSh z_C9-S36eY+E*?n}XY|kv0Ux_nY>2nMy!1Xr@y&Kej#}F~@%&UO&^@suKjR4EQ)e^!j9;yrh>u*N^L6znA-QM?(?d#CQ$~;rx%mSrIIGoNGDI1 z5U?(M3qHG|YOq?$2De&gofci6<<7aZ015nLUEhgZw%1FAQBiaVRAW3Z75-=-R&NY z6RX3_nxP0|amEZgU}TFH>Tb(SEWLaYP07Xqjv9@g$>ooj=qkk?HpQ{xE{_GhxM}1w zZzi%0y}6n7Z0r2VZg3eiZrjM5`c0ELkU8@)ySJJ!;DXGrEvN&&mq*Ui% zVO;U8(QKV#g)4<~ip+ou^Oz$@L!827H5x+1E%qQcSG7<@n1_7^3safq^;u}C)!90x z9zEU7WQ_ELoUZIyVvKYzZ-z@&Ia2XgT532she-n!4FiOF53R6o+bYBKvd zC?T32n{&pgl#sLHpoCo6Q(^@JE`v2z#D(URv7vjTq2q1A4d}Mdt{2HBuC74wa-8V=Tr#x z`*XC+XB&m>OYXd{2Lx}g+>zd(aW)>9N`q|Z1YXEY2+f9-OG38{j1q^|1hRti1FOYY$hwyehy;C+g<~n4{)j z9pI6P`uPDy?=X@74Um&4@ecvE3-}{|*9dqN;I#t232=dc#{e!A@GXFg1aQ!P{dEGq z4REo5?*P1Bz`p{xM8M+!ZxHau0GA4Q0^l+M-vzi_07n|vuMqGj0Gd0Ke+}@90{#ua z8wETGaHW7h1rUQIe+KYo0pA07i-4y9-YVex0KX*Q&jH>h;NJqgUBC|j-XY-M0lZVd zUjV#Izz+eg62MSMtS1cB>bR|5g83p;IZ`yoM~N}1HAWr_Kg}m&RrEi$|4BP%`=4am zN{_Ab;LN-bgK^ICIByvrX7ju8npqh}(f)aAV8nFtziAFrLsHo-4LOLd&B(|(d=yl` zR)AY2&CFa8ceDO}v&V}eS>Y^6A4}3VmM8JWT(Y-3x#dCvutNzW6OC)6bJ>hceAz@} zr{boU5??ye*rj+Q&CekSGLHMjq4OQJ(cH!6OHQ?UxpT~(DYQ& z7f&>HD{k{4aW1$r-Ouz@;tMAld-UAqP2%i6->bOkt;G8$8aF6zx+`(EqwiDP^jG5S zmEEuSqWES7roNIqZ=!KPahslr_f9l!RNT~9;yn|MNySZ-CC+~EgNmCvOT0SKm{L5T zuWO=lNO4nZdCn23w^={gW~lU@_-qB5qlInG$bX+buEwjC-j$|vr2YFX-PPKDv|6dR z^Xr)I&cuY4cPUujnnSfhG!zSQP~sQVC;=;3~q=G_4^$4H^+wY{jnkXKy3KEF*dYL z#)i#wbO*_}$2FlHWmo zQ~VC`EAqQdg}hIHZr7jp>(3qf^8x+2Q-40FKWsy;pT@7jug(wFth0@|&i>{)Tb=9d zdaknpy3VHPI@_e{?4Pc)mAbx&-$H&1`1SK+BYC}#pDv4^$B&OO>?S7r@Cvw#Unf75 zygGNH*ZEexel`0-*r`&FiV`$oy0%H2v&5w3#g(z>w?%C6)nmT47`Kl_|H4wZf#hEr z&^hL-jd9ml^gEVP9rI%eD%BJX=xRy&rweC}NZ9G4h z%7)$kT$HV~3vyA6lZA?|ix(+aA1_w0As$e$F&Fj0d{Ds~;z z!7s))D0pMMSHYF>9tCfTCltIn-mTy*@%0Mc3ePJ1rT97pZ;P*0@b-9I!8_tz3f>v- zRPe6&8Uo_pgL%v5o&~4>!`$X4=G>-UAH$}Gj zc)5XyA{JJNUg}PU;IxO-T0FjTV6<#zu)fZ8 z`1&%@Nwq?1SeV!?lxdHrV~_O--Fb-qP0gLCmSPXw7~J%}R;nN&9*s9b~?% zBYHODEbG&JovXXg(F9md3iUQZw*F_!rud=AwLRB0UC!evM$X*&JEiTId@74Sl~l&{l)$Kw}2QK<64X0<^`TWk90_Ed|GY!&?(^Uq|16pZNFVGnV^#Gl2 zP&d#DgES#8H>eBfG=n;UTp8{Fs#{t+kSkslpb<;MQ;oVVH4@s1K(WB9frbs*0W@UL zH9$)Y+6gph&@Ldqm1Z1hv87!Lw8)_AfEF5bJaSVqWe1`QnhQ(f= zYCVqOvB&3Jk7Jlj_~h$x442(L3ws>H=6auoJ&xgXozKS}$ELg1CuWahFpc{R?QsmM zT|QNN9D{48&)FWwAiE};yy+hX+YTvj0WTPIG8&o*SbWfnDHfCf|Hj3nP`e_&iG8oB z1M8?e!leYH*d383;1=9%#`hG+Y~V70YzZ0a2TdYrDG$%xeaZ8M8xy+$UbDwT?C_#2 z_6m36c{K=s88gPsRNux&WjC9yG(!CD!uF0knKrg>x#RXx`f)Q6-2bxcx?j-RLUrodwrz54cXd z-*wr2uFKxwy6j%pW%sx)JK?(QZr5e6cU|^6*JZDDU3T1c*#~e}DeW(s2t7%+wAr~uMhJGjmliL~v2BilISIjB1WpIWx+xhfDQ@H4mq`W78D&uc ztwZr1fz)P^0ajX$4v6Ilfmn_bh|NI?q|T;=n?(yZS8>6!%{oHrpnWzX)OWt#tybxY z9b3}o#*r&aJa)dxD^Awqquu)GfQQ0__J0eOx|dU>Z1$veZ2m_hGzt^4PV%ZLK)k|Q zR=Q8rBDJtpRJxgtnasU5Lk(j#(Ro6#f-)`_RTB0^z-{v3NU1a@44P(Vy{;CfgL}l+ zNXbYXo`oSL|Un~X!pgjw!e(n_7?^cN9Ii$P^y}> z^Ti&p_2uS0^Z5DI!tK**0Zp#x}l`;}VnOsj}F< z7iD2+PnE~Ez396}?Q~-CH#wQ*#r99Dycv6>EPJFL7x$Q?wC(pdmA2_y@h;@at%VDF zY`J)a5YcG9T1>81xsYHyp#h;NzKBJ|xfDlS39=LIN2{X|o61*5%UFmcx)j6_4C9?6 z7{Vz>u!K<~7}PMY=Dbo=q1Dl1jrQtj5kpI`5Vsn^g8Gnxew=6o^YNV#^x-lisNpFi zn1_Rmpce-jK@Wa0f^OVl1Xa9X1YJ142s-h35p>|{B53E(27)pUu4qlvR_}(^BAxhB zinaF%+NZ~j(kjvzz~uUgMnmx3iX7n6K}DDbBBJl+<3ggN5$%$ijhKyK{?Vv|kRYN= zodH7DagKnHqqdmrnsC8eOs-3XZo_46G1<-MYZ7q9WFqw~6q7xi3*V-x* zFSn{0^DdUF7W33_&i;36^W|@SeSDqoY(bp6k(rb6w)qvxHT^CgM8;CymQO=@C+t)ijb!%luZjZj{le7RB`^lbLoGTga2A^ zN?sY7{!>Uyw`F_ZbF7W23|iPkhOKGbUp52nOcB_94%=$#ryRD`)ZcN~R#WeFc&+mPONZA9{ud70YU*!0 zyg}(l9NsASpF6xs@FyMKEcmw^w$;>6IBct_zv-~8rv8S*W6J-}9JbZedmJ`7_v;SZ zYU-~!Y^$mN)L~mq{kX#>RQ`#>iOT%P4sRFyF^6qg^{~UQRr*IAzCiFt9KKNS-45Fl zE0-LsW^S`p)(<;u3#}h=`1Q*FL5FR*^?1qh?^61=93B_^n8Vi!{-(p%34YY!>jnRj z!@C9lp~I%of5YKDN@pvr+Ot>iBM#pn`0Ebu6Z|!Y_X~d5;RAyIz~LJOf7Rhh!C!IM zl>Ubto>Kak9X=%ZOAfoS_(hMr&vd{CJ>sV0?|TG0ig&)?5zHqde7~ZGf50L~J%Z`P zlh1kNgBJNckDRRspLN)F6+Gau;Q;wCc2`2fl!?xu4A%|^Z{Gh|OqqHgSHyVOz?)!(m&-e80oC zgn7HeHsQX{VRQZ7=CDo3w>sRfHcUHg>z2e7}!NQSi69;BJ+GPvaJP13G-Iy?(Pqwf{%)F&D$llEmctJZ_<4<{tS1 zv70mJ$nO)oG;@tSNbE9M^)^R-k=W(3^)2=#Vpqu0S4_^Aqt@>)ll%)Z{4LW%#C|dJ z9ejn@8{Kz6Grmgf%HTps{(#tSJy{{8{Yqmc22(e#s-vQ5# z5qn#~Uhh>WVJ0KPL8G_d^hSg4ivt z@DlqjvFU>AxV8gM#Gj|P-kdNg1)OOFPe&C;U*TB5s8P;x)3 z@JI(=t0Vqt;)o7kvm^c);>ZYg8v7!#%z>GF ziCEKZ`DJ2FrzIa?--B@&{!nI?O)U0^TSfr^d zK4&Zvvf{IJuruMAW06jFwzb(*f~BG>m07824e>`8@ADs56R zlggJ=u%r?t6(y+*Nrgu$HBxbr%867!q>>>O38^edg+R*vbFn>R>}=1VJKHnb&h`wq zvpwVOY|nr@+cV;DJ?zeqNASFcJc8FXgPhdc{{Jy?@A)p1k|`r+=RFUg7^IazCT|SLA-GBE7iWw~aM*cVWfLYv;ww zd?sLBL=k&@YoW$gJ`|`Gah(f7SD5+6*ClU2uV9r-OG2`2^(D`(h3?a;><8xM;x@gm ztu*P|r|E6W#~1m_DJDB4P352>`?*`dtfKmciArE% z4 zu{sNM!)#K{Y#xh>#HwRaiGZc*G68!o+Xz^Kt`M*S-A=$#h}Kb9fbJw<5u}TNy_GB# z%3kaySU483iX#h=H659TtnkPt)H)1%DYd-7UP{)2Wd5--B)gAwA}w>UYNRy|){tcW zv7#iqPwO~!>Dypk>UJc9Z-`*Ilx>!Cq-(RRFIAhB3)i%LZI$lotTeN)A=#f{^fLsl{#LrF+a_l2lla()=?mAcKtSla=>%trsht?|C z8g2C0W{=q=TU(=7DK-|p+Jo~w;ABiCCLV0};58n+)`JT?xX^=(Jb0Z47klt}4|FvV zg}uRpOFh6?QsU*f$!RM)ylM(`PB7bU=;f;Dby~IYBz6L|DQR0XiA8*#u8Ou;lAyKR z4?=#{FxYSqPE52on+w9Zi5Ax)KMN$`O`XPEW4OTBl!l`uIZNwa9^RxJSU<#^YM5W^ zX5)gS&E4*{R!?ZEk`C|=1DDji<(!7&4YAD)68O+VMQh(8i7yojmFx`6TDZ_KINTI6 z|CqNlT-wAQLDnC2afWR;U>%(!ZP@`(;=qm?dv8m- z*Z$9L_U8+Q;w=HY8D>jyVNYDV96Djd<{>nE+QR#PRC6I z=*q6Po`Q4_HVGq^bT{h)0uU&f!4x{+qJwSu+zC>V6dMrx!iNJiohaf@?2DtK!h)!_ zKUwlXgQ6r|Y(JF4mR;$wm$aZk2bTjAXzEFGsg*2ZUPieBX}oScp#^%MZCc=JWrX}B z#rA^nCyQ%0n3Ub{oI^qj>|@R1v{u`}vN${83cC0paE^b2`NH0w*`4P}aL={;Q>bW19 z7dk+McIN3%hYkTP_|}*r^?M$zt8>b^Jaq);ei ztjO#p}Op721kh<;UDR^<+Gtp?ZejnZc%dAnSR(VRZ2Y+Vm237 z68?nyyqK>vY06x7Txox_Uvs@Yq$$IbXG-_~tzyfqWKAkA837yRn!qc~qFfMq3d$|z zDOY#-QoL*eMq{qg-fJluIDWO>=3S?25aR4OxSm@Tg9k=#6qA z7l;;NE+V46DG@pJQi$ja{~Mr3qmiLUqmiKp!NIBlnj|SWS75xN)&}Jz{TXm}N3qbB zk$6T>#&{+J8E2;)hH{3?Gv1Sk)9@kCCbs|0fBxft^EY?@<`>4qgN(kBx5Qu*K4ZED!D&-4$qY*0~mJRfyYVA5cq+&)t4mtf8t8+5` z3?T%of2qO*q0^^b1c}+H6&V!%a}OD6gibma2TMT(GR;C4i4-lWJypCC7ySfEUCPDm zYqxGi$ms4L#U(lso1#L$mn?72gr&fkLDWo1-fp#eu)uI@x2Bk|ZVxAIc zYnsItd2ERX!wO_yS}>9viP^nXLcU+JHt*6l*UPPf8mWY{DHBDypEC_vA1a<5}=(zxgOuP6SPEK;&Los=%7*1{-PM)%qqq!9B zL?F-o%@i)Hh>jFTi^nNSr{*n%Tt-9jZLc%ez#iUptB6$SV7C0_;QMs*X$HflA zYx*c%t*~!)G@h2oZVR*=zK542E|5s1)AS#vO=_&M@0ehKs)mziMDn_bpy(exSt)uP zj~1UPkl_T!tMV;LAr<4EfKJu6rjV9CjAY$hJW(PuMp+e7Afm<^Ulvcr|Q&W9ZJ zI3AHP!Pn7+`cU@*#6*HytfPBj)tioKum1eF&_pA>H0!>YJlmR@wweyC(jAE2Plmx_ z18LVN5G_5m<-NC*hKk;jL{ZHf7KYX6fwcGR{gJmow=P)~cH6cz(3S+coE4aMS=VYa zro#2G-Cs^A#pIsm*!!jCN<2IxktHl5A$u9j_{jMC zR2eVZUc2LVT^v%6w-@SlolP%fHUjlTP!Fz;lCws4DJ7p7?0~;wh@zpOpC?PukPHj| z6F8&0Mqg1_G6_)LUd*_^x6(|W~94k25#ExL)GqXVdQ^Ha)3D1H?|cr zuyFFQvE;yn7_wwE&l8gv{)D5U^G{4__!GbCP49?jx!t~W)MS{KtV-@T?r$u}N;vFg zFG`j>Al-KQ5CG-sLask}-F}Wq|T9nX?AL};X^aZaZD_%u>10S)A_)v$f zlE#%F(XByzzU3p}_ZON_QA1_AGe^3VQ3AHRXY>mUvy5`Mwq(SJ_l$mnVU|&oNytd2 z=+M?ew+3uw@j-Oo$J-n}3VggRUVxx385s=3i&AJP9!w#jmmwG}AxMKDX+x0kIZx4b zSa)o76Sel%v1Tqnu*&t;-qVf-9{8>V-?>Z@7nX^kw1l??x3`hNIrtR<+@Q_$_WDSb z2TXpvJS^A4UqQgSP0yxU5cjMIS_2VL>t)`#XA4Zva`5u7T|IxM&=>@PHbxL zMxY|_d6P}DNd*y*V-k_tamp0GWaKIaf__D5dM1u(c?OA^xaJw4T|X3P=(xT*SD~Um zWNrr_vIwbtO`q6es?({SEZ`o+^hu6V^#r`s(kJ+w0&VMw?wd`Y zD;H5R7NXjUNb zAj}$z(`QsakSBRb9<-4#Z67O6B*${|wvSy%0d3?I1%?y^0ApN?JF>wgg|Y33JM)8j z3~KIKW38nK+Cf<|!lC8Fy!;-fsie=!$z%G%v7wqd>-6EGxR#BE z9x@s|eo-^BW591!mJ|`%7i=v+q9!viv>ymE0~kpF>AAq~H~b~bY`AK zDDiQJupIG39pD<}PVyi>2kp-Ek?qg(Z{GWE_jh5Gczeek$bshzA#J79SMOMalf#4{ zjHRm9PQ(p|wuDjl@rk5g#!H0zDEYU5omq>%PYj%PSd)^U5bH_@B9h)7+vT4`k1tCPr5ufGt%0Nsr#2Mp2=;Nig&W-Ptav^Io7dbIoyh zHcc#*_$mk647EKx#4bZ;4>4>qZdePkBmSbqoL+=seAs-zWPuJRwg;lQj`f$iaW+V0}8fAQy#m?W54XduP7Lc-s{0FP*M?)6+avZHM^#kDX_LGdUvBw z21pIz5<8^S14=zyh`DBur^RjhPoA3gAw=dQ;Ji4!bv&BD;b8^fKB(m*9U-C&YxOoi zGR1nI8IgnMQp6>-4P5Y~sgvitICmP8rN`z<|*GMX1#S{b?n z`wH5Dw}WOhuer1oN@(76X(<#iFT3Z`3eYk!0~l_+EM_-ewn3w5`_g%*u0kBv28hzZt&C#!=@!v?pPgpn>eKHOId4a(w@(y$kzxUYuYj^WAAaw*?lPwY&Wj*Sm63TC0;=#s$RP*;yKvf z8t82AnR0yZ&tMPrLj?c^#`kA*s4aa480f5z&S+zW;q2&4)^}7;RFgR}>@>N=$`IQM z9kxw^hBf)clPILgIG#i^njB<>9Ho#0lrfX{Erk-Ayl*KK(Byq9;DC6)PjZtc)G`@h zDZJm4$pTB^ecj&b+-mP56U3Qthz$}qaHml7-dxKEXM(Y=Oh(Ei@mIPtiD(&x7D<^P z6FM@PfYOz(nU;gTx$f1iIO~cAHCV#Y6;vIh2X~NXRnHvN1N0@-T+C{2n^iM?d0{b= z_2nN(8(*?4bc6<3I3QLXLloMV5 z{?moxz%AXGl5(PdPh(KB3n{cxtDXwjXuz6S>5@i??H@3;bTBy)+V*IRV=LP9*?C=ZimR~bFDdLeg(Y|OS#!EFRo#;)kJXV-ee%?NRbltZsw>u> z2hj`f>Z1rfq#~Fs)vfLEaUMT4pT|GxvKl(#uJG8BsG&11h8ontyO@7|(#0Fk&9ee& zKzM`RQrKwmxp_Q3j%5l4E14nZNrr-8$qmY9D6FXaD$h2HWo`dS7u_%ONV#ZxuKQ}q zbKJ82upV>Bv=3I+5=)|7Y7cEsPWGe&&wB6P zx8-qtqKcQEhmd&5CJv#RJwC8d zif^*Gpl20Tq@s`!l{lS46s8z7BFocm5QWJPt6C+iub_nQIk*%s6^Lc7z4q-=YO1BW zn1b9hV((n3#iYC_gs;L=la3HmPEe(y5JgbCA~I&5DGXa=7oM>h!Z0tpBp<1x>4h@! zIa3(YgwU!MVR*#lcdoufNfeluP?9lL$Ek$j5eahTGGW*v$R!LBHpnrrD%TQAqFi>J zgy9Lou(wrW9YMCAR2``>EH z$uVj%SFtDtR&{Mf>MSG6BxO?gbSipL&81!ahLJ^Sd1TGSuFBVL%$wubt~oh&fYcY{ z*gQo_pP~NVIMba1$3k*1#If!1K$8Gwb1Y2@kDKaCZ@!l^Id&kU9q1vazN8$BL6a4j zax8U(0)q;0YV{@0vAwNrpUJVgmIRKS7k6bV>{#C(B8Q?wu!!CJTEO8 zl`mgn%CV=?S`OP303(J?7lVnCX6h|s+{2=KXWXW+7Lrr8ZRIm2W5h&BdoPQoqG@ak>!+&nVYF=%p~{1> zu^G?gP9CL_9%x7KT}TajcPUg7FmH;ri_%#LD4p!l2X`+l7+&uD-69lB)8p!#oH--q zPMt&K*0R=1V1TPIzXSH=J2ID8NM~^kKst-hpHn7aY`m~c$YU{;2~6yv`XCefv-K5| z-!o_Nu59+O$1`W~JYS`=IMZIJLt`~lCct(9J9Ei|1x-E zYn)6PlL_ezyEvZLtjbLqrlwlFAWiLy7v@_kc9&`%FCWFOBwR6yotcg*$Mr6V7dMOJ zB)OhZY)EJ|jCMynYiuzN`zfGllXhj5tHox6LdfNe;oD{-4}-Td8)v4j-Rr7CexQ{E zmE{N8=V54YeqI!5pzoD&n$G_0du{g4g+H@@b9`qE>%GVzEY*2UPBr1fh6giHB^cOg zmdz(Yj)jqI%hr#wkwc=DXAjtk3YtU8J~rJm`Oh??Fb!o!HN6iAyFCrtAFnwa?}J%V z9T)V#RG9@eedN*UfBfk2kFAvjHJ9bo*0h|~WtLNWtK~H7L9m?i4`y3V=~J_uDzcnX zah-W=SR?o7ze$_Rz)h1S{^A^Cws_IqgB! zX~u80VVZMDD*bZ$Z7WG(i?@=+oY=)W6 z1vzp~>e?98*K!Y@ENc%lhe+Ft4>bolEgtZCg3Jnbh6YxZwEA}*?N6OgsW8+ads9Nm z!kQEkvpO_>)Q|QX9;X9OlbUk|gsG0UU`^VHIeGNZX7(1WW#-6}xS$XTO{^(lCe}nW zPnw6z9AL9%_Tq6Kwzy>Y@Fu7>cpx(q0<#B?L#D~II+kkk_#kZ?kqik?GMDMlHkWF^ zXHQlSrhQPMR0S>@b8VVmm5Dwz7G$<(#2)m546~_L(6sHtkQ(2hDH)xomi-7tr8>bf zz>GQOvh3SmOee^XZ^jjwQ|u*iMe!6|k%^h+2&WnW^HaWqGc^LXss_xoXau5G2qv4B zQXA+W`E#liT5|EV_ z-_HL5%RxIbmxXy|^I}dsKT~|WkO(E4WWbG(iSOcziEoG^t30F7pS$?}`4H+6r>iEJ zDq*G|5|NrN=@Z**5=Ajd#rI+c$w$V-w-+B!nG!9I?7>u@&G6*Zi_2lIIabPOj(!nm zrUfagn=JY@j;z^{y+|z><%uIKxS%NRF)Ag{T z76{tqa?jPI@5nVvFcC>{deK?J=%YnD^Y*pQ5@>*7mS_OJpyl|}%o5mv8R4ds^&*xd z{-?kMYH+4KrSrtRoF;~_BJ!nl?-dd6Ha+j7iv z+v2z{-*)Miu-Sk#q-tit4M6@Fg=RxW+NemI;U>UAw&J-7d0MLpxo}PslI8rgHq68H zL!Uu5(a9}8%Yy8U7v`GQv><~x!&VG^4oF0sz;oPu%W;>tAoFq~wIK5Y?j`_|>P0Nb zSp$w<*c|5>!<$-=efg;w_tgvwGPB@=1sO)PataG_*1(wsS<%k$R>e^URww$>Oy6_o zthE}1Pf!_G$ez&#@t>hA7Oc(1wgLxsS;s+~vMkn+WYpq!V?AHO79p3dBc&hfUeJRD z?d7>MJTLv)k$&of{RgU9Q-9e_#;TA0^7(u~1)#@J6dPLp`>gD|x@nOwm z{%p1jKCJw5bE<&hq{^FKGksVc`DuB!538#=H->e1TxVf=57v74sLDL4GyV6psX6iI zv@nhbmvNo>;&op5EOlNQ*yF2X|sxpf}AQ=uuLWQqPy;OWZyu<}?-HJ3crQX{AZYcqXVGq9E! zK}X&5*Tk97 zi!_{B=3UZ;I;I%2A=-65w`u!nY5t*)4TY!scMiY^Wd3T1LLLy|=~)U4M2Zj;@{pet z(z6r@dqz2Gw_6l$00qjHqw`gn!wWk>w4&h-+_ zuW-Ey-dDK(XXW~tf`GUQ2(1gctd#7ix61@;>f(}6Y?v^)(iAs+EkY_xQrb%5l1M&- zAe)ePx$-56nKkq`C-v@k!9SSz3=pQDMCr(XPtUENJ#5Rcr2CRhUI#eJbalU`2jyXU z2=hcJQ&XB2Zywg-EY3v!Y8DHvoom6u+d8*LN;|Zh9;v1YIQN8tj-v_X=j4>CQ&hTi zA@6#s6D`0XWuEsFEIbuUq4&j>F0fexih@|2H%l4fquTJ%;+*PGtySTg>6Gf5y~SyM zwwK2WoavP6&zAproO4P+x$+h*YC4iq^^{M0=g-i7K#gWbCiQBbP^2ufDDI>WhPvba zfB?}*-YL}+FG?SoQ)*GXSXD5Cm`#tatH~seQ>RqD)hV?&`*7E~knU^fjC;}|=f#U= zJEa!VuI9D|zNF1Ht?85s8^&-0g+8n4LLyG7-r2azJEigio;syk^f=pI$i~ZA1D@a3 zP?R_`Q1kY&DEwb8RvH&_0CpS@^hDL zCb{$THO%(hWV`27L&n3;xaTHY&qP#4^ap9sTDfHMLHA(=Jc{hcmSW}8fc1Ut?`|yU6HS5R$&MEIS|QHqp6KY zzD39QpywH(P`PN4+{Z2kLdj~8tc)Y+SIA_L-!Zi4PVmU)MCrdjA~`#O6v?tC`q8|t zg*&04)G_u1rKekd9~Y>SQTdOnQkQd3S#ITd6(lffF74FA`X#;PJJlXc3(#usQ57I- zkPbAzr=)yNn_}hEJbOM@Ky5RXc}Oc0k7|(|s5x~W`pR~bslbz*vt|lCQjJ4eObOZAwJ@ZqFit-3B%`%fyqWS8RArpR_Kj1VO6Th&$v&Moiq7zyY|-5+pUGCDN9>@ zpWv>%zc6@B;c?P`U@%gJsq-mdlO3%y-74s8)I@^{_!0#?mKN|J1w5J-aFha$sQ`&S z3dnYIh&1k{fCsxwWZFDzA8gNhro|F!6!RT65If34&KMes<_iqBL5FpkBi`ZY`M7vWB7NaAV}4DCH?? z%F6(WYt0+^_N-!TQ&HfOTrQy146@haGF*an4TGK5vXZfG(Z^hf&MNsqO1`Vl_WG5R z;zd2Wcw&WVLD~qZV?AwWIiKb4u^CW+G#k0hri&c<-XZTy=nmltp!WqjM!6siL7ETr&Ouj;l`e6`j z&M~5~mvbDj?%-2^O)uC9y|RiS_J`kBw1rDQfqrkFISnSiX{!Do)+Vx{{%1je9S<$jUeL{sIT1>T7_J?bGjlUwuV9 za-Z#+N}ey=i0`L(VNXHXeCC#w?uBM;pvWU#qouG%-3v~O^r52Bd`ppkf%&ZzzU*je z!<@aO2K<6FoUF|WG4xT>6g_DvUwzEkQKC=Jz9QBR-xX{l9uVap_fHG8h%d>H0@@s4 zJwqgD>e4g7mJj{q-8(KB`4IW&q0BySN@HG2S9?ZF4=LXXle?PAL(3&-sWShKw998C zWsA0O+`d;$8)DexV17G*+(z^v&e;un(Y&Ip3aNEek^6EcEOqC01d8^vZ&ZaVs=(Ej zuR{0_Us9$W4ZV=arHcG9A4&pWxqbS^_ULzR0y{0$oP6CtWScnK>y3z!x4Y0b1~QU8;xLOI=c1bXHbQ5odONLbAJWYvJ)!hCj%ODUgxI+Yi0^>bWdf&^#|YJyFOvRV_zqI+!A0=7=>Eao;2=CDGd6cor=kQKJs?807b5 zhcSDd4ijKC8v}|9Uuq2q-L{B@^MdF5clV&SUK*Gh;a3o zdi$G3y*ezP^T#2bOk+Z?%_HOp2tyYr>(oX+aY_g|%oQ9)D(-pV%;OXxotc2_%GRh$ ztxM!b*g6P_wB^-IuCyi9=^MhKx4F-E!sj%6%8_rGZ9ovMXgKH?ES7JgNG+WBK_;=S zk6AGr``ouG;#?t=^TG1S6FIm@@)4;nmL{E0*{w;e$CIXU7-r!Q!J2&m)gDSu&Z4+_ymt%qW1@VhAq^ek>_ z?l$gru8><`k<=;M1Bz&}0~{NjB>CBL+CU6i%GwfI8)~#`7GaBP+`h+G7CPhh2|-Kk zHlFr)1v5*$^uBtbxGk>v_X=)mNbCi*&B-ROh`S3)qZIPcds?2iSr5A+0#-sEFPZc# z#mmW;>~-bKQ7@e$LOCvuX17qJ74mp{T3R^6aO=(H_jwud!`#^65I174gJa=yO!N~D zK|LYr@shcSAP{IcA*7O>5K?OW+^E~gvaMy?i(Etb83LK z^}~b3<+%f!PqHO?xeh&z;6=EEFE({$o?odd9p3bKUB-((ts)wHC#p{PjUal@?tx%0 z&hkW)hMhQEA+UR=qBPYG9oAjaEvayHx7|t^Qc(|ecNJ62a=T1}!kXufds55c!=6Mj z&C`dM$IDkyz^HE2sBpf2y`8eA5mbPcv^9WjfS=+s^_cK8gmuE-BWw_Uj_@=*x}BwM z#5iwXo#ImZlol%ElJk9Fbn%ol^7}&GVO&di05Z- zD2YNAW+KOPQOKg!-W{WmX={n2XmMroD^-8xh=>p zXreYgu}z#GXC+Y`AM=JcjP0my;cPrl7m(DUbLhP3D}Bx8+lau% zM@sShtOxyBeIw0kEGIky6>(I)N@9knI^h9zyVeI3=&i)qwb6X1G(>G14R;!|2u7Om zq#`OD>H>spxD3jLoX<(1xS$l$(^<-%k|JEBd2(+wm=v(BOjCgxB75D^(#$+5;ZsN+ z-^i7zSH>ff$9UPwN1A z3)Awfh4K6sY+-}ziAFdKhn>t;7)`9Gc_B{oG?`>^T3FHC6Q0vLO)FWP239nah37O! z*Vbln8e2i-OyiDx_{28)#(o7u-DCa?1=XH4bmD^MJ=zKRFg+;B5%(l9sN7bdVHJzQ zS8D1;?;6A8CeYF*vp85o5Gm ziQ7PzXPSA9teWIfT;mpsFYCGo-FsW+*k|?NNV(pv@c^{Tm33=xsugi(!lev@vpYIN zR|-}p>cWSFK$mM80=p;RVNdOyfUOY4ey} zqocF!jTi%t=X+_UoWE6Gf>Q9SGM#E4!l1F7lbQ9@B z>k369sWNPmn#w>fK1#7LU8oD!FdO{q{r4C)f+59YI1-IvJr>y4W4$~R+Zv`sAyyhD zo%6OK%$b?v@N(!8r?${oU}hsRm>HysnQIWPB%#>YZg;NGWHelS;6@P8NZJLv+t=$i zt(4d6o(D?Fk-^I1odv1ZlHnqT*iPj0b~mwrA{$VEE*tv)Kodl>o!N7gTu&Ooq^p?x zqKlH1-f=@yD$$H8V8!MWV=YEW6kRs?m34fCQBBm%lRBkaS3-rmVv>^^lX`7K)J%DF zX>l-Tj6BQjFuLB%A-PxAH4o_87&bnHDzKa9}_l0OqDu{ePx zJEC|;XL=XW%R(;q&vU6;2PfS2P^h=D$L@L4ZML0ia*ysr9xQH)JMI2?vd4`s$q%3b zX4@{^Ki^f-G}bA-#V?lE_FW0jPR%OH#QpPK>HYIPuH9J~(wsb}RcrUpQ!NLYs0NiF z!Z2zCpE%5#7;SXraN6hzPrz!UH$=c|Bb|I&Fxx-?fbQfIP9rB$c68ig@(1j4{pL*k zV%fbc@=cqZHa2Z$+Q1o2OB=>fDIr_7^rgqKUxfd119K$NG|Bp=UH zdlz>_1;TQn`!WS{aa)icaOyt<=@D=UW3h~o6CUA#L`Nn^UPvUT1mhg)1O9Up$s+6s zEsUVUI91Jsm!BL;D)4fIENz>TOf_D>=SBEbp>}m$HX87grrh-zSBO*N-WtbkOD)qJ z&eD8A@5U*waX(I>&K#@fPjM5Xay-bzu+(qL3D&DAbOVVl`Q&pMRql@|;TfCt?NVgR zUVEpRGd4Y_nRW5xgQ(9XLfQh_S+*ERzDg1oUL+4ovnKpHq12*B2s`4az6c?;xFlYB za8oK1xH89d5E`_IbfNwi2w9YMI|NOJJJ{=7s>5g&B34qO%>=ST2sp-3L3?wOm9D{o z(wcJ%F)yomd6f(tS&OBe;jsyGY^rZ&GJs|&FAIDPQAXM)8tiXBP^C=t(y%b!{T)v)!!z=YKQ5}2Z zQa{!J(x&Ja$@xI@YER}73}eswV7PgXIXwTWu9nMWHSf;LoX@HJ)0Vj2@P>&*Fv%CW zAxZV0ppe5NA>BeqA*=|8$KhharhC?NQOJU9k<>b&YxAzan--k1d_bKR!Z~}PIMsHA z>6gt;zF6OyU268^R2_(CwVxDF-(2AyNJydeIArpTQtLT#_-CS79~!4nR%(OIFoQG= z(T5=t8G$_+x|+8dc4nS%!)t5F zstuONu}+s`A2&JHWlChc_)=R>qWSS+mxNb}-+7JCwRuf6MAu@O3#@YUYC(#DA`8qL zlx8q0x1qovmG;5jWUORq*r=rsBmr#9LPmAgu@bl~Lr&ne7se5q8SOETR6+e(MEP|- z$;Lc7QNj=G(IE5`& z(#fv2a!;oOe@}9lu)|iuneuv)j}wIq z^uM%CZ?FVxwWLLRi!41$VPf#2z4q`D6ND$wr!jRV?j5E1cBU|7SA zH7Kdw+D^^cXMkBhNjqluv8z|~T`>-6DoHIBj(AhIq^n3RfimxqXu7Hp$iSyK?;?76 z4|o3x=WW7y8JxG}aPE_v-g>(gDQpMq8`g_WWK$8J?m!eBptemHvlZfMy<3Mn(#lS4 zl2Lf(?$rU95RAo8QJ2vxx>aCv;2O{1h3LlQUb;HGObTK&A*w>tKG@G8~Iq0 z-f430ya*RYy5wBNitP?Kr};evyujgMAt{V;L2;GrSsqRd<{*?Rz9n0m&Jcnu1MhR- zq|F~>n{KV)wA;|qq|wl8-!R5q^I+acPudEoWr))qHd)WPf7Y1HY0?XTh{htcArUOz zI$bkgN=vd01qBrXMMKkQKG`+%?4?m|EkiiO0)-tTX8Q@O8b_^sU_`rZ6@GW2cngG% zkH4JM?6i9nC|_fzfz{q zreuR$Yo9!)ICM)fyVLXt=QA(OWKpsZxsw#?+#*#7mR=nUSQDuiQ&<$x7e0BYCX^{?<-g!aJ7FpZ4p`PJ}&m zE}Wyz_(iJfe;HLJg~`yzQ`GljwY`jvmB3UThHFnsd+Q*pzL0S!B&i<>7YgcLjQ19#c=xe@DSQ#ztFN6UAR9U_DV>`x1SZO#w=Dn3-a|Wrk=r} zdOtMTuCA~=3ZQxxWc4ga>**R|MuqIyP($`EuZ6@B6&bp+Kvh)pRV<*2B|}VzOOj$z z(0iz`L*N6g2d63PmTb$x{+XzA$DSIJwm`M21J>~FG!zhKlcAmxWXFWFOHk`(Iwnorrlcwiwl{m;_J@_0ticE13oQHIkZl$&JjZBCbf8k8-B9Ln@EwYi_WG zO#W!Zjp@tapr4avycc(#;g z${JcsgJThk#J?q?q>6k|U2}=p6c7V~HYBR3j?vP}6vdRJ-4fvq1eOdF?LWyUnO#*4 zNo;Z`tsE`gU!aU1`wo&S+ZnUX`}$6 z3q}w6V?!6n5Q=az6t!q;`v6}SFaQILMb?c0+L+-(PKXQ>+TJ4UcU0jk)cRo>0{QG= zGAU^Bu!~MhqJiK1SPvlMW{ov6YW7$!ATc-A6x2G_ARypXlao+4khRX|q1m{bG1d@S zRz^D3_*`0&D5KgeHsGJJ)&>|K*8w)wIJ7uJ+|oJ5I$xWQb-pqm>pAMuwgOEIh^BPF z7bYd~R>j7e&w0297}g)L&iHu06>%2Eo6!}qXuM--9Y~&jBLaz58*;H<)*G>1)*-Q5 z)+c0HbI98$iEWUql$zvNj0l4Q&@&^Z0>qN^xh2N+Mu+h;+E+NaOKPOFH8v8ipF?hjfi7v|~)Z(zuQ(F+7wEGOlaS zrx@i#Atj8uBuy$Mpw95rk|=^nq$P9t0)G|2Q+Sw?F$^$QQPp<|id=Zi{BsUAI1HB=?3Viv4!;GI50AeM6bAy9A5uU!_ z;A9k)ADlo=&B4)r#T;s9Nbq^H28a78LVgVwbb#+Vq%;SoqQPM&S-nT1Q}eF5lZR~{ z&oi?zF!wvz4qRv8N>c}+ov8q57oW4Qq(?p^V{u(2hzfyZPi2Fcp9~lGNc-rxxCbAi zTCtEFGW7*CMYN(56r|P;Dv@1>*iKUZI?YiHMemUy+9yTCSiV2G??iM-qYC4I$aaC-=sxMLL_{KpGFD}`GzJ=m- z=}@Cv6)jCp6q!8rWhXn_(H?CwHgV$5LIU5ukRT~zIht>vTrA;bl>J){W+hN%x2_9{ zlJ~OF9OMtE`Xz$8(iU7Yw5L8q5_7aZcp{L!xsX|#a;D!qsj_HTd)lzZe6M&uS@hv{ zYkh`U$`KC0*^sDqh$)2u>lWOPq6&)pu^M={K8$+PS`l&}bj_Ni55*~p{TPe!5_(e@ z{0oQ7Pl#o*#}es#+(jY^7PT4OkxR<2k6=8I>fsE zl(mNG#&hb1e`TGVRv(5vT^92gszy*?Fc8kOf}SnVW$E0RZX;)=lw_Sa zO(lY3LvCRT+!ZEGUJURZwi_a739eA6eVW_p4LAX`jsaeYh!OW$KE#l+v#m4jxI`}z z`Y$XHaeY)s5>CuwlP*2Wfl+UV2oRJa4cbmmFliQ7X{sA>-YQ2oOs$esku}hiwbMXw ze)5!@F;xxrnUbRHU0tZILO&vBaC~`ByLb=uE(~2Y(zRYUyK31{fiB0!OP@D1PZ4>+ zu2QJFy0A$G@N3#tkbXIK;Q&VB;mzQ2ptcb=tAPark8FlY96YKF4o+`YyDfu(S%#4J zsm)OS%v5UaV*lA@8k{{!bK$)1sBHo5=)Sd4nm}a?uGMgCGcG{AXMQ@huTozo?`c$D z#@P6*bn3tHvfj>eTYE<(Dilk2aeVj!&V(F>aUnLhVM&5p+NP5Ul1ftj@*b~qo+eSl zbv;VjX+$qxSdGBQl|6i)K?2jPzGs3HQVYDFl}t6XyIb!X{qk;s1PINFW@`~K4r`E) z2Z}`#+%<@8FMS&L>uah1QE7?{yUq%2$HP}$uFxXzF>N zfWF5FWk{q`#-d!YN}`OxX0bubL*1WibePpcdCECMqs-Ul>VCctu2JT?5bBaozy%sO zmV}btF^m9T_);7KPN0Z7QJ&N&(W6<1+IXH(nD)14$k6`w3=PaHP3sWS9hUfl0;HZo z>%sQ~LmkmwU*&2kqOxBfd!i5}nvYqf$Gx|XoD<%f%Nw&ZB> z6s4V*JO9%~(34g&J*$%G(kV*&c&U24uy*a*b!*qJ-LQ7!+D&UWuN_^xW$n4^)~;K( zZvDCq>o%_2v~Kgd(REwaox6VR`gQBquivnK*-;)Pe^ssy z93%BCQlBN%=w1$v77|9u?QP9>Ht^0$OFhz7oe$;g+&?+K=Gq&k*4(gvml4jfw(40s zp{Ma(@zs|fnA*L6-`LopeK$|;IIwcn)$#s)@s9ZF%l7XZzdF8Y$KFHZkYHQ2FBG)j zUT^}eRNLNu&N=72ldo4Q)qx{zumu$#u0+uyHGq&7(!7T%)x8E0iIu`Xc*y?cL*>yg zwkM~~L;qhe4`0!?S8LO>M@al^N8qpr5e-+_nh^fYwf4#O>fwT#p?|Uc zJ#|x*@5S=GSaVf|(C|X#M9I?~%`SbOF3~$s`&$}lWPdEs<& zoh0P-=vhKu$aVa|&gz5z%XM7H(KyBY^e;~@S)8Min#lQjhMehYlK~D+O=b*mq*|?B z^PZ{kc=x_tEymif_Jtd|!NU@9v$u_g$wZ9PX(uQfv1gno^^z6U3}}M|-Nh z+xJgS?!WocLsJ(JPV%)`Pqlc?IT1(rRBI=V8lvbJp-7gl_R!UKf&5FJAx}h1B=%1k z1}DJj-Z>k8q_E-EZ;8z>Hz zmb5P|j4X;vXSJPOTwOh;r`;Mi=Qd~ZpVKw{=aSiqx^TJ=R1+eebuAI z&%XOTAHMrvtbNN{ufFrccO4#H`tN$@UGj!=)|~&2cV6|ye}DVkANkln{`BX+`Ul^9 z?Azb@i>LoXxo`febsI;=ww`zK>)(0%M|kw$SO4I#?>zC{r~gA#?&-CsV_Pq{@Z#6M zYuEVgAN$SU`t}pwE%)@Ty5Qos5Wo9lpCqr({!3qewA5R7Qg)+|MkE9-Sg8uH{AFaKkS`1vTy(J(yM;;y}$Rl|GsGP zvXKify6p0|zU>|Fdhab?{N|H?`h#bG^j{_qest>4ul@SB*Iae_Icx6w+?OBu)_1@6 z!{6BU>-Vf#`_Yl-KlgXfKk@u!m%r`p?H%)KXRP__|Fm!a=y~UFzu@r4{_goVUU%sD zw@>`ZQ{Vr~zk43q>#shBm*T3%Z9gpE_S%l2wzj@oAL!lMwrA6_Mbkel4R#dDjZ#;6 zW4XOlXs@)_s#naL-~OhKVtKf$v(!;)FJYQ-Ja1d6S}F7{Y#S@}wO86|9dB+gwlD0t zqWqfD>QbTHSDDv6R$jWIr}BpQhVsOU>Ems;9W5=X-1a|8ztq04y0~*e_k!+;N>^n` z<*glOwO!bCcDcJ;D6OlWU0zbDmZl%z(Ma-!^6Ju5$E!;7O0OF2=s2@-+w*+`9c%hl zm*QG|-t=AN+kSnpy6^*UD=iu<*QTFqThq3+z1Ta@IsKW{g_{`FZ4Z@;@V+Ij0c7EC|XG5yf_o6234EgctjbXTUT%Svx6|5E4l`v!))7Ij|O zHT|K=@7~+JxV-MS%eVgd>FwQZZPUNgck2zccdtCN@`m#C-R0@8mxfC7@a!E~RNWp` z3I)1cgtCiWY`>}%`pWa$`sXhwE-Wr74Yw^VFE31#_7op3{z>u4?mzAPv*P!Pe_lA* z_Du1w<7dl1D*P=<_OpwszgFlzW9zFgyZob{{Nz8cw0CYk@6~Vqn-hOhUNG?Hw|s5W z6W={K{{tWV$R}H=^s>u$jlb<3U;6Ux@BgjN(Ze6RzrAbgtM^~^*Z=8l*ZjtBp0V;x zzjfrd|K+{+-T&FIKKy8<+P!e;*!dUy!l&+g{Ev^c4=!n}_~v7LpS$Apl^eEYd})?m77GU%ll+_kQMcM~|IYb3P(>p!!VlU5$U#R$@HH%Y`-POy9P& zv~J#Td3oouwzJw^Tkbt``ZJZ~<>lp-9UH5K>BF~~wTs&7rJ=UM zwk_pL+E$iJ<<5@I_HFSQFIf?Vnsd z{a?EdcI;bx;q+JE(m8+nBez~udjIx$3*UdmSs(b*>F=$&q^+x5y#2_lDuwc!+J-h3 zZ|yz1ysP`oT|K3Dl+QbNY0uf^PAIc7{TuK5Q#Ocowoi4x>8$QD?XIlsSoVwE7D~0D6VXMM(cso5l_(MA1P>1(p5hnH3drg^$L_w>T->HR#tf~RNZo?e_i zJ+`#kp+@XDZ~$B!C-1Z1U^JKa(k$=ErB(FDwho1osfJtBDPPcIYRr)~+DdMMOrq)MaL| zxY{Ko?l`d9uy!)84sGAD3rrtCtpZIp1~;M5?o!`DQ@vVQ9`D<60}VM`uhw?#ogCk> zi=LRiIKGP()vHEo*j9D=@ScNXpn^U;K<=wyLK&jdgx;)&>(%Af6jEb;`d9LxHB3(O z{IF7k6jYz*9aZTKC-+ze8mnU#OqZ>+J9&-BZkO7!qI%Yjg9pbaHW`6LS@|J99vu8F{h{^GThxSex86G~XS{y^Pe*COz8{@tU8T5&>T>9h8MRMMI z7Mcvogw5!L(kpg{I+KTadId?FNm-jd-J3mqlBdtol6ASKH)KzrJ*&EIHakx3zlw@A zlg4McXD@y=(my0Z6=%=TMW%M_!LMMwIdOJ%^Xww8*^iIpy785PXZBC7l6N8`?}G1F zF`=xko-zB~YbW>L5bBO!eO~Z2KC~J=hyMP5rI|f%)Ibo1Pokh$8Y)gv&;=nna-Y6C zi3*87f*1QJ&uK^3K-q;Qc2DFsCeiWDwW-cQIgyKA41FXcpG z*|Y0i@6683`+Bxj(`;I4_G8;xP-9QAty)jqK&m#t=sry1Inim5OE*Yv%Gy*;?=%_` z8>Jy%^K62D*2Zn^nTz()L+bU@&h^45@2Ce>&BLHl zRM)D0Rraz24{VwRm&(4Yl+8GQIHI?1+xJ!PjNXXe4O+^vA9=pTg>!V(uu59gE~rNd z6o&C6olptWu$#ai0ET#X62Qh%YG*G5BNtt@p?OhlypY1!i^7=neAH7d^Q>`F90QD@ z$($G*<&e7~n|+n4A`!*DC~nftV7C{&OTUuRZe7`fC6FI|L-9vmK!k#tzan1{YCh#lLI^VM7*wZm<8DP?ZTfD)uL5MBtvrY*G9~D<=L)yv zxF;K^W}T;0FX}Ly4a_fr8&SNQ57Z#B7>!NDA%a8Se<<`P_NZjlNw2p3R{Bb)X2CaP zo5j7m+*jQ@bJle46X%caed-XaULs~8+nrg7T|+u|)D5a@EX7gxyy-K~6Dn$df(T|q zJj&BB4mgHvGjr)NZ>)g*NUvp2f+u|_1)n|tWCge!G}Q`$&qu!w&B}sl%3AWFm@y88 z>a1nPYy=#@cLk+Ca|yoU&9&BJ8oIi5PHVxtt9j<6*1AOYd;~u7uDDRn9f)jv2b~Nx v{#l#UPQLnrnwO)%=l$orpjh4@Jw&9<0d*gTH)rZlq@%%eg#VIcPA7ctrJdt`VOKS8g zu4vR;iq{pzT+HQC@NlwdMNvG_u^0ouiKoXCjmAjxA8=kp@i|>|H4(WSq%gOK+DJRK zQ(w&L+ioV`+y!%&%x#)KcX7*%S@Rb*&r?=WY}3_O&%a?t%k@hZ&0Vl~ZnN?mif*~S zrFrQRyU%KhX`Q>E^Qc=W_FB|uH!WGXXh!qGr3;oQ?c@!k7AtGW``|wB3fj(C1m>Qt zXuf%&QpavLZP!mn8hHBEuBl!{Ra8=$&lTlSw8Le-o=VhV2f6u*OiJbI7Mc_q7PXkM zvxT8&qMPF7sM}N5^%VUuV1op9F>DmyMwY{f@HdKwv_72c9J-GWCRtRqU*) z-&2vvR`~TND~5F4>F=Xp%9B3f04(sdZq!BJU7hMJR#_fXK~&XCs?|Gcs?oQm zW+I;JYp%fa%bM|W^fY}_tsA3@vq|L(vnWD8P@7K0q0ee7NOpLz6Dj_u0#fypeWPfA z{%zmmXg|{LLD?%=|Dk_^epPLmex$z#m=pb*Ed0#6QGgz+dsRHEl61X3&1&giJy8Eu z-&(yvE9`!_r!QBD(oR;&VpX{;HuRRov1+reB6Nqg!$ku_g9k5m(V)=ZMrZg}dua7f@ov0BLqy4br2w&sC=m17n2ch7Aqd}>1K*ge{);`PBH(g!=!+7oTsZ3U~ z^~NiHmoNtXA7??|*zjA&>8G#wgKvDmr$&sIutMV^^; zE71gf#q7zE6D=x}^p9rm1a3pi6p7pG3Hm1KKeZf({eRN>6wwxa)0{>h&lP-Y59Enr znQwCF+?)kOQ$h=ZWlox^Kd@jBP1HYIu!yFGrZ4Ouni~4?YEB8$gng}tUy6zfzi;az zKTXkJUX+gKCyO?w2u>h9-y~~3OcOjz3EjK+9-<1pd}*HZ&Kh5?{!vGg{zXS*+Zodc zj+IJ%-&rP$?PhVOCL4?8()cG*=SYlqC@c(hjLOGoReOf5$On=fiOV-i_sqR*JL z*40WPn``wSmp&qea+&_cwaGL&OXBs(qr0_^grCv1qA+h%gvzHyZshHt@ftg z`mr^sG)(_-%?Q+otv!Qh-L0*3On>OswN$2;tlNU_Z?8+CDEV67aJd4$`|Wt3NBwS? zn}&z(xpN!Qh|qw$vRuCXm8wUhAUYL7goi8jMfdfjs?etU{_ZH~&1%o655e7fZ>mGnMsnoR%%Ma;C)8n*RBwjPZxfN?3Qh zicD>o#hbBOPdR3tSwCZXgmvbiGba7;*zIQhPJL=exwgMV1O{!t9HB;nNARkhHR-%y z_B>pvI;{y~`p)yyKZb6$S;92qX~!M+U+04y;qM&-qeYw&?&OyHGn0Qompku|cX&3N zeC`Sz+ALP7&|2uBhkCMTNr}~in$Y`^hwmZx2-UsJH(#fJ0{XD0UPMpd&f(E! z?9z?|G_S8NG-u}og5%!(w{5gmpR+5&4sC09Z7VFt63r8?3Q^4O>f(&jR#izwY%q(k zjCWLpu6VjM0+w<63#*;%R6tLAIm>q@AYz$AbISi5daM7Qb@`&((9 zzF>b~IHc?nQjV~UOm$fx%ql^3pSLgx!su)ZOS;s;-rwIZ8VbZZlEd~_>fH|vWGk}u z`3JIm?b#+nUdhnf?9hD&W)iIpoqe@{JjcvA?bmxByfN04k>9J`nyp14(C<7rmED!C zC%=}(HfD#aUTbqwZOC|YC<)T<9{w59C2zk%LJ&W`bEzOgC2tR<(9-u@QbEh!&wzqL z_rBlnm#KL^s21AQK73M$?)xJfX?**FF-`}{v|hIbl#vdTf@LTz6TV*h2V{rq&BZE(+grN__}2FUGo z&=owxO~+AnM9?!Xn#P~+LSt!~ksM7|#?Sx*&TuP%8J?R-FPnKwf018wqrE7;>qZk$ zjLxDzq4+6_2AFNRe6C810V9h+lETaV^jo9}U)E&tkNi{vOnQLKtS5`N1|+5IhyV-U>UtUgGzQ<)YXs@6@`;AA-sh+&U15WK< z1tK&X-&D{+@(fW)6L}5)M-`>BEq;EoifTNoOux8`_o}85g66NQDcz#UtW^n`4^>l& zrBt3!OLM55FRP`i=rZH;T3W|wuyI{Kdf3H23mEAPX^@C{{ zQMnO4l+r+o=MIAe+d0q=ZM|nW;$aC#lWOc7L75S>*?4Ch^%8X4ljz@~|96ui(o*B_ z6pDc@^M6jGCp^{?Bt5RJG*f##Sxh&8TxpDSv}|RAGB&!4c3(1P{nd1ujA4zlsDL-l zArD`EISoj&2*ik7yf_f6Iz~scE{-T|2Y>H!szX*5v&M18qqCf!SQ#>Sb1T|&Eow?vR7~@gY0@d>XK$dh)Ytg#R}@1%;8LSipY2bhwYH#DgG)^c zyHwt58KreWgcdGU1o&gd*kv?07PGwfR=UcG@WCV3lW8-BqJU3L72BB<%?aOIq?n;0B^(-zukXS_ z##91#QyDC8;@#AjIX}(OYV;!=Dg4oUDUx;>#=Uf>!zbLkm{6?c;rX2svf(i*4{-9b%M%c zF~LAGFF8sXeEM#ROiNK&FC`S?PZi~k7=N0|ij=>^_`CAuyD23yU7#O`@n`UjyU9;6 z{Mp@n42W%|7zfaQL7N&3h&_*J1DI{KdDKV?@~Tp7qp%f9RR8~_l&uCVLVi`Xpe(f; zKlcn}^iIxKEQK764r)G337i-)!3)r-!GK3H$Qz%fw9yx}Vm@B9{^KGvM34aV+ZUlB zHCyL(!Cs0|tMEN;7x%wP+OH$QX zOZWlR*1wmJdye{-Ku*$BAsA_@NtUT5V@8S*kw`7ra?%cVEYaU(YkAj=aQM)(zRED`bxKWI>mJJvV*)v1 z`=73+2)Mg|v(*d%7YevQ%@c4>0ejUp;S>VBM8%YJptpccSqF*)%(SE62O23>JJq4G z5>@s!+o9=FRnjr*m`a%{Ut-oV*>Y7fVAdg+3blJxTlfVKXr(GSH)j+prg1a|mWr|i zrS@&4U_;Hvu0a@@Uo8gjg2Py~#DY9(sRiY!Wfqj7mRnGYT46y>wbF!m&5IP@cGPs6 zVi9-9bz-d&csq$G4qD@~EkvG;D6kN!jSy>E&`7lr(tk-OVbPFI3kZ+hgJFrmb&JJl zyzwGk&EmSMUCv7$l1<=Kc2T$9-(rJ-TB7OLq~rt&sz_41TGSyXprEZx-m#Zbl5F?y z3cElzmht|*$S$(@>Af^WEc6QHF}Yldlm}z{SU$a!EiwXB(9Rft4}R`d>dKeAOpWmg zVF$O@C0?v{HQss|8F6-EK3NX&aYSM?Bwc`j+A?|lKFUh!p~lM<)k95IQ{{^CsJX_H zeMt1uz=@1Ca6xhb!zIZDoN7cKpcC$2Zs*=Zw1m=l{Q)X7{(OjbJJRgM4}HkR-&N2; z;7Z_Y-k}-(u4;mOxlf8dR`^YvFiCHh?||3qZbZIID;=2ky2BLYKRk^D-TMJ~9SN$B z`;JmqO5lY@X?TwP9uSi6ffJJNfz#32u|vho6ZrifP_MQG5g)taa3En`Akp-iacV*^ z5GUYBEn=iNbAuhk`nzK+OdNq6wiFvwN@8p>jnUDceekV|)C<|o*=MT$s!A|{CB=9S~r9V$I_oCY{b)vmnq zQ$&iceAcH_4Vm5dDa}Cf!>8DW#PHJ&mgInU=W*{-GJ-GP<6yG<=silz_ae_SlLO&U zO-Q&?D`60(-4QE18h`8rc6$E@xk8b)nL|ZVXF?*WyM$bqDE`C=nt0deq>u6nYw(Cb zj87at6No#d1qjmcA9ijbTuIoGhyX4f$%&V!+f29(tL1!7nQ%U*G*u=&wHw~kOdqz! zi1eXI*%l+xihSh}coVTcem1|H@lVQ4#BvgGQ;pD`RpetRveSj}EWHg#@1;4Wm42WF z>6Dmtax}t+oH7DRrwE;V!L$&4{>un$=Ot|>QG_+W$)ZR)0~S$F*dw3MG&5DV{Yoht zGsK*i-FbPQm*V*pN0kv<1OYRSR}BN0EW^7M8Ds>JGein+n}cShqasWBkLhUQcwzf5 zT{IFwT3Eu*1spB21A&2HBKW*7sZgvS zw^&x<0Vf`T9W(xmbv6(3s2iT{gMXA$RXsT8w03hy?ISEN53GzcZmn))v{MyHa&9<9 zjuHv8S{SZ_GkX~dYwU<=`}w_}xkZxOK#`=LmoAJ^Se=kOKzkjUM6vd4(-SMw8s`n~ z6%u6fD`+LEwqDxIywXnfgtY{6MVAa|N@muqO7WRlvtN2VGi(0u^mr7!!V;1@C&tiY zKk{Qy|`%q~=@wJZgajxz%F+>S;=~^JJE%-0Jqr z?bm&7zubOpaQo%<>kn>`Kjtf&+VHz0RJK!o#b zJ82H*+0yBbK$mc$Et4a;E-WskLkGfV=hb%hem>Eb3rFPHF{+zC@o!2>6V_F2Zm7jh zXK$2XLa@h={F_o_bC?IS8Lmh)$9_dA{QCDPmhFw=W1K9RkNk=v`NP2QmaizCI`~ar z(TjAH4?crqq@za58H%F+Gu(?b*Dj|m{$N4UfnQ6v-pF)1k%=4+A=PRN9W z3%Zo76Q9^{hT|K=W4@tV-9o6C;OQSIF~UC7E#Zg1r#vdL7 zxau60$J_f)xN?u|Txx{Q(bFs~S7xCW`}ypG#>WfAF-!|;oGj%)GwlR1|Q^MLO&09*nsTw`Z4`hcw25dKE(Y}!xPEI5jdXiwKz6O zhb=`|l;n85mu&&z$|!avK8I|KLU*Avlk)lQ2;XpsrN-+~?9R>{Kkm4QV}XzyuZd>O zApAx2g&gBP3|9VmMIHr0ay%}EWrJhmx>)uRi$oBWXPoK0DW2tvm>O$lrRk~*=V2nZ zAb}ErlGWn_BtoU|EFxb3qxOjxz%dt00@9cM%5?Z+FK83;5F|{|jO)~fn2PWry(Jm} zj_=ecLyeuSrUnCaK^rU``%Os{pg1=&Lync$$deAx^aKMgyGG6va+kkBsPn0HYC&9@UF(TFmpb0l~!4~J6|1)*1jW37q8%qzozSO#}-F!ilh9ivWw4g{NuI#!)1V0ltD zu1%dJDweb-3s|19kv#LVr7cdqY-x*gFI(EUAS0wb#+J6IgRQZ)v_&19kF%vM>cYls zVej>%%EdatmbU01g_OfLB(c1@7&T9=#tQ}C`D%>?6{xiqRIK)~pc2(iPfFE(7Ospt zl397bY_;A(1XRs}{Az;*spAz)d4{9>qmbIr)lL@x0 zJ%O4`sby^&YI2_|Yxkp;&3}`|F3Xhe#N-`F=|E)d1Zpnhcp7sP+@n}Wh%TgAUJ##Lr4aY%k}s#vn*_Zh`s9-2}!U%yn*op~|fUS`gFC7T)#=c~~Hl-~T$L zvVf0o`UL60AJf@NBx1cXSY=jm2JAFKKC-t1KT`gE;S-aXo2-Wpq<&QBDvj4nIMu@{S$UnF1PzG60qrt=$$+5K+w zlPFh9*lPA%I)Au?^uPJ3YCa%gjP|B`y&TJ^?f~(F^{m=xs$=trZOj!+)OypR)bxSTG1@mO zkJnh8Q`~}){o+%iH2b@{W=(CA1~m=hfd=*^dsGsrG=>gf_mHE1msnn;u>gA@Ptr98 z3`Fp!8vf28c6Z?m*7XSULWFhA&$?h_UF_Ro-e5S)?;8w>4(84wtO2hYJcJckLagN5 zhOm-wC4MNong$s+4`oAH7n{)rT*>8ohOjiYMzWX7>uQ;st0Ne0RPo*;SZ(oo^SdqC^Yx>cpVo^Gwdsnb9zp3s3TwpBZv5R*ES^`5W~sD=H;$J4 z-!htALw)#nquEW~;eLnYz&C=gYGj9;kLKcj#q=?(7xgvPj$wC+3laWt>{C=D#|vdP z@Qo8#J!$;N1SUSW|L+7gQ{IA(g!pjt!V_R>lywW5&!5PqV#G@mS#ON^dLny+t@QKV zlW;9%^#xa5+Wq|NN$fq)du=lNg01oMXQ!}%Y`vdrQ&|o#oXQdzmz4r*VH?*>WxG9W zqo0>Fvyr$1W2|Uq*E2!?`xcgE(O0Y+2km|%zZD+>ME|K*vU+i6X2X@NO1$aKD_J34 zOmkSHsE(V%%9GaneXT0oh0ur;YrPi2h&dq9&iBt@;~A=fxoi};G8WBc%ZV?(nx&>` zn&NkWe7!hQpDEmE9-9+zY3+RT)oc=EdG=~HG^IiGF#8k-ylR9HSCrOnOuq(Zj2Aq# zn7v9H_|he;0JV-KtO+%?6sLCWM#WNg%7JQ+8`wfx$M3p4J;m)ii}r&#g5=k zyYa_m>?4=p@wY2ke~j9{l8tl}?&@XUxipK-vViv4;Aqme%WJndoJLL2wi}nNW(~|O z=i%Z0HSkm&?QAa9bMG2f!A}KQW7b{SRfs>qCaun=5T z(>{KHr(DI_aCeU1eHH8GyZBz7@%O9PQzUMm+_VsG9=A^(T*wX@b!*t3m@a3l@Ug?Z zkGjt2ayOgK1S;7=Z8nzN%U*HC0p&7Ls>6?^x5F6S!SbBF4^_ionxiG?GF^6cn7|7H zG_hx^j4hklCa1ci8YhzGAkg)gVAS`eOu;rXYF{?LeH%+NZrsKSB8`N{>IAvX-SF_ zrzpyu4n+|^;5ZVmD2XUj>^kRvV|8hP1VzaMnxRiWlx6rM{O#jk{*7%7H!p}Vn_KK= zrqd~pH!qJs*CX%u!rI3W8;N%grq*l zcp*U>FQg;z&j2sfYUAfv_)WmKsht|;S`7*$B4$*J>1CsQ9xu#5X&d6p;0|V?bO0~f zZ%4mOl=e8=2JH5&XhI4c?*AviLKTpFn>68Jc%d-iiTD#Ue-?G224VJs5!=W{V`T_Y z+WnsgEM`~$eD_ZH*8mHh{|n>A%e zC;T@SJ|Fm!PWW#v{8GH7tP{QuBqZoO2E34@P2ZPj4N$s7%%8hp-rNOOI@n3$tLNCO z5&WYUSrH%jD)Zq;WzQ?D78fW{6!P4CES6uhj}^w1Rm^IwsV-|ND{ZPSo;|y?jK{si z3iyV77*lS-Zwt6W!g19lmE{%1Ewf50E32!^tC}k z{TNwoc4?V4t9({@bwycCaq;ZtlCm0J@*+4nC%V*{aGwK!`N_=Z_d(`!YQy`E=W%;k5-&Q)%AF0Jt2w*_U2tdjiGyqgUB=^HLotwF z^BS9i)N$Wyti)APQ(88d)9b7!4dK0CXA9WS8+g-uEP>BF#3K35*V*N4*!h=cu;GKb zcAVw$-@n1K*ofg~<-<2vHXAwE92osEOX0l^u}sIPn-ShRZDAGad~BVOGQ(2%M_me zE*l-!+&rtisl27CthI7>OKWk^?8=(f*5c~Q($=!s zWfkR@Pvu3gv+g`=FW4IN9!qmvv5)v|uR=vvy~_T|XS~N|$G4PKRn4ktX_{T#GOM_z zrg$cV^C`8!;|7B%7bk$nDp%p>e7 qj=%CL>p{2j)1R`*$kb2_@s*Xfw#=H{T3k}vTmp$y@TAY!+y4(*l2+#c delta 15287 zcmcJ033OCNy8r#Emvoj+I(tGA`gSLf1QN2ZY`I}y1!PBM2?@|3F5osIjS33ND0+QX zaDg!5AWt218oZ;jI;e<<8>5agf;>hY#Syo08PxZyy7zVh==r}h=ltQM>#MJ}ufDyi zs}H^rf9lQnby|`$jDN~3MVZCIVOoCIxbMlMkEHAI`2y92UG_i56s9Pi*f^Iq;=+;MVGZKRBolD*_U6w=(?G$ z*Dk$s!Qv$gT9nn~ZN0X&<*KE2pEZ=&wqSABQMXaj)u_*%z4WpxXSQ5+)#9bf?GzV9 zEm77|+>S$WE9f!CV!(}jMe{9;R62IMX{Y{0tbxyf+AS|mQ5BU`=5t}=+NmmEi4uR* zLGCd6m+SkgQ@Q#uO^J+*U&7ehlE@zK>=ZfjF7E>+qAvzL1|afd;B$xmY5rsSsUD9; z1{FR@VwGM~^wGr;+Ie@c)3h`4MXxx@+*#r)RKV-_M1?h}G{lSbeJnn*R~<;k4Q15G za-WKKIKpgsf*@f9Eet9J=%d{htHt=5^s*98?fQ!)VfX1Ai5Oja4{4DPN*^L>kE|*S z5jE?l%hS=xT``^p=~FA71DsRYfzO?lo7n&4=rgPG*he|~@~Yw8Hs$tJ#O$7s>a1mo z$}|?zlv3rPT>W^}#K8aL)S{W8Ip|QGnmZJfy`c)fmO|86k}aq-}DnZBuJG?nST{u%n30YhRETqbs0t-wB5I~$)r z*G`Tzhs(iVH00^a>guVCulAE)F7Qd6-gyPD!C@D{F-8w9U1$ zc&v{szOI+Wk?P3Qf!kd)G~yky#6`m*H;&vwG$c|y`d_49KQ>V>9XpnWN0yD9;h>TF zJL8{ouFdt0ifouLl*Nn=#Hi#OqklT_Me46dCLN%$`m)Is%q#KTd92tH%FjVjXfF1j^!0_J{#g?txA*O;gq7d@CVDdul_LBE8%QLh3L^5Vd4SZ(S?L?FHp>w9jPO+w%s&AR|3~+N=rb*lZPsle_ z-{0~fY~s zhhD5Tkw@#y0cP=`SF7^np!IlAE0Dnca~ke3>yMem%0@Z*0khcNsQ-D%qh~Rw4^4|4 zTQdE;=0 zqscd3@4jk0MqIw?W(@y&)vXwQces!K-?wJDMlHO+8_=Izo~0kVwH$qXtG~vlYfT${ ztuI=08&&Gxu6Y=v9=t7+;^lI_(NgpG+&*xEJl!Vh#(^ctB={3m+>p&U9mC6;n{9d zcqnq;?}Rl&u8~EXOPE(q#F|9Jf+jrtdzi`?ec&U|gUDTvs6;0tf86?r3$+>Bo)hX+ z{>7xok|(dU!M>4A%-K&nSra+FBZ1hNT>YOegaHLAQwa4l9zM%azEt zM@CSj?>jD1&*YkaS{0f3 zK0;$V-?ozdF0%DF8rt(IWlGB1+$AvA4Bq~@aw z865SRf830C>iwk7K@%fGJ{!vZk5T%G&%=VC@-IG4qyam!>41X<@DmRDkOmkpIcblJ zF5+wAXaZei9F3!Si8R<4oK0H@wD8Zm(M#uLJF)y&4rL%Y@pPv`o|j9T0Po4ANoES; zgSuw%pH<4_HF{cbeBTS&-m#JF@mzKF8X zYg>Jg|F(!yXfW?6qL_qNfW=iH{FIBmC(OXd{;u3pqNrB3n0^s zgQavc^|8_;DB^m28?fO=r!_;P)QRB6o0jja@g8jeyWZdJolI>*&$w9Pou@0 z*Vj{yH7Bzy9&`S_o-&2f!AtSfMw$;@T-HdJ(h%d5Mq0~gxN%K?dc?*4nQH_FQMQBH zjlM(SK!MxR)XqAJ5X0u06Y!ja%xI|usrTh@=l8K|72Nj07sO?ff2-FW9h zDi!m%r_h(8|Myer1XUPEr%@t9_0t*jq{p&#(mz;MnWsIGA+{T2&B}P`zS&L9$^>tM zc7FzT{nbU#g?2t}4)x;W=97mnznBJPTN5OzN)am$CaI1Kyez?iFv;J&mO+`RY_8W1-skgk~njVmspyNLR7$1J*!nv4yz2*;Rq1FOW4=cpA0`OFq7pq+eW z3st*DBa)6WcD2wxqES5DO7BpkF}00e5qq?$+X(pde0tMFW$~j6=#C!dlG;|e%Vl+r zN0=I?#%o23f{swYtL^hiVc!{|$quSFKD?CPf+II}T}25_bDm0m<~lk!&^<6wYS{Ane-ZUCovlyJ5`HrCEC-tz4Lioa z?u8v=E5UZEg62(br+&BuTrF%QAX6ZX#q1f24bGZWtXdlX$uxoh_@F6?PJ43-NB&g1X z!EFBHZpscH$7J=^yh##_iLNQy%0t0!@WdTx1DJDGTTv*OYqbH)JF86%1-n~q0R3mR zWrc#OwY9MD=wcmTC>V&cz(irY!6+}7%8DHwNp+6niAeGS)_iel(1JXwYC(Rry9MQ` zxfYb8cC#St-GZ=)H z(663@ws`mUIcTsuM@|^h28K!%rBP%!VtdCE>##)$D_g`?y(+6=9Z3O{m9#l2kgqa# zh4TBPKmmVYFU=fhZwm793fZYSXHDnDbQoI9*17{dR8~f}xdRYNsj|i$$P?vicR*|h z3Z-Uis+!IBJxywyr7T&fZ`?=e?rhCJ##_Y4e?sYfY$lr;0ilU~W4x4Kl(9lvAU!|- zaUXS04@89+RBc62dHHiRpdwpP5lIYWiE?{l0IF7|>_`kit%?;RG0;=s_ap|uuQKXL z3>5N>&%yjn#YXYfb5s~kdb~O77BvGd!?*NG?dP9=j=AFTm4SHpwS2Xp*>}szX7!ep z;9;R!BzoYqX6o1fL+v35TkSKVI}@r3X=hq(01LxsHA2~otVV#n&T4}u_3mQQmfDv@ z*%MX!(kP$0s=cYY!F=H)GSnnY9V`GG#>O&5rH^Rnr4|XeOu!zsw}8t99H*8DxI(~w zwN${B0uHLO2&l3}Rb^*Wq@ce_l@pnDY_?jJi)TBENxtCf6G6j)^YPAJrs5KT8qt==b&v>3v!X2jV zh+8w$7A#AUQiO4ohpcf@bU+l@2q`WgR2$LTnj_0blvoI#jVQGc9vi`U|1XgU9ygwN zo-Sv}scM2C+mt7yp3N%`P>(`bltlzMfin!ur<B( z%LX~pcHv>9?ZV?o+f6e*JVYP6f4!Z5^d>DulAZSo62m)>&~8VzZTIjl((Y5mTnKF0 zyzL#D8Aye@5|)fJf(Q!2FXH}6IfFN@tE;y_d3!b&p-e|v zjxtrv-x5ex3yl7M$8jtc0Ym#ZF%(GUTRueklg(fGkOny_)Ks4O5duRhANUc~Bc;3X z1;Dp|M59OLZyDlEQ{#LrAx&IvLJYo4c@r#x6hfvQ3!=6m@Z~lhZo|$6I+FO4hbd#S zXjkoaI1RI1qzJ;H!)cfZsIHaRSO~v`fYY$16oz8P`~)v=`hX_$S3f3q#s6QrM8G#A z&pCwtB3Q7=I{9laQu9rC51XxG^imP5G1x(_o!KhH8wqSCJnhf?0gb zr<9X&PMX^dskTU8!dYG{CAWNbz_%T&*@j?dCuIQbywPk!;IoqffM+KI2$FU(0MJfv z%yIDisv7Rh;jMt*nGc!Wz^`CuWH3!f=DD3gF*_P4JHw-2Mtu=y%w#}7xvHI^XW4n~ z0I_+5Hz5^(+s;Ww5rc&48t0%vx=>)~yi9t9Xn!H;McVdDNv~k!FC@M8S>gYf^unpj zq!(VNO(wm41VPvdj5gQKb0q@SYH!=@Q4~@;r7MQOUTs}8dt`;8Drq7R^gMj)XLLc> zN`Ik0;+W(yJu{Hth=5~6HtZ0jKR4y^;3LFdsQlw`x ztbrpUrL6PH#6<);u*A(BpHuHJOv@weO?)7Fh$~?H2g1D&C+vZva(p6lmv$M4I|J*a ziTu-Tg%@CDVDo4L$9SEp$jy63GxKlLUbx>xTt4P&5lEU&_dbS;v+X^brrIK<< zxUex{q$W8sSC9HB(I$-4Y6IALoDpqcR6ugQGkF6qgKD@_cSJW>Qemflb+K3MSBR{q z7@j2c%S_fYRpB#avaYH!wKsG17@72%A~r4D6mgbXDEdp0<{~j~!+bfWM7woO$gzQ< zt_eBzU5tcW@}UESf=9iqd|awpy*PhJ>g@a+6`7xlGKnXDK^ft!=%G0~YE?1O98{IZ z3$a9|T5K^kN$q7p=7B>J0JbQ1y6YU@!JSJMnQ0d*Qf_w#U>Bvz{ciKv_ki0x_C4qp z$G&i}ve9jx`?k2va~~2q7+I-;(fruvf0c(zE zf*-UHNbqB<69+H(lCo2dC&CMO%u}Pt9uCCw4-O+$UGycz@$XKMFE(B*gqGv{&M$FQ zeZa!Ongni-z_nXAB#r|2`Il5o$9eWw^gMO&V_)G)s>As4E8GYDhmn8cf0~g9_hc&c z`56hn;~To0Iml}beX&1AycsyAd z>c#7x&Mdy2_-zjML!->$akKJEsr;{H@C71+&*!_HY@{hRoIbm3V{eRf%TjD;iJB?X zL<^jnpZ9k$A+}vEW{C~Q)Tn(k?KC11oLvbY=w{gv+cY=BA)u2XLdr-1I>jasFk3(0 z9>av#d>$N9I>jb*upDBGGD#qic9a@dd)S2}HzB6zvWX7#fIk+SFjtF?6)kcTKgF_# zvDW4|HV(fKcf? zk-`9^=pIdmAymTD&<0s_xn(u?Uud;~6|OGh5Zh%KGY0}ZJCtXMkY=_4?3Acj5UStH zY6I9QT+s$&m)AIEt`$woy98@8gKt>g)Hr2+ZANRC8GU6OO)_uOOsIbt@3!}Gcw)O@mMz7pV6lkuF z-p83JFug|JB$|YZ`LXlbPP4J&{&#V>+n4}C1epq+VhExvW{1@aMaAOwL;+je7FT{Y zx5cHO&FxwNTinJIB(dgro7{fM1c$s{8xZCJT|NY8I5C zHd|1VI>>@t>R=0UszWS@_=$8@m0qO|w-BZ32n#CVy)xK~F{-v=`4y_lzsq2aRe9pe z1Vsym)b4#rKm{SSM;(qWidGU*)6CY=keY5neQ*cJTQk|rNz(brey=GZGoh2UcTkgw zo~#{5P24Y=Gk%Pk$W+bRY1D$z+IOf0cy<=+S)VOjilVK>qmV3f+1~=}W`cJB%r!|} z2N0J?qHjCE9DYp}E1V>qjNH^qKuWhFYx_`>jzrd;MooGSS$h&S=__PyD{9g^$l4~< z{QRpdHaJgSFU$2#11avrt$m?ZVoc0tZi0K1o({%x9EMtNXDXe3&T2vWY2E5b4+x`j zSuKcDU0a}jB8L^TMK6z{4(_~Lq=9A=bo#t|8?y!4FJ4NB>5#`*3&HTLizS|w!*0SC zCHLpBTE8l;+B6#G#Uq;`_^9(CHP?KZQ3N`^>-U?hAKUTpCOkADOw~}4zpd);14GYpv<4_G=?BZM8 z#Cp~r??_2}AI~S$vwhT`r!}xgFl<)?JL3LRZ}~knZ)8 Wg%dhjf7k@=*iWaHn{4 z#RJW(-gtEYTS)W=zM`4cC3<{u3EA;#&Jb^+_I?gu(ZmL_b$NVW6YFn3OG?zNt#~y^ zXBc0nvCnCjf#I)-*~brN1?-PSViUE-G1_!?OsL-Jp_uU!nMx$6L=K0zG-4iDh&DXjW^^ zP{vn{W~up2=19WJ%ToBmV_6pM;Je34TE7{~uAoLf?*evX+~|M<>WL?=WB8XBup`c0g?K-5a2zYe z(~0lKv3tdXk2@!@k5IklLS$|9O_|M_67YgKcuV35k|=yZrnU2yNo))%B1$LF)<#CzS0N$@yi+086RJPuiZGfNk5 zX7IKxK;^5fSARa?)bL(29{HpQA`Vo=`}uR<0X}sLds;k?v;kA^oWf4h~v#xDu6 ztZX3;2lmkD&Me}jRoqn#kiJiH`L46X$PvwOW0-f0KahwQ{h&Aw}hqOiI%ZrDLaN=G8q4L zHT%FNSa9t!HUOiHWo(S2_aXCX^hvYWE(_=y8|Ed={G9{t98goVokrOT*33xbSKb6q zq495SVl~F&tJ%K9gthhfa>snn`+)Hq&MsmCm0`bgHBPK&2VKcPxlEMm2*Aqr8@o2L zB4?kI^~l4_(Gql-{wU8w!#ztp7Hu4 zY;deo!9Tu!2V2GKcCe|&7dzOE6tm>Yma;_)=J40IvOc`&kL-leJ;F{AANdDXVBBG_ zWCtDP9nY}pKykXFBx8zu9Eu`-C-ZrVqNJhBwCntvXV^ejWvZg!QNptR8ATj?J@OJ+KOx~m@VI}9B0aim4A4pP^QRrji#{vdz%IBD% zvI~BKh2IZ+?=JZH7Jf7EY8U(hi4QBv!&pGSN!%*7e{|Z>>fXxvbFFA$vm8&68u@k#N2P}421iaX-jlajjzXbxs zZf*SUEc|whFdP3E@M7VWz?XOFzsJQ&aas5%Bj6b0xucbo%f(inF3;uP$VuwFrypXwVDi>gObd9pyp2uEzJNg%*eR?YRFDUvN1H=L$G>nuD zCjMIs-vE3?7yNe?eic@!>VoeJ4vBg8053RcFYL4WD+w`+7A#)4VDUT$J5#BAGsc+o z96K1p_r1(|@ihmT5AQuCykEc-Cj7I2D^0lZWx!P?e3gK!1>D0VtL^qmc;j>J-MNxrnYT%WlddG>+H7Kb87136e+E9=2XwAuCJ+TC@-JeQc+dk z$dg}YDt}@>i{lR-Vm^MwAy&fw3Wzm!ZA*Uzn7&;wDRXP98)jG3l+T@AT`^~NeOf!vZ*H{US;JaUAi`mHQ1X-#4^cyUe zk9?h7%toEFaxNP^%p`r+o1nkP8_dtfjOv0}{07TsV`ZOI9zMV_`K~uu9=qU1-XS)O znHRHhU7K%v6V2mCMyIHCPMF+p5+DCM^Yf;+L5KecD`6K->%ybU-Up5M9>Mk|@-0V@ z%}lx~I^4rk{(>z|=8OKq2GSJ%*k4#1n>vX<_BI6C^cE|2PCIY<+~hgcbL(2$s>-Wt zt6OVkx3o^@kG{<=NN#DFQ$4%7wXUkIc5Z81dFu?m@hH2N-}g3_zDRVLi8F~nrOcgM z+tAilUSC_;RyDV(ruvfUe9vpF2j6yrA;Hzk@D6g%n zYH6EO)iS4YZk18-F01pnD(Wh(zD9O4R-9m~D7mJsqNQ$bTYYU+eMN0$W$krBiX-^U zlWee~w*Gpa^gLMg{7H5orK-NRykTx@T|;$!TTAtvs^!g5zN8s1{+;zBl8lxTPUiQ2 z#Cp0`()s-0aUbIsovVJKC0te6);ecyTX{ugOGSA@L(MG|Kl`es^Dny+ze;Uga_jlO pPhEZ9&r{c&^Xt^x&i!%f?dSbA6+cEbf12vV&sCT3B_Ff5{}&<^>Qev! diff --git a/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm b/polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.wasm index e60684711d07292dd5bd9617e7eb32aff169bfd3..08b69ae04f0a291b0451ab5aafe160d67fa5b9b4 100755 GIT binary patch delta 15815 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 H^4b3aLz3v^ delta 16279 zcmch833yaR*7iMhJKfp4vyh~dKyG&uk^q5(KoVdSIv50%RYXK&3yU;}vMFu^GzbDB zdci^oiw+LXh=6qPf}#V8g0i^bD1rzhu7e0OIO-?j_g39|JKey1|Nnf?|NP05+*9Y& za_ZFCs&3uG`xAdXkhnD9cGTlX8Ko$rSbaUser&)m6suoD_u~IsRGk`Q|1hR7MTw1z z*WIi||5zm^3FR0iCV|DU7(7{wgC!}75|`vwP*xNN{>Q~738JFJn?JFN;&H^#9YhqP zlER#^R8N69ujn(_xcd3znK)(QjESQsPn~s7&TpagyIi0 zCCsJw7;|CL`E&3S8mivrq8<8M@dxq$u-~V@l#oiNLT@LGP}$-Qp%V9|G)dT#*|=fO z9L4hj8YxPGTM2A1%b}KqA%}i@(SH5Cl6|2GZBG#G2=yuTiN~b&E!n_Hh>{g;9-ME{kFqER3==x3T5a0dNqB~vsNj-h-}323 zRP2U|3My(2QG*2-YLqH}Y}9vknZ&+WskiT{G1MQ>^-J2!AL~jj_^Hm6spnkj(WiAw zr_Fl%TCcvgTZT!^=iRC)PE!9RsiSM_T!}FW8uOT~_4$A3hDPo{w*J{4`rBP5R>>}t z^zm2tKwWUfc$?zwO38Mg?LZn`o2^f*>ElXFZtjz>>_%?=Z&&)!Xk<@n9m?xoMd7-O z^z%JZ<&f3%W~g_-*-TnxRa(?DOD;!+(xIl%++Jx;+7nuS-SaWD zHxwB3G0|Hg@8Ec*FB+1ecNsE>-VQAuqN}t|*M@!MS}YdNvp;lx*aDVtKn(A5Y2-Pm zKYGiD^qO8b;v~JR_a6BTZPm+1RY1SSjT%Grp1yZh_Nx_r7=M*#`C_OIA$=o^Q5_041RER7tsHAeq- z>~%I_z_|4}AIgR-u$cuthb-6}^CLZV{L{IA6F9#|a}7@NgPpxf&?8a4q(H15n2@0- z3@_Awzx7Ui&VY6z|-`dH7OJSypvh`|o)ODDet{EfGb4&(R6 z20e%MH*Y%)`)!)Cm*iZt^(i-D5_gofT93sGPd2dSxrowzo=-y;?wCe&Bs6u}y$(96 ze}Cs7`b6(>*PZlP$hd0<(b3S1yWgeE&rBYQ*-|*v1ff)7>WB4V_m=pMNSa!rDt=cD z8)VUiI52bYc0`{#EnVMs@8fy)OhEG-wq_MkFEsJKR|WS)v&-1J?fTh+xjgqC=8^yE z8{o&974h7b$kMt{WNAlK>3o#Rp4uK+b8%G7qedj{TvX{R{lY321`oel6YOyqZ`J8O}G_-jRyznu7+uZMHul~mecF~8S zaSygp>9x?(hq4LA^!$7;Io}psB}S(DQca`vqSM{rPC&nXu|Y%@&PBY2@N( zU^48Hj-o>6CC|2zy6znA^Xil+wa%d87-F4j}O<%pf%RspU>O5Mob%M07Cp$um_ktf@&) zc`l9ZZqi#n*Nt8Zjd||0n!Zf<0xey0c;Lw7GA(P;$8IQ2TPF#rni?jY)7Nac*?np= zs)b!#qaOD{OK(Gzex2Ne8Ug%zHs~i_$kd0t;9;j;6bd?YzaWJhH${~`dQ>!P7gm?X zC~8Agsqw|gei~%wo*hw~t=p`x-OxtQe%-C_ul8txcbAIpOT*nCm0iG0+k$E`F#!rjAkS@zwnS-;dd?;f!gjk&YtyY2V?8vrHVH9WF4^%- zg{}S%T9v=Km+Eecn)d$Ctk8#++Jr`JZDc9o&RGu(Ae1p_+nZQ_{lo2}OuY;BemRHO z$(O-oPH4_6-JE9j;0=AW>omHOnMCOD8|Q3TKm5k9&=qf;WwEacNd-=B4OPC49?m!F z*T0j`8dmAE-Z_e{Z`d~^Go09%HAR35#CvvyUf(y9=uN%)z*cI|PanvO$bd2qZfy-I zLIYW#IEXX^$&N23(UA~njEba9TZL5F{;eVRy8#z;ci`VPI@phmIvw$+{bJ`aBGVDs z%dd^0$|DIFGgNc*EYUo@)3J&4kiPm@xv+uvkEOLX7c&M?%w9~>4$?Gd1V)el{PK2C z`}xi3W*6`Q;Rfit>GPp%-YPx$xIgWYRhX8@uGB!h-$Ixf|fqWW4pBX3eslrWf8Z9d5V~BYTKi!GGv2#}>%B6ruRa0ADTS+h4 zcx1a*0UlUIZ`r8QYC=LOs&2GUNR%^qw=UEkMk1VPeA|saaiZ{g4I!Nsjl8_JCwWae@?pNBC;fvq8x2>%5dr&bE#@Kn%jUcn zwL*=TdeNWE`Wbxs)pQ0hIB&u4?o9)2__zsU%nZFxHxEDEn_`VoedrMy8J!60w|iMs0>7XCdob0Bv6642 zR?TBE%LzT%$h+T0-|F|g(Z}AQ!I$#(H_{B#6?1JO#qb?B(nxyC$Q?=>8Pt2Oz9NXCeUUuDA1V$I~%tGWJfOp0?Sc>*KV-z`k%7 z(Tg0U0^{pR^otAiPE4mKt^SZ~#2Cx&q5_7#w%<)Z(iUUWJv0nOxw{0J=ig7SxuZoPC9Q2|-uCN?oD$(_f`2%ynwD z=(vl%YePxOzob}mJ@%$yzv16W@2iK)kC zRjDGGS?dl4JV6}a08Ex(N)!zzGw~J;V46+SSc$qexk_E@)>5=M3!A3JTaZJGwQB|z zB#L~=@34At2a6T{K@7|0OTMBwuUliKN+{WvE}l)vz7`tmplnU{rSZ*QQD$6*KtGf0 z%jEBUMLu%#0>q>$e^g9LY3Uu$ARD!XO zV|LXR8<;adSC~aXD+~Iw1&g2o%!#5E2mQGg4PeXqD54hhx3Y);^P*^3LBAFu3Na3Z z?F&oHWDC;qhegMvXx&xn@nkJd^I6@+Ykmug)wEU?m=}gxYPl9JN6Y4|zM`3d}zI=_9D}QqP3OIdBBL`$#v%+M+eRWXF ziRvy13W$~^Y_Zc<2*sg=P9N5yRC(CxYbl-!oIXplHE%%EynOSw)S*?D<`uf)x>#4d zfxNy+#r(vV)S|uCJhEvawiSr=i=tum@_3K$s8tJJcoF@Ytp^&P{vBOe?iJiX&9lT4 zY7SMCY7Vt3QH*3?Yk~i3vJZ0WKx>nIMf~sIQCmyj@#rem{)L*XhqMg%EzgW;f!}}s z-8J=v248}fq~&V`HJ*nWYP5$MAj%@GSk%BN!2gxn!vt-$&j`;thLc9ET~B9 zWI-8PXA5#^l_peg8qor0mHIQZTKWmoprmh=24b0qTv8y)f>tMT9f2se5pwN-&}>9o zF*hKxY(zT?;js}^%1?Zcocy@)>-V&nrKD+zf_rl@vE*L9|L@dl*w5HSq68ze#)dS2 zg56|m;rJm@u$&w%9B#yXgoF4wUUO(!R@)fOb^%T;hkMRa0kz_t&r)w;-<_3B(sDW| ze@ynll1i0lWgzKHFDLs7`RcP2O!bES-`*I(gqCJx{}Vft8?#Eta*UhtvH^tbCFB2(365!=?oGiUp0a`%ir4b;Of{+!!at0iIa{O_2 zTM@CfEG=%5>4A|!1O=28Q2XLwJsT_isS`Zr8$UZ)43XEk;9~74EQm|EmS%zntmcQPYq7@jq$!r`FB*^odI;x zmp8dtPZu^4a}+I&UvOi+(s+9htEPND!NcnC*ymxsa+%^-wpraACyUgigYxHOk+PI1&%=$!%$@Fir6faYvl- z;};0$B+VJ-RaXAXUKMg_!J)HB5hiVTRcV)N?IM26owoZlyiY+q|1E`vkU zoa@DeOrcgojl*0Dqbh4wV1Ugt5Hw-LRy%+q!?w%>G-1OQ4WON{hRxY0rEgWQM|}u2 z!gwWLSj3`cg^RFf%vUU3Yth^-70yigGd1B;WXi8;a)V%I{4SX~n@eqa0CTCcv?5Wz ze2VBO*Uay8%$3cKOzSa$;>ffflPy77k4C17K`?EstX`@dgxFS-+{s+~c(PzsX8Gdj z=4II|qdqIV^Y(_#%oR>rHMvOr>1};-sisa596;9d(?U#E`5$yLS@Dq%+;EQrtJpVX>c_@L; zZp$+Ht2r!|uQw6>1mb&vxXVPeYRfWsZZ6BA_Loo2ZC?p|J_nmS5{*UTVk3`B*uX8r;X6lpk?A z0R4d9i|`ddV3Ux?clz1Q=p{Fw^-L9;a?`vTu>oX3tsS45&x)~+d@7%P1)k;>V316{ zvVe`IJpNk&MlRyNS77@B;AdO2p=f_i z5$lQeON!WZG({TUDODT=m>kTBm6c14-o@-yW+m{BfU{Q;nJ&pE6ZpqjSDCcqNab?5 z`+rK=3q;DE&%Z2X*I-&@?QKzG%NaH!7TD>M&Nh#aZ7)TAvb_}bbsbP$?6!Z#Ml@`f zEN}(^1U{(LnA1U|_stU*+i56Fv-AZ5Q9X|zDU;H#DrY_Oo24(5qzuvz3qv5FsinrM za)vjf8T@QVxey5zc;xZI3id1nxvxU9S6;|69Po|pc;8N98H@>?*s@4=Hmeu0BM_3E zR+ZS06!8ZtquIgLy=ZoTknDU@$%=?H!&A*pusCG8@@O}M|5sO5>PFGseCV6OE4#5) z_2x`)qH3F;pQ2_7zNNQhG|C~fL`c2Vf=&{0t7Cj+v;e zU_E%W&(2I7rqx-V`k9=H&LH;6X62XC#dL>K8Q4(jvW{=;XB=SSEbOt4Vxb!nhK7L(*wXT*gj+DS++>y#M zhkXQKwh1l)m}|1S6d+E21g|Rq=J3A+SkVpA>BvdF4Wx84va|~&=~!fGJ4(`($kK}_ zN#7w$e@01q3t4&^r99rchF#TCs<#~P43OeH+nN_j?Tq;~ES|)B94G_=ne=Oy9QVkb zu5dsIF3kr%G8V;HZIJy%QlO3^a};gDhd`!NgW_It8q_`P?=CrhF)6SHoY~3lE|*2| z{#UUF@RH+$t5_vzJg$}%;?bd&4Yl>gSW?UOB+w~i$Uqjy@FsNB^(=6im;KqT1E<%B zceK_eU_Yx-2FlxO?136(P*Ntw}-QDpLdJW$PJims!hp{$khXfXHACkf^dJpmIhOxWo7~egNy%-mM5zS}c%pPYO z*Yecitd#wIEe{N5-SKuASLJUJFN0Cc;lB=N1tzY>7;_7ISfxY!)F|+|!^jxTu48!N zTUW;d)+K7fd-H>QQyn`%ukriGvK^x7N|wg^j$?n1+xEOA1*3XA8_DR9vEo*Sd(}Jn zuM^pIu9N1SH%{Y_YweuO+89fM>>gqp*9%tK^V4@AC+|O*#j;~7`Aw7AH7@IhSGYy# zMR&lG1I?3l-o}>DUSs)f3B`)v}eo=*3nvp_8g35@K0y3 z_R*MrGucc`V)sloiA7uzsh-91*^`!-7R_R55WDzdf%fzDlT3e93`uM?!>xHYf?#4-ah!U*lwp zxAXS*;6QjMA8`+>hzs8k=TF_ke6*hLxChzZM((+nb+tzueJ|@67iO3@-V4)PD=OCd zmFBB0V#F#H7d2~Sj8ViRHt?kAsgR$!7xEi>AIrksxBKt2C*tLY?nCnT3a`GO%}bW| zS$rz24;RM|@_qNS&t0zyF?sewddTs27+=h0&xp$<56!_=1J6h1!Zc|&Z~Y*!^7ie0rPVc{-+1o5PF0E_8>A;3su&@2B7`i2F&&iV@Ct?isVWK|?p^h>JTXqe@MYB`7nyI*9^1aLFg!0H+^7 zDuErw{4H!gqu056D_f1n#;vT@2<%`-lhYQ9FKY0vs`-L;qfxex-OemZMg*nF*m8iK zh{-bB#57Yh)d%a}Z9M-W>*l!Tr0g>C&bN(;X%0=YPGskYEKGBq#oLUsPuLbm>266v ziX3ikauC~$Nmy9Hl)#+Wgd>LgGj>%RS5L7HoPEcJ@tNPUp+<-Au!VO`pH|ml^29O5 zfUj`+V+{Wq3m2P;zUT+GK1`nCGRfm?vT^Mh)`8Ixe(yio{Cc~W8xj?zJF2v` zstrg|6hGk67&IPFyF3BqWR&NCo`+`&CebRQoQ^VXmMM0>Yfw-0+Xa7;JIo{>u!XM= z6YK^B=)DIj{#E zB|%Z1#Q+r|$XEV47_{bTZ@tCtK!JMh;4e0^C& zgH0B}1I-egceObG5Ci6-Y%Aj1SV%0ZvKe?Wv&T@cC7yOWd&V|>J!sfJgzIkvEXIXI z>!k`0!+=7Chu}{r$$KaZDR>|m!H6x=k+6(BlhWcr%PPl@t0=D+SKGCjmcVzTHlM4a?<@z}{UMSz85p{P z&vvL&>B?nl4Rtr3PgUcHdhjz2^%fQw%(X1Fntv9fCZvt2C@ULZSJkn+y0TMs#ki{4 znr3P)zuBn{U1M7OIB~Bp?pEII-hRh9=CcY4Kus?-i@wq=D)jfv2{4F_o%Dr7EzkQ7o~tQ zLZBA&l2pJWdAC&c_P9|iq!7xwm_j&|rUpIbS65b4msfV|Sjlk(ebL3AqA$MWOLTmC-uxl@66yfnI@R4iZCq#GP^f>::record_block_hash(header) + >::record_block_hash(header); } } diff --git a/substrate/runtime/system/src/lib.rs b/substrate/runtime/system/src/lib.rs index c7252a0acd38a..1de71cc3e6c02 100644 --- a/substrate/runtime/system/src/lib.rs +++ b/substrate/runtime/system/src/lib.rs @@ -108,23 +108,27 @@ impl Module { } /// Records a particular block number and hash combination. - pub fn record_block_hash>(header: &H) { + pub fn record_block_hash>(header: &H) { // store the header hash in storage; we can't do it before otherwise there would be a // cyclic dependency. - >::insert(header.number(), &T::Hashing::hash_of(header)); + let h = T::Hashing::hash_of(header); + >::insert(header.number(), &h); + + Self::initialise(&(*header.number() + One::one()), &h, &Default::default()); } /// Initializes the state following the determination of the genesis block. - pub fn initialise_genesis_state>(header: &H) { + pub fn initialise_genesis_state>(header: &H) { Self::record_block_hash(header); } /// Calculate the current block's random seed. fn calculate_random() -> T::Hash { + assert!(Self::block_number() > Zero::zero(), "Block number may never be zero"); (0..81) .scan( - { let mut n = Self::block_number().clone(); n -= T::BlockNumber::one(); n }, - |c, _| { if *c > T::BlockNumber::zero() { *c -= T::BlockNumber::one() }; Some(c.clone()) + Self::block_number() - One::one(), + |c, _| { if *c > Zero::zero() { *c -= One::one() }; Some(*c) }) .map(Self::block_hash) .triplet_mix() diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index c9da182130b78148ba2a8210612f5a6b2a5c3007..2f8ace8b215fc2ffacdc53f9297fccd0043cb816 100644 GIT binary patch delta 97 zcmdm2zps9S1wZ4N$(H=ZK$6i|c=G}NxlD{_HpdAqQeZr@n9&%>0gH>8@-s0mpR8)W uo^ki)tLAqZ<%)AMlT-C`^HcPSfXt-i{GwF-qSWHjoD!e_!{!T??^prS_9P(y delta 97 zcmdm2zps9S1wZ4C$(H=ZK$6i|c=G}NxlD{ZHpdAqQefP%n9&%>0gH>8@-s2+oUCfT wo^ko+tLAqZ<%&{^OLI!}ii#O>GLw??i&FKAb25`t^>g!6fP$MZSiWNg0JIPzy8r+H diff --git a/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm b/substrate/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.wasm index f648f7d54edd94cc10be5d6909d6a5c2fad254c7..2f94b9a9c82efae416d7a354f7b6b2cf7becccad 100755 GIT binary patch delta 100 zcmZ3|&A6nSaYMWylt@%-ePl?QLZ>AGdWd1H$O$M2*^xI&M!*UFG?*g%_#v2Fl=6L_mvF*g=8j- delta 100 zcmZ3|&A6nSaYMWylv4C-ePl?QLZSpxHP9kuc(+ICo?HIzbI9|I43hXRX;aB1t_?Az1>$f0A?;GCIA2c diff --git a/update-genesis.sh b/update-genesis.sh new file mode 100755 index 0000000000000..07632668c49b0 --- /dev/null +++ b/update-genesis.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +cp polkadot/runtime/wasm/target/wasm32-unknown-unknown/release/polkadot_runtime.compact.wasm polkadot/runtime/wasm/genesis.wasm From a765a858808f50f4370d14261204ec3903ffd1d4 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Fri, 6 Apr 2018 14:49:23 +0200 Subject: [PATCH 11/18] some more minor fixes --- Cargo.lock | 1 + polkadot/api/Cargo.toml | 1 + polkadot/api/src/lib.rs | 7 ++++++- polkadot/consensus/src/lib.rs | 13 ++++++++++++- polkadot/transaction-pool/src/lib.rs | 6 +++--- substrate/runtime/executive/src/lib.rs | 15 ++++++++++----- 6 files changed, 33 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 693a032721c20..8c5394756e353 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1141,6 +1141,7 @@ dependencies = [ "substrate-executor 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-runtime-executive 0.1.0", "substrate-runtime-io 0.1.0", "substrate-state-machine 0.1.0", ] diff --git a/polkadot/api/Cargo.toml b/polkadot/api/Cargo.toml index 13c19b7570f19..860536ac95913 100644 --- a/polkadot/api/Cargo.toml +++ b/polkadot/api/Cargo.toml @@ -10,6 +10,7 @@ polkadot-runtime = { path = "../runtime" } polkadot-primitives = { path = "../primitives" } substrate-codec = { path = "../../substrate/codec" } substrate-runtime-io = { path = "../../substrate/runtime-io" } +substrate-runtime-executive = { path = "../../substrate/runtime/executive" } substrate-client = { path = "../../substrate/client" } substrate-primitives = { path = "../../substrate/primitives" } substrate-executor = { path = "../../substrate/executor" } diff --git a/polkadot/api/src/lib.rs b/polkadot/api/src/lib.rs index 848bf0c72c418..1459c4a4d19f3 100644 --- a/polkadot/api/src/lib.rs +++ b/polkadot/api/src/lib.rs @@ -24,6 +24,7 @@ extern crate substrate_codec as codec; extern crate substrate_runtime_io as runtime_io; extern crate substrate_client as client; extern crate substrate_executor as substrate_executor; +extern crate substrate_runtime_executive; extern crate substrate_primitives; extern crate substrate_state_machine as state_machine; @@ -323,16 +324,19 @@ impl BlockBuilder for ClientBlockBuilder } fn bake(mut self) -> Block { + use substrate_runtime_executive::extrinsics_root; + let mut ext = state_machine::Ext { overlay: &mut self.changes, backend: &self.state, }; - let final_header = ::substrate_executor::with_native_environment( + let mut final_header = ::substrate_executor::with_native_environment( &mut ext, move || runtime::Executive::finalise_block() ).expect("all inherent extrinsics pushed; all other extrinsics executed correctly; qed"); + final_header.extrinsics_root = extrinsics_root::(&self.extrinsics); Block { header: final_header, extrinsics: self.extrinsics, @@ -404,6 +408,7 @@ mod tests { let block = block_builder.bake(); assert_eq!(block.header.number, 1); + assert!(block.header.extrinsics_root != Default::default()); } #[test] diff --git a/polkadot/consensus/src/lib.rs b/polkadot/consensus/src/lib.rs index 3ba08bc84c599..98bf3a174088a 100644 --- a/polkadot/consensus/src/lib.rs +++ b/polkadot/consensus/src/lib.rs @@ -576,7 +576,18 @@ impl bft::Proposer for Proposer { // TODO: certain kinds of errors here should lead to a misbehavior report. fn evaluate(&self, proposal: &SubstrateBlock) -> Result { - evaluate_proposal(proposal, &*self.client, current_timestamp(), &self.parent_hash, &self.parent_id) + match evaluate_proposal(proposal, &*self.client, current_timestamp(), &self.parent_hash, &self.parent_id) { + Ok(true) => Ok(true), + Err(e) => match e.kind() { + ErrorKind::PolkadotApi(polkadot_api::ErrorKind::Executor(_)) => Ok(false), + ErrorKind::ProposalNotForPolkadot => Ok(false), + ErrorKind::TimestampInFuture => Ok(false), + ErrorKind::WrongParentHash => Ok(false), + ErrorKind::ProposalTooLarge => Ok(false), + ErrorKind::PolkadotApi(_) => Err(e), + ErrorKind::Bft(_) => Err(e), + } + } } fn import_misbehavior(&self, misbehavior: Vec<(AuthorityId, bft::Misbehavior)>) { diff --git a/polkadot/transaction-pool/src/lib.rs b/polkadot/transaction-pool/src/lib.rs index 40b793ceb7925..f2473053dcac0 100644 --- a/polkadot/transaction-pool/src/lib.rs +++ b/polkadot/transaction-pool/src/lib.rs @@ -63,10 +63,10 @@ impl PolkadotBlock { return Err(unchecked); } match unchecked.extrinsics[0].extrinsic.function { - Call::Timestamp(TimestampCall::set(_)) => return Err(unchecked), - _ => {} + Call::Timestamp(TimestampCall::set(_)) => {}, + _ => return Err(unchecked), } - + // any further checks... Ok(PolkadotBlock { block: unchecked, location: None }) } diff --git a/substrate/runtime/executive/src/lib.rs b/substrate/runtime/executive/src/lib.rs index 434b36a2dc4c2..74a0f0415cb00 100644 --- a/substrate/runtime/executive/src/lib.rs +++ b/substrate/runtime/executive/src/lib.rs @@ -50,6 +50,13 @@ use runtime_support::StorageValue; use primitives::traits::{self, Header, Zero, One, Checkable, Applyable, CheckEqual, Executable, MakePayment}; use codec::Slicable; +/// Compute the extrinsics root of a list of extrinsics. +pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { + let xts = extrinsics.iter().map(Slicable::encode).collect::>(); + let xts = xts.iter().map(Vec::as_slice).collect::>(); + H::enumerated_trie_root(&xts) +} + pub struct Executive< System, Block, @@ -82,11 +89,9 @@ impl< ); // check transaction trie root represents the transactions. - let txs = block.extrinsics().iter().map(Slicable::encode).collect::>(); - let txs = txs.iter().map(Vec::as_slice).collect::>(); - let txs_root = System::Hashing::enumerated_trie_root(&txs); - header.extrinsics_root().check_equal(&txs_root); - assert!(header.extrinsics_root() == &txs_root, "Transaction trie root must be valid."); + let xts_root = extrinsics_root::(&block.extrinsics()); + header.extrinsics_root().check_equal(&xts_root); + assert!(header.extrinsics_root() == &xts_root, "Transaction trie root must be valid."); } /// Actually execute all transitioning for `block`. From 2c52c886311b71c78f1c21d683a8143cbd237705 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Fri, 6 Apr 2018 14:57:51 +0200 Subject: [PATCH 12/18] fix compilation --- polkadot/consensus/src/lib.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/polkadot/consensus/src/lib.rs b/polkadot/consensus/src/lib.rs index 98bf3a174088a..94b74745dfa5f 100644 --- a/polkadot/consensus/src/lib.rs +++ b/polkadot/consensus/src/lib.rs @@ -577,15 +577,14 @@ impl bft::Proposer for Proposer { // TODO: certain kinds of errors here should lead to a misbehavior report. fn evaluate(&self, proposal: &SubstrateBlock) -> Result { match evaluate_proposal(proposal, &*self.client, current_timestamp(), &self.parent_hash, &self.parent_id) { - Ok(true) => Ok(true), - Err(e) => match e.kind() { + Ok(x) => Ok(x), + Err(e) => match *e.kind() { ErrorKind::PolkadotApi(polkadot_api::ErrorKind::Executor(_)) => Ok(false), ErrorKind::ProposalNotForPolkadot => Ok(false), ErrorKind::TimestampInFuture => Ok(false), - ErrorKind::WrongParentHash => Ok(false), - ErrorKind::ProposalTooLarge => Ok(false), - ErrorKind::PolkadotApi(_) => Err(e), - ErrorKind::Bft(_) => Err(e), + ErrorKind::WrongParentHash(_, _) => Ok(false), + ErrorKind::ProposalTooLarge(_) => Ok(false), + _ => Err(e), } } } From a4a1d9fd673e44d7864b40c2a6968d864bbb0d66 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Fri, 6 Apr 2018 15:09:00 +0200 Subject: [PATCH 13/18] more consistent formatting --- polkadot/consensus/src/service.rs | 15 ++++++++------- substrate/bft/src/lib.rs | 4 +++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index 837f689596c55..a21f0826da016 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -231,11 +231,12 @@ fn start_bft( client: &bft::Authorities, network: Arc, bft_service: &BftService, - messages: SharedMessageCollection) - where F: bft::ProposerFactory + 'static, - C: bft::BlockImport + bft::Authorities + 'static, - ::Error: ::std::fmt::Debug, - <::Proposer as bft::Proposer>::Error: Into, + messages: SharedMessageCollection +) where + F: bft::ProposerFactory + 'static, + C: bft::BlockImport + bft::Authorities + 'static, + ::Error: ::std::fmt::Debug, + ::Error: ::std::fmt::Display + Into, { let hash = header.blake2_256().into(); let authorities = match client.authorities(&BlockId::Hash(hash)) { @@ -260,8 +261,8 @@ impl Service { client: Arc, network: Arc, transaction_pool: Arc>, - key: ed25519::Pair) - -> Service + key: ed25519::Pair + ) -> Service where C: BlockchainEvents + ChainHead + bft::BlockImport + bft::Authorities + PolkadotApi + Send + Sync + 'static { let thread = thread::spawn(move || { diff --git a/substrate/bft/src/lib.rs b/substrate/bft/src/lib.rs index cf577b22495a3..9928ca2ce5b1c 100644 --- a/substrate/bft/src/lib.rs +++ b/substrate/bft/src/lib.rs @@ -235,6 +235,7 @@ pub struct BftFuture where impl Future for BftFuture where P: Proposer, + P::Error: ::std::fmt::Display, I: BlockImport, InStream: Stream, OutSink: Sink, @@ -254,7 +255,7 @@ impl Future for BftFuture wher } // TODO: handle this error, at least by logging. - let committed = try_ready!(self.inner.poll().map_err(|_| ())); + let committed = try_ready!(self.inner.poll().map_err(|e| println!("Error in BFT: {}", e))); // If we didn't see the proposal (very unlikely), // we will get the block from the network later. @@ -312,6 +313,7 @@ pub struct BftService { impl BftService where P: ProposerFactory, + ::Error: ::std::fmt::Display, I: BlockImport + Authorities, { From c570ceb4a600c852e293dacd4458d7aca43efc7a Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Fri, 6 Apr 2018 15:26:46 +0200 Subject: [PATCH 14/18] make bft input stream never conclude --- polkadot/consensus/src/service.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index a21f0826da016..62d2b55e7291c 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -111,7 +111,7 @@ impl Stream for Messages { match self.network_stream.poll() { Err(_) => Err(bft::InputStreamConcluded.into()), Ok(Async::NotReady) => Ok(Async::NotReady), - Ok(Async::Ready(None)) => Ok(Async::Ready(None)), + Ok(Async::Ready(None)) => Ok(Async::NotReady), // the input stream for agreements is never meant to logically end. Ok(Async::Ready(Some(message))) => { if message.parent_hash == self.parent_hash { match process_message(message, &self.authorities) { From 32a33c586e37273a5aa52c29a19c9dfe2b711b20 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 6 Apr 2018 15:41:55 +0200 Subject: [PATCH 15/18] Minor fixes --- polkadot/consensus/src/service.rs | 7 +++++-- substrate/bft/src/lib.rs | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index 837f689596c55..97383ba64ac65 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -39,7 +39,7 @@ use ed25519; use super::{TableRouter, SharedTable, ProposerFactory}; use error; -const TIMER_DELAY_MS: u64 = 5000; +const TIMER_DELAY_MS: u64 = 15000; const TIMER_INTERVAL_MS: u64 = 500; const MESSAGE_LIFETIME_SEC: u64 = 10; @@ -111,7 +111,7 @@ impl Stream for Messages { match self.network_stream.poll() { Err(_) => Err(bft::InputStreamConcluded.into()), Ok(Async::NotReady) => Ok(Async::NotReady), - Ok(Async::Ready(None)) => Ok(Async::Ready(None)), + Ok(Async::Ready(None)) => Ok(Async::NotReady), Ok(Async::Ready(Some(message))) => { if message.parent_hash == self.parent_hash { match process_message(message, &self.authorities) { @@ -238,6 +238,9 @@ fn start_bft( <::Proposer as bft::Proposer>::Error: Into, { let hash = header.blake2_256().into(); + if bft_service.live_agreement().map_or(false, |h| h == hash) { + return; + } let authorities = match client.authorities(&BlockId::Hash(hash)) { Ok(authorities) => authorities, Err(e) => { diff --git a/substrate/bft/src/lib.rs b/substrate/bft/src/lib.rs index cf577b22495a3..46554fa3c5852 100644 --- a/substrate/bft/src/lib.rs +++ b/substrate/bft/src/lib.rs @@ -398,6 +398,12 @@ impl BftService pub fn cancel_agreement(&self) { self.live_agreement.lock().take(); } + + /// Get current agreement parent hash if any. + pub fn live_agreement(&self) -> Option { + self.live_agreement.lock().as_ref().map(|&(h, _)| h.clone()) + } + } /// Given a total number of authorities, yield the maximum faulty that would be allowed. From aadca8d1509722f436016e5acd2b8a3f68b00f30 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Fri, 6 Apr 2018 16:17:51 +0200 Subject: [PATCH 16/18] add timestamp module to executive --- polkadot/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polkadot/runtime/src/lib.rs b/polkadot/runtime/src/lib.rs index 11c21ac079b80..a75fadd4109d2 100644 --- a/polkadot/runtime/src/lib.rs +++ b/polkadot/runtime/src/lib.rs @@ -146,7 +146,7 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. pub type Executive = executive::Executive; + (((((((), Parachains), Council), Democracy), Staking), Session), Timestamp)>; impl_outer_config! { pub struct GenesisConfig for Concrete { From a0afe794a70d80c0c59e83bebf2295cd3fbd4e72 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Fri, 6 Apr 2018 16:32:35 +0200 Subject: [PATCH 17/18] more cleanups and logging --- Cargo.lock | 1 + polkadot/consensus/src/lib.rs | 3 +++ polkadot/service/Cargo.toml | 1 - polkadot/service/src/lib.rs | 2 -- substrate/bft/Cargo.toml | 1 + substrate/bft/src/lib.rs | 10 +++++++++- 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c5394756e353..c0f64efb0c327 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1690,6 +1690,7 @@ dependencies = [ "ed25519 0.1.0", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-codec 0.1.0", "substrate-executor 0.1.0", diff --git a/polkadot/consensus/src/lib.rs b/polkadot/consensus/src/lib.rs index 94b74745dfa5f..d6f9398486141 100644 --- a/polkadot/consensus/src/lib.rs +++ b/polkadot/consensus/src/lib.rs @@ -531,6 +531,8 @@ impl bft::Proposer for Proposer { type Evaluate = Result; fn propose(&self) -> Result { + debug!(target: "bft", "proposing block on top of parent ({}, {:?})", self.parent_number, self.parent_hash); + // TODO: handle case when current timestamp behind that in state. let mut block_builder = self.client.build_block( &self.parent_id, @@ -576,6 +578,7 @@ impl bft::Proposer for Proposer { // TODO: certain kinds of errors here should lead to a misbehavior report. fn evaluate(&self, proposal: &SubstrateBlock) -> Result { + debug!(target: "bft", "evaluating block on top of parent ({}, {:?})", self.parent_number, self.parent_hash); match evaluate_proposal(proposal, &*self.client, current_timestamp(), &self.parent_hash, &self.parent_id) { Ok(x) => Ok(x), Err(e) => match *e.kind() { diff --git a/polkadot/service/Cargo.toml b/polkadot/service/Cargo.toml index f54a84fbc7f93..f071d9ffc4d83 100644 --- a/polkadot/service/Cargo.toml +++ b/polkadot/service/Cargo.toml @@ -7,7 +7,6 @@ authors = ["Parity Technologies "] futures = "0.1.17" parking_lot = "0.4" tokio-timer = "0.1.2" -hex-literal = "0.1" error-chain = "0.11" log = "0.4" tokio-core = "0.1.12" diff --git a/polkadot/service/src/lib.rs b/polkadot/service/src/lib.rs index df7c27d55b2c1..20bbe3530a692 100644 --- a/polkadot/service/src/lib.rs +++ b/polkadot/service/src/lib.rs @@ -37,8 +37,6 @@ extern crate substrate_executor; extern crate tokio_core; extern crate substrate_client as client; -#[macro_use] -extern crate hex_literal; #[macro_use] extern crate error_chain; #[macro_use] diff --git a/substrate/bft/Cargo.toml b/substrate/bft/Cargo.toml index 4c5978429f5cb..e580c18867155 100644 --- a/substrate/bft/Cargo.toml +++ b/substrate/bft/Cargo.toml @@ -12,6 +12,7 @@ ed25519 = { path = "../ed25519" } tokio-timer = "0.1.2" parking_lot = "0.4" error-chain = "0.11" +log = "0.4" [dev-dependencies] substrate-keyring = { path = "../keyring" } diff --git a/substrate/bft/src/lib.rs b/substrate/bft/src/lib.rs index cc1031d3aa47f..e21051b1aef36 100644 --- a/substrate/bft/src/lib.rs +++ b/substrate/bft/src/lib.rs @@ -26,6 +26,9 @@ extern crate ed25519; extern crate tokio_timer; extern crate parking_lot; +#[macro_use] +extern crate log; + #[macro_use] extern crate futures; @@ -255,11 +258,16 @@ impl Future for BftFuture wher } // TODO: handle this error, at least by logging. - let committed = try_ready!(self.inner.poll().map_err(|e| println!("Error in BFT: {}", e))); + let committed = try_ready!(self.inner.poll().map_err(|e| { + warn!(target: "bft", "Error in BFT agreement: {}", e); + })); // If we didn't see the proposal (very unlikely), // we will get the block from the network later. if let Some(justified_block) = committed.candidate { + info!(target: "bft", "Importing block #{} ({}) directly from BFT consensus", + justified_block.header.number, HeaderHash::from(justified_block.header.blake2_256())); + self.import.import_block(justified_block, committed.justification) } From 1ac8bd0af650269d9105703ea60c3fa8f231daa6 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 6 Apr 2018 16:57:56 +0200 Subject: [PATCH 18/18] Fixed message propagation --- polkadot/consensus/src/service.rs | 4 +-- substrate/network/src/consensus.rs | 51 ++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/polkadot/consensus/src/service.rs b/polkadot/consensus/src/service.rs index e95f6a4a7da96..3671edfb90f3e 100644 --- a/polkadot/consensus/src/service.rs +++ b/polkadot/consensus/src/service.rs @@ -39,7 +39,7 @@ use ed25519; use super::{TableRouter, SharedTable, ProposerFactory}; use error; -const TIMER_DELAY_MS: u64 = 15000; +const TIMER_DELAY_MS: u64 = 5000; const TIMER_INTERVAL_MS: u64 = 500; const MESSAGE_LIFETIME_SEC: u64 = 10; @@ -82,7 +82,7 @@ impl SharedMessageCollection { fn collect_garbage(&self) { let expiration = Duration::from_secs(MESSAGE_LIFETIME_SEC); let now = Instant::now(); - self.messages.lock().retain(|_, &mut (timestamp, _)| timestamp + expiration < now); + self.messages.lock().retain(|_, &mut (timestamp, _)| timestamp < now + expiration); } } diff --git a/substrate/network/src/consensus.rs b/substrate/network/src/consensus.rs index 006ff83c4378d..7d13049ed4189 100644 --- a/substrate/network/src/consensus.rs +++ b/substrate/network/src/consensus.rs @@ -47,7 +47,7 @@ pub struct Consensus { our_candidate: Option<(Hash, Vec)>, statement_sink: Option>, bft_message_sink: Option>, - message_timestamps: HashMap, + messages: HashMap, } impl Consensus { @@ -58,7 +58,7 @@ impl Consensus { our_candidate: None, statement_sink: None, bft_message_sink: None, - message_timestamps: Default::default(), + messages: Default::default(), } } @@ -69,13 +69,20 @@ impl Consensus { } /// Handle new connected peer. - pub fn new_peer(&mut self, _io: &mut SyncIo, _protocol: &Protocol, peer_id: PeerId, roles: &[message::Role]) { + pub fn new_peer(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, roles: &[message::Role]) { if roles.iter().any(|r| *r == message::Role::Validator) { trace!(target:"sync", "Registering validator {}", peer_id); + // Send out all known messages. + // TODO: limit by size + let mut known_messages = HashSet::new(); + for (hash, &(_, ref m)) in self.messages.iter() { + known_messages.insert(hash.clone()); + protocol.send_message(io, peer_id, m.clone()); + } self.peers.insert(peer_id, PeerConsensus { candidate_fetch: None, candidate_available: None, - known_messages: Default::default(), + known_messages, }); } } @@ -88,13 +95,16 @@ impl Consensus { } } - fn register_message(&mut self, hash: Hash) { - if let Entry::Vacant(entry) = self.message_timestamps.entry(hash) { - entry.insert(Instant::now()); + fn register_message(&mut self, hash: Hash, message: message::Message) { + if let Entry::Vacant(entry) = self.messages.entry(hash) { + entry.insert((Instant::now(), message)); } } pub fn on_statement(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, statement: message::Statement, hash: Hash) { + if self.messages.contains_key(&hash) { + trace!(target:"sync", "Ignored already known statement from {}", peer_id); + } if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { // TODO: validate signature? match &statement.statement { @@ -114,9 +124,10 @@ impl Consensus { trace!(target:"sync", "Ignored statement from unregistered peer {}", peer_id); return; } - self.register_message(hash.clone()); + let message = Message::Statement(statement); + self.register_message(hash.clone(), message.clone()); // Propagate to other peers. - self.propagate(io, protocol, Message::Statement(statement), hash); + self.propagate(io, protocol, message, hash); } pub fn statements(&mut self) -> mpsc::UnboundedReceiver{ @@ -126,6 +137,9 @@ impl Consensus { } pub fn on_bft_message(&mut self, io: &mut SyncIo, protocol: &Protocol, peer_id: PeerId, message: message::LocalizedBftMessage, hash: Hash) { + if self.messages.contains_key(&hash) { + trace!(target:"sync", "Ignored already known BFT message from {}", peer_id); + } if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { peer.known_messages.insert(hash); // TODO: validate signature? @@ -140,9 +154,10 @@ impl Consensus { trace!(target:"sync", "Ignored BFT statement from unregistered peer {}", peer_id); return; } - self.register_message(hash.clone()); + let message = Message::BftMessage(message); + self.register_message(hash.clone(), message.clone()); // Propagate to other peers. - self.propagate(io, protocol, Message::BftMessage(message), hash); + self.propagate(io, protocol, message, hash); } pub fn bft_messages(&mut self) -> mpsc::UnboundedReceiver{ @@ -180,7 +195,7 @@ impl Consensus { trace!(target:"sync", "Broadcasting statement {:?}", statement); let message = Message::Statement(statement); let hash = Protocol::hash_message(&message); - self.register_message(hash.clone()); + self.register_message(hash.clone(), message.clone()); self.propagate(io, protocol, message, hash); } @@ -189,7 +204,7 @@ impl Consensus { trace!(target:"sync", "Broadcasting BFT message {:?}", message); let message = Message::BftMessage(message); let hash = Protocol::hash_message(&message); - self.register_message(hash.clone()); + self.register_message(hash.clone(), message.clone()); self.propagate(io, protocol, message, hash); } @@ -237,10 +252,14 @@ impl Consensus { pub fn collect_garbage(&mut self) { let expiration = Duration::from_secs(MESSAGE_LIFETIME_SECONDS); let now = Instant::now(); - self.message_timestamps.retain(|_, timestamp| *timestamp + expiration < now); - let timestamps = &self.message_timestamps; + let before = self.messages.len(); + self.messages.retain(|_, &mut (timestamp, _)| timestamp < now + expiration); + if self.messages.len() != before { + trace!(target:"sync", "Cleaned up {} stale messages", before - self.messages.len()); + } + let messages = &self.messages; for (_, ref mut peer) in self.peers.iter_mut() { - peer.known_messages.retain(|h| timestamps.contains_key(h)); + peer.known_messages.retain(|h| messages.contains_key(h)); } } }