From 5f3a7f902d807f7f033f85941faba908c1c448a3 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Wed, 11 Sep 2024 14:01:45 +0200 Subject: [PATCH 01/22] generated abi --- zk_toolbox/Cargo.lock | 2 +- zk_toolbox/Cargo.toml | 1 + zk_toolbox/crates/config/src/chain.rs | 7 ++++ zk_toolbox/crates/zk_inception/Cargo.toml | 4 ++ zk_toolbox/crates/zk_inception/build.rs | 11 ++++++ .../src/commands/consensus/mod.rs | 38 +++++++++++++++++++ .../crates/zk_inception/src/commands/mod.rs | 1 + zk_toolbox/crates/zk_inception/src/main.rs | 5 ++- 8 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 zk_toolbox/crates/zk_inception/build.rs create mode 100644 zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs diff --git a/zk_toolbox/Cargo.lock b/zk_toolbox/Cargo.lock index 75859021979f..f9d8c308382d 100644 --- a/zk_toolbox/Cargo.lock +++ b/zk_toolbox/Cargo.lock @@ -6275,6 +6275,7 @@ dependencies = [ "config", "console", "ethers", + "eyre", "human-panic", "lazy_static", "serde", @@ -6539,7 +6540,6 @@ dependencies = [ "bigdecimal", "futures", "hex", - "itertools 0.10.5", "num", "once_cell", "reqwest 0.12.5", diff --git a/zk_toolbox/Cargo.toml b/zk_toolbox/Cargo.toml index e1ad63136af1..2f43a6ce07c7 100644 --- a/zk_toolbox/Cargo.toml +++ b/zk_toolbox/Cargo.toml @@ -38,6 +38,7 @@ clap = { version = "4.4", features = ["derive", "wrap_help", "string"] } slugify-rs = "0.0.3" cliclack = "0.2.5" console = "0.15.8" +eyre = "0.6.12" ethers = "2.0" futures = "0.3.30" human-panic = "2.0" diff --git a/zk_toolbox/crates/config/src/chain.rs b/zk_toolbox/crates/config/src/chain.rs index 54ed1f7d3f35..1fce5ee7c548 100644 --- a/zk_toolbox/crates/config/src/chain.rs +++ b/zk_toolbox/crates/config/src/chain.rs @@ -18,6 +18,7 @@ use crate::{ FileConfigWithDefaultName, ReadConfig, ReadConfigWithBasePath, SaveConfig, SaveConfigWithBasePath, ZkToolboxConfig, }, + //external_node::ENConfig, ContractsConfig, GeneralConfig, GenesisConfig, SecretsConfig, WalletsConfig, }; @@ -94,10 +95,16 @@ impl ChainConfig { } anyhow::bail!("Wallets configs has not been found"); } + pub fn get_contracts_config(&self) -> anyhow::Result { ContractsConfig::read_with_base_path(self.get_shell(), &self.configs) } + /* + pub fn get_external_node_config(&self) -> anyhow::Result { + ENConfig::read_with_base_path(self.get_shell(), &self.configs) + }*/ + pub fn get_secrets_config(&self) -> anyhow::Result { SecretsConfig::read_with_base_path(self.get_shell(), &self.configs) } diff --git a/zk_toolbox/crates/zk_inception/Cargo.toml b/zk_toolbox/crates/zk_inception/Cargo.toml index 01d0697d6b6c..ac9b1b552c23 100644 --- a/zk_toolbox/crates/zk_inception/Cargo.toml +++ b/zk_toolbox/crates/zk_inception/Cargo.toml @@ -34,3 +34,7 @@ zksync_config.workspace = true slugify-rs.workspace = true zksync_basic_types.workspace = true clap-markdown.workspace = true + +[build-dependencies] +eyre.workspace = true +ethers.workspace = true diff --git a/zk_toolbox/crates/zk_inception/build.rs b/zk_toolbox/crates/zk_inception/build.rs new file mode 100644 index 000000000000..70abbf3be886 --- /dev/null +++ b/zk_toolbox/crates/zk_inception/build.rs @@ -0,0 +1,11 @@ +use ethers::contract::Abigen; +use std::path::PathBuf; + +fn main() -> eyre::Result<()> { + let outdir = PathBuf::from(std::env::var("OUT_DIR")?) + .canonicalize()?; + Abigen::new("ConsensusRegistry", "../../../contracts/l2-contracts/artifacts-zk/contracts/ConsensusRegistry.sol/ConsensusRegistry.json")? + .generate()? + .write_to_file(outdir.join("consensus_registry_abi.rs"))?; + Ok(()) +} diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs new file mode 100644 index 000000000000..54ed269b0774 --- /dev/null +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs @@ -0,0 +1,38 @@ +use anyhow::Context as _; +use xshell::Shell; +use ethers::providers::{Provider, Http}; +use config::EcosystemConfig; +use common::config::global_config; +use std::sync::Arc; +use crate::messages; + +mod abi { + include!(concat!(env!("OUT_DIR"), "/consensus_registry_abi.rs")); +} + +#[derive(clap::Subcommand, Debug)] +pub enum Command { + GetAttesterCommittee, +} + +impl Command { + pub(crate) async fn run(self, shell: &Shell) -> anyhow::Result<()> { + let ecosystem_config = EcosystemConfig::from_file(shell)?; + let chain_name = global_config().chain_name.clone(); + let chain_config = ecosystem_config + .load_chain(chain_name) + .context(messages::MSG_CHAIN_NOT_INITIALIZED)?; + let cfg = chain_config.get_general_config().context("get_general_config()")?; + let l2_url = &cfg.api_config.as_ref().context("api_config missing")?.web3_json_rpc.http_url; + let provider = Arc::new(Provider::::try_from(l2_url).with_context(||format!("Provide::try_from({l2_url})"))?); + let addr = ethers::core::types::Address::random(); + let consensus_registry = abi::ConsensusRegistry::new(addr, provider); + match self { + Self::GetAttesterCommittee => { + let _attesters = consensus_registry.get_attester_committee().call().await?; + //provider.call(tx,None).await + } + } + Ok(()) + } +} diff --git a/zk_toolbox/crates/zk_inception/src/commands/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/mod.rs index 523faea04786..7fdaf1083c85 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/mod.rs @@ -2,6 +2,7 @@ pub mod args; pub mod chain; pub mod containers; pub mod contract_verifier; +pub mod consensus; pub mod ecosystem; pub mod explorer; pub mod external_node; diff --git a/zk_toolbox/crates/zk_inception/src/main.rs b/zk_toolbox/crates/zk_inception/src/main.rs index f6f7d83dede6..2f1145d81571 100644 --- a/zk_toolbox/crates/zk_inception/src/main.rs +++ b/zk_toolbox/crates/zk_inception/src/main.rs @@ -13,7 +13,7 @@ use config::EcosystemConfig; use xshell::Shell; use crate::commands::{ - args::RunServerArgs, chain::ChainCommands, ecosystem::EcosystemCommands, + args::RunServerArgs, consensus, chain::ChainCommands, ecosystem::EcosystemCommands, explorer::ExplorerCommands, external_node::ExternalNodeCommands, prover::ProverCommands, }; @@ -62,6 +62,8 @@ pub enum InceptionSubcommands { #[command(subcommand)] Explorer(ExplorerCommands), /// Update ZKsync + #[command(subcommand)] + Consensus(consensus::Command), #[command(alias = "u")] Update(UpdateArgs), #[command(hide = true)] @@ -124,6 +126,7 @@ async fn run_subcommand(inception_args: Inception, shell: &Shell) -> anyhow::Res commands::contract_verifier::run(shell, args).await? } InceptionSubcommands::Explorer(args) => commands::explorer::run(shell, args).await?, + InceptionSubcommands::Consensus(cmd) => cmd.run(shell).await?, InceptionSubcommands::Portal => commands::portal::run(shell).await?, InceptionSubcommands::Update(args) => commands::update::run(shell, args)?, InceptionSubcommands::Markdown => { From 4eba9a9dcd23d3ac8726085c715e387266ee823c Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Wed, 11 Sep 2024 15:37:57 +0200 Subject: [PATCH 02/22] submitting txs works :) --- .../src/commands/consensus/mod.rs | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs index 54ed269b0774..50fbdcdc13f8 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs @@ -1,6 +1,8 @@ use anyhow::Context as _; use xshell::Shell; use ethers::providers::{Provider, Http}; +use ethers::middleware::SignerMiddleware; +use ethers::signers::{Signer as _, LocalWallet}; use config::EcosystemConfig; use common::config::global_config; use std::sync::Arc; @@ -10,8 +12,15 @@ mod abi { include!(concat!(env!("OUT_DIR"), "/consensus_registry_abi.rs")); } +#[derive(Debug, clap::Parser)] +pub struct AddArgs { + +} + #[derive(clap::Subcommand, Debug)] pub enum Command { + Add(AddArgs), + CommitAttesterCommittee, GetAttesterCommittee, } @@ -22,15 +31,32 @@ impl Command { let chain_config = ecosystem_config .load_chain(chain_name) .context(messages::MSG_CHAIN_NOT_INITIALIZED)?; + + let chain_id = chain_config.get_genesis_config().context("get_genesis_config()")?.l2_chain_id; + let governor = chain_config.get_wallets_config().context("get_secrets_config()")?.governor.private_key.context("governor private key not set")?; + let governor = LocalWallet::from_bytes(governor.as_bytes()).context("LocalWallet::from_bytes()")?.with_chain_id(chain_id.as_u64()); + let cfg = chain_config.get_general_config().context("get_general_config()")?; let l2_url = &cfg.api_config.as_ref().context("api_config missing")?.web3_json_rpc.http_url; - let provider = Arc::new(Provider::::try_from(l2_url).with_context(||format!("Provide::try_from({l2_url})"))?); - let addr = ethers::core::types::Address::random(); + let provider : Provider = l2_url.try_into().with_context(||format!("{l2_url}.try_into::()"))?; + let provider = Arc::new(SignerMiddleware::new(provider, governor)); + + let contracts_cfg = chain_config.get_contracts_config().context("get_contracts_config()")?; + let addr = contracts_cfg.l2.consensus_registry.context("consensus_registry address not configured")?; let consensus_registry = abi::ConsensusRegistry::new(addr, provider); match self { + Self::Add(args) => { + + } + Self::CommitAttesterCommittee => { + let res = consensus_registry.commit_attester_committee() + .send().await.context("send()")? + .await.context("awaiting transaction")?; + println!("result = {res:?}"); + } Self::GetAttesterCommittee => { - let _attesters = consensus_registry.get_attester_committee().call().await?; - //provider.call(tx,None).await + let attesters = consensus_registry.get_attester_committee().call().await?; + println!("attesters = {attesters:?}"); } } Ok(()) From 425d9923e8c2f02db6c98a400f27f76e2111d37d Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Thu, 12 Sep 2024 14:37:36 +0200 Subject: [PATCH 03/22] wip --- zk_toolbox/crates/zk_inception/Cargo.toml | 2 + .../src/commands/consensus/mod.rs | 60 +++++++++++++++---- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/Cargo.toml b/zk_toolbox/crates/zk_inception/Cargo.toml index ac9b1b552c23..09432b555997 100644 --- a/zk_toolbox/crates/zk_inception/Cargo.toml +++ b/zk_toolbox/crates/zk_inception/Cargo.toml @@ -34,6 +34,8 @@ zksync_config.workspace = true slugify-rs.workspace = true zksync_basic_types.workspace = true clap-markdown.workspace = true +zksync_consensus_roles.workspace = true +zksync_consensus_crypto.workspace = true [build-dependencies] eyre.workspace = true diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs index 50fbdcdc13f8..d91675627967 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs @@ -7,20 +7,61 @@ use config::EcosystemConfig; use common::config::global_config; use std::sync::Arc; use crate::messages; +use zksync_consensus_roles::{attester,validator}; +use zksync_consensus_crypto::{TextFmt, ByteFmt}; mod abi { include!(concat!(env!("OUT_DIR"), "/consensus_registry_abi.rs")); } -#[derive(Debug, clap::Parser)] -pub struct AddArgs { - +fn decode_attester_key(k : &abi::Secp256K1PublicKey) -> anyhow::Result { + let mut x = vec![]; + x.extend(k.tag); + x.extend(k.x); + ByteFmt::decode(&x) +} + +fn decode_weighted_attester(a: &abi::CommitteeAttester) -> anyhow::Result { + Ok(attester::WeightedAttester { + weight: a.weight.into(), + key: decode_attester_key(&a.pub_key).context("key")?, + }) +} + +pub(crate) struct WeightedValidator { + weight: validator::Weight, + key: validator::PublicKey, + pop: validator::ProofOfPossession, +} + +fn encode_attester_key(k: &attester::PublicKey) -> abi::Secp256K1PublicKey { + let b: [u8; 33] = ByteFmt::encode(k).try_into().unwrap(); + abi::Secp256K1PublicKey { + tag: b[0..1].try_into().unwrap(), + x: b[1..33].try_into().unwrap(), + } +} + +fn encode_validator_key(k: &validator::PublicKey) -> abi::Bls12381PublicKey { + let b: [u8; 96] = ByteFmt::encode(k).try_into().unwrap(); + abi::Bls12381PublicKey { + a: b[0..32].try_into().unwrap(), + b: b[32..64].try_into().unwrap(), + c: b[64..96].try_into().unwrap(), + } +} + +fn encode_validator_pop(pop: &validator::ProofOfPossession) -> abi::Bls12381Signature { + let b: [u8; 48] = ByteFmt::encode(pop).try_into().unwrap(); + abi::Bls12381Signature { + a: b[0..32].try_into().unwrap(), + b: b[32..48].try_into().unwrap(), + } } #[derive(clap::Subcommand, Debug)] pub enum Command { - Add(AddArgs), - CommitAttesterCommittee, + SetAttesterCommittee, GetAttesterCommittee, } @@ -39,16 +80,15 @@ impl Command { let cfg = chain_config.get_general_config().context("get_general_config()")?; let l2_url = &cfg.api_config.as_ref().context("api_config missing")?.web3_json_rpc.http_url; let provider : Provider = l2_url.try_into().with_context(||format!("{l2_url}.try_into::()"))?; + let block_id = provider.get_block_number().await.context("get_block_number")?; let provider = Arc::new(SignerMiddleware::new(provider, governor)); - + let contracts_cfg = chain_config.get_contracts_config().context("get_contracts_config()")?; let addr = contracts_cfg.l2.consensus_registry.context("consensus_registry address not configured")?; let consensus_registry = abi::ConsensusRegistry::new(addr, provider); match self { - Self::Add(args) => { - - } - Self::CommitAttesterCommittee => { + Self::SetAttesterCommittee => { + let attesters = consensus_registry.get_attester_committee().call().await?; let res = consensus_registry.commit_attester_committee() .send().await.context("send()")? .await.context("awaiting transaction")?; From a26d66998e9ccddd0df2c55a1c59053aa8ef9cc1 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Fri, 13 Sep 2024 14:13:15 +0200 Subject: [PATCH 04/22] wip --- contracts | 2 +- zk_toolbox/crates/config/src/contracts.rs | 11 ++++++++++- .../src/forge_interface/deploy_l2_contracts/output.rs | 6 ++++++ .../src/commands/chain/deploy_l2_contracts.rs | 3 ++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/contracts b/contracts index 3a1b5d4b94ff..73d646abe4f4 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 3a1b5d4b94ffb00f03d436a7db7e48589eb74d39 +Subproject commit 73d646abe4f42a9a38859d41b6b55a73d41a7900 diff --git a/zk_toolbox/crates/config/src/contracts.rs b/zk_toolbox/crates/config/src/contracts.rs index 0d4b1c7b1f81..92d824b91a9c 100644 --- a/zk_toolbox/crates/config/src/contracts.rs +++ b/zk_toolbox/crates/config/src/contracts.rs @@ -6,7 +6,7 @@ use crate::{ forge_interface::{ deploy_ecosystem::output::DeployL1Output, deploy_l2_contracts::output::{ - ConsensusRegistryOutput, DefaultL2UpgradeOutput, InitializeBridgeOutput, + ConsensusRegistryOutput, DefaultL2UpgradeOutput, InitializeBridgeOutput, Multicall3Output, }, register_chain::output::RegisterChainOutput, }, @@ -102,6 +102,14 @@ impl ContractsConfig { self.l2.default_l2_upgrader = default_upgrade_output.l2_default_upgrader; Ok(()) } + + pub fn set_multicall3( + &mut self, + multicall3_output: &Multicall3Output, + ) -> anyhow::Result<()> { + self.l2.multicall3 = multicall3_output.multicall3; + Ok(()) + } } impl FileConfigWithDefaultName for ContractsConfig { @@ -152,4 +160,5 @@ pub struct L2Contracts { pub testnet_paymaster_addr: Address, pub default_l2_upgrader: Address, pub consensus_registry: Option
, + pub multicall3: Address, } diff --git a/zk_toolbox/crates/config/src/forge_interface/deploy_l2_contracts/output.rs b/zk_toolbox/crates/config/src/forge_interface/deploy_l2_contracts/output.rs index 860e7e293f99..ca5cac12c02d 100644 --- a/zk_toolbox/crates/config/src/forge_interface/deploy_l2_contracts/output.rs +++ b/zk_toolbox/crates/config/src/forge_interface/deploy_l2_contracts/output.rs @@ -6,6 +6,7 @@ use crate::traits::ZkToolboxConfig; impl ZkToolboxConfig for InitializeBridgeOutput {} impl ZkToolboxConfig for DefaultL2UpgradeOutput {} impl ZkToolboxConfig for ConsensusRegistryOutput {} +impl ZkToolboxConfig for Multicall3Output {} #[derive(Debug, Clone, Serialize, Deserialize)] pub struct InitializeBridgeOutput { @@ -23,3 +24,8 @@ pub struct ConsensusRegistryOutput { pub consensus_registry_implementation: Address, pub consensus_registry_proxy: Address, } + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Multicall3Output { + pub multicall3: Address, +} diff --git a/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs b/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs index 7545ec2ec26f..45b707a157be 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs @@ -11,7 +11,7 @@ use config::{ forge_interface::{ deploy_l2_contracts::{ input::DeployL2ContractsInput, - output::{ConsensusRegistryOutput, DefaultL2UpgradeOutput, InitializeBridgeOutput}, + output::{ConsensusRegistryOutput, DefaultL2UpgradeOutput, InitializeBridgeOutput, Multicall3Output}, }, script_params::DEPLOY_L2_CONTRACTS_SCRIPT_PARAMS, }, @@ -205,6 +205,7 @@ pub async fn deploy_l2_contracts( contracts_config.set_l2_shared_bridge(&InitializeBridgeOutput::read(shell, out)?)?; contracts_config.set_default_l2_upgrade(&DefaultL2UpgradeOutput::read(shell, out)?)?; contracts_config.set_consensus_registry(&ConsensusRegistryOutput::read(shell, out)?)?; + contracts_config.set_multicall3(&Multicall3Output::read(shell, out)?)?; Ok(()) }, ) From d39b955ecb6b9f6e644ff92dacc91a9d5d336ad5 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Fri, 13 Sep 2024 14:22:23 +0200 Subject: [PATCH 05/22] fix --- contracts | 2 +- zk_toolbox/crates/config/src/contracts.rs | 8 +++----- .../src/commands/chain/deploy_l2_contracts.rs | 5 ++++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/contracts b/contracts index 73d646abe4f4..cbe788a34074 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 73d646abe4f42a9a38859d41b6b55a73d41a7900 +Subproject commit cbe788a34074b35a8f36bf8fd04d5aa7b07fc4e5 diff --git a/zk_toolbox/crates/config/src/contracts.rs b/zk_toolbox/crates/config/src/contracts.rs index 92d824b91a9c..36bb2a128561 100644 --- a/zk_toolbox/crates/config/src/contracts.rs +++ b/zk_toolbox/crates/config/src/contracts.rs @@ -6,7 +6,8 @@ use crate::{ forge_interface::{ deploy_ecosystem::output::DeployL1Output, deploy_l2_contracts::output::{ - ConsensusRegistryOutput, DefaultL2UpgradeOutput, InitializeBridgeOutput, Multicall3Output, + ConsensusRegistryOutput, DefaultL2UpgradeOutput, InitializeBridgeOutput, + Multicall3Output, }, register_chain::output::RegisterChainOutput, }, @@ -103,10 +104,7 @@ impl ContractsConfig { Ok(()) } - pub fn set_multicall3( - &mut self, - multicall3_output: &Multicall3Output, - ) -> anyhow::Result<()> { + pub fn set_multicall3(&mut self, multicall3_output: &Multicall3Output) -> anyhow::Result<()> { self.l2.multicall3 = multicall3_output.multicall3; Ok(()) } diff --git a/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs b/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs index 45b707a157be..5bfc0a623488 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/chain/deploy_l2_contracts.rs @@ -11,7 +11,10 @@ use config::{ forge_interface::{ deploy_l2_contracts::{ input::DeployL2ContractsInput, - output::{ConsensusRegistryOutput, DefaultL2UpgradeOutput, InitializeBridgeOutput, Multicall3Output}, + output::{ + ConsensusRegistryOutput, DefaultL2UpgradeOutput, InitializeBridgeOutput, + Multicall3Output, + }, }, script_params::DEPLOY_L2_CONTRACTS_SCRIPT_PARAMS, }, From b13b5fa2649c250f12f48d81c1670d790cb90d02 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Fri, 13 Sep 2024 14:49:30 +0200 Subject: [PATCH 06/22] fix --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index cbe788a34074..2aeb1f4556fa 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit cbe788a34074b35a8f36bf8fd04d5aa7b07fc4e5 +Subproject commit 2aeb1f4556fa78f50a4f668f60e78dd861e13f7a From 3483d26ba78ef5be88b95fb74c73180ecf87e42c Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Fri, 13 Sep 2024 14:51:16 +0200 Subject: [PATCH 07/22] ech... --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 2aeb1f4556fa..6079b0e551df 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 2aeb1f4556fa78f50a4f668f60e78dd861e13f7a +Subproject commit 6079b0e551dfd87caecfcb7c6f310b3d1f44d683 From dc10b6f1b5605ecb73f09c4d9a5bb4e462eda0d2 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Mon, 16 Sep 2024 11:31:33 +0200 Subject: [PATCH 08/22] bumped contracts --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 6079b0e551df..bce4b2d0f34b 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 6079b0e551dfd87caecfcb7c6f310b3d1f44d683 +Subproject commit bce4b2d0f34bd87f1aaadd291772935afb1c3bd6 From 413804112e25a00b23898055f2597618e6b8f643 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Mon, 16 Sep 2024 11:38:23 +0200 Subject: [PATCH 09/22] applied comments --- zk_toolbox/crates/config/src/contracts.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zk_toolbox/crates/config/src/contracts.rs b/zk_toolbox/crates/config/src/contracts.rs index 36bb2a128561..8296aa188527 100644 --- a/zk_toolbox/crates/config/src/contracts.rs +++ b/zk_toolbox/crates/config/src/contracts.rs @@ -105,7 +105,7 @@ impl ContractsConfig { } pub fn set_multicall3(&mut self, multicall3_output: &Multicall3Output) -> anyhow::Result<()> { - self.l2.multicall3 = multicall3_output.multicall3; + self.l2.multicall3 = Some(multicall3_output.multicall3); Ok(()) } } @@ -158,5 +158,5 @@ pub struct L2Contracts { pub testnet_paymaster_addr: Address, pub default_l2_upgrader: Address, pub consensus_registry: Option
, - pub multicall3: Address, + pub multicall3: Option
, } From 2040dbb0c57c072b033cc51dcc64eeafd5d9a381 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Mon, 16 Sep 2024 11:39:26 +0200 Subject: [PATCH 10/22] zk fmt --- infrastructure/zk/src/docker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/infrastructure/zk/src/docker.ts b/infrastructure/zk/src/docker.ts index a100d1231da6..035061a8ed0d 100644 --- a/infrastructure/zk/src/docker.ts +++ b/infrastructure/zk/src/docker.ts @@ -1,4 +1,4 @@ -import {Command} from 'commander'; +import { Command } from 'commander'; import * as utils from 'utils'; const IMAGES = [ @@ -31,7 +31,7 @@ async function dockerCommand( dockerOrg: string = 'matterlabs' ) { // Generating all tags for containers. We need 2 tags here: SHA and SHA+TS - const {stdout: COMMIT_SHORT_SHA}: { stdout: string } = await utils.exec('git rev-parse --short HEAD'); + const { stdout: COMMIT_SHORT_SHA }: { stdout: string } = await utils.exec('git rev-parse --short HEAD'); // COMMIT_SHORT_SHA returns with newline, so we need to trim it const imageTagShaTS: string = process.env.IMAGE_TAG_SUFFIX ? process.env.IMAGE_TAG_SUFFIX @@ -126,7 +126,7 @@ async function _build(image: string, tagList: string[], dockerOrg: string, platf } buildArgs += extraArgs; - console.log("Build args: ", buildArgs); + console.log('Build args: ', buildArgs); const buildCommand = `DOCKER_BUILDKIT=1 docker buildx build ${tagsToBuild}` + From 1c82e4ccb8437c2e3abb175dae4afdc8fb12942d Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Mon, 16 Sep 2024 14:27:23 +0200 Subject: [PATCH 11/22] implemented the thing --- zk_toolbox/crates/config/src/chain.rs | 6 +- zk_toolbox/crates/zk_inception/build.rs | 6 +- .../src/commands/consensus/mod.rs | 206 +++++++++++++++--- .../crates/zk_inception/src/commands/mod.rs | 2 +- zk_toolbox/crates/zk_inception/src/main.rs | 2 +- .../zk_inception/src/utils/consensus.rs | 39 +++- 6 files changed, 212 insertions(+), 49 deletions(-) diff --git a/zk_toolbox/crates/config/src/chain.rs b/zk_toolbox/crates/config/src/chain.rs index 4542772114d6..93b4f33d9a1a 100644 --- a/zk_toolbox/crates/config/src/chain.rs +++ b/zk_toolbox/crates/config/src/chain.rs @@ -19,7 +19,11 @@ use crate::{ SaveConfigWithBasePath, ZkToolboxConfig, }, //external_node::ENConfig, - ContractsConfig, GeneralConfig, GenesisConfig, SecretsConfig, WalletsConfig, + ContractsConfig, + GeneralConfig, + GenesisConfig, + SecretsConfig, + WalletsConfig, }; /// Chain configuration file. This file is created in the chain diff --git a/zk_toolbox/crates/zk_inception/build.rs b/zk_toolbox/crates/zk_inception/build.rs index 70abbf3be886..5134ff3886e0 100644 --- a/zk_toolbox/crates/zk_inception/build.rs +++ b/zk_toolbox/crates/zk_inception/build.rs @@ -1,9 +1,9 @@ -use ethers::contract::Abigen; use std::path::PathBuf; +use ethers::contract::Abigen; + fn main() -> eyre::Result<()> { - let outdir = PathBuf::from(std::env::var("OUT_DIR")?) - .canonicalize()?; + let outdir = PathBuf::from(std::env::var("OUT_DIR")?).canonicalize()?; Abigen::new("ConsensusRegistry", "../../../contracts/l2-contracts/artifacts-zk/contracts/ConsensusRegistry.sol/ConsensusRegistry.json")? .generate()? .write_to_file(outdir.join("consensus_registry_abi.rs"))?; diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs index d91675627967..ea582400e621 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs @@ -1,39 +1,43 @@ +use std::{collections::HashMap, sync::Arc}; + +/// Consensus registry contract operations. +/// Includes code duplicated from `zksync_node_consensus::registry::abi`. use anyhow::Context as _; -use xshell::Shell; -use ethers::providers::{Provider, Http}; -use ethers::middleware::SignerMiddleware; -use ethers::signers::{Signer as _, LocalWallet}; -use config::EcosystemConfig; use common::config::global_config; -use std::sync::Arc; -use crate::messages; -use zksync_consensus_roles::{attester,validator}; -use zksync_consensus_crypto::{TextFmt, ByteFmt}; +use config::EcosystemConfig; +use ethers::{ + contract::Multicall, + middleware::{Middleware as _, SignerMiddleware}, + providers::{Http, Provider, RawCall as _}, + signers::{LocalWallet, Signer as _}, + types::BlockId, +}; +use xshell::Shell; +use zksync_consensus_crypto::ByteFmt; +use zksync_consensus_roles::{attester, validator}; + +use crate::{messages, utils::consensus::parse_attester_committee}; mod abi { include!(concat!(env!("OUT_DIR"), "/consensus_registry_abi.rs")); } -fn decode_attester_key(k : &abi::Secp256K1PublicKey) -> anyhow::Result { +fn decode_attester_key(k: &abi::Secp256K1PublicKey) -> anyhow::Result { let mut x = vec![]; x.extend(k.tag); x.extend(k.x); ByteFmt::decode(&x) } -fn decode_weighted_attester(a: &abi::CommitteeAttester) -> anyhow::Result { +fn decode_weighted_attester( + a: &abi::CommitteeAttester, +) -> anyhow::Result { Ok(attester::WeightedAttester { weight: a.weight.into(), key: decode_attester_key(&a.pub_key).context("key")?, }) } -pub(crate) struct WeightedValidator { - weight: validator::Weight, - key: validator::PublicKey, - pop: validator::ProofOfPossession, -} - fn encode_attester_key(k: &attester::PublicKey) -> abi::Secp256K1PublicKey { let b: [u8; 33] = ByteFmt::encode(k).try_into().unwrap(); abi::Secp256K1PublicKey { @@ -72,30 +76,166 @@ impl Command { let chain_config = ecosystem_config .load_chain(chain_name) .context(messages::MSG_CHAIN_NOT_INITIALIZED)?; - - let chain_id = chain_config.get_genesis_config().context("get_genesis_config()")?.l2_chain_id; - let governor = chain_config.get_wallets_config().context("get_secrets_config()")?.governor.private_key.context("governor private key not set")?; - let governor = LocalWallet::from_bytes(governor.as_bytes()).context("LocalWallet::from_bytes()")?.with_chain_id(chain_id.as_u64()); - - let cfg = chain_config.get_general_config().context("get_general_config()")?; - let l2_url = &cfg.api_config.as_ref().context("api_config missing")?.web3_json_rpc.http_url; - let provider : Provider = l2_url.try_into().with_context(||format!("{l2_url}.try_into::()"))?; - let block_id = provider.get_block_number().await.context("get_block_number")?; + + let chain_id = chain_config + .get_genesis_config() + .context("get_genesis_config()")? + .l2_chain_id; + let governor = chain_config + .get_wallets_config() + .context("get_secrets_config()")? + .governor + .private_key + .context("governor private key not set")?; + let governor = LocalWallet::from_bytes(governor.as_bytes()) + .context("LocalWallet::from_bytes()")? + .with_chain_id(chain_id.as_u64()); + + let cfg = chain_config + .get_general_config() + .context("get_general_config()")?; + let l2_url = &cfg + .api_config + .as_ref() + .context("api_config missing")? + .web3_json_rpc + .http_url; + let provider: Provider = l2_url + .try_into() + .with_context(|| format!("{l2_url}.try_into::()"))?; + let block_id = BlockId::from( + provider + .get_block_number() + .await + .context("get_block_number")?, + ); let provider = Arc::new(SignerMiddleware::new(provider, governor)); - - let contracts_cfg = chain_config.get_contracts_config().context("get_contracts_config()")?; - let addr = contracts_cfg.l2.consensus_registry.context("consensus_registry address not configured")?; + + let contracts_cfg = chain_config + .get_contracts_config() + .context("get_contracts_config()")?; + let mut multicall = Multicall::new_with_chain_id( + provider.clone(), + Some( + contracts_cfg + .l2 + .multicall3 + .context("multicall3 contract not configured")?, + ), + Some(chain_id.as_u64()), + ) + .context("Multicall::new()")?; + let addr = contracts_cfg + .l2 + .consensus_registry + .context("consensus_registry address not configured")?; let consensus_registry = abi::ConsensusRegistry::new(addr, provider); match self { Self::SetAttesterCommittee => { - let attesters = consensus_registry.get_attester_committee().call().await?; - let res = consensus_registry.commit_attester_committee() - .send().await.context("send()")? - .await.context("awaiting transaction")?; + // Fetch the desired state. + let want = (|| { + Some( + &cfg.consensus_config + .as_ref()? + .genesis_spec + .as_ref()? + .attesters, + ) + })() + .context("consensus.genesis_spec.attesters missing in general.yaml")?; + let want = parse_attester_committee(&want).context("parse_attester_committee()")?; + + // Fetch contract state. + let n: usize = consensus_registry + .num_nodes() + .call_raw() + .block(block_id) + .await + .context("num_nodes()")? + .try_into() + .ok() + .context("overflow")?; + multicall.block = Some(block_id); + let node_owners: Vec = multicall + .add_calls( + false, + (0..n).map(|i| consensus_registry.node_owners(i.into())), + ) + .call_array() + .await + .context("node_owners()")?; + multicall.clear_calls(); + let nodes: Vec = multicall + .add_calls( + false, + node_owners + .iter() + .map(|node| consensus_registry.nodes(node.0)), + ) + .call_array() + .await + .context("nodes()")?; + multicall.clear_calls(); + + // Construct update tx. + let mut want: HashMap<_, _> = + want.iter().map(|a| (a.key.clone(), a.weight)).collect(); + for (i, node) in nodes.into_iter().enumerate() { + let got = attester::WeightedAttester { + key: decode_attester_key(&node.attester_latest.pub_key) + .context("decode_attester_key")?, + weight: node.attester_latest.weight.into(), + }; + match want.remove(&got.key) { + None => { + multicall.add_call(consensus_registry.remove(node_owners[i].0), false); + } + Some(weight) if weight != got.weight => { + multicall.add_call( + consensus_registry.change_attester_weight( + node_owners[i].0, + weight.try_into().context("overflow")?, + ), + false, + ); + } + _ => {} + } + } + for (key, weight) in want { + let vk = validator::SecretKey::generate(); + multicall.add_call( + consensus_registry.add( + ethers::types::Address::random(), + /*validator_weight=*/ 1, + encode_validator_key(&vk.public()), + encode_validator_pop(&vk.sign_pop()), + weight.try_into().context("overflow")?, + encode_attester_key(&key), + ), + false, + ); + } + + // Execute the update tx. + multicall.add_call(consensus_registry.commit_attester_committee(), false); + let res = multicall + .send() + .await + .context("send()")? + .await + .context("awaiting transaction")?; println!("result = {res:?}"); } Self::GetAttesterCommittee => { let attesters = consensus_registry.get_attester_committee().call().await?; + let attesters: Vec<_> = attesters + .iter() + .map(decode_weighted_attester) + .collect::>() + .context("decode_weighted_attester")?; + let attesters = attester::Committee::new(attesters.into_iter()) + .context("attester::Committee::new()")?; println!("attesters = {attesters:?}"); } } diff --git a/zk_toolbox/crates/zk_inception/src/commands/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/mod.rs index 7fdaf1083c85..78a46797602f 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/mod.rs @@ -1,8 +1,8 @@ pub mod args; pub mod chain; +pub mod consensus; pub mod containers; pub mod contract_verifier; -pub mod consensus; pub mod ecosystem; pub mod explorer; pub mod external_node; diff --git a/zk_toolbox/crates/zk_inception/src/main.rs b/zk_toolbox/crates/zk_inception/src/main.rs index 2f1145d81571..3db5b32cd6f1 100644 --- a/zk_toolbox/crates/zk_inception/src/main.rs +++ b/zk_toolbox/crates/zk_inception/src/main.rs @@ -13,7 +13,7 @@ use config::EcosystemConfig; use xshell::Shell; use crate::commands::{ - args::RunServerArgs, consensus, chain::ChainCommands, ecosystem::EcosystemCommands, + args::RunServerArgs, chain::ChainCommands, consensus, ecosystem::EcosystemCommands, explorer::ExplorerCommands, external_node::ExternalNodeCommands, prover::ProverCommands, }; diff --git a/zk_toolbox/crates/zk_inception/src/utils/consensus.rs b/zk_toolbox/crates/zk_inception/src/utils/consensus.rs index 06848334a6e1..c1d3e963c7c4 100644 --- a/zk_toolbox/crates/zk_inception/src/utils/consensus.rs +++ b/zk_toolbox/crates/zk_inception/src/utils/consensus.rs @@ -3,6 +3,8 @@ use std::{ net::SocketAddr, }; +/// Code duplicated from `zksync_node_consensus::config`. +use anyhow::Context as _; use config::{ChainConfig, PortsConfig}; use secrecy::{ExposeSecret, Secret}; use zksync_config::configs::consensus::{ @@ -11,23 +13,40 @@ use zksync_config::configs::consensus::{ WeightedAttester, WeightedValidator, }; use zksync_consensus_crypto::{Text, TextFmt}; -use zksync_consensus_roles as roles; +use zksync_consensus_roles::{attester, node, validator}; use crate::consts::{ CONSENSUS_PUBLIC_ADDRESS_HOST, CONSENSUS_SERVER_ADDRESS_HOST, GOSSIP_DYNAMIC_INBOUND_LIMIT, MAX_BATCH_SIZE, MAX_PAYLOAD_SIZE, }; +pub(crate) fn parse_attester_committee( + attesters: &[WeightedAttester], +) -> anyhow::Result { + let attesters: Vec<_> = attesters + .iter() + .enumerate() + .map(|(i, v)| { + Ok(attester::WeightedAttester { + key: Text::new(&v.key.0).decode().context("key").context(i)?, + weight: v.weight, + }) + }) + .collect::>() + .context("attesters")?; + attester::Committee::new(attesters.into_iter()).context("Committee::new()") +} + #[derive(Debug, Clone)] pub struct ConsensusSecretKeys { - validator_key: roles::validator::SecretKey, - attester_key: roles::attester::SecretKey, - node_key: roles::node::SecretKey, + validator_key: validator::SecretKey, + attester_key: attester::SecretKey, + node_key: node::SecretKey, } pub struct ConsensusPublicKeys { - validator_key: roles::validator::PublicKey, - attester_key: roles::attester::PublicKey, + validator_key: validator::PublicKey, + attester_key: attester::PublicKey, } pub fn get_consensus_config( @@ -57,9 +76,9 @@ pub fn get_consensus_config( pub fn generate_consensus_keys() -> ConsensusSecretKeys { ConsensusSecretKeys { - validator_key: roles::validator::SecretKey::generate(), - attester_key: roles::attester::SecretKey::generate(), - node_key: roles::node::SecretKey::generate(), + validator_key: validator::SecretKey::generate(), + attester_key: attester::SecretKey::generate(), + node_key: node::SecretKey::generate(), } } @@ -113,7 +132,7 @@ pub fn get_consensus_secrets(consensus_keys: &ConsensusSecretKeys) -> ConsensusS pub fn node_public_key(secrets: &ConsensusSecrets) -> anyhow::Result> { Ok(node_key(secrets)?.map(|node_secret_key| NodePublicKey(node_secret_key.public().encode()))) } -fn node_key(secrets: &ConsensusSecrets) -> anyhow::Result> { +fn node_key(secrets: &ConsensusSecrets) -> anyhow::Result> { read_secret_text(secrets.node_key.as_ref().map(|x| &x.0)) } From 65b957098b164209573f3889eee3f483258b5248 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Mon, 16 Sep 2024 14:34:08 +0200 Subject: [PATCH 12/22] added missing activation --- .../zk_inception/src/commands/consensus/mod.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs index ea582400e621..59fe0a0e6956 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs @@ -181,16 +181,16 @@ impl Command { let mut want: HashMap<_, _> = want.iter().map(|a| (a.key.clone(), a.weight)).collect(); for (i, node) in nodes.into_iter().enumerate() { + if node.attester_latest.removed { + continue; + } let got = attester::WeightedAttester { key: decode_attester_key(&node.attester_latest.pub_key) .context("decode_attester_key")?, weight: node.attester_latest.weight.into(), }; - match want.remove(&got.key) { - None => { - multicall.add_call(consensus_registry.remove(node_owners[i].0), false); - } - Some(weight) if weight != got.weight => { + if let Some(weight) = want.remove(&got.key) { + if weight != got.weight { multicall.add_call( consensus_registry.change_attester_weight( node_owners[i].0, @@ -199,7 +199,12 @@ impl Command { false, ); } - _ => {} + if !node.attester_latest.active { + multicall + .add_call(consensus_registry.activate(node_owners[i].0), false); + } + } else { + multicall.add_call(consensus_registry.remove(node_owners[i].0), false); } } for (key, weight) in want { From 52fc1c92af18e5f30819a38d537b38714e0165d4 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Tue, 17 Sep 2024 14:45:23 +0200 Subject: [PATCH 13/22] doesn't work --- .../web3/backend_jsonrpsee/namespaces/eth.rs | 5 +- .../src/commands/args/run_server.rs | 2 +- .../src/commands/consensus/mod.rs | 67 ++++++++----------- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs index 15528c5b309b..2f0ec8902245 100644 --- a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs +++ b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs @@ -46,7 +46,10 @@ impl EthNamespaceServer for EthNamespace { ) -> RpcResult { self.estimate_gas_impl(req, block, state_override) .await - .map_err(|err| self.current_method().map_err(err)) + .map_err(|err| { + tracing::error!("estimate_gas(): {err:#}"); + self.current_method().map_err(err) + }) } async fn gas_price(&self) -> RpcResult { diff --git a/zk_toolbox/crates/zk_inception/src/commands/args/run_server.rs b/zk_toolbox/crates/zk_inception/src/commands/args/run_server.rs index ebe407d4822d..d090c0de03f9 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/args/run_server.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/args/run_server.rs @@ -17,6 +17,6 @@ pub struct RunServerArgs { additional_args: Vec, #[clap(long, help = MSG_SERVER_BUILD_HELP)] pub build: bool, - #[clap(help=MSG_SERVER_URING_HELP, long, default_missing_value = "true", num_args = 0..=1)] + #[clap(help=MSG_SERVER_URING_HELP, long, default_missing_value = "true")] pub uring: bool, } diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs index 59fe0a0e6956..923d3f204110 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs @@ -109,13 +109,13 @@ impl Command { .await .context("get_block_number")?, ); - let provider = Arc::new(SignerMiddleware::new(provider, governor)); + let signer = Arc::new(SignerMiddleware::new(provider.clone(), governor)); let contracts_cfg = chain_config .get_contracts_config() .context("get_contracts_config()")?; let mut multicall = Multicall::new_with_chain_id( - provider.clone(), + signer.clone(), Some( contracts_cfg .l2 @@ -129,7 +129,7 @@ impl Command { .l2 .consensus_registry .context("consensus_registry address not configured")?; - let consensus_registry = abi::ConsensusRegistry::new(addr, provider); + let consensus_registry = abi::ConsensusRegistry::new(addr, signer.clone()); match self { Self::SetAttesterCommittee => { // Fetch the desired state. @@ -156,7 +156,7 @@ impl Command { .ok() .context("overflow")?; multicall.block = Some(block_id); - let node_owners: Vec = multicall + let node_owners: Vec = multicall .add_calls( false, (0..n).map(|i| consensus_registry.node_owners(i.into())), @@ -170,14 +170,14 @@ impl Command { false, node_owners .iter() - .map(|node| consensus_registry.nodes(node.0)), + .map(|addr| consensus_registry.nodes(*addr)), ) .call_array() .await .context("nodes()")?; multicall.clear_calls(); - // Construct update tx. + let mut txs = vec![]; let mut want: HashMap<_, _> = want.iter().map(|a| (a.key.clone(), a.weight)).collect(); for (i, node) in nodes.into_iter().enumerate() { @@ -191,46 +191,35 @@ impl Command { }; if let Some(weight) = want.remove(&got.key) { if weight != got.weight { - multicall.add_call( - consensus_registry.change_attester_weight( - node_owners[i].0, - weight.try_into().context("overflow")?, - ), - false, - ); + txs.push(consensus_registry.change_attester_weight( + node_owners[i], + weight.try_into().context("overflow")?, + ).send().await.context("send()")?.tx_hash()); } if !node.attester_latest.active { - multicall - .add_call(consensus_registry.activate(node_owners[i].0), false); + txs.push(consensus_registry.activate(node_owners[i]).send().await.context("send()")?.tx_hash()); } } else { - multicall.add_call(consensus_registry.remove(node_owners[i].0), false); + txs.push(consensus_registry.remove(node_owners[i]).send().await.context("send()")?.tx_hash()); } } for (key, weight) in want { let vk = validator::SecretKey::generate(); - multicall.add_call( - consensus_registry.add( - ethers::types::Address::random(), - /*validator_weight=*/ 1, - encode_validator_key(&vk.public()), - encode_validator_pop(&vk.sign_pop()), - weight.try_into().context("overflow")?, - encode_attester_key(&key), - ), - false, - ); + txs.push(consensus_registry.add( + ethers::types::Address::random(), + /*validator_weight=*/ 1, + encode_validator_key(&vk.public()), + encode_validator_pop(&vk.sign_pop()), + weight.try_into().context("overflow")?, + encode_attester_key(&key), + ).send().await.context("send()")?.tx_hash()); } - - // Execute the update tx. - multicall.add_call(consensus_registry.commit_attester_committee(), false); - let res = multicall - .send() - .await - .context("send()")? - .await - .context("awaiting transaction")?; - println!("result = {res:?}"); + txs.push(consensus_registry.commit_attester_committee().send().await.context("send()")?.tx_hash()); + println!("{} transactions in progress",txs.len()); + for h in txs { + ethers::providers::PendingTransaction::new(h,&provider).await.context("awaiting transactions")?; + } + println!("done"); } Self::GetAttesterCommittee => { let attesters = consensus_registry.get_attester_committee().call().await?; @@ -241,7 +230,9 @@ impl Command { .context("decode_weighted_attester")?; let attesters = attester::Committee::new(attesters.into_iter()) .context("attester::Committee::new()")?; - println!("attesters = {attesters:?}"); + for a in attesters.iter() { + println!("{a:?}"); + } } } Ok(()) From 3493749de991a8e81a048467daa3593317e6213c Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Tue, 17 Sep 2024 15:56:08 +0200 Subject: [PATCH 14/22] works --- .../src/commands/consensus/mod.rs | 70 ++++++++++++++----- 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs index 923d3f204110..cee8c851698d 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs @@ -1,4 +1,5 @@ use std::{collections::HashMap, sync::Arc}; +use std::borrow::Borrow; /// Consensus registry contract operations. /// Includes code duplicated from `zksync_node_consensus::registry::abi`. @@ -6,11 +7,12 @@ use anyhow::Context as _; use common::config::global_config; use config::EcosystemConfig; use ethers::{ - contract::Multicall, - middleware::{Middleware as _, SignerMiddleware}, - providers::{Http, Provider, RawCall as _}, + abi::Detokenize, + contract::{Multicall,FunctionCall}, + middleware::{Middleware, NonceManagerMiddleware, SignerMiddleware}, + providers::{JsonRpcClient, Http, Provider, RawCall as _, PendingTransaction}, signers::{LocalWallet, Signer as _}, - types::BlockId, + types::{BlockId,H256}, }; use xshell::Shell; use zksync_consensus_crypto::ByteFmt; @@ -65,10 +67,42 @@ fn encode_validator_pop(pop: &validator::ProofOfPossession) -> abi::Bls12381Sign #[derive(clap::Subcommand, Debug)] pub enum Command { + /// Sets the attester committee in the consensus registry contract to + /// `consensus.genesis_spec.attesters` in general.yaml. SetAttesterCommittee, + /// Fetches the attester committee from the consensus registry contract. GetAttesterCommittee, } +/// Collection of sent transactions. +#[derive(Default)] +pub struct TxSet(Vec<(H256,&'static str)>); + +impl TxSet { + /// Sends a transactions and stores the transaction hash. + pub async fn send, D:Detokenize>(&mut self, name: &'static str, call: FunctionCall) -> anyhow::Result<()> { + let h = call.send().await.context(name)?.tx_hash(); + self.0.push((h,name)); + Ok(()) + } + + /// Waits for all stored transactions to complete. + pub async fn wait(self, provider: &Provider

) -> anyhow::Result<()> { + for (h,name) in self.0 { + async { + let status = PendingTransaction::new(h,provider).await + .context("await")? + .context("receipt missing")? + .status + .context("status missing")?; + anyhow::ensure!(status == 1.into(), "transaction failed"); + Ok(()) + }.await.context(name)?; + } + Ok(()) + } +} + impl Command { pub(crate) async fn run(self, shell: &Shell) -> anyhow::Result<()> { let ecosystem_config = EcosystemConfig::from_file(shell)?; @@ -109,11 +143,15 @@ impl Command { .await .context("get_block_number")?, ); - let signer = Arc::new(SignerMiddleware::new(provider.clone(), governor)); + let signer = SignerMiddleware::new(provider.clone(), governor.clone()); + // Allows us to send next transaction without waiting for the previous to complete. + let signer = NonceManagerMiddleware::new(signer, governor.address()); + let signer = Arc::new(signer); let contracts_cfg = chain_config .get_contracts_config() .context("get_contracts_config()")?; + // We use it to batch read calls. let mut multicall = Multicall::new_with_chain_id( signer.clone(), Some( @@ -177,7 +215,8 @@ impl Command { .context("nodes()")?; multicall.clear_calls(); - let mut txs = vec![]; + /// Update the state. + let mut txs = TxSet::default(); let mut want: HashMap<_, _> = want.iter().map(|a| (a.key.clone(), a.weight)).collect(); for (i, node) in nodes.into_iter().enumerate() { @@ -191,34 +230,31 @@ impl Command { }; if let Some(weight) = want.remove(&got.key) { if weight != got.weight { - txs.push(consensus_registry.change_attester_weight( + txs.send("changed_attester_weight", consensus_registry.change_attester_weight( node_owners[i], weight.try_into().context("overflow")?, - ).send().await.context("send()")?.tx_hash()); + )).await?; } if !node.attester_latest.active { - txs.push(consensus_registry.activate(node_owners[i]).send().await.context("send()")?.tx_hash()); + txs.send("activate", consensus_registry.activate(node_owners[i])).await?; } } else { - txs.push(consensus_registry.remove(node_owners[i]).send().await.context("send()")?.tx_hash()); + txs.send("remove", consensus_registry.remove(node_owners[i])).await?; } } for (key, weight) in want { let vk = validator::SecretKey::generate(); - txs.push(consensus_registry.add( + txs.send("add", consensus_registry.add( ethers::types::Address::random(), /*validator_weight=*/ 1, encode_validator_key(&vk.public()), encode_validator_pop(&vk.sign_pop()), weight.try_into().context("overflow")?, encode_attester_key(&key), - ).send().await.context("send()")?.tx_hash()); - } - txs.push(consensus_registry.commit_attester_committee().send().await.context("send()")?.tx_hash()); - println!("{} transactions in progress",txs.len()); - for h in txs { - ethers::providers::PendingTransaction::new(h,&provider).await.context("awaiting transactions")?; + )).await?; } + txs.send("commit_attester_committee", consensus_registry.commit_attester_committee()).await?; + txs.wait(&provider).await.context("wait()")?; println!("done"); } Self::GetAttesterCommittee => { From 94bc0a43b7752f32b266b3ec87797d642c93cb60 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Tue, 17 Sep 2024 16:05:49 +0200 Subject: [PATCH 15/22] zk fmt --- .../src/commands/consensus/mod.rs | 74 ++++++++++++------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs index cee8c851698d..7f87c7358239 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs @@ -1,5 +1,4 @@ -use std::{collections::HashMap, sync::Arc}; -use std::borrow::Borrow; +use std::{borrow::Borrow, collections::HashMap, sync::Arc}; /// Consensus registry contract operations. /// Includes code duplicated from `zksync_node_consensus::registry::abi`. @@ -8,11 +7,11 @@ use common::config::global_config; use config::EcosystemConfig; use ethers::{ abi::Detokenize, - contract::{Multicall,FunctionCall}, + contract::{FunctionCall, Multicall}, middleware::{Middleware, NonceManagerMiddleware, SignerMiddleware}, - providers::{JsonRpcClient, Http, Provider, RawCall as _, PendingTransaction}, + providers::{Http, JsonRpcClient, PendingTransaction, Provider, RawCall as _}, signers::{LocalWallet, Signer as _}, - types::{BlockId,H256}, + types::{BlockId, H256}, }; use xshell::Shell; use zksync_consensus_crypto::ByteFmt; @@ -76,28 +75,35 @@ pub enum Command { /// Collection of sent transactions. #[derive(Default)] -pub struct TxSet(Vec<(H256,&'static str)>); +pub struct TxSet(Vec<(H256, &'static str)>); impl TxSet { /// Sends a transactions and stores the transaction hash. - pub async fn send, D:Detokenize>(&mut self, name: &'static str, call: FunctionCall) -> anyhow::Result<()> { + pub async fn send, D: Detokenize>( + &mut self, + name: &'static str, + call: FunctionCall, + ) -> anyhow::Result<()> { let h = call.send().await.context(name)?.tx_hash(); - self.0.push((h,name)); + self.0.push((h, name)); Ok(()) } /// Waits for all stored transactions to complete. - pub async fn wait(self, provider: &Provider

) -> anyhow::Result<()> { - for (h,name) in self.0 { + pub async fn wait(self, provider: &Provider

) -> anyhow::Result<()> { + for (h, name) in self.0 { async { - let status = PendingTransaction::new(h,provider).await + let status = PendingTransaction::new(h, provider) + .await .context("await")? .context("receipt missing")? .status .context("status missing")?; anyhow::ensure!(status == 1.into(), "transaction failed"); Ok(()) - }.await.context(name)?; + } + .await + .context(name)?; } Ok(()) } @@ -230,30 +236,44 @@ impl Command { }; if let Some(weight) = want.remove(&got.key) { if weight != got.weight { - txs.send("changed_attester_weight", consensus_registry.change_attester_weight( - node_owners[i], - weight.try_into().context("overflow")?, - )).await?; + txs.send( + "changed_attester_weight", + consensus_registry.change_attester_weight( + node_owners[i], + weight.try_into().context("overflow")?, + ), + ) + .await?; } if !node.attester_latest.active { - txs.send("activate", consensus_registry.activate(node_owners[i])).await?; + txs.send("activate", consensus_registry.activate(node_owners[i])) + .await?; } } else { - txs.send("remove", consensus_registry.remove(node_owners[i])).await?; + txs.send("remove", consensus_registry.remove(node_owners[i])) + .await?; } } for (key, weight) in want { let vk = validator::SecretKey::generate(); - txs.send("add", consensus_registry.add( - ethers::types::Address::random(), - /*validator_weight=*/ 1, - encode_validator_key(&vk.public()), - encode_validator_pop(&vk.sign_pop()), - weight.try_into().context("overflow")?, - encode_attester_key(&key), - )).await?; + txs.send( + "add", + consensus_registry.add( + ethers::types::Address::random(), + /*validator_weight=*/ 1, + encode_validator_key(&vk.public()), + encode_validator_pop(&vk.sign_pop()), + weight.try_into().context("overflow")?, + encode_attester_key(&key), + ), + ) + .await?; } - txs.send("commit_attester_committee", consensus_registry.commit_attester_committee()).await?; + txs.send( + "commit_attester_committee", + consensus_registry.commit_attester_committee(), + ) + .await?; txs.wait(&provider).await.context("wait()")?; println!("done"); } From 0170682a23e4c03a4fc6fd640b56cd27800362d6 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Tue, 17 Sep 2024 16:18:07 +0200 Subject: [PATCH 16/22] moved file --- .../src/commands/{consensus/mod.rs => consensus.rs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename zk_toolbox/crates/zk_inception/src/commands/{consensus/mod.rs => consensus.rs} (99%) diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs similarity index 99% rename from zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs rename to zk_toolbox/crates/zk_inception/src/commands/consensus.rs index 7f87c7358239..1c809e33c9d8 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus/mod.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs @@ -221,7 +221,7 @@ impl Command { .context("nodes()")?; multicall.clear_calls(); - /// Update the state. + // Update the state. let mut txs = TxSet::default(); let mut want: HashMap<_, _> = want.iter().map(|a| (a.key.clone(), a.weight)).collect(); From 979625194d317c8494de2e4d0c71c640f4f13575 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Wed, 18 Sep 2024 12:47:08 +0200 Subject: [PATCH 17/22] json abi for ConsensusRegistry --- .github/workflows/ci-core-reusable.yml | 4 + bin/zkt | 2 +- .../zk_inception/abi/ConsensusRegistry.json | 1135 +++++++++++++++++ zk_toolbox/crates/zk_inception/build.rs | 2 +- .../zk_inception/src/commands/consensus.rs | 38 +- 5 files changed, 1168 insertions(+), 13 deletions(-) create mode 100644 zk_toolbox/crates/zk_inception/abi/ConsensusRegistry.json diff --git a/.github/workflows/ci-core-reusable.yml b/.github/workflows/ci-core-reusable.yml index cac585a00a87..3366234dc11f 100644 --- a/.github/workflows/ci-core-reusable.yml +++ b/.github/workflows/ci-core-reusable.yml @@ -341,6 +341,10 @@ jobs: ci_run sleep 5 + - name: Setup attester committee for the consensus chain + run: | + ci_run zk_inception consensus set-attester-committee --chain consensus &> ${{ env.INTEGRATION_TESTS_LOGS_DIR }}/consensus.log + - name: Run integration tests run: | PASSED_ENV_VARS="RUN_CONTRACT_VERIFICATION_TEST" \ diff --git a/bin/zkt b/bin/zkt index 4736401a29d6..36921dc4705b 100755 --- a/bin/zkt +++ b/bin/zkt @@ -7,7 +7,7 @@ if which zkup >/dev/null; then cargo uninstall zk_supervisor zkup -p .. --alias else - echo zkup does not installed, please install it https://github.com/matter-labs/zksync-era/tree/main/zk_toolbox/zkup + echo zkup is not installed, please install it https://github.com/matter-labs/zksync-era/tree/main/zk_toolbox/zkup cd ../zk_toolbox cargo install --path ./crates/zk_inception --force cargo install --path ./crates/zk_supervisor --force diff --git a/zk_toolbox/crates/zk_inception/abi/ConsensusRegistry.json b/zk_toolbox/crates/zk_inception/abi/ConsensusRegistry.json new file mode 100644 index 000000000000..3826d258072a --- /dev/null +++ b/zk_toolbox/crates/zk_inception/abi/ConsensusRegistry.json @@ -0,0 +1,1135 @@ +{ + "_format": "hh-zksolc-artifact-1", + "contractName": "ConsensusRegistry", + "sourceName": "contracts/ConsensusRegistry.sol", + "abi": [ + { + "inputs": [], + "name": "AttesterPubKeyExists", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInputBLS12_381PublicKey", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInputBLS12_381Signature", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInputNodeOwnerAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInputSecp256k1PublicKey", + "type": "error" + }, + { + "inputs": [], + "name": "NodeOwnerDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "NodeOwnerExists", + "type": "error" + }, + { + "inputs": [], + "name": "NodeOwnerNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "UnauthorizedOnlyOwnerOrNodeOwner", + "type": "error" + }, + { + "inputs": [], + "name": "ValidatorPubKeyExists", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "commit", + "type": "uint32" + } + ], + "name": "AttestersCommitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "nodeOwner", + "type": "address" + } + ], + "name": "NodeActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "nodeOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "validatorWeight", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "b", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "c", + "type": "bytes32" + } + ], + "indexed": false, + "internalType": "struct IConsensusRegistry.BLS12_381PublicKey", + "name": "validatorPubKey", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes16", + "name": "b", + "type": "bytes16" + } + ], + "indexed": false, + "internalType": "struct IConsensusRegistry.BLS12_381Signature", + "name": "validatorPoP", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "attesterWeight", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bytes1", + "name": "tag", + "type": "bytes1" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + } + ], + "indexed": false, + "internalType": "struct IConsensusRegistry.Secp256k1PublicKey", + "name": "attesterPubKey", + "type": "tuple" + } + ], + "name": "NodeAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "nodeOwner", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes1", + "name": "tag", + "type": "bytes1" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + } + ], + "indexed": false, + "internalType": "struct IConsensusRegistry.Secp256k1PublicKey", + "name": "newPubKey", + "type": "tuple" + } + ], + "name": "NodeAttesterKeyChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "nodeOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newWeight", + "type": "uint32" + } + ], + "name": "NodeAttesterWeightChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "nodeOwner", + "type": "address" + } + ], + "name": "NodeDeactivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "nodeOwner", + "type": "address" + } + ], + "name": "NodeDeleted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "nodeOwner", + "type": "address" + } + ], + "name": "NodeRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "nodeOwner", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "b", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "c", + "type": "bytes32" + } + ], + "indexed": false, + "internalType": "struct IConsensusRegistry.BLS12_381PublicKey", + "name": "newPubKey", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes16", + "name": "b", + "type": "bytes16" + } + ], + "indexed": false, + "internalType": "struct IConsensusRegistry.BLS12_381Signature", + "name": "newPoP", + "type": "tuple" + } + ], + "name": "NodeValidatorKeyChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "nodeOwner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newWeight", + "type": "uint32" + } + ], + "name": "NodeValidatorWeightChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "commit", + "type": "uint32" + } + ], + "name": "ValidatorsCommitted", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_nodeOwner", + "type": "address" + } + ], + "name": "activate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_nodeOwner", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_validatorWeight", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "b", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "c", + "type": "bytes32" + } + ], + "internalType": "struct IConsensusRegistry.BLS12_381PublicKey", + "name": "_validatorPubKey", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes16", + "name": "b", + "type": "bytes16" + } + ], + "internalType": "struct IConsensusRegistry.BLS12_381Signature", + "name": "_validatorPoP", + "type": "tuple" + }, + { + "internalType": "uint32", + "name": "_attesterWeight", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bytes1", + "name": "tag", + "type": "bytes1" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + } + ], + "internalType": "struct IConsensusRegistry.Secp256k1PublicKey", + "name": "_attesterPubKey", + "type": "tuple" + } + ], + "name": "add", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "attesterPubKeyHashes", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "attestersCommit", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_nodeOwner", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes1", + "name": "tag", + "type": "bytes1" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + } + ], + "internalType": "struct IConsensusRegistry.Secp256k1PublicKey", + "name": "_pubKey", + "type": "tuple" + } + ], + "name": "changeAttesterKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_nodeOwner", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_weight", + "type": "uint32" + } + ], + "name": "changeAttesterWeight", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_nodeOwner", + "type": "address" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "b", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "c", + "type": "bytes32" + } + ], + "internalType": "struct IConsensusRegistry.BLS12_381PublicKey", + "name": "_pubKey", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes16", + "name": "b", + "type": "bytes16" + } + ], + "internalType": "struct IConsensusRegistry.BLS12_381Signature", + "name": "_pop", + "type": "tuple" + } + ], + "name": "changeValidatorKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_nodeOwner", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_weight", + "type": "uint32" + } + ], + "name": "changeValidatorWeight", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "commitAttesterCommittee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "commitValidatorCommittee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_nodeOwner", + "type": "address" + } + ], + "name": "deactivate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAttesterCommittee", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bytes1", + "name": "tag", + "type": "bytes1" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + } + ], + "internalType": "struct IConsensusRegistry.Secp256k1PublicKey", + "name": "pubKey", + "type": "tuple" + } + ], + "internalType": "struct IConsensusRegistry.CommitteeAttester[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getValidatorCommittee", + "outputs": [ + { + "components": [ + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "b", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "c", + "type": "bytes32" + } + ], + "internalType": "struct IConsensusRegistry.BLS12_381PublicKey", + "name": "pubKey", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes16", + "name": "b", + "type": "bytes16" + } + ], + "internalType": "struct IConsensusRegistry.BLS12_381Signature", + "name": "proofOfPossession", + "type": "tuple" + } + ], + "internalType": "struct IConsensusRegistry.CommitteeValidator[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_initialOwner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "nodeOwners", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nodes", + "outputs": [ + { + "internalType": "uint32", + "name": "attesterLastUpdateCommit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "validatorLastUpdateCommit", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "nodeOwnerIdx", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "bool", + "name": "removed", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bytes1", + "name": "tag", + "type": "bytes1" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + } + ], + "internalType": "struct IConsensusRegistry.Secp256k1PublicKey", + "name": "pubKey", + "type": "tuple" + } + ], + "internalType": "struct IConsensusRegistry.AttesterAttr", + "name": "attesterLatest", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "bool", + "name": "removed", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bytes1", + "name": "tag", + "type": "bytes1" + }, + { + "internalType": "bytes32", + "name": "x", + "type": "bytes32" + } + ], + "internalType": "struct IConsensusRegistry.Secp256k1PublicKey", + "name": "pubKey", + "type": "tuple" + } + ], + "internalType": "struct IConsensusRegistry.AttesterAttr", + "name": "attesterSnapshot", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "bool", + "name": "removed", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "b", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "c", + "type": "bytes32" + } + ], + "internalType": "struct IConsensusRegistry.BLS12_381PublicKey", + "name": "pubKey", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes16", + "name": "b", + "type": "bytes16" + } + ], + "internalType": "struct IConsensusRegistry.BLS12_381Signature", + "name": "proofOfPossession", + "type": "tuple" + } + ], + "internalType": "struct IConsensusRegistry.ValidatorAttr", + "name": "validatorLatest", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bool", + "name": "active", + "type": "bool" + }, + { + "internalType": "bool", + "name": "removed", + "type": "bool" + }, + { + "internalType": "uint32", + "name": "weight", + "type": "uint32" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "b", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "c", + "type": "bytes32" + } + ], + "internalType": "struct IConsensusRegistry.BLS12_381PublicKey", + "name": "pubKey", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "a", + "type": "bytes32" + }, + { + "internalType": "bytes16", + "name": "b", + "type": "bytes16" + } + ], + "internalType": "struct IConsensusRegistry.BLS12_381Signature", + "name": "proofOfPossession", + "type": "tuple" + } + ], + "internalType": "struct IConsensusRegistry.ValidatorAttr", + "name": "validatorSnapshot", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numNodes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_nodeOwner", + "type": "address" + } + ], + "name": "remove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "validatorPubKeyHashes", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "validatorsCommit", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x00020000000000020015000000000002000100000001035500000000030100190000006003300270000004ad0030019d0000008008000039000000400080043f000004ad033001970000000102200190000000200000c13d000000040230008c000011c30000413d000000000201043b000000e002200270000004af0420009c000000280000a13d000004b00420009c0000023f0000a13d000004b10420009c000002b60000a13d000004b20420009c000002e10000213d000004b50420009c000005590000613d000004b60120009c000011c30000c13d0000000001000416000000000101004b000011c30000c13d0000006501000039000004f40000013d0000000001000416000000000101004b000011c30000c13d000000200100003900000100001004430000012000000443000004ae01000041000012b00001042e000004c10420009c000001330000213d000004c90420009c0000024c0000213d000004cd0420009c000003970000613d000004ce0420009c000003040000613d000004cf0220009c000011c30000c13d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b000d00000001001d000004d00110009c000011c30000213d0000003301000039000000000101041a000004d0021001970000000001000411000000000212004b000000450000613d0000000d0110006b000003b50000c13d0000000d0100002900000000001004350000009801000039000c00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000000610000c13d0000000902100039000000000202041a000000000202004b000000610000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b02000039000000000402041a0000002003400270000004ad03300197000000000701043b000000000107041a0000002005100270000004ad05500197000000000353004b0000000d030000390000000703002039000004ad04400197000004ad05100197000000000654004b000000040600003900000001060020390000000006760019000000000606041a0000ff000660019000000c540000613d0000000003730019000000000303041a0000ff000330019000000c540000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000b00000007001d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000009cd0000613d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000b01000029000000000101041a000a00000001001d00000000003004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000a02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000b020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000005180310009c0000102e0000813d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000a0100000000920000000a0220017f000000000021041b0000000b040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000a0220017f000000000021041b0000000d0100002900000000001004350000000c01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000004b70000013d000004c20420009c0000026f0000213d000004c60420009c000003a20000613d000004c70420009c0000034b0000613d000004c80220009c000011c30000c13d0000000002000416000000000202004b000011c30000c13d000000040230008a000000400220008c000011c30000413d0000000402100370000000000202043b000d00000002001d000004d00220009c000011c30000213d0000002401100370000000000101043b000c00000001001d000004ad0110009c000011c30000213d0000003301000039000000000101041a000004d0011001970000000002000411000000000121004b0000067a0000c13d0000000d0100002900000000001004350000009801000039000b00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b0000016d0000c13d0000000902100039000000000202041a000000000202004b0000016d0000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b02000039000000000302041a0000002004300270000004ad04400197000000000701043b000000000107041a0000002005100270000004ad05500197000000000454004b0000000d050000390000000705002039000004ad03300197000004ad04100197000000000643004b000000040600003900000001060020390000000006760019000000000606041a0000ff0006600190000a00000007001d00000f8d0000613d0000000005750019000000000505041a0000ff000550019000000f8d0000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000009cd0000613d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000a01000029000000000101041a000c00000001001d00000000003004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000c02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000a020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000c0100000000920000000c0220017f000000000021041b0000000a040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000c0220017f000000000021041b0000000d0100002900000000001004350000000b01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000011940000013d000004ba0420009c0000028f0000213d000004be0120009c000005400000613d000004bf0120009c000004f70000613d000004c00120009c000011c30000c13d0000000001000416000000000101004b000011c30000c13d0000003301000039000004f40000013d000004ca0420009c000003b90000613d000004cb0420009c000003510000613d000004cc0120009c000011c30000c13d0000000001000416000000000101004b000011c30000c13d0000003301000039000000000101041a000004d0011001970000000002000411000000000121004b0000067a0000c13d0000009b01000039000000000201041a000004ad03200197000004ad0430009c0000054f0000613d000004f6022001970000000103300039000000000223019f000000000021041b000000800030043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004fd011001c70000800d0200003900000001030000390000050404000041000010190000013d000004c30420009c000004e60000613d000004c40420009c000003760000613d000004c50120009c000011c30000c13d0000000001000416000000000101004b000011c30000c13d0000003301000039000000000201041a000004d0052001970000000003000411000000000335004b0000067a0000c13d0000006503000039000000000403041a000004d104400197000000000043041b000004d102200197000000000021041b000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d2011001c70000800d020000390000000303000039000004dc040000410000000006000019000010190000013d000004bb0420009c000005530000613d000004bc0420009c000005030000613d000004bd0220009c000011c30000c13d0000000002000416000000000202004b000011c30000c13d000000040230008a000000600220008c000011c30000413d0000000402100370000000000202043b000d00000002001d000004d00220009c000011c30000213d0000003302000039000000000202041a000004d0032001970000000002000411000000000323004b000002a80000613d0000000d0220006b000003b50000c13d0000002402100370000000000302043b000004f402300197000c00000003001d000000000232004b000011c30000c13d0000000c0200006b000009280000c13d0000004401100370000000000101043b000000000101004b000009280000c13d0000050e01000041000003b60000013d000004b70420009c000006830000613d000004b80420009c000005760000613d000004b90220009c000011c30000c13d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b000d00000001001d000004d00110009c000011c30000213d000000000300041a000bff0000300194000007c80000c13d000000ff0130019000000000020000190000000102006039000e00000002001d00000000020004150000000e0220008a00000020022000c9000000000101004b000007cc0000c13d000001000100008a000000000113016f00000001011001bf000004db02000041000000000121016f00000100011001bf0000000003000019000000000010041b0000000d06000029000000000106004b000009650000c13d000000400100043d000004df02000041000009460000013d000004b30420009c0000056c0000613d000004b40220009c000011c30000c13d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000601043b000004d00160009c000011c30000213d0000003301000039000000000101041a000004d0051001970000000001000411000000000115004b0000067a0000c13d0000006501000039000000000201041a000004d102200197000000000262019f000000000021041b000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d2011001c70000800d020000390000000303000039000004d304000041000010190000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b000004d00210009c000011c30000213d00000000001004350000009801000039000000200010043f0000004002000039000000000100001912af128f0000040f0000000002010019000d00000002001d000000000102041a000900000001001d000000010120003912af11d30000040f000c00000001001d0000000d01000029000000040110003912af11d30000040f000b00000001001d0000000d01000029000000070110003912af11fc0000040f0000000d020000290000000d02200039000a00000001001d000000000102001912af11fc0000040f00000009050000290000002002500270000004ad02200197000000400400043d000d00000004001d000000200340003900000000002304350000004002500270000004ad0220019700000040034000390000000000230435000004ad025001970000000000240435000900000001001d00000060024000390000000c0100002912af12360000040f0000000d0100002900000100021000390000000b0100002912af12360000040f0000000d01000029000001a0021000390000000a0100002912af124f0000040f0000000d01000029000002a002100039000000090100002912af124f0000040f000004ad010000410000000d03000029000004ad0230009c000000000301801900000040013002100000051b011001c7000012b00001042e0000000001000416000000000101004b000011c30000c13d0000009b01000039000000000101041a000005720000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000001400220008c000011c30000413d0000000402100370000000000202043b000d00000002001d000004d00220009c000011c30000213d0015000d0000002d0000002402100370000000000202043b000c00000002001d000004ad0220009c000011c30000213d0014000c0000002d001300440000003d001200a40000003d000000e402100370000000000202043b000b00000002001d000004ad0220009c000011c30000213d0011000b0000002d001001040000003d0000003302000039000000000202041a000004d0022001970000000003000411000000000232004b0000067a0000c13d0000000d0200006b000009d10000c13d000004df01000041000003b60000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000c00220008c000011c30000413d0000000402100370000000000202043b000d00000002001d000004d00220009c000011c30000213d0000003302000039000000000202041a000004d0032001970000000002000411000000000323004b000003890000613d0000000d0220006b000003b50000c13d0000002402100370000000000202043b000000000202004b000007f00000c13d0000004402100370000000000202043b000000000202004b000007f00000c13d0000006402100370000000000202043b000000000202004b000007f00000c13d0000051101000041000003b60000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b00000000001004350000009a01000039000005630000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b000d00000001001d000004d00110009c000011c30000213d0000003301000039000000000101041a000004d0021001970000000001000411000000000212004b000006c80000613d0000000d0110006b000006c80000613d0000051501000041000000800010043f0000050f01000041000012b1000104300000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b000d00000001001d000004d00110009c000011c30000213d0000003301000039000000000101041a000004d0011001970000000002000411000000000121004b0000067a0000c13d0000000d0100002900000000001004350000009801000039000c00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000003e60000c13d0000000902100039000000000202041a000000000202004b000003e60000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b02000039000000000402041a0000002003400270000004ad03300197000000000701043b000000000107041a0000002005100270000004ad05500197000000000353004b0000000d030000390000000703002039000004ad04400197000004ad05100197000000000654004b000000040600003900000001060020390000000006760019000000000606041a0000ff000660019000000d3a0000613d0000000003730019000000000303041a0000ff000330019000000d3a0000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000b00000007001d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000009cd0000613d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000b01000029000000000101041a000a00000001001d00000000003004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000a02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000b020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000a0100000000920000000a0220017f000000000021041b0000000b040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000a0220017f000000000021041b0000000d0100002900000000001004350000000c01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000001041b0000000102100039000000000002041b0000000202100039000000000002041b0000000302100039000000000002041b0000000402100039000000000002041b0000000502100039000000000002041b0000000602100039000000000002041b0000000702100039000000000002041b0000000802100039000000000002041b0000000902100039000000000002041b0000000a02100039000000000002041b0000000b02100039000000000002041b0000000c02100039000000000002041b0000000d02100039000000000002041b0000000e02100039000000000002041b0000000f02100039000000000002041b0000001002100039000000000002041b0000001102100039000000000002041b0000001201100039000000000001041b0000000001000414000004ad0210009c000004ad01008041000000c001100210000004d2011001c70000800d020000390000000203000039000004e80400004100000dae0000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b0000009702000039000000000302041a000000000331004b000011c30000813d0000000000200435000004e301100041000000000101041a000004d001100197000005730000013d0000000001000416000000000101004b000011c30000c13d0000006501000039000000000101041a000004d0021001970000000001000411000000000212004b000006bc0000c13d12af12740000040f0000000001000019000012b00001042e0000000001000416000000000101004b000011c30000c13d0000009701000039000b00000001001d000000000101041a000c00000001001d000004f20110009c0000102e0000213d0000000c010000290000000502100210000000bf01200039000000200300008a000000000131016f000004f20310009c0000102e0000213d000000400010043f0000000c03000029000000800030043f000000000303004b0000000003000019000008ec0000c13d000000800030043f00000020020000390000000002210436000000800300043d00000000003204350000004002100039000000000403004b000006b20000613d00000080040000390000000005000019000000200440003900000000060404330000000087060434000004ad077001970000000007720436000000000808043300000000a9080434000000000097043500000000070a0433000000400920003900000000007904350000004007800039000000000707043300000060082000390000000000780435000000400660003900000000060604330000008007200039000000008606043400000000006704350000000006080433000004ed06600197000000a0072000390000000000670435000000c0022000390000000105500039000000000635004b000005230000413d000006b20000013d0000000001000416000000000101004b000011c30000c13d0000003301000039000000000101041a000004d0011001970000000002000411000000000121004b0000067a0000c13d0000009b01000039000000000201041a0000002003200270000004ad03300197000004ad0430009c000007b60000c13d000005160100004100000000001004350000001101000039000010310000013d0000000001000416000000000101004b000011c30000c13d0000009701000039000000000101041a000005730000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b00000000001004350000009901000039000000200010043f0000004002000039000000000100001912af128f0000040f000000000101041a000000ff011001900000000001000019000000010100c039000005730000013d0000000001000416000000000101004b000011c30000c13d0000009b01000039000000000101041a0000002001100270000004ad01100197000000800010043f000004d401000041000012b00001042e0000000002000416000000000202004b000011c30000c13d000000040230008a000000400220008c000011c30000413d0000000402100370000000000202043b000d00000002001d000004d00220009c000011c30000213d0000002401100370000000000101043b000c00000001001d000004ad0110009c000011c30000213d0000003301000039000000000101041a000004d0011001970000000002000411000000000121004b0000067a0000c13d0000000d0100002900000000001004350000009801000039000b00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000005a80000c13d0000000902100039000000000202041a000000000202004b000005a80000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000701043b0000009b01000039000000000301041a000004ad04300197000000000207041a000004ad05200197000000000454004b000000040500003900000001050020390000002003300270000004ad033001970000002004200270000004ad044001970000000006750019000000000543004b0000000d050000390000000705002039000000000606041a0000ff000660019000000fcd0000613d0000000005750019000000000505041a0000ff000550019000000fcd0000613d000c00000007001d0000009701000039000000000401041a000000000304004b0000054f0000613d000004e203400041000000000303041a000004d0033001970000004002200270000004ad02200197000000000424004b00000e8e0000a13d000004e302200041000000000402041a000004d104400197000000000434019f000000000042041b000000000201041a000000000402004b000009cd0000613d000004e204200041000000000504041a000004d105500197000000000054041b000000010220008a000000000021041b0000000c01000029000000000101041a000a00000001001d00000000003004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000a02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000c020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000a0100000000920000000a0220017f000000000021041b0000000c040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000a0220017f000000000021041b0000000d0100002900000000001004350000000b01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000011940000013d000004d901000041000000800010043f0000002001000039000000840010043f000000a40010043f0000051201000041000000c40010043f0000051301000041000012b1000104300000000001000416000000000101004b000011c30000c13d0000009701000039000b00000001001d000000000101041a000c00000001001d000004f20110009c0000102e0000213d0000000c010000290000000502100210000000bf01200039000000200300008a000000000131016f000004f20310009c0000102e0000213d000000400010043f0000000c03000029000000800030043f000000000303004b0000000003000019000009100000c13d000000800030043f00000020020000390000000002210436000000800300043d00000000003204350000004002100039000000000403004b000006b20000613d0000000004000019000000200880003900000000050804330000000065050434000004ad05500197000000000552043600000000060604330000000076060434000004f406600197000000000065043500000000050704330000004006200039000000000056043500000060022000390000000104400039000000000534004b000006a20000413d0000000002120049000004ad03000041000004ad0420009c0000000002038019000004ad0410009c000000000103801900000040011002100000006002200210000000000112019f000012b00001042e000004d901000041000000800010043f0000002001000039000000840010043f0000002901000039000000a40010043f000004f901000041000000c40010043f000004fa01000041000000e40010043f000004fb01000041000012b1000104300000000d0100002900000000001004350000009801000039000c00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000006e40000c13d0000000902100039000000000202041a000000000202004b000006e40000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b02000039000000000402041a0000002003400270000004ad03300197000000000701043b000000000107041a0000002005100270000004ad05500197000000000353004b0000000d030000390000000703002039000004ad04400197000004ad05100197000000000654004b000000040600003900000001060020390000000006760019000000000606041a0000ff000660019000000cc80000613d0000000003730019000000000303041a0000ff000330019000000cc80000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000b00000007001d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000009cd0000613d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000b01000029000000000101041a000a00000001001d00000000003004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000a02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000b020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000a0100000000920000000a0220017f000000000021041b0000000b040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000a0220017f000000000021041b0000000d0100002900000000001004350000000c01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000011940000013d000004ef022001970000002003300210000004fc03300041000004ee04300197000000000224019f000000000021041b0000002001300270000000800010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004fd011001c70000800d020000390000000103000039000004fe04000041000010190000013d00000000020004150000000f0220008a00000020022000c9000f00000000001d000c00000002001d000a00000003001d000004d501000041000000000010043900000000010004100000000400100443000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d6011001c7000080020200003912af12aa0000040f0000000102200190000007fd0000613d000000000101043b000000000101004b0000094d0000c13d0000000a01000029000000ff0110018f000000010110008c000000000100001900000001010060390000000c020000290000000502200270000000000201001f000009500000c13d000001000100008a000000000200041a000000000112016f000000010300003900000001011001bf0000000b0200006b000002da0000c13d000002d60000013d0000008402100370000000000202043b000000000202004b000007fe0000c13d000000a401100370000000000101043b000004ed02100197000000000212004b000011c30000c13d000004ff0110009c000007fe0000813d0000051001000041000003b60000013d000000000001042f0000000d0100002900000000001004350000009801000039000c00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b0000081a0000c13d0000000902100039000000000202041a000000000202004b0000081a0000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b06000039000000000306041a0000002002300270000004ad02200197000000000501043b000000000105041a0000002004100270000004ad04400197000000000242004b0000000d020000390000000702002039000004ad03300197000004ad04100197000000000343004b000000040300003900000001030020390000000003530019000000000303041a0000ff0003300190000b00000005001d00000e920000613d0000000002520019000000000202041a0000ff000220019000000e920000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000009cd0000613d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000b01000029000000000101041a000a00000001001d00000000003004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000a02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000b020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000a0100000000920000000a0220017f000000000021041b0000000b040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000a0220017f000000000021041b0000000d0100002900000000001004350000000c01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000011940000013d000004e60310009c0000102e0000213d00000000030000190000006004100039000000400040043f0000000004010436000000400500043d000004e60650009c0000102e0000213d0000006006500039000000400060043f000000400650003900000000000604350000002006500039000000000006043500000000000504350000000000540435000000400400043d000004f30540009c0000102e0000213d0000004005400039000000400050043f00000020054000390000000000050435000000000004043500000040051000390000000000450435000000a00430003900000000001404350000002003300039000000000123004b00000e150000813d000000400100043d000004e60410009c000008ef0000a13d0000102e0000013d000004f30310009c0000102e0000213d00000000030000190000004004100039000000400040043f0000000004010436000000400500043d000004f30650009c0000102e0000213d0000004006500039000000400060043f0000002006500039000000000006043500000000000504350000000000540435000000a00430003900000000001404350000002003300039000000000123004b00000daf0000813d000000400100043d000004f30410009c000009130000a13d0000102e0000013d0000000d0100002900000000001004350000009801000039000b00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000009920000c13d0000000902100039000000000202041a000000000202004b000009920000c13d0000000a01100039000000000101041a000000000101004b000009920000c13d000000400100043d0000051a020000410000000000210435000004ad02000041000004ad0310009c00000000010280190000004001100210000004e0011001c7000012b1000104300000000c010000290000000501100270000000000100001f000000400100043d0000006402100039000004d70300004100000000003204350000004402100039000004d803000041000000000032043500000024021000390000002e030000390000000000320435000004d9020000410000000000210435000000040210003900000020030000390000000000320435000004ad02000041000004ad0310009c00000000010280190000004001100210000004da011001c7000012b100010430000c00000003001d0000006501000039000000000201041a000004d102200197000000000021041b0000003301000039000000000201041a000004d103200197000000000363019f000000000031041b000004ad010000410000000003000414000004ad0430009c0000000003018019000000c001300210000004d2011001c7000004d0052001970000800d020000390000000303000039000004dc0400004112af12a50000040f0000000101200190000011c30000613d0000000c0100006b0000101c0000c13d000004db01000041000000000200041a000000000112016f000000000010041b0000000103000039000000400100043d0000000000310435000004ad020000410000000004000414000004ad0540009c0000000004028019000004ad0510009c00000000010280190000004001100210000000c002400210000000000112019f000004dd011001c70000800d02000039000004de04000041000010190000013d0000000d0100002900000000001004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b02000039000900000002001d000000000302041a0000002002300270000004ad02200197000000000501043b000000000105041a0000002004100270000004ad04400197000000000242004b0000000d020000390000000702002039000004ad03300197000004ad04100197000000000343004b000000040300003900000001030020390000000003530019000000000303041a0000ff0003300190000a00000005001d0000101e0000613d0000000002520019000000000202041a0000ff00022001900000101e0000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000010fd0000c13d000005160100004100000000001004350000003101000039000010310000013d0000004402100370000000000202043b000000000202004b000009dd0000c13d0000006402100370000000000202043b000000000202004b000009dd0000c13d0000008402100370000000000202043b000000000202004b000003950000613d000000a402100370000000000202043b000000000202004b000009e80000c13d000000c402100370000000000202043b000004ed03200197000000000323004b000011c30000c13d000004ec0220009c000007fb0000a13d0000010402100370000000000202043b000004f403200197000000000323004b000011c30000c13d000005050220009c000009f30000213d0000012401100370000000000101043b000000000101004b000002b40000613d0000000d0100002900000000001004350000009801000039000a00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000010f70000c13d0000000902100039000000000202041a000000000202004b000010f70000c13d0000000a01100039000000000101041a000000000101004b000010f70000c13d00000001010003670000010402100370000000000302043b000004f402300197000000000232004b000011c30000c13d0000012401100370000000000201043b000000400100043d000000400410003900000000002404350000002002100039000000000032043500000040030000390000000000310435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000900000001001d00000000001004350000009901000039000800000001001d000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000400200043d000000000101043b000000000101041a000000ff01100190000011cb0000c13d00000001010003670000004403100370000000000303043b0000006404100370000000000404043b0000008401100370000000000101043b00000060052000390000000000150435000000400120003900000000004104350000002001200039000000000031043500000060030000390000000000320435000004e70320009c0000102e0000213d0000008003200039000000400030043f000004ad04000041000004ad0310009c000000000104801900000040011002100000000002020433000004ad0320009c00000000020480190000006002200210000000000112019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000700000001001d00000000001004350000009a01000039000600000001001d000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000101041a000000ff01100190000011c50000c13d0000009703000039000000000203041a000004ad01200197000004f20420009c0000102e0000213d0000000104200039000000000043041b0000000000300435000004e302200041000000000302041a000004d1033001970000000d033001af000000000032041b000000400200043d000004e70320009c0000102e0000213d0000008003200039000000400030043f00000040032000390000000b0400002900000000004304350000000107000039000000000372043600000000000304350000000008000031000001040380008a0000050804000041000000400530008c000000000500001900000000050440190000050803300197000000000603004b000000000400a019000005080330009c000000000405c019000000000304004b000011c30000c13d000000400300043d000004f30430009c0000102e0000213d0000004004300039000000400040043f00000001060003670000010404600370000000000404043b000004f405400197000000000545004b000011c30000c13d00000000044304360000012405600370000000000505043b000000000054043500000060042000390000000000340435000000400400043d000004f30340009c0000102e0000213d0000004003400039000000400030043f000000200340003900000000000304350000000000040435000000400300043d000004e70530009c0000102e0000213d0000008005300039000000400050043f00000060053000390000000000450435000000400430003900000000000404350000002004300039000000000004043500000000000304350000009b04000039000000000404041a000000400500043d000004f80950009c0000102e0000213d000000a009500039000000400090043f00000040095000390000000c0a0000290000000000a90435000000440880008a0000050809000041000000600a80008c000000000a000019000000000a0940190000050808800197000000000b08004b000000000900a019000005080880009c00000000090ac01900000000077504360000000000070435000000000709004b000011c30000c13d000000400700043d000004e60870009c0000102e0000213d0000006008700039000000400080043f0000004408600370000000000808043b00000000088704360000006409600370000000000909043b00000000009804350000008408600370000000000808043b0000004009700039000000000089043500000060085000390000000000780435000000400700043d000004f30870009c0000102e0000213d0000004008700039000000400080043f000000a408600370000000000808043b0000000008870436000000c406600370000000000606043b000004ed09600197000000000969004b000011c30000c13d000000000068043500000080065000390000000000760435000000400600043d000004e60760009c0000102e0000213d0000006007600039000000400070043f00000040076000390000000000070435000000200760003900000000000704350000000000060435000000400800043d000004f30780009c0000102e0000213d0000004007800039000000400070043f000000200780003900000000000704350000000000080435000000400700043d000004f80970009c0000102e0000213d000000a009700039000000400090043f000000800970003900000000008904350000006008700039000000000068043500000040067000390000000000060435000000200670003900000000000604350000000000070435000000400600043d000c00000006001d000005090660009c0000102e0000213d0000000c08000029000000e006800039000000400060043f000000c006800039000b00000006001d0000000000760435000000a006800039000500000006001d00000000005604350000008005800039000400000005001d00000000003504350000006003800039000300000003001d00000000002304350000004002800039000200000002001d0000000000120435000004ad0140019700000000021804360000002001400270000004ad01100197000100000002001d00000000001204350000000d0100002900000000001004350000000a01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000c020000290000000002020433000004ad02200197000000000101043b000000000301041a0000050a03300197000000000223019f000000010300002900000000030304330000002003300210000004ee03300197000000000232019f000000020300002900000000030304330000004003300210000004e403300197000000000232019f000000000021041b0000000102100039000000000302041a0000050b03300197000000030400002900000000040404330000000065040434000000000505004b000000010330c1bf0000000005060433000000000505004b000001000330c1bf000000400540003900000000050504330000001005500210000004eb05500197000000000353019f000000000032041b00000060024000390000000203100039000d010000000092000000000403041a0000000d0440017f00000000020204330000000052020434000000f802200270000000000224019f000000000023041b00000000020504330000000303100039000000000023041b0000000402100039000000000302041a0000050b03300197000000040400002900000000040404330000000065040434000000000505004b000000010330c1bf0000000005060433000000000505004b000001000330c1bf000000400540003900000000050504330000001005500210000004eb05500197000000000353019f000000000032041b0000000502100039000000000302041a0000000d0330017f000000600440003900000000040404330000000054040434000000f804400270000000000343019f000000000032041b00000000020504330000000603100039000000000023041b0000000702100039000000000302041a0000050b03300197000000050400002900000000040404330000000065040434000000000505004b000000010330c1bf0000000005060433000000000505004b000001000330c1bf000000400540003900000000050504330000001005500210000004eb05500197000000000353019f000000000032041b0000006002400039000000000202043300000008031000390000000065020434000000000053041b00000000030604330000000905100039000000000035041b000000400220003900000000020204330000000a03100039000000000023041b000000800240003900000000020204330000000b031000390000000042020434000000000023041b000000000204043300000080022002700000000c03100039000000000403041a000004ed04400197000000000224019f000000000023041b0000000d02100039000000000302041a0000050b033001970000000b0400002900000000040404330000000065040434000000000505004b000000010330c1bf0000000005060433000000000505004b000001000330c1bf000000400540003900000000050504330000001005500210000004eb05500197000000000353019f000000000032041b000000600240003900000000020204330000000e031000390000000065020434000000000053041b00000000030604330000000f05100039000000000035041b000000400220003900000000020204330000001003100039000000000023041b0000008002400039000000000202043300000011031000390000000042020434000000000023041b000000120110003900000000020404330000008002200270000000000301041a000004ed03300197000000000223019f000000000021041b000000090100002900000000001004350000000801000029000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000d0220017f00000001022001bf000000000021041b000000070100002900000000001004350000000601000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000d0220017f00000001022001bf000000000021041b000004d001000041000000150510017f000004ad01000041000000140310017f0000001104000029000000100200002900000012060000290000001307000029000000400100043d00000000083104360000000103000367000000000973034f000000000909043b00000000009804350000002008700039000000000883034f000000000808043b000000400910003900000000008904350000004007700039000000000773034f000000000707043b00000060081000390000000000780435000000000763034f000000000707043b000000800810003900000000007804350000002006600039000000000663034f000000000606043b000004ed07600197000000000767004b000011c30000c13d000004ad04400197000000c0071000390000000000470435000000a0041000390000000000640435000000000423034f000000000404043b000004f406400197000000000646004b000011c30000c13d000000e00610003900000000004604350000002002200039000000000223034f000000000202043b00000100031000390000000000230435000004ad020000410000000003000414000004ad0430009c0000000003028019000004ad0410009c00000000010280190000004001100210000000c002300210000000000112019f0000050c011001c70000800d0200003900000002030000390000050d04000041000010190000013d0000000103700039000000000154004b00000c7c0000a13d0000000401700039000000000401041a000001000500008a000000000454016f000000000603041a000000ff06600190000000010440c1bf000000000041041b000004e906000041000000000464016f000000000603041a0000ff0006600190000001000440c1bf000000000041041b000004ea04400197000000000603041a000004eb06600197000000000464019f000000000041041b0000000501700039000000000401041a000000000454016f0000000205700039000000000505041a000000ff0550018f000000000454019f000000000041041b0000000301700039000000000101041a0000000604700039000000000014041b000000000102041a000004ad01100197000000000407041a000004f604400197000000000114019f000000000017041b000000000403041a000001000100008a000000000414016f00000001044001bf000000000043041b0000000703700039000000000402041a0000002004400270000004ad04400197000000000507041a0000002005500270000004ad05500197000000000445004b00000cba0000813d0000000d04700039000000000504041a000000000515016f000000000603041a000000ff06600190000000010550c1bf000000000054041b000004e906000041000000000565016f000000000603041a0000ff0006600190000001000550c1bf000000000054041b000004ea05500197000000000603041a000004eb06600197000000000565019f000000000054041b0000000804700039000000000404041a0000000e05700039000000000045041b0000000904700039000000000404041a0000000f05700039000000000045041b0000000a04700039000000000404041a0000001005700039000000000045041b0000000b04700039000000000404041a0000001105700039000000000045041b0000000c04700039000000000404041a000004ec044001970000001205700039000000000605041a000004ed06600197000000000446019f000000000045041b000000000202041a000004ee02200197000000000407041a000004ef04400197000000000224019f000000000027041b000000000203041a000000000112016f00000001011001bf000000000013041b000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d2011001c70000800d0200003900000002030000390000051904000041000010180000013d0000000103700039000000000154004b00000cf00000a13d0000000401700039000000000401041a000001000500008a000000000454016f000000000603041a000000ff06600190000000010440c1bf000000000041041b000004e906000041000000000464016f000000000603041a0000ff0006600190000001000440c1bf000000000041041b000004ea04400197000000000603041a000004eb06600197000000000464019f000000000041041b0000000501700039000000000401041a000000000454016f0000000205700039000000000505041a000000ff0550018f000000000454019f000000000041041b0000000301700039000000000101041a0000000604700039000000000014041b000000000102041a000004ad01100197000000000407041a000004f604400197000000000114019f000000000017041b000000000403041a000001000100008a000000000414016f000000000043041b0000000703700039000000000402041a0000002004400270000004ad04400197000000000507041a0000002005500270000004ad05500197000000000445004b00000d2d0000813d0000000d04700039000000000504041a000000000515016f000000000603041a000000ff06600190000000010550c1bf000000000054041b000004e906000041000000000565016f000000000603041a0000ff0006600190000001000550c1bf000000000054041b000004ea05500197000000000603041a000004eb06600197000000000565019f000000000054041b0000000804700039000000000404041a0000000e05700039000000000045041b0000000904700039000000000404041a0000000f05700039000000000045041b0000000a04700039000000000404041a0000001005700039000000000045041b0000000b04700039000000000404041a0000001105700039000000000045041b0000000c04700039000000000404041a000004ec044001970000001205700039000000000605041a000004ed06600197000000000446019f000000000045041b000000000202041a000004ee02200197000000000407041a000004ef04400197000000000224019f000000000027041b000000000203041a000000000112016f000000000013041b000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d2011001c70000800d0200003900000002030000390000050304000041000010180000013d0000000103700039000000000154004b00000d620000a13d0000000401700039000000000401041a000001000500008a000000000454016f000000000603041a000000ff06600190000000010440c1bf000000000041041b000004e906000041000000000464016f000000000603041a0000ff0006600190000001000440c1bf000000000041041b000004ea04400197000000000603041a000004eb06600197000000000464019f000000000041041b0000000501700039000000000401041a000000000454016f0000000205700039000000000505041a000000ff0550018f000000000454019f000000000041041b0000000301700039000000000101041a0000000604700039000000000014041b000000000102041a000004ad01100197000000000407041a000004f604400197000000000114019f000000000017041b000000000403041a000004db01000041000000000414016f00000100044001bf000000000043041b0000000703700039000000000402041a0000002004400270000004ad04400197000000000507041a0000002005500270000004ad05500197000000000445004b00000da10000813d0000000d04700039000000000504041a000001000600008a000000000565016f000000000603041a000000ff06600190000000010550c1bf000000000054041b000004e906000041000000000565016f000000000603041a0000ff0006600190000001000550c1bf000000000054041b000004ea05500197000000000603041a000004eb06600197000000000565019f000000000054041b0000000804700039000000000404041a0000000e05700039000000000045041b0000000904700039000000000404041a0000000f05700039000000000045041b0000000a04700039000000000404041a0000001005700039000000000045041b0000000b04700039000000000404041a0000001105700039000000000045041b0000000c04700039000000000404041a000004ec044001970000001205700039000000000605041a000004ed06600197000000000446019f000000000045041b000000000202041a000004ee02200197000000000407041a000004ef04400197000000000224019f000000000027041b000000000203041a000000000112016f00000100011001bf000000000013041b000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d2011001c70000800d0200003900000002030000390000051404000041000010180000013d0000009b01000039000000000101041a000704ad0010019b000900980000003d000880100000003d0000000007000019000600000000001d000a00000008001d00000dbb0000013d00000001077000390000000c0170006c000010f40000813d0000000b01000029000000000101041a000000000171004b00000e8e0000a13d000d00000007001d000004e301700041000000000101041a000004d00110019700000000001004350000000901000029000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000000080200002912af12aa0000040f0000000a080000290000000102200190000011c30000613d000000000101043b000000000201041a000004ad02200197000000070220006b00000004020000390000000102002039000000400300043d000004e70430009c0000000d070000290000102e0000213d00000000051200190000008001300039000000400010043f000000000205041a0000001001200270000004ad0410019700000040013000390000000000410435000000ff042001900000000004000019000000010400c03900000000044304360000ff00022001900000000002000019000000010200c0390000000000240435000000400200043d000004f30620009c0000102e0000213d0000004006200039000000400060043f0000000106500039000000000606041a000000f80660021000000000066204360000000205500039000000000505041a0000000000560435000000600530003900000000002504350000000003030433000000000303004b00000db80000613d0000000003040433000000000303004b00000db80000c13d000000400300043d000004f30430009c0000102e0000213d00000000010104330000004004300039000000400040043f00000020043000390000000000240435000004ad011001970000000000130435000000800100043d000000060110006c00000e8e0000a13d00000006020000290000000501200210000000a0011000390000000000310435000000800100043d000000000121004b00000e8e0000a13d0000000601000029000600010010003d00000db80000013d0000009b01000039000000000101041a0000002001100270000804ad0010019b000a00980000003d000980100000003d0000000008000019000700000000001d00000e230000013d0000000701000029000700010010003d00000001088000390000000c0180006c000010fa0000813d0000000b01000029000000000101041a000000000181004b00000e8e0000a13d000d00000008001d000004e301800041000000000101041a000004d00110019700000000001004350000000a01000029000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000000090200002912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000002002200270000004ad02200197000000080220006b0000000d030000390000000703002039000000400200043d000004f80420009c0000000d080000290000102e0000213d0000000004130019000000a001200039000000400010043f000000000504041a0000001001500270000004ad0310019700000040012000390000000000310435000000ff035001900000000003000019000000010300c03900000000033204360000ff00055001900000000005000019000000010500c0390000000000530435000000400500043d000004e60650009c0000102e0000213d0000006006500039000000400060043f0000000106400039000000000606041a00000000066504360000000207400039000000000707041a00000000007604350000000306400039000000000606041a0000004007500039000000000067043500000060062000390000000000560435000000400500043d000004f30750009c0000102e0000213d0000004007500039000000400070043f0000000407400039000000000707041a00000000077504360000000504400039000000000404041a00000080044002100000000000470435000000800420003900000000005404350000000002020433000000000202004b00000e200000613d0000000002030433000000000202004b00000e200000c13d000000400200043d000004e60320009c0000102e0000213d000000000101043300000000030604330000006004200039000000400040043f0000004004200039000000000054043500000020042000390000000000340435000004ad011001970000000000120435000000800100043d000000070110006c00000e8e0000a13d00000007030000290000000501300210000000a0011000390000000000210435000000800100043d000000000131004b00000e1e0000213d000005160100004100000000001004350000003201000039000010310000013d000a00000006001d0000000a0150003900000009025000390000000803500039000700000003001d000000000303041a000800000002001d000000000202041a000900000001001d000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000200210003900000000003204350000006003000039000c00000003001d0000000000310435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000600000001001d000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0005010000000092000000050220017f000000000021041b00000001010003670000002402100370000000000302043b0000004402100370000000000202043b0000006401100370000000000401043b000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000200210003900000000003204350000000c030000290000000000310435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000c00000001001d00000000001004350000000601000029000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000101041a000000ff01100190000011c50000c13d0000000c0100002900000000001004350000000601000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000000050220017f00000001022001bf000000000021041b0000000b030000290000000b013000390000000a02000029000000000202041a0000002002200270000004ad02200197000000000303041a0000002003300270000004ad03300197000000000223004b00000f590000813d0000000b060000290000000d02600039000000000302041a000000050330017f0000000704600039000000000504041a000000ff05500190000000010330c1bf000000000032041b000004e905000041000000000353016f000000000504041a0000ff0005500190000001000330c1bf000000000032041b000004ea03300197000000000404041a000004eb04400197000000000343019f000000000032041b0000000702000029000000000202041a0000000e03600039000000000023041b0000000802000029000000000202041a0000000f03600039000000000023041b0000000902000029000000000202041a0000001003600039000000000023041b000000000201041a0000001103600039000000000023041b0000000c02600039000000000202041a000004ec022001970000001203600039000000000403041a000004ed04400197000000000224019f000000000023041b0000000a02000029000000000202041a000004ee02200197000000000306041a000004ef03300197000000000223019f000000000026041b00000001060003670000002402600370000000000202043b0000000703000029000000000023041b0000004403600370000000000303043b0000000804000029000000000034041b0000006404600370000000000404043b0000000905000029000000000045041b0000008405600370000000000505043b000000000051041b000000a401600370000000000101043b000004ed06100197000000000616004b000011c30000c13d0000000b060000290000000c06600039000000000706041a000004ed077001970000008008100270000000000787019f000000000076041b000000400600043d000000800760003900000000001704350000006001600039000000000051043500000040016000390000000000410435000000200160003900000000003104350000000000260435000004ad010000410000000002000414000004ad0320009c0000000002018019000004ad0360009c00000000060180190000004001600210000000c002200210000000000112019f00000500011001c70000800d0200003900000002030000390000050104000041000010180000013d0000000101700039000000000343004b00000fb60000a13d0000000a070000290000000403700039000000000403041a000001000500008a000000000454016f000000000601041a000000ff06600190000000010440c1bf000000000043041b000004e906000041000000000464016f000000000601041a0000ff0006600190000001000440c1bf000000000043041b000004ea04400197000000000601041a000004eb06600197000000000464019f000000000043041b0000000503700039000000000403041a000000000454016f0000000205700039000000000505041a000000ff0550018f000000000454019f000000000043041b0000000303700039000000000303041a0000000604700039000000000034041b000000000202041a000004ad02200197000000000307041a000004f603300197000000000223019f000000000027041b0000000c040000290000001002400210000004eb02200197000000000301041a000004f003300197000000000223019f000000000021041b000000400100043d0000000000410435000004ad020000410000000003000414000004ad0430009c0000000003028019000004ad0410009c00000000010280190000004001100210000000c002300210000000000112019f000004dd011001c70000800d0200003900000002030000390000050204000041000010180000013d00000000060700190000000702700039000000000343004b000010020000a13d0000000d03600039000000000403041a000001000500008a000000000454016f000000000502041a000000ff05500190000000010440c1bf000000000043041b000004e905000041000000000454016f000000000502041a0000ff0005500190000001000440c1bf000000000043041b000004ea04400197000000000502041a000004eb05500197000000000454019f000000000043041b0000000803600039000000000303041a0000000e04600039000000000034041b0000000903600039000000000303041a0000000f04600039000000000034041b0000000a03600039000000000303041a0000001004600039000000000034041b0000000b03600039000000000303041a0000001104600039000000000034041b0000000c03600039000000000303041a000004ec033001970000001204600039000000000504041a000004ed05500197000000000335019f000000000034041b000000000101041a000004ee01100197000000000306041a000004ef03300197000000000113019f000000000016041b0000000c040000290000001001400210000004eb01100197000000000302041a000004f003300197000000000113019f000000000012041b000000400100043d0000000000410435000004ad020000410000000003000414000004ad0430009c0000000003028019000004ad0410009c00000000010280190000004001100210000000c002300210000000000112019f000004dd011001c70000800d020000390000000203000039000004f1040000410000000d0500002912af12a50000040f0000000101200190000011c30000613d0000000001000019000012b00001042e00000003015000390000000202500039000700000002001d000000000302041a000800000001001d000000000201041a000000400100043d000000400410003900000000002404350000004002000039000b00000002001d0000000002210436000000f8033002100000000000320435000004e60310009c000010340000a13d000005160100004100000000001004350000004101000039000000040010043f0000051701000041000012b1000104300000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000600000001001d000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0005010000000092000000050220017f000000000021041b00000001010003670000002402100370000000000302043b000004f402300197000000000232004b000011c30000c13d0000004401100370000000000201043b000000400100043d00000040041000390000000000240435000000200210003900000000003204350000000b030000290000000000310435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000b00000001001d00000000001004350000000601000029000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000101041a000000ff01100190000011c80000c13d0000000b0100002900000000001004350000000601000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000000050220017f00000001022001bf000000000021041b0000000901000029000000000101041a000004ad011001970000000a02000029000000000202041a000004ad02200197000000000112004b000010d60000813d0000000a050000290000000401500039000000000201041a000000050220017f0000000103500039000000000403041a000000ff04400190000000010220c1bf000000000021041b000004e904000041000000000242016f000000000403041a0000ff0004400190000001000220c1bf000000000021041b000004ea02200197000000000303041a000004eb03300197000000000232019f000000000021041b0000000501500039000000000201041a000000050220017f0000000703000029000000000303041a000000ff0330018f000000000232019f000000000021041b0000000801000029000000000101041a0000000602500039000000000012041b0000000901000029000000000101041a000004ad01100197000000000205041a000004f602200197000000000112019f000000000015041b0000000703000029000000000103041a000000050110017f0000000c04000029000000f802400270000000000121019f000000000013041b00000044010000390000000101100367000000000101043b0000000802000029000000000012041b000000400200043d000000200320003900000000001304350000000000420435000004ad010000410000000003000414000004ad0430009c0000000003018019000004ad0420009c00000000020180190000004001200210000000c002300210000000000112019f000004e1011001c70000800d020000390000000203000039000004f704000041000010180000013d000000400100043d0000000603000029000006990000013d000000400100043d0000050602000041000009460000013d000000400100043d0000000703000029000005190000013d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000a01000029000000000101041a000c00000001001d00000000003004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000c02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000a020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000c0100000000920000000c0220017f000000000021041b0000000a040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000c0220017f000000000021041b0000000d0100002900000000001004350000000b01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000001041b0000000102100039000000000002041b0000000202100039000000000002041b0000000302100039000000000002041b0000000402100039000000000002041b0000000502100039000000000002041b0000000602100039000000000002041b0000000702100039000000000002041b0000000802100039000000000002041b0000000902100039000000000002041b0000000a02100039000000000002041b0000000b02100039000000000002041b0000000c02100039000000000002041b0000000d02100039000000000002041b0000000e02100039000000000002041b0000000f02100039000000000002041b0000001002100039000000000002041b0000001102100039000000000002041b0000001201100039000000000001041b0000000001000414000004ad0210009c000004ad01008041000000c001100210000004d2011001c70000800d020000390000000203000039000004e804000041000010180000013d0000000001000019000012b100010430000000400100043d0000050702000041000009460000013d000000400100043d000004f502000041000009460000013d000004f5010000410000000000120435000004ad01000041000004ad0320009c00000000020180190000004001200210000004e0011001c7000012b1000104300000000002010019000000400100043d0000051c0310009c000011f60000813d0000008003100039000000400030043f000000000302041a0000001004300270000004ad04400197000000400510003900000000004504350000ff00043001900000000004000019000000010400c03900000020051000390000000000450435000000ff033001900000000003000019000000010300c0390000000000310435000000400300043d000004f30430009c000011f60000213d0000004004300039000000400040043f0000000104200039000000000404041a000000f80440021000000000044304360000000202200039000000000202041a000000000024043500000060021000390000000000320435000000000001042d000005160100004100000000001004350000004101000039000000040010043f0000051701000041000012b1000104300000000002010019000000400100043d0000051d0310009c000012300000813d000000a003100039000000400030043f000000000302041a0000001004300270000004ad04400197000000400510003900000000004504350000ff00043001900000000004000019000000010400c03900000020051000390000000000450435000000ff033001900000000003000019000000010300c0390000000000310435000000400300043d000004e60430009c000012300000213d0000006004300039000000400040043f0000000104200039000000000404041a00000000044304360000000205200039000000000505041a00000000005404350000000304200039000000000404041a0000004005300039000000000045043500000060041000390000000000340435000000400300043d000004f30430009c000012300000213d0000004004300039000000400040043f0000000404200039000000000404041a00000000044304360000000502200039000000000202041a0000008002200210000000000024043500000080021000390000000000320435000000000001042d000005160100004100000000001004350000004101000039000000040010043f0000051701000041000012b1000104300000000043010434000000000303004b0000000003000019000000010300c03900000000033204360000000004040433000000000404004b0000000004000019000000010400c039000000000043043500000040031000390000000003030433000004ad0330019700000040042000390000000000340435000000600110003900000000010104330000000031010434000004f40110019700000060042000390000000000140435000000800120003900000000020304330000000000210435000000000001042d0000000043010434000000000303004b0000000003000019000000010300c03900000000033204360000000004040433000000000404004b0000000004000019000000010400c039000000000043043500000040031000390000000003030433000004ad03300197000000400420003900000000003404350000006003100039000000000303043300000060042000390000000065030434000000000054043500000000040604330000008005200039000000000045043500000040033000390000000003030433000000a004200039000000000034043500000080011000390000000001010433000000c00320003900000000410104340000000000130435000000e0012000390000000002040433000004ed022001970000000000210435000000000001042d0000006502000039000000000302041a000004d103300197000000000032041b000004d0061001970000003301000039000000000201041a000004d103200197000000000363019f000000000031041b000004ad010000410000000003000414000004ad0430009c0000000003018019000000c001300210000004d2011001c7000004d0052001970000800d020000390000000303000039000004dc0400004112af12a50000040f00000001012001900000128c0000613d000000000001042d0000000001000019000012b100010430000000000001042f000004ad03000041000004ad0410009c00000000010380190000004001100210000004ad0420009c00000000020380190000006002200210000000000112019f0000000002000414000004ad0420009c0000000002038019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000012a30000613d000000000101043b000000000001042d0000000001000019000012b100010430000012a8002104210000000102000039000000000001042d0000000002000019000000000001042d000012ad002104230000000102000039000000000001042d0000000002000019000000000001042d000012af00000432000012b00001042e000012b1000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff000000020000000000000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000740211cd0000000000000000000000000000000000000000000000000000000099624cb500000000000000000000000000000000000000000000000000000000d113233100000000000000000000000000000000000000000000000000000000e8de12de00000000000000000000000000000000000000000000000000000000e8de12df00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000d113233200000000000000000000000000000000000000000000000000000000e30c39780000000000000000000000000000000000000000000000000000000099624cb6000000000000000000000000000000000000000000000000000000009ec3f92700000000000000000000000000000000000000000000000000000000c4d66de80000000000000000000000000000000000000000000000000000000094ca304a0000000000000000000000000000000000000000000000000000000094ca304b0000000000000000000000000000000000000000000000000000000095570d1200000000000000000000000000000000000000000000000000000000994057ef00000000000000000000000000000000000000000000000000000000740211ce0000000000000000000000000000000000000000000000000000000079ba5097000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000003ea053ea000000000000000000000000000000000000000000000000000000005139839b000000000000000000000000000000000000000000000000000000005139839c000000000000000000000000000000000000000000000000000000005875da2b00000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000003ea053eb00000000000000000000000000000000000000000000000000000000426cb7660000000000000000000000000000000000000000000000000000000047b4a7a60000000000000000000000000000000000000000000000000000000029092d0d0000000000000000000000000000000000000000000000000000000029092d0e000000000000000000000000000000000000000000000000000000002f9c8f0d000000000000000000000000000000000000000000000000000000003d1f16d40000000000000000000000000000000000000000000000000000000008dc336000000000000000000000000000000000000000000000000000000000189a5a17000000000000000000000000000000000000000000000000000000001c5a9d9c000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000038d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270000000000000000000000000000000000000000200000008000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000647920696e697469616c697a6564000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c72656108c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e002000000000000000000000000000000000000200000000000000000000000007f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498c7eabfa90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000200000000000000000000000000000000000040000000000000000000000000354a83ed9988f79f6038d4c7a7dadbad8af32f4ad6df893e0e5807a1b1944ff8354a83ed9988f79f6038d4c7a7dadbad8af32f4ad6df893e0e5807a1b1944ff90000000000000000000000000000000000000000ffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff9f000000000000000000000000000000000000000000000000ffffffffffffff7f1629bfc36423a1b4749d3fe1d6970b9d32d42bbee47dd5540670696ab6b9a4adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0001ffffffffffffffffffffffffffffffffffffffffffffffffffff0000000001010000000000000000000000000000000000000000000000000000ffffffff000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffc810fe33ecde832d7a0b696cf1738e8ec84938965b214bd4e1195ef8d6e8dd26000000000000000000000000000000000000000000000000ffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffbfff00000000000000000000000000000000000000000000000000000000000000564da7df00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000205a2493904fd7ff8685b368c0a13560ddcc577aac288385c5834c57996c9ad2000000000000000000000000000000000000000000000000ffffffffffffff5f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206e6577206f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000800000000000000000000000000000000000000000000000000000000000000000000000010000000002000000000000000000000000000000000000200000008000000000000000003d2e97fa99e681fa81a4ec393f21f6b0fcccca1463d6bf43cb3a80299968091c000000000000000000000000000000010000000000000000000000000000000002000000000000000000000000000000000000a0000000000000000000000000a88f0bfec4ed62be2eb084417ce4a44e7289b24faec9f1ae553fce55c475c3d25c0844614cb8580962e0ce8f75301a64eccd757945ce5620b7d84b65e232a673d9957750e6343405c319eb99a4ec67fa11cfd66969318cbc71aa2d45fa53a349164b707307f2b1481ff9787806cdcc4d8b12e532a6a84dd0a3f4c4507c1808e700ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6b0949d8000000000000000000000000000000000000000000000000000000001a956ace000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff1fffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000020000000000000000000000000000000000012000000000000000000000000034a1749086dfd00e126255be02329843f1c05be61db5c1fc80ceefc38ccef67683ee5ccc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000008000000000000000001088e0c600000000000000000000000000000000000000000000000000000000c5cbf870000000000000000000000000000000000000000000000000000000004f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65720000000000000000000000000000000000000064000000800000000000000000cfc24166db4bb677e857cacabd1541fb2b30645021b27c5130419589b84db52b2fc842bf000000000000000000000000000000000000000000000000000000004e487b71000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffa07dc8b937d2916b130743c447af3d771fa55e66b7393105150e2e635ac3e87260bdc213f90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff80000000000000000000000000000000000000000000000000ffffffffffffff605c3973df1c57590f450df32f693e00b74a06572949ddc108dd33c91827cf42f0", + "deployedBytecode": "0x00020000000000020015000000000002000100000001035500000000030100190000006003300270000004ad0030019d0000008008000039000000400080043f000004ad033001970000000102200190000000200000c13d000000040230008c000011c30000413d000000000201043b000000e002200270000004af0420009c000000280000a13d000004b00420009c0000023f0000a13d000004b10420009c000002b60000a13d000004b20420009c000002e10000213d000004b50420009c000005590000613d000004b60120009c000011c30000c13d0000000001000416000000000101004b000011c30000c13d0000006501000039000004f40000013d0000000001000416000000000101004b000011c30000c13d000000200100003900000100001004430000012000000443000004ae01000041000012b00001042e000004c10420009c000001330000213d000004c90420009c0000024c0000213d000004cd0420009c000003970000613d000004ce0420009c000003040000613d000004cf0220009c000011c30000c13d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b000d00000001001d000004d00110009c000011c30000213d0000003301000039000000000101041a000004d0021001970000000001000411000000000212004b000000450000613d0000000d0110006b000003b50000c13d0000000d0100002900000000001004350000009801000039000c00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000000610000c13d0000000902100039000000000202041a000000000202004b000000610000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b02000039000000000402041a0000002003400270000004ad03300197000000000701043b000000000107041a0000002005100270000004ad05500197000000000353004b0000000d030000390000000703002039000004ad04400197000004ad05100197000000000654004b000000040600003900000001060020390000000006760019000000000606041a0000ff000660019000000c540000613d0000000003730019000000000303041a0000ff000330019000000c540000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000b00000007001d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000009cd0000613d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000b01000029000000000101041a000a00000001001d00000000003004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000a02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000b020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000005180310009c0000102e0000813d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000a0100000000920000000a0220017f000000000021041b0000000b040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000a0220017f000000000021041b0000000d0100002900000000001004350000000c01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000004b70000013d000004c20420009c0000026f0000213d000004c60420009c000003a20000613d000004c70420009c0000034b0000613d000004c80220009c000011c30000c13d0000000002000416000000000202004b000011c30000c13d000000040230008a000000400220008c000011c30000413d0000000402100370000000000202043b000d00000002001d000004d00220009c000011c30000213d0000002401100370000000000101043b000c00000001001d000004ad0110009c000011c30000213d0000003301000039000000000101041a000004d0011001970000000002000411000000000121004b0000067a0000c13d0000000d0100002900000000001004350000009801000039000b00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b0000016d0000c13d0000000902100039000000000202041a000000000202004b0000016d0000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b02000039000000000302041a0000002004300270000004ad04400197000000000701043b000000000107041a0000002005100270000004ad05500197000000000454004b0000000d050000390000000705002039000004ad03300197000004ad04100197000000000643004b000000040600003900000001060020390000000006760019000000000606041a0000ff0006600190000a00000007001d00000f8d0000613d0000000005750019000000000505041a0000ff000550019000000f8d0000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000009cd0000613d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000a01000029000000000101041a000c00000001001d00000000003004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000c02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000a020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000c0100000000920000000c0220017f000000000021041b0000000a040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000c0220017f000000000021041b0000000d0100002900000000001004350000000b01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000011940000013d000004ba0420009c0000028f0000213d000004be0120009c000005400000613d000004bf0120009c000004f70000613d000004c00120009c000011c30000c13d0000000001000416000000000101004b000011c30000c13d0000003301000039000004f40000013d000004ca0420009c000003b90000613d000004cb0420009c000003510000613d000004cc0120009c000011c30000c13d0000000001000416000000000101004b000011c30000c13d0000003301000039000000000101041a000004d0011001970000000002000411000000000121004b0000067a0000c13d0000009b01000039000000000201041a000004ad03200197000004ad0430009c0000054f0000613d000004f6022001970000000103300039000000000223019f000000000021041b000000800030043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004fd011001c70000800d0200003900000001030000390000050404000041000010190000013d000004c30420009c000004e60000613d000004c40420009c000003760000613d000004c50120009c000011c30000c13d0000000001000416000000000101004b000011c30000c13d0000003301000039000000000201041a000004d0052001970000000003000411000000000335004b0000067a0000c13d0000006503000039000000000403041a000004d104400197000000000043041b000004d102200197000000000021041b000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d2011001c70000800d020000390000000303000039000004dc040000410000000006000019000010190000013d000004bb0420009c000005530000613d000004bc0420009c000005030000613d000004bd0220009c000011c30000c13d0000000002000416000000000202004b000011c30000c13d000000040230008a000000600220008c000011c30000413d0000000402100370000000000202043b000d00000002001d000004d00220009c000011c30000213d0000003302000039000000000202041a000004d0032001970000000002000411000000000323004b000002a80000613d0000000d0220006b000003b50000c13d0000002402100370000000000302043b000004f402300197000c00000003001d000000000232004b000011c30000c13d0000000c0200006b000009280000c13d0000004401100370000000000101043b000000000101004b000009280000c13d0000050e01000041000003b60000013d000004b70420009c000006830000613d000004b80420009c000005760000613d000004b90220009c000011c30000c13d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b000d00000001001d000004d00110009c000011c30000213d000000000300041a000bff0000300194000007c80000c13d000000ff0130019000000000020000190000000102006039000e00000002001d00000000020004150000000e0220008a00000020022000c9000000000101004b000007cc0000c13d000001000100008a000000000113016f00000001011001bf000004db02000041000000000121016f00000100011001bf0000000003000019000000000010041b0000000d06000029000000000106004b000009650000c13d000000400100043d000004df02000041000009460000013d000004b30420009c0000056c0000613d000004b40220009c000011c30000c13d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000601043b000004d00160009c000011c30000213d0000003301000039000000000101041a000004d0051001970000000001000411000000000115004b0000067a0000c13d0000006501000039000000000201041a000004d102200197000000000262019f000000000021041b000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d2011001c70000800d020000390000000303000039000004d304000041000010190000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b000004d00210009c000011c30000213d00000000001004350000009801000039000000200010043f0000004002000039000000000100001912af128f0000040f0000000002010019000d00000002001d000000000102041a000900000001001d000000010120003912af11d30000040f000c00000001001d0000000d01000029000000040110003912af11d30000040f000b00000001001d0000000d01000029000000070110003912af11fc0000040f0000000d020000290000000d02200039000a00000001001d000000000102001912af11fc0000040f00000009050000290000002002500270000004ad02200197000000400400043d000d00000004001d000000200340003900000000002304350000004002500270000004ad0220019700000040034000390000000000230435000004ad025001970000000000240435000900000001001d00000060024000390000000c0100002912af12360000040f0000000d0100002900000100021000390000000b0100002912af12360000040f0000000d01000029000001a0021000390000000a0100002912af124f0000040f0000000d01000029000002a002100039000000090100002912af124f0000040f000004ad010000410000000d03000029000004ad0230009c000000000301801900000040013002100000051b011001c7000012b00001042e0000000001000416000000000101004b000011c30000c13d0000009b01000039000000000101041a000005720000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000001400220008c000011c30000413d0000000402100370000000000202043b000d00000002001d000004d00220009c000011c30000213d0015000d0000002d0000002402100370000000000202043b000c00000002001d000004ad0220009c000011c30000213d0014000c0000002d001300440000003d001200a40000003d000000e402100370000000000202043b000b00000002001d000004ad0220009c000011c30000213d0011000b0000002d001001040000003d0000003302000039000000000202041a000004d0022001970000000003000411000000000232004b0000067a0000c13d0000000d0200006b000009d10000c13d000004df01000041000003b60000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000c00220008c000011c30000413d0000000402100370000000000202043b000d00000002001d000004d00220009c000011c30000213d0000003302000039000000000202041a000004d0032001970000000002000411000000000323004b000003890000613d0000000d0220006b000003b50000c13d0000002402100370000000000202043b000000000202004b000007f00000c13d0000004402100370000000000202043b000000000202004b000007f00000c13d0000006402100370000000000202043b000000000202004b000007f00000c13d0000051101000041000003b60000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b00000000001004350000009a01000039000005630000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b000d00000001001d000004d00110009c000011c30000213d0000003301000039000000000101041a000004d0021001970000000001000411000000000212004b000006c80000613d0000000d0110006b000006c80000613d0000051501000041000000800010043f0000050f01000041000012b1000104300000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b000d00000001001d000004d00110009c000011c30000213d0000003301000039000000000101041a000004d0011001970000000002000411000000000121004b0000067a0000c13d0000000d0100002900000000001004350000009801000039000c00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000003e60000c13d0000000902100039000000000202041a000000000202004b000003e60000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b02000039000000000402041a0000002003400270000004ad03300197000000000701043b000000000107041a0000002005100270000004ad05500197000000000353004b0000000d030000390000000703002039000004ad04400197000004ad05100197000000000654004b000000040600003900000001060020390000000006760019000000000606041a0000ff000660019000000d3a0000613d0000000003730019000000000303041a0000ff000330019000000d3a0000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000b00000007001d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000009cd0000613d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000b01000029000000000101041a000a00000001001d00000000003004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000a02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000b020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000a0100000000920000000a0220017f000000000021041b0000000b040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000a0220017f000000000021041b0000000d0100002900000000001004350000000c01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000001041b0000000102100039000000000002041b0000000202100039000000000002041b0000000302100039000000000002041b0000000402100039000000000002041b0000000502100039000000000002041b0000000602100039000000000002041b0000000702100039000000000002041b0000000802100039000000000002041b0000000902100039000000000002041b0000000a02100039000000000002041b0000000b02100039000000000002041b0000000c02100039000000000002041b0000000d02100039000000000002041b0000000e02100039000000000002041b0000000f02100039000000000002041b0000001002100039000000000002041b0000001102100039000000000002041b0000001201100039000000000001041b0000000001000414000004ad0210009c000004ad01008041000000c001100210000004d2011001c70000800d020000390000000203000039000004e80400004100000dae0000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b0000009702000039000000000302041a000000000331004b000011c30000813d0000000000200435000004e301100041000000000101041a000004d001100197000005730000013d0000000001000416000000000101004b000011c30000c13d0000006501000039000000000101041a000004d0021001970000000001000411000000000212004b000006bc0000c13d12af12740000040f0000000001000019000012b00001042e0000000001000416000000000101004b000011c30000c13d0000009701000039000b00000001001d000000000101041a000c00000001001d000004f20110009c0000102e0000213d0000000c010000290000000502100210000000bf01200039000000200300008a000000000131016f000004f20310009c0000102e0000213d000000400010043f0000000c03000029000000800030043f000000000303004b0000000003000019000008ec0000c13d000000800030043f00000020020000390000000002210436000000800300043d00000000003204350000004002100039000000000403004b000006b20000613d00000080040000390000000005000019000000200440003900000000060404330000000087060434000004ad077001970000000007720436000000000808043300000000a9080434000000000097043500000000070a0433000000400920003900000000007904350000004007800039000000000707043300000060082000390000000000780435000000400660003900000000060604330000008007200039000000008606043400000000006704350000000006080433000004ed06600197000000a0072000390000000000670435000000c0022000390000000105500039000000000635004b000005230000413d000006b20000013d0000000001000416000000000101004b000011c30000c13d0000003301000039000000000101041a000004d0011001970000000002000411000000000121004b0000067a0000c13d0000009b01000039000000000201041a0000002003200270000004ad03300197000004ad0430009c000007b60000c13d000005160100004100000000001004350000001101000039000010310000013d0000000001000416000000000101004b000011c30000c13d0000009701000039000000000101041a000005730000013d0000000002000416000000000202004b000011c30000c13d000000040230008a000000200220008c000011c30000413d0000000401100370000000000101043b00000000001004350000009901000039000000200010043f0000004002000039000000000100001912af128f0000040f000000000101041a000000ff011001900000000001000019000000010100c039000005730000013d0000000001000416000000000101004b000011c30000c13d0000009b01000039000000000101041a0000002001100270000004ad01100197000000800010043f000004d401000041000012b00001042e0000000002000416000000000202004b000011c30000c13d000000040230008a000000400220008c000011c30000413d0000000402100370000000000202043b000d00000002001d000004d00220009c000011c30000213d0000002401100370000000000101043b000c00000001001d000004ad0110009c000011c30000213d0000003301000039000000000101041a000004d0011001970000000002000411000000000121004b0000067a0000c13d0000000d0100002900000000001004350000009801000039000b00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000005a80000c13d0000000902100039000000000202041a000000000202004b000005a80000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000701043b0000009b01000039000000000301041a000004ad04300197000000000207041a000004ad05200197000000000454004b000000040500003900000001050020390000002003300270000004ad033001970000002004200270000004ad044001970000000006750019000000000543004b0000000d050000390000000705002039000000000606041a0000ff000660019000000fcd0000613d0000000005750019000000000505041a0000ff000550019000000fcd0000613d000c00000007001d0000009701000039000000000401041a000000000304004b0000054f0000613d000004e203400041000000000303041a000004d0033001970000004002200270000004ad02200197000000000424004b00000e8e0000a13d000004e302200041000000000402041a000004d104400197000000000434019f000000000042041b000000000201041a000000000402004b000009cd0000613d000004e204200041000000000504041a000004d105500197000000000054041b000000010220008a000000000021041b0000000c01000029000000000101041a000a00000001001d00000000003004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000a02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000c020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000a0100000000920000000a0220017f000000000021041b0000000c040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000a0220017f000000000021041b0000000d0100002900000000001004350000000b01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000011940000013d000004d901000041000000800010043f0000002001000039000000840010043f000000a40010043f0000051201000041000000c40010043f0000051301000041000012b1000104300000000001000416000000000101004b000011c30000c13d0000009701000039000b00000001001d000000000101041a000c00000001001d000004f20110009c0000102e0000213d0000000c010000290000000502100210000000bf01200039000000200300008a000000000131016f000004f20310009c0000102e0000213d000000400010043f0000000c03000029000000800030043f000000000303004b0000000003000019000009100000c13d000000800030043f00000020020000390000000002210436000000800300043d00000000003204350000004002100039000000000403004b000006b20000613d0000000004000019000000200880003900000000050804330000000065050434000004ad05500197000000000552043600000000060604330000000076060434000004f406600197000000000065043500000000050704330000004006200039000000000056043500000060022000390000000104400039000000000534004b000006a20000413d0000000002120049000004ad03000041000004ad0420009c0000000002038019000004ad0410009c000000000103801900000040011002100000006002200210000000000112019f000012b00001042e000004d901000041000000800010043f0000002001000039000000840010043f0000002901000039000000a40010043f000004f901000041000000c40010043f000004fa01000041000000e40010043f000004fb01000041000012b1000104300000000d0100002900000000001004350000009801000039000c00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000006e40000c13d0000000902100039000000000202041a000000000202004b000006e40000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b02000039000000000402041a0000002003400270000004ad03300197000000000701043b000000000107041a0000002005100270000004ad05500197000000000353004b0000000d030000390000000703002039000004ad04400197000004ad05100197000000000654004b000000040600003900000001060020390000000006760019000000000606041a0000ff000660019000000cc80000613d0000000003730019000000000303041a0000ff000330019000000cc80000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000b00000007001d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000009cd0000613d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000b01000029000000000101041a000a00000001001d00000000003004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000a02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000b020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000a0100000000920000000a0220017f000000000021041b0000000b040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000a0220017f000000000021041b0000000d0100002900000000001004350000000c01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000011940000013d000004ef022001970000002003300210000004fc03300041000004ee04300197000000000224019f000000000021041b0000002001300270000000800010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004fd011001c70000800d020000390000000103000039000004fe04000041000010190000013d00000000020004150000000f0220008a00000020022000c9000f00000000001d000c00000002001d000a00000003001d000004d501000041000000000010043900000000010004100000000400100443000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d6011001c7000080020200003912af12aa0000040f0000000102200190000007fd0000613d000000000101043b000000000101004b0000094d0000c13d0000000a01000029000000ff0110018f000000010110008c000000000100001900000001010060390000000c020000290000000502200270000000000201001f000009500000c13d000001000100008a000000000200041a000000000112016f000000010300003900000001011001bf0000000b0200006b000002da0000c13d000002d60000013d0000008402100370000000000202043b000000000202004b000007fe0000c13d000000a401100370000000000101043b000004ed02100197000000000212004b000011c30000c13d000004ff0110009c000007fe0000813d0000051001000041000003b60000013d000000000001042f0000000d0100002900000000001004350000009801000039000c00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b0000081a0000c13d0000000902100039000000000202041a000000000202004b0000081a0000c13d0000000a01100039000000000101041a000000000101004b000009440000613d0000000d0100002900000000001004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b06000039000000000306041a0000002002300270000004ad02200197000000000501043b000000000105041a0000002004100270000004ad04400197000000000242004b0000000d020000390000000702002039000004ad03300197000004ad04100197000000000343004b000000040300003900000001030020390000000003530019000000000303041a0000ff0003300190000b00000005001d00000e920000613d0000000002520019000000000202041a0000ff000220019000000e920000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000009cd0000613d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000b01000029000000000101041a000a00000001001d00000000003004350000000c01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000a02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000b020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000a0100000000920000000a0220017f000000000021041b0000000b040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000a0220017f000000000021041b0000000d0100002900000000001004350000000c01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000011940000013d000004e60310009c0000102e0000213d00000000030000190000006004100039000000400040043f0000000004010436000000400500043d000004e60650009c0000102e0000213d0000006006500039000000400060043f000000400650003900000000000604350000002006500039000000000006043500000000000504350000000000540435000000400400043d000004f30540009c0000102e0000213d0000004005400039000000400050043f00000020054000390000000000050435000000000004043500000040051000390000000000450435000000a00430003900000000001404350000002003300039000000000123004b00000e150000813d000000400100043d000004e60410009c000008ef0000a13d0000102e0000013d000004f30310009c0000102e0000213d00000000030000190000004004100039000000400040043f0000000004010436000000400500043d000004f30650009c0000102e0000213d0000004006500039000000400060043f0000002006500039000000000006043500000000000504350000000000540435000000a00430003900000000001404350000002003300039000000000123004b00000daf0000813d000000400100043d000004f30410009c000009130000a13d0000102e0000013d0000000d0100002900000000001004350000009801000039000b00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000009920000c13d0000000902100039000000000202041a000000000202004b000009920000c13d0000000a01100039000000000101041a000000000101004b000009920000c13d000000400100043d0000051a020000410000000000210435000004ad02000041000004ad0310009c00000000010280190000004001100210000004e0011001c7000012b1000104300000000c010000290000000501100270000000000100001f000000400100043d0000006402100039000004d70300004100000000003204350000004402100039000004d803000041000000000032043500000024021000390000002e030000390000000000320435000004d9020000410000000000210435000000040210003900000020030000390000000000320435000004ad02000041000004ad0310009c00000000010280190000004001100210000004da011001c7000012b100010430000c00000003001d0000006501000039000000000201041a000004d102200197000000000021041b0000003301000039000000000201041a000004d103200197000000000363019f000000000031041b000004ad010000410000000003000414000004ad0430009c0000000003018019000000c001300210000004d2011001c7000004d0052001970000800d020000390000000303000039000004dc0400004112af12a50000040f0000000101200190000011c30000613d0000000c0100006b0000101c0000c13d000004db01000041000000000200041a000000000112016f000000000010041b0000000103000039000000400100043d0000000000310435000004ad020000410000000004000414000004ad0540009c0000000004028019000004ad0510009c00000000010280190000004001100210000000c002400210000000000112019f000004dd011001c70000800d02000039000004de04000041000010190000013d0000000d0100002900000000001004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000009b02000039000900000002001d000000000302041a0000002002300270000004ad02200197000000000501043b000000000105041a0000002004100270000004ad04400197000000000242004b0000000d020000390000000702002039000004ad03300197000004ad04100197000000000343004b000000040300003900000001030020390000000003530019000000000303041a0000ff0003300190000a00000005001d0000101e0000613d0000000002520019000000000202041a0000ff00022001900000101e0000613d0000009702000039000000000402041a000000000304004b0000054f0000613d000004e203400041000000000303041a000004d0033001970000004001100270000004ad01100197000000000414004b00000e8e0000a13d000004e301100041000000000401041a000004d104400197000000000434019f000000000041041b000000000102041a000000000401004b000010fd0000c13d000005160100004100000000001004350000003101000039000010310000013d0000004402100370000000000202043b000000000202004b000009dd0000c13d0000006402100370000000000202043b000000000202004b000009dd0000c13d0000008402100370000000000202043b000000000202004b000003950000613d000000a402100370000000000202043b000000000202004b000009e80000c13d000000c402100370000000000202043b000004ed03200197000000000323004b000011c30000c13d000004ec0220009c000007fb0000a13d0000010402100370000000000202043b000004f403200197000000000323004b000011c30000c13d000005050220009c000009f30000213d0000012401100370000000000101043b000000000101004b000002b40000613d0000000d0100002900000000001004350000009801000039000a00000001001d000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b0000000802100039000000000202041a000000000202004b000010f70000c13d0000000902100039000000000202041a000000000202004b000010f70000c13d0000000a01100039000000000101041a000000000101004b000010f70000c13d00000001010003670000010402100370000000000302043b000004f402300197000000000232004b000011c30000c13d0000012401100370000000000201043b000000400100043d000000400410003900000000002404350000002002100039000000000032043500000040030000390000000000310435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000900000001001d00000000001004350000009901000039000800000001001d000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000400200043d000000000101043b000000000101041a000000ff01100190000011cb0000c13d00000001010003670000004403100370000000000303043b0000006404100370000000000404043b0000008401100370000000000101043b00000060052000390000000000150435000000400120003900000000004104350000002001200039000000000031043500000060030000390000000000320435000004e70320009c0000102e0000213d0000008003200039000000400030043f000004ad04000041000004ad0310009c000000000104801900000040011002100000000002020433000004ad0320009c00000000020480190000006002200210000000000112019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000700000001001d00000000001004350000009a01000039000600000001001d000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000101041a000000ff01100190000011c50000c13d0000009703000039000000000203041a000004ad01200197000004f20420009c0000102e0000213d0000000104200039000000000043041b0000000000300435000004e302200041000000000302041a000004d1033001970000000d033001af000000000032041b000000400200043d000004e70320009c0000102e0000213d0000008003200039000000400030043f00000040032000390000000b0400002900000000004304350000000107000039000000000372043600000000000304350000000008000031000001040380008a0000050804000041000000400530008c000000000500001900000000050440190000050803300197000000000603004b000000000400a019000005080330009c000000000405c019000000000304004b000011c30000c13d000000400300043d000004f30430009c0000102e0000213d0000004004300039000000400040043f00000001060003670000010404600370000000000404043b000004f405400197000000000545004b000011c30000c13d00000000044304360000012405600370000000000505043b000000000054043500000060042000390000000000340435000000400400043d000004f30340009c0000102e0000213d0000004003400039000000400030043f000000200340003900000000000304350000000000040435000000400300043d000004e70530009c0000102e0000213d0000008005300039000000400050043f00000060053000390000000000450435000000400430003900000000000404350000002004300039000000000004043500000000000304350000009b04000039000000000404041a000000400500043d000004f80950009c0000102e0000213d000000a009500039000000400090043f00000040095000390000000c0a0000290000000000a90435000000440880008a0000050809000041000000600a80008c000000000a000019000000000a0940190000050808800197000000000b08004b000000000900a019000005080880009c00000000090ac01900000000077504360000000000070435000000000709004b000011c30000c13d000000400700043d000004e60870009c0000102e0000213d0000006008700039000000400080043f0000004408600370000000000808043b00000000088704360000006409600370000000000909043b00000000009804350000008408600370000000000808043b0000004009700039000000000089043500000060085000390000000000780435000000400700043d000004f30870009c0000102e0000213d0000004008700039000000400080043f000000a408600370000000000808043b0000000008870436000000c406600370000000000606043b000004ed09600197000000000969004b000011c30000c13d000000000068043500000080065000390000000000760435000000400600043d000004e60760009c0000102e0000213d0000006007600039000000400070043f00000040076000390000000000070435000000200760003900000000000704350000000000060435000000400800043d000004f30780009c0000102e0000213d0000004007800039000000400070043f000000200780003900000000000704350000000000080435000000400700043d000004f80970009c0000102e0000213d000000a009700039000000400090043f000000800970003900000000008904350000006008700039000000000068043500000040067000390000000000060435000000200670003900000000000604350000000000070435000000400600043d000c00000006001d000005090660009c0000102e0000213d0000000c08000029000000e006800039000000400060043f000000c006800039000b00000006001d0000000000760435000000a006800039000500000006001d00000000005604350000008005800039000400000005001d00000000003504350000006003800039000300000003001d00000000002304350000004002800039000200000002001d0000000000120435000004ad0140019700000000021804360000002001400270000004ad01100197000100000002001d00000000001204350000000d0100002900000000001004350000000a01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000c020000290000000002020433000004ad02200197000000000101043b000000000301041a0000050a03300197000000000223019f000000010300002900000000030304330000002003300210000004ee03300197000000000232019f000000020300002900000000030304330000004003300210000004e403300197000000000232019f000000000021041b0000000102100039000000000302041a0000050b03300197000000030400002900000000040404330000000065040434000000000505004b000000010330c1bf0000000005060433000000000505004b000001000330c1bf000000400540003900000000050504330000001005500210000004eb05500197000000000353019f000000000032041b00000060024000390000000203100039000d010000000092000000000403041a0000000d0440017f00000000020204330000000052020434000000f802200270000000000224019f000000000023041b00000000020504330000000303100039000000000023041b0000000402100039000000000302041a0000050b03300197000000040400002900000000040404330000000065040434000000000505004b000000010330c1bf0000000005060433000000000505004b000001000330c1bf000000400540003900000000050504330000001005500210000004eb05500197000000000353019f000000000032041b0000000502100039000000000302041a0000000d0330017f000000600440003900000000040404330000000054040434000000f804400270000000000343019f000000000032041b00000000020504330000000603100039000000000023041b0000000702100039000000000302041a0000050b03300197000000050400002900000000040404330000000065040434000000000505004b000000010330c1bf0000000005060433000000000505004b000001000330c1bf000000400540003900000000050504330000001005500210000004eb05500197000000000353019f000000000032041b0000006002400039000000000202043300000008031000390000000065020434000000000053041b00000000030604330000000905100039000000000035041b000000400220003900000000020204330000000a03100039000000000023041b000000800240003900000000020204330000000b031000390000000042020434000000000023041b000000000204043300000080022002700000000c03100039000000000403041a000004ed04400197000000000224019f000000000023041b0000000d02100039000000000302041a0000050b033001970000000b0400002900000000040404330000000065040434000000000505004b000000010330c1bf0000000005060433000000000505004b000001000330c1bf000000400540003900000000050504330000001005500210000004eb05500197000000000353019f000000000032041b000000600240003900000000020204330000000e031000390000000065020434000000000053041b00000000030604330000000f05100039000000000035041b000000400220003900000000020204330000001003100039000000000023041b0000008002400039000000000202043300000011031000390000000042020434000000000023041b000000120110003900000000020404330000008002200270000000000301041a000004ed03300197000000000223019f000000000021041b000000090100002900000000001004350000000801000029000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000d0220017f00000001022001bf000000000021041b000000070100002900000000001004350000000601000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000d0220017f00000001022001bf000000000021041b000004d001000041000000150510017f000004ad01000041000000140310017f0000001104000029000000100200002900000012060000290000001307000029000000400100043d00000000083104360000000103000367000000000973034f000000000909043b00000000009804350000002008700039000000000883034f000000000808043b000000400910003900000000008904350000004007700039000000000773034f000000000707043b00000060081000390000000000780435000000000763034f000000000707043b000000800810003900000000007804350000002006600039000000000663034f000000000606043b000004ed07600197000000000767004b000011c30000c13d000004ad04400197000000c0071000390000000000470435000000a0041000390000000000640435000000000423034f000000000404043b000004f406400197000000000646004b000011c30000c13d000000e00610003900000000004604350000002002200039000000000223034f000000000202043b00000100031000390000000000230435000004ad020000410000000003000414000004ad0430009c0000000003028019000004ad0410009c00000000010280190000004001100210000000c002300210000000000112019f0000050c011001c70000800d0200003900000002030000390000050d04000041000010190000013d0000000103700039000000000154004b00000c7c0000a13d0000000401700039000000000401041a000001000500008a000000000454016f000000000603041a000000ff06600190000000010440c1bf000000000041041b000004e906000041000000000464016f000000000603041a0000ff0006600190000001000440c1bf000000000041041b000004ea04400197000000000603041a000004eb06600197000000000464019f000000000041041b0000000501700039000000000401041a000000000454016f0000000205700039000000000505041a000000ff0550018f000000000454019f000000000041041b0000000301700039000000000101041a0000000604700039000000000014041b000000000102041a000004ad01100197000000000407041a000004f604400197000000000114019f000000000017041b000000000403041a000001000100008a000000000414016f00000001044001bf000000000043041b0000000703700039000000000402041a0000002004400270000004ad04400197000000000507041a0000002005500270000004ad05500197000000000445004b00000cba0000813d0000000d04700039000000000504041a000000000515016f000000000603041a000000ff06600190000000010550c1bf000000000054041b000004e906000041000000000565016f000000000603041a0000ff0006600190000001000550c1bf000000000054041b000004ea05500197000000000603041a000004eb06600197000000000565019f000000000054041b0000000804700039000000000404041a0000000e05700039000000000045041b0000000904700039000000000404041a0000000f05700039000000000045041b0000000a04700039000000000404041a0000001005700039000000000045041b0000000b04700039000000000404041a0000001105700039000000000045041b0000000c04700039000000000404041a000004ec044001970000001205700039000000000605041a000004ed06600197000000000446019f000000000045041b000000000202041a000004ee02200197000000000407041a000004ef04400197000000000224019f000000000027041b000000000203041a000000000112016f00000001011001bf000000000013041b000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d2011001c70000800d0200003900000002030000390000051904000041000010180000013d0000000103700039000000000154004b00000cf00000a13d0000000401700039000000000401041a000001000500008a000000000454016f000000000603041a000000ff06600190000000010440c1bf000000000041041b000004e906000041000000000464016f000000000603041a0000ff0006600190000001000440c1bf000000000041041b000004ea04400197000000000603041a000004eb06600197000000000464019f000000000041041b0000000501700039000000000401041a000000000454016f0000000205700039000000000505041a000000ff0550018f000000000454019f000000000041041b0000000301700039000000000101041a0000000604700039000000000014041b000000000102041a000004ad01100197000000000407041a000004f604400197000000000114019f000000000017041b000000000403041a000001000100008a000000000414016f000000000043041b0000000703700039000000000402041a0000002004400270000004ad04400197000000000507041a0000002005500270000004ad05500197000000000445004b00000d2d0000813d0000000d04700039000000000504041a000000000515016f000000000603041a000000ff06600190000000010550c1bf000000000054041b000004e906000041000000000565016f000000000603041a0000ff0006600190000001000550c1bf000000000054041b000004ea05500197000000000603041a000004eb06600197000000000565019f000000000054041b0000000804700039000000000404041a0000000e05700039000000000045041b0000000904700039000000000404041a0000000f05700039000000000045041b0000000a04700039000000000404041a0000001005700039000000000045041b0000000b04700039000000000404041a0000001105700039000000000045041b0000000c04700039000000000404041a000004ec044001970000001205700039000000000605041a000004ed06600197000000000446019f000000000045041b000000000202041a000004ee02200197000000000407041a000004ef04400197000000000224019f000000000027041b000000000203041a000000000112016f000000000013041b000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d2011001c70000800d0200003900000002030000390000050304000041000010180000013d0000000103700039000000000154004b00000d620000a13d0000000401700039000000000401041a000001000500008a000000000454016f000000000603041a000000ff06600190000000010440c1bf000000000041041b000004e906000041000000000464016f000000000603041a0000ff0006600190000001000440c1bf000000000041041b000004ea04400197000000000603041a000004eb06600197000000000464019f000000000041041b0000000501700039000000000401041a000000000454016f0000000205700039000000000505041a000000ff0550018f000000000454019f000000000041041b0000000301700039000000000101041a0000000604700039000000000014041b000000000102041a000004ad01100197000000000407041a000004f604400197000000000114019f000000000017041b000000000403041a000004db01000041000000000414016f00000100044001bf000000000043041b0000000703700039000000000402041a0000002004400270000004ad04400197000000000507041a0000002005500270000004ad05500197000000000445004b00000da10000813d0000000d04700039000000000504041a000001000600008a000000000565016f000000000603041a000000ff06600190000000010550c1bf000000000054041b000004e906000041000000000565016f000000000603041a0000ff0006600190000001000550c1bf000000000054041b000004ea05500197000000000603041a000004eb06600197000000000565019f000000000054041b0000000804700039000000000404041a0000000e05700039000000000045041b0000000904700039000000000404041a0000000f05700039000000000045041b0000000a04700039000000000404041a0000001005700039000000000045041b0000000b04700039000000000404041a0000001105700039000000000045041b0000000c04700039000000000404041a000004ec044001970000001205700039000000000605041a000004ed06600197000000000446019f000000000045041b000000000202041a000004ee02200197000000000407041a000004ef04400197000000000224019f000000000027041b000000000203041a000000000112016f00000100011001bf000000000013041b000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004d2011001c70000800d0200003900000002030000390000051404000041000010180000013d0000009b01000039000000000101041a000704ad0010019b000900980000003d000880100000003d0000000007000019000600000000001d000a00000008001d00000dbb0000013d00000001077000390000000c0170006c000010f40000813d0000000b01000029000000000101041a000000000171004b00000e8e0000a13d000d00000007001d000004e301700041000000000101041a000004d00110019700000000001004350000000901000029000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000000080200002912af12aa0000040f0000000a080000290000000102200190000011c30000613d000000000101043b000000000201041a000004ad02200197000000070220006b00000004020000390000000102002039000000400300043d000004e70430009c0000000d070000290000102e0000213d00000000051200190000008001300039000000400010043f000000000205041a0000001001200270000004ad0410019700000040013000390000000000410435000000ff042001900000000004000019000000010400c03900000000044304360000ff00022001900000000002000019000000010200c0390000000000240435000000400200043d000004f30620009c0000102e0000213d0000004006200039000000400060043f0000000106500039000000000606041a000000f80660021000000000066204360000000205500039000000000505041a0000000000560435000000600530003900000000002504350000000003030433000000000303004b00000db80000613d0000000003040433000000000303004b00000db80000c13d000000400300043d000004f30430009c0000102e0000213d00000000010104330000004004300039000000400040043f00000020043000390000000000240435000004ad011001970000000000130435000000800100043d000000060110006c00000e8e0000a13d00000006020000290000000501200210000000a0011000390000000000310435000000800100043d000000000121004b00000e8e0000a13d0000000601000029000600010010003d00000db80000013d0000009b01000039000000000101041a0000002001100270000804ad0010019b000a00980000003d000980100000003d0000000008000019000700000000001d00000e230000013d0000000701000029000700010010003d00000001088000390000000c0180006c000010fa0000813d0000000b01000029000000000101041a000000000181004b00000e8e0000a13d000d00000008001d000004e301800041000000000101041a000004d00110019700000000001004350000000a01000029000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000000090200002912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000002002200270000004ad02200197000000080220006b0000000d030000390000000703002039000000400200043d000004f80420009c0000000d080000290000102e0000213d0000000004130019000000a001200039000000400010043f000000000504041a0000001001500270000004ad0310019700000040012000390000000000310435000000ff035001900000000003000019000000010300c03900000000033204360000ff00055001900000000005000019000000010500c0390000000000530435000000400500043d000004e60650009c0000102e0000213d0000006006500039000000400060043f0000000106400039000000000606041a00000000066504360000000207400039000000000707041a00000000007604350000000306400039000000000606041a0000004007500039000000000067043500000060062000390000000000560435000000400500043d000004f30750009c0000102e0000213d0000004007500039000000400070043f0000000407400039000000000707041a00000000077504360000000504400039000000000404041a00000080044002100000000000470435000000800420003900000000005404350000000002020433000000000202004b00000e200000613d0000000002030433000000000202004b00000e200000c13d000000400200043d000004e60320009c0000102e0000213d000000000101043300000000030604330000006004200039000000400040043f0000004004200039000000000054043500000020042000390000000000340435000004ad011001970000000000120435000000800100043d000000070110006c00000e8e0000a13d00000007030000290000000501300210000000a0011000390000000000210435000000800100043d000000000131004b00000e1e0000213d000005160100004100000000001004350000003201000039000010310000013d000a00000006001d0000000a0150003900000009025000390000000803500039000700000003001d000000000303041a000800000002001d000000000202041a000900000001001d000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000200210003900000000003204350000006003000039000c00000003001d0000000000310435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000600000001001d000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0005010000000092000000050220017f000000000021041b00000001010003670000002402100370000000000302043b0000004402100370000000000202043b0000006401100370000000000401043b000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000200210003900000000003204350000000c030000290000000000310435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000c00000001001d00000000001004350000000601000029000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000101041a000000ff01100190000011c50000c13d0000000c0100002900000000001004350000000601000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000000050220017f00000001022001bf000000000021041b0000000b030000290000000b013000390000000a02000029000000000202041a0000002002200270000004ad02200197000000000303041a0000002003300270000004ad03300197000000000223004b00000f590000813d0000000b060000290000000d02600039000000000302041a000000050330017f0000000704600039000000000504041a000000ff05500190000000010330c1bf000000000032041b000004e905000041000000000353016f000000000504041a0000ff0005500190000001000330c1bf000000000032041b000004ea03300197000000000404041a000004eb04400197000000000343019f000000000032041b0000000702000029000000000202041a0000000e03600039000000000023041b0000000802000029000000000202041a0000000f03600039000000000023041b0000000902000029000000000202041a0000001003600039000000000023041b000000000201041a0000001103600039000000000023041b0000000c02600039000000000202041a000004ec022001970000001203600039000000000403041a000004ed04400197000000000224019f000000000023041b0000000a02000029000000000202041a000004ee02200197000000000306041a000004ef03300197000000000223019f000000000026041b00000001060003670000002402600370000000000202043b0000000703000029000000000023041b0000004403600370000000000303043b0000000804000029000000000034041b0000006404600370000000000404043b0000000905000029000000000045041b0000008405600370000000000505043b000000000051041b000000a401600370000000000101043b000004ed06100197000000000616004b000011c30000c13d0000000b060000290000000c06600039000000000706041a000004ed077001970000008008100270000000000787019f000000000076041b000000400600043d000000800760003900000000001704350000006001600039000000000051043500000040016000390000000000410435000000200160003900000000003104350000000000260435000004ad010000410000000002000414000004ad0320009c0000000002018019000004ad0360009c00000000060180190000004001600210000000c002200210000000000112019f00000500011001c70000800d0200003900000002030000390000050104000041000010180000013d0000000101700039000000000343004b00000fb60000a13d0000000a070000290000000403700039000000000403041a000001000500008a000000000454016f000000000601041a000000ff06600190000000010440c1bf000000000043041b000004e906000041000000000464016f000000000601041a0000ff0006600190000001000440c1bf000000000043041b000004ea04400197000000000601041a000004eb06600197000000000464019f000000000043041b0000000503700039000000000403041a000000000454016f0000000205700039000000000505041a000000ff0550018f000000000454019f000000000043041b0000000303700039000000000303041a0000000604700039000000000034041b000000000202041a000004ad02200197000000000307041a000004f603300197000000000223019f000000000027041b0000000c040000290000001002400210000004eb02200197000000000301041a000004f003300197000000000223019f000000000021041b000000400100043d0000000000410435000004ad020000410000000003000414000004ad0430009c0000000003028019000004ad0410009c00000000010280190000004001100210000000c002300210000000000112019f000004dd011001c70000800d0200003900000002030000390000050204000041000010180000013d00000000060700190000000702700039000000000343004b000010020000a13d0000000d03600039000000000403041a000001000500008a000000000454016f000000000502041a000000ff05500190000000010440c1bf000000000043041b000004e905000041000000000454016f000000000502041a0000ff0005500190000001000440c1bf000000000043041b000004ea04400197000000000502041a000004eb05500197000000000454019f000000000043041b0000000803600039000000000303041a0000000e04600039000000000034041b0000000903600039000000000303041a0000000f04600039000000000034041b0000000a03600039000000000303041a0000001004600039000000000034041b0000000b03600039000000000303041a0000001104600039000000000034041b0000000c03600039000000000303041a000004ec033001970000001204600039000000000504041a000004ed05500197000000000335019f000000000034041b000000000101041a000004ee01100197000000000306041a000004ef03300197000000000113019f000000000016041b0000000c040000290000001001400210000004eb01100197000000000302041a000004f003300197000000000113019f000000000012041b000000400100043d0000000000410435000004ad020000410000000003000414000004ad0430009c0000000003028019000004ad0410009c00000000010280190000004001100210000000c002300210000000000112019f000004dd011001c70000800d020000390000000203000039000004f1040000410000000d0500002912af12a50000040f0000000101200190000011c30000613d0000000001000019000012b00001042e00000003015000390000000202500039000700000002001d000000000302041a000800000001001d000000000201041a000000400100043d000000400410003900000000002404350000004002000039000b00000002001d0000000002210436000000f8033002100000000000320435000004e60310009c000010340000a13d000005160100004100000000001004350000004101000039000000040010043f0000051701000041000012b1000104300000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000600000001001d000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0005010000000092000000050220017f000000000021041b00000001010003670000002402100370000000000302043b000004f402300197000000000232004b000011c30000c13d0000004401100370000000000201043b000000400100043d00000040041000390000000000240435000000200210003900000000003204350000000b030000290000000000310435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000b00000001001d00000000001004350000000601000029000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000101041a000000ff01100190000011c80000c13d0000000b0100002900000000001004350000000601000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000000050220017f00000001022001bf000000000021041b0000000901000029000000000101041a000004ad011001970000000a02000029000000000202041a000004ad02200197000000000112004b000010d60000813d0000000a050000290000000401500039000000000201041a000000050220017f0000000103500039000000000403041a000000ff04400190000000010220c1bf000000000021041b000004e904000041000000000242016f000000000403041a0000ff0004400190000001000220c1bf000000000021041b000004ea02200197000000000303041a000004eb03300197000000000232019f000000000021041b0000000501500039000000000201041a000000050220017f0000000703000029000000000303041a000000ff0330018f000000000232019f000000000021041b0000000801000029000000000101041a0000000602500039000000000012041b0000000901000029000000000101041a000004ad01100197000000000205041a000004f602200197000000000112019f000000000015041b0000000703000029000000000103041a000000050110017f0000000c04000029000000f802400270000000000121019f000000000013041b00000044010000390000000101100367000000000101043b0000000802000029000000000012041b000000400200043d000000200320003900000000001304350000000000420435000004ad010000410000000003000414000004ad0430009c0000000003018019000004ad0420009c00000000020180190000004001200210000000c002300210000000000112019f000004e1011001c70000800d020000390000000203000039000004f704000041000010180000013d000000400100043d0000000603000029000006990000013d000000400100043d0000050602000041000009460000013d000000400100043d0000000703000029000005190000013d000004e204100041000000000504041a000004d105500197000000000054041b000000010110008a000000000012041b0000000a01000029000000000101041a000c00000001001d00000000003004350000000b01000029000000200010043f000004ad010000410000000002000414000004ad0320009c0000000002018019000000c001200210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d0000000c02000029000004e402200197000000000101043b000000000301041a000004e503300197000000000223019f000000000021041b0000000a020000290000000201200039000000000301041a0000000301200039000000000201041a000000400100043d0000004004100039000000000024043500000040020000390000000002210436000000f8033002100000000000320435000004e60310009c0000102e0000213d0000006003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009901000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a000c0100000000920000000c0220017f000000000021041b0000000a040000290000000801400039000000000301041a0000000901400039000000000201041a0000000a01400039000000000401041a000000400100043d0000006005100039000000000045043500000040041000390000000000240435000000600200003900000000022104360000000000320435000004e70310009c0000102e0000213d0000008003100039000000400030043f000004ad04000041000004ad0320009c000000000204801900000040022002100000000001010433000004ad0310009c00000000010480190000006001100210000000000121019f0000000002000414000004ad0320009c0000000002048019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b00000000001004350000009a01000039000000200010043f0000000001000414000004ad0210009c000004ad01008041000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000201041a0000000c0220017f000000000021041b0000000d0100002900000000001004350000000b01000029000000200010043f000004ad030000410000000001000414000004ad0210009c0000000001038019000000c001100210000004e1011001c7000080100200003912af12aa0000040f0000000102200190000011c30000613d000000000101043b000000000001041b0000000102100039000000000002041b0000000202100039000000000002041b0000000302100039000000000002041b0000000402100039000000000002041b0000000502100039000000000002041b0000000602100039000000000002041b0000000702100039000000000002041b0000000802100039000000000002041b0000000902100039000000000002041b0000000a02100039000000000002041b0000000b02100039000000000002041b0000000c02100039000000000002041b0000000d02100039000000000002041b0000000e02100039000000000002041b0000000f02100039000000000002041b0000001002100039000000000002041b0000001102100039000000000002041b0000001201100039000000000001041b0000000001000414000004ad0210009c000004ad01008041000000c001100210000004d2011001c70000800d020000390000000203000039000004e804000041000010180000013d0000000001000019000012b100010430000000400100043d0000050702000041000009460000013d000000400100043d000004f502000041000009460000013d000004f5010000410000000000120435000004ad01000041000004ad0320009c00000000020180190000004001200210000004e0011001c7000012b1000104300000000002010019000000400100043d0000051c0310009c000011f60000813d0000008003100039000000400030043f000000000302041a0000001004300270000004ad04400197000000400510003900000000004504350000ff00043001900000000004000019000000010400c03900000020051000390000000000450435000000ff033001900000000003000019000000010300c0390000000000310435000000400300043d000004f30430009c000011f60000213d0000004004300039000000400040043f0000000104200039000000000404041a000000f80440021000000000044304360000000202200039000000000202041a000000000024043500000060021000390000000000320435000000000001042d000005160100004100000000001004350000004101000039000000040010043f0000051701000041000012b1000104300000000002010019000000400100043d0000051d0310009c000012300000813d000000a003100039000000400030043f000000000302041a0000001004300270000004ad04400197000000400510003900000000004504350000ff00043001900000000004000019000000010400c03900000020051000390000000000450435000000ff033001900000000003000019000000010300c0390000000000310435000000400300043d000004e60430009c000012300000213d0000006004300039000000400040043f0000000104200039000000000404041a00000000044304360000000205200039000000000505041a00000000005404350000000304200039000000000404041a0000004005300039000000000045043500000060041000390000000000340435000000400300043d000004f30430009c000012300000213d0000004004300039000000400040043f0000000404200039000000000404041a00000000044304360000000502200039000000000202041a0000008002200210000000000024043500000080021000390000000000320435000000000001042d000005160100004100000000001004350000004101000039000000040010043f0000051701000041000012b1000104300000000043010434000000000303004b0000000003000019000000010300c03900000000033204360000000004040433000000000404004b0000000004000019000000010400c039000000000043043500000040031000390000000003030433000004ad0330019700000040042000390000000000340435000000600110003900000000010104330000000031010434000004f40110019700000060042000390000000000140435000000800120003900000000020304330000000000210435000000000001042d0000000043010434000000000303004b0000000003000019000000010300c03900000000033204360000000004040433000000000404004b0000000004000019000000010400c039000000000043043500000040031000390000000003030433000004ad03300197000000400420003900000000003404350000006003100039000000000303043300000060042000390000000065030434000000000054043500000000040604330000008005200039000000000045043500000040033000390000000003030433000000a004200039000000000034043500000080011000390000000001010433000000c00320003900000000410104340000000000130435000000e0012000390000000002040433000004ed022001970000000000210435000000000001042d0000006502000039000000000302041a000004d103300197000000000032041b000004d0061001970000003301000039000000000201041a000004d103200197000000000363019f000000000031041b000004ad010000410000000003000414000004ad0430009c0000000003018019000000c001300210000004d2011001c7000004d0052001970000800d020000390000000303000039000004dc0400004112af12a50000040f00000001012001900000128c0000613d000000000001042d0000000001000019000012b100010430000000000001042f000004ad03000041000004ad0410009c00000000010380190000004001100210000004ad0420009c00000000020380190000006002200210000000000112019f0000000002000414000004ad0420009c0000000002038019000000c002200210000000000112019f000004d2011001c7000080100200003912af12aa0000040f0000000102200190000012a30000613d000000000101043b000000000001042d0000000001000019000012b100010430000012a8002104210000000102000039000000000001042d0000000002000019000000000001042d000012ad002104230000000102000039000000000001042d0000000002000019000000000001042d000012af00000432000012b00001042e000012b1000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff000000020000000000000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000740211cd0000000000000000000000000000000000000000000000000000000099624cb500000000000000000000000000000000000000000000000000000000d113233100000000000000000000000000000000000000000000000000000000e8de12de00000000000000000000000000000000000000000000000000000000e8de12df00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000d113233200000000000000000000000000000000000000000000000000000000e30c39780000000000000000000000000000000000000000000000000000000099624cb6000000000000000000000000000000000000000000000000000000009ec3f92700000000000000000000000000000000000000000000000000000000c4d66de80000000000000000000000000000000000000000000000000000000094ca304a0000000000000000000000000000000000000000000000000000000094ca304b0000000000000000000000000000000000000000000000000000000095570d1200000000000000000000000000000000000000000000000000000000994057ef00000000000000000000000000000000000000000000000000000000740211ce0000000000000000000000000000000000000000000000000000000079ba5097000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000003ea053ea000000000000000000000000000000000000000000000000000000005139839b000000000000000000000000000000000000000000000000000000005139839c000000000000000000000000000000000000000000000000000000005875da2b00000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000003ea053eb00000000000000000000000000000000000000000000000000000000426cb7660000000000000000000000000000000000000000000000000000000047b4a7a60000000000000000000000000000000000000000000000000000000029092d0d0000000000000000000000000000000000000000000000000000000029092d0e000000000000000000000000000000000000000000000000000000002f9c8f0d000000000000000000000000000000000000000000000000000000003d1f16d40000000000000000000000000000000000000000000000000000000008dc336000000000000000000000000000000000000000000000000000000000189a5a17000000000000000000000000000000000000000000000000000000001c5a9d9c000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000038d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270000000000000000000000000000000000000000200000008000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000647920696e697469616c697a6564000000000000000000000000000000000000496e697469616c697a61626c653a20636f6e747261637420697320616c72656108c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e002000000000000000000000000000000000000200000000000000000000000007f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498c7eabfa90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000200000000000000000000000000000000000040000000000000000000000000354a83ed9988f79f6038d4c7a7dadbad8af32f4ad6df893e0e5807a1b1944ff8354a83ed9988f79f6038d4c7a7dadbad8af32f4ad6df893e0e5807a1b1944ff90000000000000000000000000000000000000000ffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff9f000000000000000000000000000000000000000000000000ffffffffffffff7f1629bfc36423a1b4749d3fe1d6970b9d32d42bbee47dd5540670696ab6b9a4adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0001ffffffffffffffffffffffffffffffffffffffffffffffffffff0000000001010000000000000000000000000000000000000000000000000000ffffffff000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffc810fe33ecde832d7a0b696cf1738e8ec84938965b214bd4e1195ef8d6e8dd26000000000000000000000000000000000000000000000000ffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffbfff00000000000000000000000000000000000000000000000000000000000000564da7df00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000205a2493904fd7ff8685b368c0a13560ddcc577aac288385c5834c57996c9ad2000000000000000000000000000000000000000000000000ffffffffffffff5f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206e6577206f776e657200000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000800000000000000000000000000000000000000000000000000000000000000000000000010000000002000000000000000000000000000000000000200000008000000000000000003d2e97fa99e681fa81a4ec393f21f6b0fcccca1463d6bf43cb3a80299968091c000000000000000000000000000000010000000000000000000000000000000002000000000000000000000000000000000000a0000000000000000000000000a88f0bfec4ed62be2eb084417ce4a44e7289b24faec9f1ae553fce55c475c3d25c0844614cb8580962e0ce8f75301a64eccd757945ce5620b7d84b65e232a673d9957750e6343405c319eb99a4ec67fa11cfd66969318cbc71aa2d45fa53a349164b707307f2b1481ff9787806cdcc4d8b12e532a6a84dd0a3f4c4507c1808e700ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6b0949d8000000000000000000000000000000000000000000000000000000001a956ace000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff1fffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000020000000000000000000000000000000000012000000000000000000000000034a1749086dfd00e126255be02329843f1c05be61db5c1fc80ceefc38ccef67683ee5ccc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000008000000000000000001088e0c600000000000000000000000000000000000000000000000000000000c5cbf870000000000000000000000000000000000000000000000000000000004f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65720000000000000000000000000000000000000064000000800000000000000000cfc24166db4bb677e857cacabd1541fb2b30645021b27c5130419589b84db52b2fc842bf000000000000000000000000000000000000000000000000000000004e487b71000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffa07dc8b937d2916b130743c447af3d771fa55e66b7393105150e2e635ac3e87260bdc213f90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a0000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff80000000000000000000000000000000000000000000000000ffffffffffffff605c3973df1c57590f450df32f693e00b74a06572949ddc108dd33c91827cf42f0", + "linkReferences": {}, + "deployedLinkReferences": {}, + "factoryDeps": {} +} diff --git a/zk_toolbox/crates/zk_inception/build.rs b/zk_toolbox/crates/zk_inception/build.rs index 5134ff3886e0..43c8d7a5aac9 100644 --- a/zk_toolbox/crates/zk_inception/build.rs +++ b/zk_toolbox/crates/zk_inception/build.rs @@ -4,7 +4,7 @@ use ethers::contract::Abigen; fn main() -> eyre::Result<()> { let outdir = PathBuf::from(std::env::var("OUT_DIR")?).canonicalize()?; - Abigen::new("ConsensusRegistry", "../../../contracts/l2-contracts/artifacts-zk/contracts/ConsensusRegistry.sol/ConsensusRegistry.json")? + Abigen::new("ConsensusRegistry", "abi/ConsensusRegistry.json")? .generate()? .write_to_file(outdir.join("consensus_registry_abi.rs"))?; Ok(()) diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs index 1c809e33c9d8..4db2553a3eba 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs @@ -109,6 +109,24 @@ impl TxSet { } } +async fn get_attester_committee( + consensus_registry: &abi::ConsensusRegistry, +) -> anyhow::Result { + let attesters = consensus_registry + .get_attester_committee() + .call() + .await + .context("get_attester_committee()")?; + let attesters: Vec<_> = attesters + .iter() + .map(decode_weighted_attester) + .collect::>() + .context("decode_weighted_attester")?; + let attesters = + attester::Committee::new(attesters.into_iter()).context("attester::Committee::new()")?; + Ok(attesters) +} + impl Command { pub(crate) async fn run(self, shell: &Shell) -> anyhow::Result<()> { let ecosystem_config = EcosystemConfig::from_file(shell)?; @@ -223,7 +241,7 @@ impl Command { // Update the state. let mut txs = TxSet::default(); - let mut want: HashMap<_, _> = + let mut to_insert: HashMap<_, _> = want.iter().map(|a| (a.key.clone(), a.weight)).collect(); for (i, node) in nodes.into_iter().enumerate() { if node.attester_latest.removed { @@ -234,7 +252,7 @@ impl Command { .context("decode_attester_key")?, weight: node.attester_latest.weight.into(), }; - if let Some(weight) = want.remove(&got.key) { + if let Some(weight) = to_insert.remove(&got.key) { if weight != got.weight { txs.send( "changed_attester_weight", @@ -254,7 +272,7 @@ impl Command { .await?; } } - for (key, weight) in want { + for (key, weight) in to_insert { let vk = validator::SecretKey::generate(); txs.send( "add", @@ -275,17 +293,15 @@ impl Command { ) .await?; txs.wait(&provider).await.context("wait()")?; + let got = get_attester_committee(&consensus_registry).await?; + anyhow::ensure!( + got == want, + "setting attester committee failed: got {got:?}, want {want:?}" + ); println!("done"); } Self::GetAttesterCommittee => { - let attesters = consensus_registry.get_attester_committee().call().await?; - let attesters: Vec<_> = attesters - .iter() - .map(decode_weighted_attester) - .collect::>() - .context("decode_weighted_attester")?; - let attesters = attester::Committee::new(attesters.into_iter()) - .context("attester::Committee::new()")?; + let attesters = get_attester_committee(&consensus_registry).await?; for a in attesters.iter() { println!("{a:?}"); } From 024af6f50fea012e1e9c6d8ce316f9ab61dc40de Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Wed, 18 Sep 2024 13:28:03 +0200 Subject: [PATCH 18/22] zk lint --- zk_toolbox/crates/zk_inception/src/commands/consensus.rs | 3 ++- zk_toolbox/crates/zk_inception/src/utils/consensus.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs index 4db2553a3eba..f39179ed539f 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs @@ -19,6 +19,7 @@ use zksync_consensus_roles::{attester, validator}; use crate::{messages, utils::consensus::parse_attester_committee}; +#[allow(warnings)] mod abi { include!(concat!(env!("OUT_DIR"), "/consensus_registry_abi.rs")); } @@ -205,7 +206,7 @@ impl Command { ) })() .context("consensus.genesis_spec.attesters missing in general.yaml")?; - let want = parse_attester_committee(&want).context("parse_attester_committee()")?; + let want = parse_attester_committee(want).context("parse_attester_committee()")?; // Fetch contract state. let n: usize = consensus_registry diff --git a/zk_toolbox/crates/zk_inception/src/utils/consensus.rs b/zk_toolbox/crates/zk_inception/src/utils/consensus.rs index c1d3e963c7c4..7166a4ebfc0f 100644 --- a/zk_toolbox/crates/zk_inception/src/utils/consensus.rs +++ b/zk_toolbox/crates/zk_inception/src/utils/consensus.rs @@ -34,7 +34,7 @@ pub(crate) fn parse_attester_committee( }) .collect::>() .context("attesters")?; - attester::Committee::new(attesters.into_iter()).context("Committee::new()") + attester::Committee::new(attesters).context("Committee::new()") } #[derive(Debug, Clone)] From 773c00bbcb358d91424cce03fd37183c32ae26ca Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Thu, 19 Sep 2024 11:33:06 +0200 Subject: [PATCH 19/22] reverted garbage --- .../src/web3/backend_jsonrpsee/namespaces/eth.rs | 5 +---- zk_toolbox/crates/config/src/chain.rs | 13 +------------ 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs index 2f0ec8902245..15528c5b309b 100644 --- a/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs +++ b/core/node/api_server/src/web3/backend_jsonrpsee/namespaces/eth.rs @@ -46,10 +46,7 @@ impl EthNamespaceServer for EthNamespace { ) -> RpcResult { self.estimate_gas_impl(req, block, state_override) .await - .map_err(|err| { - tracing::error!("estimate_gas(): {err:#}"); - self.current_method().map_err(err) - }) + .map_err(|err| self.current_method().map_err(err)) } async fn gas_price(&self) -> RpcResult { diff --git a/zk_toolbox/crates/config/src/chain.rs b/zk_toolbox/crates/config/src/chain.rs index 93b4f33d9a1a..affc8ccc770c 100644 --- a/zk_toolbox/crates/config/src/chain.rs +++ b/zk_toolbox/crates/config/src/chain.rs @@ -18,12 +18,7 @@ use crate::{ FileConfigWithDefaultName, ReadConfig, ReadConfigWithBasePath, SaveConfig, SaveConfigWithBasePath, ZkToolboxConfig, }, - //external_node::ENConfig, - ContractsConfig, - GeneralConfig, - GenesisConfig, - SecretsConfig, - WalletsConfig, + ContractsConfig, GeneralConfig, GenesisConfig, SecretsConfig, WalletsConfig, }; /// Chain configuration file. This file is created in the chain @@ -102,16 +97,10 @@ impl ChainConfig { } anyhow::bail!("Wallets configs has not been found"); } - pub fn get_contracts_config(&self) -> anyhow::Result { ContractsConfig::read_with_base_path(self.get_shell(), &self.configs) } - /* - pub fn get_external_node_config(&self) -> anyhow::Result { - ENConfig::read_with_base_path(self.get_shell(), &self.configs) - }*/ - pub fn get_secrets_config(&self) -> anyhow::Result { SecretsConfig::read_with_base_path(self.get_shell(), &self.configs) } From 3e63bc30c1dcf1c1bff6a014b4b1ce25a2606e68 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Thu, 19 Sep 2024 12:01:40 +0200 Subject: [PATCH 20/22] logger --- zk_toolbox/Cargo.lock | 1 - zk_toolbox/crates/zk_inception/Cargo.toml | 1 - .../zk_inception/src/commands/consensus.rs | 18 +++++++++++++----- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/zk_toolbox/Cargo.lock b/zk_toolbox/Cargo.lock index c8542ebdc787..9379c6427167 100644 --- a/zk_toolbox/Cargo.lock +++ b/zk_toolbox/Cargo.lock @@ -6416,7 +6416,6 @@ dependencies = [ "cliclack", "common", "config", - "console", "ethers", "eyre", "human-panic", diff --git a/zk_toolbox/crates/zk_inception/Cargo.toml b/zk_toolbox/crates/zk_inception/Cargo.toml index 6b7d50b835dd..28b709c557b7 100644 --- a/zk_toolbox/crates/zk_inception/Cargo.toml +++ b/zk_toolbox/crates/zk_inception/Cargo.toml @@ -15,7 +15,6 @@ anyhow.workspace = true clap.workspace = true cliclack.workspace = true config.workspace = true -console.workspace = true human-panic.workspace = true lazy_static.workspace = true serde_yaml.workspace = true diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs index f39179ed539f..06bfd12b8511 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs @@ -3,7 +3,7 @@ use std::{borrow::Borrow, collections::HashMap, sync::Arc}; /// Consensus registry contract operations. /// Includes code duplicated from `zksync_node_consensus::registry::abi`. use anyhow::Context as _; -use common::config::global_config; +use common::{config::global_config, logger}; use config::EcosystemConfig; use ethers::{ abi::Detokenize, @@ -128,6 +128,16 @@ async fn get_attester_committee( Ok(attesters) } +fn print_attesters(committee: &attester::Committee) { + logger::success( + committee + .iter() + .map(|a| format!("{a:?}")) + .collect::>() + .join("\n"), + ); +} + impl Command { pub(crate) async fn run(self, shell: &Shell) -> anyhow::Result<()> { let ecosystem_config = EcosystemConfig::from_file(shell)?; @@ -299,13 +309,11 @@ impl Command { got == want, "setting attester committee failed: got {got:?}, want {want:?}" ); - println!("done"); + print_attesters(&got); } Self::GetAttesterCommittee => { let attesters = get_attester_committee(&consensus_registry).await?; - for a in attesters.iter() { - println!("{a:?}"); - } + print_attesters(&attesters); } } Ok(()) From 0137e00556ad2adcb7d83852debd5e7f8e68032f Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Thu, 26 Sep 2024 13:47:23 +0200 Subject: [PATCH 21/22] reorganized code --- .../zk_inception/src/commands/consensus.rs | 372 ++++++++++-------- 1 file changed, 208 insertions(+), 164 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs index 06bfd12b8511..41b968e71289 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs @@ -11,7 +11,7 @@ use ethers::{ middleware::{Middleware, NonceManagerMiddleware, SignerMiddleware}, providers::{Http, JsonRpcClient, PendingTransaction, Provider, RawCall as _}, signers::{LocalWallet, Signer as _}, - types::{BlockId, H256}, + types::{Address, BlockId, H256}, }; use xshell::Shell; use zksync_consensus_crypto::ByteFmt; @@ -110,24 +110,6 @@ impl TxSet { } } -async fn get_attester_committee( - consensus_registry: &abi::ConsensusRegistry, -) -> anyhow::Result { - let attesters = consensus_registry - .get_attester_committee() - .call() - .await - .context("get_attester_committee()")?; - let attesters: Vec<_> = attesters - .iter() - .map(decode_weighted_attester) - .collect::>() - .context("decode_weighted_attester")?; - let attesters = - attester::Committee::new(attesters.into_iter()).context("attester::Committee::new()")?; - Ok(attesters) -} - fn print_attesters(committee: &attester::Committee) { logger::success( committee @@ -138,19 +120,43 @@ fn print_attesters(committee: &attester::Committee) { ); } -impl Command { - pub(crate) async fn run(self, shell: &Shell) -> anyhow::Result<()> { - let ecosystem_config = EcosystemConfig::from_file(shell)?; - let chain_name = global_config().chain_name.clone(); - let chain_config = ecosystem_config - .load_chain(chain_name) - .context(messages::MSG_CHAIN_NOT_INITIALIZED)?; +struct Setup { + chain: config::ChainConfig, + contracts: config::ContractsConfig, + general: config::GeneralConfig, + genesis: config::GenesisConfig, +} + +impl Setup { + fn provider(&self) -> anyhow::Result> { + let l2_url = &self + .general + .api_config + .as_ref() + .context("api_config missing")? + .web3_json_rpc + .http_url; + Provider::try_from(l2_url).with_context(|| format!("Provider::try_from({l2_url})")) + } + + fn multicall(&self, m: Arc) -> anyhow::Result> { + Ok(Multicall::new_with_chain_id( + m, + Some( + self.chain + .get_contracts_config() + .context("get_contracts_config()")? + .l2 + .multicall3 + .context("multicall3 contract not configured")?, + ), + Some(self.genesis.l2_chain_id.as_u64()), + )?) + } - let chain_id = chain_config - .get_genesis_config() - .context("get_genesis_config()")? - .l2_chain_id; - let governor = chain_config + fn governor(&self) -> anyhow::Result> { + let governor = self + .chain .get_wallets_config() .context("get_secrets_config()")? .governor @@ -158,153 +164,191 @@ impl Command { .context("governor private key not set")?; let governor = LocalWallet::from_bytes(governor.as_bytes()) .context("LocalWallet::from_bytes()")? - .with_chain_id(chain_id.as_u64()); - - let cfg = chain_config - .get_general_config() - .context("get_general_config()")?; - let l2_url = &cfg - .api_config - .as_ref() - .context("api_config missing")? - .web3_json_rpc - .http_url; - let provider: Provider = l2_url - .try_into() - .with_context(|| format!("{l2_url}.try_into::()"))?; - let block_id = BlockId::from( - provider - .get_block_number() - .await - .context("get_block_number")?, - ); - let signer = SignerMiddleware::new(provider.clone(), governor.clone()); + .with_chain_id(self.genesis.l2_chain_id.as_u64()); + let provider = self.provider().context("provider()")?; + let signer = SignerMiddleware::new(provider, governor.clone()); // Allows us to send next transaction without waiting for the previous to complete. let signer = NonceManagerMiddleware::new(signer, governor.address()); - let signer = Arc::new(signer); + Ok(Arc::new(signer)) + } - let contracts_cfg = chain_config + fn new(shell: &Shell) -> anyhow::Result { + let ecosystem_config = EcosystemConfig::from_file(shell)?; + let chain_name = global_config().chain_name.clone(); + let chain = ecosystem_config + .load_chain(chain_name) + .context(messages::MSG_CHAIN_NOT_INITIALIZED)?; + let contracts = chain .get_contracts_config() .context("get_contracts_config()")?; - // We use it to batch read calls. - let mut multicall = Multicall::new_with_chain_id( - signer.clone(), - Some( - contracts_cfg - .l2 - .multicall3 - .context("multicall3 contract not configured")?, - ), - Some(chain_id.as_u64()), - ) - .context("Multicall::new()")?; - let addr = contracts_cfg + let genesis = chain.get_genesis_config().context("get_genesis_config()")?; + let general = chain.get_general_config().context("get_general_config()")?; + Ok(Self { + chain, + contracts, + general, + genesis, + }) + } + + fn consensus_registry( + &self, + m: Arc, + ) -> anyhow::Result> { + let addr = self + .contracts .l2 .consensus_registry .context("consensus_registry address not configured")?; - let consensus_registry = abi::ConsensusRegistry::new(addr, signer.clone()); - match self { - Self::SetAttesterCommittee => { - // Fetch the desired state. - let want = (|| { - Some( - &cfg.consensus_config - .as_ref()? - .genesis_spec - .as_ref()? - .attesters, - ) - })() - .context("consensus.genesis_spec.attesters missing in general.yaml")?; - let want = parse_attester_committee(want).context("parse_attester_committee()")?; + Ok(abi::ConsensusRegistry::new(addr, m)) + } - // Fetch contract state. - let n: usize = consensus_registry - .num_nodes() - .call_raw() - .block(block_id) - .await - .context("num_nodes()")? - .try_into() - .ok() - .context("overflow")?; - multicall.block = Some(block_id); - let node_owners: Vec = multicall - .add_calls( - false, - (0..n).map(|i| consensus_registry.node_owners(i.into())), - ) - .call_array() - .await - .context("node_owners()")?; - multicall.clear_calls(); - let nodes: Vec = multicall - .add_calls( - false, - node_owners - .iter() - .map(|addr| consensus_registry.nodes(*addr)), - ) - .call_array() - .await - .context("nodes()")?; - multicall.clear_calls(); + async fn last_block(&self, m: &(impl 'static + Middleware)) -> anyhow::Result { + Ok(m.get_block_number() + .await + .context("get_block_number")? + .into()) + } - // Update the state. - let mut txs = TxSet::default(); - let mut to_insert: HashMap<_, _> = - want.iter().map(|a| (a.key.clone(), a.weight)).collect(); - for (i, node) in nodes.into_iter().enumerate() { - if node.attester_latest.removed { - continue; - } - let got = attester::WeightedAttester { - key: decode_attester_key(&node.attester_latest.pub_key) - .context("decode_attester_key")?, - weight: node.attester_latest.weight.into(), - }; - if let Some(weight) = to_insert.remove(&got.key) { - if weight != got.weight { - txs.send( - "changed_attester_weight", - consensus_registry.change_attester_weight( - node_owners[i], - weight.try_into().context("overflow")?, - ), - ) - .await?; - } - if !node.attester_latest.active { - txs.send("activate", consensus_registry.activate(node_owners[i])) - .await?; - } - } else { - txs.send("remove", consensus_registry.remove(node_owners[i])) - .await?; - } - } - for (key, weight) in to_insert { - let vk = validator::SecretKey::generate(); + async fn get_attester_committee(&self) -> anyhow::Result { + let provider = Arc::new(self.provider()?); + let consensus_registry = self + .consensus_registry(provider) + .context("consensus_registry()")?; + let attesters = consensus_registry + .get_attester_committee() + .call() + .await + .context("get_attester_committee()")?; + let attesters: Vec<_> = attesters + .iter() + .map(decode_weighted_attester) + .collect::>() + .context("decode_weighted_attester")?; + attester::Committee::new(attesters.into_iter()).context("attester::Committee::new()") + } + + async fn set_attester_committee(&self) -> anyhow::Result { + // Fetch the desired state. + let want = (|| { + Some( + &self + .general + .consensus_config + .as_ref()? + .genesis_spec + .as_ref()? + .attesters, + ) + })() + .context("consensus.genesis_spec.attesters missing in general.yaml")?; + let want = parse_attester_committee(want).context("parse_attester_committee()")?; + + let provider = self.provider().context("provider()")?; + let block_id = self.last_block(&provider).await.context("last_block()")?; + let governor = self.governor().context("governor()")?; + let consensus_registry = self + .consensus_registry(governor.clone()) + .context("consensus_registry")?; + let mut multicall = self.multicall(governor.clone()).context("multicall()")?; + + // Fetch contract state. + let n: usize = consensus_registry + .num_nodes() + .call_raw() + .block(block_id) + .await + .context("num_nodes()")? + .try_into() + .ok() + .context("overflow")?; + + multicall.block = Some(block_id); + let node_owners: Vec

= multicall + .add_calls( + false, + (0..n).map(|i| consensus_registry.node_owners(i.into())), + ) + .call_array() + .await + .context("node_owners()")?; + multicall.clear_calls(); + let nodes: Vec = multicall + .add_calls( + false, + node_owners + .iter() + .map(|addr| consensus_registry.nodes(*addr)), + ) + .call_array() + .await + .context("nodes()")?; + multicall.clear_calls(); + + // Update the state. + let mut txs = TxSet::default(); + let mut to_insert: HashMap<_, _> = want.iter().map(|a| (a.key.clone(), a.weight)).collect(); + for (i, node) in nodes.into_iter().enumerate() { + if node.attester_latest.removed { + continue; + } + let got = attester::WeightedAttester { + key: decode_attester_key(&node.attester_latest.pub_key) + .context("decode_attester_key")?, + weight: node.attester_latest.weight.into(), + }; + if let Some(weight) = to_insert.remove(&got.key) { + if weight != got.weight { txs.send( - "add", - consensus_registry.add( - ethers::types::Address::random(), - /*validator_weight=*/ 1, - encode_validator_key(&vk.public()), - encode_validator_pop(&vk.sign_pop()), + "changed_attester_weight", + consensus_registry.change_attester_weight( + node_owners[i], weight.try_into().context("overflow")?, - encode_attester_key(&key), ), ) .await?; } - txs.send( - "commit_attester_committee", - consensus_registry.commit_attester_committee(), - ) - .await?; - txs.wait(&provider).await.context("wait()")?; - let got = get_attester_committee(&consensus_registry).await?; + if !node.attester_latest.active { + txs.send("activate", consensus_registry.activate(node_owners[i])) + .await?; + } + } else { + txs.send("remove", consensus_registry.remove(node_owners[i])) + .await?; + } + } + for (key, weight) in to_insert { + let vk = validator::SecretKey::generate(); + txs.send( + "add", + consensus_registry.add( + Address::random(), + /*validator_weight=*/ 1, + encode_validator_key(&vk.public()), + encode_validator_pop(&vk.sign_pop()), + weight.try_into().context("overflow")?, + encode_attester_key(&key), + ), + ) + .await?; + } + txs.send( + "commit_attester_committee", + consensus_registry.commit_attester_committee(), + ) + .await?; + txs.wait(&provider).await.context("wait()")?; + Ok(want) + } +} + +impl Command { + pub(crate) async fn run(self, shell: &Shell) -> anyhow::Result<()> { + let setup = Setup::new(shell).context("Setup::new()")?; + match self { + Self::SetAttesterCommittee => { + let want = setup.set_attester_committee().await?; + let got = setup.get_attester_committee().await?; anyhow::ensure!( got == want, "setting attester committee failed: got {got:?}, want {want:?}" @@ -312,8 +356,8 @@ impl Command { print_attesters(&got); } Self::GetAttesterCommittee => { - let attesters = get_attester_committee(&consensus_registry).await?; - print_attesters(&attesters); + let got = setup.get_attester_committee().await?; + print_attesters(&got); } } Ok(()) From 407ceb7d5634555edb9b26b1e63d0b89dc2d6d61 Mon Sep 17 00:00:00 2001 From: Grzegorz Prusak Date: Thu, 26 Sep 2024 15:34:42 +0200 Subject: [PATCH 22/22] moved strings --- .../zk_inception/src/commands/consensus.rs | 32 +++++++++---------- .../crates/zk_inception/src/messages.rs | 20 ++++++++++++ 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/zk_toolbox/crates/zk_inception/src/commands/consensus.rs b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs index 41b968e71289..6cc63b0bafa4 100644 --- a/zk_toolbox/crates/zk_inception/src/commands/consensus.rs +++ b/zk_toolbox/crates/zk_inception/src/commands/consensus.rs @@ -97,10 +97,10 @@ impl TxSet { let status = PendingTransaction::new(h, provider) .await .context("await")? - .context("receipt missing")? + .context(messages::MSG_RECEIPT_MISSING)? .status - .context("status missing")?; - anyhow::ensure!(status == 1.into(), "transaction failed"); + .context(messages::MSG_STATUS_MISSING)?; + anyhow::ensure!(status == 1.into(), messages::MSG_TRANSACTION_FAILED); Ok(()) } .await @@ -133,7 +133,7 @@ impl Setup { .general .api_config .as_ref() - .context("api_config missing")? + .context(messages::MSG_API_CONFIG_MISSING)? .web3_json_rpc .http_url; Provider::try_from(l2_url).with_context(|| format!("Provider::try_from({l2_url})")) @@ -148,7 +148,7 @@ impl Setup { .context("get_contracts_config()")? .l2 .multicall3 - .context("multicall3 contract not configured")?, + .context(messages::MSG_MULTICALL3_CONTRACT_NOT_CONFIGURED)?, ), Some(self.genesis.l2_chain_id.as_u64()), )?) @@ -158,10 +158,10 @@ impl Setup { let governor = self .chain .get_wallets_config() - .context("get_secrets_config()")? + .context("get_wallets_config()")? .governor .private_key - .context("governor private key not set")?; + .context(messages::MSG_GOVERNOR_PRIVATE_KEY_NOT_SET)?; let governor = LocalWallet::from_bytes(governor.as_bytes()) .context("LocalWallet::from_bytes()")? .with_chain_id(self.genesis.l2_chain_id.as_u64()); @@ -199,14 +199,14 @@ impl Setup { .contracts .l2 .consensus_registry - .context("consensus_registry address not configured")?; + .context(messages::MSG_CONSENSUS_REGISTRY_ADDRESS_NOT_CONFIGURED)?; Ok(abi::ConsensusRegistry::new(addr, m)) } async fn last_block(&self, m: &(impl 'static + Middleware)) -> anyhow::Result { Ok(m.get_block_number() .await - .context("get_block_number")? + .context("get_block_number()")? .into()) } @@ -224,7 +224,7 @@ impl Setup { .iter() .map(decode_weighted_attester) .collect::>() - .context("decode_weighted_attester")?; + .context("decode_weighted_attester()")?; attester::Committee::new(attesters.into_iter()).context("attester::Committee::new()") } @@ -241,7 +241,7 @@ impl Setup { .attesters, ) })() - .context("consensus.genesis_spec.attesters missing in general.yaml")?; + .context(messages::MSG_CONSENSUS_GENESIS_SPEC_ATTESTERS_MISSING_IN_GENERAL_YAML)?; let want = parse_attester_committee(want).context("parse_attester_committee()")?; let provider = self.provider().context("provider()")?; @@ -249,7 +249,7 @@ impl Setup { let governor = self.governor().context("governor()")?; let consensus_registry = self .consensus_registry(governor.clone()) - .context("consensus_registry")?; + .context("consensus_registry()")?; let mut multicall = self.multicall(governor.clone()).context("multicall()")?; // Fetch contract state. @@ -261,7 +261,7 @@ impl Setup { .context("num_nodes()")? .try_into() .ok() - .context("overflow")?; + .context("num_nodes() overflow")?; multicall.block = Some(block_id); let node_owners: Vec
= multicall @@ -294,7 +294,7 @@ impl Setup { } let got = attester::WeightedAttester { key: decode_attester_key(&node.attester_latest.pub_key) - .context("decode_attester_key")?, + .context("decode_attester_key()")?, weight: node.attester_latest.weight.into(), }; if let Some(weight) = to_insert.remove(&got.key) { @@ -303,7 +303,7 @@ impl Setup { "changed_attester_weight", consensus_registry.change_attester_weight( node_owners[i], - weight.try_into().context("overflow")?, + weight.try_into().context("weight overflow")?, ), ) .await?; @@ -351,7 +351,7 @@ impl Command { let got = setup.get_attester_committee().await?; anyhow::ensure!( got == want, - "setting attester committee failed: got {got:?}, want {want:?}" + messages::msg_setting_attester_committee_failed(&got, &want) ); print_attesters(&got); } diff --git a/zk_toolbox/crates/zk_inception/src/messages.rs b/zk_toolbox/crates/zk_inception/src/messages.rs index 3bbac066dbb6..1bf3b0d598aa 100644 --- a/zk_toolbox/crates/zk_inception/src/messages.rs +++ b/zk_toolbox/crates/zk_inception/src/messages.rs @@ -4,6 +4,7 @@ use ethers::{ types::{H160, U256}, utils::format_ether, }; +use zksync_consensus_roles::attester; pub(super) const MSG_SETUP_KEYS_DOWNLOAD_SELECTION_PROMPT: &str = "Do you want to download the setup keys or generate them?"; @@ -481,3 +482,22 @@ pub(super) fn msg_diff_secrets( pub(super) fn msg_updating_chain(chain: &str) -> String { format!("Updating chain: {}", chain) } + +/// consensus command messages +pub(super) const MSG_RECEIPT_MISSING: &str = "receipt missing"; +pub(super) const MSG_STATUS_MISSING: &str = "status missing"; +pub(super) const MSG_TRANSACTION_FAILED: &str = "transaction failed"; +pub(super) const MSG_API_CONFIG_MISSING: &str = "api config missing"; +pub(super) const MSG_MULTICALL3_CONTRACT_NOT_CONFIGURED: &str = + "multicall3 contract not configured"; +pub(super) const MSG_GOVERNOR_PRIVATE_KEY_NOT_SET: &str = "governor private key not set"; +pub(super) const MSG_CONSENSUS_REGISTRY_ADDRESS_NOT_CONFIGURED: &str = + "consensus registry address not configured"; +pub(super) const MSG_CONSENSUS_GENESIS_SPEC_ATTESTERS_MISSING_IN_GENERAL_YAML: &str = + "consensus.genesis_spec.attesters missing in general.yaml"; +pub(super) fn msg_setting_attester_committee_failed( + got: &attester::Committee, + want: &attester::Committee, +) -> String { + format!("setting attester committee failed: got {got:?}, want {want:?}") +}