From 92b5b5644f817f492ebff38c6b7e636cf11be67c Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Fri, 20 Apr 2018 16:38:30 +0800 Subject: [PATCH 01/95] Use forked app_dirs crate for reverted Windows dir behavior (#8438) * Remove unused appdirs dependency in CLI * Use forked app_dirs crate for reverted Windows dir behavior --- Cargo.lock | 7 +++---- Cargo.toml | 1 - parity/main.rs | 1 - util/dir/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 72c163e4d86..fd372304603 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,7 +19,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "app_dirs" version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/paritytech/app-dirs-rs#0b37f9481ce29e9d5174ad185bca695b206368eb" dependencies = [ "ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -379,7 +379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "dir" version = "0.1.0" dependencies = [ - "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "app_dirs 1.2.1 (git+https://github.com/paritytech/app-dirs-rs)", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "journaldb 0.1.0", ] @@ -1943,7 +1943,6 @@ name = "parity" version = "1.11.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)", @@ -3766,7 +3765,7 @@ dependencies = [ "checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" -"checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" +"checksum app_dirs 1.2.1 (git+https://github.com/paritytech/app-dirs-rs)" = "" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfdf7355d9db158df68f976ed030ab0f6578af811f5a7bb6dcf221ec24e0e0" "checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" diff --git a/Cargo.toml b/Cargo.toml index 9daf4fb5586..4237bf545ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,6 @@ toml = "0.4" serde = "1.0" serde_json = "1.0" serde_derive = "1.0" -app_dirs = "1.2.1" futures = "0.1" futures-cpupool = "0.1" fdlimit = "0.1" diff --git a/parity/main.rs b/parity/main.rs index 24b53ae2c92..705cf777e7b 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -19,7 +19,6 @@ #![warn(missing_docs)] extern crate ansi_term; -extern crate app_dirs; extern crate ctrlc; extern crate docopt; #[macro_use] diff --git a/util/dir/Cargo.toml b/util/dir/Cargo.toml index 5963833a7ef..e1a13401a25 100644 --- a/util/dir/Cargo.toml +++ b/util/dir/Cargo.toml @@ -6,4 +6,4 @@ authors = ["Parity Technologies "] [dependencies] ethereum-types = "0.3" journaldb = { path = "../journaldb" } -app_dirs = "1.2.1" +app_dirs = { git = "https://github.com/paritytech/app-dirs-rs" } From 9c5e35548de8e05c8533fa03e9d889456b71ad1c Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Fri, 20 Apr 2018 18:22:19 +0800 Subject: [PATCH 02/95] Permission fix (#8441) --- ethcore/src/account_provider/mod.rs | 0 ethcore/src/executive.rs | 0 ethcore/src/state/account.rs | 0 ethcore/src/state/mod.rs | 0 ethcore/src/state_db.rs | 0 ethstore/Cargo.toml | 0 ethstore/src/account/crypto.rs | 0 ethstore/src/account/mod.rs | 0 ethstore/src/account/safe_account.rs | 0 ethstore/src/accounts_dir/disk.rs | 0 ethstore/src/accounts_dir/mod.rs | 0 ethstore/src/accounts_dir/vault.rs | 0 ethstore/src/error.rs | 0 ethstore/src/ethstore.rs | 0 ethstore/src/json/vault_file.rs | 0 ethstore/src/json/vault_key_file.rs | 0 ethstore/src/lib.rs | 0 ethstore/src/secret_store.rs | 0 ethstore/tests/api.rs | 0 ethstore/tests/util/transient_dir.rs | 0 20 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 ethcore/src/account_provider/mod.rs mode change 100755 => 100644 ethcore/src/executive.rs mode change 100755 => 100644 ethcore/src/state/account.rs mode change 100755 => 100644 ethcore/src/state/mod.rs mode change 100755 => 100644 ethcore/src/state_db.rs mode change 100755 => 100644 ethstore/Cargo.toml mode change 100755 => 100644 ethstore/src/account/crypto.rs mode change 100755 => 100644 ethstore/src/account/mod.rs mode change 100755 => 100644 ethstore/src/account/safe_account.rs mode change 100755 => 100644 ethstore/src/accounts_dir/disk.rs mode change 100755 => 100644 ethstore/src/accounts_dir/mod.rs mode change 100755 => 100644 ethstore/src/accounts_dir/vault.rs mode change 100755 => 100644 ethstore/src/error.rs mode change 100755 => 100644 ethstore/src/ethstore.rs mode change 100755 => 100644 ethstore/src/json/vault_file.rs mode change 100755 => 100644 ethstore/src/json/vault_key_file.rs mode change 100755 => 100644 ethstore/src/lib.rs mode change 100755 => 100644 ethstore/src/secret_store.rs mode change 100755 => 100644 ethstore/tests/api.rs mode change 100755 => 100644 ethstore/tests/util/transient_dir.rs diff --git a/ethcore/src/account_provider/mod.rs b/ethcore/src/account_provider/mod.rs old mode 100755 new mode 100644 diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs old mode 100755 new mode 100644 diff --git a/ethcore/src/state/account.rs b/ethcore/src/state/account.rs old mode 100755 new mode 100644 diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs old mode 100755 new mode 100644 diff --git a/ethcore/src/state_db.rs b/ethcore/src/state_db.rs old mode 100755 new mode 100644 diff --git a/ethstore/Cargo.toml b/ethstore/Cargo.toml old mode 100755 new mode 100644 diff --git a/ethstore/src/account/crypto.rs b/ethstore/src/account/crypto.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/account/mod.rs b/ethstore/src/account/mod.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/account/safe_account.rs b/ethstore/src/account/safe_account.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/accounts_dir/disk.rs b/ethstore/src/accounts_dir/disk.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/accounts_dir/mod.rs b/ethstore/src/accounts_dir/mod.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/accounts_dir/vault.rs b/ethstore/src/accounts_dir/vault.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/error.rs b/ethstore/src/error.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/ethstore.rs b/ethstore/src/ethstore.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/json/vault_file.rs b/ethstore/src/json/vault_file.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/json/vault_key_file.rs b/ethstore/src/json/vault_key_file.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs old mode 100755 new mode 100644 diff --git a/ethstore/src/secret_store.rs b/ethstore/src/secret_store.rs old mode 100755 new mode 100644 diff --git a/ethstore/tests/api.rs b/ethstore/tests/api.rs old mode 100755 new mode 100644 diff --git a/ethstore/tests/util/transient_dir.rs b/ethstore/tests/util/transient_dir.rs old mode 100755 new mode 100644 From 24f6d8296b56e85d17ba246a96bc31732a97a309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Fri, 20 Apr 2018 11:32:00 +0100 Subject: [PATCH 03/95] Block reward contract (#8419) * engine: add block reward contract abi and helper client * aura: add support for block reward contract * engine: test block reward contract client * aura: test block reward contract * engine + aura: add missing docs * engine: share SystemCall type alias * aura: add transition for block reward contract * engine: fix example block reward contract source link and bytecode --- Cargo.lock | 18 +- ...authority_round_block_reward_contract.json | 61 ++++++ ethcore/res/contracts/block_reward.json | 29 +++ ethcore/src/engines/authority_round/mod.rs | 117 ++++++++++- ethcore/src/engines/block_reward.rs | 184 ++++++++++++++++++ ethcore/src/engines/mod.rs | 6 +- ethcore/src/engines/validator_set/mod.rs | 4 +- ethcore/src/spec/spec.rs | 7 + json/src/spec/authority_round.rs | 8 + 9 files changed, 412 insertions(+), 22 deletions(-) create mode 100644 ethcore/res/authority_round_block_reward_contract.json create mode 100644 ethcore/res/contracts/block_reward.json create mode 100644 ethcore/src/engines/block_reward.rs diff --git a/Cargo.lock b/Cargo.lock index fd372304603..547c3c88bdc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -462,7 +462,7 @@ dependencies = [ [[package]] name = "ethabi-contract" -version = "5.0.3" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -514,7 +514,7 @@ dependencies = [ "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.11.0", "ethcore-bloom-journal 0.1.0", @@ -745,7 +745,7 @@ version = "1.0.0" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.11.0", "ethcore-bytes 0.1.0", @@ -780,7 +780,7 @@ version = "1.0.0" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.11.0", "ethcore-bytes 0.1.0", @@ -1786,7 +1786,7 @@ name = "node-filter" version = "1.11.0" dependencies = [ "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.11.0", "ethcore-io 1.11.0", @@ -2084,7 +2084,7 @@ name = "parity-hash-fetch" version = "1.11.0" dependencies = [ "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2305,7 +2305,7 @@ name = "parity-updater" version = "1.11.0" dependencies = [ "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.11.0", "ethcore-bytes 0.1.0", @@ -2708,7 +2708,7 @@ name = "registrar" version = "0.0.1" dependencies = [ "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.0", @@ -3815,7 +3815,7 @@ dependencies = [ "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "" "checksum ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05e33a914b94b763f0a92333e4e5c95c095563f06ef7d6b295b3d3c2cf31e21f" -"checksum ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca2263c24359e827348ac99aa1f2e28ba5bab0d6c0b83941fa252de8a9e9c073" +"checksum ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "210c9e21d164c15b6ef64fe601e0e12a3c84a031d5ef558e38463e53edbd22ed" "checksum ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2bc7099baa147187aedaecd9fe04a6c0541c82bc43ff317cb6900fe2b983d74" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" "checksum ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3ae691a36ce5d25b433e63128ce5579f4a18457b6a9c849832b2c9e0fec92a" diff --git a/ethcore/res/authority_round_block_reward_contract.json b/ethcore/res/authority_round_block_reward_contract.json new file mode 100644 index 00000000000..e008de117f7 --- /dev/null +++ b/ethcore/res/authority_round_block_reward_contract.json @@ -0,0 +1,61 @@ +{ + "name": "TestAuthorityRoundBlockRewardContract", + "engine": { + "authorityRound": { + "params": { + "stepDuration": 1, + "startStep": 2, + "validators": { + "list": [ + "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e", + "0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1" + ] + }, + "immediateTransitions": true, + "emptyStepsTransition": "1", + "maximumEmptySteps": "2", + "blockRewardContractAddress": "0x0000000000000000000000000000000000000042" + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x69", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0" + }, + "genesis": { + "seal": { + "authorityRound": { + "step": "0x0", + "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x222222" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" }, + "0000000000000000000000000000000000000042": { + "balance": "1", + "constructor": "6060604052341561000f57600080fd5b6102b88061001e6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063f91c289814610046575b600080fd5b341561005157600080fd5b610086600480803590602001908201803590602001919091929080359060200190820180359060200191909192905050610125565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100cd5780820151818401526020810190506100b2565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561010f5780820151818401526020810190506100f4565b5050505090500194505050505060405180910390f35b61012d610264565b610135610278565b61013d610278565b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561018d57600080fd5b85859050888890501415156101a157600080fd5b878790506040518059106101b25750595b90808252806020026020018201604052509150600090505b815181101561021d5785858281811015156101e157fe5b9050602002013561ffff166103e80161ffff16828281518110151561020257fe5b906020019060200201818152505080806001019150506101ca565b878783828280806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050915090915093509350505094509492505050565b602060405190810160405280600081525090565b6020604051908101604052806000815250905600a165627a7a723058201da0f164e75517fb8baf51f030b904032cb748334938e7386f63025bfb23f3de0029" + } + } +} diff --git a/ethcore/res/contracts/block_reward.json b/ethcore/res/contracts/block_reward.json new file mode 100644 index 00000000000..9209967f3ac --- /dev/null +++ b/ethcore/res/contracts/block_reward.json @@ -0,0 +1,29 @@ +[ + { + "constant": false, + "inputs": [ + { + "name": "benefactors", + "type": "address[]" + }, + { + "name": "kind", + "type": "uint16[]" + } + ], + "name": "reward", + "outputs": [ + { + "name": "", + "type": "address[]" + }, + { + "name": "", + "type": "uint256[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 387dafd50a4..4807d6c3fbb 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -27,6 +27,8 @@ use account_provider::AccountProvider; use block::*; use client::EngineClient; use engines::{Engine, Seal, EngineError, ConstructedVerifier}; +use engines::block_reward; +use engines::block_reward::{BlockRewardContract, RewardKind}; use error::{Error, BlockError}; use ethjson; use machine::{AuxiliaryData, Call, EthereumMachine}; @@ -68,6 +70,10 @@ pub struct AuthorityRoundParams { pub immediate_transitions: bool, /// Block reward in base units. pub block_reward: U256, + /// Block reward contract transition block. + pub block_reward_contract_transition: u64, + /// Block reward contract. + pub block_reward_contract: Option, /// Number of accepted uncles transition block. pub maximum_uncle_count_transition: u64, /// Number of accepted uncles. @@ -95,6 +101,8 @@ impl From for AuthorityRoundParams { validate_step_transition: p.validate_step_transition.map_or(0, Into::into), immediate_transitions: p.immediate_transitions.unwrap_or(false), block_reward: p.block_reward.map_or_else(Default::default, Into::into), + block_reward_contract_transition: p.block_reward_contract_transition.map_or(0, Into::into), + block_reward_contract: p.block_reward_contract_address.map(BlockRewardContract::new), maximum_uncle_count_transition: p.maximum_uncle_count_transition.map_or(0, Into::into), maximum_uncle_count: p.maximum_uncle_count.map_or(0, Into::into), empty_steps_transition: p.empty_steps_transition.map_or(u64::max_value(), |n| ::std::cmp::max(n.into(), 1)), @@ -388,6 +396,8 @@ pub struct AuthorityRound { epoch_manager: Mutex, immediate_transitions: bool, block_reward: U256, + block_reward_contract_transition: u64, + block_reward_contract: Option, maximum_uncle_count_transition: u64, maximum_uncle_count: usize, empty_steps_transition: u64, @@ -620,6 +630,8 @@ impl AuthorityRound { epoch_manager: Mutex::new(EpochManager::blank()), immediate_transitions: our_params.immediate_transitions, block_reward: our_params.block_reward, + block_reward_contract_transition: our_params.block_reward_contract_transition, + block_reward_contract: our_params.block_reward_contract, maximum_uncle_count_transition: our_params.maximum_uncle_count_transition, maximum_uncle_count: our_params.maximum_uncle_count, empty_steps_transition: our_params.empty_steps_transition, @@ -970,9 +982,7 @@ impl Engine for AuthorityRound { /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { - use parity_machine::WithBalances; - - let mut rewards = Vec::new(); + let mut benefactors = Vec::new(); if block.header().number() >= self.empty_steps_transition { let empty_steps = if block.header().seal().is_empty() { // this is a new block, calculate rewards based on the empty steps messages we have accumulated @@ -998,17 +1008,33 @@ impl Engine for AuthorityRound { for empty_step in empty_steps { let author = empty_step.author()?; - rewards.push((author, self.block_reward)); + benefactors.push((author, RewardKind::EmptyStep)); } } let author = *block.header().author(); - rewards.push((author, self.block_reward)); + benefactors.push((author, RewardKind::Author)); + + let rewards = match self.block_reward_contract { + Some(ref c) if block.header().number() >= self.block_reward_contract_transition => { + let mut call = |to, data| { + let result = self.machine.execute_as_system( + block, + to, + U256::max_value(), // unbounded gas? maybe make configurable. + Some(data), + ); + result.map_err(|e| format!("{}", e)) + }; - for &(ref author, ref block_reward) in rewards.iter() { - self.machine.add_balance(block, author, block_reward)?; - } - self.machine.note_rewards(block, &rewards, &[]) + c.reward(&benefactors, &mut call)? + }, + _ => { + benefactors.into_iter().map(|(author, _)| (author, self.block_reward)).collect() + }, + }; + + block_reward::apply_block_rewards(&rewards, block, &self.machine) } /// Check the number of seal fields. @@ -1521,6 +1547,8 @@ mod tests { empty_steps_transition: u64::max_value(), maximum_empty_steps: 0, block_reward: Default::default(), + block_reward_contract_transition: 0, + block_reward_contract: Default::default(), }; let aura = { @@ -1563,6 +1591,8 @@ mod tests { empty_steps_transition: u64::max_value(), maximum_empty_steps: 0, block_reward: Default::default(), + block_reward_contract_transition: 0, + block_reward_contract: Default::default(), }; let aura = { @@ -1617,6 +1647,8 @@ mod tests { empty_steps_transition: u64::max_value(), maximum_empty_steps: 0, block_reward: Default::default(), + block_reward_contract_transition: 0, + block_reward_contract: Default::default(), }; let mut c_params = ::spec::CommonParams::default(); @@ -1894,4 +1926,71 @@ mod tests { _ => false, }); } + + #[test] + fn block_reward_contract() { + let spec = Spec::new_test_round_block_reward_contract(); + let tap = Arc::new(AccountProvider::transient_provider()); + + let addr1 = tap.insert_account(keccak("1").into(), "1").unwrap(); + + let engine = &*spec.engine; + let genesis_header = spec.genesis_header(); + let db1 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + + let last_hashes = Arc::new(vec![genesis_header.hash()]); + + let client = generate_dummy_client_with_spec_and_accounts( + Spec::new_test_round_block_reward_contract, + None, + ); + engine.register_client(Arc::downgrade(&client) as _); + + // step 2 + let b1 = OpenBlock::new( + engine, + Default::default(), + false, + db1, + &genesis_header, + last_hashes.clone(), + addr1, + (3141562.into(), 31415620.into()), + vec![], + false, + ).unwrap(); + let b1 = b1.close_and_lock(); + + // since the block is empty it isn't sealed and we generate empty steps + engine.set_signer(tap.clone(), addr1, "1".into()); + assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + engine.step(); + + // step 3 + // the signer of the accumulated empty step message should be rewarded + let b2 = OpenBlock::new( + engine, + Default::default(), + false, + db2, + &genesis_header, + last_hashes.clone(), + addr1, + (3141562.into(), 31415620.into()), + vec![], + false, + ).unwrap(); + let addr1_balance = b2.block().state().balance(&addr1).unwrap(); + + // after closing the block `addr1` should be reward twice, one for the included empty step + // message and another for block creation + let b2 = b2.close_and_lock(); + + // the contract rewards (1000 + kind) for each benefactor/reward kind + assert_eq!( + b2.block().state().balance(&addr1).unwrap(), + addr1_balance + (1000 + 0).into() + (1000 + 2).into(), + ) + } } diff --git a/ethcore/src/engines/block_reward.rs b/ethcore/src/engines/block_reward.rs new file mode 100644 index 00000000000..510a5255f5f --- /dev/null +++ b/ethcore/src/engines/block_reward.rs @@ -0,0 +1,184 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use ethabi; +use ethabi::ParamType; +use ethereum_types::{H160, Address, U256}; + +use block::ExecutedBlock; +use error::Error; +use machine::EthereumMachine; +use super::SystemCall; + +use_contract!(block_reward_contract, "BlockReward", "res/contracts/block_reward.json"); + +/// The kind of block reward. +/// Depending on the consensus engine the allocated block reward might have +/// different semantics which could lead e.g. to different reward values. +#[repr(u8)] +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub enum RewardKind { + /// Reward attributed to the block author. + Author = 0, + /// Reward attributed to the block uncle(s). + Uncle = 1, + /// Reward attributed to the author(s) of empty step(s) included in the block (AuthorityRound engine). + EmptyStep = 2, +} + +impl From for u16 { + fn from(reward_kind: RewardKind) -> Self { + reward_kind as u16 + } +} + +/// A client for the block reward contract. +pub struct BlockRewardContract { + /// Address of the contract. + address: Address, + block_reward_contract: block_reward_contract::BlockReward, +} + +impl BlockRewardContract { + /// Create a new block reward contract client targeting the given address. + pub fn new(address: Address) -> BlockRewardContract { + BlockRewardContract { + address, + block_reward_contract: block_reward_contract::BlockReward::default(), + } + } + + /// Calls the block reward contract with the given benefactors list (and associated reward kind) + /// and returns the reward allocation (address - value). The block reward contract *must* be + /// called by the system address so the `caller` must ensure that (e.g. using + /// `machine.execute_as_system`). + pub fn reward( + &self, + benefactors: &[(Address, RewardKind)], + caller: &mut SystemCall, + ) -> Result, Error> { + let reward = self.block_reward_contract.functions().reward(); + + let input = reward.input( + benefactors.iter().map(|&(address, _)| H160::from(address)), + benefactors.iter().map(|&(_, ref reward_kind)| u16::from(*reward_kind)), + ); + + let output = caller(self.address, input) + .map_err(Into::into) + .map_err(::engines::EngineError::FailedSystemCall)?; + + // since this is a non-constant call we can't use ethabi's function output + // deserialization, sadness ensues. + let types = &[ + ParamType::Array(Box::new(ParamType::Address)), + ParamType::Array(Box::new(ParamType::Uint(256))), + ]; + + let tokens = ethabi::decode(types, &output) + .map_err(|err| err.to_string()) + .map_err(::engines::EngineError::FailedSystemCall)?; + + assert!(tokens.len() == 2); + + let addresses = tokens[0].clone().to_array().expect("type checked by ethabi::decode; qed"); + let rewards = tokens[1].clone().to_array().expect("type checked by ethabi::decode; qed"); + + if addresses.len() != rewards.len() { + return Err(::engines::EngineError::FailedSystemCall( + "invalid data returned by reward contract: both arrays must have the same size".into() + ).into()); + } + + let addresses = addresses.into_iter().map(|t| t.to_address().expect("type checked by ethabi::decode; qed")); + let rewards = rewards.into_iter().map(|t| t.to_uint().expect("type checked by ethabi::decode; qed")); + + Ok(addresses.zip(rewards).collect()) + } +} + +/// Applies the given block rewards, i.e. adds the given balance to each benefactors' address. +/// If tracing is enabled the operations are recorded. +pub fn apply_block_rewards(rewards: &[(Address, U256)], block: &mut ExecutedBlock, machine: &EthereumMachine) -> Result<(), Error> { + use parity_machine::WithBalances; + + for &(ref author, ref block_reward) in rewards { + machine.add_balance(block, author, block_reward)?; + } + + machine.note_rewards(block, &rewards, &[]) +} + +#[cfg(test)] +mod test { + use client::PrepareOpenBlock; + use ethereum_types::U256; + use spec::Spec; + use test_helpers::generate_dummy_client_with_spec_and_accounts; + + use super::{BlockRewardContract, RewardKind}; + + #[test] + fn block_reward_contract() { + let client = generate_dummy_client_with_spec_and_accounts( + Spec::new_test_round_block_reward_contract, + None, + ); + + let machine = Spec::new_test_machine(); + + // the spec has a block reward contract defined at the given address + let block_reward_contract = BlockRewardContract::new( + "0000000000000000000000000000000000000042".into(), + ); + + let mut call = |to, data| { + let mut block = client.prepare_open_block( + "0000000000000000000000000000000000000001".into(), + (3141562.into(), 31415620.into()), + vec![], + ); + + let result = machine.execute_as_system( + block.block_mut(), + to, + U256::max_value(), + Some(data), + ); + + result.map_err(|e| format!("{}", e)) + }; + + // if no benefactors are given no rewards are attributed + assert!(block_reward_contract.reward(&vec![], &mut call).unwrap().is_empty()); + + // the contract rewards (1000 + kind) for each benefactor + let benefactors = vec![ + ("0000000000000000000000000000000000000033".into(), RewardKind::Author), + ("0000000000000000000000000000000000000034".into(), RewardKind::Uncle), + ("0000000000000000000000000000000000000035".into(), RewardKind::EmptyStep), + ]; + + let rewards = block_reward_contract.reward(&benefactors, &mut call).unwrap(); + let expected = vec![ + ("0000000000000000000000000000000000000033".into(), U256::from(1000)), + ("0000000000000000000000000000000000000034".into(), U256::from(1000 + 1)), + ("0000000000000000000000000000000000000035".into(), U256::from(1000 + 2)), + ]; + + assert_eq!(expected, rewards); + } +} diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 3412c483678..8556879f95a 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -18,6 +18,7 @@ mod authority_round; mod basic_authority; +mod block_reward; mod instant_seal; mod null_engine; mod signer; @@ -56,7 +57,7 @@ use ethereum_types::{H256, U256, Address}; use unexpected::{Mismatch, OutOfBounds}; use bytes::Bytes; -/// Default EIP-210 contrat code. +/// Default EIP-210 contract code. /// As defined in https://github.com/ethereum/EIPs/pull/210 pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73fffffffffffffffffffffffffffffffffffffffe33141561006a5760014303600035610100820755610100810715156100455760003561010061010083050761010001555b6201000081071515610064576000356101006201000083050761020001555b5061013e565b4360003512151561008457600060405260206040f361013d565b61010060003543031315156100a857610100600035075460605260206060f361013c565b6101006000350715156100c55762010000600035430313156100c8565b60005b156100ea576101006101006000350507610100015460805260206080f361013b565b620100006000350715156101095763010000006000354303131561010c565b60005b1561012f57610100620100006000350507610200015460a052602060a0f361013a565b600060c052602060c0f35b5b5b5b5b"; @@ -119,6 +120,9 @@ pub enum Seal { None, } +/// A system-calling closure. Enacts calls on a block's state from the system address. +pub type SystemCall<'a> = FnMut(Address, Vec) -> Result, String> + 'a; + /// Type alias for a function we can get headers by hash through. pub type Headers<'a, H> = Fn(H256) -> Option + 'a; diff --git a/ethcore/src/engines/validator_set/mod.rs b/ethcore/src/engines/validator_set/mod.rs index de2164f918f..d439c69c2e5 100644 --- a/ethcore/src/engines/validator_set/mod.rs +++ b/ethcore/src/engines/validator_set/mod.rs @@ -38,9 +38,7 @@ pub use self::simple_list::SimpleList; use self::contract::ValidatorContract; use self::safe_contract::ValidatorSafeContract; use self::multi::Multi; - -/// A system-calling closure. Enacts calls on a block's state from the system address. -pub type SystemCall<'a> = FnMut(Address, Bytes) -> Result + 'a; +use super::SystemCall; /// Creates a validator set from spec. pub fn new_validator_set(spec: ValidatorSpec) -> Box { diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index c1fda86672a..7f6d650dd4f 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -848,6 +848,13 @@ impl Spec { load_bundled!("authority_round_empty_steps") } + /// Create a new Spec with AuthorityRound consensus (with empty steps) using a block reward + /// contract. The contract source code can be found at: + /// https://github.com/parity-contracts/block-reward/blob/daf7d44383b6cdb11cb6b953b018648e2b027cfb/contracts/ExampleBlockReward.sol + pub fn new_test_round_block_reward_contract() -> Self { + load_bundled!("authority_round_block_reward_contract") + } + /// Create a new Spec with Tendermint consensus which does internal sealing (not requiring /// work). /// Account keccak("0") and keccak("1") are a authorities. diff --git a/json/src/spec/authority_round.rs b/json/src/spec/authority_round.rs index 4dea4f09899..4ef9368362c 100644 --- a/json/src/spec/authority_round.rs +++ b/json/src/spec/authority_round.rs @@ -16,6 +16,7 @@ //! Authority params deserialization. +use ethereum_types::Address; use uint::Uint; use super::ValidatorSet; @@ -43,6 +44,13 @@ pub struct AuthorityRoundParams { /// Reward per block in wei. #[serde(rename="blockReward")] pub block_reward: Option, + /// Block at which the block reward contract should start being used. + #[serde(rename="blockRewardContractTransition")] + pub block_reward_contract_transition: Option, + /// Block reward contract address (setting the block reward contract + /// overrides the static block reward definition). + #[serde(rename="blockRewardContractAddress")] + pub block_reward_contract_address: Option
, /// Block at which maximum uncle count should be considered. #[serde(rename="maximumUncleCountTransition")] pub maximum_uncle_count_transition: Option, From 28b5906d9e785c7f9e8f8ab635708fa8e7e53f37 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Fri, 20 Apr 2018 18:32:25 +0800 Subject: [PATCH 04/95] Improve VM executor stack size estimation rules (#8439) * Improve VM executor stack size estimation rules * typo: docs add "(Debug build)" comment * Fix an off by one typo and set minimal stack size This avoids the case if `depth_threshold == max_depth`. Usually setting stack size to zero will just rebound it to platform minimal stack size, but we set it here just in case. * Use saturating_sub to avoid potential overflow --- ethcore/src/executive.rs | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 142086beb92..cded6358e8f 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -34,10 +34,21 @@ use transaction::{Action, SignedTransaction}; use crossbeam; pub use executed::{Executed, ExecutionResult}; -/// Roughly estimate what stack size each level of evm depth will use -/// TODO [todr] We probably need some more sophisticated calculations here (limit on my machine 132) -/// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp` -const STACK_SIZE_PER_DEPTH: usize = 24*1024; +#[cfg(debug_assertions)] +/// Roughly estimate what stack size each level of evm depth will use. (Debug build) +const STACK_SIZE_PER_DEPTH: usize = 128 * 1024; + +#[cfg(not(debug_assertions))] +/// Roughly estimate what stack size each level of evm depth will use. +const STACK_SIZE_PER_DEPTH: usize = 24 * 1024; + +#[cfg(debug_assertions)] +/// Entry stack overhead prior to execution. (Debug build) +const STACK_SIZE_ENTRY_OVERHEAD: usize = 100 * 1024; + +#[cfg(not(debug_assertions))] +/// Entry stack overhead prior to execution. +const STACK_SIZE_ENTRY_OVERHEAD: usize = 20 * 1024; /// Returns new address created from address, nonce, and code hash pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, nonce: &U256, code: &[u8]) -> (Address, Option) { @@ -332,12 +343,12 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { tracer: &mut T, vm_tracer: &mut V ) -> vm::Result where T: Tracer, V: VMTracer { - - let depth_threshold = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get() / STACK_SIZE_PER_DEPTH); + let local_stack_size = ::io::LOCAL_STACK_SIZE.with(|sz| sz.get()); + let depth_threshold = local_stack_size.saturating_sub(STACK_SIZE_ENTRY_OVERHEAD) / STACK_SIZE_PER_DEPTH; let static_call = params.call_type == CallType::StaticCall; // Ordinary execution - keep VM in same thread - if (self.depth + 1) % depth_threshold != 0 { + if self.depth != depth_threshold { let vm_factory = self.state.vm_factory(); let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call); trace!(target: "executive", "ext.schedule.have_delegate_call: {}", ext.schedule().have_delegate_call); @@ -345,17 +356,15 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { return vm.exec(params, &mut ext).finalize(ext); } - // Start in new thread to reset stack - // TODO [todr] No thread builder yet, so we need to reset once for a while - // https://github.com/aturon/crossbeam/issues/16 + // Start in new thread with stack size needed up to max depth crossbeam::scope(|scope| { let vm_factory = self.state.vm_factory(); let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call); - scope.spawn(move || { + scope.builder().stack_size(::std::cmp::max(schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || { let mut vm = vm_factory.create(¶ms, &schedule); vm.exec(params, &mut ext).finalize(ext) - }) + }).expect("Sub-thread creation cannot fail; the host might run out of resources; qed") }).join() } From d86333af6b51afa006b438de63e7acbd05f05985 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Fri, 20 Apr 2018 15:45:53 +0200 Subject: [PATCH 05/95] Private transactions processing error handling (#8431) * Integration test for private transaction returned * Do not interrupt verification in case of errors * Helpers use specified * Review comments fixed --- Cargo.lock | 1 + ethcore/private-tx/src/lib.rs | 11 +- ethcore/sync/Cargo.toml | 1 + ethcore/sync/src/lib.rs | 1 + ethcore/sync/src/res/private_spec.json | 30 +++++ ethcore/sync/src/tests/consensus.rs | 4 +- ethcore/sync/src/tests/helpers.rs | 42 +------ ethcore/sync/src/tests/mod.rs | 1 + ethcore/sync/src/tests/private.rs | 150 +++++++++++++++++++++++++ 9 files changed, 193 insertions(+), 48 deletions(-) create mode 100644 ethcore/sync/src/res/private_spec.json create mode 100644 ethcore/sync/src/tests/private.rs diff --git a/Cargo.lock b/Cargo.lock index 547c3c88bdc..ae38937ba8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -858,6 +858,7 @@ dependencies = [ "ethcore-light 1.11.0", "ethcore-network 1.11.0", "ethcore-network-devp2p 1.11.0", + "ethcore-private-tx 1.0.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", diff --git a/ethcore/private-tx/src/lib.rs b/ethcore/private-tx/src/lib.rs index 80510938cff..12028ddf121 100644 --- a/ethcore/private-tx/src/lib.rs +++ b/ethcore/private-tx/src/lib.rs @@ -306,11 +306,6 @@ impl Provider where { /// Retrieve and verify the first available private transaction for every sender /// /// TODO [ToDr] It seems that: - /// 1. This method will fail on any error without removing invalid transaction. - /// 2. It means that the transaction will be stuck there forever and we will never be able to make any progress. - /// - /// It might be more sensible to `drain()` transactions from the queue instead and process all of them, - /// possibly printing some errors in case of failures. /// The 3 methods `ready_transaction,get_descriptor,remove` are always used in conjuction so most likely /// can be replaced with a single `drain()` method instead. /// Thanks to this we also don't really need to lock the entire verification for the time of execution. @@ -339,13 +334,11 @@ impl Provider where { trace!("Sending signature for private transaction: {:?}", signed_private_transaction); self.broadcast_signed_private_transaction(signed_private_transaction.rlp_bytes().into_vec()); } else { - trace!("Incorrect type of action for the transaction"); - bail!(ErrorKind::BadTransactonType); + warn!("Incorrect type of action for the transaction"); } }, Err(e) => { - trace!("Cannot retrieve descriptor for transaction with error {:?}", e); - bail!(e); + warn!("Cannot retrieve descriptor for transaction with error {:?}", e); } } verification_queue.remove_private_transaction(&transaction_hash); diff --git a/ethcore/sync/Cargo.toml b/ethcore/sync/Cargo.toml index a09f161e2a9..6930baa101b 100644 --- a/ethcore/sync/Cargo.toml +++ b/ethcore/sync/Cargo.toml @@ -35,3 +35,4 @@ ipnetwork = "0.12.6" [dev-dependencies] ethkey = { path = "../../ethkey" } kvdb-memorydb = { path = "../../util/kvdb-memorydb" } +ethcore-private-tx = { path = "../private-tx" } diff --git a/ethcore/sync/src/lib.rs b/ethcore/sync/src/lib.rs index bf3b475fc6f..a3e24bdb823 100644 --- a/ethcore/sync/src/lib.rs +++ b/ethcore/sync/src/lib.rs @@ -46,6 +46,7 @@ extern crate ethcore_light as light; #[cfg(test)] extern crate ethkey; #[cfg(test)] extern crate kvdb_memorydb; #[cfg(test)] extern crate rustc_hex; +#[cfg(test)] extern crate ethcore_private_tx; #[macro_use] extern crate macros; diff --git a/ethcore/sync/src/res/private_spec.json b/ethcore/sync/src/res/private_spec.json new file mode 100644 index 00000000000..f93d754a611 --- /dev/null +++ b/ethcore/sync/src/res/private_spec.json @@ -0,0 +1,30 @@ +{ + "name": "PrivateTransactions", + "engine": { + "instantSeal": null + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x11" + }, + "genesis": { + "seal": { + "generic": "0x0" + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x989680" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } + } +} \ No newline at end of file diff --git a/ethcore/sync/src/tests/consensus.rs b/ethcore/sync/src/tests/consensus.rs index 287a61916a4..8825bad2c8c 100644 --- a/ethcore/sync/src/tests/consensus.rs +++ b/ethcore/sync/src/tests/consensus.rs @@ -48,7 +48,7 @@ fn authority_round() { ap.insert_account(s1.secret().clone(), "").unwrap(); let chain_id = Spec::new_test_round().chain_id(); - let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_round, Some(ap), false); + let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_round, Some(ap)); let io_handler0: Arc> = Arc::new(TestIoHandler::new(net.peer(0).chain.clone())); let io_handler1: Arc> = Arc::new(TestIoHandler::new(net.peer(1).chain.clone())); // Push transaction to both clients. Only one of them gets lucky to produce a block. @@ -135,7 +135,7 @@ fn tendermint() { ap.insert_account(s1.secret().clone(), "").unwrap(); let chain_id = Spec::new_test_tendermint().chain_id(); - let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_tendermint, Some(ap), false); + let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_tendermint, Some(ap)); let io_handler0: Arc> = Arc::new(TestIoHandler::new(net.peer(0).chain.clone())); let io_handler1: Arc> = Arc::new(TestIoHandler::new(net.peer(1).chain.clone())); // Push transaction to both clients. Only one of them issues a proposal. diff --git a/ethcore/sync/src/tests/helpers.rs b/ethcore/sync/src/tests/helpers.rs index 54b62c79a07..086dc503bba 100644 --- a/ethcore/sync/src/tests/helpers.rs +++ b/ethcore/sync/src/tests/helpers.rs @@ -33,7 +33,7 @@ use io::{IoChannel, IoContext, IoHandler}; use api::WARP_SYNC_PROTOCOL_ID; use chain::{ChainSync, ETH_PROTOCOL_VERSION_63, PAR_PROTOCOL_VERSION_3}; use SyncConfig; -use private_tx::{NoopPrivateTxHandler, PrivateTxHandler, SimplePrivateTxHandler}; +use private_tx::SimplePrivateTxHandler; pub trait FlushingBlockChainClient: BlockChainClient { fn flush(&self) {} @@ -210,7 +210,7 @@ pub struct EthPeer where C: FlushingBlockChainClient { pub snapshot_service: Arc, pub sync: RwLock, pub queue: RwLock>, - pub private_tx_handler: Arc, + pub private_tx_handler: Arc, pub io_queue: RwLock>, new_blocks_queue: RwLock>, } @@ -335,7 +335,7 @@ impl TestNet> { for _ in 0..n { let chain = TestBlockChainClient::new(); let ss = Arc::new(TestSnapshotService::new()); - let private_tx_handler = Arc::new(NoopPrivateTxHandler); + let private_tx_handler = Arc::new(SimplePrivateTxHandler::default()); let sync = ChainSync::new(config.clone(), &chain, private_tx_handler.clone()); net.peers.push(Arc::new(EthPeer { sync: RwLock::new(sync), @@ -362,8 +362,7 @@ impl TestNet> { n: usize, config: SyncConfig, spec_factory: F, - accounts: Option>, - private_tx_handler: bool, + accounts: Option> ) -> Self where F: Fn() -> Spec { @@ -373,11 +372,7 @@ impl TestNet> { disconnect_events: Vec::new(), }; for _ in 0..n { - if private_tx_handler { - net.add_peer_with_private_config(config.clone(), spec_factory(), accounts.clone()); - } else { - net.add_peer(config.clone(), spec_factory(), accounts.clone()); - } + net.add_peer_with_private_config(config.clone(), spec_factory(), accounts.clone()); } net } @@ -410,33 +405,6 @@ impl TestNet> { //private_provider.add_notify(peer.clone()); self.peers.push(peer); } - - pub fn add_peer(&mut self, config: SyncConfig, spec: Spec, accounts: Option>) { - let miner = Arc::new(Miner::new_for_tests(&spec, accounts)); - let client = EthcoreClient::new( - ClientConfig::default(), - &spec, - Arc::new(::kvdb_memorydb::create(::ethcore::db::NUM_COLUMNS.unwrap_or(0))), - miner.clone(), - IoChannel::disconnected(), - ).unwrap(); - - let ss = Arc::new(TestSnapshotService::new()); - let private_tx_handler = Arc::new(NoopPrivateTxHandler); - let sync = ChainSync::new(config, &*client, private_tx_handler.clone()); - let peer = Arc::new(EthPeer { - sync: RwLock::new(sync), - snapshot_service: ss, - queue: RwLock::new(VecDeque::new()), - chain: client, - miner, - private_tx_handler, - io_queue: RwLock::new(VecDeque::new()), - new_blocks_queue: RwLock::new(VecDeque::new()), - }); - peer.chain.add_notify(peer.clone()); - self.peers.push(peer); - } } impl

TestNet

where P: Peer { diff --git a/ethcore/sync/src/tests/mod.rs b/ethcore/sync/src/tests/mod.rs index 8b9059fc135..eb01108286b 100644 --- a/ethcore/sync/src/tests/mod.rs +++ b/ethcore/sync/src/tests/mod.rs @@ -18,6 +18,7 @@ pub mod helpers; pub mod snapshot; mod chain; mod consensus; +mod private; #[cfg(feature = "ipc")] mod rpc; diff --git a/ethcore/sync/src/tests/private.rs b/ethcore/sync/src/tests/private.rs new file mode 100644 index 00000000000..a9e8718e5e7 --- /dev/null +++ b/ethcore/sync/src/tests/private.rs @@ -0,0 +1,150 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use std::sync::Arc; +use hash::keccak; +use io::{IoHandler, IoChannel}; +use ethcore::client::{BlockChainClient, BlockId, ClientIoMessage}; +use ethcore::spec::Spec; +use ethcore::miner::MinerService; +use ethcore::CreateContractAddress; +use transaction::{Transaction, Action}; +use ethcore::executive::{contract_address}; +use ethcore::test_helpers::{push_block_with_transactions}; +use ethcore_private_tx::{Provider, ProviderConfig, NoopEncryptor}; +use ethcore::account_provider::AccountProvider; +use ethkey::{KeyPair}; +use tests::helpers::{TestNet, TestIoHandler}; +use rustc_hex::FromHex; +use SyncConfig; + +fn seal_spec() -> Spec { + let spec_data = include_str!("../res/private_spec.json"); + Spec::load(&::std::env::temp_dir(), spec_data.as_bytes()).unwrap() +} + +#[test] +fn send_private_transaction() { + // Setup two clients + let s0 = KeyPair::from_secret_slice(&keccak("1")).unwrap(); + let s1 = KeyPair::from_secret_slice(&keccak("0")).unwrap(); + let ap = Arc::new(AccountProvider::transient_provider()); + ap.insert_account(s0.secret().clone(), "").unwrap(); + ap.insert_account(s1.secret().clone(), "").unwrap(); + + let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), seal_spec, Some(ap.clone())); + let client0 = net.peer(0).chain.clone(); + let client1 = net.peer(1).chain.clone(); + let io_handler0: Arc> = Arc::new(TestIoHandler::new(net.peer(0).chain.clone())); + let io_handler1: Arc> = Arc::new(TestIoHandler::new(net.peer(1).chain.clone())); + + net.peer(0).miner.set_author(s0.address(), Some("".into())).unwrap(); + net.peer(1).miner.set_author(s1.address(), Some("".to_owned())).unwrap(); + net.peer(0).chain.engine().register_client(Arc::downgrade(&net.peer(0).chain) as _); + net.peer(1).chain.engine().register_client(Arc::downgrade(&net.peer(1).chain) as _); + net.peer(0).chain.set_io_channel(IoChannel::to_handler(Arc::downgrade(&io_handler0))); + net.peer(1).chain.set_io_channel(IoChannel::to_handler(Arc::downgrade(&io_handler1))); + + let (address, _) = contract_address(CreateContractAddress::FromSenderAndNonce, &s0.address(), &0.into(), &[]); + let chain_id = client0.signing_chain_id(); + + // Exhange statuses + net.sync(); + + // Setup private providers + let validator_config = ProviderConfig{ + validator_accounts: vec![s1.address()], + signer_account: None, + passwords: vec!["".into()], + }; + + let signer_config = ProviderConfig{ + validator_accounts: Vec::new(), + signer_account: Some(s0.address()), + passwords: vec!["".into()], + }; + + let pm0 = Arc::new(Provider::new( + client0.clone(), + net.peer(0).miner.clone(), + ap.clone(), + Box::new(NoopEncryptor::default()), + signer_config, + IoChannel::to_handler(Arc::downgrade(&io_handler0)), + ).unwrap()); + pm0.add_notify(net.peers[0].clone()); + + let pm1 = Arc::new(Provider::new( + client1.clone(), + net.peer(1).miner.clone(), + ap.clone(), + Box::new(NoopEncryptor::default()), + validator_config, + IoChannel::to_handler(Arc::downgrade(&io_handler1)), + ).unwrap()); + pm1.add_notify(net.peers[1].clone()); + + // Create and deploy contract + let private_contract_test = "6060604052341561000f57600080fd5b60d88061001d6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630c55699c146046578063bc64b76d14607457600080fd5b3415605057600080fd5b60566098565b60405180826000191660001916815260200191505060405180910390f35b3415607e57600080fd5b6096600480803560001916906020019091905050609e565b005b60005481565b8060008160001916905550505600a165627a7a723058206acbdf4b15ca4c2d43e1b1879b830451a34f1e9d02ff1f2f394d8d857e79d2080029".from_hex().unwrap(); + let mut private_create_tx = Transaction::default(); + private_create_tx.action = Action::Create; + private_create_tx.data = private_contract_test; + private_create_tx.gas = 200000.into(); + let private_create_tx_signed = private_create_tx.sign(&s0.secret(), None); + let validators = vec![s1.address()]; + let (public_tx, _) = pm0.public_creation_transaction(BlockId::Latest, &private_create_tx_signed, &validators, 0.into()).unwrap(); + let public_tx = public_tx.sign(&s0.secret(), chain_id); + + let public_tx_copy = public_tx.clone(); + push_block_with_transactions(&client0, &[public_tx]); + push_block_with_transactions(&client1, &[public_tx_copy]); + + net.sync(); + + //Create private transaction for modifying state + let mut private_tx = Transaction::default(); + private_tx.action = Action::Call(address.clone()); + private_tx.data = "bc64b76d2a00000000000000000000000000000000000000000000000000000000000000".from_hex().unwrap(); //setX(42) + private_tx.gas = 120000.into(); + private_tx.nonce = 1.into(); + let private_tx = private_tx.sign(&s0.secret(), None); + assert!(pm0.create_private_transaction(private_tx).is_ok()); + + //send private transaction message to validator + net.sync(); + + let validator_handler = net.peer(1).private_tx_handler.clone(); + let received_private_transactions = validator_handler.txs.lock().clone(); + assert_eq!(received_private_transactions.len(), 1); + + //process received private transaction message + let private_transaction = received_private_transactions[0].clone(); + assert!(pm1.import_private_transaction(&private_transaction).is_ok()); + assert!(pm1.on_private_transaction_queued().is_ok()); + + //send signed response + net.sync(); + + let sender_handler = net.peer(0).private_tx_handler.clone(); + let received_signed_private_transactions = sender_handler.signed_txs.lock().clone(); + assert_eq!(received_signed_private_transactions.len(), 1); + + //process signed response + let signed_private_transaction = received_signed_private_transactions[0].clone(); + assert!(pm0.import_signed_private_transaction(&signed_private_transaction).is_ok()); + let local_transactions = net.peer(0).miner.local_transactions(); + assert_eq!(local_transactions.len(), 1); +} \ No newline at end of file From 9e9045ab94570490597df33a09f6de5465633b8f Mon Sep 17 00:00:00 2001 From: Nikita Chebykin Date: Fri, 20 Apr 2018 15:46:08 +0200 Subject: [PATCH 06/95] Update Cargo hidapi-rs dependency (#8447) --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index ae38937ba8e..408a1c22769 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1210,7 +1210,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hidapi" version = "0.3.1" -source = "git+https://github.com/paritytech/hidapi-rs#e77ea09c98f29ea8855dd9cd9461125a28ca9125" +source = "git+https://github.com/paritytech/hidapi-rs#70ec4bd1b755ec5dd32ad2be0c8345864147c8bc" dependencies = [ "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", From 4e76cce0b7752b1e86e836476ccffbf89153a8d1 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Sat, 21 Apr 2018 11:24:51 +0200 Subject: [PATCH 07/95] Allow 32 bit pipelines to fail (#8454) * Disable 32bit tragets for gitlab * Rename linux pipelines --- .gitlab-ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f3a8a3f0c1e..3a04125e577 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,7 +13,7 @@ cache: paths: - target/ untracked: true -linux-stable: +linux-ubuntu: stage: build image: parity/rust:gitlab-ci only: @@ -31,7 +31,7 @@ linux-stable: paths: - parity.zip name: "stable-x86_64-unknown-linux-gnu_parity" -linux-stable-debian: +linux-debian: stage: build image: parity/rust-debian:gitlab-ci only: @@ -80,6 +80,7 @@ linux-i686: paths: - parity.zip name: "i686-unknown-linux-gnu" + allow_failure: true linux-armv7: stage: build image: parity/rust-armv7:gitlab-ci @@ -96,6 +97,7 @@ linux-armv7: paths: - parity.zip name: "armv7_unknown_linux_gnueabihf_parity" + allow_failure: true linux-arm: stage: build image: parity/rust-arm:gitlab-ci @@ -112,6 +114,7 @@ linux-arm: paths: - parity.zip name: "arm-unknown-linux-gnueabihf_parity" + allow_failure: true linux-aarch64: stage: build image: parity/rust-arm64:gitlab-ci From 650948feed36d96b96f65494cf616e7ff40ad7cc Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Sat, 21 Apr 2018 12:27:39 +0300 Subject: [PATCH 08/95] Update wasmi (#8452) --- Cargo.lock | 6 +++--- ethcore/wasm/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 408a1c22769..2b5807fe502 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3627,12 +3627,12 @@ dependencies = [ "parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)", "pwasm-utils 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", - "wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmi" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4033,7 +4033,7 @@ dependencies = [ "checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d" "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasmi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26b20dbeb7caee04597a5d2c93e2b3e64872c6ea2af732d7ad49dbec44067c35" +"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb" "checksum webpki 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1622384bcb5458c6a3e3fa572f53ea8fef1cc85e535a2983dea87e9154fac2" "checksum webpki-roots 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155d4060e5befdf3a6076bd28c22513473d9900b763c9e4521acc6f78a75415c" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/ethcore/wasm/Cargo.toml b/ethcore/wasm/Cargo.toml index 2b8075f7413..a39e6ee5292 100644 --- a/ethcore/wasm/Cargo.toml +++ b/ethcore/wasm/Cargo.toml @@ -12,4 +12,4 @@ libc = "0.2" pwasm-utils = "0.1" vm = { path = "../vm" } ethcore-logger = { path = "../../logger" } -wasmi = { version = "0.1.2", features = ["opt-in-32bit"] } +wasmi = { version = "0.1.3", features = ["opt-in-32bit"] } From c983efe895c6ef3aee0e7f6fe035ea14073c5924 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sat, 21 Apr 2018 17:41:09 +0800 Subject: [PATCH 09/95] Return error in case eth_call returns VM errors (#8448) * Add VMError generator * Return executed exceptions in eth_call --- rpc/src/v1/helpers/errors.rs | 16 ++++++++++++++++ rpc/src/v1/impls/eth.rs | 8 +++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 4e5fa2fb72d..acff796646e 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -24,6 +24,7 @@ use jsonrpc_core::{futures, Error, ErrorCode, Value}; use rlp::DecoderError; use transaction::Error as TransactionError; use ethcore_private_tx::Error as PrivateTransactionError; +use vm::Error as VMError; mod codes { // NOTE [ToDr] Codes from [-32099, -32000] @@ -375,6 +376,21 @@ pub fn call(error: CallError) -> Error { } } +pub fn vm(error: &VMError, output: &[u8]) -> Error { + use rustc_hex::ToHex; + + let data = match error { + &VMError::Reverted => format!("{} 0x{}", VMError::Reverted, output.to_hex()), + error => format!("{}", error), + }; + + Error { + code: ErrorCode::ServerError(codes::EXECUTION_ERROR), + message: "VM execution error.".into(), + data: Some(Value::String(data)), + } +} + pub fn unknown_block() -> Error { Error { code: ErrorCode::InvalidParams, diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index c894f16dfc4..a7ff4916dee 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -859,8 +859,14 @@ impl Eth for EthClient< let result = self.client.call(&signed, Default::default(), &mut state, &header); Box::new(future::done(result - .map(|b| b.output.into()) .map_err(errors::call) + .and_then(|executed| { + match executed.exception { + Some(ref exception) => Err(errors::vm(exception, &executed.output)), + None => Ok(executed) + } + }) + .map(|b| b.output.into()) )) } From b0cc44aabbdc09a31fd9cf20d438300d492975de Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Sat, 21 Apr 2018 12:54:48 +0200 Subject: [PATCH 10/95] ParityShell::open `Return result` (#8377) * start * add error handling for winapi * fix typo * fix warnings and windows errors * formatting * Address review comments --- parity/main.rs | 2 +- parity/run.rs | 5 ++--- parity/url.rs | 52 +++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 705cf777e7b..6774a83864c 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -231,7 +231,7 @@ fn take_spec_name_override() -> Option { #[cfg(windows)] fn global_cleanup() { // We need to cleanup all sockets before spawning another Parity process. This makes shure everything is cleaned up. - // The loop is required because of internal refernce counter for winsock dll. We don't know how many crates we use do + // The loop is required because of internal reference counter for winsock dll. We don't know how many crates we use do // initialize it. There's at least 2 now. for _ in 0.. 10 { unsafe { ::winapi::um::winsock2::WSACleanup(); } diff --git a/parity/run.rs b/parity/run.rs index 6ccd4caf562..f07f67caa83 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -145,7 +145,7 @@ pub fn open_ui(ws_conf: &rpc::WsConfiguration, ui_conf: &rpc::UiConfiguration, l let token = signer::generate_token_and_url(ws_conf, ui_conf, logger_config)?; // Open a browser - url::open(&token.url); + url::open(&token.url).map_err(|e| format!("{}", e))?; // Print a message println!("{}", token.message); Ok(()) @@ -157,10 +157,9 @@ pub fn open_dapp(dapps_conf: &dapps::Configuration, rpc_conf: &rpc::HttpConfigur } let url = format!("http://{}:{}/{}/", rpc_conf.interface, rpc_conf.port, dapp); - url::open(&url); + url::open(&url).map_err(|e| format!("{}", e))?; Ok(()) } - // node info fetcher for the local store. struct FullNodeInfo { miner: Option>, // TODO: only TXQ needed, just use that after decoupling. diff --git a/parity/url.rs b/parity/url.rs index 4189ae24184..41c4e545831 100644 --- a/parity/url.rs +++ b/parity/url.rs @@ -16,33 +16,67 @@ //! Cross-platform open url in default browser +use std; +use std::os::raw::c_int; + +#[allow(unused)] +pub enum Error { + ProcessError(std::io::Error), + WindowsShellExecute(c_int), +} + +impl From for Error { + fn from(err: std::io::Error) -> Self { + Error::ProcessError(err) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + match *self { + Error::ProcessError(ref e) => write!(f, "{}", e), + Error::WindowsShellExecute(e) => write!(f, "WindowsShellExecute error: {}", e), + } + } +} + #[cfg(windows)] -pub fn open(url: &str) { +pub fn open(url: &str) -> Result<(), Error> { use std::ffi::CString; use std::ptr; use winapi::um::shellapi::ShellExecuteA; use winapi::um::winuser::SW_SHOWNORMAL as Normal; - unsafe { + const WINDOWS_SHELL_EXECUTE_SUCCESS: c_int = 32; + + let h_instance = unsafe { ShellExecuteA(ptr::null_mut(), CString::new("open").unwrap().as_ptr(), CString::new(url.to_owned().replace("\n", "%0A")).unwrap().as_ptr(), ptr::null(), ptr::null(), - Normal); + Normal) as c_int + }; + + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx + // `ShellExecute` returns a value greater than 32 on success + if h_instance > WINDOWS_SHELL_EXECUTE_SUCCESS { + Ok(()) + } else { + Err(Error::WindowsShellExecute(h_instance)) } } #[cfg(any(target_os="macos", target_os="freebsd"))] -pub fn open(url: &str) { - use std; - let _ = std::process::Command::new("open").arg(url).spawn(); +pub fn open(url: &str) -> Result<(), Error> { + let _ = std::process::Command::new("open").arg(url).spawn()?; + Ok(()) } #[cfg(target_os="linux")] -pub fn open(url: &str) { - use std; - let _ = std::process::Command::new("xdg-open").arg(url).spawn(); +pub fn open(url: &str) -> Result<(), Error> { + let _ = std::process::Command::new("xdg-open").arg(url).spawn()?; + Ok(()) } #[cfg(target_os="android")] From 1ab06ce2d2e8c46ef090fcf342bcb327099492b4 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Mon, 23 Apr 2018 16:36:08 +0300 Subject: [PATCH 11/95] fix docker build (#8462) --- docker/hub/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/hub/Dockerfile b/docker/hub/Dockerfile index 70d7277800c..71655036e03 100644 --- a/docker/hub/Dockerfile +++ b/docker/hub/Dockerfile @@ -59,7 +59,7 @@ cd /build&&git clone https://github.com/paritytech/parity && \ binutils \ file \ pkg-config \ - dpkg-dev \ + dpkg-dev &&\ rm -rf /var/lib/apt/lists/* # setup ENTRYPOINT EXPOSE 8080 8545 8180 From 7a28f72abc5689527e8e21e9a1cd46ce8e71ed52 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Mon, 23 Apr 2018 15:36:20 +0200 Subject: [PATCH 12/95] Add changelog for 1.9.7 and 1.10.2 (#8460) * Add changelog for 1.9.7 * Add Changelog for 1.10.2 * Apply proper markdown * Run a spellchecker :) * Be pedantic about the 32-bit pipelines :) --- CHANGELOG.md | 25 +++++++++++++++++++++++++ docs/CHANGELOG-1.9.md | 26 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f42b781888..6272c32a7e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,28 @@ +## Parity [v1.10.2](https://github.com/paritytech/parity/releases/tag/v1.10.2) (2018-04-24) + +Parity 1.10.2 is a bug-fix release to improve performance and stability. + +The full list of included changes: + +- Update Parity beta to 1.10.2 + Backports ([#8455](https://github.com/paritytech/parity/pull/8455)) + - Update Parity beta to 1.10.2 + - Allow 32-bit pipelines to fail ([#8454](https://github.com/paritytech/parity/pull/8454)) + - Disable 32-bit targets for Gitlab + - Rename Linux pipelines + - Update wasmi ([#8452](https://github.com/paritytech/parity/pull/8452)) + - Fix Cargo.lock +- Backports ([#8450](https://github.com/paritytech/parity/pull/8450)) + - Use forked app_dirs crate for reverted Windows dir behavior ([#8438](https://github.com/paritytech/parity/pull/8438)) + - Remove unused app_dirs dependency in CLI + - Use forked app_dirs crate for reverted Windows dir behavior + - Remove Tendermint extra_info due to seal inconsistencies ([#8367](https://github.com/paritytech/parity/pull/8367)) + - Handle queue import errors a bit more gracefully ([#8385](https://github.com/paritytech/parity/pull/8385)) + - Improve VM executor stack size estimation rules ([#8439](https://github.com/paritytech/parity/pull/8439)) + - Improve VM executor stack size estimation rules + - Typo: docs add "(Debug build)" comment + - Fix an off by one typo and set minimal stack size + - Use saturating_sub to avoid potential overflow + ## Parity [v1.10.1](https://github.com/paritytech/parity/releases/tag/v1.10.1) (2018-04-17) Parity 1.10.1 is a bug-fix release to improve performance and stability. Among other changes, you can now use `--warp-barrier [BLOCK]` to specify a minimum block number to `--warp` to. This is useful in cases where clients restore to outdated snapshots far behind the latest chain head. diff --git a/docs/CHANGELOG-1.9.md b/docs/CHANGELOG-1.9.md index 0351d611353..133c93c4770 100644 --- a/docs/CHANGELOG-1.9.md +++ b/docs/CHANGELOG-1.9.md @@ -1,3 +1,29 @@ +## Parity [v1.9.7](https://github.com/paritytech/parity/releases/tag/v1.9.7) (2018-04-23) + +Parity 1.9.7 is a bug-fix release to improve performance and stability. + +The full list of included changes: + +- Update Parity stable to 1.9.7 + Backports ([#8456](https://github.com/paritytech/parity/pull/8456)) + - Update Parity stable to 1.9.7 + - Allow 32-bit pipelines to fail ([#8454](https://github.com/paritytech/parity/pull/8454)) + - Disable 32-bit targets for Gitlab + - Rename Linux pipelines + - Update wasmi ([#8452](https://github.com/paritytech/parity/pull/8452)) + - Revert Cargo lock update from master + - Fix Cargo.lock +- Backports ([#8449](https://github.com/paritytech/parity/pull/8449)) + - Use forked app_dirs crate for reverted Windows dir behavior ([#8438](https://github.com/paritytech/parity/pull/8438)) + - Remove unused app_dirs dependency in CLI + - Use forked app_dirs crate for reverted Windows dir behavior + - Remove Tendermint extra_info due to seal inconsistencies ([#8367](https://github.com/paritytech/parity/pull/8367)) + - Improve VM executor stack size estimation rules ([#8439](https://github.com/paritytech/parity/pull/8439)) + - Improve VM executor stack size estimation rules + - Typo: docs add "(Debug build)" comment + - Fix an off by one typo and set minimal stack size + - Use saturating_sub to avoid potential overflow + - Upgrade crossbeam to 0.3 + ## Parity [v1.9.6](https://github.com/paritytech/parity/releases/tag/v1.9.6) (2018-04-16) Parity 1.9.6 is a bug-fix release to improve performance and stability. From baeda9347471760d52be9a6b08444196f01f9bea Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Tue, 24 Apr 2018 15:25:27 +0300 Subject: [PATCH 13/95] fix typos in vm description comment (#8446) --- json/src/vm/vm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json/src/vm/vm.rs b/json/src/vm/vm.rs index c7e33b609a7..8cc01e3bac2 100644 --- a/json/src/vm/vm.rs +++ b/json/src/vm/vm.rs @@ -22,7 +22,7 @@ use hash::H256; use blockchain::State; use vm::{Transaction, Call, Env}; -/// Reporesents vm execution environment before and after exeuction of transaction. +/// Represents vm execution environment before and after execution of transaction. #[derive(Debug, PartialEq, Deserialize)] pub struct Vm { /// Contract calls made internaly by executed transaction. From 7fdb87ad38f8ea969a4e733c7bbf621b1668a82d Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 25 Apr 2018 16:00:58 +0800 Subject: [PATCH 14/95] Use rename_all for RichBlock and RichHeader serialization (#8471) * typo: fix a resolved TODO comment * Use rename_all instead of individual renames --- rpc/src/v1/types/block.rs | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/rpc/src/v1/types/block.rs b/rpc/src/v1/types/block.rs index 2b3a085ca55..486e3b9c140 100644 --- a/rpc/src/v1/types/block.rs +++ b/rpc/src/v1/types/block.rs @@ -44,11 +44,11 @@ impl Serialize for BlockTransactions { /// Block representation #[derive(Debug, Serialize)] +#[serde(rename_all="camelCase")] pub struct Block { /// Hash of the block pub hash: Option, /// Hash of the parent - #[serde(rename="parentHash")] pub parent_hash: H256, /// Hash of the uncles #[serde(rename="sha3Uncles")] @@ -58,37 +58,28 @@ pub struct Block { /// Alias of `author` pub miner: H160, /// State root hash - #[serde(rename="stateRoot")] pub state_root: H256, /// Transactions root hash - #[serde(rename="transactionsRoot")] pub transactions_root: H256, /// Transactions receipts root hash - #[serde(rename="receiptsRoot")] pub receipts_root: H256, /// Block number pub number: Option, /// Gas Used - #[serde(rename="gasUsed")] pub gas_used: U256, /// Gas Limit - #[serde(rename="gasLimit")] pub gas_limit: U256, /// Extra data - #[serde(rename="extraData")] pub extra_data: Bytes, /// Logs bloom - #[serde(rename="logsBloom")] pub logs_bloom: Option, /// Timestamp pub timestamp: U256, /// Difficulty pub difficulty: U256, /// Total difficulty - #[serde(rename="totalDifficulty")] pub total_difficulty: Option, /// Seal fields - #[serde(rename="sealFields")] pub seal_fields: Vec, /// Uncles' hashes pub uncles: Vec, @@ -100,49 +91,40 @@ pub struct Block { /// Block header representation. #[derive(Debug, Clone, Serialize, PartialEq, Eq)] +#[serde(rename_all="camelCase")] pub struct Header { /// Hash of the block pub hash: Option, /// Hash of the parent - #[serde(rename="parentHash")] pub parent_hash: H256, /// Hash of the uncles #[serde(rename="sha3Uncles")] pub uncles_hash: H256, /// Authors address pub author: H160, - // TODO: get rid of this one - /// ? + /// Alias of `author` pub miner: H160, /// State root hash - #[serde(rename="stateRoot")] pub state_root: H256, /// Transactions root hash - #[serde(rename="transactionsRoot")] pub transactions_root: H256, /// Transactions receipts root hash - #[serde(rename="receiptsRoot")] pub receipts_root: H256, /// Block number pub number: Option, /// Gas Used - #[serde(rename="gasUsed")] pub gas_used: U256, /// Gas Limit - #[serde(rename="gasLimit")] pub gas_limit: U256, /// Extra data - #[serde(rename="extraData")] pub extra_data: Bytes, /// Logs bloom - #[serde(rename="logsBloom")] pub logs_bloom: H2048, /// Timestamp pub timestamp: U256, /// Difficulty pub difficulty: U256, /// Seal fields - #[serde(rename="sealFields")] pub seal_fields: Vec, /// Size in bytes pub size: Option, From fa261ebd02906df6f25d79ce9c8fd597184cf680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 25 Apr 2018 15:39:46 +0200 Subject: [PATCH 15/95] Don't require write lock when fetching status. (#8481) --- ethcore/sync/src/api.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index 6270bcfd596..c66a1c6a625 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -318,7 +318,7 @@ impl EthSync { impl SyncProvider for EthSync { /// Get sync status fn status(&self) -> EthSyncStatus { - self.eth_handler.sync.write().status() + self.eth_handler.sync.read().status() } /// Get sync peers From adc3457a893bac241c00e897df702e9bbc1468d9 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Wed, 25 Apr 2018 16:25:43 +0200 Subject: [PATCH 16/95] Bump master to 1.12 (#8477) * Bump master to 1.12 * Bump crates to 1.12 * Bump mac installer version to 1.12 * Update Gitlab scripts --- .gitlab-ci.yml | 2 +- Cargo.lock | 216 ++++++++++++++++----------------- Cargo.toml | 2 +- dapps/Cargo.toml | 2 +- dapps/ui/Cargo.toml | 2 +- devtools/Cargo.toml | 2 +- ethash/Cargo.toml | 2 +- ethcore/Cargo.toml | 2 +- ethcore/light/Cargo.toml | 2 +- ethcore/node_filter/Cargo.toml | 2 +- ethcore/stratum/Cargo.toml | 2 +- ethcore/sync/Cargo.toml | 2 +- hash-fetch/Cargo.toml | 2 +- hw/Cargo.toml | 2 +- ipfs/Cargo.toml | 2 +- logger/Cargo.toml | 2 +- mac/Parity.pkgproj | 2 +- mac/Parity/Info.plist | 2 +- miner/Cargo.toml | 2 +- nsis/installer.nsi | 2 +- price-info/Cargo.toml | 2 +- rpc/Cargo.toml | 2 +- scripts/gitlab-build.sh | 2 +- transaction-pool/Cargo.toml | 2 +- updater/Cargo.toml | 2 +- util/io/Cargo.toml | 2 +- util/network-devp2p/Cargo.toml | 2 +- util/network/Cargo.toml | 2 +- util/version/Cargo.toml | 4 +- 29 files changed, 137 insertions(+), 137 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3a04125e577..2c216496f67 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -188,7 +188,7 @@ docker-build: before_script: - docker info script: - - if [ "$CI_BUILD_REF_NAME" == "beta-release" ]; then DOCKER_TAG="latest"; else DOCKER_TAG=$CI_BUILD_REF_NAME; fi + - if [ "$CI_BUILD_REF_NAME" == "master" ]; then DOCKER_TAG="latest"; else DOCKER_TAG=$CI_BUILD_REF_NAME; fi - echo "Tag:" $DOCKER_TAG - docker login -u $Docker_Hub_User_Parity -p $Docker_Hub_Pass_Parity - scripts/docker-build.sh $DOCKER_TAG diff --git a/Cargo.lock b/Cargo.lock index 2b5807fe502..bb7936297e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -478,7 +478,7 @@ dependencies = [ [[package]] name = "ethash" -version = "1.11.0" +version = "1.12.0" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -504,7 +504,7 @@ dependencies = [ [[package]] name = "ethcore" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "bloomchain 0.2.0", @@ -516,13 +516,13 @@ dependencies = [ "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 1.11.0", + "ethash 1.12.0", "ethcore-bloom-journal 0.1.0", "ethcore-bytes 0.1.0", - "ethcore-io 1.11.0", - "ethcore-logger 1.11.0", - "ethcore-miner 1.11.0", - "ethcore-stratum 1.11.0", + "ethcore-io 1.12.0", + "ethcore-logger 1.12.0", + "ethcore-miner 1.12.0", + "ethcore-stratum 1.12.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", @@ -530,7 +530,7 @@ dependencies = [ "ethstore 0.2.0", "evm 0.1.0", "fetch 0.1.0", - "hardware-wallet 1.11.0", + "hardware-wallet 1.12.0", "hashdb 0.1.1", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -596,11 +596,11 @@ dependencies = [ [[package]] name = "ethcore-devtools" -version = "1.11.0" +version = "1.12.0" [[package]] name = "ethcore-io" -version = "1.11.0" +version = "1.12.0" dependencies = [ "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -611,14 +611,14 @@ dependencies = [ [[package]] name = "ethcore-light" -version = "1.11.0" +version = "1.12.0" dependencies = [ "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.11.0", + "ethcore 1.12.0", "ethcore-bytes 0.1.0", - "ethcore-io 1.11.0", - "ethcore-network 1.11.0", + "ethcore-io 1.12.0", + "ethcore-network 1.12.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -648,7 +648,7 @@ dependencies = [ [[package]] name = "ethcore-logger" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -663,12 +663,12 @@ dependencies = [ [[package]] name = "ethcore-miner" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 1.11.0", + "ethash 1.12.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", @@ -682,21 +682,21 @@ dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parity-reactor 0.1.0", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "price-info 1.11.0", + "price-info 1.12.0", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "trace-time 0.1.0", - "transaction-pool 1.11.0", + "transaction-pool 1.12.0", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethcore-network" -version = "1.11.0" +version = "1.12.0" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-crypto 0.1.0", - "ethcore-io 1.11.0", + "ethcore-io 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -706,16 +706,16 @@ dependencies = [ [[package]] name = "ethcore-network-devp2p" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0", "ethcore-crypto 0.1.0", - "ethcore-io 1.11.0", - "ethcore-logger 1.11.0", - "ethcore-network 1.11.0", + "ethcore-io 1.12.0", + "ethcore-logger 1.12.0", + "ethcore-network 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "igd 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -747,12 +747,12 @@ dependencies = [ "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.11.0", + "ethcore 1.12.0", "ethcore-bytes 0.1.0", "ethcore-crypto 0.1.0", - "ethcore-io 1.11.0", - "ethcore-logger 1.11.0", - "ethcore-miner 1.11.0", + "ethcore-io 1.12.0", + "ethcore-logger 1.12.0", + "ethcore-miner 1.12.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", @@ -782,11 +782,11 @@ dependencies = [ "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.11.0", + "ethcore 1.12.0", "ethcore-bytes 0.1.0", "ethcore-crypto 0.1.0", - "ethcore-logger 1.11.0", - "ethcore-sync 1.11.0", + "ethcore-logger 1.12.0", + "ethcore-sync 1.12.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", @@ -819,10 +819,10 @@ version = "0.1.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.11.0", - "ethcore-io 1.11.0", + "ethcore 1.12.0", + "ethcore-io 1.12.0", "ethcore-private-tx 1.0.0", - "ethcore-sync 1.11.0", + "ethcore-sync 1.12.0", "kvdb 0.1.0", "kvdb-rocksdb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -832,10 +832,10 @@ dependencies = [ [[package]] name = "ethcore-stratum" -version = "1.11.0" +version = "1.12.0" dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-logger 1.11.0", + "ethcore-logger 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", @@ -849,15 +849,15 @@ dependencies = [ [[package]] name = "ethcore-sync" -version = "1.11.0" +version = "1.12.0" dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.11.0", + "ethcore 1.12.0", "ethcore-bytes 0.1.0", - "ethcore-io 1.11.0", - "ethcore-light 1.11.0", - "ethcore-network 1.11.0", - "ethcore-network-devp2p 1.11.0", + "ethcore-io 1.12.0", + "ethcore-light 1.12.0", + "ethcore-network 1.12.0", + "ethcore-network-devp2p 1.12.0", "ethcore-private-tx 1.0.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1024,7 +1024,7 @@ name = "evmbin" version = "0.1.0" dependencies = [ "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.11.0", + "ethcore 1.12.0", "ethcore-bytes 0.1.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1165,7 +1165,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hardware-wallet" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", @@ -1330,7 +1330,7 @@ name = "journaldb" version = "0.1.0" dependencies = [ "ethcore-bytes 0.1.0", - "ethcore-logger 1.11.0", + "ethcore-logger 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1784,14 +1784,14 @@ dependencies = [ [[package]] name = "node-filter" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.11.0", - "ethcore-io 1.11.0", - "ethcore-network-devp2p 1.11.0", + "ethcore 1.12.0", + "ethcore-io 1.12.0", + "ethcore-network-devp2p 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb-memorydb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1941,7 +1941,7 @@ dependencies = [ [[package]] name = "parity" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1951,18 +1951,18 @@ dependencies = [ "dir 0.1.0", "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.11.0", + "ethcore 1.12.0", "ethcore-bytes 0.1.0", - "ethcore-io 1.11.0", - "ethcore-light 1.11.0", - "ethcore-logger 1.11.0", - "ethcore-miner 1.11.0", - "ethcore-network 1.11.0", + "ethcore-io 1.12.0", + "ethcore-light 1.12.0", + "ethcore-logger 1.12.0", + "ethcore-miner 1.12.0", + "ethcore-network 1.12.0", "ethcore-private-tx 1.0.0", "ethcore-secretstore 1.0.0", "ethcore-service 0.1.0", - "ethcore-stratum 1.11.0", - "ethcore-sync 1.11.0", + "ethcore-stratum 1.12.0", + "ethcore-sync 1.12.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", @@ -1979,20 +1979,20 @@ dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mem 0.1.0", "migration-rocksdb 0.1.0", - "node-filter 1.11.0", + "node-filter 1.12.0", "node-health 0.1.0", "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", - "parity-dapps 1.11.0", - "parity-hash-fetch 1.11.0", - "parity-ipfs-api 1.11.0", + "parity-dapps 1.12.0", + "parity-hash-fetch 1.12.0", + "parity-ipfs-api 1.12.0", "parity-local-store 0.1.0", "parity-reactor 0.1.0", - "parity-rpc 1.11.0", + "parity-rpc 1.12.0", "parity-rpc-client 1.4.0", - "parity-updater 1.11.0", - "parity-version 1.11.0", + "parity-updater 1.12.0", + "parity-version 1.12.0", "parity-whisper 0.1.0", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "path 0.1.0", @@ -2017,12 +2017,12 @@ dependencies = [ [[package]] name = "parity-dapps" -version = "1.11.0" +version = "1.12.0" dependencies = [ "base32 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0", - "ethcore-devtools 1.11.0", + "ethcore-devtools 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "fetch 0.1.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2036,11 +2036,11 @@ dependencies = [ "mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-health 0.1.0", "parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-hash-fetch 1.11.0", + "parity-hash-fetch 1.12.0", "parity-reactor 0.1.0", - "parity-ui 1.11.0", + "parity-ui 1.12.0", "parity-ui-deprecation 1.10.0", - "parity-version 1.11.0", + "parity-version 1.12.0", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "registrar 0.0.1", @@ -2082,7 +2082,7 @@ dependencies = [ [[package]] name = "parity-hash-fetch" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2107,10 +2107,10 @@ dependencies = [ [[package]] name = "parity-ipfs-api" -version = "1.11.0" +version = "1.12.0" dependencies = [ "cid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.11.0", + "ethcore 1.12.0", "ethcore-bytes 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", @@ -2124,8 +2124,8 @@ dependencies = [ name = "parity-local-store" version = "0.1.0" dependencies = [ - "ethcore 1.11.0", - "ethcore-io 1.11.0", + "ethcore 1.12.0", + "ethcore-io 1.12.0", "ethcore-transaction 0.1.0", "ethkey 0.3.0", "kvdb 0.1.0", @@ -2154,22 +2154,22 @@ dependencies = [ [[package]] name = "parity-rpc" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "cid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 1.11.0", - "ethcore 1.11.0", + "ethash 1.12.0", + "ethcore 1.12.0", "ethcore-bytes 0.1.0", "ethcore-crypto 0.1.0", - "ethcore-devtools 1.11.0", - "ethcore-io 1.11.0", - "ethcore-light 1.11.0", - "ethcore-logger 1.11.0", - "ethcore-miner 1.11.0", - "ethcore-network 1.11.0", + "ethcore-devtools 1.12.0", + "ethcore-io 1.12.0", + "ethcore-light 1.12.0", + "ethcore-logger 1.12.0", + "ethcore-miner 1.12.0", + "ethcore-network 1.12.0", "ethcore-private-tx 1.0.0", - "ethcore-sync 1.11.0", + "ethcore-sync 1.12.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", @@ -2179,7 +2179,7 @@ dependencies = [ "fetch 0.1.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "hardware-wallet 1.11.0", + "hardware-wallet 1.12.0", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", @@ -2195,8 +2195,8 @@ dependencies = [ "node-health 0.1.0", "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-reactor 0.1.0", - "parity-updater 1.11.0", - "parity-version 1.11.0", + "parity-updater 1.12.0", + "parity-version 1.12.0", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie 0.1.0", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2212,7 +2212,7 @@ dependencies = [ "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "transaction-pool 1.11.0", + "transaction-pool 1.12.0", "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", ] @@ -2227,7 +2227,7 @@ dependencies = [ "keccak-hash 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-rpc 1.11.0", + "parity-rpc 1.12.0", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2253,7 +2253,7 @@ dependencies = [ [[package]] name = "parity-ui" -version = "1.11.0" +version = "1.12.0" dependencies = [ "parity-ui-dev 1.9.0 (git+https://github.com/parity-js/shell.git?rev=eecaadcb9e421bce31e91680d14a20bbd38f92a2)", "parity-ui-old-dev 1.9.0 (git+https://github.com/parity-js/dapp-wallet.git?rev=65deb02e7c007a0fd8aab0c089c93e3fd1de6f87)", @@ -2303,21 +2303,21 @@ dependencies = [ [[package]] name = "parity-updater" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.11.0", + "ethcore 1.12.0", "ethcore-bytes 0.1.0", - "ethcore-sync 1.11.0", + "ethcore-sync 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.0", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-hash-fetch 1.11.0", - "parity-version 1.11.0", + "parity-hash-fetch 1.12.0", + "parity-version 1.12.0", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "path 0.1.0", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2328,7 +2328,7 @@ dependencies = [ [[package]] name = "parity-version" -version = "1.11.0" +version = "1.12.0" dependencies = [ "ethcore-bytes 0.1.0", "rlp 0.2.1", @@ -2355,7 +2355,7 @@ dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-crypto 0.1.0", - "ethcore-network 1.11.0", + "ethcore-network 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2418,7 +2418,7 @@ version = "0.1.0" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0", - "ethcore-logger 1.11.0", + "ethcore-logger 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1", "keccak-hash 0.1.0", @@ -2493,7 +2493,7 @@ dependencies = [ [[package]] name = "price-info" -version = "1.11.0" +version = "1.12.0" dependencies = [ "fake-fetch 0.0.1", "fetch 0.1.0", @@ -2573,7 +2573,7 @@ name = "pwasm-run-test" version = "0.1.0" dependencies = [ "clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-logger 1.11.0", + "ethcore-logger 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2802,7 +2802,7 @@ version = "1.4.0" dependencies = [ "bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-rpc 1.11.0", + "parity-rpc 1.12.0", "parity-rpc-client 1.4.0", "rpassword 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3415,7 +3415,7 @@ dependencies = [ [[package]] name = "transaction-pool" -version = "1.11.0" +version = "1.12.0" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3620,7 +3620,7 @@ name = "wasm" version = "0.1.0" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-logger 1.11.0", + "ethcore-logger 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3663,9 +3663,9 @@ name = "whisper-cli" version = "0.1.0" dependencies = [ "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-logger 1.11.0", - "ethcore-network 1.11.0", - "ethcore-network-devp2p 1.11.0", + "ethcore-logger 1.12.0", + "ethcore-network 1.12.0", + "ethcore-network-devp2p 1.12.0", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", diff --git a/Cargo.toml b/Cargo.toml index 4237bf545ff..a611458e653 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ description = "Parity Ethereum client" name = "parity" # NOTE Make sure to update util/version/Cargo.toml as well -version = "1.11.0" +version = "1.12.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index 8e35b213e06..a7ce5a54893 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity Dapps crate" name = "parity-dapps" -version = "1.11.0" +version = "1.12.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/dapps/ui/Cargo.toml b/dapps/ui/Cargo.toml index e7f409b1c1c..acb7a91735f 100644 --- a/dapps/ui/Cargo.toml +++ b/dapps/ui/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore Parity UI" homepage = "http://parity.io" license = "GPL-3.0" name = "parity-ui" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [build-dependencies] diff --git a/devtools/Cargo.toml b/devtools/Cargo.toml index d5e275a3adb..71eeaa2ddd0 100644 --- a/devtools/Cargo.toml +++ b/devtools/Cargo.toml @@ -3,5 +3,5 @@ description = "Ethcore development/test/build tools" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-devtools" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] diff --git a/ethash/Cargo.toml b/ethash/Cargo.toml index 91f1ce56f70..4bb1b50470e 100644 --- a/ethash/Cargo.toml +++ b/ethash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethash" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [lib] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index c9db7cf9f68..147d9484c70 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore library" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [dependencies] diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index ba76dc3b104..3853ad910ff 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -3,7 +3,7 @@ description = "Parity Light Client Implementation" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-light" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [dependencies] diff --git a/ethcore/node_filter/Cargo.toml b/ethcore/node_filter/Cargo.toml index a726448bd1c..25b5ec59f4e 100644 --- a/ethcore/node_filter/Cargo.toml +++ b/ethcore/node_filter/Cargo.toml @@ -3,7 +3,7 @@ description = "Parity smart network connections" homepage = "http://parity.io" license = "GPL-3.0" name = "node-filter" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [dependencies] diff --git a/ethcore/stratum/Cargo.toml b/ethcore/stratum/Cargo.toml index de65a470c66..bf967df504a 100644 --- a/ethcore/stratum/Cargo.toml +++ b/ethcore/stratum/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore stratum lib" name = "ethcore-stratum" -version = "1.11.0" +version = "1.12.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/ethcore/sync/Cargo.toml b/ethcore/sync/Cargo.toml index 6930baa101b..d2d060e686f 100644 --- a/ethcore/sync/Cargo.toml +++ b/ethcore/sync/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore blockchain sync" name = "ethcore-sync" -version = "1.11.0" +version = "1.12.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/hash-fetch/Cargo.toml b/hash-fetch/Cargo.toml index 6a735fe37e0..d4f46a121e8 100644 --- a/hash-fetch/Cargo.toml +++ b/hash-fetch/Cargo.toml @@ -3,7 +3,7 @@ description = "Fetching hash-addressed content." homepage = "http://parity.io" license = "GPL-3.0" name = "parity-hash-fetch" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [dependencies] diff --git a/hw/Cargo.toml b/hw/Cargo.toml index 778fb26e069..9a717e4bd3c 100644 --- a/hw/Cargo.toml +++ b/hw/Cargo.toml @@ -3,7 +3,7 @@ description = "Hardware wallet support." homepage = "http://parity.io" license = "GPL-3.0" name = "hardware-wallet" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [dependencies] diff --git a/ipfs/Cargo.toml b/ipfs/Cargo.toml index 15bd173c2ff..9c7b5f3b003 100644 --- a/ipfs/Cargo.toml +++ b/ipfs/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity IPFS-compatible API" name = "parity-ipfs-api" -version = "1.11.0" +version = "1.12.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/logger/Cargo.toml b/logger/Cargo.toml index 368d860fd44..a1f793769c5 100644 --- a/logger/Cargo.toml +++ b/logger/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Log implementation for Parity" name = "ethcore-logger" -version = "1.11.0" +version = "1.12.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/mac/Parity.pkgproj b/mac/Parity.pkgproj index e5229f927a3..36b8921ee2f 100755 --- a/mac/Parity.pkgproj +++ b/mac/Parity.pkgproj @@ -462,7 +462,7 @@ OVERWRITE_PERMISSIONS VERSION - 1.11.0 + 1.12.0 UUID 2DCD5B81-7BAF-4DA1-9251-6274B089FD36 diff --git a/mac/Parity/Info.plist b/mac/Parity/Info.plist index 2cc7e67b83e..e0bdc21e695 100644 --- a/mac/Parity/Info.plist +++ b/mac/Parity/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.11 + 1.12 CFBundleVersion 1 LSApplicationCategoryType diff --git a/miner/Cargo.toml b/miner/Cargo.toml index cf8eb0cdd8b..95dd888dc9a 100644 --- a/miner/Cargo.toml +++ b/miner/Cargo.toml @@ -3,7 +3,7 @@ description = "Parity Miner interface." name = "ethcore-miner" homepage = "http://parity.io" license = "GPL-3.0" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [dependencies] diff --git a/nsis/installer.nsi b/nsis/installer.nsi index 01155723401..c1f4033312c 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -9,7 +9,7 @@ !define COMPANYNAME "Parity Technologies" !define DESCRIPTION "Fast, light, robust Ethereum implementation" !define VERSIONMAJOR 1 -!define VERSIONMINOR 11 +!define VERSIONMINOR 12 !define VERSIONBUILD 0 !define ARGS "" !define FIRST_START_ARGS "--mode=passive ui" diff --git a/price-info/Cargo.toml b/price-info/Cargo.toml index 8dd497be9a1..948f09983ba 100644 --- a/price-info/Cargo.toml +++ b/price-info/Cargo.toml @@ -3,7 +3,7 @@ description = "Fetch current ETH price" homepage = "http://parity.io" license = "GPL-3.0" name = "price-info" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [dependencies] diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index d35a64af9d0..b8eb5254629 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity JSON-RPC servers." name = "parity-rpc" -version = "1.11.0" +version = "1.12.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/scripts/gitlab-build.sh b/scripts/gitlab-build.sh index a2a084adc9b..5f353a63da3 100755 --- a/scripts/gitlab-build.sh +++ b/scripts/gitlab-build.sh @@ -313,7 +313,7 @@ case $BUILD_PLATFORM in snapcraft clean echo "Prepare snapcraft.yaml for build on Gitlab CI in Docker image" sed -i 's/git/'"$VER"'/g' snap/snapcraft.yaml - if [[ "$CI_BUILD_REF_NAME" = "beta" || "$VER" == *1.10* ]]; + if [[ "$CI_BUILD_REF_NAME" = "beta" || "$VER" == *1.11* ]]; then sed -i -e 's/grade: devel/grade: stable/' snap/snapcraft.yaml; fi diff --git a/transaction-pool/Cargo.toml b/transaction-pool/Cargo.toml index fd191929937..b8630781123 100644 --- a/transaction-pool/Cargo.toml +++ b/transaction-pool/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Generic transaction pool." name = "transaction-pool" -version = "1.11.0" +version = "1.12.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/updater/Cargo.toml b/updater/Cargo.toml index 9e7733bc46e..d76db6ec0ea 100644 --- a/updater/Cargo.toml +++ b/updater/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity Updater Service." name = "parity-updater" -version = "1.11.0" +version = "1.12.0" license = "GPL-3.0" authors = ["Parity Technologies "] diff --git a/util/io/Cargo.toml b/util/io/Cargo.toml index dca0426d509..8538863d03e 100644 --- a/util/io/Cargo.toml +++ b/util/io/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore IO library" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-io" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [dependencies] diff --git a/util/network-devp2p/Cargo.toml b/util/network-devp2p/Cargo.toml index 74edf83ad5d..a8207ca615b 100644 --- a/util/network-devp2p/Cargo.toml +++ b/util/network-devp2p/Cargo.toml @@ -3,7 +3,7 @@ description = "DevP2P implementation of the ethcore network library" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-network-devp2p" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [dependencies] diff --git a/util/network/Cargo.toml b/util/network/Cargo.toml index f98cd9e93ca..f7131da0388 100644 --- a/util/network/Cargo.toml +++ b/util/network/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore network library" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-network" -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] [dependencies] diff --git a/util/version/Cargo.toml b/util/version/Cargo.toml index 1cc0dc6d2c2..297211b2bd0 100644 --- a/util/version/Cargo.toml +++ b/util/version/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "parity-version" # NOTE: this value is used for Parity version string (via env CARGO_PKG_VERSION) -version = "1.11.0" +version = "1.12.0" authors = ["Parity Technologies "] build = "build.rs" @@ -13,7 +13,7 @@ build = "build.rs" track = "nightly" # Indicates a critical release in this track (i.e. consensus issue) -critical = true +critical = false # Latest supported fork blocks for various networks. Used ONLY by auto-updater. [package.metadata.forks] From f56c065f57d6a27332c7afabf27c53c9524caf16 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Wed, 25 Apr 2018 16:25:57 +0200 Subject: [PATCH 17/95] Fix snap builds (#8483) --- scripts/gitlab-build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/gitlab-build.sh b/scripts/gitlab-build.sh index 5f353a63da3..89fa2a08541 100755 --- a/scripts/gitlab-build.sh +++ b/scripts/gitlab-build.sh @@ -309,6 +309,7 @@ case $BUILD_PLATFORM in x86_64-unknown-snap-gnu) ARC="amd64" EXT="snap" + apt update apt install -y expect zip rhash snapcraft clean echo "Prepare snapcraft.yaml for build on Gitlab CI in Docker image" From 4e85015836a0e0c6ad89d3124fd4532078df7f43 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Wed, 25 Apr 2018 16:27:22 +0200 Subject: [PATCH 18/95] Update hardcodedSync for Ethereum, Kovan, and Ropsten (#8489) --- ethcore/res/ethereum/foundation.json | 111 +- ethcore/res/ethereum/kovan.json | 3422 ++++++++++++++++++++++++++ ethcore/res/ethereum/ropsten.json | 1522 ++++++++++++ 3 files changed, 5052 insertions(+), 3 deletions(-) diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 53322e6ffec..4438718711a 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -174,8 +174,8 @@ "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" }, "hardcodedSync": { - "header": "f90219a061d694007fbaca6e23e73e29c8c6a60099abc740ab7e27ae3cd1b9c6a47efef7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca0a2f1bdabc1a72737de1c22a76cacc8fc162366904f759a99db7d6d19efee3090a0ac5f5b236e8977928a2ce43c7569ea5a74919643cb0b06d7540407b1ea1298f0a04356ddc5d77c83923a6541260308be167386e0969a608a017770c9e38091cfcab90100a00010002001009080011010141088000004000080081100000a002023000002204204801204084000c000010008000000000880080020c0000440200460000290005010c01c80800080004800100406003380000400402040000028084002a80087000008090a00200100544020019580022000000306100a0080100084020006809000e80000010000254810002000000a240050014200002002c10809202030006422022000203012000241089300080400000009001021020200012410348500028290230408100302000000058c0000020c08c20480081040020260004008481000080000800010010060020000e00020002140100a8988000004400201870b9af4a66df8038350a8018379d54483799eba845ab0426d984554482e45544846414e532e4f52472d3231323134313232a05eeccc80302d8fecca48a47be03654b5a41b5e5f296f271f910ebae631124f518890074810024c6c2b", - "totalDifficulty": "3144406426008470895785", + "header": "f90216a03b798fd7d7c51f61fdbe7a08d6d2257eea4501c12dfc5442146b85837c0da51fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ea674fdde714fd979de3edf0f56aa9716b898ec8a0a2df7c321f2a532f63cdaf4e234227dd067f3782787db2ac892e875a8cb6842fa0c3a3f2c96c938633c7a99531a3876d544dbb8d5fac06879bea8e3cc5b6ece09da0221863f4a4fa6ca8dc7b6eed0eaefea36a5069f06ba9a61e78b87b634b5e4409b9010000a02080204012000000004100800000c0a08040041160000000740200200148000000000104011040800081808000102001180000000a80000011401020002c14008402000000100014400e20082080400000aa004100000000d10e8a0026180020882008200400a548000000201010088080000c0020800000001004046200600000052004020001800400800400420001800084002c1200040088028840004604020820400000264000005808500400410451c0808020140380c02014000440000002010422080800000240000000048a80072140000400409020020220810010020018008021800280a05008020000400000000044178000008000044410870b075e7ebe9d268353f001837a11f88379cd17845adfefa59565746865726d696e652d6177732d61736961312d32a0c92755fe5da24ea52d89783e387d88e1c2e24ac202641dd9906fc704a88979d28818d4dcc0009d0541", + "totalDifficulty": "3828700463149109414955", "CHTs": [ "0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc", "0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11", @@ -2757,7 +2757,112 @@ "0x568f44291c13efc908db42d2473bc91ebb16e062e9b4368bcb770a3033d67741", "0xe5ecad510448855ff0aafb92a8c7aa54aca0fb390bec3c14ad5d2ba200380aec", "0xa40aa7655c1458b76c04ea5934ae171fb01c72c8c375bb61a0c27b0ebd70f21f", - "0x770ad5107ac47fd983979b016553ca8f340a13e2647b9140e65c980dcf349cff" + "0x770ad5107ac47fd983979b016553ca8f340a13e2647b9140e65c980dcf349cff", + "0xfd074cacab08d2d5f113669672632ab0e94e03bfbbe17fc3de27a30e9f0e8327", + "0x2063bf5ce8eed483242157113534b314296deb123cb33083cb0cce04db610c9a", + "0x9dfb8274e842fd3cb7d73506e64adacc39eb12ebd8a972b7101385ac4eb5b12c", + "0x8294c3d4892cb0bcba9acdd31d53af5bfc97daf124f08d903297da8bbb28cdfe", + "0x9dc2d04fe197009f24ebd4a0c95a0b91d4ff0093387b61569af993fa91edb3fa", + "0xe88e256abdc6447b1f141c2fcf2c46721d9717a9fcb302513c93ed6e31b7c11c", + "0xd2ad4ca6091f6ae6c323b6565522c208a839e36958a1675e5e9b48b13068e7c8", + "0xb168169f2643b8cdbec58f3f94d7889af37117a35389726563ac770f5205faab", + "0x09f32b423ca728b8fd04f9872325c0e2a4c9b1eb36fab49b31ae51254c69ebab", + "0x0b47f8f28a3242c9ca705fd11949e648f190053de023366f98e6c736eb2f0de1", + "0x870a8067623b35b5f0146ec95047869357617fe3773a8285a622c18d44963f9f", + "0xd14e05d8f3238294ffd8885c1f1710f64f2d8eb3d3b4e8a921f7f5c94a0a6288", + "0xf9cdef6ffacbea7692e9fef3de1b778bd11399492486dca0209b27bd474eb04a", + "0x5dc41201eaa00957d070c68bb289fc00eb31b7e5fff52f0603d52d27a40abf81", + "0xae3a53054ff4e3e5562795b45777e1e3e82abeed84e2fab748af50aace8bc8e2", + "0x93fd6f9af3b1efd27487477edccd690b19902300a4eebd34cb0d9b2e60b3cccf", + "0xbe475a9dc045e70ac8218e5a65450edf026d70f3f814162251f83a88098245c2", + "0x20566435d247cc1e7d0d81e143c01b6649fa1fd3cd5a9f97738e6045b29460c5", + "0xb37273228fe8b0c1679bb2dab7176ee1282400daddaaeb0db415c716f5dd1f71", + "0x494bb2cea59fc43629b0f8be3fba9ee5b52948c72fd1f1c94d31600756bfb675", + "0xc690eb3d8e65d5efc211def8fe8f198e42c0321000b8998a6ab218d897d593a5", + "0x26821d73690b9d1bdd9594c92b086291474cd365bd41f7de5edc49dfc29c26df", + "0x026a57937338c9e168d254f99dc9dbe3fb41508049ac1a5b6d7df868e2935e6c", + "0x50dc451812556bd69244f3728c6a17e958b2fa125248103942ac94142610bcc7", + "0x0ffe7ea32c3ef43049d8041a16bd3381ba89b1439dc5329e839546aa01a64726", + "0xab1e06f13dbaed341fc9e33ef387ebbe187787ccd8961a47560f7e02617a06db", + "0x8b72166b0d16ebfd9c3156f5972e3778e16b3d7edf3decd4b6efbc779990ca3c", + "0x149de0dcdbe03bf6d0ae9ccc989a074a4cf2e78311ce8cb6dee3856c2a374caa", + "0x42147f5960814dc31cc38b692089e6d1d53b85cc85a69e4cc01954dc61c268a6", + "0x1460ceccff1ac00f3e126383c3102c424b75c2abeb973d0baa8bec8e7bdda692", + "0xdbbbf28a5d25c832c5f625868dea79a481dce880d5145f4119d3e9eb32356a6b", + "0xd8e5b32a88bdb502fbd62888b9906a0c7955ccaaad1ead31636572a07fe7419b", + "0xdbc42abbec7d223666da11767d9862cd1458f91b5bf2f6499da4ae5bff281888", + "0xc3138499753f545de139238bdc8cd4cbad254c6b87bf0eb37dc1fe7a85168e79", + "0x42be700f627bb081543ab289fcd01235bedea5e33a9779d6d14744685f5a652a", + "0x8660e4130c98f6a8024c1b587dd24ebe402126d4d9a2adf610c62bf033b749c5", + "0xdab926bab8c4ff9e492f992b5696e8f7e3ba3ce77e49fe0e2ca36d3efc8791b6", + "0x0e3911bcf379fd57014bee6a1f796b884c62f2392cf6e8ac5a145126e4622b88", + "0xbd52346714664eeb7b4034bc6a54804824bdd40d9e5bdbae9375a302926babe6", + "0x641e58eaeb404f7a40b9c4be686c26721563b310f7624a654185a60374c1512e", + "0xfa07b0f7b970413ae5085f042224861bb1bc5f2f6ad72a44c3681d47a817c0a9", + "0x70cf3fffa7e27f03d5cbb1664bbd0e1315dfc43df76f1b0e3dce494255e54752", + "0x1d5b0118939994aa8be89dc365f909309df84e7c92530aef25d62118b09e0572", + "0x8b34c5a5cd5a42a58bbc60166f3f2a4be7d79057691c708e7a9639c21b6f57c7", + "0x7b149005e7f8378189c70c33c073d897cb07f62ba5ae319088b3be204beea8e4", + "0xf2a41e8feb5d294faca47dd1f7a90f66b7b616addcd179ae60c5f173cd44a85d", + "0xa2875c8e5a226f2cf69f07e19b13a628ef6a8662f3a5de4c9d666ca5ebddb001", + "0x4231ca8bdccd59526900a487608912a4fc0918a6c693250bd67787bc61a9d09b", + "0x2b06301a6372e0fca0da8a15d4e31a08522ecb91efbda58c3e495e2ab7f4fceb", + "0xd0e19f62b07275097b56e7f409cd52826a1dbc0be26eeaae20562420559153dc", + "0xa4ecf1ef04bcc95ba0ed9214e9118129ae5497c37db94dda284dd536b4dd75c9", + "0x3dc87ba482aaac6b59678c899bfb1da9b768e1385e0f8e8574852efeee2db8c0", + "0x07f8df3f6ec63d926c3a76b17ad1750a9ac6c62a8cdffa549440e651f6087178", + "0x96952f8ba7c83d640119868a030cb7397624ef322b2d153aa3843259da5f468c", + "0x08eca2fb4295f069f3fa62849b354a9e10b8a8e9b771cb8d2790b28b7b09d70c", + "0xfd5832f531c8819c0ce9d031434c33eb442578e81cf711e8ba23e9b21d096e13", + "0xfee9a8bae124565c963b65fa47dcf7f0c9b5ef7e778c2d99539b8a04efd04522", + "0xead692739a0723a73dd38b3aa02f93d72b3b6922c2520ea0b74981eaafe7f6a1", + "0x890dd8befeee6c7c7b4942b02a3bf1a9d1b9e1140ecd1c07de570f38b6c323b6", + "0x690343489ed214b9195db6181c42237b7a62fc935a18ca1a5dc883a2045ceae7", + "0x4bdfdc1bef8c19b89344230c0f48841abfeea788a4973c34afff4d2039ce4417", + "0x6ef6a94338d794400f95f8c0b6d5a40df8b56c31e9bd0037bdd7e41234bb32a1", + "0x00b7568bfdf2d4780b8650a49f707752a12fe9a88302622e68f264622877acdc", + "0x83e96e0b864df30b53ae08075acc83f785e9b8b2bc80e8976b1a954f995df012", + "0x664305b610d0b3167dd25210acba7eea291a37a224546a6f6d59aa7b71d16e5f", + "0x3d3a6401ab83eabc2af15a23b9c0e6d123f661b3599c6131d5923a106f562ac8", + "0x7a11833fbc8ce3d9883088649b930238625e6f6136dfa06a00daf8e646cd020c", + "0x112c33932097c4ec4e18f6308b2a6502cbf746605f1e404555dd07703d60ba2d", + "0x9e77cd028749d69caf352a95f75dee842c0d9323e3618afa2927b2aaaf7fc4a8", + "0x7fe0a62bfd04e263b4c67c5808f6231ad6faca7ff0f5bc0c02177034608d6991", + "0xea820d62b423b68da2f8ce345dbb56e2205fdfae1fce261d64acc959fb30cccd", + "0xd8f6367448dec55e8e2e26b5d304d92969abde131d402de313b1705c0bfd528f", + "0x4b97f3b4e0bff7cfe322e4f50176f6bfb379a706d42308ae75b2a46735762a95", + "0x7425ff9cea5e4869332ce12ef727fbcb004add827eb567424fd4c17717def390", + "0xc7dcd4fd005ae8d4d9e125727b54a64e900b3fee9cdc82fb5057c012178c8483", + "0x8ba88bfba201db1db716f762b5517369d3ae232ca045d2932fc27f6c47b15806", + "0xad2f63fa4fddd0cfc7f6cb01116d285e8aad4b0c51fa9445d39a4cb4949ed020", + "0x366874aec4ea26ece424f5402604ec7df9f40fc4cb9087cd3f45e764b1e36ebf", + "0x7f27eb75010b0d5da72794c129042511e24794b6c8491c1ff2e257dadcc7052d", + "0x27eadc596f6eaeb9247704c3339f7fe4e649f683fd815f9d71270caf5d9e38cd", + "0xba3f72ce8f45b1575554bd0c64feda3959c2a68f0300f021b67880b56f7152e2", + "0x50833c82dc63533f7ec918cd6d58ffbef4e2d597f354589b8eb66c9de0fc9697", + "0x30fc354a8893f683ef03bb024254574b550710f3c05496976cd39166a29e1c98", + "0x1b6b8d13fca6583d358b173c1a255c3db9efed8ad72084eadf10e29868a26fdc", + "0xb1b2a80122d1210160d8649d31422a1edc26b23e8499aa3a88b047dc52b42222", + "0x4e6c85a13cc0c739fbdf844a4f52c78979a84a86db728e4a5d2043ee3b2fcb3e", + "0xe98c28b49aa690aecfa43527acd3e5a010c8f90faf79ef5b4b479a715fe66a99", + "0x5b56e2b50ec96f7bda3f529ed71321650d688e2ee5c16723f6199256532ee660", + "0x1c9b8f5106a23096f2f57dfdb2a7a82876f4374be97b6a818fdc3c742b216b09", + "0xcb6973f775356ec7596ed6f9a036258e98677c7c5b2358da75af28f553327506", + "0x26b42a54252893f59e8eca923a0d2f2c0fe507a680e8907e2904702791c42aea", + "0x25fec26921bb5b6cd9657588b09813270cad72947abc6cb2726764db44181ff2", + "0xdfbd186df632b63f4cf74db660c59e658e0b4b725fe244a563c6698dd94adaf4", + "0xd1e00635e2399f6fa625f5c204e4c1643a7b619271394141433d26d902479bbe", + "0x3d3323fea45851eb0bc0b6c80a79cc0d0582abd8032aba957e719c31bb7901e6", + "0xe7d7b4c68d4f55ea8b71b43ad20bdd86402d36b6360ed0ca18082942736a7e41", + "0x1436749eca0a72b74bf8d596e3499414d412fbea0b936ee3564c4f83de907092", + "0xa828c16af52bd4adcb64928fada82a02d0a49fd3f53c5083ca9acfd998f8af1d", + "0x0fe559ad45cde755dd41876c5a65a690d32fc3d294fafeaa43e3fe133ae48da8", + "0x8f91d2082e5a1e6c1c905936515ab5f03889ac67261ef1d892fd909a9379a8ba", + "0x3881a9fe4ba6a24dcfa86351be2ca741dc9b2078409b2e7e0140569f19733505", + "0x4a3295525bfdda29bb9a552d8dc5c992649699f5694f96ff5bb0647910386db2", + "0x337389b3e800bae87fdbe5271f2167f169ffeb4710ecdcea30f08b2cefba57b1", + "0x2978e1e3c2b5dfe0b41ceb5c9c4029f42d346a2123a199c52ba6efdbf1d5fb68", + "0x8abbdb4f1f88fe8900afdfe15f3d03244435d4fb871606a689c11f6420145b45" ] }, "nodes": [ diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index 0d00478c599..1cd74d973c7 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -55,6 +55,3428 @@ "difficulty": "0x20000", "gasLimit": "0x5B8D80" }, + "hardcodedSync": { + "header": "f9023ea032ac0e3f2dcc2042b6b47cbe502d5c7dc39d27d147e3273e17fbdf7966518a69a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e4a10650e5a6d6001c38ff8e64f97016a1645ca0c97490dcc8dc3a85050fb7df999bd772c3ab40cababcf5df4ea7141a9a183353a002bc045bf48b7208ffc5764f48c35162f488bd1213c5e96b3b06c0dd3a32f24ea07041b8f6d8db9964497fcb512b3de8e71cb87d89ab7ef592caff47b444f30637b901000008000000004000000000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000200000000000020080000004000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000080000040020800000000000000000000800000000000000000000000000000000000000000000000000000008000002000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000200000001000400000000000000000000000000000010000000000000000000000010090fffffffffffffffffffffffffffffffe836ac001837a1200830a4245845ae02fd896d583010a008650617269747986312e32342e31826c698416b80bf6b841cfbb3c579ee8e631a9b2916de71778e0c4f477d1424ed65cc9ca7958899c4cab09721b8eada42b49c146c870291efe475bb8d88652810819dc03ebda2659f3f100", + "totalDifficulty": "2330161772435517944412054200548742154048251186", + "CHTs": [ + "0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac", + "0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02", + "0x7f2f84afc6caad6efe59a0fb9ff523bdd96efbb5bd22a0f67b3be8bfb8bb036a", + "0x7b7d86ae379af1c88f75a4b44d3097213b3461b9b7fd7333eac581537982dbb8", + "0x8525f5fb8149a1a64a83ec1915a78f3ce03a4a9afa4683544076f40f0ddbeb59", + "0xcc4a4b3e1bad427ad0d8b8ffd1c1c0789a08a67a09fdb0d1ffa4b1e71eb43aea", + "0xbaeb6b0b2fded26cf7f731603df0838397489bc12fdf8713a7cff865f009c5ec", + "0x3dbef76befeb39249e5c65d068fd97b8aea736714001a6dc2353b46d44f4bf35", + "0x306d007ef62b7cfed18e711d1cf449c009fbd5a8af7c9af66f3cda47678b478e", + "0x6b6038335d65726218d1d0301e12e792488a7ea879367c95263a20870ac91aa6", + "0x85ab7fde05c7cf468c4a65c5f7817e902f16038b3ce5e359490acae9c7a4f6b8", + "0x6784db2e15b6dffe0db864b2738804cf7b9804ae8932a2bb93a6bd2f2d4a8c2b", + "0x634119343bbd64c312a540e290b227adf6a84872ca9ea0fb7b3a7f5c2a4ba293", + "0x5836715c071dcaed0a79c77c12a02d54e6af55baed2c9325e10debc6fb07726b", + "0x7508b06556911cddfe4fc80e8a24603fd93cc79081759d4b7f19b2a6550757be", + "0x85de35d1995609af96aab65b1509dae77281a72932cda1e52e6af1d2c81cd46b", + "0x6575f31d4a44a479af6e4f53b7f0a5a1156c6965767b6e06cc3da8b46fbf0355", + "0x1d2ca9c1629b0e0775756536de5afef7dba628856e87dc84e5e6d16b08e12bf1", + "0x776edcae4d9a2e2a461fdf99eaeb1e717e3599f77934e058094b769c0a51f0b6", + "0x7fdbd14ca3a7408577c4e5b3b982edec1e7a95db784a34f9828ef5a30878f85b", + "0x64bdaef77b520a11c7ba92f494caade113a7682a565126cc4231d825412cee6d", + "0xc413f58e336df38771b3616ff1c9a1cbc881e4729dfa0a4bcd18dfca8e22f2d3", + "0x8da02b95474762995773eea74254861bf3eb62c099488aea97d0d271677a513a", + "0xf8d0c469352bd199cf28c997530afc31eb6b47662e1de2a1af05bcf31e6d5d00", + "0x88d9d2f7c1c44d4d0498c1f5ec21ea5d2ed2987e62f8dc6b17359b40200dfff0", + "0xe389fde4b8b06ababced10fb3756ce80b01a36751defff9ee0528accbf979b0b", + "0xb1f3785c2d15132fe17cfd455d015a01628ccf0116006d57de6425ef32bcc63e", + "0x9b2b9e6c015d85d3ba14bdf6ba6889db43cb8dd02dd020d1a01a4e7831604f03", + "0x8b22134cbd6b94ed1d17c89dc73771a3d3df57bc5c4b3d1540631c18dada7e4f", + "0x0a08bcb5fc682d91f0f95f934b4a38a71afe763b4924c8d049e407dea2bbc467", + "0x1d67c81b3c9316621088b42599abaf7e7cce42d60da44d2eafc8b904413b2c77", + "0x7bbbc5f13015a3ddfed8d3abc1d85ddd4646af588b534656256d894677c08c0c", + "0x2a442700726b19f5c82f756b08d07e9bc2777fe1557c079cce7a391684fdb59f", + "0x94a08a1519a9261f664c972e0c56b4628c3a0ab25a245abb4957cddc8a8f4754", + "0x5982827a354ee3703427518938a9b5b281249c04265db359bc47a7061f994a3c", + "0x3dd33939d000789b3ae1221b47d80ab4b8b248f79c97ea69c10148a4f8e946b6", + "0x37e5bf322012483f8e702f8a2a511b5f1225293b7c1be743cc83c637ec83c5f5", + "0xe671341e7a0275c306d55183e36b06665d2380bec4865c4c7cba51612446cef7", + "0x57ace89c46a589ca5150fc99028f9d586c4a8b1b6cf7af8b17ec1a16ebbdf8df", + "0x633ea492c2391b957bdac23f5a9428a5ce69882dc90db968e2882304bdf2b560", + "0x16aaa8ad98f3d2c127ca4dee2c9e1a36a0d4009447240e3297484d7cb2d5ce73", + "0x21abe93df9c382e5897599f54a31d3f46ce8e5e969c655c61da1125e6abe45a4", + "0xb01895100c1b028bfaeb1a126c4b4208075ec2a15fbc29a6499edbf939e7866a", + "0xd635cec21335fe1a644ec8913ea79ea987b815964ff883f00fc01c3a18c9d7a6", + "0xe5c761d35900479ea482e7804a056ca810043389f96ad208f55282e2e7617000", + "0xfa73e547f6a32b8154abe367a0138219514bd0d3fc304c742cb8b3d1eb8f70c3", + "0xf9de607cdd47e7337c815f4fbd44d983da6e38d653c3d3fbf2c6ac8d33707a63", + "0xa0d2cde0aec685c1d6cc05b21bf59817f123700e778cfe5eb80eb11add7e3dbf", + "0xaaaa3bd9f11785b477762ea0a3fcbc983c8a11b34d64475d16bc8c7d43904b9b", + "0x0031a12ba8c6e7408c7ce7987179b7534f1aea95a10aacbba0dade542ef4e1b9", + "0x101544e606fc49a7555855b72be050aa8a7a77e1e8985c3f54dec8ff3bb49a83", + "0x62202e7ed22ddc5d0cb3ccdf81770d4ed935e771be3d689c4dfd24afdb9c20e0", + "0x312cfe1c896a2624e9b2096ef5f3579b543d76ae166cb468e76a3b3b7fccaec7", + "0xcf1820f096d4b80808c50fbbf8de1b57da7b399a6f40312a293c4b5c7eb6d73f", + "0x1dde45a5e8ee62605753259a78e2c34a74cd5cf053a4c045ec5467f9e1311161", + "0x6b6ee017250b468ef3ded726892be7e8dae77c9e9e998b7e9889a34ff5da0cfd", + "0xb82bad6b19786930dd7159f35a4a24336d3f3b5b905b43f2a58165e0845b881c", + "0x77d20bc08ac7a25e115a1d23157c35c6ec22afd89948daba7ebd4809c3b95a2d", + "0xbe24e34aeb20602c184302bb10ac1f424226a985741f34faba4f346d8937e737", + "0x505e5b92245ecfde4a870197f7ece1ad181b6e8be4efce08763a37947122f4ce", + "0x6aeb3807dfe7a6db67278b5b6b6ee9ebb8996034c5ec82b3446a8c2efd3588fb", + "0x495f38afce7862a6614ed3d35531994e8d1e81dede4a4c9702922a3c06084e20", + "0x4acef831186426af96b90e1007561bffe2e8074bb33955dc36cdffb85e61174b", + "0xb2d7638804d6ee3e0747a4de335a26506898cdfd9221fe7e7e464feb268136b1", + "0x1aaa327ed400e0f6780fbaf818fc1f69c6cf407ecf80aa4f769ce42bffed7cdc", + "0xb955281446f41ea2330d07603803e148d5f1a2519f6233cad87dfd1ce4985259", + "0xec5f0c5f001e7897464a5570543060957fe20f88a905d3769615355c240e4859", + "0x18f872e3796787ef015a99bb3bc5ee4d31eeeec260213da70bd452f64de14c6b", + "0x9df2268daa9354a8264b5e7428d390a8d813266188df966fd58549dbb66898bf", + "0x6fdf62c4c161997e854846ed44e2096ea948c40efcdba2479896ba87fe484138", + "0x206bf3386af35a010906ea7a5263a71fa47fd317d23b57e448e49a36082916ff", + "0x4f627219247a8a93fbaa32b7f95e84b45146752d245e54299e7f74ca7070b2a8", + "0x3235819426f3a8b7affa6b38c0627c8efe0c2abd1eac7f8d6545e4332ebbf4f7", + "0xb5e514ee180f781ffadbfacc1831926f24cb305c352bb76ed7ae0a8247e792cf", + "0x6f287758e18c7967a5d52c05f8458e2d3ab2ec86fe0ef1d3146b99d7c3e3f5b7", + "0xc17dee632a1da285bc78d6c83715810e0e003c65c61c4105899b440487bfd126", + "0x173bab1413b65b801e136fe2dbf335b7d1f8689a127eb549bcd24f55b0bfd979", + "0x7e85be26cca16f2f34468f1aadd30a4766e4fe9d3746455f301f7f6e1baedc6e", + "0x85a0a9be1ab79a754c8875688b19a12719087e09d4cbe03f29965bbffee8437c", + "0x9c1c826a39e48b1b8d9d88ed29ca2d1864425d28e273695e35168eb01179ee62", + "0xf88831327094e7ec631fb9cf42719f89c4bceefbf25130784f09f4fa0a3b0a05", + "0x813e01a9713693c11c2781ac98604e51d7c7f610effdac795f74d538f7e5ec89", + "0x35ad80a70b0086c0a762ec29c577b031ea85132f777a324410c3870128aa91b3", + "0x6db9c2349d95bd51dfcb499ff26e90bf73e999f25b693ffa232c573f67164104", + "0xcff82a9fddf588d3d40e642f1eba1b9d24ece27131104e2e3995d6643e8afbf7", + "0xc6bffabb187ad144e33e7e3867f94f754e7e479c503d03de4fa891d294b175e6", + "0xd360ab92cf13a519f5bb41ea825e9baac0bfdf2298220c5ea60304ee9ac15617", + "0x8920024d447d0635cbe88f642966da52c1ef74d3ddc6c1c2df1df80c0a0014a0", + "0xc64a9294f5ca5fd1e1e05403e625222568c32bfd2f2f95bed2ad532b4c3a33f7", + "0x258ec76b8532f1f5169b44d8f5e0c1ddfc19fafab4cfce7c6afddc8aa4978cab", + "0x47f2aac68456bc931a0a8c458b802651173b1ebda2e032fb9541139352148156", + "0xa87a36800ed7e27bbee7ad937c1ace3ae08e2ae50a6673af70a2ec6e44ef1ec5", + "0x9182c6debf58629bd0d37043cc70b3c5e4af18b8aaa23cc5b455f009d1686371", + "0x0fe5abb9ff345ca06fa55cdfaa0804a6523c3ae162638e95edee4ba092eec443", + "0x24d7d4eb0c17869860d83e8be8f7579212cab60655aea5fcf070cd1461191357", + "0xf0971d8a37bc9b6a54d37ac7cd90aa4766cfe78cf8a6f376dac2304cea05683d", + "0xdb3e2e62d2da694788d2a0aecb2226c01de2b9d655421a079e2bb34092e7fd8b", + "0x57100a2ff274daa465da031c86f9b282fa03724c93823399c08d6b014054d207", + "0xc81fd4efe86a9ad97415928ae213959f2a716361da4a2937ceaab7358f105382", + "0x5836a5c844e45ae687b388603d62d28d81cc98ee1eeea6a34dad79d7ea6a599c", + "0xc98ad6c12f3f371a69eccb37407b43d3185b68380dcefae448b2e43db41afeaa", + "0x33ea1db64fad9787532d20f7739dd53a35fa810db902f2c33dfec4d652921073", + "0x3219209ffb0a9c5ae33779564dbf8a9618fabd1c0830d32a06dfd5a3990f7dad", + "0xeb6a367ee7f10c5d2882d86850f4a2680f78ce9374b7218d7cff11f0b01ff336", + "0x026bb678fb224a4e62c0d31450cf5394f4f71b9519106a5e92d58464edfaf63f", + "0x040ae0a25cc2c70fa710d394be7212b81128d7593a5c210549a96bf391a2f58d", + "0xa32caa1d1b36281e2c917f1951b3b0a0acde7c78f775681dd09c7cb81a2f14be", + "0xfe532be3ae441c5e9ec98fa0e006fe8529dad0ae6ba384300eb2198841014391", + "0x49d3b4aa6742d68b59eea7b44aaeb0693670c7b3b43788e93cd99f10d7ddbb7c", + "0xb205da5396369be6b68fa19264df3326c2bc825d88814843ac4f654cc7f921a7", + "0x57521341b29c1ed0cb02e8a64c43155e6020c4d8cda103ff56b2d2bb0cacc749", + "0xbbfc055f310e3930447bd33092081917d7661056ded31d3828b9a4eaff3649ce", + "0x52fefff36b4a0a9c2ce8cda94cb792a8260507df759ae2348ce79a6df3a2aa17", + "0xc4a7420741c5e8e041b8c7765b5c48ab0ee01fdf780efc95f820fbf549e5331e", + "0xbf90dab5cfd58fe4899475a911afd460ed0bed6e79487d9739399f7749520642", + "0x1f27056f98106e007efed121b017e82fd5c9b2c05de65cfb28fa9f67edaa6eee", + "0x6ebc2d4f7bc27d116b499dcbbaef72f8dd053559dce743706ecae5ce5338b508", + "0xdc6eb02678ccd7b2db8a9a9272ee53fc8110415ae5e84fbb8bf981eb25ccda51", + "0x3e261edddd8d34ba379cf163dab618aabfc198ce81bcdb1484b71a5bc4b50fc5", + "0x128bdd0f27a6d741399010b26f4056f0a919e7c1bdebb1bb69f22d32c80a2b88", + "0x68a749488b6e5bbeef10c98b678f67d1a7e53fb62bf502dc3743bf3c9138247a", + "0x52dc462248ddfead4b4aa85f4b2179280799b902519e83f721a849cc2f2b6037", + "0x7d70e4fab02e6a462e4688e96f7fc56a4fb9a945da942925ae039c6f13907c29", + "0xc746bf3861b3b63bd15b3cf0f0b6c0c331da578c35705176b90dee8a5b1e0d6c", + "0x4e251d7c4b2ae114b2f11a532fa060f6f7b1c4f0bc760034fe4e69c053a43746", + "0xe67185a040a731762897ac2e07ec2b955644d0784d18c6351c805d28e83f776b", + "0xa8ed7fd02d1dca89683183877cdc2a4c9985b48141d7967b10b38b59b831cc6f", + "0xc1020b2e8587f3c967ea138ea755437d2660e69abe8caa0d9bf9da9201b50750", + "0xd789a8a4a025f5725759e359859f2e15f7901a077d7683e3572d9ddba15ae94c", + "0x54f4372c804a66eb887614df08364d0e6b1f10c090584619c89c43962f513eda", + "0x3aa00d2431ba1c4c03452536047bdad3a5af547d2e16baad0bfeea0e7a8c3722", + "0xb341d41f92def7f5bf2d7c9a39b9fcdb2892b95a63ffd7b643bffaa523783dbf", + "0x9796b217efb64cc5f829a668989bb1915206e016c9714325f068b8cb2cd303c7", + "0x5deef3457cc95fae69c47f35422ca8731c80da50fd7f664583d13bb44d2f9ac4", + "0xa381a97eb8cf01a9b162666aaf9dd3142c6b2a2247830faf693e894ce99809de", + "0x7418829d2890fc2514b6e4da7b5643af269016ce2dd31d1aa7333c66c1273a6b", + "0x65466713071b4b5abe6a9c9b0e9fab247d56d72fea481e96b65999e2a085de95", + "0x0f97a6523532b4b80a7b54c1850ac2b062ff99d0c7848457fc3465d0d60623dd", + "0xdd1826c79f92c089522f853f87b551104b8b173f1c1797a752f2e8da2fd506f0", + "0x86a635a38b956903ce95ed3af65257383e2d7d86e6b63a61deec3ea5c8acc081", + "0x4afbdcdbe4a647f1137d417ac3580a116022c87cd6e7511330c4f2494cd90a0e", + "0x1d179aa8b0cb3b27844da4f06734f199fca43b66319cd2f16a60722eda994121", + "0xb1f1e42972a0b99268f42f6149452019259565cfeecc3459a58c17ba69ec4ad1", + "0xb80f8b8bee43d9e98eba909691ed6c9e900e8757326f7d20b6e7ba741d404a4a", + "0xadfea6390b526ec42aec881cf8226b9ad94f28ca1e682237914b30564d887208", + "0x50619f2ddec37c184798dfe50b067ae4bc0401bcfc1ab4d42cc19627b7b183a6", + "0xa53a92d3d223652e6572a48ad7624aeb2bb24c10872d17ebefd41ead1579edb7", + "0xeef7725747b978d578e5b576bc18d5c6e7148b68c2389478e0102b7656e7f3e6", + "0xbda668b4961ca5f6951f6ac55ca3c03a66e475e21905dfa8e797cd4a5ef1381e", + "0xba8c3be48f94186114afaab72a27a21db0316856619b400645469511b2bcc165", + "0x44d80fc17e0d131e6e98a4567885cdfa5224aeba8616d8f369cc84f3b85566e1", + "0xdce65f6c57bb81f01fe80daa1c6869c890a4bdfaf0f016456098bbd13c376f72", + "0x0b63a4585671669622a3c751d5ff5433f07cb0e9f4dc0acd9dff493c6ed01495", + "0xa287abbc612e2d318488a370e792845ff01ba5f7d387a2f0d82c21fc3d236992", + "0xae83dd70c6cc9cbd2a418397401461687bfeb8fa6d606fb7105153e50b5dfce0", + "0x02e31ae89b0dd8f66b6590a1f65711145bb9154825b7c68ae5d76228d92f016b", + "0x1e38ed1613141cd046a2449540f1450ffdca2c1a8d9ec2f1ce8d9c74ee189d89", + "0xc8f4747dc7b311c1a234f7d7eff3e9000e11c38624c23519b889543d8d33dfb3", + "0xbb7aa989e7d116e3c288ed8fdc0c7884fb3c6183ced8a0ea63a9de037ebf49ee", + "0x88d5a00fda80c28fa6e6d0bf6a6891b492cd6c85526955cfdfbba2428c9353c0", + "0xab03bd8ecad4f1afd0ee84a2caee745d4b7ade0f32bfbd61db50be15688e4493", + "0xb9ee61e8ab9ad32da0728394b5ec53452014f6fd99a5409923cf75c8d739da5d", + "0xa4c357be81081b833b5d4fd3cf4644b2ef1a28fdf67a8e0b0b2af3e8cd6ade4e", + "0xfb56d0c3b65882317ba962e2953a75d9d9b43c9f40ea0894629dc09bb29f6712", + "0x0f354b29bf19612285957523fc7d487922795d8fe5fb0aa4019b94a1f13d89d7", + "0x61c6ec536ebec0a740ad39900a2a71cfae8e8ff81ce3a37c5a4354ae48d39ada", + "0x769d94d0b3fcdcf22eb6c36a7c5b18711c79f69c27e9a396476d03e92ab0d058", + "0x5009c84cc24149c0134790682e0a9bc88fa5a8d2bd650207309002c25bc345a4", + "0x32b697d3cf2ab3bfb9ef79d27f3e61eb423ec9d802f2256b1d8875df78ca5887", + "0x3b8ba94c607acdcaaa7f0f7ad30028ecaf4d505d0675df95c358607210a23eae", + "0x433ea023715de94c5885d16762c0caf40079f5377f3cf3f5ee871c6812182ebe", + "0x4758426d43b67ad4d6e7a36272a3d772b94dc497d45292b061ac655111c41240", + "0x12542964fe7e8c837cd8e20a0f80de473127bab6aecfcc5be266bc7bcee87ccf", + "0xbe7362114d69220ba08ce42396e92d87027a63c3287be0fcf633c8a2853b8c71", + "0x722e26ddb7fbcff7dec266ac0ca388353c3a34d8ee23bbaef579b7acda48241a", + "0x04ede2fbedd140490e0b215e89850b8bccb059cfd7a72bd2fc3118495aa4e811", + "0xf47ea26f501cc95c62c4da4c57e743bb20c4caf6e81b394ceea58bc64b1a77a6", + "0x6f208393c290c02f4a505a6e7b2420da859e7ee83583e9a41d709333e67dcf9f", + "0xbedadad9293e12d706c963f31fc06535dd23432f7b27d157e529cf73e4f5603a", + "0xbc3572c828c9c1d1f0c90f56bcee1fe414a413fdbb7362a416bf4033405276ee", + "0x084bdee3faf8a9e45990094d668f6ae0050c1427e3aa918223849357f7865633", + "0xec5a32f5ff6f3887e5aa33d6dd61d2d63e36520ff0647a9eff2355a7311a0fe5", + "0x13fd23c260c0298286e193f23295b67497fb00c60047017bc62f94f6a25d4574", + "0xda66b3d4773530c3a3b563a8721523dd10f4b598b3976aa2f3becbc15fdda495", + "0xfa981ea461800e9eedd73c1423291c69bb43555321e1c5710a052a12bdc68707", + "0x232b0ab7709616262fb48d32ff36284ceb5dafc823ff4f6d5b79e8ed12c7040a", + "0xd90bc0dc26f812e0f05433c30fd8e19e81a81ac589c49a528e86027e8a352e78", + "0x3666c6eaef02990c263e0611e90d793c82815bc0032c2ae16813e957659c6412", + "0x5b46e134edbbc9466540878a637ce22194f040f519efd98a52da8e9bff05595b", + "0x4bff68f29ddbf33950af965ccc3fad46c81b6e2371922abf27b88fb2d669b83e", + "0x67dbb166d4afd3d1c32b9ce9ed5da75a25eaa160f90baf0d46a74fb7ddb09dd2", + "0xdba720e169d3c1dfde88d08bdf445eb428908560a520ccaa1da84d2dc07369b7", + "0xeee7477387db069e7de5d10a8e77d7f3ac7d692b4d582b5256bac44ba3d8381e", + "0x968ffed5244efe79aa4dbe1bcc7a05e24b5e50d1fd4d92117e1b654707bd3c43", + "0xcff2abc22b0cb5865f9767b5f6fa4b1420e3b774ff4de6f593516db3511d9fe6", + "0xd710ff4e765bd0d5e2284c8a11726c4924b6ba159702214a6016555110c2a251", + "0x31523dcadfbc24f1d3011cc1cff03a4df5f2c10fc4bef7cf0bb807edd1c97520", + "0x079cf6974e4e64675de7ce75b1262e2fed194440c2789f6fd72110f105503754", + "0xb121c3ac31a421442faf07a4b553de22be8e1726a67b0feaa4d426e5b48930c5", + "0xc39a8aa81b5c0a95d0037e20f3043e16832cd4b4cfa78e59a424493cd8322754", + "0xcb30c5710457eb0d9ece9274fcf01a96758e6e48db64093b1a08f773f5bdd594", + "0x916203fb9c6cb117f46f66a6693501711481691c0bef0ba0563369841762c657", + "0xf6711b05e901583fe0b51177597d44354ce57364282e042e143f37185af0b13e", + "0x3f22f516c9fb33c327d2184b842edc2535dd6cf4969178c56ab98ac11996ea46", + "0xd51b6361e37ceb481bc6e37eb61432fdfe23d52f2b64aea70c0a12a3c79d2784", + "0x9a1e99c578e7f7a69b7d914c0f748b3f94b6b30bae1be056849bfecc74e31751", + "0x5539c971cb882506860bf724b3f3d05cc399af4640775ed805288468dd83cfd7", + "0xc54c50d46acb1fbe017364ebcb66b4563bc0ab60753b055a19b126a55c476bc7", + "0x3adb55f5b09858cb849ec9edc3adf5e3ffb8eac43434c1ccb817038610b57c08", + "0x5fa06980ab83374613079b9d61c53d6ba93d41af996f5d9fb5e5ef05d36d8aae", + "0x1b66a155b1ebb780d501ac9f6d14f8ce6c644af88b7f86f87b5815379258c494", + "0xb75860039c1886823bd489d9f3b92c4f6bc46629d3fedc9f7d6fde59a318518d", + "0xaffab6d2682c1641658270a5b63e9e46b0bb90c05eeded11079b8f7d33899983", + "0xb5aede6209f50349dcbdaf85ff444e2252bd3e8e2faac12b517552b493ce4cde", + "0xa7c3e97ca8efbde3c829f2e363c5aabde3afe2fde9a1d106f868e87c0fc0682f", + "0x84f7405932b9aabbda33ac93170ffb73ccd5c584f0f55c17af4cd66fc938f739", + "0x7eb2a3d7ef2dd3fc0fc337070f1429e9b472a5912f9217ce4777bbdd07911034", + "0xb208f1088e65776f684d8b097b847c98cee4e274d49b07918e4ebae9585c443e", + "0xe0cec73204567174e0594f4082d01d7b8e8d382a6602e40b35b3197ba2eead6b", + "0x06642dd13587031239255686a40625c53358c4ced6eab78c696413f3cad9c6d8", + "0xb91a9a676da327548f5ed89ca74608c9403b994ed8f0cefeb53a1b5b09e76da5", + "0xe7dec1d92e8d551a54e7e310ca217933375c3a3944371ad5975d1601d5c6d0ac", + "0xee0d0b46a607e2b7df37f24ee652dde4ff65c95eb94b93092452a56f6ef9c754", + "0x8ef8f5852fd8e1f96f82cd3f4bdc716824070b3eaccbc2cca5da345298b752e4", + "0xe801666d13de5a51eba7c9e1d149339023b1b56c513bcba2e37dcf22bdb261a2", + "0x37a53559f626a819de48d74f7e6b484ec90c1fac766adfe08bf9234a139b0fec", + "0xeb8d703867e169bb31f5390ec877a7c6c82aab53f144593b75fc1599604d6c80", + "0xfed3012f3f281de26b447003799eca69e9845c6b5be85bc42670a64487c92a3f", + "0xf70358dc2c4e9d449727affd9cf45ddefa0f3480d964f85aaeb1543427e062a5", + "0x6491b2c05e217b7f21094e96c3381164f9db86c480b0970a27d8e25c875f5b7a", + "0xb4561f6329dd718c03d7ef6be0224612d776b72511294d29b293eb2e0a7b5cad", + "0x89f4a1b613ee34e1728899eeb294c48a21c28da7035d5d036cc46439fa42c965", + "0xe78f95f15c015a18e4598e33f06f6517c4455cbd2efd0dec1bead6080f050b35", + "0x7c64eb0c96598f099d0e9383eeabdc303002819b35223f744bf8a2bb80cbe394", + "0x98e5b4eaf42e390156a730d9e80606d80e2c0c9203e5511af1cea5361af63165", + "0xa481b0af82146b7aeb690456acab564fe356b2b8a560c4b5ab46817167bbed33", + "0xddac876def8620f40cc43a04c8d939fa12bb6d985223caf955e8174c46578bab", + "0x10a97a5a30805c28828d6e4eb4205905845d121149b7146e7373cdad4850ac88", + "0xe14ce88a794100c126707edb5a99922d394e004ce5fe178fbd02c8a34202d4b4", + "0xc3f18b1d11de7706063e2aeee7159589f64539fee39db233ce6983b24ffff076", + "0x6ae533d2bf3f35c6f1f256b9d1fdd863d5394956ded7a80b56ab1e12da78c93c", + "0x79ec4573d7df2f3b48ea706582d48d29a8d1483ae29577fd85b11c346a22e3a9", + "0x263652485fc477fc5407ca079eb494d4618943d01ffbc27ba3824fbc34e6bd63", + "0xcd414c2dfd20a303c9fd623d847e0387cb93cff53d006f335358894be35ac0b3", + "0x75d23d879b23aca1f2152147212506b0cc789c3e15fa8644a6c89a10ac926336", + "0xe166233fed0bfa647b84b95b4a04553087b4f42784334f5017dfd2a8e246f0d5", + "0xc48f212eef40b227aa429405e6c63d25fb35e9889a33007fd1afcc2bbb57a8df", + "0xfe6e67fe4057baa0701a7bc7f98f1b59e8c0ef03401e564d51b9fbbb49a5d11c", + "0xc31d73c0443dad07f6eaffa3171c77c8da87c54780d4f374128adb79fee4ed54", + "0xa0ea13b2425ec84fea7bb9f121f0aa72cfb00e36019e63fee991606246569281", + "0xce7e8e4515b0ebfcdd0afdb002f9017076de88e278b914c902bafca65a8b12fb", + "0xd14a72a5605124a8545dfc4d7419f00e85083d558fc662dc17b3bb289107da83", + "0x3e89c3740c294a0f54068cf769091b1a976fe4e60ab4fa48b9c38c034c08e9a8", + "0x2ee8355965ba13e91d71bde2a72347709c97cc33bcaf1ecc6952c860b07c60c4", + "0x63a87a93a0e410e53146a60a46ca870604f8301e221fb5b470402aa2dd5b9c54", + "0x0bbdfc34316855dfa828a58923acd7ebc556c88a43b655d32bd46ec6008d8351", + "0x4721db737d99128133928670bd229a0a7fd2889e00e222378fe5f663e35587f5", + "0x4f52db42c0f03f342883d78d387ec913a65f92961276b0e718d4b5fa268aaadf", + "0xf7d28588843f736c341b8572322d1ab397e0c5863ac9a30facec3eae0126f3b8", + "0x48940fceeebf3fca0496483b58228516b9c54404fddd31e573c951b12d017d2e", + "0x87542780e6dad24843883c420ef6fbcb2ebea31b073fe54cbdbd5ffb2c4b30e2", + "0x35bb6ee5defc7d7489b24e9e8659b7131ab9f7673960f3ab9bc9324d6034f3da", + "0x11719cf1a1d10bc3c4a48ab177ad65039ff09d1dbb34b1b7c15fa78b5506b5ce", + "0xd086c0fa8b0a1f7cabd9bcc5a1e36137f59b7ed6d91057defc6f62fbbce73956", + "0xeb461e410c324c9ef9a0d240fc5f153e1af9e88810f1563767022723bbac62bf", + "0x10a384a0f6c927bc9efc21ae1b2988e79268de24065b91065b582aff4e0cbcb2", + "0x7020503d8d86fe9bce39301207283c9f9bea9d7789d0f1488506a4073d482d6d", + "0x93657d3b8bd95e33b9b13c3a4130a623d4ed6d8eca8cfde3e6fc9e16b3f1f898", + "0x40727606bcdee8714dc15b349561d8b7d293ca4231227384c56f1a8fab986041", + "0x5ba216663e223675ed7da19a7bbcb08483f6871cf11d911c3ba992829e40ce2d", + "0xe9eabb151a2d735f0ca36ac9ed65c612276a21e28b1a63b5fe632dba27207969", + "0xed88ead1835a70d30368a33955de7c4736bbdc22ba95f04aff7097589887b2bc", + "0xca47f392632e4684e54fd50f5cb8e6983c8c2085d4df8550e3398c4e2bfb9bb7", + "0xeb8699fcad43fac0bb54ab553c4f29c7d1a3ea6079e9d5218a14b675477576d8", + "0x912ab118b513c06e618f29f9a7273e8035b4723b3a21521a91a43100486759d1", + "0xc89d31d9d5bf2fcdcfbf8ba8c61307656bb5673474ea605d1e5d70ab1d7ba43a", + "0x8fbcad4bb94b91cec5d9ac2534666f019c807f8889d37e3107fba28002c7dd1c", + "0x3f606a227cd3a38e2d5da4c611b9069c109e9c291d390e5c1bb3b427be68c5d7", + "0xa69c47f146ba22a6f53562f4ec3d13e1cc5499db587095dadb4a89f6456be664", + "0x36a9e5d14b3fbc061dc83eccc0e6dc3f2a56f0a56e88a987f09d89257c2d2ccd", + "0x9d77184cdeaec05bdde7df7005467af592a625bb0a470e5b071d6cc6537a24b8", + "0x3f9634b50a524ff350dbd4e764d3c01d848b44400485f792d4ce4e17a3afed80", + "0x142e648622d2f13dbfa4c0e58f91ec0073455a6b327a2a2273fef05ca9fa7553", + "0xa4348c80308a3e0b0b4d290152bd09b24d2420281ff3240d2b54c406ba2ac003", + "0x95e86927eca33fadf4d35feb4514ecb90babbcf2ab5c801533a4d36ea8ccc87a", + "0xbefc0239b823cfca21afc0f57c144226a8a72f6acf86a1152d8a80ccb27475e1", + "0x1bdc16bd7d21c2cf818f4d3f5f1cab4a7d256ebb8b32a8464c6b6ca111c9ab87", + "0x04aa15ecdc0277166a77953b4596e2558af4295a342330ecf9d21b6221f21a40", + "0xb432d2660f59648ef7929901a0ce38ff577b4162a69ec92609c8ca1cbea5f8e1", + "0x985a13bc2bafb56e5ffd1b0e582790eff30786bbacc6e28ca57017d398f1552a", + "0x57c5399f6606f02bd06c9470246948e3d482ff9dec5de270f6c06dcc49c8c8dd", + "0xee471268956c3947f22dc8a6077c850f10c1227f50cd24ab7a059b94f3496274", + "0x97cc4534898ab427418bad275c9c21c18d6f51cead840bd5b800e27e1bb1f76f", + "0x1370774538f3c6aff104060091a573c94269421e5347d9ee26c9c5ec90956174", + "0x7b29a2dc9f4e8c3d43d3ec93d01484205583cfc6c8fac71ed0dd6eeab3c7e987", + "0x2127f737690dac5f24595b5d0b96e869f750b732fd8f004860b5510376b154a7", + "0x196f4545946a3a4b9d5a1c2ce3813e55245cefcbbe424eb50dc7126a6f7ce294", + "0x89a6c2dd239f741797b47166d4a97d8a6147b26c7f61471a272035fa6a19ca04", + "0xd4cec04b0a1a8a2240cd2745e53e55dd560c3da0bef625e3472a03c60e5e1346", + "0x482aa6954d7bfb528abdd0d2a44ca7256adc9d2b5c885f67af0424add0f85039", + "0x16d73722fc18c4c5fe53ec609695dab204ea3a0ac8d52356acc56377495dc715", + "0xa2fc87f2deaf252bc56f50d67e5ea24cdd23fc3a0931c69e5c7f832c57e6cf5c", + "0x95702d0ce28a00a2c52cac13db300b535e6be5aab6f1acd8f7f8f3664d8f1942", + "0xd7423e6ac1d49688437234bfcaff2f8075a6237b35b719084c6f9257d6b095ea", + "0xc1efed370db76aa0e6e31680e91ae03788ffb343c13700ed30012102a727ab05", + "0xad108c165dfc00e6db95fe8fb28a51a21f471d16093f761af92dc3c1a76cde18", + "0x579ff43e25ed4183ab6638a5b3b8ca5ee06343b410a47abecb154fa98fa701db", + "0x58446a3cb729e43ef984f52bd3a1c0c5bc2986b355993dc04826987c9a4c2b0d", + "0x916b6e17ed534b2ed79c4139250ced98cf81a39ce19092ca7593b8046b010fe9", + "0x5a85afb15b437acc1958c1a35beb35ea25a4e4bb2856fe82f4d2c257ad92e4ec", + "0x74f15f12f6acbbc1ebe68f82e5832c2581660451eecec1d2369ca842c0384927", + "0xe3724b93bfba09e69c4d3991f5bb7560dfa58f264a2ecefc1fae2a933fd81c75", + "0x4651a72f64ecfaa2b51804f6c02f0e341d43163b408786df50569668d6b1afc5", + "0xd67008562a459791d2de81c71369507475fc3727fb46f68ded3bdf313ae3dbaf", + "0xcfd841df8cc01abfdb09b47afd98caaaba19b900c7d4249eac819f24ef7ae98b", + "0xedb8f1bb736b4b16985f41b97209730b6f99d981fe3ca0c614d138cc9f3651e6", + "0xf03d65be04a3b5011007b48aa3eeae54b39166013f8f0977fe185036a2302360", + "0xdbc7e5449a0af2b69668ef3f860dbaf2b0e0053eb5f96bd5879f59d1535aac78", + "0x44e3d860cf489a017a5a0c99b7fe2facf87c7bbe8c641bc2ac020bd45ae278f3", + "0x8f2d4fb90e6fb5d1465e5e5368b36d44d2081842b2c3b1ac3c2789cc8e2061e7", + "0xb47a9bfac379a6414b66c2b79ced91d87f130b0c2f86c67ca5295fa656547b24", + "0x8975e42bd19f5ff5a6336f835a53e0e7d8ec1288b9f59c266e1da463fff8f24e", + "0x52a573f0165af4f0a8bbd90c8ec2539ff430ae8bb9818c2cbc2c91f82ec056df", + "0xba647605f77311d053ff9c76ac71e88b6d1dd6b4dd5296eb0b7fe3e07eb43880", + "0x1c6d4757e48f80ac0a247bc7b2649239d0284b2580248a8b6706f04ff47c1f1c", + "0xfe42314e663a9196f7bc6b795bdf2763f49467c9b2183eb02c25b5c79e20fc44", + "0x15b6054f899df7793f03ab925c1d8df2f94d6221552b890af6de5d8a5b7948f5", + "0x694798b4238b93838948377161ef5165af4dfbda5f0f9d8d2d37c083c3718393", + "0x58724b920890120f1f90ce8bc3e9c6639042b3cfa78123bc9917b8854315e31e", + "0x21f057c8e538eee76a95659618bccefab9a7a5ffc955781141a3eef71f3b3423", + "0xa5fec657cc7ab1b633023791470bb2c5a7f1dbfb3ccc4e6442565a791754f319", + "0x67a17493b80cf75ab905ccee157746c7ed048a8406fdd94af1c6916cfcb29220", + "0x9d5132754a73e0ba316da2f824f5264e851526c6a75bccd153cd41f232e1ba42", + "0xe9f6b8e973183e7b89ab72479003bcf07cd0d141521c23e4e4269f58f51692ad", + "0xe52cf37c47ddd837146288364ba448980c24dda74c6a2560a99ece3174c94a57", + "0xefb69d2b602cd8b073314ae5af7d6200d23335f1e46980c205ba0bdd979d0ec1", + "0x3e2f6e13459a82666bfc366941b39506d84b1b6a1c94e4361d51d30cc1bf4218", + "0xac8562bd8210325b1dcc8cc3c4214a97d04ce795c3fd9049c7296f0d855045a8", + "0x22b62db26899a50ef8630a9aac5cef645512355901ba14e8f1a3468610473756", + "0x24f7a40ba3243eed13a4c2ad7fb273a1fd822a3d2b8ec729b0e5184c3f791e76", + "0x1ea72f2b13fbc945e3ca51bd681b2e12e4ead38f42622ac3be54a1b89c826baf", + "0x95b26a476c67aa211235b0b177964422d037768a1c162526a53e73b2777b85ed", + "0x1ed2cbd748843651a8ab0a31b256d4d3c6bdf3cbd3db7e73090a679756880a6f", + "0x20e857d94a0038a51313c8a67d30f7aed8b335e7cebdffe8795ee03e62e5443f", + "0x9b807ff518a22a7a40521537b137cc25904b8d2607d7d9ce1f0e50f2327801b3", + "0x35e573f1dc47520f16eb43240dcddb95d167eb8e59430c608f17303a9c86b639", + "0xa06a21571951ec87f6cba9dec2cc9f1e55b4b4d5d3e2e9415d30fbe50370af12", + "0x7961da55526e7a67feeac00e625a1ca93607b7bc4d4d68142ba791e46d333e78", + "0x5accacce3901feda7004414e0d514129bcbb14ea727f34f58fddf4b928774589", + "0x0d66a4004a235178a69941894ccadc2e91a843c849284db82e90a088c3d3c6bc", + "0x8255a1650988cee8c57e30a5a8fa159f71fc2f3e23f799e11f5bb31b09c54667", + "0x7d6936163556f21f56185718a6b7de5bec0375a01f4c88467820d8c66dd983db", + "0x3e3c08ff6cd5f69aa8f85e9a5d8c91462cc228a41e392b7a544e2efb6af87cd8", + "0x4f401bca18b8cfab219430fd6807aff86867ea52f12b45ec224fa9dc318dd789", + "0xe14e32f37af0204cc56fb10ae891cb09b0c27a116ad42b5946dd1815f445cfe2", + "0xae46c70ae8bd612e760b614689d48b34358bf504a2414b660224312622917e4a", + "0xe8870fb901d8234646d87be0eb0b15d46f55c8d3765beb631dbd06da88d50038", + "0x997b7b18cccdd31b611bc01767a3be138f5ffb2c92de11aa1fa486a578c94799", + "0xecc5dea6b6e3d233f7caaf17e07a5f58febf9fa6d0736228da43b28cb5538dc0", + "0xb56b9b982a7915d85fef49df531e0a1e8e8d000b30da66104265eaa7317ee2cd", + "0x09601975476271e885e83f96799f15cfa6c0a67037b9d31eebf01cf510fdd752", + "0xab2e7c3c19f0d7aad30ff986e9b2c8a56f09906b851c53455af4d35d61b20a32", + "0xe5590d245bcc42d8efe40d677c42d840da1b32c49369bf352f46690bed9a4dfc", + "0xb46810ae0d11af6412e219bb99be0ac22c033433b1567a36a69cd962c9456d41", + "0xc296086ad6481ed8954c5542e4083388a4048132a952f500b2c362a19e8333c8", + "0xc39bf0d7e42ecfe35ab387932eb54ce0c1e502168ba5aa74b838aa17ec294d27", + "0x1ea48989819dcdf6aa0e9b0cc41d52a4d348fa80c8aaadb24091c517e3fd203b", + "0x58974a726103f506b2d8c904a8b942e247ca648678b7b98e484c203e4bf03ae8", + "0x0ccee08094a04e4db707f8d570c6098cb87b271a2aeeed08e0f589d2c162afa2", + "0x5a8620a1f85f856a8cfc105a05d4a935cfe626de46eac68e2c78c7b8fbb08c31", + "0x070101ef142836edb475e9e5bddfc821fbac8b2f8605ad9f52a1ae00bd0d1f6a", + "0x822efecd485d634912a4fdad41d72479c31b7cfaf664f3a0f78dc9ebb624cede", + "0xc6c7f14ff1b5618cfa096080c6fa59d301b3c2f516ed9f4eb0c3acdcac3e1ee2", + "0xbe85e53c24900f6d22564f33f05f1250c9f80b1b4616c0dcbb6f500f22d376b5", + "0xa84385d0d3f54995864695c96c5fdd30affe8dd9548b754edd12d80802706ef4", + "0xe12c3324e68b4efbb14fa5522ef6d2418ef7c397f390c2b91e30352ffb538c48", + "0x06cafdf319f45ac908dccc5e510b67be82635a488234d9b3fd016dd2f09667d3", + "0x236822c1c20ce528a5d9a985c2a2eaf8349a3ff1dc13cb7f9a8c7bb5bc39e9de", + "0xc438b7d70a69768bb81ab867d6772133a592f7cf770931eb51e893c106461143", + "0xa49a416419f910f762ea095d4e8eddaaa7b01b406e730d3bc1846d24b6952302", + "0x08c83875d8ad54befb643c8d8dc684358aa22c144b9448820c0a62e5ceb9e9a0", + "0xd81a30c959e06eeeab28bc3b95a1c8a3466f2552d51ec0bde69a1d1f107f5405", + "0x76803ab074a7170033dbcc33a68d2b497998dfde8b9ff86101fd54539d1bd393", + "0xf7b9503ce1753623091cd263ff23af68851445bdf97c166358b890ff9dc78f17", + "0xbef1f09e8233542c73ea380abf0115279469e2bbe3abd557b89d12b514bc7a7f", + "0x8ef2348cff8d0d40e6f1b0973636915adb3ca63fec663383b8afac1a46dd0e8b", + "0x9724f0ce677572033e30756e4fd356680bc64d171acf7483d5dfc936267d3d8d", + "0xe5fe7147af6d1d1d52d34714de41a7cf7bedf38bff1a29a25263beab0f59fe61", + "0x3782ed2e5a049f3d877c8480b590a5d2055918c17804fad7ee7a6c2a4358bdc6", + "0x9bb40bd9cbb5d20c8987aa4e75b0a8036d0d10d87c46abee889d5fc23d10c98a", + "0x75d9d23fb96bde45550b2cb8ae4759ad36fbcbed51f00cf1bd1d04d0f5d0400f", + "0x5a5f79793464475b35bd7fc427a745b76541ab65d62e500d93e5357e588948ac", + "0x903e3a38194c6eb3cc98c857b98ef68bb1fc988220b12138ab40141335b2b9af", + "0x9c5c6d1fc8f1242a0f3f41e6dd9cb7c1ce6dc644b1ce552b3dc0ff7db83251f6", + "0x77b89a725a743a7b31b01022e4ffd1f35f733461828f204cc75f4f00290a01ba", + "0xabc38d580c92f199cc0aece60899fb6967ca48a096b98991dd757ed1fba6c36f", + "0x61742ed64d417b66d67e4638d0bb60d95f88cca17cb7630b1254ac3c47739df5", + "0x47f7bdedee6e8eec229eb0f66fad208a8a05450c8b649e2dc400e1b5759f4b1e", + "0xdeea16c07180d8a4eb104e309343225a354a3adfbf1b8af733456a185f3ca669", + "0x6df5b47f5b11511f42b4e981d92d55cd9aa3373fd90735cfc4c594c516159027", + "0x5a5af9e8656afd3b52f4e27002f1be9b09c5e7a3746fac7e64f5973ed423c14f", + "0x1ccb86d370ee32261f76a3e9d5948c40489c26f2f4216535484d7bd586f2851b", + "0x313dda0f2ce1542eb1236a1d555959516abe06951460d77664650b6cb7613d5f", + "0xfcf5408ed6675b5d1c15629e02635d726777e63817c3ccac36d4726bf95fc4db", + "0xbf5f15c67971a4b624a8ee8f81086fe24f1940a084bbfa031d0b69b865d553c6", + "0x9fbc4b0ebc2a128d391b68be84f6ef7833d5413bd95f751b503799a54c55c3c5", + "0x7ba3b1dec981980a957680b3c125328bf3683578828412c3de197ad07d06565c", + "0x4d2ea255cff42df73c96d18fc2c372e5ea9fe80eab5c98a6c6579725bf4c6fa1", + "0x9793db50b81ac75df1846e8b8898dccfa822d69bc4f99f6bcdc95ace2e3317fe", + "0x21c1959416e88792275d6eba88e8fa503c40a1f4a4b78cbab5b94e6c1ef714ea", + "0x3161a8a5b42bcf792b44bc3f7fef3606978b6bf716effb5ca1b0fa6b85518ae1", + "0x59ca1b7fd1f09941c911a4a6d0365e7a852a420a43af73ee0bd76f6413c6f3f6", + "0x86db4d45c982f195667fefc3de1af4a17b083b6f3700e47568ea43829e686e06", + "0xe5a713d52d696cbe65220fb30a4183ff9121ae1868967eee002cc032fa41b07b", + "0x446668d8777d9666222a04bc9963f89873387535f485490adbbd15094e6cb9db", + "0xda139e22348743ae9d600e9e2f651a717b8864f7bc8a4881a875945daa2645fe", + "0xae22c6f51fa8c11daf898addd39665d7bdf6d266d42ddabd790accd6538a6778", + "0x1059bd6151a5a3de93e45f7b3c498225b759a46444717cef5e66879b6e0a43ab", + "0x893e490bd7a3cef98d878f4f55d22aa0456f934e16a5ed635bab5d993909b006", + "0xefff7bff0a97e0e51718eff0d61540e164cb131ebaf466f01516ebe956b6e0f5", + "0xe6eef674ead50579daf941c526fdb904419a37f009fd432ce0521835b7ea09d1", + "0x7cb9c0e3aed016176058c80a03eea8f70e6f0467cc744ee752d937422ddf455e", + "0x995c33746119fe51b3a3c71311fbd4d91810a2ad95a558101bd11ff1a9913da5", + "0x926048c8fa6053aaf47f8986f195d19f1a86a4e01d5b34c45c91a09f57be0cfc", + "0x18ff8ac452c3f84463c8d8d92fa6f5550149f0d9cc0bf9b9a6ff6f05a8e3dac4", + "0xb495eef7e11375f1fdd6fa2fe3f97e1b834c39abe60ef1eb75333f36474a57c8", + "0x8dd386ddc871b764849a057f98a838f0f66883cdaea5ce4a9728910d3e1d124b", + "0x344c77e81e60bb40be5a20fa14b7fdc8c4c696d523cfcabc408e04df7fb79259", + "0x6b55d08a7eeb8f800866f031cf194c0ac2292923fe0df0460fedddcc77ba59ae", + "0xa007e70a725287607f23c03a782cb36ebecd692b45c1273b62769ddd1d0caf1d", + "0xb196d7291e437b6a26d006634de1edd3096367faacaa2b64b6c52a5d2228fd43", + "0x7f4f82aaff92c6e348d8b52e3bffddc7d06780b3750630d40022d54e668ec761", + "0x942e657c2125a5f57351b6e5fc76cf6ff6690529034f65d1bfa18ec8827bb241", + "0xce436799308200b480aa234ee2a4ad407bed1142999a360ce8a3d2230bfd4285", + "0x9f3fe03371f56c4afa64fbf2379c7dda3752eb19077a4de4b412fb7b5a4721be", + "0x53f63ddffee8a93759f68730026c3a8c9026a1a61a17ecd8b98d29e3d24dd019", + "0x08c2112cf1abe207076a67b43f67402df0d9d99990cec96e10ca46f4799134c0", + "0x41c4a5929a07431a1a0918caa5294b9b0f706960afe8e75b0e4555e40e182d7e", + "0x188b2fbd1b54709384dbc8b62e21cb1cde0b5c743aa3c25d8ce5ba4557728a54", + "0x92cc75e85ad9a09407bd0c09d68436fc419eda5c29614e125ff99964e304c0e8", + "0xfad03371877721fb4477f73575cee54356114f0842222f6a343357a15d409568", + "0x6072b8482ccdfe974790727775e8c0c43228a724068a39e351a5c702e7086fe3", + "0xdea9c30a8f46fe7e34b191d90b14fe09aa61275a32063ccca2d138886419c60a", + "0x3c24861389a3d1a8ed5d2c71e052914d4dabca490be956b7ed63a2195d65bf60", + "0xa2dd585af11cc6d60b55ab7b5295db6f5fd49e34c58948ece2ba6a4417f53fed", + "0xd0cd3dfcdee7cf3b00e718b6086ffbad37e61b80df49c373371b6ea449e5dfe9", + "0x018a9cccbbee610c3d978afce046e1e729013fc7ae71a0d80b2c22054acc32bf", + "0x6cd7707d257de792f35bc5d5080ae5bcfc50188ec61b406743f0390e8f5e4ee0", + "0xf036437c80029ef8595f65cede2446255b436ab2b47cacebcbc513ee09bbc6dc", + "0x438c8373efeb9d010e459097f7eef12dfd469a5d447f5494742321fcad2f5fbd", + "0x97174ad7515662e1cde2300a93986316ce4b7ae00b7f35a0908cde607ef6070e", + "0x8527198f8104df2b8559ff578ef5e2a84a9f0ffd63d8faedf26a50b44a19932c", + "0x7e4b79ce0fa7dfb5b4cfb92a98a0f4de105ac1a931a34efe94c16e29d5b03fa0", + "0xc240072b872710ac52ef170ca53ab03b3f76f1e2c1cc40dd48ebec3d0636d6cf", + "0xf957c0f8495186575f4a1bd2fc19350c9fed57fd60a884999d943e5fdca35038", + "0x814f0dfbdf3cddeaa502feb0f13f879223d9f0a14d01d756c3b3e773b44ce581", + "0x999f07e2f640408c58cb9cc0d15b4ff6c90db7b85e98e6888f74beefce295c1d", + "0x71e4362451b4d259a942b2a0425a070a9f0053aebface053d9c02f9ca4a5ff3f", + "0x28a29356d506b43e9dc9fc05bf6c7533e6670f5ab1122f49ac572bc2c9b94b49", + "0xa6dc1aeb3352b65845baa0329491789262c71b444171e36a55f3e20ab5edc026", + "0x6a0d71aee995e2857459513c124ccf8f81212ef0f14ea8a99b24b395e763e2b5", + "0xebd35e5b9134079efbdb4759e0c2af7728b73caeabc2c2bfdc3f590d5eaabc68", + "0xf1a7367e7b712b141602d204924a0c8808c68b013006b344e30d207a3b8c179a", + "0xb142818bb0edf0b1cc120389d0bef91b1a7b3e1fe0058810bbf73d04cd573147", + "0x8aef2ed196ca7cea305211c656084a46438ccdb7d2549f24fe4bd3fabf11af57", + "0x934cdfed19bc7321061d3ad217879cd14def18b18f6d8d2baa625626214d39a0", + "0x16f1b202a884faa4dcccf5d408b3acb639a78aa1104d1bcae40182f71d94a1f6", + "0x5cdb53c18168fa65c252659ba594552ed95150a4f0f2b9391ea3fb56badfe814", + "0x304558b9ab585c1201af4e88848d81f5fbc380341bfe8df9e9ebd279a94a1c4b", + "0x7c13cf0890b8fea28d01b7446750a5f1429d343ba69525e3909f054495d30f41", + "0x38ff978ee475767c435e5cbf5c0ba9c10c48426a9839735b67e2d32028a1582e", + "0x7fc90ebe34bd2cea4744c1ca0f3968a304f7cbb133353cd0aa76b45d0e88a23b", + "0xb0da2f67974a7cd5a291665ee3d216d5f57df1b66e7a2f36dabbd97cc68bcd0b", + "0xc220942a0821ea338d4307365bd1be586dc8b3a89f2b0f60065c92375b1bfcf5", + "0xda1019e4bac45eae0717a35e7aad0c63e0063ba18a8e970cd631112a9baa3d3f", + "0x7efc5e52c0a590ceabce9eb4eab90c50a1bdf595b7a59b0ffb3e3091317377c0", + "0x2347c7c6cc6f741e484eac237688427292a65d01f037ab25419d3c17d538db6f", + "0x207e2f3f0e856faab65882a7d3cf09daa37f08406cb96e5bb4252c8d0fa7f27d", + "0xc425eaba8494a111289148c65db0c8d6a6dc27d16986b0b70ee4995723c878f1", + "0xf7778a3d1b7fd83b3d4926d2022cf823801a2749283c9ab4f86f87126b9c7e80", + "0x1316c7953bb3170efc234d13e9632e017ec4f58a30e4e062ead373b206461f1d", + "0x9b4cd6a0e47f2c64c0ba4d9a7565f74e956cf881bdc33b1176617bf9f25af5de", + "0xa972bf247d8428e97218ec0e9a36e3b7fad10ce9a3126bdeb2cac7e9b4e48e46", + "0xc6a4e22ff93e8c9483dfd8eb8f2c384c72fe69cc4f5644e8d68d419b92509c61", + "0x601a9a84099f3205c6aecd034b53f586382379dc39be605facbc2da5f793b990", + "0xb7ed45da8acd237dc9c265afbaa15300cc7cf72c740bbcc00eabaf4dd90cf9b1", + "0x37bcee935e0ef47df22a7f9833b3b3a3830efb1656059c450a7e6a144798552d", + "0x06e7ecbc0f4d4b16a24d4260d77d0161c5a627083589747c72f765281ca8d3c4", + "0xc45d35b6c6a81240767ee9d994c8e2f5823d8a4e0f51abb7187e234d6dd5076c", + "0xd3c726980fdf096fa314533ca3e882cb1c1a2a5eba4b9ccef7193e9ab7ce34b6", + "0xa6c23887788743ac8bdc123c7b21873889d538f7acc389c28d6ac9dd26da06ec", + "0xb8b8e38541b9143da71d68cb705ad5076b089b6174d99bab4b87428d8828ac9c", + "0xa70ec737a97e306a66b7ab8a7866d03d496bdac04a08a0ccede2b84583ee5d21", + "0x6d43013f53b03cbaa4c82a2d42f5336306301bc7a624542387cb0a822ce89a50", + "0xc24661eb76bee7b5db00df129db5c2038dff544a90de77809a447530e8200d02", + "0xfd291a2a58d472bb262b3e9b4b2c08f8ca40536082e05c081ccd502c77a78fde", + "0xa34be368c12bd1c05ada73b647d72da9595b0d618679905c2df760ff1a2b6dfa", + "0x4e68946f1b2d9f9a1c10f90b0d354084561bf5440a823945c2d95f76fe23a765", + "0x44e04796d2516db3ec1d1b47b47776999614e81f6d300e2dacbd4d15746982ea", + "0xaac3047a84d57dac9b3f3c8ba907bec354f99ec2d35b915f115f4af6a658cb41", + "0x58489c0ccf49e147ec986ffeca33e037dedabc57690bdefeee7af8a70b781fbf", + "0x3707fd39b11fa9b79749a84848deba1c70534a493769788de1610798b30eb70a", + "0x891483f79855a712f99bf6bbad19a3291c4d417a4f27d66868951c454ad1bbbf", + "0xbac1fbd157279efe1b895138c55e8da4be5dac3b78c179c4cf25a0c8b5e7c5a2", + "0xed050c00def0f6b5936324a13f426cda7229ffc68c7f0eb0ff6dadda957c737f", + "0xb0e759e352ea7ccca080e4ed51a6a4aa4573c7c0d703183da7a98918fa9bed81", + "0x914fb73a4233f0368088073688994cbb0bf5f973a5afadc11076cd64f92ec5d3", + "0x153136092380ba6be166df58738c72d5be76acafcab31474a72b7f7e70e9296b", + "0x7d4d6f2fef46e1b87a73acc8c6eac29195286af79ed7e07998aa966c536f8f80", + "0xa0d10b259aa47815403230b836be272c3dde8cea738868ded0d55d89f2692dae", + "0x13ba7e74aeb0ad66c77cd5112e1ae1b6d3eea84a7c306d161408ef592f2f3399", + "0x491fe1f14cc862fa156f04901a7a93ef26ad272cf98e4f29d28a6250f8b4738a", + "0x92a8a01853ee89642fcf51e42e6a39616f8374937a98ea579d9fe35557d37bdc", + "0xc140bc3ebebc1509940644318dab91a6b8722a54bc32ac7500d94d1aa24ae1ed", + "0x55a5a8541d36a244b1d73b32fbe99263cd6a7b3d9b88312747de6d66302e2a63", + "0x510caebe6714728c47beb114e95177c3a0fc2438369842278a17da9c4327caa5", + "0x8ec8d3e19017cdd4bb4b789ad29bca53d8635596e6771e09becb9e261df64be9", + "0x2e832a7e47a73b47ae881794122f86e1a06e1d84c5bd0a946bb61175dbb5c0bc", + "0xbdb48c7ec1f278b646faca580983ddf4088835803fc0dc2e505be6b092442d04", + "0xcee8eee843b37076f11f69b77094872966f88b4629240e04cea69d4eb16d642c", + "0xede0d0302e40a6e71dd63a52fc1bea3828c4dd56c754b576af9c441ffe2945aa", + "0x07c84f827310d73cc44181f612f5f5ee0ac1207b3f72ae857f9f1fc0180e8454", + "0x40c4dddc5fff7a7a5372de4d64945900e1d6908f378d87b4bb75e425d1fd3daf", + "0x61d9dec3abd29d998af2cadfdc7d22344b651efc717797a486712dd10a726c01", + "0x9de133af95e03c3bacdc17ee428c0ee05b70ef2b1b515edd6fe488db3d091e88", + "0x109aa9704907a39615ccbd296974e428bf5fbac0bce5af02d9c3a8e45e47e160", + "0x8a1f2230da7f048dda7d17e7347cb1cdd2bbcc2ed0908980f22ec070d158689f", + "0x9e8215bd095daa6870eca13dd025edfc700bb5f5ae4f0ef9d44a85b04f15596d", + "0xf93f90b45c5e3358a73392f21fe640c6aff9cbf352eb7a1725088313630d6226", + "0x4e4c1ceb1177bd15944b238624f6e41aa0713564eccbd7f0976f22cfb03c90b9", + "0x2b7d1e8792dc0271b3802e79e4531e42d93475471d880de288dd4cfdd85155df", + "0xbffb3529844e19c7e24a3bad1fd0b90d8319c6982badd3716ec897ae01b0ff57", + "0x497725904d682be0024f5327c62907f1507530231fe6437341e85373aa941d03", + "0x20c7929ae689311a8edc8672b1ff85d79b2187c46da7d0f1e0decdda16eec6b9", + "0x87fec4a78f73a200c7798a07e9f7d956aafc83ab4a90309591bb76152b8e11e3", + "0xabe053b8ae209ab83d827b63e43e08b9b4228b04d51026bcbf044531a2e8f86f", + "0x4220e78d59f01c20f45273e5183a2a36d6d89c2f406df441e76fa8b3f540c8e4", + "0xbbf658cff95c4f1cff08b95069d5eecd60ce5960818014edd66b4f0761708827", + "0x885d316eed1f99685d4dfb1d50701b7a0c9892131a99bf1c676d53c15ba1f7d7", + "0x0fd86d1ee76af5eacc36255f29606e4574b93b1501762118173cfb9997996c78", + "0x400114dc52b491898bd47923cd5d91384ad6a728f725ffe87c916ba858e58a95", + "0xd489355bf13693c3c70b031421c885aa09772cb9d10381d6a5dad584f2055790", + "0xbbe033546ee5909557cb5b96d466ca32973b455f34bba60ddcdee782d8b6cadb", + "0x207bdb63fcf0b403bdbeef4f714da0393b1760adcd1f1f5b21a178bc404c9617", + "0xa30b9d2cffd283cba9de68eed716761ea78170a8d7e6444068d64563c141dd2f", + "0x995015315151329c91ad8ad28aac545c50196dabf0ae393c72d9f369524c9fc8", + "0x3928c0b178546ff50c5668677d2605b701b06f4d28af0c189e746b73b9d5c53d", + "0x46bc7b35d38eb9efecb3082436f28e3d0e36465e41222dd8b8b47fd9857de499", + "0x93d83ff35c0e00277205f12b3ccc89ae35c28177023f2c37b562df491dfd0e1a", + "0x11442d3d7778f2e463da87bfe957768e36087cd2b777e8b0d78fedc624b9a9e7", + "0x2c4ca247e8c280db854ac3ff7d270ca3100b30377b6ff807b853da46c7321113", + "0x0f72e138a21dd3ddd2913dd1eeae525cd78aa578b909672b4450158bcae26aa4", + "0x6a02b4d5e27880290806d410461c10558f33ea04ab655d291e45a7baae5d48d6", + "0x5698a8526618fe20a06bbaa970590e97ca9677ad95b0b532cc816b2577ec1bc7", + "0x7fb913cf94da8bfd05526a954c1f2e1382ae275a060b646d2ba78f004d67d30b", + "0x1aab7d83cd25cceeadc8352a9de9600b0b69acf33a3e157e5e54044a4b1baa60", + "0x03df372e7293b449518d07c4d672c76157c97c6bdc8d7ea75b5d37daca19dbb7", + "0xa928453adde66a9ea45a6b19560fef2619fde93a0a0ee463d64ce538fed0f8a2", + "0xf9cb142d5728bc1dfd59812afcaff8877e6357a46ac9da8beb54c1cdb53bf4f2", + "0x3c67d2318e1867ee0bf234129e7f9ff7aced4d6a94bc2493df3d49d3ef7a1f1b", + "0xe7995735d058d5f1281298652cfec16318f36d90aabb73bec620db045a4127db", + "0x796b4fc8ff8d962425ad653c20cd5e3cf5802edf8fc363824cbb4a117e5dd9c6", + "0x3e1f5f3519dcd5649bed8a4fce463bce7b8a28ce4853b2a34c219c76d8e64238", + "0x0b56a06fcc04ecab448189e170470bcee6415c859a59a2d18b5e9a838bcf2ff3", + "0xa8ceb396b19d4c72d6379f27d0a8283a06c7920811c045dd2521b20d719c9f60", + "0x42c02012a9f184d3bf976ecdb7f65e7abd70b4a32493d75cbf0c3403f5ca358e", + "0x79aa61d2303214ca5099ce8d8c8b59d7d3f64d4af9a009683ca4fe2ecd1ba4a2", + "0xbf626f7b1e4be0c3fbd962e021d50f40e580f133b6127a71ee06c621fe6508f1", + "0x3a8e93479758ef89aca8a3311a16fb82fef78b19ed11c058625e6bc6d4a4dab0", + "0xb44da67d7c6114b0578183dd1287bf06f0f8185a41c77ea75728e48954b4959b", + "0xf49609ba698b8085cccdd8f95a51996d9df32cfb8d0293c01182482dd03b56f2", + "0x94226b7a92c9aea67f94df39675af2f27cdc9a95c847eeedf85ffa17238b3b58", + "0xcb27475102016a2ac05f8c8718e110b74fffcd6c2a97ad0b344ff07a6a806e2b", + "0x84b0c9983378884ad2ecd01c7851efa8c0906b4741d42581c3f1c52c47a88151", + "0xa9071e8c2f56b564873a782630fbe3bd292337b2b620eaead27a397ee3b3aafd", + "0x8c057d25493e712878bd8b628b3cff7bb1249ae41dd34c25ff57a3bd12b9a96d", + "0x7c2b71dbda144cfea3c1e492f0a1e30f2699f3f1968da76a97fe39f3867d37bf", + "0x63b9d33e4d168389637e6fff44d525b67b5e0c52bfab9fbeb53df0ecdd601984", + "0x2a74b62ae8feff55542905a34d6f45c1441891130351bc9959c62f53864385b5", + "0x725a488e62ba0c296ee78267ce714a8ac84ecc3fb8dc4b5147024ee500821dd7", + "0x6c54d3f508c1421a60a707000e1236dd6b45becf483b1f21a53723188c1629b6", + "0xea9072804289a3b9fabd8652a56c2da6e661f14ba764f72949f7fce38e517e7d", + "0x65118fa4f148eb7b0feabd60c0ab9d42802a5ad7685b70bee9ef8eab668c046b", + "0xb07416ee467668d8c7f92a260a6fc430bf636e29b9d5ded3dfac9751e006eb4a", + "0x55385976c32b170335a70a213780cada5fb0c6dd5402cd3056a60a40a6f13afd", + "0x7d9f44575cfa89ae8f4e160a1f432e3e05d02c40b9d25ca0c06df6d35226985c", + "0x12774d382f48d5be794157e2a601c3814135f8cb961d534e685368c3d605f430", + "0x2be48bbedbb5d66af410fa612328524aba00374c152a0b533fb2f15e98bcce10", + "0xcceb249b515238c46a805cbd452395633f28864f16959cef39ca13b69acdcc2c", + "0x90b5204c90b256708cc946daad4a70e3cbbcae36356b377ea6cb251568d8e87b", + "0x468a2c9bd83eabbd10a5e301201e54b9530b9a376452096bbed509240c6d7b08", + "0x322456bcf4495d9787fb66d0d8f21242210167a1dc622706c647e1495c19d064", + "0x1708f1ba83981d7d6d21b8a7d55a4bd9c6355195bf42eb96e870a36480f90cd1", + "0x904c7c58505bb73503c5baefa79936d96df91a15a6ce8121c7f38c632dc7172a", + "0xb2592d5491583e30e4b0e89820f6cd518d4b082436ccbb3a7685c365fb6e9aa4", + "0xf2b08ac926804a68d4c1dce8fda9cc1eaf14e963499f29527caf4797fc47933f", + "0xf9274e64683f5717fc4bce6bb2590921be5a67c1c3f9275bc390a438bdee8295", + "0x7d6c4c1ddfd161753d2782c80532479eac3ae593ca4decbe0b4308123759a218", + "0x3215152f21280b1baf712191a11b3bb80d48f936221a02d199f52437d878c402", + "0x748ac2bba96f92574ff048d2e3100b8e8543c181c8e817f3770e405f24b4e3be", + "0x056d9dd029b79d40d3599b6f6bf240603931a247979db979dd9e6dacdcc53d94", + "0x56c57e769cb7f53c4ca489db4de4eec62071cbed1bd33759c27662e411de0221", + "0xfc7a497be0b417bc1557eb04ec43f9ba4432cb029b6684c295b84e500527d5da", + "0xb505ce1021402ccac337fd5c5346fa162c6843b2d945b44ed45afee0139df1c3", + "0x267595787775e5a0d97e1cdf0a4deaaa785c03b8456a6e5b433767bbadb00ab8", + "0xdfd8e51ed2325e8f2d2bbcefcd24bf9242fbfd75dac246ac8186cf3a72b35de9", + "0x11004185cc8175d91364e878229f5aa5a5366130152e1dd8132cd22cb0333086", + "0xf5ec1ef381b33decb885d21749cc32ad02cfc66392281967758c3fb30158f9b2", + "0xef7fce98b3054d4fc282b38aeb4bddab1c35b085ad4ce803856157d7fc9025ce", + "0x7acbcfac776f80cf46614121866a2621df9302b7be20c079e224cc1377637586", + "0xef8433ec6eca61afc8bf7e8ccef7e1284aaacbb4972938fe061086307a6417a4", + "0x1f76cba9e66ca16339c3effb745c71443bcae09a22f1b07e39155a1805402890", + "0xd720f64f8ae3da220074c029256cb459b1ee8be67ed4dcaec10933cad35fc58b", + "0xf841bac34a5db54625473826eab74d3a53f7b3448e5835cdf4df370624d24aa7", + "0x7b784f45b8f2b0ec9229924fcbe26f66c306297cacec42af1c474566e1f83f6f", + "0xeb333d1de57ffe52d60603c66bbe9f2941fdb01f81832d418307596c156cf54a", + "0x06abb43d2b3733811dcf3059f48be59587425b5d24c086689191e5bc69fa03a3", + "0x76ffcb35a00362f10fb36d68eb7676093c3e36a3fe7ad65acd0f58a064865f2d", + "0xbfa99b31b08807772e417d9ed67daebed645ccfa0d94607dc0cce754bfdce0a5", + "0xa91db056c961f435693a047611028c7fb784ca015f450e146bc8e2b85ac8d592", + "0xf2489993da543373e00b5b42b8db157eae15026a65635e5784d06702d6574de4", + "0x1629e6d410d12987f412c01d14a21ae700e4939f45ec4ef0e1820905649b7899", + "0xf127b506db1c5b3a1aa6bcbb2c530e822bea1ab3deb497c54430fec6a60824f5", + "0x4860301daa24a54ae1902388dd072e7eae2ad449f4a86c123caf783284cbb7a4", + "0xa54be84ce7432042663e40822685cd4c3c1a33bdddb295dc32f9170ba7c95a14", + "0x576136e6b6f941a6861e863989da38d7234f524886f278f8a57e88bf925088a4", + "0x08e84b8d1e15a7aa660666a346a0b90db8cbbee7cc086378d4020d86b1385511", + "0x9229a29e091b9184dda6d66e244af33b0c536eb7e61b7777a5bb0d02f0a283dc", + "0x58e34e5a073bacffd29a05f85320aa52625a9cd27675954f739f3f9229e3a163", + "0x25d2f9f20d7cedf8582931d6dd9ef68233f3af9caf6c9c6d5a10f2b9372358ab", + "0xad43fec2e1ea1ff81772fadf5e38a4f280305cb225567becda2cd518ce2f1dd9", + "0x05195e944c209b1eefbe1925827e976c19d065d18b3e23d883ae2086471c73ac", + "0x62232485944c27ed398d4928cd9ad1680765a4efa652a925b97ae26220229fed", + "0x735c916d78f40581506a4cf286e044a6d61afe6d70daf97d80f8c584ce41d940", + "0x8b50f9bc93ce7c7582ebbd77bddcbc3a123e90d43434d63aa4b5c397a18bd1e1", + "0xa270240950e22fd66879927f8c51322f0feaffaf09e7bba8829ce5dd841b9e56", + "0x6791446d6f864992e3b50fb590719af98aadd7f8af54e4c71ec474cf0db56cb0", + "0xa22feb28061c72ce02f7d6bf27c7d04049900ec24394a73ea678b90c100de62e", + "0x0fbb9f4ef4d048767b036f40babd8769e185c549cd71e2e46cde94b2fc1916e6", + "0xb32bf314ae6b3994bf2caaa716691eb2116289a796f968ace5c49482965d2037", + "0xf68f7edc391befc772458ce2dc9e5a1c3eb9d3c709c4e177535a14a863eb686f", + "0xee3c3122cf1f7890fcbf409897c6ca4a634b6a90df2d33cafd8dbe1fd2895ea5", + "0x44c407d967d458d6cdbec3e4fd90e0f5fce309f702f08df5f7fa7d4d66ab8d90", + "0x1e4c7644e30228dd70194e600a57f98c3501a598835ba35a3b0c99f53101b108", + "0xb619a4deb408b73810fd4c5a827c0cdc3f7f9885470f63c468794c7a0796c184", + "0x69ad24f8814b17603ff6ffc1f585346e243a296f74bc3781453a512bfb746a9b", + "0xd311dacba946134de52ed8f98e5a643c0b4f8d5c6d2c928ebc5087b33b309422", + "0x59ac40ae911e0a13aafdb4961c459a9cc8168e444f9288cec782911aea1e5548", + "0xfbf447c35dabf67ad4e88a41e30c40133f166adbebaa154f0c571028f86bb183", + "0x64792ffea472b80e6241942b1191a4e4228e79c4e0a436873ed3eb714338aff7", + "0x618ea5b82192c2e43742b8d74e78234efbcd6332d74c18c97ca087be66baa8e9", + "0x8e659da466b2150870fd5ccd6b4c7e879f3d5e248bb386869bcef965fef02837", + "0x4ef68ce8190a3430e4aa1497ccfc26e31d17ce522f1f16bb7280fa9ca2d377b4", + "0x79a10cac12b7e9b922d9c8d1cac99ff5616826a5f176a81536402cb968377e9e", + "0xa4fe7b019557ab1cd8d212da8704a0a84e8078eb9ab53952c2ebc0c3914835b7", + "0x59916f12d4cdc91b9a0e135d84630d10c48a803dd9b84ae35fe00c29d1acaf58", + "0x802690bc2c2f03e08e2d2dc7216a033be7eadcce3180f220fa5baf411cfce958", + "0x40fce55d2c349a7f97a252f6ae7d10013c396710905abdac17ca794ee1e247e1", + "0x73dc6101cee72bcc15f9ef398f90f2c5e3f616c97b0c6714b65e9a6a83edc190", + "0x7a179bc76526a5752b82b1556692acb502a72e364ba1295aee91abc726c23de6", + "0x313f3a435058fe29e7e9c490553bd9791dad94ceea2ba672a2a2a3e7f69039c8", + "0xb528f654e6456ae46ca764295454d78f4d5a4334d49340a754b5d8ac24b0d21f", + "0xc06aefcbe61ee635fefaf4e2e933c22c73c48b55f8672cc6a3c8ee09836af286", + "0x6626a0134d8ead3f18aa09af7b1c05c01be0cd88c286535115edf3ff19e8f06c", + "0x90051f7019b8d99acbeb816ee256899d8f0a5504f156475cacc631f427273c40", + "0xaa93485a22e1fc2da4c5b5483ad81208bbac2595e758e23677e93521106c1665", + "0xb334853c4ed01341742733a9b1d7ba7430f3353fc1a52d0751808c98f621ab51", + "0x67d2672662726fb24d884ea92668fea97d9e0d908a11f70bd29126fdcaed009d", + "0x09cc08cd5c0da5caaf74d0e8e417fe151129ee7ee9b5082f415f2ede57351dca", + "0xf87ef937db4618c977d871e06bcd6e2eabc7a20faa0ec0f08deff573200b0aef", + "0xaab334b96f82ec056e3c8e1e95b9326f35d57408ce24e63071e182dc38d552b9", + "0xa0d5f838bf15f771f9adf19f82e01308ec34111bda56e2edadf5806dbe80aa88", + "0xf288f085a08d5edafdd58a3a0637a48f0f6cbc730b0d3a0530a6780cea152281", + "0x8a9e915a3e1ac769bc5e3b308fb05cd49d6cc40e97f6cf8cf789f1cbebf7bd6a", + "0xfabd2bf75fef724ead94c7b6e24026264ec2728bf792bd0595aad04900c69640", + "0x3b4a6d3a6e62b3fdc14173ff99419ef02b18134050f8433080e65322bb0934a2", + "0x8d72cbb4e088da0a6725163af3aa47a69b63120f3bd02b93e12788b144e1a26f", + "0x0a112bde7c1434c444519ab9371a553ac25250067c72171fa6779efee4bdb7d6", + "0x8b89d89dfa4a2cd35757629c84edf71815311ade9742e48b6f28d1886f1741b5", + "0x538bd079c14a70a3f6db4b45b528e405a210fd6e2343fbdccec4235a09f016d3", + "0x95ea30334671da97054445f307f3b991ccf1fc965ef148000253bca44f6f4209", + "0xce98031baee0108eb9695be729938f22ee71abd8f368c7284fa7c102c2c03672", + "0x916fa5e6d29e5b17d29e6393f96f2707b2e245ef49a671ca30987c9d31223ef8", + "0x1caceadd646069b69b86699e555e0695c756108dce2c74ebedaa00b8f4c1d4cd", + "0x46a5419c22b3bca18ad94d7b0f34af90c62bb3cf660a4b0b6d28bdc11b079390", + "0xa83044af490b0706b350357979a9e648e041ea747ffec7a50f952b71b9c42a66", + "0x677dff9b0b4ca0f39d526ef4a8fac9bb49d83b5618f73d7ef78c3ace311fd071", + "0xc85d8672b034eaca3715eb6db5408d00d8157c991fbfb55b8fe29ce168aaec9d", + "0x89869cff97616604b696706b28474ae54d88387c2d5a30e690c0e5b31bffffd2", + "0x168585a4f4a9a745a588d609d3eced8e550f1d69a7399547a60456df218bf4d5", + "0xcb4d9270dd367735a6844dcc314782b708ea9b2de82e5f1fc11bc83b0970938a", + "0xb3b2ba42395b4c15d6de64f7ce010486ce1dae4e6b14f01901cf1f4b6a538d30", + "0x11601920286560aeb98fe1436a1f66e2c9ee69ed2ce11ef1eaa6b4b3be447787", + "0x45cdc9aea631ac46062e1d848c3a737da5f7f1d396177196e52b4ae1019a73b7", + "0x113956d33be8473ea7b52f062945a1fafe98a424d50b8b418eb1b4f8403f7036", + "0x2d5a740fe5eabb6fd783b9c47ee75166e2ef7916e75bd5fbc40fa0a6680d97e1", + "0x3bd16b4f04c059d78b8a28627039d6e47954d6a87543c611d6fc8e2e941a04de", + "0x86b1f14be4ac193baaac8092ca3d377f47dfc4e41b6b81e02dd51655fb590c67", + "0x1cc63d91541476745e3732b4220403bc3c994be2e62c6fb2e788c5a47af7445b", + "0x5d09f5a6d1570b09f03b79e869b7f55b344a2c5087bd4c2c06c8d4a85f49095e", + "0x6b48201724527b22e31898ab54616f0008afdf463b9afb6f0c516e7347bf0519", + "0xe79894ec014f7835965959a9914ec4620c6dedaeeabe7aaa791965b30d503908", + "0xe549b3679ff2dd8cca080bbf27826ebdcc14a6ef6ff6f06a2f2ec93a4fb1baf6", + "0x5bbb4f98a26c9c9fa8ecb2b71bbe032c0c4d349bfeaa81790eeb066412de248f", + "0x614dbf21c81332c690c934bd9d9f4c640f3df9c9510e9aecd105f5d2563a6071", + "0x44231b331eabb55fc08363ce5da10d7df42626b94fc9dc4d08f99ac220ee145c", + "0x3e22a80bfbb6e99438d4394700bd26964ca97de1214b20c8a69fd1788c50a4c0", + "0x280ee234189ec732bec0b7a25b9bff60b04e7be32c54fcb95121b14725bf62a4", + "0xd94627e7ecf1abc160c432aed8c677eeb4a0502b3100737567bb2d19b1c81478", + "0x6b2de1031473d511a197f131e579522f8bb2bf9abfe7ee561d8e7ef9b1912b6b", + "0x80b1447503f606ec08175cdf5cadf774f3d0d2a1f447ba41ee66941811690b68", + "0xd0b95ce90aa06affd35cfe7d1f3b45fc121bdf2565ee5d3a1998a932c2fb6db9", + "0x4575abb623e43a73f1be5ee52988e2820cf35170b68c6ba8caeaff086783a1eb", + "0xa03708f13596c11a3b76c49b44102350c06aee7ba92b3f2bf3829952f6fd6c86", + "0x4916a6e3dbbcbc8a13c91f4db3f0695f94cca48b81cfd56b9836e7ea44af8daf", + "0xb73b5c9471a175c8eba25a4df896302b65af142819e047928b8847a5261e13ce", + "0xc5e4bf50a5d4825fcc44eadc3877bbbae0589fb5a2e9ce1b16bf9fd60056af5c", + "0x43abc2f7f189448316cec758251cc7b63526e95b16ad919e74fb50a9831b76fa", + "0x072a4368d93c89d6bf3beee22c6df5acac53b9c8225e53bf3e368739890c2bf3", + "0x395bc2072a773c314c9cfa3c9983f7d8d23fd77276a6cacc93f580405ffd03e3", + "0x50528bae45e8dff5a7d4533bd413b103edd5097c78f35f49d0674c6f4378f7d0", + "0x02c2b72bb7fcdc07939d7fcd641dc148ce0699e5b9c76e7af3984c36a7da08ad", + "0x0b6ce8ccf42bce819e02e2b0f725830fbf136095e361806a2b5eee5ec975af90", + "0x59da0fc5802651044d72946d162d95412e98e3a3bbc170139a5a54a9d0330a70", + "0x2d2f3bf4346e6f38045e925bcb90656bbac77f7edf2182a3c6835b2f6e61f9f8", + "0x213ddcd0341b130de4699b81b7eeaf93126907e52ee92213ecac458bd957eb5f", + "0x0ffbbec5a21fa439c09f975abc684ad9884d396433aaa4f4890e5e377d7cb4c6", + "0xf52462396c136854067622763c21ee796e880115bdf0fa08a07a130ced1031b4", + "0xfc9bd5b2de2b2ca5b16a7f7c608ed4218f3ab60499a691843548e530123ffdae", + "0x8eb92cab2abcc01f735011f27566324816450dfc5ae2d0af14137028b046bc29", + "0x0795e1456a6894c0ddfc3ff3cfa979855e39179b03c15285ce084bd483067a63", + "0xb8b428f8ff1ceea1e694133996663d000a9bf0304abceb7cdaeb6db5be74983d", + "0xe682c8aefc32e0ea3899f6708057ee708ce46125462e8dc2b2d4605f456e3539", + "0x100f58fdafde5a4e2070784f54088d7522f2537ab249095966cfc9b8250f6bc7", + "0x8efb5cf8633396437ab174527ced3ede99be7e20790ef382b5e25e49b7f49c23", + "0x196ee4cee920a9faa42cd5f3262af5b35dd212169550664a3c9c15bb3a3fd86a", + "0xd6781eebac997c5b8eed3b0058a058b3f6da487d143fee14711398a017d16333", + "0x096aaef445abfcd0de2a662b16cba39ce371d053fae63c27f3599df3d169ed0a", + "0x3eee47ffe2e9d5b29c5e1139911d57d3a3d8d87b4ef290dd95e88a8d9a56d890", + "0xacb1b75fdbc4c4850565ab27978e7d10f7c29d6528e7bf198958238a4be4846c", + "0xd0cd5035132f5f8b303aaaf10d6873482b4870a74965d8055c48e8449935b76b", + "0xe65aa97a1cd3aa5b9cc906157f7d9352cf6592abbeb66647623632a9f3a93b07", + "0x76d08e7ef145ee5f393fad5faca53efb07b9fb493157a6e0b290525127b5cabd", + "0x533af4ec13c168f2e7c7368cba5ab0a138a5633656b8c19f284c98c42018d849", + "0x0d61ae94270aa651231f1933cb968bfe0cd2f4e097ae2f0ad8d41b8e2a785327", + "0xc22f8e6418938369b4e505425a28488c54571c4a803df35a233f70ebb933c635", + "0x743c0c8d16b790edf5e51a8453601ada99965007cb4dda51c82cd68e7d77a224", + "0xe5a62da310591a98f6b3138ee367ad2a334cd48d430399c425b71a57ba44a46b", + "0x5a7dad70619d620e5991b7476d125af8db51b67935a49c786b57f09d3fbc4035", + "0x1459d52e06d83b9ef94f035d08af0d63f66ce87bdfc3fa25984292aa2680ec68", + "0x2139af4823664ad7b8f2d6222f86a5feb7a5df0f1a934e8af139d73a6d008d84", + "0x31a7000f3b576d91c543c5ffc4dff45205aee1120d9732c3a342318bbc4d72a7", + "0xe046d4e9ea0c367a2b47a0a23181e144d95f9a3b8d77244fd70384f031fba4b1", + "0x294de2ab05861fb25db6e1392e8eca830217680610165a2dc3f6131eea1d9918", + "0x1f2dc7721a6ec2f13b9c9dcfe3d166b323c53dac5ed49c883fb6104caa841184", + "0x3b2797e3eb732182ff4928045800ce8837b7b4796d9af977b118c080ebc1099c", + "0x4f076d935900c3cdcce4ca42e206caa7e63dbc926dbe230f640807bbb7965c60", + "0xcf8dd9699ad2fb397f19b16b851d85a565b4d197735f8e3c279de61fc4e45bdc", + "0x3d3544db3dc8e8fe1b672ec5ae8c341524bc7e1eb3c96bec3867ae910d7b85a7", + "0xb7d7bfdba9ead1c68bcd54c46c7ac2a34f5292333f62e7b91b193baee6c09037", + "0xa8fc4eea921532a7fe31196f68a915f6f935b8ab480b9943dfddb7279cc069f6", + "0x6c749c6ae083721c5f5613a581435fb837166bcb3f07325873ba321de17f4526", + "0xed17ee542d4953c8bd4a7035bd34be4e6e80b73ed19f86d3198c7efb661ea78d", + "0x24e11ece5e106eb20534043c2c9452d5faf327e0555bc3b8f923c108781dc1d9", + "0x094a0636d62e402344d2bc9c01fa145ba0f32e03383e5eeaf85b257eeac3acc1", + "0x0e02c54a2ddff2892841d6e450d8deb610057e559ade4b8c3c943bca63b31384", + "0xcf147eda0c90b66e59c407ae4b2edb236270672ffc4bb68ac7da7a23b0274c84", + "0xae8054abfb1b72499642a11f80348857e49aa315b8debd3d61cad8662ef56b08", + "0x8f9429544ab9309d5a18a2af44ae6bcaf2e04de344d9d55cf22d8c503caab64b", + "0x8c6288b1027063bde39e399be8e7c82a7f8f9b853fbc04a32f73404945002e4e", + "0x189a06ad980a6e9710acb970572b8c04c2fc041fdd169ccde19b5a939b69cd81", + "0x0ae24fe54c7724a8c075eed2813b90e1c520119e2eaab0a0578e8759868e3ae4", + "0x5d22a1a2f551aa1bef7b552ac797f5b2a22441f7c3fbdbd017f4c5dea89b7842", + "0xc1827d89c778f3fb6c35842aaf940bf8a829079e008421db792cf04018bc2b03", + "0xcd9547011c12cef89331daa486d5a89bf36c8dab81d5d0e4abdd9c2e35d2bd8f", + "0xf115534a66431250450d68d8c1ef80ab9a3c68e63a203094ccee81fcce0213dc", + "0xbe9a16558434d1f940ac08ce7bb0ed0b1e400583b7bcbd06dbd9fa933d1de6c6", + "0x692dc4f061262a3f2a50765773294909d03477b0663f47f4aa0f675f2c0cf0d4", + "0x6127590ebcd139f736331080139c1b3bc6aed2f3c961732395ace62edec7ca5f", + "0xdc75a2ea1a80516dda32d61a2d671fcd421ab9ecd81473230ff9d3be8aab444c", + "0x369e3a3621551d67f48e544d76a815cfcd9a72b188972b02c12ec433e54c5f7d", + "0x195110af607c6bf30e268ae88dc0245c6d3a34d392f0d7698e51eceb1e10ef4e", + "0x950743ee4492e360e7a594dbc4b786ef4ca1b061210fe967bb5acad5622f43fe", + "0x926f538cfba0853b453169710a7acd6c2a002b87d2826374bb55790ddeff417e", + "0xb93a4ff2a88a8ef3ac4c77b55e828172f20b9b9ed655ba7a37b00ffb524b5138", + "0x08947d220add3e64d2db582c988faa58556b11257b9b4d8ee817122085145340", + "0x28ce559274d5455f0f9db83b263ceb6f1a2bfc00a2512931b04cfa23e7887612", + "0xdeea519fbf4ff441c8e61ec1f0ade9258a50a10a4702d0be90b408f30b27aed8", + "0x3aa93241858d4d882409dacdb7e716e6fc8bbd19587c15e349ddd5a7d90e287b", + "0x87a42a8eb92cd20a8dea17bb9a241354559443dbb1b4f549e2f9764321a1549d", + "0x365f92d4e3e88e73a155edf264ff3adad231b6a8eb9de11a1fdd473d9f2fd27f", + "0x85056e53a4b8368bf1ac1327db65d01d35e72da358274dc7c0d47a924615dc87", + "0x0fa77604f4d0a3bfbcbe9019207fd21dfdb118d94b391c8f3467b7ede0085494", + "0xc58d6bcd06d9a666bd5217cc75ec70c65d90f45d3266d78262d44dd1c48853bc", + "0xce225ea3d493c85c9ff2719af2d7316577c7c87e43598210446575fa10263038", + "0x010a27979371a2f4c5790ec5d61aa1ea443347d1e8622b4869fa33816306afda", + "0x34cffe4d5ce1449e6c1efc3c6ef2dfa24b3502370dd847b536a41976cc1e7e55", + "0x423da7e80d01cdb061b17cce2dca3f31fb62c25ce0b25c7ee5a45df3ca02e72b", + "0xff680f2c9fe4896d1e117bdf7e655d7d86baeb0753ed21b373a621d954be262b", + "0x9527f4e412a189e2e1bdccf0217cb6159b912c0c3765d5ea7f9e54e2cb393b48", + "0xa14f94bab1a626a844886e0338510b09edc8eaf9f3b416787b72bb2729d22c3c", + "0xde5afc9aba2c6db5ab784212bc940193db7f03b695049dc969f1d5ddadbd722d", + "0xdb39c68d462695c642bb704f1fd8de951d4752bd15e25115032a5b36fbc6d2c4", + "0x64987238a6b0d048f5747a81ed04806e89108ac247e5ffb3fba66fd875797690", + "0x0eabaca3229eed1341b2e330bdfa87432bbb685a116d02f943dda9ac66b4e877", + "0x2247273340e0c7954df9a5db6700911a4f786eea68c98106a29ba0c3abe96baf", + "0xaa035892630e9168378963dc34c427fe2146d6bffc6c8d1c5026ef8c3ccf395d", + "0x26a8e42afb55511f170429010e07fcefdce8bff03e3acbb3f8571be05960bb6a", + "0xa95bd3416ceb31df25f3b5e262109680341f742c11580e2e83da5f36d8b84ea2", + "0x09929d531b919f43ccf5b6ab7e87265ede17ee5b4103fb3fe2bf608fe9075c25", + "0xe6ec4893fa4840d90006defa51d5599b5a164f0e19c54a624430b5e7be1f6280", + "0xc21953eb5683f71adf5e5229286e6167c48dd68f2599d7cc35817b4b9ea0dc35", + "0xf30d268431af3d017f42363da727dc3f4fb42c6c1397a2417f8a6d862131610e", + "0x8a686f06e784dedc2b9e015d7ca5232deda4df832428050361c4c24639898c40", + "0xac5ced4388aa2f66869f6c3f72de0e531787bd415c8472e1a491cf750b4d2d41", + "0x5f4bd5ed18dbc2dbfa1662c45363fbb662337f8253cb1260dfa54ef496b51ce5", + "0x67b8eb13416e83606e2b1544a02e0172a1a9c1b9cba1d56613d2c1ac4c243966", + "0x3f450fd3a47b94ad683939f8af79603cc390bfe4747c6c013321e39f6f1807ed", + "0xf7f5ddfaf17bdbf632bab24d9aa0bb6a960e0e7bf1ea3efb3b60bd558aa357fa", + "0xe00cad28e524f273884ed368866865d466c0afed78390d8586c2660944e0d007", + "0x370dc3ee72f58da1a1cfc6d5311c688f171251c46b322d07f61548c41948ee36", + "0xd5b426cb386ed0f0017206e0c551cb2ef9f3cf02a3d94f68cb499f8f900f740b", + "0x837bbfb8d1db4e394c5917798b251d7281e4e1d024d95a0f8e8963ffa0a3fd95", + "0x2e7b8bd8121d24134418f88bbf49f8888357fedb1ffe1f928ab0ed4d3ef96a1a", + "0xa695fa51c83d2eadfc3b3775c200a8b39a239aeec091b281a022c9a3aed96b7a", + "0xff4ce70579c4ebed37684fc8f2d774cc358ca29a54d2520989cfb66444a4449d", + "0x7a34a4cf28f43b160218d77f742251b92f8ce3b627c23f632fed544e9234b2d9", + "0x67a36d6b2f04573dce9a2f0adc37bb9922ab038d2e706330ab6bf72b60afd88e", + "0x5c81c0bf60c07bd82794389b682be408a09b34dfbf016453a174229152e0b763", + "0xbc48cdfd853ef43a5982252eabd16b0ce575690195fa2cfe12a66fe10b3555dd", + "0x2125afff5e4a9e2451df3955e3bd17c8f6b10e628f8c3060a30ebf6bc4c616da", + "0xcf447b12f03d41da20fce5d8046559be590173f902e96ebf3c9b037398fae548", + "0x58b29b2b214e0c58bd8e71fdceca3ba0825bf7614a504e7bceb87c7f13ae41d0", + "0x1683843f47ac40ad0ebee6ba68a87894fc94e37a11433882a8d9363bf7bf4b44", + "0x17d702c3071014ef41b20d93cf42084dc31db7c97121f2f41e1b0a8ba2c7d557", + "0xc3f57d154b1047b3cfcf25b393aea31e0c87dc20cd601a62fae58bd56158e30f", + "0x1034d9216d4db99620ed2a256c454cdfd9e803e1c066eda49bd2ba1288d59d2c", + "0xb4f23a426c5458e52a667cb01c734d6d7473cf0900139da17d355cb679d0406a", + "0x16b7beff5ba9edc9442bda4b46e34afb8fc1ed917d226a4beeb6d9d2410d8fdf", + "0x3b2cf0a7782ef7e1a1b4590df0930c44ec2053ec2f519612b0f20f6e48f47107", + "0xbde784b24ded1a05e6d650b238021e904c72cb35d02dfb6fce107925ac947873", + "0x7a42213f3c331c3d183703dcf4e7704b696728c6de4296161b1fe73c78277a01", + "0xaaa0c71970eee0f71ee064dc6c908dfa1d2c0637983a18a78ad6284a72a5e010", + "0x72f2af281d44553d2cc0645c0b1a01a9a089c282344a4d2d2e5271594c58ec3b", + "0x46c6cddfaaf1d204e735c4804be955fbd0c3aa2720a6d40640641b4e777b18e1", + "0x7e52fbfa76e745f3cfd6e0e0620e7597afb4cac20374e8a54c56dec4fb1d040b", + "0x69ac36b338093a55343f7b1e3b2288965e7113f255d34add5d08211932c35b1d", + "0x9cb03dc2371657f840b5da9fd420c4202176168b1411fbce0eb93eec3c342229", + "0x14eaee01119803c9c427f990418126a03d1ee9b829b23d78b11ad94e29f92c1a", + "0xfee4f3621e875f9b69254865849a58538cc742e79843ba229df2a179bceb5b82", + "0xdfbc9322655f9f2ab5e918c2dcf819f0b4d6de07905dd2f94607e3b564275f57", + "0x07c42d1a39c3fa351ae4aa0adf903c39f3f7ba020776293b0ea5250b09c4cfcd", + "0xad6101974f08962920d9edfcfe8bfa4181d9465c1a571b128a5767406c7c890a", + "0x9f29341ba8b368f9c4dacb12094979a0e9bf2f6969c5262a880e974ce98c2aee", + "0xbcb3768fca1e380de80628bc55e911aac7a3e9810794ab9b86fd2ccbf3a727cf", + "0x18d8a90af389f112f1229b591f3898ea5a0f2a6ea46eab7aec3c99d82ea40760", + "0xfcb7860baa54275ba72b34069fd8874ef29a22331b65586671ca2ce88410cc14", + "0xe8323d318b6d03ddedf163b07961e747830f51a8b7ba90ef4b568305d5a8589d", + "0xd7d9d5853392e3cf51e6a4b9b8d60e5e1eb0e00962bf70270ae7f3a64e2efcab", + "0x2f6cae0f3f4facc6d5b1e87f4dfb2698211cbb6429c00af32af1b8963aab2750", + "0x4fe11c9667cecc0cb8ffa78a2ae76cda09adb8c993746149bc322dd4dbb389f3", + "0x1d7c6bd7731617983089a3a450e3cabb5c9e48873a516d08646c9b90ec152615", + "0xf3cb5662cd5414b486fe8d664a799550957422ce0b990f36bdbd9403ceb9afbd", + "0xe0da2757036de2ef8539c522ecaea947e47b351f68a1426c86ec621ed4bf54cd", + "0xa865a7275662e1f977b260ba85d5ecf1236fba2ac01a69aed047b2d261ed2610", + "0x780cfe59c907e3db653c573888464c41c4b8883875fceb57501f60ea34fb1322", + "0x754f80993771441ad0836d84a0233bfde1a4fc0fd20e199c1a0b6a755932b83f", + "0x9253cdd043387ddae4da68098b995268b3983a17a200c8990b4de3c3102042fb", + "0x4aa535ff3fcf8ca9ba6ceabee3d59fedfa3c7632cf68fbbd3743ea9c86686fb8", + "0x4f5110933431db2c0880d9d4699e33e8f4bacc31e4971801ad968cc25f064d44", + "0xe4443aff0965d78b747dbe5b7e92b03b4c1898e7fd9911177f3afc3f8e765fc9", + "0xc7113de3a6ed094a63f9d1cc5f68d29801ec550d8dd48fcf1296f10b73f97988", + "0xd707b5f7b09c7b264e323df29236aadbc03389a9fd75da07c73b9eb76ef928ec", + "0xc671f6c1003e8a2fa46a0f6100b1ebe5fb4657b8a3bcc8c4190de8a5770e2bd7", + "0xa1f8030d4bb2d37062ecd95a87dce8b3ce7bc7be55de7aa1028adcdab436cb96", + "0xef9a06d2dc5c209a7f7747128c22b17c2724d62b655f07b57fbde1ec5926a168", + "0x82b15ac8a4341283ca4177e0e7b89378367e205ff8fd59e3e43439dae8d6101e", + "0xcf641779c36577bf02101d739b7b1bc19f1788b22d72f473bb4129a44869c26f", + "0xee111a9312dde0a65002434b38bac07e127167463068d047fc95eb53469dfa5a", + "0xc21dce0be4bf464ff63c59b104f3a9e8ac9a5900cdd77b7fc6676e4e2a17f260", + "0x546772808ee95a5453a95e581b86ccada861e2f37840de932c70ddf65450779c", + "0x748dd0b051d0dc1e5cf18584c1111b1fd7648b62d0f340539eaaf2ca155e292b", + "0x668719274b07db2b66d0f2bd7e5efb6e18455f25e49b07bad9d6c046ae8543bf", + "0x305c577aaa37c8f67c631de5a2ff8833841daa6a1f52e8f860e7b6cfaba5e921", + "0xa7a197c39bcfb74d5f3c523de12af1651b76106f422c1f52fed35e6628749804", + "0x6b46e5b4a447ab9f64a529756a689db73706c626a94b5fee28415c33c0175e94", + "0xedd9664015849f4dba53c83f75e8f86e44f8b79d3fb9bd48e526cabc85b8501d", + "0x218bf5e9a2db20afdbeb167f75574adacbf64463f11665f2b8be2b76d741fb95", + "0x9f1c7175bb294b7e24a5eb61de4da073a5af547e7dc911c9b05d98ef64358d58", + "0xd6d859b88c49be0bbc83b1d34d7c87331bf281136146651d3320ad49db320f30", + "0x3b4ecdff0b3eb94c8d7acc0e101b7fbee9aff87992fb2431fe2c4d9f44a394af", + "0xd33de0cf69370a33f13d9d7db35e3490c88dec0ee23b71ed040338049616e274", + "0x84d004e9a8ba6b1bac42e8d6bc1253ff21b47a1fb494e5d19caa1bcf34b6c22f", + "0x71057ea68aacfbaa3655aa22c75a22fae502a9afce8aa206a220d96654b9d4e0", + "0x8a47b01548946acdd553570ad9b9bf3c78bda4f96fba851ee9b0a94b355d1c55", + "0x53b7a7ae02459b17760ad47f69dec212ed628d3fe856af16a0568468e7a0b752", + "0x66ee4b75bd15f446fbbb3f1a9f0f3a159b8f6c66f708917156d7fee5fe64e6b6", + "0x706b81fb39b3e09eba9e83250f2b3e2b567f9fb1c397125fc0157e346d5ea352", + "0xcca91f2ce2b51595cfb86e0a7458d45654f61d35a66e49d25e6dab01ebb350c6", + "0x4397d4d33ec5ad07b3a583e9f39df02f5756dbca92fbfdfed59a11cbcf9e08b5", + "0x88ad8498c15ebfbdec6b1f68deb7515746e5c110910150eabadaafcf715a50ad", + "0x715d175a3badf17771c686793223fbd837f2579ed674539eebb0ce1244fd45c6", + "0x96acfa1d0cc7475359b4f1ee596aa2975a87f314e80d4baa0a6af7c7c77bb92b", + "0x26b4c14547c255841bac2852456f386e8addf8cd8c45cc9f4be0377e05411bbc", + "0x124524955310b1a35fdd19104b6c0bfef503541fa55d0b7c24efdb8d0cb33a4c", + "0x9806202158a5a5421e94f69a904670c161bf61ab1c41bd5d104ad9ba63866067", + "0xf156a5c71bbe49c45f91ec3185654ef8cc446e9d18d2ae6d51ea0f0409fc89b1", + "0x7003d7fb1b01fb6e036fa33ca535bcfb836415e7661277634c47c628d81bc140", + "0x6f23e519c11871c12185c1af12b8840ede513e28877f7e860603703b3853b14b", + "0x3aafd215a348dc20c5ee5444cc007cfa0e90157bd33c8a4c4de4fb5b7a231ea6", + "0xe8f6cdda4ae600ab617fb40d96d0b2c13ead6ed5e36eaac9f8cff9df918b35f1", + "0x75e63daa0a330a4b52efe0e0e447b345622fe35586037ae88e6e48a8b544a087", + "0x6c4c8865b2673508e4c62dcc711e9886e57043d758a60787c6241578670550bf", + "0x21ed5b252ba5e9607045ec6ec85455db4615a1fc43e22138ab3a087c5e6236ba", + "0x2e2ccc6f66368ae083905358a182b0cf3e85330dd2a3875a846baba61c9be3ca", + "0x4a8987c10833a298ff22cc199be4816aa05f25e39a10bf007e72790081ccc26c", + "0x7a4b05fa47d37c86aabe456bda0ae7bfea3b28a375697d4d19ea2b1676425016", + "0xe203aec00f8bed45f3cb0911860093a5fe228c22476f189f2dfe4621145f49ba", + "0x7b2ba1b4da99ad50a33de156eb412d0020efc63c85d0840af6d9ff9199ff7dd0", + "0x0b84a8362a67c9cd715fbb09e0a48e046afafe8814ea7e1c0bc99da9ca670bce", + "0xb9457e83e503f6b65bd357b0c1cfb655b4c157e213c1aa2e4ebe6b88524c20fe", + "0x401fa17417f9c8f21156a3e660fa2b0a27eea8fb287bda37ca309a3c918d1c91", + "0x8bd1e0e83f35107a65777a1889afef35f2d89e70e9ef3fd56a0fe77b5a5a07f7", + "0xafba338c738de0a748fff79650392894482f094f79bf0c88b871324a6db0b1a2", + "0x40e66643c2f93c60de74a976f7f05d753ab09d33601cc1421da1e987378be84b", + "0x4a5d0c268a86af032703b688745b91bde7090b4e3b245f235056b5d675760685", + "0xa8d7233658eb85c4a309293e35aa9768768e78b9635ff989b4a5a1b64f6f26b1", + "0x7b30cf0f31a942afa35ee2b30bd3e67cf0fc3c366eb35b1e331ad8805e9e0d40", + "0x5730206b218be1da571ff8022b975412746f88606ee3014626a03eac8893deb0", + "0x4dc767b54a2e685d7588f6fcc1468cfa7c7e47474297b29b15957b2f21fb90d2", + "0x528933096ece3ea9bd4b3e0fa78ecc95915eac29b8b608af3b18eb7fd4adaf50", + "0xbbbe02a2b2949c73839afa56e959b23d3dff141776137e5e804d5d37a69ecba7", + "0xd8c4081e5c0ffe7797f07db6e5696e04ff097410b1e45a649bca43362366bd87", + "0x46402c1f08238694bc32bcc396093230cd2e522c54dbf7d00d042986d22f00b3", + "0xfcfff397df45c333b4fdf271b63a4510c45310a3c9cc78b97b867372203228d6", + "0x6d2350213ec1c6a79fb7dfcb5a66f065fbc41d4250075d81b7647e4db991543c", + "0x393995f9a4a358d13b5fd9684510068f9fb86c71f2382230999bb36b41586a56", + "0xb3b65d3c835ed1aeed86f34117431fc46d62ee2209db054a5e04cc81c1f795fc", + "0xd1ed46b6e64544acd6f9fffb126fea4b74de84664c2b22c760eb89878cd44ad7", + "0xf21c944b3e41a4f630ad5452a28633c885427b386ca81ec9814ca14bc94bb2ed", + "0x54c5c6c093bd6cf2cc72e058fbeb26012d71fc8e2bc6987fbdadaaa48ccffec4", + "0xa2e79a266c6044703233fea5d0c31bcc22ae247eeb55a982bc2e1c0c64af1468", + "0xafd38477bf1cbad227b489818e335a79d38bd052f7957efb2d07b9adaff6c68c", + "0x4872bf318a2066d5338e31929da36fca3e2390d1dc8dfe88eae5ef854b81bf97", + "0x896b1e0fb7a6daa96f00f7ef633ad67bc4462c962ec288d7f924c64c978f21f9", + "0x0c3617575c8a625e7fe35c30312b147be400b2777ac4b1c0fd84ee233175faf1", + "0x6f47126daaecfa7b84568c26b02ee779763c9f63b4b7f5cb0cf0ccd4a2c0a499", + "0xedf2e0e03c0d321911693c1554254d82c764f2987dcb5c76a4204b1184906abf", + "0x5af810bb6ef491ccccf2dd00c658bddd02a1124ca26be59c97a69199605a2d8c", + "0xf8a597f22125a6f3fd76e28db6ca04fde9f5eff62b78e162855b9a48c51a0cf9", + "0x9b50cf0abbc883c6af57fb52c48defb2ae67f77de2f2ef5aa4fd42f6236f3f43", + "0x6eca9c995386aa4f161e6f4c6ff999cf6bf1bb4184d9beab567abaccfce9fc1d", + "0x7d7dd300658f784ec68cc3021a54680ac5767085657bf87ab6f76f05e505e6eb", + "0x1eab27e441a43a3534507ba0b5390a13c7df373813131b09b2eaabab179b5cdb", + "0x45efe5848f21e2b4f670bf06f0067fe453eb29ef45df102588c7b8f902005066", + "0x086f17e6047e9476d828eab4ba0016e3a4a0f51f25eace2c27445b5fc28926be", + "0x63547a7274cbc857d547291923cc9e507e3f4b6fe85b1ea88a527674f15403ce", + "0xdb0d2c2f050c4235e9fd03de4c491e09061ddfb4e55fda8ea25a8c8f013193c4", + "0x5f5bf14f72834ddb7ef96affc52b3461d0512fd9bb0337313cb7cedbfd858228", + "0x92c4250a5ba9ec5890c39a608770d500ac31ae5da1cc26c05aca55a453e15a25", + "0x4fb2c385632f512303dd76f4c9a3888837227bbb5e5b949a7b9d74906ea6d015", + "0x4814397680a72cd024c3df1faf854d03c0d308b74c93fb846e620de95de7bcbf", + "0x068512253a6b5ccc302e494d1b17ab082f2ff4ee710c58d345d6de4a436fc3ed", + "0xbcba2fe1b54c6fbe1438fcc26e955ecce58c5f30f4f19219195a413fbf1c6eba", + "0x29ad9a11da3f646ae4ef3a5202abab2ed8a7058f336a6039a5c41d3619752d6d", + "0x5fc2a5edf9264de88df58c3bbc705b8e73bba19179d097f414598bd4b5fd63bb", + "0x9592c969a049ac723d756bd2ffd95cf599087a1da14ee9f472ca07e7e54f8ed4", + "0x735ace051a5e3896a9dcc788654f95cf0dd9cc98eea1b5d8d7340f9e51eba698", + "0xed5ec9f70d613be406c237ab7e8e2480c7a81cc666316d984bb3f9c67e10d6da", + "0x3b8248b4de2768d9a4ed2ce07c8735103b480e23bd17ef1910d75d29c2791886", + "0x2a9ce5a8366862e7b790d865b0406d9d5d4013999f42caa9235d4c2b2813449a", + "0x6c67c00db439fbc9d548cbdb57377064419ac47211be90747c74c13b29d4e562", + "0x1695a7ad7e64d438a9b749b07180910a7af207bb46063a92d41be315cecfda67", + "0x6fcb36c8b8ae4d6e4bc21fd14e80dcb402561a011fb4e71408f05807b1141f49", + "0xf6ff3dd9e40b6bdf881654e12fc9959a928bb7d83a81189db1520bec70386ec8", + "0xf17f8b88f04772598eb87c8bd1b3a03f5d96ac68de7d36be6c1fbe5fd4a2ef4c", + "0xf5d9c9e25075f8ab6c34e9231d36becfe90df0ae6bece4ad1847dc4ea938ede3", + "0x5d409a230ffc6a7e149e94b0184bcd00eb8705fe173c67ccf4f81e2f0d3cb0a2", + "0x80647dea82a0c218462836c14cab2550f558391a901a708d7e4e6c28b4b71869", + "0x4ab906af7910a57f1f4bc338d5e952a899ed256e2a28e1947890a372aa29814d", + "0x6e6e180aac3ebd616af90069674ce54459f169d33d30d95d98351259d90a38ee", + "0x5d30699b02a45d5cafc14c945bbd208943ea83ac6a10229c199a92b87dc0c76f", + "0x19c26fe48c497a4b64a4d537eea9646cab7704dc28c46fc3510a14b226b9a690", + "0x5ddc881ec8fd1bd34601f06a5ae0cd23680e2e8bf12b78df48a5f86ed6e96ab1", + "0x39b933493defd81502420663a0c85df3a6cf727e4270816bb3cdec3dc58bc7ef", + "0x62a9e911426f267561f84210d7356069f6168c4e7afb9aca4a4a70d18fb34ba1", + "0xae792d0011eeabbae89f6de39ad44f0620e50e5ffe7392f9bb792a966d1f83f7", + "0x737b257fc55f1da44584687b3cca4bffda13ae014f089e75f0c75b0b2d08c426", + "0xe923546185355abaade908d18f3223bb9c404c4a399ff94419c3a5798c90d9ef", + "0xfbbd3e2dfe2e9e6f985d139dbcfa5b95da918acbf49de992d01875bd44b61e28", + "0x781d9962f2cbe94e355b93e4c0eb3a3de44d9779eabdc3c6d18e7120b3c0c01d", + "0x2722229fd2cef3564c38d8e4120a6ae89728ab4063c8199ec098f139b83ee0f2", + "0xe29866bef5051041d25449f334e4ca246df606c5d7c0bce7067c6c98cafd0534", + "0xe0320de1a972b563113eddbecfc90fe902f2ca80befe15378c94bd073b44eb92", + "0x9227e1d6c68bdd60cd0deb8ed760eee67af6623c44d05136251d89654f3f2e7d", + "0xfc3c7dd2d36ca954545f3a978cbd7e4c413ae38a0fb5cb59b84329b5f5ff2347", + "0x934c332cb52521de4216c29e40601d3250078fe9314a364064692daeb38f71a6", + "0x77aa1b31191caaf80acdf5d411c4b6b834a6e50f2f0ceb17e1f06a807e3eef01", + "0x43eb0928a0ab9a29ed084cbf9ae75d1e5593595d55fc8a32151bf56b9977a1dd", + "0xc6f4fe473048728c5031a465c9157e38c72367c7f937aa9633768b32839e765b", + "0x21dd6e252382965adf71b94fc0b9b2e6e5b0b9dc9732987e1fe8d8610b1125f9", + "0x9808b8c9e07babfb30c120a4a7d3582cf4259f8309e586ad42bdb9e9cdd3dbb4", + "0x72ec40a055dd6c5f21333f9540bbe7e38f28f39f90204f6f87f3c94faebabeb2", + "0x3a04743cd849a1a48e0b012f39fa4eb690c314eae7b0500ff1ea487a6d399734", + "0x484892e8d3585d871f7105a49cdda18af036d787b6519f9d32f8dac5a3eb9546", + "0x3a73f64acae91b70d39cb20c1ace35547e733b253b47339a1c47ad0841c7a27f", + "0xf33014797bb0e339f2f0dbcda6706dc6b33c8491cb9ef777ee2cb88b8fd1e35a", + "0xf94ec9b178e1e287fc2aa53d397960e89485ad22f306bdf0226212415900648f", + "0x8aac6aad1127202909e112df54be070e353fb9079dc5cbeac146ed09faabd4dc", + "0xb8fdae091491634efcb9b2f78f1258d401a9439d806fac04de4a0f9503d9259f", + "0x4e872ddaeda3ae79efbdfd3ad8e5ac3597003a933aa793c50fe74fb59ef43637", + "0x15293110604e842775b59198cb8dafbdf07b4069fa0c3e2d61ce6665ec8f6742", + "0x7423d6d010ca3aef37831e003164b583c2cde4e859705ea191e6ec687f08cc49", + "0x73828a90a0f97e5bd83c4a6484f84ef8af04d325b739a2cfb96b8cad36717b09", + "0xc9af1d054e4ba3af1002ff0ed63fc361be99f8c7bbe90fc951357ba28fafb8c2", + "0xff2849e97d79e7c25a58266dfeab64f512ebc57620d45d6f5106a71fa43063ec", + "0x98da87856c0aae3af6dece2efbe0a2f7bae295ece2b90b633ff894e5c83fd407", + "0xa17f5aec76c8f4aac84741baae18e179ce5c1ce0d23d3e2e5b4fc7f79ee91171", + "0x79c9a766323f5381dce7241fa53da4c7fa018a43556352c54b52fca209f3ee37", + "0xeccb07e66f967613c13a1e867f8a96bb2c96b7c0347e4262ebdb583eca48e71b", + "0x36c357f0249aff34dc519f420b77fe14357a009022262cca7f1467c2dff7d0cc", + "0xd52a496e2c176cd98b94e8dd4c18a9651f46ce47d70c51b21e5970bc7d81c96e", + "0xd3fbff9d80c163f6b9d4ad4660f4504101e167ba866266ff905f8564ca7ffb68", + "0x321b832e81f461e871bd05e6847f8548825464425036a1a92bc44fc30961fab1", + "0xb58be0aa640c7047e2b27c6044dfc44c216b4b69f48751686cf29e66a8dc985f", + "0x2c9153f20a845b8ec8e70cb1dba8436c7af618367c3344130defb1e7c39afe1d", + "0x6d129dba3e7c6e5ba8412d9290d7dcbd29b36f3e93eee6b6d203740de06802ca", + "0x5f8573d1de1c9b4725fb639b565a2ab6dc79d138c3d6495325e6ee609073965c", + "0x5f78ebcd3f73da424734bb2ba0c711fc54be4f21f29afb1c33af44c598d31dd1", + "0x6b48dbe0e509dfed74f60e16782d268076e53863b9f86e4078c90f4c6619b644", + "0xec30ba6ff376fc1ce9f4b87693e586b5fef2cc5a5ef26726d8e756b3c8e28920", + "0x8ac0cfa126e35c8dd715bb0ce13bc70c8d55c34be0abcb85576393a460762659", + "0x8825a63c211a92ba8f8f5aca7a27d1921df071072467c88ec9932a41d43ab5bf", + "0x39cf82416d543f45afcc6aa0cf68522d0d5ed4f76b07b9f742594a88309b393f", + "0x105449b542eb5ab0b1ec7ce69c5e8bed9a72b6470b644e0815f15c6d9122663f", + "0x10fd8c442d6d44b533675b937e5defb004271a87d4ca3b238a395002da42adf9", + "0x390a40177f4155c30bc10539a54991f4759ecea69c31e9b2904743834bbbc618", + "0x0f11e934cc159af39a4b22bcd6817b1abc21bc6fe81c442dece1c178d695787d", + "0xcfeb9c70d8e2d4e40bca485200c0b5db1152d9440237f76a58d4cebaf43cb1b9", + "0xc45c5247fcea2312642437f90870b6fb4b9927eb2af3adda30b5c738eefaa952", + "0xb6886cd5b6329ca5f5e36d1c49b7426b1a20d3e3455f660e662128193b6e1a32", + "0xb708efc6f2f6ab093482d8b53483a3d8216043a437da09433ad0eccd4c9d607b", + "0x12b76069143a66c55fa3ba54a27e2cf51a94d8300a6a6a317a65df345a9d77f8", + "0x0d9b6dacca16c1be986db368dc92d652984da9aad149ba7c22831ac94719139b", + "0xbe298f54460f273d2106a102dfda3e86d7eed783bac4ab88d8caadc0f3116ab0", + "0x82fbddaa5cf8847d2166d40f9fef5fad4933bf338422bc5457e5d5c29774e5b3", + "0x2a75f2442f4ed494666f48168ebe8620819d97f9749b279eafa550f20b1b622c", + "0xc874be785abc89e0fa92d089889ce06e1b2297f647c31cddd24d29017ba74b0c", + "0xa6984ff3e4f7ab1da131668f77342bb0182cd23593dded5e487c134b1b13a9cb", + "0x4293f4fb5bbd41aca9fb12f58e2427e20b791ea523fa125c40b72699ed89ce02", + "0xc316b1b066bf437d3933d7fbc8a8546a10f7c274d2ea84781d8a99633bdc0c3f", + "0xb40cf7adca885ffa6148d8008c5df235e938659d6249fd883960b847a409747c", + "0x3285b34b3e90a83293292221a89bb244a91ddf4647cf2d297c2116826c605640", + "0x465af97dbd1276496387568d41ec69961f70b382c6e0686c103a73bccf0f7830", + "0xda2cd161e715ffd3ca0eab361e66e55450230f9acddf8ee635b412807a9067d5", + "0x3136630cc6b24f59ba9c0347c6c612feb043f9fb58d1d26598331aa623fcee68", + "0x24014d00bd6ed71da4044cbbf256ef99927950736f084cba2a61046ed7c8d471", + "0xcf1824f9a407009243ade6df4e3f241dcb60bd7257d843792d12fcd42e659076", + "0xcfafe5abf154f2ca9b6f9d70a91149b01cc8fb6b8bd083e24559b860e439f04b", + "0xa4de7f7024d405f6738301df2132107b135ecf824777f1b844685bfaee6b30e7", + "0x507abab909bf25bd3907ff757a69acca54af0c21ed6faa975d20106908e8540f", + "0xd6e584b876926c3989b84151eb574d737bfd229151dbb0f653b693b2bac7c45b", + "0xed4eedd2952e96c9298f68a1f8ffc4772652517356ed4a02762a3355e7dc89f7", + "0x36d0a7f0f5ebf3c35a576ff56c8aaa1caa04dda95edda5d496381c9601949451", + "0x9beca310b79181f7695a0b6b49e923e7b67462904457df0af82c88b92fe4ac3b", + "0xcf792a534a0b5126116e9f7c9b92aa4d32083fbdb539c91dcb8de347000b49f5", + "0xd4024c9ca180adef5a9311c8a2fb0fe75e64728af00ca4ea1484548f182b5488", + "0x5517e825a0d6e1bd9ab4435278b8691ad2772b9edb581b58725483c4393187f4", + "0x9e4ae4c36d00217af787ee52862f87bd37cf391adb23a8b51fc05ed1ec3f6631", + "0xe428dd2523abc537b868bb6f5588597175a622767b600b1ed9486d09624c8ab1", + "0x2fb95198976ddfea942f737322470f9de6635f7116839e5148d3f64766f6fa2a", + "0x211ff8c237bba495c03bd6e8eea2a64f05c8a0eb15951751cfcc4c337f1cbd02", + "0x44c49c62604c39e38561c7d9285b9a2e168fa164a47c7b17f1fe83faaa3c581a", + "0xfe663bd908aa64290ccddcc300aa5f616455d8f10032af9317ddf717c94d0bd8", + "0xb04add424a6780e81e2cdafbd81699fc5ad621c666e1ab5583f3953ce8b3abdf", + "0x5f2f6958e89ad99e28e96059aa8b6e2d9518009f824874e327dbce226918e0a5", + "0x491c9e17210c2770c0cbe566aced7dcfcb6781e70a288f91d4eaac8dc4fa07a0", + "0x73651853f625c534d5848d1bf7f93433b09d9297b13d46aed9b022ddc37c4b85", + "0xb1333ff43af73637e2235f97a1a7a5f42c590cb15f93a733cbe16d1a9c187e0e", + "0xddca0492f5c36c8eba140575b4521227ad1216d04a7e60da7c9727cb2a756df3", + "0x6da48a25ef31b1e25e33b1df1c539b14e6d3837f8061c6a4faeccc861b7c908d", + "0x7d250fc602fefae7409a7edb1260f4c520d4717b881c8afb6551a89cc781efc9", + "0x043db87fb979042ae7ea709cebe4ad58028916f035e99382be9826f1236e5753", + "0x01b125ca25e2a254e0ce54e4f3da04c647ff6fe982f1df158c3caa90b1e2a2b6", + "0xec617f330285f2d4c6ad161250688cbe57bb81a5e45fb11354ac033e2fd724cf", + "0xf7cc72b3307f0ed731b990d2c10f71cf195b02f7e1d2767873c3ffc192cc43ae", + "0xf19619c5e62c5f244ef4156cc2c8f6edb6c230664e4c19ab32e1fa137c9ae173", + "0x91c313a770e9eeb92fa74c335f9cdb735bd14582b385d2a380bca534cf7a6dbe", + "0x14c1ecb6b06c18c240932c705154f009d9032dfe576ddb545a3a4cfab9968fc4", + "0x7d2cf6029c764b4c676c3a30567efa13f0fdd3cd6587631bd79cc08f26d75505", + "0x8c889efbf596d20043d654a6cda1a58d480ed2e3c3db65f51aabfd25f85784fc", + "0xe0bcdec3debf12856f3b4fc781d407a52b6b3d544b56cddf847105760a99775e", + "0x32c229b6b99b2173338bd7615a1a0c2c4fb5acafd41e332c9be7dba91b8e89dd", + "0xb24b187ffb16385b85e6782fcb4563309afefa8a7900cfdb81d024c2257913fc", + "0x81bc38df942c4c9c309f19e4fe5119f3d7fc2347fceb83f7d31e990a042581c0", + "0x1e6ec7caf14747f470d65bea046f7cc03e081271775be615905632ec9a18a637", + "0x4eea8052ac23fae83fd1fa63b328bb4c2c66277480b78ecc00132c1afa53d37c", + "0x8810dfc2084515339a0c6f1b3fa771aa0819b47498e57b3733aed0d40b9a55e5", + "0x3cefd28b10c2ada59c1bb66a832f1ce79c6d96dc0eae3b2759515839cad25ce0", + "0x8fb0cd31102c06d1e33f782fd9dd7f6f9af8e975e10fbe560183ca366d088039", + "0xbd7842672dba588021f7b395a55b949d41090039b14741ac667aa75977e00d62", + "0x7c4ceca9b53e12dcf2bd5a625274f30e2a825d5075d640c7bf78abe4bdab907a", + "0x945f8fd6e3171159a57fe5ad95e46cf93c494613247051b941bf4ee7fd6d4e29", + "0x01e9b5d3ec0f6f100907603f591e5007d086086476dcdca849996b98089b924a", + "0xec9545ab618538789965fd828fa8830ac17ee52489dcbbd71b296abcf12c11ba", + "0xdb1466a3705b6a035fc7794fafb497fd2e7606b003e73c6cae16b8d9b2aed314", + "0xdc36ec38da93a79b5a1e70d1cb3453f3ff324793d2fe64fc1c4e8fb1b22e7f29", + "0xc1f2a76b96cc31541362b5d6ae9271740bd540631b4f3f0274ecc5928e17e10b", + "0x4a5108aa8e22f9555d94caa9c29b9793b4a97e2c7270b8e24b2b3717d9efd8f1", + "0xc8938a2890c4f884837acb06c4a3854d1c03286d58d5d62c85c06e00d8597fe9", + "0x61e1708488fca9b334a1682d4f11bb046b5088151a7333655c733766ba0e5e5d", + "0x75705cfc2a41a44eada0a51ad75eb93972d84122658c487803287235c0a5a405", + "0xd818c5f5dcb79e84b2b41341261bf3e4e97f1bcbe572c1eb5be5f7e3eaa52db6", + "0xee9b8a62f9bb12306b38c129ddca08e1481db588b6e07b45a7defc3750cec078", + "0x1bf73759029c056f0e59b27a8d05714c916daf36517080e724662bffebf9e380", + "0x4ad981191be35ab37c559020fd42db86f57c56f51a902017aad1deb2d71debb8", + "0xea76176e1ae162188a798fc6ba2426c5e39b98a2832ef5f730c06d51f0b6d71f", + "0x1e425a410f888435fe7c1d6912efddf8ddc3a763a136ec730c31ca3ed0a3c162", + "0x5f6ba29d31dcbaa0220a7c2f901b987e968233bf19f398528e91973b421aacf6", + "0x935266f8976c34566a762204de924295a5203630aac2d2bc9c9cd0cc8286819e", + "0x323fa129d881b6406662cf69f01c720060a13cb7c93ea7fca3f089cf47d1b9c5", + "0xe17499346fcb6ac5f95e10c794f05ad12ba85d201c4d9a2571837b287dd90fb1", + "0x8bd288a3aa8be55687979fa9d94ef1d1ef8a0036bfc5615419920c6df3c31bc3", + "0xf05028fd3368402e82d4f6c6a4b12e622b048a612f80567d6e874541998b87b7", + "0x7e35b77cce743749b57b7614bf4f3724226ea82cc1f76e6f6232ef25b42eb6e3", + "0x58cb381e320b2ee7ebf17aba08316d86c6e8f2dc038f8fc6839e94f16b411a3c", + "0x24c1e91b745127f12bd8603ca59bacde6fe1b990a1d4de58c5e91c29da27e371", + "0xffb99ea8a8fc58a1c7e33ffcc199519165a452ed9b87196cbfb48ca23198e571", + "0xce37cc2df44d4308d1e5b846d46c9d7f2bd78f6b771b1eebcda1142858cbd4e9", + "0x0babd6dfc4f5a3da90ffd6f74297db7ecc7964f23bfdd3404f49c47cf7019856", + "0x97ba6463ece697d1b340dbea1e4e51e2f59e1f1283fef71d2aef12060b188b6c", + "0x3cb4d7dd238435f316ef70fee4bda79bce6b9a333bc10a36c2e58f7fa4bc24de", + "0xe44502680a574938a0f483c72cf5843ffc506bd2d9eae270bd108a4b7dd55422", + "0x3c9ef69fbc9a23ff7646a9d99f27584f3969b20bc56249dddc7f83fef68742b9", + "0x555a8316eb846760d2996998291e81d5f80bb0d8db71e5c02c42791ce83e456d", + "0xd4d68b9b231fa41e4571e258fb5d4770e843b3e50832aee6c7e327a568c062b7", + "0xe0a8bef3a6755a4d50f379f9f324f0404fe677372f307fc67ef2b938eedf986b", + "0x57f32b8c263c9fa6e3b5df8603307216469dff93a400290cc54f3a76b54a2a75", + "0x3749d954f6fd6dd710a0a9b4abcb0da071b3c50d125206c0caf4f4786d590d4d", + "0x58efd182fb42171c896accf391b30f1916503f616102251b9dccf2a45a823c5f", + "0xe44810336515f4f45693cbc57ad0eff2105d70faca32097f7ad6aa505c4d3b67", + "0x0d720fe2f29af2607ee5582016bd0f122f63d0f82a84c4931446a184843594dd", + "0xb3106d35e5a904b6d460ffa8cb494f6a95045d717b3f532847105bad0dc5ecc6", + "0xd1bcc88ff9f5ed1b7625e7242ecddb2b615401dd8fcd01c9b9f03a6d22d144cd", + "0xd4d4702668cc3673bd4266be291aa0f25e8ff835df3c43d556df01342986a279", + "0x9fb62301f00d441319f81de73fd49fa1126a29b3a11b022b3a92401dcea15772", + "0xdac3eda26ad4eda3d83c0e83d65c74ca4c4c3ae47eb4e5e82c6b315f80266125", + "0x7b24a259081a547d55e9af822fc54d5dc6f69ee3e961ebd0a0248ac36f6e25dc", + "0x64e96157f5e4be77c9f50df8ea9c518026ce1d7db6adc52189c9354922504635", + "0x35ee981b1a7d307671605b25399cad71503fc9ffc00d2f9ca80e868901e9c269", + "0x6965520591a7697f7c62ce4aaa6bd90691ae1a89a5f8e29237ce5241d8003636", + "0x30c305cc886b538fb8808be71bddeaec3a1276986906b7f028347511bbb653e0", + "0x5f63caf0aba563f62811903619a10786761011d2fa6fb58e835b8dcd5cbcb3ff", + "0x6d7219f08e8288e4dad53a7fe227951e81d9ff2633bbfa636a3d0b147b98342d", + "0xef315cb919bc5537bdc9bc47d2dda7442e4a372c74163fc2134173773ebfd7a6", + "0x83016cc642eb5b55b5a667d36acccc35eb9c33cec2caa28ec263f00800bca2c1", + "0x0c855426475046350b58fb7e179202cd794f482598d73ad05bb0072774561493", + "0xcc8dcd45a49fa55fdd2871245cbc611613f203203ae4ffdb1e647e7143b8513b", + "0xefdb25f8a05ae4c869bbfbcac9c302f3dcd8a917eca4d5807deb09833e876820", + "0x055646d6adfd108be923b275e21c07162227694df780512d0dbd7a0b58cdda91", + "0x4abdf1b201aaaf4724e81ff29e8d48a223f7b98ed6d9c9696375047b7643280b", + "0x929ef44a9c004029274bc1dbe13b49bd6452ea3a3ee6d378dc296c9baf0b1e9b", + "0x909a57470dee2764e5ca646d6711de3908b3b35d98e73f67adc23a3a8aa3c48b", + "0x42e5bfa041faf65f224d7985ad464a526a18fe591a156c0b70df9d397beb9aa3", + "0x241d0b24f3c0e08a17f10d579e49e72af7d2e4d0f0d621ea8975d50a3901950c", + "0xb1f3ce2968fed1bfcf363a031d79cae0174d642e931862adff7ee97f947522ed", + "0x7e4db35d3aaf0bdba5cf1d5465f77e6c927f42b775e8ec2bbfb43be36270b5b7", + "0x7995fbf9d69f7222ddb9d28bacc6d97c61780755e933d3dd47998f1f3747aa32", + "0x31317d422307751b59eeb45270518af357bcbf7ef413f81c8e7c6bd48d79d696", + "0x5c58fe54e2781cf91a9d09e080a9ae5b6a8124cc06275aea65ffe422567aca2d", + "0xa4da628ada51d57b378717218e6753fda428e2b8ce88859f37837b4c2fcc5076", + "0x9c9f744e7e3275808f9913767657af8a33a7717e45adfd84305cfbcce328a065", + "0x1381182d1b1ecd75969148742706a27a044cdeeb5cd984886945e5de5f3311d5", + "0x71a4759a9096d67a4061ad639ea4ff7df35c811eb1c7b10638aac889584567f2", + "0x1bf9536eb1692291213d4f7f340647025c10793c2c84e8e775db5cb5afb5022f", + "0xf2af02ebd1cf78bf30a215d80133c7d5f7361a58b827efa23e940e7c91430af0", + "0xa90ab1a925b660baff138369712be90a6cf8ebb658ccccaa9e8b0305adcb4ab0", + "0xbcaff27b022e0873b10da43c78b1395f1878e2ab1c8cf33368988a6060c6132f", + "0x6154955bb4a81d1b96e618ab29a53c393ec78153a733f90227c9f83683131eeb", + "0x451b4a606ef40653e1ccd38b07fd4e8efd9fe796e01b5a5772ff903b45042187", + "0x011e748c7fbb39346bba2b3235c185fde946d28627e2f6ed39c68076d5e6fcec", + "0xa849d075319c4f0cb13f3115ab99e0cdf0341d719f5c65a36b100ac1bec98826", + "0x1e61220e9a615b1ec127001aaa19f307c268bfbf14bca900ba1005539a7ced1d", + "0xebc6254608585c487baf6e312130a06468551cf4ea171335480881f42ec626a7", + "0xce073708172f6fd1e6d792f4b9fe088dc06e164422c5e85e4098c0c8672bdecd", + "0x8102653797d93a7d372b1ddbd92c8c8cebf79fdc8213392668d62181c2639a48", + "0x2062a79855e50c96f3eceae62ab0f873eb3f051f66931efdb00649f07b82061f", + "0x28302f6a2106296e587b03f2f0963ae9c8f8eca56198f7d5e0fb52d4485e1da0", + "0xdb69e062fd4f03ad8327c3b33fce7efdd2a1455cb9c1c90a7e2e9127b12ca041", + "0x984232b5675edfe8312be559135281ff49be1219e3ab17e84560221368166aae", + "0x303557f3d60ebeaa591cf88e583c366a7db4adf1031b3de9c8d3381466e15b7a", + "0x2179d8b03104be3b8d2e6f4ab4c6b9851bf85ed4545aee93fc40d3320d3b5d2c", + "0x708174830261838f9d87279a51c4d65814f7da2495c1a7ba1eb867ae7217bdce", + "0x5c5b77681b0d9d6789aea3494c60571311f2b6690de38c2e4c2a8caa738afe5b", + "0x68782d0db788b3e7441e94e4300a93c50d641c060677c6ac98ac50c69ee972ec", + "0x3c3acde8f5a99d8e131d33c7d55ed4415f0c230ed6fb711627b11e464faa3264", + "0x0289fabcc6d32e03cf75d7958e22ae050c8fa6b31c03221d78ddab3469d9b95f", + "0xf10cc55e619ba8b9aa5ab92c272ed1459020ae6f43e45fd9d427075d86230c36", + "0x20ae1b4f3c79618339a0f0627919ab94809328164ec1dfa6b9e1f556e68ce770", + "0x071e6f74436830ace1c6bca63d915218d8f561e184d15cd83ddb199319907dad", + "0x7334a6ac9991ef0876f0b4bbe18dfc407e748c65ee79bcf114c1a2a71b46f41a", + "0x4f44e709a1e59bfc7315843f399add75d5c1e8c3cbd0f485afee94e1c4cb0d33", + "0xec0514297634ea605be68932d68de290e15306061e20a16b2e3bf675fe573bc8", + "0x9c72bdae94b6f57b594c11872ee21af41c704ba1addfaf8ec4d828d6ac6101a7", + "0x1d1a60f27879b14930bb0351e39d3d31233e7d55f3ecae5c9cad4affdd2edb67", + "0xff4fe06f62b19f1e6079955baafbcf5b74627785b5edf90cc49ac75490a07f8b", + "0xcfc332e8af474ce72548c5f0fd50d4e6c10858376b0ddfb706e99703177b31e5", + "0xd7d5eb515bad41cf09df99d5fe0400ecab66ebcc9f7af53ff8cad256d9ad2bea", + "0xe6f7024457d9e945da6737c34090f689bbaacd479849a7c64afb6aee85b6950f", + "0x15fff05c7ff12fb455b77b5430532011748a52abce46919f69ee0a4c30b59fd0", + "0xaccd46e8d8482209373407310b988ba3e1f39d6eb17f07861d33bfaefeab3347", + "0xd97650055032b7bdbabc7b49b7343d0362d6241aa45fb17ce9ca1815e7d58983", + "0x0a4b45c31d3a1dab81b47da37e896360fe5a1e45903f59d6ad0f0b8ceb2a7747", + "0x8b2a42405ceba8740c02c526023247a262088e35588fa4253eb6e229c273463f", + "0xf43516578e7fd03970d57b08384b0bb3441ee7f50213c2ac0d1830d43c857abb", + "0xe2aa1bc333310c27fd699455b06398679a100f6a942c0eb37f70da89d7f025f7", + "0x1f13aa876a2a348d7de6adaf51e8af65ad7bfe0332c4c9cbb4dd709dbde8e1a2", + "0xd766018ae514f5b7daddf6e716bf4570456cdd46e7a3be68c1c515f2df441bf3", + "0xa2ce855ff00054aea57559662ac95b2445c1fa2491d9f4448183a474396daa53", + "0x8583ceb1254f6546539fdd57d1fa1e3580d81f1aa44dbc875de8b0f56e5e7ea5", + "0x7e09579f21572f2ee72399c3ef67c01a5f3f27ee4a3c43e8b6f692e231fdcf1d", + "0x6153e318c7eb123db88f9afbe8ff1c8f66e1cc0e8704db45730912a8281b3366", + "0xd31dc325333526bfcfd29e50e5fe13cd696e5948910abf46e66dc73f7d271942", + "0x9089fab0aa038217485edcae76bab74735a1fd2897c30a610f5e43f1d2da5425", + "0xe193e06c904f53031be5910209b7aab785bca6b65e917351764e2f231800bc4c", + "0xf732414a066d5a8fd13241f5aaa9570e5c6285119a1f7c69063a8b4cb62729ff", + "0xe149ce7e516f9d54df933717a11040e4a9bbf8ce13c5a3612288009a99724295", + "0xf29212544b867ec2505e35cc5ce79ede41fcafd676f41df15af7f178d6dc5cd7", + "0xcdbad6c9eab35d13dc6461ffaa793b180e28085b8047cc56a5328f4066ca944e", + "0x13f5597439e924b31cc8ab8b9cce0776a8d89bdf7e6a0a306763ae259bb92787", + "0x791e0daad106b9ba1ad684994744d2ce89c6e413c51954321d9eb3d87e0ad14e", + "0x892436f41d7a6d8385d66f6ff19fc7235dc6241477d2745792bf3a38085c8d5b", + "0x68b0efdb41ac9e0c2cf0df78ff6f9f790c3c1ba63ecec6bdf9426d860952f81f", + "0xcb4cca4320ab1a4ff11f868d769ce9fbae1e98d154207acc85acf2f8dab8c4f4", + "0x3dd2dc9e0d99e9ff820f22283ccae495545ff37b6e7e89b3d721bdb5ee169eb8", + "0xad216b8e962ca5b8f388c89bdca543059065c7b6573c5c0868be031b74c2e184", + "0x36953abc02bfd8d72b7667b068f63f6c441e78938b15591440a9550ef796b8c8", + "0xbf85fd9301cb248c0e616e4297e2d4ec43783bde218ab67a7e2049059236f633", + "0xd6764c6e1f3e8d671f1cfc1e55c4d65b274fccdf783ab1b27eab1099b9f46299", + "0xe1f4b5fc4fa5e50ea8a7129f2786d7b13531d608ad6e413d3acd0637ddbfc5ae", + "0x225f99906c6ffebd2c77eda9c7b2e318740a36f84b8d6424b2f479f3e98b1fed", + "0x7850e352fda7e9b524fb1b1c04ee4695ba3613441ce0c5321b26b9cdb3317625", + "0x4913a582ff57cb276667a4eef0e85d31c79ff5f048b8b017dc89653fece5e88e", + "0x1cf357321372b71199a20da7e7490bafa5d9f837fdd3e433a68e8f84d03fa550", + "0x978cd04d02821dc54a1ae97385ca618a91ab42e9c227b5da2be433369825aff4", + "0xef0098b9b604b3bf4b7898d887b5f36ba8c196606b5688476547e89981e84a21", + "0x1c9cf750c7a5188cd346781612291b20ab07039831a77e55ed890987a876a412", + "0x6bd6e5e5f57b23bab83994c68760951a0a5126976fa9c46a99bef5b329ec7cc6", + "0x14db2e7acd6fccb3b019382385a1f988dc368d5da69cb96956901bc4ce06ec1d", + "0x48c20e5365cd6febb128db3fb93ca7a88b7f2cd3dfc5b7a6fda331e62d8f6875", + "0xec6ae4cd53c6c40f3b77e82cbf386d478120145c0c18f26220eeeefccc54b883", + "0xb27738db32dcb1fb5637ee6b86c528aa9ad75a47777931d45285f0745d6d9618", + "0xfe9671bdffedf2170714da275ff0dfdd533ba1be2ce2590bc1ebdea9208bc951", + "0x25cbe60b7936b87c09e92b9982cfd1bf80ee1d6ce65133434ac330065c9a60c1", + "0xc777ee866895e41d8e7320601a8341fcd99c98ba9d600888397f1788ed79fce9", + "0x63425e84adaa76af6e58807d3fc3dc294e9bd9c32a170a60d8571c667ee804bd", + "0x086c8a54c5d1c2f4160d7f0f5f6c1a333ca91875ba23727025d77225e2f4db95", + "0xd8da17ce51dc8419c40723d1c3a88f74fe336f9a4f98eca61bf1349b0d4a89da", + "0x0d2169c32328187125474e97c7a917253b90dfecec0682f3ca7982e064fffdf7", + "0xc83f335b6903eb3ad4b0f94fd6bb3a8b5b463d0137547a4252043d58ac00df75", + "0x175f57c174875ebc474879251e4bca53bb7efa9f27f456f10266864719e073e2", + "0xb0ea4c419abf7a74ed69807b3d14e0de6def5f55e645fbf0a625c7e9e3765201", + "0x4a246d6ec272afa613f9b6aa288477795bceb920d6b3ed1a78286314cccc2e35", + "0xd3af9fcf65dce23d27b46704753c0b4b24dc752db5389876d31181313cf91ec2", + "0x7301d3627cd3bc2ab317c377e4f81ef6b07ba64939813b20050b53c8f63a533c", + "0xcf785d9ca7c95247ae005537d0db37ae9c54494b0a2c1e655e9c5ee1292e8338", + "0x3de4a30d38f8ef549ae45b777149a547c8cc785c6e6f48e5dba40b7bc7fb4c82", + "0x27fbff002680b942c31cc8f04211be03c8646f024857ae52121dec778163452f", + "0x2a37be7d47abffbfd08f1aff379a27e1d9dd79833f67b466a59b8ebad854e3ea", + "0xedf73b72736afb79d07c6e726c74b88039da0c21285ae55b5e2c8191d3f802f0", + "0x99a6e045680aaa9aa3c175140a9337aee7967d78e97b41a0cb37c03f60c24b63", + "0x5baf77fcc6542689195c10fedca877c6d59ec418867f25c79d4c3ffd36493b84", + "0x85d64816bc21349e07c5dc852a8790c6169d26274dc4a7fc35c53c199c8f6dff", + "0xb59cca680fc9baee6d3d80e11e374bfe8c111b0f47be83157e54e6d18ca93e02", + "0xae13047af776510ee9d13cd6af0e669495704651d5894f30e5e49c6c9d33bd0c", + "0xb2cc9c6705f969f07f700e3d9fc62fbd9de299ca3510985ae5e6fe339e187c75", + "0xb198d0787de7b8e5e9beae4821f587608770fab12845a901edb33da4c50dd217", + "0x7fec95f60944c1796bf42a978a3a771613b889fbb14e6cfcaad143819bafff9b", + "0xda81d0a99cb64b0c8828a05f11bbe38719cd6ddd6cdbdc814a317cee492b1503", + "0x554823c8958d8631a06ea110de162710e66da426210c4c89bb210684c7dd9394", + "0x0914908175ce4d9fb7415d5fdb52367c616a1b95198c9421459cc1c769911cc2", + "0xfbb629523797ff98da78d0f41e2acc45acbb20e4a1e0e1dacbce45c69216a964", + "0xd88684c269bdced43c0bccbf8c041aa6fa2fa9354a6aa67d7053aaa0f2074962", + "0x3920c4c386860756180fb1f7fe605801f7696d5b9e4e1576e1aae0e8525df880", + "0x5deb5c080a346877454cd98ee36312bc3e4a79b3cd9f3c39971d892ed955e927", + "0xe099ae7dfa63b764ef3952ef921cd229acead0b0e047af94030ae09a34b0be2a", + "0x7e754b454ded479b4bf36835b0d52074183c9eb6c42398d3e7338948992d08bc", + "0x1b22378457b71df9263473eceba4f57933f11d33d31be11ec5edcb36df0dfd95", + "0x6605794adab619d57a2ad55913afe54cd5ec219f3d6740185409ac61d32a2567", + "0xa1039d1a4bb3e763dae6dca5b8c00deac9bf0b76c178eff53527a95852c587c0", + "0x9d43d1daf7c4295431136143ae7ad2192b71c16e8da4cd1ae9a282d113122c6f", + "0x38d5c14dc112d21963208fb735e8f76d9842c2ad13e2cdf32b0f6e70006f911c", + "0x09396c809912d9403208968d6f13d8845398b26e93f444acf7538e5c357df7b3", + "0x1ed6f3b995bfbabb0d55b107b2b3ec11c4be5cd68f207d9d059a8eb7671ccb8a", + "0x69db9592c01441747056fc5c646057d4bb992e4affd23654af7f24c47a002900", + "0xef015d193b0137175d8de710c2141d23cae1130c368a20f19bd59f9289d1a17b", + "0xeb63f8ea306392d336b2a8e0568e1a067d8f40c4e2b28f7911ebe48a67638942", + "0xfb12bbb145b5dc7ead7ad984045e62b922649a70ec00da06ebd9eba65fc83c23", + "0x10bdd7c613ce8584ac10f75891afefacc98cb0c711504e0f0284f634d19c3714", + "0xab851b2b35fcf427bd0407865a5989c533b855e65a9891e39b2a5e161a345af1", + "0x6bce48ac8c3553878ff831b672de737cfc7d7c3293e86fe322d229ea3f5d2c78", + "0x0c7313d927f845de9f7c03c09775e2c8fb8e9f2fe63413fff066e9f38d799ed0", + "0x347135f2e53f4002b5687d287b5134de9134eeef4cfa4d4494b086d957157870", + "0xedde43ae708664ffeb9d92cbeb03daa5fc0c7d1d03ac3e9d6541dabe9ac50c65", + "0xd14aabe2a11d404dcbabfbbd8d7c73ec05af5a0f9fcb79bc8f198f00420a2179", + "0x2c9d2e1c881d46c0fd68fffbd5ac45e3dbde2a4d1ddbb77d0ddc4f520ab83c94", + "0x42ea8109042da88b6ed9c71dca34907f54c356b46db55955e3a6cc1541904a0c", + "0xf81c890a5e8660bee4d5a0f18cc0f3a709ce48a5a49a36f0138ab6431783263c", + "0x492144091be2113571cf9cc84c53390fd00db10eafa2f5533f78b8a5d6bdc7b8", + "0xb42ff2a6b3d1e736c56a37a0a46f927caa4ba9fa6bd3f2d1a98459c7c30eb262", + "0x464c4d7daf1acf7786041d3c797f15354cc03cc5620454abdd88679659df1292", + "0xd5dca22e9c436660ee18a941129578021359c0bf2f22008b161c91494ed80594", + "0xb54d6f7ab969f0f95ca94d0a2070b5f2aca9f991e3b64a60c903a03d3d48e938", + "0x1261a3e911769c5c55151982e994aefd4d773fd96e8583f41a44cda306b4e1ab", + "0x669a364ae954397361f4c703c102513315552af241e306406fafb3dc70db8ec9", + "0x54d5a3162659886b7a0aad65839ef2cb72233dab58bb91961d6b6ccb1476da8d", + "0x449242a1b0ecd0bcfe9acdfb2b6779c9f291c98c09add8e13981617486423bbb", + "0x4dda9dcd34dbf574f62d475b7e3052b2e393be6331ab4b0ddb3f1a6270041e8d", + "0xd23f7682f463c5f58940bd199136afba80496fab562aaf665710ff1d5cddee66", + "0x70503762d711f0ed6eac70a12b728f3d84152094b1e4f9495870433592cfa268", + "0xcba23bd9ebcf36500a69fb8be017f0ebfe9872abba5070c6702047e3814dfd0e", + "0x0e2fd927efdd930e1843103c837526ea8f846230ef6ec9f0e8af61f9d3b19aff", + "0x518a527d8d9af923c12692405837e35d58a4625ca36c2041e539d9e369589192", + "0x0a697ad4d29f33cf10f6e08024a18d36a09f459f8ca427cc8b36def0fbdabc1f", + "0x5d96d5562fd252ca3b5f2bc6e6439572ec842764594463b349fc50cc8681d8d0", + "0xa093f86f7e70f80c308ce12554c6c23cdfc02dfda87579335ff1983d549619a5", + "0xef0d1f6787ea178b22a66632a6e44ff464b7de08afd8dfc780f39720b4746a08", + "0xd3a6e3eeaf50eb34d9af9ea4fc461fd4784ecbc6a2b7a8eadc37796d7f00218c", + "0x4c1dac930f116474ffb251df529847732dc575ab404342e651d6fcd67708be96", + "0xd5ef4aa7047c1ba5f18e81417886490624b5520743a1cfacbb04df4dc7724af7", + "0x2c0b01e814e880c5d9b9e01c08671e9a5bce1aa1190e58e0fcee1acf14b36cf8", + "0x464c6952f2738c8b28819299565a7ad027ffff4bd74d06ffe210ac5a44760975", + "0x5bb7a03847d5d77fa84567f913b2da4b87e4d2d453bd5194dcb15a2d07fb284a", + "0x7dd9b9c68e2df4a415c1c4898e979229a764cbda85c215bdf9b8eb2fc0af21e0", + "0x75048e56ab8cdf0cc6031e3a57fce809e540664872bfef2aa32fcedffc32e597", + "0x6c570e74626bdc74454167d24b0e755469e57930c0c5514847db10dd224beede", + "0x511151b41b26e5137b1e564295744e6b9115a277fe569a355a63cd483e2af7c3", + "0x885899509c8d7dcbbe3f9b6fc3ab2b1ec3df00909c92450dee7b329ba7abbe7d", + "0x40bc202e2040897eb3e06346d5d5c71276985470ed2e582b6f32ab8e4107984a", + "0xb442612b838cbc33bd65416baca317ae931bb2b6724bd565ca181a4aae95b590", + "0x23be2219b6842dfbe704c7fdb2bd4723cc4c12fff81ef96e0368f0feed5486ba", + "0x8ce2344dc7c2f11924f54185e191f22b536ec7a9ed82930e223e0dcac3ea6649", + "0x68b8de1cd88ae7fd5be9d8eaa51af21efe55359e5dba2aac1125232d01ddaf1a", + "0xc771dc187da76a5c761c9f00dbd9f50bbc0f149ef98f897c519457104c9f1a0c", + "0x697ef9d13cb317e94d4a40b9c6f45cba2680d6a2247e50ceff250be0f0934fa0", + "0xeae45a6899bdc251611165055e02b3fe3fe65dd938fbef43b01da4282d7fbe8d", + "0x3a352faefaf059235c46420d95a5d26618933e993ec97dee1a87cf55be10d4d8", + "0x59a105b2a42cbdec8ac080fbd09c98bd671ba47ac654c69fcffa0089ab9f4d95", + "0xb2e2c32ca966983c1951db62ef157be6824228d14468d1cb9856d53f9be6a9f7", + "0x67371fdd266043a11d59d4f05f0c5d920eb2f60b434928d7b558099623050c9c", + "0x0d0b97a7b38358d661718b2b77f50d1ab580632f030985d9e44ef3116cafa38c", + "0x2d19591fcdb7bbfe41412891fa43201363d0a5b18a48994674dfeb211701507c", + "0x7b42ac2c855a619963157ad7f3d36bcd1de0ea5689dd3e454aa2afc7b28dd071", + "0x16298885164e7c509b99d5a05549f95f57f3401f723cab1719b76a2bbce8b0d5", + "0x91b028e3ebca0b60cbc4080fb0f816d834f0898fd00ff42080b3e8dceb28d66d", + "0xe3802595c56c2981e3a4b35c149e29c421107c47ee6df2b27e979f59bb06cd3e", + "0xd285c7cdd2fa2eefce09e902c86a1856ab4cfe33e6695e94dca8fa74695a5424", + "0x2b78d2e0c0770ffc67b92d56c4b26a675e7f3639ea394842edf9019ad6920b2c", + "0x495f1461f887371cd29e86bebfedbd429f7eecbc7c759ccfa56500d7845db4df", + "0xeec765f7d794010adaf8dd7f07674eefed3f6d5b9dc43e39a3b3537288b9c9ac", + "0x1a4f6372274bdce3bc6ea83f768561d6c9ed996e72145d524211df0130f3b7b7", + "0x3955a47abdd98eebd3d38244e408aab387096dfa74443b9f607fb6fa59456e64", + "0x7930f2d3fb73869045d7b144061eb1445ea74202b8f090f4f017c27e1c4350ed", + "0xfe0e4fed81793226f51942fec125072e439e701bebbb049337a5f7b24576d29e", + "0x87a4cad6943d444f9da79e4fcbffc198c96752ae72ee3fc2487a82e724a045cf", + "0xde75d28f56b1fc3e411dbfd9a56fd748de3f7490b931328f3a5131c143832218", + "0xffed1a9fe59006557ecf383d162f0f6011b59f63bfc693d61b77232329f8d956", + "0x1cf303aae3e5d342a33d369736563133519e1434f981bbe6067f444e16d89230", + "0xf3be3a8b280dde0fd0aa8322cb7836136b8801420602e45c8ceb84ebed7c7e02", + "0x2813d9eec11134a3987955f4389d4bf07fb4b986b700d982f89d2c81caa2ac1d", + "0x28f236d43bab078d0e9662be120609f8de33bb4661596317905815e7771b42d4", + "0xd72f262c68e657dac4247a7db98fd115b1865942071d0eb06f68ddbb64b392d9", + "0x4215eb42c3bb1333a0acfc8240f1b5d9938b68acdcf0c048fa037d90cd6c59aa", + "0x5a70ad627a347a1884a9e7fdd6c87cb7c0d5922ad69054a3b9d56e96aee436c0", + "0x8ad7e96941d03426434d6b7e0eac92a04e94108d2b1fe71178b582f6d861e2c3", + "0x9902aa9f7e7f1e9e1da269bb387739c103b3ff7c67032097e309df96768b21ed", + "0x0af467ddad68dce1180ecaf84a397e5c8fc98281ac52c10d064e5972fcf87d52", + "0x4f945046721c0071c9b53a8324b391126d26c8bef20435d60a6aaa69e2d156f1", + "0x78bacb8175c8dd89e4c12b74aa687211114b47906d763e0f26cba8410e5e3300", + "0xdf20aab8a9e472d877262d3985813365acdab5dffd05139f0fb87eeae10a4627", + "0xda39d3fa1f48b617d3586f3700119f60a294c1e3d2546393e3a4bf09ba5e3030", + "0xb6ee6e1a15c36710e6d37d2cee67f4646ac94de616c3ad65b08cf6b7aa3b32c7", + "0x17fdf37e749a06f9b8768d73993bb7fcff8b6da75ff4545c1facd812c5c89031", + "0x17c88f6d416ac2e913cf054b9116f8639a566dca223243fa9dba0e0dbe047597", + "0xa04fa8fb398b38a48e134c62d9e31fabce109651e25fab8d32318bc6409edbcc", + "0xfcc5dd8bb39b3782154608c5e3c2a6b050382ded90f0b8352c645ca2b80a88eb", + "0x6b3f1cc76318f33d63b204bdd72a009a7e2acc1a81ff6530739c41990de6552d", + "0x5f4e8c17b0f337f546abdc595f953cfd056015e3add1aacc4e058b318277a3cd", + "0xd9917cc1fe0d4b12b85b2713c9942cdb07178e4c6f594baa4fc2617491d0ff07", + "0x2f6df9e5f1b821365dae46222c7f252a13693fc34a9ff96c1038f154496b49a1", + "0x5807dc551b31c69db61bd1619ad0f9631483957bafc20d4ab1a3e6902332fca5", + "0x04b97d025d8a5b1ac619c36ba6dc8185c05b4f1244993f684299f7368ebeae3f", + "0x16c71e2b84a27105527ae46ad63c9e2eb8d2145168c285ae2f7065e5354d768e", + "0xa562d2718f87e2086106f87bbb574bcb1e767cbf9471999018eb3cc21515b004", + "0xc2ff97b7e8736ef6de59a226cf0ce16353eab76b4a8b8ee147995238dff57d73", + "0xa9abdc4a8f70bc74134eed2e64045b24a1e9290ddbdc6d833179fdb4122c2293", + "0xbf0473bfd49593b516300cae47d7e603f9a2ac0767db39e2ee6e028083099490", + "0x8479dc0704190c2e34795dcb6dd447a4aa25672b9e45dd2e39f3864fc9521203", + "0xe03fe87b29737c7e663196fb33c69f02a35caed2e791f2a15a562bd2989d8cd5", + "0xf50fecb879d837e8556ebf2a5ae833649ff8f97118caa2e3b617b59153b65b4b", + "0x0eddf32c7032a26f6a0e0cce24ad9cb266d11500db33b863dc5d3470e3ee0a60", + "0x85161c9ae941dac62edc22409804ff1ae3111d9f903843a7f86b7a138e702da8", + "0xaba0acb42e5acf464de70e965b47872964d7241a57e21fe753535540b8e04a53", + "0x70de7226fe37eec9dfd4c7902761d0ee25a24748d47dd73202f9c10269bcfd18", + "0xe5f9e07e4757f99c0b3042102abbcc59b1472f45b53313626fa49fffb13a318b", + "0xe4e4be40e0d945d84851d54c2a317f0c56cb1a2a78b9efe1c58d996f9f7be4d8", + "0x5f45e651327d2fed7f559b97e56f2c954e82b843c59cd2e550628639f7f36d26", + "0xdb33bd941740ca4d547b52f857ab2fb06a5d144eef147b5dca309b6edfa730cb", + "0xdbedd24c3f6fb0f3d1fb2eefeb658076338a5274f01bf988dc65c7062f211d73", + "0xbe54c3757785c7346e4e94e2f975e97c6a9c542b2a621281b95529b58d3ba7cb", + "0xff9a08a7d3bad55b530fc2ce5b8437ad524b176f151b10366376e8752630a1fc", + "0xb8e1cc41b404d9b605c67ca266bb338f4b94db9d04f71c33b6205a7aad5e581f", + "0xbc06897480daec866c9faf1723f19873448feedff8237f8163ccd796dcc2a4c2", + "0x1681fa8a577b819397aef568125a2f81aeb94d313c5f37c8041a6fc8cd4619ae", + "0x91b95548f18cd07f37ae2b7d53c56a37dba797361f986d1dbf290e169a8f9bcd", + "0x2e0daea275060cf0d7759fea5f50a5d22bc13c2ad85b1776154409f4d4eb30c4", + "0x1999fb0544b4155419e2e84fed331c401f6a2e3314117acc21da81a135bdbb47", + "0xa35676895a52c8b1de46ee4059d57d1fb5efd480828fdb120048294347c3c18f", + "0x8892717f9562e3f1e5dd2f88b45c299ad91e8ab05dcf6be1c0de7a95d0ee7a3b", + "0x91ac521bd8ddbc2efc821a82c6336d01cca79b55c36fc05932ba588d68bb62ef", + "0x76850eae9c3e3984a06d664df14c1e3ab86532b16624e93603fa098df1136ec9", + "0x4379c37011e615085ad33e48b21781b943437e073964033d6bf2dc9fe85fad21", + "0x15cf24d1b72cf5c797531314204207e899820c07f2c611377fa4a8d2b23e9e64", + "0x964b36d4050d4eacf96a2e71bdde62d6908efc0291795432b45b3032f78c5fca", + "0x5e8abbf414ebf24bca3f1db28a81e34ab73491ef8535fd661661ff7064b989c9", + "0xc1499796680c37d46d0844a902f0ef966efc8117c2460e73f89b1d81a3b35f76", + "0x16be9d9569bc82d5245e0d2f5f2efe4a52ef09277d84efdfecf219ce5c7368e4", + "0x05c7f5f0b28e1fca9441830a38e54813e4ea3a73c7c4f7a873781040e4718c95", + "0x0902c45ce41d4e6cbddd66046e9baac2ff2b6fe4b4b5fce0ee91932d57f74edc", + "0x523cb2017561cba6cabdbcbb54ba2f97d6a52a5ada114c533912c457a4fcd02e", + "0x9df4d35c4f05636670123ee3d9a6255c9adddfd7d17cac6ea2b6e8dd33becc09", + "0x05638d9e998b4eff7249981556c9493fbcdc39f78d34f6c120cf87a0b4153316", + "0x451c25c490adda5cecad4a7569450e4be71b08e6541f0e122683ea3544b74375", + "0xa82e2fc3c1d30e7bc9f5a4a83ac3efdd57a7d05617889001c075086dfdb0d206", + "0xb2e0beed5b15c9db6e0d4f31a2111c4dcc193c0dae3ad9fd320d0e2bd4410ca1", + "0x40183f421d938e028836b39156862b8af8f88b207ac17b9f7535df0f6e7c8bcf", + "0x311e6dfe62efa8e3b5ee21ed0abb73d1ec69b357e689f22d04d7010b3e6c9ed0", + "0x7abd56b8ecedeb87fc6ae95d2a108829f8ccb109e05d75ae19ea67bfa73a13e1", + "0x46771d8f8adaea3d100fa756a801c22d277e1ada2256fb7e613730484a856de3", + "0x3463faf96b0c752199950ccdc1ba7b16c07df750fb76c10c8ecb1b155e3ce021", + "0xddd0b47ff5d1fd28ea7bef1247f683c3c2ae6356b8260376b390b0e4770c2c70", + "0xe50cc4bf0b3278ec508e7d9d0f233e942721dc9116c56d65182c5afc04219574", + "0xa567e9287f6e919a716ca159f6f59e0ebc6e27bada9e0312e4e7a248f3a1a195", + "0xfdec56f24cd59d833907cb21a4311c47d4baaea891efdfd4cc1fe48f875ba73d", + "0xda2ecee4f7f28fd5893d7db76b248fd5a5c8ad18002230177438f1209e92449b", + "0x267e150fd803d5dfa94dbd099f8960c52278fe338d1786b1678ba7de6c101625", + "0xf70ae6d7f25e486d08489d70481e7e537eedd8303b71c656e80ec04359dba398", + "0xa02efe6e14630c760bd69af9a6fb3f8391b5e7ba3cfb8bad4958421b3cd067f5", + "0xa5c4ac4a8cf93b8695d2f1b080ea00745b52a656b6f55e4debfed402226f3605", + "0x434c8b7d449c62e779aca1daba7e2c5b7f264dca8879768dc0b9c02c02ff77c1", + "0x67268d79875e46e0abd507e67b75e5cbbf9aa3de463284e96c057ce2f3be893d", + "0xc3d6c58cd4418eea6fa0e0be7de002279c761588135be2dd2dc152c6f580d75d", + "0x52f6b52e67e84c9cf8d56fd1dfa7d8e45e4e4129d33f9a942307929d28ff2859", + "0x8833fecfb8236f00abb49621694b0fd2a59a41f41035d2704a81d05a196fc4ae", + "0xca068fd3b005b08c2f3daef99d7447332a7720880ad94aaec632d54c591063f9", + "0xa3de1f4bb4c142ad685773b15e9a4e97c35267eac119e3c29e0aa36f2b814487", + "0xe8433c0f128f18299bda56175b279a5e271a8af30e3176aa48f6a734352e5b1f", + "0x9727cfeb52499b591e360f88de264235661a21fbe7242ace5d849d90bc506c74", + "0xa0c2265b8ab7baccbf56801e5d06baf4ce6af5879bd7e193f5fbc67a717cf2b4", + "0xb6303d8b21a2d08fb82154142bbd014329841a5564adbd217468597302d4cbb2", + "0xc6571041af75a5bbb7552811ded08fd4d93b8e33e974451771a629593df7d656", + "0xcdbd84961c2639aa0159de12abaef96152026ba3710385ca44e2080b5ef6008b", + "0xec8fab8e1adf154822c799dd35e2627420663b4d1f9439c79d89f360467fc216", + "0x8aaafbfb4414ab5c8ea23ccc43b5abd2349194cdf98792bbff46b7734a886d00", + "0x1e2462355a74d1a705e3c3f28d826a6b229a134c472f8d2541e9d03ac37d8d2f", + "0xd4e33157363845de8fa0564d1145e4a46eb22fc909c6b182e6bd7aba4b380613", + "0x7949178782807772e6f9160a14b54fb0ed503d5c1630932cf17cd9e385b00ee7", + "0x089d7d1b5a0f3ec62db8d1c11a95365688a47bdb14954b72770d5cdb7af3a365", + "0x69fe40a2c3b725eb25be1310ba0b97e8974b17ce9eb233eafc1306a6ccd7a463", + "0xfb4cf8727985a7d97917d3b020ee11dcdb08cded73085363f625a37ed0d8b04f", + "0x5ffa2a923b9a50832644a8bd39f0ee569f9e4ad8f50c4e1d57c9ec96a1c03477", + "0x8360233860f889d96a7e077d221b4ab6d9e3f7f1c5fcb20287ce486e9c244979", + "0xeef9332e4fdb2022128df42a2f311dc5ac080c7273e1a24b50774058b1d9adf7", + "0x89d790c825dd9b3de1635ba3162fc0a3a99467747869b409db97d95f7ff6cf59", + "0x04a088709bb769fcb5b670fa79cd97ec2dee21e62992cb2df693e1f18b3a2d11", + "0x86519becccecba9b91d0af72c176a414589b056dab914f877fe8032ca1b8ef9b", + "0xe61b3d8ddc856aa2ab755d4097ab9040ddf3554a1d8493fc5b93b5fd58aa0fa4", + "0xd8efd5557426e233870b8bcb53e0fc89fe79545d4c2d1aaf13409a7fba84acef", + "0x0b74a2eefcd26ca8322495468afa0c2ed24db0e4cb8ddf30bb84f9d2bd9dc4a4", + "0xa9fbda8887f5ab139d567d9a14c507e574352003b6fed49d3cc3ea49ccb544c0", + "0x078261958231fa17c1b904ec7b80ec7c2a0e49925a2309abc701521b90306b6b", + "0xc4d9c5af76a0b6c55ed8243985779bc77d4ef86adfa63a8ceac44efe908ed012", + "0xb02867e224a85e4a929894919fdd1f3460f909ac276278129d7fbc859f56915d", + "0x7a66267c51322887433994e3a01fdff4600e596a06e1c627c5a50c42e2bf203e", + "0xa66849c9503997ed600daabeb23c1e316d938d7c36561013f41d9a994d819735", + "0x572641c0124606eab803d11c3548ea828cf67b3d238eda5efde6098a210ba6fd", + "0x0a920057716b8b6b968bd5a28478ff99224b687bc6c97e26669fa1dbaf99850e", + "0xe198e1c691d14b3ad0a6b1888f7ae40ca60042ac91ffca0d6df3b4bd12090898", + "0xcf8cceabc0ccdcb4951cc37f625c1e8c120620e42ff3f1ff4a72e4f6dd6139cd", + "0xfb06a9c8215be6da3ade6c298f565f7c3116d12c87da1fc9fa48d17240e3b545", + "0xc967f1f8b116fb2faac0ae0760622a488cecc6498c074ee0f013d985475c914d", + "0x7351f762b23b48612b1369c3a7754ac2414e4d337f94cbee4fc1adc29759eba4", + "0xc3410fbbcda7e7bb868ed399d8950db593b7e79d5fd482a5fdb6e6bf342fe6e8", + "0x68c7626ebe19b8d30af71d3cf3635dd7c7912aed7a47bec3c369b72eedcffd05", + "0x3de93c3bb133dcfdf07ede31fb2933d8acda317e7680e7bd18cc1485f30b9225", + "0x4f2c0cc1f9f2f2c1b84448cd9b033d95f74940f6dde28dff0cffeb2840b6eb67", + "0x4e2934f4981c6a3591ba4048b0f3794a6b92bbad76e94d68ec4a99ff95601d06", + "0x8ae0d36b4e3212e9055cef96398fa706d9df90c2ced2c89c4828758b62154840", + "0xde41a196177d404534cc4b46f6b877ca4dc22a443f6a4680915e43046396e8ef", + "0xcd273ae452ad455f430d5f57d6411454fd2fef1698f9b8c23a4fec298936e47f", + "0x95c9ab467c02ae75c80cf924e81ff6c9f9f9176b828bc3dead827d4707fc5cdb", + "0xf9ad1ac9623d7b8b55dc1b363ac5e6b81fee9cb0bba042ee9802b74f3d6d12ef", + "0xb77f49f9fe7da05e6233e1aafd35cfa8042f8ac8220bb04fba898bf75b485237", + "0x6c7dd1ae1b2c378203b2be05abaff1e6f24d9a16d2fc4fc76bf237e61f5b0951", + "0x50c1046183493f9a0b860effdce20c193a7c7e89cbb509cdbfc839c522c99677", + "0x38a84d66ab731cdc96ae16a7f0dfb8c61c586bd0755cd409f4a785d426ab2e74", + "0xedf3c6c8ea853068d511c74639236e1daafb2caf96964e5b0daa22d354e39658", + "0x3445d411938c39b0168b96f8a4b0e32206a531910bbf52743faf37b3581f3236", + "0x4c418ec9d20b934a3f237b4c13682cc1638ba8e517e86d168e8c990971098f97", + "0xa610b6a8777a0467100a3581087f5bbcc1e7d4b697d9f53d00d9fa6f0d77247c", + "0xdc9e46a16000ec340bbaf70284f6a1528dbec79e4e8c371d4b04847f8c844089", + "0x34e76ef7897de33eb66e4ae37b5534c6240540048c525f858dc832b166593181", + "0x36dda3dbe43f18880aad5a4f25ec29bfa2da4a6c7f964e6418c0cd421bdbea36", + "0x64221de18086e9361ec07e4cede9e0103109d315d97684f26f05e831ee2878fa", + "0xd0fdddc2384a132f50ae0670cac8e62e918aff264277d350faa66a0e95430a2c", + "0x4da406b43c8247743de53b0a395e47204ca3f0d15f2a29d8715e11a71001257d", + "0xd0e67a0d70cd2140f55941d6ca90cd15ca6886ae013ccca40c0afc0bb8bbe016", + "0x70e6b1561209e95921f3800b1c48ee3bf3e532f5571bb2e4a5d82e9b288eaa33", + "0xbbe85ae238d623b1434dc75fb5e5d09a75578d2b85c59b8e69d635befc784248", + "0xc617186c1cc1c807b9626ae1a68d8d4fcd6b42aa153dc586d5ee2192cf9918ef", + "0x018329ceb98202471fcd740a34c7c987c2daa081b0d105b86b5b948c8248ab63", + "0xa1bd431642f0e1dd5f0bf01e610c29e5d695b8f578faeb0f511a7a9a2fa3116e", + "0xc8df41c2aae79331b86e7b007a28e2731f27f50609e9b4924678b8ff24d509e4", + "0x377c56c1c8b9686225cfed2710e4934c17ce890222c7482e7fe7fc77ebccc52e", + "0x0262617467f33b9eb0f3b28f368f5d08483a38dc9423510442eb88537c6d49f6", + "0xcdfd57a4737a718352b19c48aa72c41b2be0a7267ec7abbc3b539c81fb5a4b7a", + "0xace32a66c3c9540cbbd81c26a429487e3ee135677b8a43ee7468c0fc0c584c05", + "0xd4a50046105d5d01c4c928a0ade2d1a82db88ec52dc1f02b7c2daecbe9985841", + "0x350c5fd3734cd35dc6e02080e087858bef8d8dfdee44bd8e2bf75aef795a961f", + "0x5e597461c6e1468b3056a2cd4483e85a8b38dc27195ba60d50ef9952aa640a49", + "0x4f9d19414803bee7dc37e16413e033bb710543d86b38d6133adb1ab4ce90cd0e", + "0x3470068fedcdb6183c16ab34a1743e2414151eeb7a46d71961c1359adff1e214", + "0x66054a35bf4b53cec8302e2c94b8be80f3692fcbee87da4f894769799453771e", + "0x752d55b28bc47a388b098fc5b6b5f60ffe153459ddc1c0da007cafb3be151be8", + "0x3b969e58d42a927a7b214ed99c34ca6a77234703908bbf4ffa17e17e21fb8cc1", + "0x6f0157bcb211940600bb88d08f026fe4af881dd11d8dd1351ca014c88c3db72c", + "0x8592dac47e72c7bc32099c102a582c00543a0d35f2dfbdb9b57068c79d077815", + "0x8c95e048954d689645df63ae447101dceed5e75d154502c61f37990e5a97ddca", + "0x9f4a5e8e60a88088c391040bc01c46538f0cfc032344a882bf5f00cfe1b10d3d", + "0x04817ac392930b9b4d81cd529703b6688717da8101fa8a327fe49c503c0694ea", + "0x446d3e1470d3f965fce24932f5f1824f998c9cbcd9eac1c9ed7fc7a323658bdd", + "0x8603a9e9b6b852768b751175cdd2b23e354777e38408903b42d67a108c1b0999", + "0xd04177d8e00ab233b6336da228ac1b9d683128c66a85f1eaf2d462e7d52c9ac9", + "0xb01c3a41c7864d5f14f7b2f18bd5e4576c2d4d296d78927f75dcc50f488b54ee", + "0x6c7f1c0024685c819230e8accfc6a0e5f967b440d069bfff8c79185f152f940f", + "0xa2106a57c2faaea7c6ed8c7edd48e64ffadca5c03674672da9a972b4d32ffc7c", + "0x2c245fd6206db27c4f95be2fc01b04d24febc0e7781efb69623bc5214e7ddb69", + "0xf4aadfddb0d2d00668dbb5a7aa1cbd4302d0778d3697af4cb2ceed68e5dd1639", + "0xca6ff39151d73d4ff9aafb89ec0843e5d93eceacdd69b1c95cfc745857397c15", + "0xa18081aa619e1ee71c310a810c8b3198d515a0954edd34994fedc974f24bd0a3", + "0xc05f8f372ddc52ad91874e45aa48683c969331a3c472708714c19af1d8e3dc07", + "0x57a2027a86cf6e524d7a4e7b0b920a98ddbcce80f018bf402f7fbe73cb366614", + "0x3fcbb5d3f51987fb786b0ff83f39526e2aaf1791abc5aabf2f11a6ec8ea4bad4", + "0x61dbfda0b2940f034dd239375ecb5c8fa7385547a6ffd4bc5951bca8f5c8bf0e", + "0x662820a806693485407041ced34740b6ed57649bdb2d346aba5cb77108f697bf", + "0xe368491b3e2fd70d2c6f06c6e05a41f2bce9fca28df109882fd1bf3e47c82287", + "0x6cedbe3468d4903c73316b43534912e1b69cba4623791121b309fe37b6ad9b64", + "0x6517d421dbdf6e9041df293e6112572b8229208430277c85a7e52acad8a760fb", + "0x8a1602ba31438ed89e0f922aa165e0740e9cd9caccd82ca7ac79c176fdd0a2e3", + "0x09a07f8791bc59a20a326a727803822d1dd8de5e9281870818469145ee90f114", + "0xf6c3a82062633e2072f5b2c59b78b3f6613663afb2b35546c1240c696aaff8a5", + "0x1b4ce49dc9f835afcb3c34e92caa9a30db92c0fc2cec32c1746cc5eda1caeff0", + "0x2bea42fdae58791ac76d7bc2fbfc08712cb8ecb70b011a271572f047a678293b", + "0x01964b0ad4072d281dd451f41ce9e2d61f990bb104fecf29baf012779652f8e3", + "0x773cf0d41e03244bc688be7660101ba39fbdfa2cc94e6bfb02a1dd291c5c7265", + "0x651f0346eac119d14bba1a1078536dd986024c4dc5cc5953b4d9cad09735f97f", + "0xa4389eb16c42465582dbcbb6af80198f8412091c6ef2ecc7ec84c093f8925306", + "0xed75036dbba0069f415af01cdc723c0901676182960e2e2b51994f0e0c6ce0e2", + "0xac433ea4fa502fe9d126115a386eabeb86df2c895e3908bcd02a9d7d125dcb00", + "0xa65d04561f73a2f6e1f107c3759143c136b12619ab498ff7ad31994e7db5438b", + "0x6d9815c2f081d54013ad118b2c0ff456aa1396eacae1dffef461c2f2ba066527", + "0xab192c650d80aeba5b885a67d07512a6f532fae12ea69a3eb39af7da95c64b8f", + "0xa1d329666928263f1980f72c9a21414c7302fb5e77cd1dd7a91c4dc5d6d748ef", + "0x9e84e47ddab8900337e35ae9287dbd041d0b1d059582f95d375f3231eefd428f", + "0x89c11687a6c5e5a5b45255b4a8ffbe337d8706470c3a39063a960d103ade6af6", + "0x3547ba85cf24a64983968f8587f28bace1a797a93ecc16ce6787263f0de18185", + "0xa98634b1d1c39ec41c7cfa6a4f353c4c276f0618fbb3bd257008b43bb33b262b", + "0xec39ca2cdf7a3798a1530c8bd1424622822f6824415b2964d0467ba313faa940", + "0x8e66c39bc71e16085bba945ac0aed19f3f169d9d2dc7c0ec090583bb896e1a51", + "0xfd7f6e227a8c9025a57c73ff8c82265bc69c9aaa185eebfa924ef608234f1937", + "0xf55d1247afbfc35128a41465800daf2f90c1d57866e4bd37f92bc8278baa95a7", + "0xe82faf145ba98fb5af7e32f5aa90e7b2aafe9e2074c86bcb2aabe17ff35a025b", + "0x62abf9c26e0e5a7c2ca3047c8ae9f27c5215846595b4f41aff72c8a05ce42549", + "0xfc5cd59f7ff8b54d787cc77e29af8f9f78102be33ab4fd561481dbae04426b3d", + "0x69af5e5777a5ee39cc76a049e268845af3e1ecfd0b8de8644197469460880a31", + "0x8c1ea859c343697564a88b170973903e588967d89b63d511f63218bafa4c4aa5", + "0x8f9c38834fee0d5653d4df327232737d342f9b389df61f5cd377164e38a91e6a", + "0xbdaff64768fcdb9210cf8e33fe94a6cb38ba068c2d21d970efe6cf5cfb919eb1", + "0xf64aac8df844e56afa1413e9765a955b6879af44202a43e3f9aa15db421f6643", + "0x06762bddba350befcfddef5148ea1f05729760cafe5f018eb71285b92e30ad96", + "0x536ff0949c7f34762613747c2b7d14f605d6bf0ac328346e34b4fae516771af3", + "0xc30d536522242b0b805546882d5a283d517efc518abbdd674156b6f67dbaecab", + "0x818fcbac4a40b856bed993b9021286fa5f59f0b76b25af731f4123a83b5eb90b", + "0x2e6c3d4de85428210eda505421b253bf3964f5b2403084a1202d940de2d6dfdf", + "0xb31f7199cc69689b24ee2f52c8b50746ba3ecba904c49e2b352f8d6a64f514f5", + "0xf910446802e79809cb62cf6d958d570186ec7a477a16ebf6c0eb45c245c514ae", + "0x36e60616ab618daa724963f56bec00da5cbfac517a41f291da6e6cda890d68ff", + "0x4ae4e0c39ed59901fc74ef1fe52643f1f4341457aab052be71382d9945115b47", + "0xf5038c706b2cdcb2337a88ff34ed3e8e3093fe95d48e0342fb3bc3c0adc2ce51", + "0x021c48a8ce17f06cf41f89033a70b201b73d2fdc5c314bc313e8cff57cda9fd5", + "0x363c94da2187a9e497c77688f70baec16e64c4454db1f0dab37925fbfb9139c8", + "0x2d7c8407dd4ac5ea3212b18e103f10626d8bbc0cd18fe261409043399f026b99", + "0x05c3dea4c6599a259c3297c51c38c13f618ee5372c6b43e1945396bdd7a91229", + "0x7eb49d1da78b683659a33b9346c65bddcf6154043c97438274394e3ba868d0ea", + "0x17c008f4a8fdde5d0dce03adc57310580912599fca0535a42144526b4a630503", + "0x0011edd3b9175a765f1ab25a3123b91ec9ff9f233e8f782a2001ced391da2f05", + "0xcb62dd00e7a67019c782abd7e4bf7e3eef12614b03f90219434bba24e3070097", + "0xee086e5721066d4d8886e61e228facef0f518f8140926067be9f0f55b261558a", + "0x683c738a40a8fb871f3f7ef575a422d9fc60511ef4c84cf0fa9161605c10ef2f", + "0x43a4ef42030692e416d28c72f899fa83b4e3d3066fedc72d8c1ce0c3f7f60dcd", + "0x964a579e0415c2875382d1dc5953a54850494ace6077f7ed247f00eeada0bf1d", + "0x286bca4d5a0ce6fe9c9ecab2110fef1c13f71f8e11c37ab5667e164d2f4cb3e5", + "0xf2faf12c85d82d434a5db7d43d51bc99508bb11db731d7a22136d08f57901639", + "0x645944ae04d68cf3c993f75d75f217c8a78531ea3f17718aea08c849bb705382", + "0x7e4c87b6078ae798210fc39cb080772ad2034dcd9ec0f7a28b2de7d7e15377b0", + "0x4760f5e4af303ec759aea4fc2add0759caa3ae96bff4f727c0654f81d02a763f", + "0xe2f15372e72f6e8852c7289b192e959fb797fed0fb9581afd755e4352ec288e2", + "0x760975db833255fb7f325477153462be406b63ce08e6ed0da0dc48f9dac5375b", + "0x2ea20f22253680c49663ee8df8c74aa2f0703223c5d0dcb3db37b8c3ae7475a7", + "0xe7622392c52ce0d6cd698806142e6e26c9d86c81f1877bfbe9022ef150cae57b", + "0xe973760c42ebed38e37252019fd73f4ef14f2503bd3ffb2d859124b7e25ee557", + "0x7d0c3cb847b2cb7c1a5341e0214e830ef886073983e08498f89617b5833c22e0", + "0x5f5939c73fb684dd39227cdc88af51936e59a9881f8fb63e071366b9df4a6b36", + "0x081d5b53b84e2fe7f8cb04a6a6a045e4c11dc726710b6e9994f426fa9d32ed9b", + "0x436e895e16cc13777cd0b740538a64bb3a1360a7038e6fe8efa3ed3f590d05a3", + "0x55a611a3cc6106a86768053e268658cb541c8ca17a66a4a90a375772f0b5e016", + "0x583da6ef703398a2b781acd935f9916932050fa0cbbe1548b86d40b3b1941fd4", + "0x055531e88f18a0d79546a3bf00cce987c33ee0f97ecb7550b3c301530b279bec", + "0x4408c0007dd2dabe7814546fdc336f3ebc5a1dcc7daa1d8a38a9db819eb86374", + "0xcf6e7dab9c72babdc051fcf35ea89e793aa6fe380830d61870cfb4ebc3e7d919", + "0xdb02f15887419e3f89e1930d620748ca53e7f0c026ea8b60cd6e9ebc62f9da1a", + "0x4d1bb9da4321c7f2962a275272c6c1b1c3da6ca9549c19134dfbd43cccd76359", + "0x6ea8fc2a9138c404993edc83b3f54b0d5d94c85367c8e6884ef5d889ccf1bfa3", + "0x4ff5c77a56a90c20872cc7ab5b868557f7fd5d0103503d4217ea2d0079690ef9", + "0x5edd2bd35b9d24b9d5a3c68025061137c82e04261291c4d958d9e0e9a2763329", + "0xefc287bb7ef397298052013ab79d5a46a3a80a55f60e42c66746c9a25ef2dd15", + "0x986fbdb20fba887f3e4441a5b4b98824e1ab4df9aa43cc1d151eeacc55bbf4b3", + "0xbc70117b2b1204e3868a610bf3d2819095185245be082c96ffd3e0c2e406be51", + "0xaaacb52b835b235c76b02960517159cd1f2fb08681f13c8352a04820a990fbce", + "0x43e8b0fb11a657e4afc022573de30184947153497936d6cd47dfb2ccb61bb110", + "0x63fc1cbad428e16b1e2063db10c85ceb6684680c044adc2aed184054492cb19e", + "0x776674ec78cddc642e69ee9b16f2ee876655ca3efaf6a24a72c99a998d55348d", + "0x09dfc550074184d46ec04de265047ce529bdf2c02f7b44e428742f674c31a0de", + "0x897263eb076edb3071a306922207d17cceba6ad179d0f7fead2912ee42c69774", + "0xbbd230729752cb6d078eb853681e85823d2946095ba318d44b28eca479bf217f", + "0xe731c6c7938b7f2dafa8b5935cff095289b993d5fa4dcbaa715e6817d83fc823", + "0x04fe3b2d9727b05033eb4955f0c6693b0e63de665db904bc62b4dad5ce59a487", + "0x881aec4ca776991226a24f1ba9c736f9e86a051cffd1ed42d563c01a602fd126", + "0x9dd5adf0aba333d3cf13bbd8636dcec128911b675f159d11fadbf75137e1b766", + "0x26fb6742fa3be87da75218a1a138a3ed64cfa939791cbc718c181e226b5ecebb", + "0xad0c9794ce6109aa72c3b0ea6110fe96191ce3efc89bef5a99696ae84380ef3c", + "0xd710b6759276fc3149afc75ede514256c092a9e044555ece9fe27e27364181e8", + "0xeaf3b11fee973c4aae9fd19de92a7b14ecd347275c64b2343a2e4f97d1204785", + "0xcfc68b631ffa430c95ea583a1a1cef0a43e3ca182deb646c399a451ce55aa921", + "0x52057b9108fdf67ce8b7a28596e933ff57369b9ec9f1183b79cb0d0c9f32d651", + "0x1b99aa1987d512c71cfecbe56d6bdb4828ff254d055dfe1b23c472ffa4a6c3ba", + "0x64968b18cf678d322a84d54b2a91e77f44c108e2d722cb1f52708cfb824d227e", + "0x51be4bb756c2a3b74d4552310d49c7edf084014ea2787e349bc32143295380c3", + "0xf98742fa2e646e8add000e8ff892eae0fbee6f61a2a200eb129758285938a881", + "0x0f963737d026fc353f0576ae146a0dc7a8a27f31138b3753101a07f0e833f1f3", + "0xc3af9d91a1e44a3e865f44e75cffd5e9b135b04fe6d423895fb1911ec08573b3", + "0x366072ca53e1b7c312088a2c3504894c2bbbe1f1fc3204e22a22b5b619e09a9b", + "0x46ca1ff3099150438131eb934083404728921e498773b5d91ea59814e8078588", + "0xe2b18d6bba927615a8f9252188c141864cd61cfe570ba65f7290e4ac0739b403", + "0x6844fe922e79f335ff103ec551476f4433d4617bf9f3e25efe5340cff0c9406e", + "0xd433ef7f7b8d1d517815e5f77f95a2f3e5100a08a1ba9e5de78fa57076d1d307", + "0x6a2a72db31e9cad268f13dd07c3c91d2c2c23e0c92c6f1047a6f3d59f447b821", + "0x9f0ceb8da593cf1c70f4eeb08a3f7dfb6f682ac4bc1c175efac43b10e100ac46", + "0x5ac594092618aeb04d6ab2c5b2612f1d4ad57162e62aff2d04decb0ace6658ae", + "0x003792b77b6c078c98e3ebdc29014a2c24c238a79e71ed5e36e27c1e273583af", + "0x15e869175252c89249a7728c33bb8e4c67f90f3c802d80356d25344ea05e9249", + "0xfa67b16cab4a3f1f8c4e8f6b3fe98f5be59e0f13ebc50d32f9d1dcf55fa4c984", + "0x3259027d8095d69e4bdaa0ed9c7d80681f4e40222b1d03347a141a634de40344", + "0x8aa2f2b46d0f85d66ebe39c00fd999b67d576e2fa119fad6783d6af4939fb25b", + "0x0f6073a427daebb861b9e1c45ab46ca9b8410e8f094137b979f6d17662fe4ed1", + "0xc9a4e1be21bb3dbde859c1bbd9ef9b63f8312f95c3d961414338ee8f9c8611d4", + "0x1c24d8de991c7daffe35d65f90c9eaeda59163f481140928c737d1066a95c01a", + "0x94f41fc0f4257b24ed6ee005e62486dff71f6ce8176b9fddede2eaff25d9fe55", + "0x9fda793acc69eb63981e28716bd20e8fa3ac091595929d943c651f73f6559593", + "0xf7eb671c5e563de2698cf69b2976e25a91c2c462eb7583d754211b252b4f8479", + "0xaac71c1761b78cb396167f177572144e68e1051ca3c332e94514041b9c7833e9", + "0xaec9323ccb0314b0407a591c05a0eb83e48052eda78fb5e9116cf32c902a79da", + "0x73a2019eee50ec26354b6f7d47416bc10982ac44ef47ce4720b6e73aed28f869", + "0xa45d192de4836829a913a20b14a9d8c95dadc04edaa07edd2599f2a75f85f5f4", + "0xcd8f6adf06fc2f226bcb713fcde720e205e4bae7a188d5135e3728d752835dea", + "0x59614e66b31bcaee5066f04bffdf318879126e7bbebdefe39b921fdfa5c1ba67", + "0xb27c406a25b24d78aa543a26b8321e43aea21523c7805215ded3d72c9043e0c0", + "0x1485ccd46c327cdae534d95c4b61611213377dbde0728f2ab309a65b69012deb", + "0xfd69566c9456b5af6a515aa031b326011cae67e88708557cefc5f1e67d76cd49", + "0xc7e49938469e6a6d27fdde544dcb48ef3f761d60ba4671163f505de1ca644228", + "0x96cdf2b037a658f75433883813f9edae930769dde761fde991e141fe383d82e0", + "0xc0ba35adef71f25b99450a0bb0a46b450dddc56ecea4c831a53dbea55463c594", + "0x97de7293e71b1779b23c3b51fd85e46d7ac86c55c18385d9c54d3da1c458a387", + "0xa72bf43cb3dc7ae59052542fa2bb2d5b921f49ac14485c1e9bfd1286af59abc3", + "0xbe7d7862602bb9911073bd4a8ec5421901a3a66698ed478102f02df87727fc12", + "0x7d17171e3edbeeb85326d785c2a68d6666526d8912c6aac44bf16fd0c0ef9834", + "0x3f3a36b17fbcc5ad93d99e71ac0bb2acb10b24fbb914773a0991c52287c201ce", + "0x0ddcef7f14d933eb8b28e5877e71595116a98e408b416f01de80be49a8e52957", + "0xccd5bc27319844f5b389b3b15e564ceecb55a91d748f145709025913fbfdaf91", + "0xaf27df2c5e88c00e482e78e44de581fd17edc2ae91e3b7d1017badf00aa8bc51", + "0xa850950e04076c8653eda7cd11761d6a8e9b46a070ece44dcbf5b8e99d9fb0c3", + "0x6c934e50d34130b0ea5d5776ab74fbf4ecf48f8a178115f7e93670599b406653", + "0xc6d3df6d3c0ea6c8573b314e7e0a8065d76d27333c0d6032b97637fc7013aa5e", + "0x4f7cfed4bad1d65ddbb1e28c8d9814450af8d573c0f1880d5647eb008a13a44f", + "0x0a3162cbd7a81248f449393fbd62f65ca948e9134cfc722554f28b2ef7ba4f89", + "0x6cb294c5c312be01110ff0566dd76d4b36e86c76587084faf6ff7f28b717873a", + "0x799574f8dee1769273651e19b56c17d3aa27d3422feee1d18080608b4882e2de", + "0xec0537da4c25bb664270f90fa72c0ede19127f7bfce5724762700715986f5b2e", + "0xb955c2ff50d42cce782c991be3eef70de85a1a382aaa6f7775c456d87a987592", + "0x79f931169917ff38a71b45d85a5f8e068bf45e8ece7a8e5530a0b4eb01efef9a", + "0x8d20869224be1328197ed93a88fd53d0b31ebeff49870bf7851d6e8dab77f730", + "0xe6323bef31280b55572d866f315b97f5be96148a3d640284110a23115a59ae27", + "0x47c847e3a20412135b22a2bed001bd32dcae67a70e5681a5e14a210553eff25d", + "0xb71b250754e11a7c9fe804a33e15a662321d9449fc63b1038a17d58273fab04a", + "0x89128e0b4180512ba5c75216b3030192d9b1574df87f1b926c5c7aecec92a7d3", + "0xbad078b9e9b0328b48dea551a962e437b51902c056c5b0776482712f9db786bf", + "0x4d5aed467fd88e4e026bf006aca0a78717d6b52f311d32449b1104f415bb5515", + "0xe72015b43036bfb62431d15335e719c549c61162f4879c0eaa81421017922d15", + "0xf70009d15065bd1570ef3fe2273da35e894206361590d38a4bd414ede7d69d06", + "0x2a4a2d96e00f06616d77b29a72d7c494cb6c29f50811ea616452ac769910005b", + "0x21f9218ff5737a4e6e6a167f83691dd6445a23732cdf4491ba7e24747fa0391b", + "0x26461e3689a21987bb38091f0fdc4f371002f4a84eb3b618e8c7ffdd6b3f1a31", + "0xd683d8a1f060a5e9cd282d641dd852ae20b7b1c0f9ba785d5ea15b234ace728e", + "0x6b4c803a6643293b9160d82212e5b3405b69a4115dde4de0258a24832ac658bc", + "0xe9a00afe1af35d7811d82e2312d02c5daace99f050e42388e76e5c1b745d8779", + "0xe756e9edf9bb83f450ba9791a245adcb89ee4fe56770d1894086ed6be3d089aa", + "0x729d6bfa3c1d41089d53e08164418779c9abf94d8276a8a8e7f1e4ff492183bd", + "0xd582a6b03425d0ab29d1405232e088822467053d470a99c3127c46ecc02dc93f", + "0x69ac67b95b725e5102ac7ccb59b46e4a4457e368b90f80624d84a37104ab166e", + "0x8de7f79cb5eb8dc096e9307968dd1b46acf940994dc1fc27156c5168e1ae5364", + "0xaf5fa4455d5b4ce635f9394f1ad4840e4686d80dd52696fc392c3eb89b7a536d", + "0xcfd7922b5650cab0a29e0468cf1e816f741b8b7af1768308f78ec0ac800870fd", + "0x5e14d14657d534de1846182929bcbe7c086d0bb9c418019193406ddaf34a7e5f", + "0xd727f88dbb4a62310cbdbdcbbe40023937a1f681b7d8f6186665129b9cbd32d1", + "0x5739e5a0f02a3239eb0f2b1242c7e8e0042bf7bede814cfdc6775e172d34bcde", + "0xd426e8bf6dc9171c6850a492b883bd4c92468b861f0c539ca890e444f854f44f", + "0x8f9b7d20a62ec75492dba773b54ed3416ff18adf070be3b3a35a803da5aba931", + "0x8af025719c903aa861de42fe4d082321f600c17e4b3a5f342ca408787957922d", + "0x43133e4fac22d85951ef650fada9a746b464a0659f370ee40ac6286d5ac3968d", + "0xd95ef78d2685255b58a7a0a581d953837b1d891f8764d2842c76137bb8f92628", + "0x5fc07f1fe21167cb65405edef11d30206ed7907d396252ed460365c9d6ea89fd", + "0x3b86a46c42d2ce31c39ac0bd352ac1feac8705e825c17b06d0f9db4f15f0b793", + "0x3672191b6d718f4ffe5e17039c25be00b258336cdf959abcb1615d7e77fbf415", + "0x017faf0c950fd86809e7a0acf0d7dea5b13d41b21c60d4844ce57459af471963", + "0x5236905646defeaf3666262c1781392fbafc496693b0f26167e14622ffd5e224", + "0xac45332d1c62566039b653fe67725544d531d0d0d385cb31d18d461e36ff3c4b", + "0x2ddde66714e4fefcf8d1130e2847d92bc758b39fe7a2b87dcecf9b3d0d1bc5f6", + "0xe8c6c341b96f9771c5897a0423dec64b2d3f57aa5923b0f694988302c99c1864", + "0xd31b332e66e44f8804ab8d224d179b3dc20f718dcc6b254273f2539311ae9038", + "0x2776a9d5ded89c9a8bb243b41bda3760dc173c41f16bc477a0c6e2de420f7aea", + "0x19c9b95e82cd6277e16bdbb383593459eae5584e8b746de7262b447f313f1052", + "0x6d602a973ee15804f76848823844da1ded9e2fe49b689e4e4c62948bbfb699ed", + "0xf8feaafdb855524369a0d0f011cee5f545b7e2dfc210148b13f84e0cfc5a7a49", + "0xe242c86f0d4421c505b4722b38c13e73c760d0d82bfb77fe6677a738e3f19679", + "0xe1d5352fdf59b76318738f0932c4960a590e46a0073694d9518a6e8a779206e6", + "0x7db333e369dc65cd5f8718ef0cbf38def00cd60bcc47c1ce2034203c6b2f8b38", + "0x1a57adefa64ef6f07306db76e9425624d106e73bc554822cb99b4697bb317f02", + "0x4a6acaff19b541b0b2fd43d9165f179fbefd353f8fda107d53926e71ecf68a8b", + "0xe5e886e9b31a3378ba585b16dc81f0d5cad83f4fc5aae85945e9a8898dd038c7", + "0x4d59ae8cb31c36c39c2aec16ff682862c097aadc499da6de1ffa72a6ed87b4d2", + "0xb92d833f46038c267f09c500c2ae557810709d7db9bd210ad4df55c65bc0826d", + "0xf1b971e2530edc4703ceb21b58a750a37399c05bec8a02409895af98df7e5e6d", + "0xbf1508b24e5d01809d39c110816f3ad5d703ebaeca4f218b24925dd9577fad40", + "0x2e25a66f7a580845ecf04e66fdb0ddc0e17237f6812f5f2a1640c3511c9f9db4", + "0x5e4f36c5ec099fbc35ca767f548304f8631700326b3a4497f8977d72c3727f13", + "0xaba60fa3aa0661858a1143d01d9408834c2be440cf06d72a93e4df1df6617853", + "0x42d149eec229a03ad942d1745ec4742f9f39a03534df077977f3f4691c939eb3", + "0x6b276de3cd30f0d7659292ba6e8bea190cc24badf88c10bf269fb4d6927b16e0", + "0xd978546ce32bc1123773b6562ae0a7a55b7d82c72f2aef2a56394c9940e7cd12", + "0x297a80b1aad7e95f57ba4f31c4835728a48f7af0e9adfa10d40fae8bd18cce12", + "0xef0d03d9db22500fae80ddba96bed81bf4769e645b25dd717c5ab0748e3da691", + "0x1a094a2ca17fad3f0e2703cd172bcdf4a0ce28e01840655a0bd19cd398153601", + "0x78f08815cffd7e21af3392d2ba9ce33335d8f25758631f9eb6352b826723d093", + "0x827646562aaa1ff4a12d97e59da6aa7c9166418dd2ba204e448bb12b321b7be7", + "0x5c0e92edb551cc6d182b35b9408d2538aa982b105003606575b5514c8e40729f", + "0x416dc98309f2e650eaf9a122508c163cc9e3c9d719812e0a6388b84fd48016ce", + "0x4f8382c1eee160e6877d95ce97b3a53cf7607c59483176cf55b40b47d198efcc", + "0x8acbe66fee2f75c73255b39489f15e6eaee75585426406d96ce786bf53076b6e", + "0x74ab3f7057275e0769c3356bb7515f108c69b42f4501a9d3873433e22639a240", + "0xe0bb35e880ee793203ad5ea844081b6fa99eeed85f570b6bfbbc0efbdd7f79ce", + "0x5761b5e7f8872c8cc13278f3c2ff836c325f4179b89897d0c5b6846752c312dd", + "0xeda698bc3ec12d8004406a7c7c9e3a16fa085a8448901352ce3713efdac58930", + "0x22138b1713dd83a25b1434813492910fa8e54d8feb9eebe1aa5d2bcb6ec2c69f", + "0x4ce3cfc5b1fe6f87e9830840e85b81ff6117ab62300953524c39bfdbf7868980", + "0x6a6c7372b5c90808a6a966c0b90419b5efc739e5ad5ca1fd0d6c9583ac37f240", + "0x257fb60e826d4a92c030a645375fb46b3790c5b318b56b1a299e09e0e7ee3911", + "0x5f577cc4d21c818bd18e427e6d9ebd8f207fc71ad5f883d0e24eb9f856e3e10a", + "0x0f387595af36d3d5df451ff3de879016c6cf575fc1f02d40d547ee91f6aa36c5", + "0xd8ae5a19d1327025446b5e16d0585740839bf32d9c5798bd39e3e0697113efac", + "0x10e80ae2881a780061bac8bae4514f0df0077152639aa0da1b9d8b3ae234e184", + "0x377f9a9fc5a6fdc69cc76f6f36282cedbe9c83bc43dc345fb49db28ef6b37cf9", + "0x2d52e3af5f7ca108b3ac7cfc495b96e05e2d7f82f7f83ee3234c84b77a1874ab", + "0xaad9190dc0748ae3f78e9e5a3b4ae10eb6bb0b2617cc2d16ad3806bdd994688c", + "0x83b863f21344a6a576f805ed480eb72d3ae3dd06a2979b539a43f2c955429a24", + "0xd4d0622b957b87f71610bf3af65ab018360d320ebf328222df10899830ca33a0", + "0x7ca92b8bf0337d0bc56aab4c1a57e29addf6f0a4b9070482f06a7ee89ccbde84", + "0xcb9c71abfdb931e30a67e7b77d247be70b005076b64fb138be12f260f9c73334", + "0xfe44663a9c2067fe4bb8b43d241438cc63af9638cc1859b5d4c7c7f89318e558", + "0xc962b737dd9438cff5272e16038ef0ca55c4e1b5497d75ef5a0aa53ac6c09448", + "0x2b3a80ef8b20644facd31b5d1618814507c8f603dd8079ba40da09b550f3a2ad", + "0x4664f49d6f114ae491a0364d007724cffe144f4085d91f24f8d3fe87f5b8e393", + "0x1e2456e2e055decfa092a838d2052b12527c6e56b43a787518b121b61f7e316b", + "0x2f45b1ef6d6ae7196818f81278f226f3e0fd535d3a27b63497a6fd208f195c0b", + "0xaf265121e6406f84f7711447d3118c02b446c0d6db9c4ef266208adaa1acc0ec", + "0xbdf275c92443f0755251473e89ff46d741681c7eb2e7811eae25a0f1853c0bc3", + "0x5adf59b0a9cc02fb5bb5c469a52582efec5c317ee1896d8df49d15c18db944d5", + "0xd9aec0aa26bdd240b709a688a0b0565f3543a9b3686b78efeaf070140f2eaef2", + "0x1f4890ecb2250b7ca57a092a0a40b0e4b0abeceaac015189e0f6e9486ce4bc7b", + "0xb0be545c813daf899627b982dae9edd9de72ae54094dd8eb25570423e5c5dbf6", + "0x0f98f4ac26d2966ff4b129950dfcb287098fef2e60c3bfeb1156425fab8db92b", + "0x5622210376d1016d0b7615552cf3d66cbbc2d39d3eeaa2bb100cc2328a81cd95", + "0xe3523e80affdd0ccc3090ce202e7aa408ebaea9fcaa1e705242b948eb15f3cca", + "0x98154cd06a09aa5f9d3e4b4c824f1efdf6eb5ad4b5c0deb1a16a8372bd073a94", + "0x6680dde58fd0b4ee4626a8564f827c8c2cb9c7d0ceb4437412f30a15ad486689", + "0x61f7582008e42c3bedf33342c9c47003a6ce9264c977204ab5ef778f6e6d234b", + "0xa8ffa5ea4717d9f8d55db7d5626799aa102f1e340d80c68896a14204ac38c8f2", + "0xb83aed2db0ce9eb79c45259f66d72cd00546caf8e39e5efe91bd03ec64cf96ee", + "0xae616f4c1416b46a21390e0bd5336935490b9894eaa7c653fd9909086a1df5be", + "0x18f84c5cbad9477e0571574a0bed0714d3fa587ca21e39839a95752e6e3f0299", + "0xdd5d5c64b54437f649d7004d54863160da8db8518ccc99ddaf6942fb551dd798", + "0x72b7fd1a0758b72010c216bc7394a19c1a0cb6620386a8a91c21d3db69004b49", + "0x2dafd23aeae504b4ebd17ed518648939cd63f5e0e7448bd8c0fcc78dceec4059", + "0x787827158ba2f53c21c6d05eeca56fd0fc2fc08026bf09c76cb17583340944e4", + "0xb1a4b60e4d00c8189d940ed2fc070c1238d03d58d572ddd029ae794e47352df5", + "0x33e1420671ccba2d938f5b75d45bd31d90c5b424d9a02e7e7eb4ca60ae402443", + "0x094b7129d1087747705a683bbbe61b13c546decbed3953c7867aef485865c7df", + "0xde05a46ee5e26ff79801bf32d1f4bb4dab2127ea60f7bb037dfafbc16678e1d0", + "0xc81b90e47d6aae3641ddbfade2f8146324456ef372da470b319528114131743b", + "0x2b835f2a36503a9ef3591f1913924ab134d3fba8c95153f1cc80d503c74a1af1", + "0xfe99568c1fc3808ad05d99fe2261b27308c97bb39a965f96119e012ca8ae63e1", + "0x2bc9ac9d5a461286cbfbdc7d6181c795321ea0779835322b5e09381db7169be6", + "0x6cf2449053f134a8ae48a4f0007ac1f8f39d30d9c3269155b8922581a64b5d43", + "0x7ff755adbbfee435992589e1eb09e92532624a9888375497ab3f46d921aa3aad", + "0xe708615d47cd53d7856688d2ce264311f7f94631f318588726b88ef29dafd93b", + "0x96e1a15735e93923060b3954925e8d52b0a4b5cf6516190efb907bdfe6bc34ec", + "0xd33e1c73fa37307c1199ee2dcdf3a0e92152f3f6f9f667ebafa190837a77cc66", + "0x57fa01905f12ba8decb5f5beda857a607e32e9781d39a46001679f537d57391b", + "0x2e5f2df2fb0d327f4b574c0a37c243b7fb4210af7a0796cc2c880252ad8438cc", + "0x26714de3dfeb00f0d8c27bc6729b89d3b55b82cc1eed2999f742c89fab424fb5", + "0x7bd11bfbafe1e87b58428db1f819f4ff2455a4f90db5e60e3d84b28d818a1173", + "0xfcf5fc7965f836dd04e54a9ce577aad76d10464b678259ef1c8bc2a0a0c67723", + "0xdb2e6587cea3bcc6f109e350d6c138cf919229e884a2597e4d6e599c26625736", + "0xd23ff7e12ed5f3177dfdbb51edba35d879fda9fc4ecb2c6f89bbd6addb772697", + "0x0a64a15947b2f5a87070fc3b8171485aac3e131619fb8c88b6bb2cdc1969a5f2", + "0x17d617aa1c6ccbd70ead8237a312152f42926333e8d9165266c497ee9a18da61", + "0x74082588643fb771a733c66b4ddbefcb50daf6742323e05ef4a2604c5d56eb83", + "0xa2cbc98dde5cc72ef8b0d222037f01d308a550ede1f3097c4bf7fa3e36914258", + "0xb7e7d0fc915050bcb17f685f798292ce93d3776096c2b3a252f0fafb4c799230", + "0x6f4f736ebd9941ebb79da6456d8ad423a3711f26d3cb643b81c8e02fc5689af1", + "0x21a21b15bf03238f62f610971eaa96dc5dd41ad45a6be2867afe6206f7ddaa20", + "0x459ef1b2c13a6bf1ad48e62b2020851a4505bcb88923bf0d5ec2408c309b973a", + "0xccb6429f43f6447cb714d4bed7e003239ff6926804185c6c51aabab4b355939f", + "0x5e580a7635cbfb695c97fd68a118ea37680c7408f1504b723189470826016f8d", + "0xc523d6c489334472d1af61a7ba1732195edc25bbf68eb821d1acb14ed5c98663", + "0x31a01c69fa6a86680831350cb67fd5fa06fe8accbd5cb6e2ce0ec689dbb23114", + "0x4fd4d85570c94d03c49e9aa60cd6bd6e684bc77d3b04eb5fc6b2b7f206ba9bc1", + "0x29b8a2ddb612c8c135eeb9f3d8791b603e7bf4d860c0d0b6bab53deb22b2070c", + "0xb156a9272bc83b3b85b93ae2c43f7accaceec85e1d77ddb1343b18356e00d572", + "0xcb08ef4355bb9e2ecc478bb4e80425acb497650f20509e10e134f3f60b216866", + "0xe2f0614ef7265b21deeda6d174341d59b7d13655ee7d473e5c4636dcf788d674", + "0x0727823720192b8a7a66ff04cf1913a31f0dd5b71dc145840533c30e0b7eed06", + "0x4b321b6181092414a3816b076bc86551fb8763ddb401a6923daa9c54c788ec5b", + "0x3831bf3c54c1aad7f557b8c914dc6e3d4c106169175d1e988eb028d160d49473", + "0x95d94729d493223bbd8649cb5117f14c279fac44fe40d1de1e82b7bd1d9261ea", + "0xe2632a472234dc31a473885d7a72e84c24f7883069afed9dbcb643cc5c32af55", + "0xc9bfa80366e9c466df9cda1b1c97de5f627a0142552e97f0554e597b8bc6563f", + "0x345a832166ef2f750ff143a57fadcb439233cb8292124d20bdcc294fafc5cb92", + "0xf8e032c077431b49212307adb00743b054e996e6d3dd101a40959cf19b9ec796", + "0x2243b4956a00a8d2d09275010330f4268d2f536cfa14741313231e6a7b33f445", + "0x12e0f3ff844f21b058d0e311e266cae6d0ab5dce8952d6133a95fb8659e337a7", + "0xf6d80062e8efaef3021b7a747220e713003c37ec733ff8cd15ace6b58ce60fa7", + "0x58c2f923852b77377eb36cb9c26f1b73be98a55c9b0dc65982098e5580ac8e26", + "0xb517d1be70a5d39a4da4ce46821d678257836e6f70621f529c4019d974eaaedd", + "0xa25aa7b0b4c5a3a0f063d4d2493d8b9ab46afc091161df9b1840f47d42334433", + "0xe1795c2a1fc25ea19e6599b070aa9209f2e89a10f0524d8aa78e921c12251514", + "0xdbec5c0577039e79efcad6ba30e0693127b50dd3b108281cfbb4adee3f212ca1", + "0x2c4835b03837ea2310484879212f94fdac6bd2dafbee292ed67f55851053f969", + "0xe0d9e5d1f86eb15c09f41181c96d64fa1ce3a9c69b3ceadad476353e0de1423c", + "0x2a0cff721302a055d3aefdfce14020b3f2418110084c0b1ac1c30a07e3ce988c", + "0xc8ab63d730c578afbb7611167850159fed6d1e73fc3c0b406db19934073ac0ca", + "0x3855c134a5a94513c46470411794ed81d83b29a8da353709035f6e224a9da80e", + "0x6b54eb434f5cb21a1e01b9f067647b857d9b236044220dcfadca3617ef2b568a", + "0x710ae824655688ac255d8046d8fd8438b110d768bdf9bcf4debc9381e02e873c", + "0xde3196ef84179c193b82b1175a417820a9403bdc06c4bfbb5010c8d83172edbd", + "0x5f4e1710e4896439b22f34cf4485b27edf1c35a2b49328eb8f018cb690d4ab04", + "0x37aaadc6f1e57a61a8fd925a6b583105eac77105e167735fc117b347ca58ef47", + "0xc02093ebafb3fc424cef40f5d8699681a4ef9fcad5c8b52002bd911f23812a58", + "0x34d274e1699647b5883100c125da1fce744238bdfe4e1ca2a694a5efb03a44eb", + "0xc14618c6491fe32dcc5848c2ae2a1aa26832343a1ca21bf327ae2a0ad182c85d", + "0x434b07e53641dd82eec95f4b472c1d1d9855ef8492ccd53137ecc82b2bfa5845", + "0xef6763df32b5ab25d8371067949efbdb7f2b9924685918ce3d8068766d6e729d", + "0xe534aacf1e9b44d4464b82ee17ed9cde79ca3a574c5869ff5b6f44d292d1a926", + "0x45ee62bf59e4bfcc76208dce86cc8234727de291de27a69a72bf15ce78488a1d", + "0xb170601af6545cbbab9d707a4623a07b9cb69471f994b769bb534338d3b556d4", + "0x73c8e569840ff39b4dbb24a7adc678e1e7b63621aa77a5533ca968e260d8b638", + "0xad8002631bf3e364dd09f094028a9f4faa5c67ad311838cf65215d6a17d58a04", + "0xee81a28db1d369d17ae97346196672e6f00fd622865cd618ad8447acab9bea7c", + "0xa8caab152258db32f3f03f44ce090e3759538b33d5e557f4a9a4169a0d436754", + "0xfc037393a2fc3a24a567923bca89a7714c72c742c1c466dc0d47296eb6d81b2c", + "0x1ff9e9455c7aa193842f453554c89ab25dd9033b0f7dce5c795e19b1c84b44f8", + "0x894d063e6911b107a6a42a542d99bca6f77192a0852029c0b5cd31a47c8bd2fa", + "0x6df6ca69e3a40334a4c081d74474e00c98ad6793f5cc58b5520be41eff4b17cb", + "0x688504ac6a0ae42368f496f0651e4c1f8ce13fa707a6b98eb52c1f264eac14b3", + "0x6f200669f73cfce5f2f0d9318673ed75c38371476e94ec96dbfcc683aa583816", + "0xff4a6e25786931e08a89007848dba7f62f84a776f7d926bd6983c2d9dd3a14a6", + "0x496c57858748bccddfeee4c5e496119f29a627a659349a4f8f65d1016e92d841", + "0xa5fefc6e3ea89e87875efe37fa9d796f678c6abfdd651897184b52d966fbdbc1", + "0x08e6f4c847dd3aff0e6e45c63939869cf7b007f712ffd79a16313eebf77eb4b1", + "0x00351e602b0508184ea47bad9e47b77071640422296e6574e1ab52cc02552a59", + "0xe1980e52f5fd5b81c96c6c9f1e6baf14bac191388d7e29e1191110fe68d6c88f", + "0x2ba58560d35e709c358a6caa9347c51961642756f4cd28d09b8aeaa532f7c382", + "0x3b8c4425cf002597f470d30c40ca0e40f019d72e33ca6ac54a5c80509bb4e45e", + "0x25da4aab586d49e195e1f9e0d8371d3368e88e3801ab9db750a40df31b2556ac", + "0x9b2693658ec603d976ec25a76c8ffb492d0647581da186a5b7b49bc6c18eafb8", + "0xd27630e4ef91c7144b5db0de4fd83fa53aafc8a463991819a919916fccb66aa5", + "0xd296657df9243ccfa00571774c0bfc0b85a64ceba954b876cb40713aca41d24f", + "0x9cd59fb8b4582d88a9af204976da07e57e066d48bc15b7c707c17dd11536f735", + "0xd6789d7ca6f21a983e7ff5baddd5c7743bf9a76419136384662a685060f16eb0", + "0x38e752a76cf82b63556556042e8cd6e4304d08338aea8746c55ee5864eae341c", + "0x56efa0c6d7d82b0d6b9ef82ea4b8d792d2786ac54b001d77e8493129accec545", + "0x9bb4717f3ab9f8d8a8fa059ef6d09716dea547ad0a1d99eb41d5ef3d21a46d78", + "0x2a616d50d6c4199351074e4bfb6701c3a8a6a65a235a7de581fcf40c6b50eff5", + "0x5a7f0e8b42847b84813d9129819636a60d7f50271f4c1dfac09b7bac0e00be54", + "0xd046e59d18b22e4ad6b9c83a41599afcd2d89d6bfa59f95dae874e8491b1469f", + "0x851c439d105b3622e675f986d249065d7936a7013a05d920bef87e44bc2bb08e", + "0x8e8c4e96b687a26e22a340465a8334fb8594544e7cd652f0e667ae5849cc082b", + "0x355ef21e4e57693374780b2a871b20f361f472074e938e9f33e7b4ebbfd9f447", + "0xbc97e95990cd4a23b97759f2a5ccc45359118ba88dd99895b2e5a3736753b756", + "0xf01b5e69d8d5871473833acaca6d2a1adaea66b76aec97e258bf72f50bcdec41", + "0x3eef80b3124ee89c5fda3a87aeb870dc5fbc781df98e7b0fc1a868acc3b01259", + "0x218a98c02e2b81ccef1bfc460703e57eb8ee5696553cab7b8ce9c95da70ea058", + "0xed6a555d0a858e362e15791f49cca517b74f0f764d8b032c0278becacb694739", + "0x23d9e9207f88148f7648c0955bcccae4138b029ed5b4bf2d574987a568d8283a", + "0x28af6fc0dcb7f57f8541a8b2bb3e781a0ff4d9020cdf26a8119a93401d45eab7", + "0x01989d5a75479a5a6eeb10430746b76a639a9716b8557b7864a1b7b778d265bf", + "0x475611d8792a80560752a9573f864f9ef3153a4c30bb16f7bf1bccb69241a8a4", + "0x0e52e291214aa6300ab1d875db31fbe6274d9769cf7dabef852b5d847e3c6a2b", + "0x04ea3fdf2d26c297c4276344bfc70b4a7645bb22382127f8ce9a621967a54ae4", + "0x64694ef5067706b01581730944a112fedcca32ce9e9103119d9ea4b4b75efd23", + "0xf37ab55394c6233443e1341d03ff07009f1b0771d12b202a78e2789a97e83c7f", + "0x4d723e3c6d46625adfaeccdd1d8bc3811539a7b658050ea0bc9dec625f180df3", + "0xf44e4c0d2e30b8bf0aad255325dba7e2093bb518b56e9c89625f67d5c139a65d", + "0xcd9bdda98c027168fcba6eed7c551291b59613aac11e6e02a00989c93a13225c", + "0x5fae33477d301fda6e6e0e29bb6ddf39c1720aacdf33a4b854806f8a09cf5e6b", + "0x464ae4d9549ea34f25c28ce8daae16fc129adc7ecf71527cfe6df6e1fed72234", + "0x01079ed69a40bd07152e241433be91d61bc1338d83a686d619fa1a21e8c57727", + "0x1f36d242a382eadc149704d8d525e4ac25e0fd2741876022e8bb474d3c726ce2", + "0xe54d3b597d9e37ff213472332bf31a0b16ffc809540c593b1478666019205dd9", + "0x24fd9f8ef011c060d698711a163444b20dde695a1b0db81dc3dc171ad227619a", + "0x01fe14f246bcec9826c6b5dd668b256baba5939749ed90932a603b1cab47fdc8", + "0x6e4f521a4824ae2306c046f5545c2f7ce911104d9ac1204095b8951ef5d63cb5", + "0xd8f0f8bfa160374ebfc90fa7966df4391c1aecea802e3b04a03c087080f01fb0", + "0xb4720294d8b145f29af00f220e076b271b587e9af98653efa47e2d47bbe6d95e", + "0x93223951fd8a31a3e6c98fa17cd33086e8155779930440a7c2fd25eca31f682e", + "0x752fb11e15acc591e78509137beb18cbf177877e4a9846bd33acb1a6426d1999", + "0x3304e2f07aafd6b10cdce727c41ed85ce0fb80e59fee6b96b9a2e98f73280979", + "0xa756425b9dedd5e6c2197ab4a76c14e76b250d7ce4e2b8ada00fc61e9f62dae7", + "0xdcc034de60f855c63dd2c5a9cd4930a45a54e416558c6945cf8e058d55886d32", + "0x77ab21e42cd147f95466d22f5e95e965e38ff22938eaa6b5bca2810d6a9e2e4a", + "0x65e59fd9132b911d65da3c1094a6b8523ed5d9b7eb8822b8d2273b55ce4aac61", + "0xff6aba7d3fd54e3948829cb59ae47084eb809481665c5c09300b834567ee4b66", + "0x0a2b95075de7b0579ccc23f174b3fdf6a4ce6aa9a42f1ace679953fba0956d41", + "0xcc6f0e601cfdbb0631c13df4decb454d5cbd554363694faeaccd4edf16a9ec26", + "0xf2937d3b0c62b8f47cbac34a29d0a7fe92ddda227f984ab360521d5168274583", + "0x9f0e54b594397e29868adafea8686c5e3536fe8ea767274e277d77a5ef2917c5", + "0xfb8ec9c26eae16db5dcd2f05476d89416d2c56a841157685dbd1653274ded2e7", + "0x07d71ac9ba4b3f0a616205d182155d7a34b2463c2db95a47b8d03a45382b8e18", + "0x6e5d854c2848a36b6feef20c80a87a88a40af50888e787652ca54601a7d37d90", + "0xf9bb21fa1e3d6af9962a9946d7fa4430708193335cf32766ed56aca50fc368b9", + "0x7750970996ed6e687ca27f08481be0fd426318aad87cdba015ce129dc896b41b", + "0x4ff8c843185d1b5b4291788c869ba3723969d2dde2d74a9b8fe27ba71da67ae5", + "0xd5730d698ac2ab71bc360f24bcd7a71b8001ddc86205d7274e636bda83d8e3a3", + "0xde41dece62466d3ca8700150723f0782fd624162030086be716485e12d5a93bc", + "0x7a709bc4ed84e8bf45818e0e918115d686504fa0dce6a3bf8513d0bd488dd39e", + "0x620fe2d0affe0c46bbd0b74ab6d7c3bc6b4950915cb83742c832c6117ea42347", + "0x542ee63637f2115e11a3e132bb4246d809232772e08b23401eb8a8f0067a4ed9", + "0xa284a3dfebff214c436ad67d8a36162a1810bd7a51387ab68188267a1e166d2b", + "0x0ea68982e12031ad38aff543ca7d623ca8945e649527eef2afca28993de42ebc", + "0x1249a7d56112d4146105a1f257bfd399f18aaaa94ed5198df8634c89c807d4c3", + "0xa691469bf6b8f7caa8559865c0c99f77350f41e0de9851dc887d850be5809cf6", + "0x34ee8cca77c5b32a79cc0a6811cc73910cd0353fb860171443f08d17e3f18174", + "0x73a7b7f8bb18df6038c0df35ee55b0fcb4735c7e0977efc98008c710530216ba", + "0x0a8d0b414621d022fbaf4a1c0a07169e879a857fb105637cd8193633ce755f11", + "0x36f21a7a7d142d026e9222b884b583387f10ba692b1cc9232a32ab401affd684", + "0xb5b69e29e0558368a8abc4ff3ca022d158fb11ac6f2138cbe0be84b387e1ab7c", + "0xa57d1845ab38ef86763a374b0323b7ff84722941b06dde3c5cec61de40c9afca", + "0xe8063bccc4fec0a51a6d57ff999a7169e15d93c0d7cc3ed57c065cf8afa912f9", + "0xe9b89463cfd719b357f878a927bbc72ca3d06f8b88f9a5c8568ef2afd3118ed0", + "0x4f2ae01579376ef5a2ac6e849cb2d3befdc4e5e814a5b8de31941183697e51dc", + "0x6356b87dcc8f1c6c83a2601be987b44f77180da8b8d8186e6c61eec301ffab06", + "0x4f2918a79394961e5802b8aed07d89b3b5b459a3d9706f0749ec65f3b3d9ebc9", + "0x145016d42f0052f68aae089538ffa956cfb2c5a0f26763fdaa940e427bea7ff8", + "0x897e9dd36d2c12e8941763ac6090321db8cf73de4319c99f5e4343d5eacc856f", + "0x7c1cafd66922a53506f93d8aeb80dfacc9da69e6b73cd3e4a9779cfee5e4f64b", + "0xbd76e3eb8ceeb1f47ed865351b54cf491173ef562a51f068966b71cd294766ee", + "0x600135fd75adae0801296f92e1a7219287ec588fb4627d18095887da1c71ee2d", + "0x1bbd55de061070b1060b4184583e9b5b2e307197235c986dc1a3b942f64cb107", + "0x07e182e958faeacdecdc43de50c8d4226c6f697d7dd4e2ca9754687605719068", + "0x3591aa6b10db91679824f182cb58ecbce7210444314eb4b4e657cbe6518a55a6", + "0x8948a1a48823911e4e16b54b3cf789c8b04a3c26008f97f3c71577a22c23cb02", + "0xd37594cbc0353af27e1e70e249db20f3f16bbdcdbfee1ded9bbbb178c3454d3d", + "0x639159845a1397fe73d7ab041d7d9a74b99ad8009e3d63d37f329df35afcec0d", + "0xe41e444d9f8b0daec348208914d665db316136f42614013a35e3c7e97e219dc7", + "0x2ed6880fd4b6631ee593d3161dddf19021a1365650009d01e264243e032f4f6e", + "0xa6e5eb641f39345184365aad2c9258d21ef4b7c65ee5dba93825aba5e8e481c4", + "0xe2880fe0d6e512ae4e0e78a9249f6319407ec2def2c5745292b750d16cc41786", + "0x54729b299e086a2ce795d339e5e20cf87afdfeaab0dc6fbbd0ce5f55194c319d", + "0xd3d3dc4b51e0d0487c9a09281e1115f593bd24cd09a113c0f1a89468ca1ea2b5", + "0xc86f8dc093f2adaf17fbeda345eb2f4ace3df6d5bde0c99e85200eae84cb892c", + "0x84ba70a7754f31ae366693375c5daf4fa38f7f086791c1aded55198adfb91392", + "0xc7ccc21a8a1b96591c32e98d2c7ad358279c2c1bf6bf51dadb18cb9504a1d751", + "0xdce9df5d5bc2852e8fa61e254a9aff0f03628659df28f51dca37a5a6816bc479", + "0x6d0a555491a6fb3f592fad8b97754d02bc6166257e5a83131fe9d859e05d1531", + "0xdf805b41cf7c7b9346ed152953e6334cca6725a6428e81b9fa4227329d231ce1", + "0xf94a98ffcfd4e28d863e790d1d6f507445f9e64165b3937b0c40af11789d5296", + "0x56723b13f5112f637e1e84c18bc3dafcdbc40508bb6a88c68f3a46e56f5783d6", + "0xd550a9d0bbb3745e7f5b7e290f6755b030cab20ecb6f5daf701dd3850737692f", + "0x7d88f7a5af354de5678a270b8083ce441be4c1bd6875a337b244d93bd3cf0d2b", + "0x52b48af317cb248300cebad6fa682a741f3dde7da4bf0e7c4162f9f1607e7d68", + "0x04a7147b282fead783019f3453ad8d95618f416eb7ac0d80cbe3be8f68a13c31", + "0x4be24f18efeb4c1f8b12f124bd1f48d3edd1777629094292616bd89ad580682e", + "0x146f8719d2e7f74deb3619ce6dbb782850431bd5a5fdf5f5d2dd33a54874f536", + "0x6497f392deeeb3359e35622360f6416da4d0986ef0770ba22876cf1990e5903d", + "0x858d7fc84e4504c9e5f54cca2c9facdacd309d742aa7657c6f90e25e4d7b6f84", + "0x6fc455af373dfa77825bbaa65b1539e9eda251850479b83db15b9be2b5e144c4", + "0x3893304198a242335c96423344d68ffeda11c17c9b6c5785bc59482c385f60d4", + "0x3b2a22d6d87679b173a1e82db970e6cec44179be8218489a8aa863b7603adc3d", + "0x52534879ad0d442147ca743ea21fb5dde78510c11da353fc21636f9725f9609a", + "0x194e094c77eaf3973447de9faa29007b7b895e3c855cd01c0d5609e478df10ae", + "0x64ca084e56ecda7e9f2a10b0b2262f29d5bb8bd361019367dc41bc8f97963961", + "0x05754bcc136f5b541e59f1c40c99572fe188f6f2eec3d91989072ff3f3c1ceee", + "0xaad0bc1df434492344bf9351345d3288340aff851f687f952e84d968e1a29afa", + "0x90c5f0e124e125b2fae5d2ae5c8a1f5fe065ac2cdaf62829733599c69f66d674", + "0xc20d9e82fda10425082d631b6705815ac17aea924aa2ca534066d76734ed1bdf", + "0x68fc07e734ecb1c3951262cf804b831ff32e285246ebeffda3949e62d31d937d", + "0x7e472ad7b556415586fb5950e8d0b85e895b8c9c7fa31952936247c8117fa0b6", + "0xf5c3457576bf1b624f0f558bdba237ec349349c60926eff5c3ba8c55b32fd6be", + "0xf9c3dd5d7fcadfe33b2dabfcc4f732661985a72166afb8d16486028b89f35bc2", + "0xa493336b47637629c4bbbb89e8c8e1272722db0f7f781f4f78185d6125f0e5a9", + "0xc8cab7f153c08cdc9607263c5129fa8278a7228188c950806d5732db541cc59e", + "0x85c0c18f11c32eac54537d2c492eb9cabea9a39d2e1ac56d8087c02f68f64bd0", + "0x26a001beca07a641ad1e3ea64c63e395c436836d098818f937b4354b7a925122", + "0x75cdeed9ee0eacc02eef853a54a6f0201693cd1a60d26e504d5ef16110ede59a", + "0x8e4a5fd1a18f9513cf70dcfedeea862dfa2b61cbee80fc204bb0315a2c051424", + "0xa42896ce30565041da64ffff0a80ee6a6e280d0459e5c29c0fa3a79587d4a330", + "0xe65f4193189ca1da6d6fefef1c2f14bb340e56271b2bae3024dce98dea451cca", + "0x48c844ef658f2270efa4be7b85879cdaa2d7cb27f5fe9cdce0ec4389a5801707", + "0xedf37c427ac85a7c317bce25f06acf626cbe86e79f99f148667a95c03ccd34c9", + "0xbeca93d3b7e0f9d2f2a6b9b9ff7fcfff658c0d417830e46a3aa233f31908782c", + "0x61dac332da33e3533b9eecc1a287e732cfb9a666ef32de6bf2d2706792264927", + "0x622624f3810a1e24d48f54082f0df3ab3227c9cf9d39b007875a3428e2d70208", + "0xc1276025a1c848b7dbdd6f4dc1b7b2f4b19dcc7b0e312897758ca538ea334bff", + "0xefa6b7d35c2aeebf0d472745aaf6d4118279a88273b7513d5a21c3f619af8f76", + "0x2250fd4931ae5059e99572a7bfcee0117090c362075c0d90eda1ba2be2c864bb", + "0xe9b7860868856d1ba5d17cfcc78020485a36814482e1e8812555094dd4e85ff0", + "0x4df6b40297b258ae69a8858e54ea4f45d58b0ab1b0f1b35c3bcc4f96c928c58a", + "0xd17bcb3447f309b3ce0a48b651de3d979810cd9cb7edecb9b44366644e25c729", + "0x7292155c0cf9a6466c80ac2930f8305cf9458f64f40523a6b5e08d2ddc180080", + "0x536bc35368df05c3d3773b27110217c2df04d2f86e6e8a8dbf9dcd13cbbcb984", + "0x0f4dd55ebf1e1ea736108e62612972036dc533bc4e52a8480e3c875a7961ef69", + "0x902334a20d083b4634a79aae1a2b4158df3832d4c7f9105e8aeb8e38ac0be589", + "0xbbce2d76e50b1150179456ec4ce4faabcddc8700435675ebe94204325ee6f710", + "0x6cc4afc371970811c0cbeed73acc72641066edf1d81a585f28987ca1c11e8ed8", + "0x7cf1f9f26bdc8c7ca419400a03d683564bd5947068e4a01670200358d339b12b", + "0xf1e37f56a2eefc9688ebd8a95772f98b9f995e3fa9ba6601095f973cd34a13aa", + "0xfd7ee922a80adc2f6719e6e1e90add658033c7165441e399a3f61e93ed56af2b", + "0xd8ee732eedd804de6063af6b828fd6c4d9496115a367cfdd424a035646cc9e02", + "0xbf6658fb5940aabd9cf82fd9e808c9a23d04d171a62d0601d2c9dd67009f0b36", + "0xaaf7099280336cb78b87d9cc3c06694c4a66aea2a095ed614a4578fa8d61cbf9", + "0x46e23a8b56b9061bb89a42253998e7fda17289a12c63fd239a0c2866df529f3f", + "0x19b3323694c1dc611fe3722987d1a927dbf1a1ccd211b3c148798cce7b814fea", + "0xc16ac7ee79c7ac2223f79bd97a193c3bb68f609affa1596b061e9ba32a4978b2", + "0x5b929b2451c9c284c40c745bd441e1db499e336ea8a0b616e925ae780a6553bd", + "0x954a69859410a4a8309ddedda3f1af305c0baf02b1c0cffb27c0f89e629e4dac", + "0xff44052a4c53837e32b9bf4bc6080e78d3a78108a69100bcb05a85d4cf9e65e7", + "0x6199a3fdaf20c64b9587cf303682571f0de0bfcbf6ae34b4cc20485228a39043", + "0x0472d6b6c1efa88008d9931b3a1348a8892a61897e8634f2416758667da516f7", + "0x566bfd31096a3829990cc587e64e2a4477349e91b1b37ad6100be6b3de6250b9", + "0x5f51ac85ca1ebfbd382b4d60281d3746d98950aec6cd6bc1ca5ab22eff929a20", + "0xd45228a818a9f5d8325d2fe4873ddf5b0cccf4bc6ca907a08887adc19223936e", + "0x71d00ba260caf196d91b48601bb92052272067d1eddc4492f8709c3494ca253e", + "0xea6234921dde61659d45b0c36da969b7d3ed641c53cb54392e5a56da9f8df1d3", + "0x5a0dd2c3c892862da0f65bb4be26de9984c65aa2ff90526e6deaa1a3c079e7ac", + "0x18fde3435086b1d71fd5d24888c99bfcc2d4e7146ef4715192f4213ee9af70fa", + "0xbdf9a94e2cc27a784153c66df5d7f25316300d43f5a802cb7c5d6979a502c23b", + "0xb111d486bad8fddd2cd7d22e49d3ea3f4a0177af6fbebcdcff7f7f6585dc97ac", + "0x56921a22df9c98a49aa2602e551ac3e3d07f857faa228b56dd55ff3962f2646d", + "0xf8c7cc4743849e6cae415696d543445b22150afd4f4badbe9365f169a8aae3fb", + "0x8b9945119a385c746b1eae86d57e2a53453ab4183d49aea9412003a5e815ae8b", + "0x0dd84a3fbdb5a44b934a223503e9dcc73f893d35c77c3110c005398c640d011c", + "0x0960711a40b3c268874fa251c6c642c9e43ab14adf98daff1bc44949ca4a472d", + "0x4097f47259eea82fa8a531ec8c32b20b0064a0c47ecbeb1c426514498e5cb703", + "0xb17fab14bf8cc4aa51a1209711533b566b907d83f17b5ba62187681951307e74", + "0xcf522b0a5f9c427dcd8a7c6e358b7bea8d683bcb1fcee19fb3ecc05b85afe281", + "0x61eba4f90383706a2220ed3ba48020c14b3b6f1b76bedfdd3dd84cf66e7b93dc", + "0x112dffaef31440102f9660a5d73880a7df7b4cbf3c5189b9cc86c7641ac87f21", + "0x908edf9e1920e01592cc0478bc15011699771fba5a3624296521b1997e409d06", + "0x44636c1768f04f94d933c5d93679572d01e9d69f88251e67e8ccca7a50d63bb3", + "0x146add71dd815d75bd46324c8820e2c3d485567ad276f0ce1e2b63c294c989cc", + "0xc3cd14435b5cbd2657f38726908aefd18b21d9fcc82e80b7e1ab0be96a13a2a2", + "0x7d9cee568a4ecbf2d1f980d8946595bc599bf56ad6b07ffb2a83e3b479b1dd07", + "0xfafb0df45cb663db42cdbfb09f7381a49fabaf9266f1ff788dd31ce22c30bd55", + "0xd16d87925d29d26760244c938cefeb1366bf9551545342fdb7583325e08850f6", + "0xc6186d21f0f3391a8456d1b1753da24806d02cb9c3391a40c9fe84143d5ce31d", + "0x14b9cc8f7d3e37d7af07f80c72ae6528b326b146c6380ad0bbdd8fda89d225a4", + "0x5580ba4d7233e13cce87ba2e2607db7a4e87e571d5b1b1a75887f261e03d393a", + "0x07b144469f1d123ef7249ef2c445760a995c2c70f6e48e6e166d5f3508f4333b", + "0x0d883f633ceb91e413494b00e9dd563cdf121d2a2dd397baf4d29f7664633475", + "0xc619796115f48419208b0122a9b18a0bbefc05f8d96c39248973d66583ffd8dc", + "0x994e6fe6c27ba71693d04b2e02ba9c0d8679d1b10fbe733240ee5c323ac5f936", + "0x88b987ef2d0f823fcd17ed43ab28bdcdc23d23127e462ddafe56163e4be4a980", + "0x67e115f2ec5c6f6f7983b4bc2c2ecd21f639a8da639da2a594b018be2a3bfe64", + "0x8e4b8ff44b5028560b047780ce05353c94fba885e186b1b198cac5e90a6cb990", + "0x0a0fcd91048ef7e0833552ca444ed59d74fe7151190d57e5b7fddeb02f119300", + "0x9a5203fa1af89bb99c8d2228d396731ede004ae03afab9566195b89ddfa51a8e", + "0xd540a1122c44c8e728a78048884f79fbe5367873fcc73cc46a9d4b5b4848e3c9", + "0xbf8a42d56b46f6036c6382bd1e970b1d6b5f72ba54d1d5b8d0a3edaa165b7165", + "0xe0262a446e33431abd61bf3e199fca97a575c7ccb97710c2a1847188157909f6", + "0xe7f717feae9bdcd172fa4b6b701f0ca5b58671f9608b5b5a01d51a048241418d", + "0xc0ee34d09069301fa5ac3378ff176efb2b526665925eaf67965699c8fa002c8b", + "0x241837a9dea17bf12b78b30255177b3f14f1871a7b9eaf5c964d30eeb2038212", + "0x2e5204320b7ff83e16ba9727b5df0eab080dd2ea374db22a664f0045540ad936", + "0xaf4e24e4430a008265a6f113c097729ba1802e23d119ae0efef2f2a8bfe4ca0a", + "0x462b2de54860e6d8efcbfde08b381d74eb8e61cd2b311cf14300853aa2f9e88f", + "0xfba00f6c3e6262fa9f282d179b976894376e7e644c1d745302cfdd21cbc3e311", + "0xfbd6361624060852c33c3199ecf0fcbd8e56549d64786d320850ef3911dc9fdf", + "0x7be237a921be1921f90265288026ab1ff7d951e1412bc93470e09bd40a17ce97", + "0x64f51dd23a43c312e57bb2c0da1fde00b48b36eb1c9142589bb66407acde869a", + "0x721c44f4450bc4d92330caf7faf277faa1f10ee8f4614f9f903b27e8b82d8e9e", + "0x71a65acf3a07914cfa45698674a9fb1a35618e6f849aac0be337e44afa7b814c", + "0x620969bddd7756c5d3990528b1ac4dbc81becbac02843b3c4c75ee991ebbf4f5", + "0xef0f2a4fca1191d5615ac096dbae87ecd3aa1a83c46c43a3cd48395a47b2b65e", + "0x5f9bdefe969c0554757a1bf17d990451a58cd2ac60cdb521679081699ba4c2df", + "0x8ffa4537562335a6e21036f6c3af75614887e1c0e54bdd719f53c4675e4e8948", + "0x700d67449ab43081029dd61cec4b31cad71335d822df7ae4053e5040e47090ed", + "0x22a9ede76ca8f831125f7e6d1600aa373934f0cefa888e84a0481247b2c98d2c", + "0xb5b7c6c9ca26d8981191b27dee2aad72dfcd7e6d135d09c3b0b5bbc6e9d64849", + "0xa24232b8ea1e1ef8a07cce001d37d148a07ecbf0792690470c106804476e61fc", + "0x254935114b97e601fc5653001b01faa3f0fac11653926e749cb114cdb8239874", + "0xdec3d44fc5130107d8270358b91d7e0d933e74c4bec6d97cdc9b6f77a1fbe1db", + "0xe947a36694956d7d65315377c81225aee6128c7f075c2a37db61b7b917599008", + "0x4451d920ca782f22a3dba977235c49a4e3b97d8de1fdf9cc9d819dbe7237ddc7", + "0x234caa79670cfa3aa39b37887e2cce3f88ab5472bf2c2e7063b9c9b9424b20d2", + "0x79d8c448a7c637fd4f4e545968bfb5fa59a62948bc7b9031eb4c17493efb41d2", + "0x0b8cc0552966a5ffa6567c51ca7e36f5ad1bbfb5dbf5a52759314721d4e5f463", + "0x774983d323706ba773f8058519a450ae096be9001790cb5e51d00ce1ff206b46", + "0x0dab876db72ff5b208e61e18360e37b2fa6425a3eadc178fdcf654ca273374b0", + "0x20339939f9a89a1c38d6a2dc5ac9a505f2f899a158966cb18775831b045baee4", + "0xa42e2405b8a4a4da00dbe1d2e2a7244e2270f9ce16f054128b93b076af58cb08", + "0x149f8b8bcc176aed12a041b55d040b306ea7d34cc84d5eae4dee06d7a1f204a9", + "0x9b8a117cd1948845b4b98086d80c3ba055a138e471fd3ce38173e3b06b55499f", + "0x22db704c6cd8a8efb8ba974ec4d0ddcf64b1396aabd57cfc271e47ddc5c66363", + "0x25366f36babf4dcd6a41a218cfc8007521c9934f3b70a6835eb5490ce5c32937", + "0x5d21555e54954b075214c3eea858256b109667ebba80b117eaf08a11d4c9a9e7", + "0xcd876855021bdd0ccfc05ae507c711b9ef1ddd7aeebb7e2d330d1205528fc2f3", + "0x09355ca9b36a3aeac9c496af56af3719df2e1e052a878731061720e1b77ff35d", + "0x488d20b385f25d7c6519042136ed3c959a7b341d0118220407034b9527bfa040", + "0x0c516cb443e22322e176465b7c2e0359823374cd4aba574d4104a70e002c1f37", + "0x586593c505b94eba3ea1f7dd3eaa1ffab88548e150997d05b336dea37cd9a971", + "0xa1ebea5af17b8c85755ca5693fafdb4fce32c5e1f6b87127b3306138612d3ca3", + "0x7cb91701609765f3df12a2c051219622cb4a662507c6a14384553364de076dd3", + "0x3d5540773e424e0a92c40204f7c531efcba2467d27d204e0f3c6e655b44e5c87", + "0xc59531ab703c789a20fdbbdd08179893bf671c0d2041631c75d4221bb865b3c4", + "0x7df727560b0f89ef9af22de693230ea551e315918b0cf268cdc07f10690ef2e1", + "0x6d95bde1d89676d0efde7c58d71f91cecf8777e701f7f02a59b9679058e67ac8", + "0x225dae1c7d795471bb2498f380f2a144bdf457734cd3090925027375303e840e", + "0xf14008b13b4db1498bb9a902f1468367e0040cf4d21922ba288adb2a4fee0a93", + "0x36f293cff22d6d738d3cee9e22772f9e3a344a5eee2caefbba321054226c4762", + "0xca2c1e34994d1c454d4abd4b2bf939534a2ceadd6c6a3103d40de4725f77e403", + "0x4c1c6a5ec4bae84cdb0f3252b9f721da9ad348ad1ca6986ffa5e5735603cb005", + "0x0d35e0d8950362606c804221ef0b5feb04b0ad62d5d90134bf1fe119bc5a9eb9", + "0xa8bdf0d3fc34cb80cd14429fbadd0a2d73273e454d96aae4448f60c42f0150ab", + "0x11cc9d0d3064d5c7468a8c0a4146df476f254b7bd8f748fb42d899ce9964ffff", + "0x6d8752e6f51856b90d4723a34d94db4aec1f8da55f2b0d94f263ef0393dc57d9", + "0x038a4fb7f9cea5e3779a026873da89b85d03ba8c9038124eeadf88fa85696f1d", + "0x9d55a956aa38c72d7fb45f856c440b012ce8969c2990c7e1fd48357daf8ecfa2", + "0x163ded59e9ba07e781e07a5329c2921babb49be1a36bc7a54e22b3bc325840f5", + "0x0afd0e16f53b05aab3a77749fd114b353fc848d5e17dd8d701c37baf5c976298", + "0x5ca8f5796743e66d24f7dd342da174ee646c60dd8bf1e7564a814ff28b0922f7", + "0x5e856feff23db5b9892430e9e493b10e2fa2db28bf6833523f158ec1946eba82", + "0x59dec8e839a2d9ba33a5a687fcb92d8b450585864660c202d7e79bbccfe49f57", + "0x8b0a8363e98ac24707164bc767c0f6df7ba6b4ed5584f14693a06b08c3a23c4b", + "0x9214f12639d8f39488579e8265d33850dffe16aee099318da700475551da4ba4", + "0xc98baaa91e6f46d6c218fdc79aeab7d46063fc22107e457eca0559d500489d8d", + "0xeed3ee9c8c71a9035585dbc7a69f91966ff45ca33d81ff0ac69dd9ecbc05df05", + "0xa4b2f4ff38e28613f5ddbccf9f8b4cd17cf50704e398ac3b9b7be043d631ac36", + "0x7de22d2449411bc1e342ad3ee83af0aab2461dfdd7dd51b915a17fbf4350a660", + "0xb644191de416e8385167f5ce348cc3fd3020b69aa7f8e4ce4b58d796b401e3aa", + "0xfa137d84153b3ddcbbea95c810592ca1d219a825a3a9144a1f60a2f15890d959", + "0xb297211d2aa65b91fdedbdc6445e56c012e7d4e99250727f0f18471a204097d9", + "0x87c07e37c34bf4fbaaa2cabcd7c72842828fe0bd4e0af3dbda59a8b7dd8f5832", + "0x60a8ed3981341120c3e6c821f09332c6b83770357dbb1bbcb535fa771ab9ce56", + "0xe79330fb9dab7ff5ebd8511290b629e0feb97ed3907199f47b422e2b62192cbe", + "0x699c36af1b18f84f1443cb7dda84e24eeba099c59b2a3d45a9757b528a459ecf", + "0x0cf4295cec116acd9b74e3ab126b020e82dc216259a40003f493f15d1c89a9d0", + "0xf89bc33459d999b54f77f66ec80613d2b4a7d7e5ca5d58d5d2d9f9f65d9947d7", + "0x2d3a04ea977f6aecbfb671f1ece353c899c6597660a945c78be66a9c3868ede2", + "0x064e090bcd4bfe32f0b9a2756a01f2764d82b7fbc71ecd6eeab2f018ca1a0237", + "0xa3d1be5a6aea2bd18f5ce206e0f8c2ca898e4d4581d2d9ef3bc1b62b86b4d6b8", + "0x3be703b1204cb9800e53bf8b1521eae921f7f6567080f9fe385e712390d92161", + "0xee5c0b22d83a67a2a9ac8661c79d8212252dcf7d4062420cb57878ab8b9dbc66", + "0xbb9813100f3153ff7472f61f97fbaf603f228eb6cd715031018b913c70070d52", + "0xe416f16bb22dba18d653ef75e374b73722723a9f426696ee7477598e1aad6458", + "0xe2d51294dba9887f33cb3009ce096a4e9d086b3bdb114fff71f3438bbd784a0a", + "0xfb6aabfa3219f4401ac3ee4bf697052aec4cba80f755208b42fffbb1b0b3b1e4", + "0xf4d28c88355ed07f3c2007b9e8b7f4e6b1ccd988ba2b32fec0733d57a178d123", + "0x824ff2ab95f74ef02726a483f38342338c16d895a1da8cee5177ee1e4719e465", + "0x8aeec0b4a40bee3ae28552df14d4b6855ffacfc3d01ccde285e66228abc0771a", + "0x5573c773bb5bb5c5236109ef3eda585d2da1c5c38eac46b908fe283c4d519145", + "0xb82014148f595f5e440b729035cbdc2490db0523b7d00f9f0fbd4c383090fd4c", + "0x3bd847f5f5514f396e663821c8865296e3d3f7e817da4e93ba1c9b98b1758812", + "0xe5bd2846840a2049c0f78fddcb4892639156ece271097b56a74fd338f3862066", + "0x916ea84d9ed21144b3f9d73b03d02fbec444449c3a1f982c30bb20c0f75e64f5", + "0x2c7c705d9ec24d6cfbfb7f2bbbc46aee8e3c81a41becf39a23ac19df32dc19a5", + "0xfb9693cb2fab44966e6a0ec4c118a68354de660ae0bbbbe4da349df91e231fdb", + "0x64503206586c60381d9cb74e5f548e417ae80767d48e15c61d2f08f50548b7dd", + "0xc7bcdb552852328cc3d511538e3a0c94dfe1b77d489f3a44cbfab30b3b781036", + "0x4d68f37bbe1a45eaa3e72e3543d23063a4eaa1d38ae56909fe11b309230c8632", + "0xc21a5df0d75ec8d06498535c40ee76a330eb90add0cb99b9f0f4671f504ab1a0", + "0x5558d71b23fd39caf7021402520090f13b50cba5edd669ecf7eac05196e03531", + "0x2164e1ba3b7d927af0ba644481273ccebc5646e2c49825d456a1e75fc7c80db8", + "0xf10702b40b03ef7ae672004cd1747705636f7432a7493021aa8c900397b0123c", + "0xdef29e2febf8fd4a3313106832f3f723469f352f614f20e7d0e6c2e298240060", + "0xe62566d6d85c3ca3d33b8daf61b518abe76b28ec26b91a0b747ec3affab41285", + "0x1c286207dfee4b99fc86818c7614804782c8921d8d8f8815cd2f190f42b992a8", + "0x3670362acbc89076aa41149033484fa2cdaae47c8c10461f6e886040cbabd1df", + "0x8a74d7452f3a76bd20e2d1686243b90243d3d0b40b5b98fd313ff33c8d932e70", + "0x13f1f59beccce0f8d8066742249156a5dc0f21918588b6b145ab40d3eb4bb822", + "0xacdff4a0adff4cfd4756dac55df04e23cc1b9a6447d11d9bd86361fcfb6534cf", + "0x54fa4bbcab952b44cd3cb6042d6ef87fd9131f1850b8de0a44f221ca20a490cc", + "0xa06748708ef2e6c391d0d11c6c8043d91f9f1abe8292d55d70d616ebc5a94ed6", + "0x64dd68699969109d334ab59d64d8d22e114382bf2ebec5fc7ec66875a795276e", + "0x6e66b02d463c76d3a217202c527f798a4c472b37b234bbe0d3d8e6c16a34719d", + "0x3773853e93233b5c39d7bd53b89b769aff1504d9ef433c46b3caca15637ffe93", + "0x817633f3cc0665d68f497362bba1d32d3512016b2490047a245175654cc3d851", + "0x41e14c9198fd548c4b70963eeb24679cd7138dc061988cdd452f2de7cb85c14b", + "0x9ef5c3f4acda962833a68cf1298198b68ad38cd3ef9f8dde0add0dce93e4925f", + "0x7336e43b284042dabf2326e15f9717399fe3d3aee9586118a6047024ce3fbaac", + "0xfd037d85e4f6d39887ea64406302acaedb64a72c1ebb122519c2fbd236d789ca", + "0xa28129819bdab4818cd82aa1bfb0d31d642f66b6f072a079bfc414cfa6d7385f", + "0x02b7d36f55c39b97e2a882d47bb150dc74bab3e3d3c44a13d0149bd87f653f82", + "0xdc6609b3e7e5acd44d8bdd69913d864061c4c5b5d34a24a25c04affed384e687", + "0x0c5adc52eb0e98c0945a821a270e00c1b8424fc88eab4e4e53d8b047c2990509", + "0xb47060a6278b3da926c799a4c01e9682b2c38b9a255427499c03ee9305156939", + "0x8cdfbe9548608021b7fbf4a9845bdc03d2187885a25972f434af7706d8e9743a", + "0xf29db31d7986d96f18766658ae38aaf4210b22bfb14ddd1ee7c8e6a534292fcf", + "0x2be2578382bf5a26aced019adf5e1be8eaada7226996ad0968b41e0211950064", + "0x0fdcf225eb3c840d6a9dab17976b86c02a3a2ad6c457d8ae90a90120cb71239a", + "0x04412b8786da3f17b29aefcd1de44359ca334d551e4b84ab93ef562c16c34bfe", + "0x0be08908e549fb47570db3f9850a43dc3bea22fb569e7e56763029c2612f28dc", + "0x43312d35db155b984f27756d5f74c5028a9d182c346287b6d22318d6d09fa287", + "0xd99d026f8d05e8301728fe546ac68d0b7161d4c5f39d321d81c2d84af8dd9479", + "0x2aa222445dc7ce013979a51aeccbb0331d0b9618bd44d6eeb41978402d787a4e", + "0x7106550433791e214c8d1bc44a6bb74c13cb04ef44d888e4e86618a7699a6c0d", + "0x4cafa83063379aa62aec4ab93ea53b6ee3340b567bd8bea89b1f576ab2b32def", + "0xaa19fc5e04747c49682a08a04e26588ff2097586546c7e6307ebae3faff31ccc", + "0xc95bd63ec24007b5bfb3f3b62b358e32b7c4b562a3904d858b30131ae5146df5", + "0x33aca1207ba456f03f62dc351c975ee927b48d2c9ba394a56e955ab1b2cda20d", + "0xa3d6317111e98d624e5a68256f142ad3c99c3d2fe997650fd65d584579f9d6dc", + "0xfa3d58b3b49da8411398ed8b288f70757be569475c02f9ba23a4d913679b8ae1", + "0xeb470c4d3513dc24664d00944e9fc6da9fbdaacad66900accf0467ecff11d6e4", + "0x9a339d9d68706dbb4300222a5ac8b5823ac55af237273e0aad0999aeab8c72b4", + "0x0b67fe0a96dd8688b8fa98ce128e025402173dc49e0de904c390ddb828f059ee", + "0x634ac8f82795f1cd08f8cafdf00f869100f84350157e12d5a87de7d013a856cd", + "0x1530833bee82f5fa0aa8dab062da230024ed503e352de3956831a92cdbe36199", + "0x69b26efea6cca6ac3ae1bba540db8fb9288e421163bcc50172669053e7751584", + "0x8a4fa2c094135582d17b7733f74e7fe4dbdd0ccd0e5671696739639b64752c5a", + "0xfbff6abda57f9b1689cb7ea8809555db3efd4b21b0b2b1351199654d044fcca4", + "0x16425718846535b46733b84761e16648fa7eabae0e5995108a2fc6c3f324ddf4", + "0xc72eb88c5161469517e7980f86ed414b4e5e54dcfa734e2255908100795078ee", + "0x91e0e6cf1fabea993097496cf7ccfb023e798363bdf8a85bb5e73866f1442ab4", + "0x2530aacd1b1238514aba9ac1d13de20aad119ac4994984bfa04518a31051b973", + "0x481970f2e7e34a0064d136e87cd59fbf6131341027ab27458b9803aeb7e79983", + "0x99beb276484210f5b55e2b3662304a73c86a46633f3ff5aedb133217b7b593b7", + "0x0541564d394f368aa15e88097bb26d951d099e103b5866a3186455f422af1b8f", + "0xdab00c8928bddd0b3773af6dda612de649c18e4029c54eaf8467f82b153af878", + "0x343a7e702237917aa5d06778a592d1f279eac470beb8f340ab338c41a31826e6", + "0xce9fb58528596c0da68cfcd52d4556c41d7d6e8b858d665bfd110bb95a76b3cf", + "0xd40e49ffc0eec56394bb73f469b0aa1e1667eb4f912f5c3e82cf395545af07b5", + "0xcccf0af25ebe7d4e84acedcc9a88e885a4b99ab77b9881c524bf0e7aab724192", + "0x0ff189bfed3b2f56a3448bc08ac2dc6eb1d64125c95971ea0ce0fd5b7ea74416", + "0x60d25468039d7e8a89117eb468b4f561ea072554520d7010047680c1ddf5e70c", + "0xcd7a3c31ab25c421547b379a508fa0cf6d86cb9ce96377a5174ddcc315fee2ee", + "0xf681f339b4698b7f5016e9c7cb9a516d230a3f769b0da08096372bc87664ce5b", + "0x93dfe64853f84944856a2b79789ac7c73d18826e9a4fa6d970dbef77d000f7c3", + "0xc599ae73c9dee91ddef71fe0303080403753e3610ab73f242f3f8fe49b598b4c", + "0xf87d38124c8014802c3f523d56eb08ddffe645ed5d84ec1f11d025a88c594cdb", + "0x556e5962355580a0c44e5d80b28abcbf5a55feb5c81bd7b7a74c4aa664a7bf6b", + "0xdbb37e17df80f67cb8958590469d6d8a602b11b4dd28c8bdf8cbe873a386e644", + "0xb4932582d58d113231ead5a2d31eb8ccc0aca98a8dbdd9a450bf66fb4d65e18c", + "0x91ef1100276650f3dcdf96395859c123ee6fcb4686eecbb97bbbd6ed6ec6a656", + "0xfd5d42dfcb6c00aed36fb6f5a38aea10198758e59fdc4ca80b6baef694793fd6", + "0xb9d56c16bc71828af33e2a58b504ad96c96ea445c4fa56ba3703d6c8a971d9b0", + "0xa6ea2c5703efc858f9ec4a96062d32cfa23feb7d7bce6c25a12535c23b395809", + "0x72c1fc542e61af3181e988774989c782875d3b978df6e837b3a601839225dbdd", + "0xf332d4922e029f84d9aa2f49f910191df88f7f1d96d59ffe03d8956b0a5d54ff", + "0xe45ca95879c07250f3a317bb34d7f5bd0188fc947bbeb04262afd9c78039e197", + "0xc8c33079ba577066cb8e5af8c0682ff5575aa64cb30e400e5ed73fc749933d9f", + "0xc3e6fa3de28bee05a531d588d4895e63452eca2a188385727d466b87462c54c0", + "0x6740e11063142bf755d0bef9c254673af1f72807c3be4c531212efff63636f6e", + "0xce52344424c05c60bc7130b05febd30f611a081fd287757442687ef4adda6948", + "0x99491636ce876cd89f40d38ead2ba1579a050c16400052d516dad0a89b092069", + "0xbf6cd1f7f026023683c23d9f0d891e765823885b211420b9a6b33947138776c9", + "0x7b478202b808e4a54037acc93daa1136c6fb27d89b9f897b9fd3fe9afba73ee8", + "0x2cb32599960b97177a94c84ad7a047967eb2e212415afb7f1626a75a75cf1b46", + "0x62ef86c77b59fc2261a10ff39d74aceb1b7f7051758e5372081bbd911f56ccb6", + "0xcdd56a98c6b30e17a3239158ff7d91a415a28e7bb7e9528cc9996c8db8745667", + "0x8e432c62c747d730b197d6462d9369e5e9c3fadb7f36702c4c76803c5dccaee3", + "0x9eca51d69547f45fac4b49f0c6f126e9b5c67259880d28112dab89ab8264ed9f", + "0xdfcf59e4a92c389ed131b40b048abcd0725aab626f4fdd3575a37b4a3a206549", + "0x5152046f56a54c8f926ed10300d516f30a4a624aa7fbb888e465ba7359c4f3cf", + "0x54135b5e02b568eeeae74e59f1796650424233966758fcd1d007a727145509bd", + "0x9253844423f0fb792a2248fb887ffd10be43114b810b2635486ca0f6d43bdbf5", + "0xf3394a79eb65ff0184fad992adf3d0a86b5e6df85b629abed224a85460261db3", + "0xa4a1b651f300133e86986fd3a881e6577c6fcac410bc58c63f4b031e2ee2bdbd", + "0x5e074eec6c53dc49c55b50c584b0855e8c5a3c64dc72e73e5cdc1b086d07596f", + "0xf110a1c5c23d3bb9ac48d2bb03972e11e04b52da5eb62db65a4f4a2ac8d2c068", + "0xad11be682bcc25d30ac1eb6ad15990499d488c402ac6ef78085ef8faa5d4a248", + "0x0e13e09b2e3b8de9e5fc9e93382f06b64f03f98c3e26a5b3af811d32136ed0d5", + "0x494944f0a5afa4efbd967941129275dd6046535ad489443db1a384798cd7a02b", + "0x38474b45706c7cc93dd2ce11c41ac7f12f494c38f3a00c9cd38e44bc8771e04d", + "0x9a986ee21db81a38be8d1ed319f2d2558eb22de3899942fdb6395a188320de30", + "0x13ba368a9882ee28efcdfe67f4bfbb263fc8bc1c07b6f1369d3bd5ffdcbb3a01", + "0x451ff9f8e52bedb6a0f47ca9093b83b7d9a61e94329403d8eb913868945e0b6e", + "0xa04bf418215767d2aa8e6a8c6bf6563c80fd6f439d8d8759d2a43d8f4fa69630", + "0x551df5f968cdd4d0b78c1927b20383ddb6183a62f80480983d23f734be98c265", + "0x0df43d41084f9aaead6b9d77cc8f7760772ea1d27bc574bcde7061985e2891eb", + "0xcd8fb777f3d81581c5ad765b4f6d7f9c8d45c92466c65fdfb02637f226aca9f8", + "0xe4a92928a67ce00b8569eebd95c446ab82ba5beefdf467ffb0ac1bb08f4f471e", + "0x3ae0b6e5ed51401ac85ed96a84326cc1e894fb89a24269c9f3cd25ca157cc698", + "0x8363e4315a1a914a3d98eaadc9d985324073cc04e55b5859264c997d6d22834a", + "0x1e77238479593a1ab25b61990f3876869d2d87c9817e061dd82eb43e6404e0e9", + "0xbf35e78bd78e97326d6cc6c87f9f9c89362234327d06a65344cc9e692cd0d739", + "0xdbfa8ae2f7df4c5c0391e50c5cf9e144b45763a13ee250033d133c08b33f8029", + "0x828df5dd874a8e47e198ef4751dfec528c34348378574baeb2cb3b85f2376dfa", + "0x60deecf89aa73bf16f800255387ce9b9b74e02820b335cd96eef4b41939461c8", + "0x4e6a6312ff2847e8e419be96cbaf266ffa7aa91139d9d59da4b29c7e28aa813f", + "0x6c0d32f28bd65f020ac3c803fbed871422d6c6f02cab380056721825cb05cc22", + "0x7639acfede0e940dcea1965352cacf2b08f8ba0cd4254608a1033e2c80b1f12b", + "0x235155d27105a7f73b46d0c4a91c5a4978eda6d69db1af58d13b89076ebb98d8", + "0xcd1cb877b7b138f598658a39d1e135ae211a2169b2afefcd80923f244630233c", + "0xe9744fc928cf00f5ce170b81d28f5bc8f324d37fa535f2cbc2a23d82406d0423", + "0xe376bdbf2b052cc9d5f00f36b0af4d360174ae54b52620439c25d3430f405cb5", + "0x5a00ca653123aa856545902da24e3066386d1df00be733f95a4d105bb722b085", + "0x8e7995454fa8c9e7da6f19d9860cd0ddcaf1232033d43325b211c39023ca4d7b", + "0x8047e3cf7584e57729cc92c406f2c9caf41d9f5b3fc3a1f14e9357c954972474", + "0x7de15b023b1f923008d08ef6312fe8c3db5f499a26fcb3594795f47a30d28c85", + "0x7924df166e716bd934f98797b4a7f344693bacef336bad132ce068c6b70e5ab8", + "0x9ba0b15b18f2735800255de7b9e52fa971f2ec7bdc7de455c2e989abd27d35c3", + "0x9a5707a0ee4ff0d88fd8f9b5382ffddc558dc6c21ed9c8daad043a4ff4a561e1", + "0x898ea840f2e1e07c23fb9e18045e8addf5291661a72d6517b029620b52b0eea2", + "0x8f5ff6dfcc7c8ea2022c7b5d8ebcdbf713d303f164230a74192ca06fcd2ef20b", + "0x1508febeb95c2d3ffc8f1d13787bb9883be3529f8d71accdd55e747211fa8c08", + "0x2c7e4797847fe62a55f64c64977462cb792d9ec899e16f1a46851aa670d09eb3", + "0x825588a04dc941ba395deb99c00c282373e042a064cfc1ff557f54d8e0479187", + "0xef56430f5950a91b9a2028a549d4aedefd7322e36793d3cfaad18f97b58e9e3a", + "0xb92537e03ab350a4fd855bbe5175e8ff0e0df0fa8588885fdfd33bd2e37650b8", + "0x57b54ecd05c5582b98b62caadaef9e3386962a15c302caadde0f3ab2de98ab8b", + "0xa3f9ebe4db242dbfe248bdf7f504fe1f92079c60babdfad99a1a1adf446b3750", + "0x0939ffdb6c07b240cc1448f7276d7c8b436051e9488942d4b1a5afe5a0103aa6", + "0x778210367f625571f9d075ba06aa1ef5a8b59a411ec25b4e9540e7dede11e013", + "0x12087182676e11950138448ec4258ba3bd6ae31662f13db6cbc46c52a266dec9", + "0x7dd65f0f816152a53d8221e5554f4d3dd293219b0537a600caa6c5b758deb4cf", + "0x060370c4afa823b9cac3b2a87af1a989f8478169da3e12ad4073731a6729112c", + "0xe57c5b36d7372b192549e2ed987cc16beb412db8e22c3acdaf1f1c95ce1af81b", + "0xa9946d302b6f3dc7ccae4e4a69c21c862da4dcb9df371a8b6486534d8d3c6e76", + "0x350669a215b44b8cabfb6019d89f5268b299d6fd9db56fbea93cdd9f4991a977", + "0x4bbfa211e42c2b92c1cc979f6303e2eb428292500c6b59f0ddeb87c3fdb4b314", + "0xd243e1fe99ff82487def980022b204794fe4eb5b8fd657b851f7f5f323eb81f6", + "0x0eba7b7031613d9c2cce87ae3a9ff6e7b57b8e537913657c5c97f80a65f774c8", + "0xa5ad33c7f0755f82a0d6f47ed774bd8f2a00a66f2a967a52372dcee62f52c099", + "0x36d42846ce8b3021f00a615c0423d1bb1f00ed05df1748249a79c8a515a5cff7", + "0x7808d7655fb173387cc5601c469a26402b631c1d3e490b1c1d25e2e2e4dc3807", + "0x533b133383362a66e34e9e261442d4b867ea762b4422d2ebae579c144621ce20", + "0x46e2dffa796139a441b4b2a2ecc9530924ba032bee783cfae1ea1623508d55a7", + "0x0acaaa36ef65ec28c8a5447a2d594e48e4382737fac248b7895d3521cf2730b7", + "0xf191dcf174b7a1b026a9e2ad51a49a684abbd84556988b8cef315c3c5804f032", + "0x940284119cf5d5667d45103ef0cc790cb6540926c0f645911c669ccb78f6f127", + "0xc8be6193a1a094924999b527d81561f1ab47966c6fee7699418aeff2e16dd27f", + "0x3aa137a876b08b74d0e507ec47e72ae5d2049e01a83c68b90860ed7e9b594f4c", + "0xe375dba7c6b94fef6314cf569f887010165f40f930156e15c2897ac50db96e4a", + "0x82c766f09a89d2d8644603c21005c342208e2a61922eb13b476dcfa9de9ebc4f", + "0x06bb8f251decb2ec72365235d98bb9c0e0d0a18f7ef7b069f70eb432455ebb7c", + "0xdc4d5d8aa9f4a4e224510a32df3ac984428b8bbf38a9638fad1c74a22cb32c0f", + "0xfa394e11c7ea81618a3735ff52c67d182a013caa52897b10e1057de7a95b6f92", + "0xbe3dfee256c7cea8b110e9915e167d56479f5593cc5a8bd7e6375539c9ca8984", + "0x3caf7941bd973212ba085982ea0707889aea831d3df45468060a1f8afff8da93", + "0x17ac6c1fa00755480ab3fdd4d5969e8477d55ecac99ad1b1dc123e677560062b", + "0xdaa4e5841582d605767a49d59dcdde3067a61681f40e55e19adf73fcabdc65a6", + "0x465b0a0f2c6dc1583d1517a303947d372af513284cf2fbbda30831032c45674b", + "0x450b14d7773bb9ce708f8dc12aa7b8a9a83161eb8086d6fbe91fdf940f24cea3", + "0x0893e90abc7481e9413d33560ee9087d5e39305c0ee7fd8168d09da19c9a9e26", + "0x3b3e3615b3cb2402f807b1f7568174a6972421f3c6fada50c489428ac6d3a3e0", + "0x8ca9eb6c550474b93362bc8eaf6cfd7f39808dc115242310ff4ff6e5acfc121a", + "0xc55d95d03f1359410a23debadc8691ea0b53f4cc50073b449546c4422b16c037", + "0x26adc021bed5d143a3933824ecea25e0b6c577d8cdb9b899a86fbf706338dbd5", + "0x81b350f0026673f871a8981d899a31e2892730fb58e4b0273351b256e74151df", + "0x8a97e6e927342a4b9ebfeda5f5eede61ddd23b8b4421a0d2a8baedfaca168cfc", + "0x96ac659b574a4e63a8874a91fbf045f90f460b6c5b1222d72d8ddc240c870907", + "0x77c0baada7e37994e9f91075fc8ec335ce0a5d4f1627ceeb0a79034bed0b0f41", + "0x3b626e112b641b7ac01efabb2faa0b0a9166be0f156becd1254f0365d6f08a12", + "0xa15072f15329fb0c090eb5f1f91299421abd81efb05a00efd1361fa10228d584", + "0xb44bd4b0648b95e0d427cc5173d605fe21b00a5ee2c26d44d7c9a4f49e0fb521", + "0x0794d131e1ad17eb35301fab7566269e99b48b2e4cddc5b75f0aa15996220f03", + "0x994a7c6159433a62ebae86bb4212983478372b94fb3712bf025fbe3c5169038f", + "0x154a2ac1a23bf367f6873a7b51014d4377dc1008767510440a490365c4c1fedc", + "0x5881a0306e88c24bff0354b5df839f86178d2ba5e54d3cb80889df8e72952c38", + "0x770ae9a90625a5424e470f484f2c97b4f191eed61e15813dd59cafcc5bd0f127", + "0x6eb956fc5c743e7a2e02d694cb9c643e5ef97f960e90b75989aa91d3da1edc5b", + "0x3100b5a08d157428c6c10271486d050f913f436fc99e6fcc9b8eb1be9dfc39fe", + "0x507a78e12cf89269bc156b2fe5d991cffcd6ca6d7d085aadf8fdbb44d7689b16", + "0x0d2d43bfc425c8686487ca97d7ae5888535f5bf4d5e4feff6769ac36e1ee0946", + "0xfe866c43ed650b6fb1d3719df09ccb5126c36add42428bb8048a6841a88b4520", + "0x73ee2d004147c22f7beb21ec84293d6cd5974289a6f4eaba670da364df657a9b", + "0xe20395be53c10d9885bb2c7cfd78927051903ff4ad8301cb6f4e54c471b79308", + "0xc039903cfa0af94172d211f2e5c2c653d7d31905a1c194aea0a4be85c2dae075", + "0x468490362f1a7781b4e08d05bc1417107daf8dbeb092f1ab1a9e2d8e604741cc", + "0x186a3a6e4e1ce30ec18c1d72ecc4fac270a7d1ba9cdca0b7937794913f25c603", + "0x2fad6bab068378729dc7edeaa8ed516b6274396f21d24382d889f1146deedf70", + "0x257f8eb447ab096ce41e774fc4874335e77f750cc0d6bf4bf3e6b9d699de203d", + "0x4ace53b3bf327fd95451be5144dd2d62d906a25234959e33410bfd28e615bf11", + "0x0dbe710b12cd27f1196c9d7f1c5a981194ffae507b36b287cb758c32e264cc17", + "0x2c6def5c3a93b3c718839efe26835b0096efea132f6870ece1c33a7e91a2ba8a", + "0x2781ca465483c0079336532daf646104b9260c29cba0b6f4399feb557760825f", + "0xfcdecd6aa3e2c1b4d9f1991894cfe5d75f198dd445cf61ccce1c32fa8ec19e98", + "0x951185273ba63162c2d920f5acc888a7e4c1c6e755ab1215d8df5089276caf43", + "0x3e092b4e7488ba0172ed20dd9189f06d19a74269231edb0a592979eaf7c0ab88", + "0xd03afe649dcaae2de18474e82cd88935f50091394511a1f334e7590249d2583b", + "0x20c54aac1af04178d8c6ad55dced6e5cd2b83963f53ca65cdcf503708206285f", + "0xd8102d6cb1ab6c9f5f13a38ad0c375587877b22a6836a882f128804d5577b527", + "0x323445a4e659b00a2abd18bbddfa87dbd824877eab5693930c63a4704f0072f8", + "0x21caf56fdbf708f486b7756928bb74f117cad771a850dabc2a69291faf2e8d6c", + "0x4227752d2a7118b37d2089ed9319095d388c9048c0082f337d62d5275abb1145", + "0x78b96472d555ffb616105b2b471e2893ad6e1f8b735c4596be9d74f028932693", + "0xb11adf3fa7f2922095d6811564831e7371f87f4d417c730927949cc6b5227bda", + "0xebc5565e3b1338fd34f4427bb60075f6461dc072b097ea9a95237a411cd8fc8f", + "0xf4becc05db259bcf2790f79cc1fd1c88396db483c2c85c127818374be47da818", + "0x8178c8a0e6eebe2be426cd30266ef6574973d200e84339196bf6401dff1fe746", + "0x3d5a6f60d5351d577ffd38306e3a12606a1a3aea9023f2b8b8bd2452847d6b9b", + "0xa80644fc78939a7e41d390c6156ddc0d2b96f80265e5ef333c49e167dc585ef9", + "0x3e141f89a256b3b45cae79ac0c604dd9a19c09af6f685157872b42031bd62e1b", + "0x01a6910b5403b23b6e0102f4e012e0a0c06dedb944d36ad4c4e2eba8cb3be4ba", + "0xea5bed79158402d5f0c295f363a211b26d9ddf4d4d04e95564cffcfadbcce518", + "0x3a9d2d41ee14a76564ccf9a56d7c6d1ce732475ffa64499706b50e8ecd0e2050", + "0x8be57936b28e208f26fd382bc1404ea474001287a2c4d21e5213bd9327253ce2", + "0x672af36bc6de92544997f7cde2ea8870ae0f09b4cb2c22e8fd2f64bd88911f60", + "0x0d8d34a4ca78aea4627d1439402d4f0c64f130043e45bd6db1a0511dd16328f1", + "0x376539fe4c0de33e48d4c308800fbcd3606b82482ef9addbf5bf9092d6a55f92", + "0x93a25650ba0615e36facc75fa2ec8e86d6135022a31d86722307432871d6b72a", + "0xe95b8505b1ab584e83efd0bfb62a0d3c45785ac2ab74ff5e58178b2e742aa6d7", + "0x6fb4db8b3eb5b55916e2b06536b179ffec93b7300e3be36234e4ebb915a840bc", + "0x5d7545abcd38bffaf08f6745872e0dec47b0867df5102f42d83fce722dfe4406", + "0xb6eb5b0ef418cd1158ce9588e003e944d8afbd704eaab53d2643defa365115c3", + "0xfcf5ae4e3d7e2ba5e29653d5b732a1d86f18e2aa79ea2354958ab5dda5c57f4b", + "0x95aaf721f3c015305eaa78a8879d2f33b9270deee9d03acce855f0f44480dad0", + "0x054b3629ed6ab0be7ad07d3c658acc3ecfba8e9ab68492838b35690556dd722c", + "0xd87e3fd945b27bc037299325752c775a76f1c3b5b7c825fb9b6e2f6dd3680975", + "0x827fb42c7548a9f034a835a54ccc598398d2a8281677638197bd8d2bba4fdd31", + "0x7db908e4263cf7cdb822e42acf0fc9aa94999a1ddc327b6535e0a33c5237d1e5", + "0xa022198a7f3027a864615df968dd6c77d03878e12b9f6adeee611deffc82f33c", + "0x19269380075fff6af87dd26b7824ea70398e3802ea3c6fb2b4c2ee630562dc75", + "0xa13f3c9a337d9aaf86b0a5e5d5bda796d2f1d99c7548278d0b752e304392c3c3", + "0x13067c9ed1f15b7365541cf00ee6d7790aa0cf24ef3c60b10f16d0b5d0d67266", + "0x8d17d62ac8abfbe2b9696f918d92912199177e94ec49628baba2ff3897ce8323", + "0xbf65bee541ac0ed5f7529637a156446214c77018c5c59f0774b410bc9d2812c3", + "0xb3980e23fd6ad0683e19db55b7a8837a14c5c809f52de2950788ddc7f6d2187c", + "0x2e633f27e48af14dbd484a42b002517456028a2323c49916d777ec5d00accd2a", + "0xa44bfae290d8ac9e0ade331b4c362f5008152a38199996bc71d17e41d4a90069", + "0x8cfa7989fe18f803b1fcd926ed6e835286acbcd4dda22ffefb24cd3fdacf2389", + "0xf5b997a3440078a7c1322b70bae558cffc1234bf459cd295d5cd3d9be135242f", + "0x2fb715d33fe3c624ed35cb931c0a5b38475c1b97b743c15d5f0835d4836c1e02", + "0x9d1f7e02c66eeb6a75899233c02467624b46b7720a0a38b9af62a363480bf8dd", + "0x0c0a8f695812e88e92db4304d43c7a12c4958350b4df66813235dd0a69fdc643", + "0xca7e816b73d005cf04f08dcb5fcba1657fb6d339a2435fd74670155d097d6fda", + "0x4160cfa822311731d67d0f23948b99abd2fab077dde4efabc3a9625686a5aa73", + "0xdf9702f40c2564b7d460c35d25642b58179e12e859f935f7b87d41bcdddb517f", + "0xd24e79820676effc95265384449ee4bd8edfc7b747f2285b99518a2658470c5f", + "0xc79e6494fb1d7f01a4e8c36b221956e16097e92da140c3d3ccf336d5d99252e4", + "0xff84f37720a37852a94d31e3552d7605e403ca42c74830cd2856055448bd60f6", + "0xef0c3c8ca70dd9227d2cac50c3c6dbc272124b74eade2f26e6d20e21de527f92", + "0x82a1e299f56312e65bb42a054c044d58914109a9e914792ae888fcd94e30897c", + "0x948894d3791476e20b63650460960af12d2a33a4d9b23b6509ebe216e77e1cc3", + "0xd7dc6732db63ff742830bd429766ae73ee21ff37fd3831f5ca0e39c3cc16e284", + "0x594af612776eaa16e4f10c2416d5912f025df7c1284653ba844bbb3985e53b1d", + "0x348ee29dea90b5e6cd96abe5aac2537734efc4f5564e854dfd8153408f6222d4", + "0x9eab3769bdda9b57cf3b2a8d07a6dc2e07c856a15a79faa7890582b43f26e6ac", + "0xb97f381205bb10d19ffa24dd62f64b8687422c1a2967ca3b1b1bd59e30f5b5b3", + "0xf2bad3504422193b7f8dec65b2edb5bae77a3ec12a6403be0cf98e6372c59886", + "0x36a4a3f86f14ddf99c0822988616018d1d569a55f3e51cceab26d2a5ed6d1f3e", + "0x2976ced02e0fd21ee9992f847e912e4cb480d676347c721a1d8cf088242d2208", + "0xc6fe83273f10de94767eb3d67bd5e7ded408d674248cd87ed64e1e8384f15998", + "0xbdbe5d93b2812f44914fcb97b0fcc61a6cce96b9bc811e3cfdd6c9ac05619faf", + "0x415e343e7ae318153d4a9930f9779aefdfed85eb31a5f63810836beee854a370", + "0x33767db7f68c7432d03ccc405554fcb662044f6e43a5e073a8dd473f012bba66", + "0x32a7cf4985194e23827f89e1589da83b9158e98219b173f7295fd0c25310fc79", + "0xa304a15516c340a220b119243565f8a75bf6edf678029e0344ed6c1a49fa96c2", + "0x88c0c9b589f7c89d38f3f83a18dc38d9a3bcd752c214805c0876ddf2a3b45b86", + "0x216643d8038ec1cb6809b8ac77cf909dd160cf433da853e0572705e00aa210f9", + "0x4e5bfb91e5929da7d07e2e4ec30ca006cfc8399439cbab8c0a612e1f951fe35e", + "0xb20afc9312798f01965cfd83deb2a254f477636a565eb0578d8b6a86abf16fe4", + "0x83ad6dabfd5de39138c7dbac41b9548ec3fd601487ef3215fd520b4d8fd505f0", + "0xe96fe232f32f9f4a45842d502ca714f933412210eda69d28eb11bfefe1f60786", + "0x838711b43402e0c6ffa32b6c96ff20d47d8e00cfa39cab1526e7a6a6ab48a239", + "0x1d29b1af9a80c63e675ce5e957a98f31c57975fd6ff48adc3f62192393881c9c", + "0xece5ad70b3b260c8c7247d1e29c95a6347ade7034c26e9a470c0469bc9a91900", + "0x2cac591b892b14911202dc80a32e50c1c80a82a6f78a8a704bbc3e0c4f726cf1", + "0x1999c48903a3a6ab132189d27889c19c29eb04e65aa7d9a8c35722dabbc66cde", + "0xd03f863788d323b508d695a6ac3fcbaf93b44401efaebd5b7942c635c10a7eb8", + "0x57e92bc43ab1a66e45c054e6b46240838422dcaed9701d65e3fe41035b7479ce", + "0x848a6f66c7f5c3c25ae9f0783891c5f004600f274967870a4e9aeb91c34f11cb", + "0x193448bef47c66cfdf060191e4bc58820a3e1c9424a8c9933a1315bbc874d4c6", + "0xb9821736ea8e93609f701ebd178f00e87d4c7931deb9287a76ee40424eb377fd", + "0x88b01f8ec4bed91861870404d1191cd0144e0615943c609e006aa7570462ca0b", + "0x4014996b1a6ec5e1bc625a304ff1bcbd310b7094065dc6a75cb4070f44fd343f", + "0x1b1db3c8dfd7843c993cc50b4dea25179310ba77d1ce0459bad775bad54c7cf8", + "0x7ac6bef10622a0863b979573f8b9b34b9008980a6752027838ba7a50e68b077b", + "0xcaf393ba83566504254674bb9e8cabec2b1c366f4e7a867b8da663fd0dee1a01", + "0x05769a695b0b171e849df667fd873d1de4d1b0fcf67588986569e631417df8ae", + "0x13c76a5de115bd5bf30c939e21504d27e10d7e0ac5ea1ba4e71cec387b469e1f", + "0xfa24eacdcb99a7d18c49e095649ca414b3477d4188a3129120847dd513083030", + "0x907c3b7af8b74131260997f69c41850437dd00ba24b660371f23a1706835336b", + "0x4e812bb9a20644e2c48296e39688409d3499bb2a250abfaf8b0cf56ad0125aab", + "0x3238205f0b9d4062ae1ad8a5191d65f2f50bb3c0b7e1351fb8b66fab97a314d4", + "0x9130f27aba4aae0e7d48375a67f25fff231998d7b7815f24a2a8e86fff39ed6f", + "0xcf32280598cd5a0579a5f250b8e418567d31f3334fe8245c0a874d508eac745f", + "0x150f4bcda2e49b6d09a975335d33dc480db17ac59a508f28f6f05dd1d3caa22e", + "0x379b96da6a733c88a0888fd3a270c889f5e2c0728272e3ed1d654c7fe582d9f2", + "0x8df473f7e356f0dabe0d6f917728732a3f9e0519cb8e399ade5dd98762d0c1fc", + "0xf8b8368aa697e7748404e589f2f2f4d2808e7cb35086dce48437702afb8b882b", + "0x2b3560074c07e7955151dfc09b1293fd759d286b65dcdcf7b2c9f3dbff404816", + "0xa6361ee7b8af32325cb36304f400c9c685767c96d0b5181e7503ddc8a36eafb2", + "0x51405ec92bb2c7fb57f95c555150afb6351035e7553a63d26fb87e1827a6c3b7", + "0xa0290cadd15d77123903184806de7f04723cbe2eb4bcc2da4c926bfb3195cd54", + "0x4bbfd31db415a8bcba7188529ccf09d7cc10037f2c3dc7671ace6d4dd60a35c1", + "0x918152123a239ae6c50d9895940626e7f77ea624596d1144989a5fb7e10ef48e", + "0xef73abb8745093394fc130c7145e2de31c9457151ed78bcf63171b7633e22dec", + "0x09f80e170b2a1d599185c562344821d0e36bb48f91d8205653eba143deea6cb6", + "0x793055e11ded973ae3b55bb95ef6e985ecef03497e76e4e23ac477f6ad070fc2", + "0x2ae7e9c72203cc2aacbb79cd7cb5cb7fc4b997c9c740578253cea957ffd847e0", + "0x9f8caf269df06cc8c81cde32f1ee4f081d8a2ea8d945663e0339456e583c4703", + "0xb8533ef2fdac7587034839d1ce877bbccee50c473d4546c3fceeb7ecbf661f77", + "0x31a51d443ca2a588596b3c6a0ddd5fddf7abe8138177babd8205d165de21e76a", + "0x0a60c5ce88246c2e999725b2be6c330dd2482145fb0859ac0dad38f11e24e5f9", + "0x87d81ca8b664f33920634c62eab8f0ba3fafdf28ca19279b4d0c60a71eb738cd", + "0x1070087084fc2cc2e47fe731b8f08736cbef46194d16f418c87befc693c8a8b4", + "0x09140a959753b2c1622f0ad55f8f5d34b5f52a5ad6de7b6112e4ea1b8fda9e1a", + "0xf3af8d94fba3f4a6e018ebc0fe5088710876209a39e37b85e6b6bfda70f097ca", + "0x3346983bc9ed1f7f4f112b38526a92e7b416f30e4d1c7a934c7d74974f86dfec", + "0x587472df09a53693596d6bd1f60485df25fdd54fdcfa4c20f3558107f3bd4588", + "0x4c408ab0922f27796fd4fef68bc20c6385647a8ad4397a4a553fb68c5ce1710d", + "0x2eddf19c4a6ea3c2ec855e5b90ef78f3f861bc6317369db137f1a7f89110e69e", + "0x30391283286a30ea6df7b5739c7955a1a659bb0c46f3ffef8a58c0140d7386c2", + "0x8ca8497844280911bd97ce06b69d9e09a86ea135ca0adce596614fb6c584d0e0", + "0x9a699d399b3ea784ecc1e4f2dedd9ebf9a383fe44f40b4cc67dcce4ce98cd61a", + "0x013681943970f17a86dacea448bdbcd0d0ff56b243ef2c147ba77e58f1b47c8a", + "0x8717f032bc745c9a16eeacd20f3d86872e9cef3c4c777a8dfd867ab898e73fee", + "0xe3d4059812ed8f3d4e23583544131dde2a56276dd513d2679be07a36ee08dc48", + "0x265ff09a3d0413bc7bef45d66e34180c432b5f66ca96f8c39d390a83c5821411", + "0xddcdf72b890fafd78daf04a9e2afa824de34b761c25876763d9814fe41a9fba0", + "0x75168bbb488d49dc440360206d5b36d8934b1d9c50d8d8239cbdcbd27f238796", + "0x57aeafa912ef24841935fbe295c7f922b61bd729afce4537ed4985d06fed8eb7", + "0x7be35f0ba773bbabb596b674d73d8f0b9e6746688322dc99536e52d6f0100183", + "0xceb32481ad49ec6c259273d2b302352f121fe3c0d6a38c2576fd0667ef1c1088", + "0x1e1a7e3edefa2943844e452e8d4959f06681449e91622a537e196c7f3c069f5f", + "0xc4c5f628c0e705d6ed6e84b26f74d76a4ae13b9a602f4ca8fec8d94318b1e05c", + "0x324a02a05df574b12be04d2ae137c409a87963d524eac913d2b671d950aecfed", + "0xb1c115671fde450792a1bf3541d8024e84fa4239b3fd894af3ffa25bf4d10da3", + "0x9e9db6ae30894084f36122ca1946b96851c0e2282cc4361fdcaec5381552c26d", + "0x230b1fdb77d049d548a6cbb9b4dc8ddb983c3225591a323820b908cb79ac5ffa", + "0x88bc17b5d10e4b474c9f85c935ae3cd914aa437185f9bc7c03d66cf407e102ff", + "0x6ee030f383a99122c498a9c43bb51ed46932be9cab7efad96fac65f3b39d032d", + "0xd600f1dfab24e5b671a68e56d2d27f288e9b15ecd870b0fb3d811c1cb6fe17ae", + "0xe892c488faa1e15b040acfee5411b0c6cc93d1d9082a605436a0757a0cec7a85", + "0x8607ed1eca84dcec9c9c2d9ca8f9dcc952de7ea3c54c051d0d41e78fe725cebf", + "0xd9f378c67ea3834d89a85d72bfab542d6877370c8b542d1be2766e867a25229e", + "0x725ca420d55211930c77e292f602f58c281c12a2d10d77ac70f128c122272485", + "0xc141d38375f3269e92d6ed85dde2cfff491b9fa60b3554ca9909b944838f7781", + "0x572f4aa12ec73e99f35c523c864ccc964422946a0ffc5606792cb65944a1c61c", + "0xfb2f827d05901a25debd15a6b5a45d6a42f2fa84e212f79493e46e760cf8d620", + "0x9f08663b613bf973e1861e244e61e4b842853b8a388360234c85982e94ad96e0", + "0x17ce1320123e19c42bf806a0f204c9475cb3340a0434eddf3d8954b08d8a3c26", + "0xb3d935cccef673064e94e186c4649d19dbd7d6fba4ab7802eeb44fe4e6448bb2", + "0x2a04d4c2b009e424a88196f109923ab308052c6709b0f37f31131a74db07ca2f", + "0xd30500ba7ad6548049313227f37e094507e03d2a71792fe28f2dabe6c7a477fd", + "0x133f0204075c4a44764bd55409878a85f730f412a64d8098bf26246ed89fb88d", + "0x0dd3f70cb92468b09475aa687e81d84b7b5551038813b1dcecf9ad62394bf29d", + "0xe9b2107b3efdfa5b52ebd9d25bc17cbf934190af323cbb821aa01454809cc5b7", + "0x5a10e855a18fb6e2beed325f9d4df38645e52c8098761996a455eb3320c2819c", + "0x7ff65f7a24f95a7408272ee4122f202e2d651c084495b5173bb046bc4618f96b", + "0x06b0e4bd3381c9983715fcfa8c3f48b4beb289754fe7bfe8caf5eb21901c8ad9", + "0x5ef4e799c3d7bc81fddaf790f00166b63255836f5e03bdf584ad2535e05d3cc1", + "0x9efde50127e985d2c255ef17a7a5c82b46242f18230cc68bac49867184e897e9", + "0x78309317ac6418cbf58090dc8091b3746ae1b5f05b8b082610eb28d101e519b8", + "0x81851a87801abc649ddf08e1e372e7d0a50c8d18661bb3a13193389b06854ca6", + "0xc5170992c381aff40d4d02f0b1978ee689dc9ea00d0665d53c642c6e1617f82d", + "0x9c4d06f36bfd2a08a02715c5eea44ca07adc04b1176f7a47a3404af181feefcb", + "0x7f1910a654df3160f91affee5f286299958a5665ed0d37e39ebf429b281f5b4e", + "0xb60950ce3005d7854f9f957b4f1f49f0b4e781728697ad312769ee4ab80433eb", + "0xda6666bca71087804de7b3567e1f0047bd69f8f62d0bc7f63aec65ce8222ca2d", + "0x7e9625d6fe07985ae5a378a35cd5108c1db05e429328f639504fc17527b2e04a", + "0xeb606494a39941d272aaa9cc3e18d2c502b0438de5ae974e6687e2c2c433104b", + "0xfbbdb8353f8288217930f085c51e0c67eb9fa268cc66c0a96673918501119802", + "0x071dde3764caad8163d85a5a7d9a05f31b857828db55819afc95b08e10d6c87b", + "0x262a03e39027887a11b93963c7ca4676cc2352fbe46a05ca2e432902ca4235ee", + "0x1366a718f5e2a2b328943afa839241903a4bdb776b6f732d6a0172ff8c9f544c", + "0xe04d325284bd27091857f289c6bc8ded91dd16ff7ecb157e39965c3c98058e34", + "0x648d5113a9c413874f2e8187905045f9d8e044e29cd4dca0658d283d0944a130", + "0xe7706395d101ed29949e59b10f69214eeed0377be7af3cfa8231b917c6793023", + "0x7d37f50db8c210bec2d202a7211565d53ccac0e9b17baf887a9b865f4a57ddb6", + "0x73302fd966c3e65c0d0e7d610dcfd1a87970d26fd2ac15deb73d812a878fb8d6", + "0x7cb0a793aa40ea9894377e0f941b284a792065a8fb20a0bf60e8dc51744f07cb", + "0x1c2435e5e922dbd482e3279cbf88a632e34fdfc1e7bbadba3247e11089871ef4", + "0x8fbf585e305c90965c47c190b2e125276a5cf5747ea57e60e9bd36feefc7225e", + "0x320d5616868006a5f311c79c86761b47f683ab7ea1025e794a9ee45b699793a2", + "0x8706208d64c31ebf34d6c4126f72787f3d604dc7c0f72ea74075bd21afe21686", + "0xac6a123d378afdcc284d34bf487714e4cf9a090da9d9f3d67bd5510ebde00415", + "0x623376328e2e3c6ffb9a25250a24a5b8486915317fab74c46c06cbda943dd74d", + "0xbbb4c4513c3902167bc14cb17738633113cfe22ed5846d409fde2446740f6b9a", + "0x62ce10523cbfd602cf3e3e5b8c09b310f4bf1d7c645e3a2cca9d20d156b51f4c", + "0xf427a9a8c4390d7a4237f0b72cd19343c4986e771b180421c21dfb37e6912c74", + "0x52980fbe4416be30e88b1fa6e3325a0037feec3b6c40ae66f9d5e884f2deb153", + "0x9aaf58f469e9c8362e3016de4b12350e8f3c28f86ce58702fda69be65267dd04", + "0x0fdf4d58461e0e9477d39c18eb528501eeaa066dd61aed414a50613182057934", + "0x708b1667152c18475d00a25c8b87de03dfa6b2270bda21278c0dc0faf21464cd", + "0xf7903da3c49bd894edc260ac372926d90763b459539eca32eb3865d4a16c9bd5", + "0xf9b6180481cb5b2f4692793de59cd707c71b3f6f7396a40e506fffecd3c4fe7d", + "0x6f298c8d88b0e5120805b453e0ad10f6d65809fb0558c4bb5a344ee00aab4745", + "0x4bb3b6e0cf86c6937668b4a298da229492d98d99212c88e3e60af9e89fe7a4b1", + "0x0e2b0211c17ff6e28c459ea410d3bf33838eeba869c4d46238a25994fcb9dfbf", + "0x113e8f5c4c21ba5909963c3e65b112c78c19b8f3d6526c55de1af9a4b1eb8d60", + "0xf19f2f2e0a8de0d04a26dd1a10e96257f4a6a764b92d7c360453db32d65e89ea", + "0xb20efac16095e63f5f530de22271ecebb1fa7bf4d8ce6f49057327d692caa5cc", + "0x8781f616535ce6b3352820758ea0ddc74ac97e49a3ae9eae6ab0bda4e8741606", + "0x205895b72b02e22c73c3fc2e814c121d6b899c821d72f1b02bfd8c122fd817dd", + "0xee8e1b3a255140333295253ecfbf9a2d375d5ba1ea2879bd72088f6c62b3f9a9", + "0x4d3c138f077007962fa3fc56c7e5bb409c860d11ba48ca9658e67473fc4c4417", + "0x283ee3738c2bda7631f3f30fa2c29d3f3bed26c63180c61e1de03504b48f7c38", + "0x900a45ce2bc0f4b331d3df872f3d34c350f6b7dcdd704e36670eba878776b303", + "0xcd148e1b7d3a4ed41c51129d14cb226ac20ff975de1de2a802ba93b0e872f2f6", + "0xeccc9ff6f75fc844cdc8a723ee3f168d3f54788aa99a5f81aa9e609f8b4e4ba4", + "0x9e4ba2027ba44f31bdeb8ef27db30474de2f3728fa0607f098eaf8f03faa2fee", + "0x8d7289beac6c06009f0b72c2634c176a0784afc8bbd484bcd8040500b15f902e", + "0x9624bce0632d9a49d9b040a45da65e1d686dc6e6eed7eb3ec1536384b5cb3530", + "0x8187e9b62c764ebb82f5bda0bde0cda2842c47dff910e81c03db5c83dcf02da2", + "0xab7be6424ecf0041a1a0aa6c57cc231270ee6e50b80e6a8e07f6e40e8e11931c", + "0x43d8ffb420ac0cfec24a8d378d7d35230aef8887268414779b09247543b2f044", + "0x185cd7124a200639a0f60f1412ec44083f742960e46897a85d45a04bf5ab2516", + "0x91025f84bb714cd201f4d3539f7c5e6c7cf9fa83b399704ed0130b311c6886ba", + "0x13100633274ce0d423732cbc1bc1610123959f15974868af0b1900b74ca4cda5", + "0x3b00927007417f0d762f6b37c7ec0441e963a9afcf3d54e5be1adfa4278010b7", + "0xa8e59f21955c983044955aca7bca29aad4d408a1c958ddbc2ae526a87e3fabbd", + "0xcb836def3579f067bc45c0dee5f9a80eba544348c7bda65964c6b1fa2866e0b2", + "0x404d40e1bcf36d7d4e34b32eadbcf5cfa858be1499b088fe8ace025a2e73d3a4", + "0x2d9a5f05bec8712d206349bdc8fb8ec897cf2ed28d295cd275c31c5ce46c4fea", + "0x48c577fcf9d050f2b35ba0195606d8b8d91ac17e524fe0b6ec16be1ce7cda0d0", + "0xcffe1c3ab5caf25224c870cdfd63b4faa738362299cd37cea8b66cb1542f0201", + "0x7bc007a452ddb66827cef27c5bad01e87265cb38cf8e111ee7eebb21cd263bb8", + "0x8c26cc0839859eba7744b73a03f6318e3ea249736ae20bd206461e79bd7e401d", + "0x165e4a10b343dc952ee54c56f21b74b6486929dbb59ff24e066115bf35c223b1", + "0x2ea42214e74cd75bea948323313453dc6242fb0593f7e267abf5e544e0ad7d2f", + "0x2caa11a0a255bb4db80e305ccff40608534e638a17cb8bbfe6580a035cbc8ffa", + "0x0ad0490a3008883d02cc92624352fb7caba9a97cc46f82d1e64480559778edd9", + "0xfb24953b551a2b544ed6c6cad2755e6aa634112c3e225607a0efcb0d811ffaa9", + "0x4ec8e3591d27b911b1495f6fcf5e6dcc9461e9e602b67a5bd536bb0e6bc68f88", + "0x790b7eecb797e391d27085b27cdc5d4be20bf78de9918c3d1ed72ece2738dfee", + "0x7b73acfbce9837bbc5f821412c92a1b58b3af2bdf08b4c4cbbd12e151efcc90a", + "0x16e576b05c5c95fd38ac7d53699ee8b8b3431d78a5f671535590cc1c59c78039", + "0x2b4bddc77ed675df91af490a565c6ece5247335c90de744d6863e24e624bacbf", + "0x277efde1689605ebdaaaf4b9364449345ac664b5fe270736b2a7f2a97301dbbf", + "0xf727799af7a95e92eaea1bb2e3a0f79cecea663113e4781797101acfde46c234", + "0x54eb62372f7c5893d6be0a031edd80a25cbea3db2a0edde69ef4bcbfeaa24b4d", + "0xcab1e0eaa0aa475de501b2e3fbb5ed790744040a465a4256c4397e85a31f9eca", + "0xa0c54864bb507baf47aeef61433ef7418f68295f08d24c8acfac1eb18982163c", + "0x9a76cba0046b4e4cc89aa333a0f633147056044624c1b4c1c61a8a62f1f98573", + "0x510d25772f6e14f8e14905b05d8cfd6384561994ec3c92cc76fd37ae6a9812dd", + "0x39ffb78991cfab4236e4bc04325331dd8be2e06c4162f8e51aa592b27e1fa0ed", + "0x45c4d7eed33f4be6f8c0aba3ef42ad6a6e5f654b104895d9d662ea28704d6b43", + "0x21887c54231da9d400b964c63cb2f5378ca3c15f118fa105c0b2545528cf302d", + "0xb71cd47b4a6d40f9b18133c456c2aa7eb2bfe6170ca723a0c584ea28483d13dc", + "0xfb3c2158485851f4f564370c590f4a6b8f6481e6e4736ce9280a89d946b0e016", + "0x5c3ff34c067986eea52db9443be346eb1576498cedefc4a66379b24a3244fcc3", + "0xb27349be4de4d9be3cc9e904f72455c2f131c0beae6757592f49b2f0efd546e1", + "0x15877d8cccfa9f9cfd60408c5a6a173597c2e091a47fcdbaaf0a944a2232edda", + "0xa004d11f0d305763a613cb6d3d44a493ff669c5098b63b3f03e6402adc207bb9", + "0xc033417010a0f390418ff55348055e8b3e676c1d060f0cca2dad80aadc3b253b", + "0x035224e9c4e562b1f0c080ae58a7e9b8d48e565ab0be332fe580303a6b3661ca", + "0x6c7f4fcba6dbe1150b5bc6ebcf176ec3427e555978ca7978bdafa674cd50f4fe", + "0x4f62b3544c9828f9b7aff8fd5991e32b4f18e72c12b1d582c671a71aab4cbacc", + "0x8124e36227c5788e3608c63a93a8a0d966e4d8e12a81e2fa2378a969dabe0ef2", + "0xfffb09addea705c2ae3583b45e80908640b728867cdb8d49b2b1150280795b49", + "0x6ff99c0f0c3b3e208373fa3b7f031b8023b6660801a8ddbde0fe8668310ba332", + "0xfff2fb5a358d3f2bcaf5040e7e0fb9ad96fc918f3be7fc077a8aba08edc64a9d", + "0x3d734511c149e8c1f617fc48fc9edbe27da5e2837dc634ad4a359cb4fc1ce32c", + "0x0c8903bcec94ac45ebe8ee7c5875c23216d9399f7d14fcae79b7af4efcb4e503", + "0xf020a8e3254695e8c5a7b0a952531af6c886719b9354d4142946304220f18b53", + "0x4e1b5e445e923e783b878b943b0d9c9d2427cd8b71c346b79968faaf2a3ad337", + "0xea488d31ea2b67854997c6a88db87a13b4594b429b0dcb531eefede8e22308c0", + "0xc5dd53b4f8c9379c0f86e6b1270b6838d6a6e689865542791917251273c5360e", + "0x1646e9b43ac92494a90ae04647a4047f8de9640aa6f2c2c137962bbcfc80c8bf", + "0xf2f64a9c2e2de9ea1e314d84d44769a114c7035722f5cf7633145c13c5986216", + "0x62f06eb562f3c838c3b24a3da792769e9de8e2bfeefbd70c7aeb9271f19f439a", + "0x1cb36e1cfcfc9e4d8292cccd8d8b8f0bf90db7b63878e147188b16ec19754110", + "0x0316d23ebb039aa69d6b3b9b4603d9092f800b191735abe2a8ea2937b943f725", + "0x4c85e7f1e285380f4d80efd1d572781a93234149b8628350df7d93cb7625155c", + "0xde0010a2a469394e8422f52d128b930aa52a773368c3b8bf38a0dc830f161f8b", + "0x05ef4316554e9e05ca9a16c20f178481b630322c8dd438cbbc18c2bda644fc7e", + "0x64673e06bfcbe84232442ed29179e0b235d29e398e2867a484c2b60727377bc0", + "0x8dfe2659a262b307fb1cfd68fb18925a310691dbadab254c0a81aa9f9ea05c7e", + "0xb0a9fd59b0cbf68d53654d131aff4449c0fdd18217970c3de8d1adfe58d1f4c9", + "0x4ba2ff3b6232b74f661271aa29654638b05ce829083f54be06d8ad4290182910", + "0xe087ab9202b948f3c20cf02cb21f5f1b97d508773d8d7c2e5baf14fd52845076", + "0x702e6b8f663d10c1054de9751594d33f9e0915f1d3c71b36cd9c974574ebc85d", + "0x4dbec1c6654555295d0dada515dc606c18fd72e55b3cdb63ae018b1661c4385a", + "0x151d1c8c60780242caf26e5aeb8860f0ee9bcc4968e96c8c540d3ed0690d9635", + "0xf385a1e79bf23ea44d14b3f8668175342846ebc31e5a6790fca01b52074aa6eb", + "0xf5e94b06a1fbff820e98af762dcbeab9d38a45fe4099728543dc4784ec34b1e4", + "0x2396c1dc9e8b6cb903f97aff55b026511d64b88b08a05c83bc2ffd6becf60ee3", + "0x4b76c7764b5b098c3168779d95ca4aef2b861201c427c416c97b81372436d9ce", + "0x1a5d26c1839a09d7116868abdb2626467ed948bda413adeeb09c1eb146863369", + "0x25d61eb2338186246b78e3a4c4857c89cc6df0c77ec0f19b2d58ee9277c02d38", + "0xb9fab6c7fe62208f5f9c2714747714883987a513f115ba8d4c6904df172e9b0f", + "0x44f2066089cbd0ebae33e1b58179db26332ae99534ae4f864abc94fbcbdf1acd", + "0x97ffcb0dc94906687481210847ad2522c7cbff5758f6242c8a6ead1a010c0423", + "0xd681901709d666912f87058a300cf15b0bad137f4f0993809c37372ae1a73bc8", + "0x1e89c647ffabf82e228aa2ad65a989da66fb9f4a8d0f3efc7d66d72ef75f449d", + "0x40177f69aa2c7f7711c6e2212c2278a861100f1a46a99c340992e776f278bd99", + "0x8c09a1a9e84305a94b702fe21ed39db90d2c0eee6ff21185c555496e99c9807f", + "0xe13af929bc3b6b693936cbe82ffec90cd2d2e177758af41d5c7c7f8b3922582b", + "0x4ed170e95d7b677fc97533837ea0e350a30df6a3862d7b7794e051fbba68adca", + "0x5603af56d81026197df080dc437f9dbedfc82f1acc26f2ade39db63033b7a053", + "0x815bce3f12b5c5b5ef1585ab98a025aaa8117efdb75d2b677abb4522e4b933eb", + "0x603c0103be82ae58d4af604be625016b64c4985e3f2aae31ed620d1635d85a7d", + "0xcec52fdf68b04fccc6c7dc2990412c955d08b6bd4a7a3f0f9fa77d77d1c3481e", + "0x1b3a7d5f6206a15645ed55669485dc4e1cdf7ba41f3488427e8b7202d6175552", + "0x59946fdb729dbda327e825d64932da21571c83e4170c1c7748c527bc81937fee", + "0x676793de267e7078dc3b6927cd472eb1babd4f537bdd8386ee65b88166cd592c", + "0xc5379a7f5ffd7942f9b7590ff83592d91fdbddfa09c040006564434379868110", + "0x44860e8cc625991899e5a5c16d805f6b1aab9e1a79fa462e4ff2f92d6c40e76a", + "0xaa31dc38a358e3a1fc78c4cabbf05517b2ff78e23befdfcf7595074bc0b5498d", + "0x9e7d9885b3a84dc90dc25f1a48987d8d4cc1cd08f51baf1c3f33e86fd17341fd", + "0xd6790620e79c46699c21b0bd61cd09baa1e2b350fddf6d125c4c06fe30a3244c", + "0x4f60d8a3dc5859f69f1b96507527d2afbf899854e72d0d12ef27086dce561a53", + "0x67bd7c84772d709e1276a1863ab4b26ec84eb02767a804ffbda23eba3a8af0d8", + "0x707155713c08309b0ce29e867a9c025e36876935398a87d1153a997801cd7b96", + "0xe94c592379266a58679af9df945fb443b790e1c5a7318a5a1738070ec479d1eb", + "0x00205e95873d1670a9212fdcae09b06fc941128e4db1427fae7b3de33105c292", + "0x0a730cf91406030fea04d74b78d1625a3e5c73a1e7f39fda6db9225e064697ec", + "0xc32b3134dab797f09bc4986a7d9a969b9331a99e431b4026abde8d06a7910f19", + "0x7b9fc8ad3f2bc9e4c680e2400fad27bd0de271f193cb4f7e9727a87e999aecf1", + "0x39d65165378d375fed612489145d41dd4f9d57fcdce1a5fbba35a09210edb201", + "0xebe86247c803ebe65de42feab2d95a8d45775f352a0079e6a868692f444fabfd", + "0x04eb04c01e29b4a0f96cc9072576a8f7f3cda3fbf9b4050f3853ebf763bd85f8", + "0x701a86ebe017b55312ad8277eee062bf0a1b1ea2595631c9c28c740da3d4c117", + "0x57d6119ae2469213c921ac6606f41ed137181c179d6e207d21693399d3b21e67", + "0xdc189a5837c11ead4c6a1b7530b718476a8d0ca879fa4e499d72f7d8fec348de", + "0x96511948f65eed76fd3e17c9f1201e605ad2ee59778df04fcfeab5206dd29192", + "0xdb3930b8a1e2a8eb35940084eb0e98dc53aa1d3aa563e3ca6b260a50cb3a68a9", + "0x806d567cb6fd15fb18007354be55fee1c2b5f0aa1b1e5229ed0e758910af617f", + "0x6e2e8273a970e21164be1e548b92963ab241a68da41e9e231c12ee08bfa4129d", + "0x168e45c60dec2496e48b471b7d2fe1b829e9111191e6bddc936d0787fd42eaf7", + "0xab1ec5c8aeee05f24428c291a4d8afe776a92826f6e58dde95f8bf63e5c8ea29", + "0xa9db30a831b1ff69e38b342ee4fd3c9a8c3f5cf7b647a0c7f5735a4682eb42db", + "0x2b55ec4fe76bde0bc4f8d769d3b182e4ac7fcfd85a28c89fd7fa5d511f41969d", + "0x74ca1b5889e8920833042da86aa8d1259463827bc0cc9e7796144927757e7db9", + "0x5a3d4a8bfd449265b74b85e62305c3184209f12f4f55271cebd7d2df56b9983c", + "0x0b450e356dedc2d73ce19c6028dc5d36818cd3714879e5a402dd8cf7465b2253", + "0x073f03a0316a886c4cd71d4cec42ee7705b6cd897932b6547612f3cbc5c6b8c6", + "0xff2b0244634cc4fc8cae0b44f737dd47db2cb60e05578a34b336c46d0ddc8f09", + "0xedf8c719f93e1bd0cd421bdc14c03f2795dce10bbec5647eb98f5a64da5e7f74", + "0xe9192cd76b33b1d4b09e7d8c3e1ccecdb7a532420dac942934ab76d6491fafb5", + "0x5fa7a590d22896c2ae781644ca8db3ecf779691609dee9d0554ce562624a1e9e", + "0xe6af198683501ff90b9d14a343553e0c5d7c5b9fdf653311e022ad4a33eab72f", + "0x3c28170602ddcb77078d6f715a6629aebe4a35b2498a2cad37057f3357598dd5", + "0x29aa81bc8d9c54f146917aca4b1ea1a0f147f6ced0d23a647a51af942826bbf1", + "0x0056b54bb953c389159a761d3a405b71cb54162481f5cae225b86c8d2f409960", + "0x3c4d9ec5c31c3c087545487bfcda5db713f1ad44450eb310a66d66330b67a0d0", + "0xbbf3002577b95053f241733cdf991602a570a6f33935d50ad64bd31ea9a8714b", + "0xed526f4ea68cbb5a15baaaf6ea698e2d293afe848f3056b803646046aa6d5526", + "0x0162b7210309d0144b8464d21afdbd80b5ac8bc3cf5a93f32fbb87565fd4c30c", + "0xb051288210e1d0ef546dffc2e52026815261e2ea866e1276809000a3e7e3d060", + "0x76397a5e4c77029699eb10959f51ab090437888ea06b1c5d0cdf16b74bc44d3a", + "0xb5cd5928e3dae6cee3ef0fdf7f1deff66628ca8ec29743bf1aedba2e10fcf9b7", + "0x6d1f9aa0f4ab673ca6d0d0f10bdb491882fd1d582c2489eddfe7084eaca0b034", + "0xc636f215b9918856a0ef971a2340dd3d3019ba671c0118c352a1bf64e50f0e61", + "0x8ed6b16c3b89411cdb2a92cd42f2ba4983b26a83eb3112a6a376015458aea55c", + "0xa964e5da59c92492270317ca6a0b86402cb22e0c568dcd20a90b3e826846e634", + "0x2f16af813410d4c3519d9bce71c3c31ff09799d42760f49790f3789a2d365046", + "0xefe1139708e6ec67886b9cc3d6efa9b2b67868c626c3541e7d7a17c75434f2ae", + "0x199135b37713cdf4e1ef3766e331ea84f8e4911552de1e3c133ce9a3a3b52e1f", + "0x400cd17cba12320d710833bc5089c070c482f6fd4188b704628ff47611ca12a3", + "0xaf26e7080fc110911a649b03f8212b43626cf75c867b2af9e70cf35fa99092b3", + "0x346dcdf1ea179f89187527d73747c6bad12ee0efe4c02eda34ad3704d24638a3", + "0xa6df7e1b1a8fc69ad26110c0166383e5d4db331e98fbebb1b56611e0f7539a46", + "0x9d2b7acf84de840c1cc035a355360919ab5599ffce825dcf9598b6c8c23bae24", + "0xf18a92492752d0a118efb2ea386767122acfaa728a39d788cbe1e836ea0f6378", + "0x28f49f4f5a61322658ca40035c0340af61bbde7bd42b74c4a1867b19992dc787", + "0x890dd6356256b7bcdcb27d415c10709c6e898e5f947ca209389b42872102b36b", + "0xa24f6907d5fef0a0c28e79c3be437bab1e4470d29365b9b4779378099a9c3007", + "0x7ce1d586d950a3875954ef50e2b6bacb51e8cb11db45c34b709868aa7eb6bb4f", + "0x5cd316a998fca726c58a56079b8793d208f2324e399413aad3fafae077d834c3", + "0xd367cca6c37fe087c9acf4cedc12ae875eccfa34a4798bf916a2ff1cb245a8b0", + "0x78a1dc488545388a618cfb6eb0047236adaf32c0b5bb3dd35a1843720e41afd3", + "0xb7bdc303b26e920a184e250c398ffae03fe29491523b68e2a9fd658c7f55a734", + "0x72ea58270b1512daa51c08840dfc33e657c4495a5f50bb6ade1fe4e7f2e5d35b", + "0x3af82e240d734c66ecf715b2fa6d42a5976f5451694a9669ed49cb4ce6d495c8", + "0xd875ad205979ae78c6d334e5c2c0c539574172be4f2113e53dce70ac6320e1d3", + "0xa808ff0a2eba422021f62c0de2cb9ea114dcf340fbd97ab0506461578db78104", + "0xc6d5c1cbcb505220f3f47fd100470180620e47cb5b7ea81b4e6b27976ae093e0", + "0x3f788657a09cc34dbf670108046d4debe140154ea8283f5a762b2a6f1927cc89", + "0x0441ef2e2865848be1d3bbf10dd99bd9b307dc6a3833cc8066f71fcc9fd4657c", + "0xa033b833635e284605c2a25cf4b9ed595a8f6b7b6928a60f849019b68e412197", + "0x0c6bf4f59f2369da915c5cda4358a1b84326c94cfde7886fa99c3cd8cce00d3a", + "0x16f8cd5f6cab6aa0968931090a06cd78804da1332ae794954e43e880e6436380", + "0xc44d1853d161e5970cc4b0541aa7498948da07226d9747191d677c1c6c61260a", + "0x63fa006b716a07a172580b605dec90a99f4eb1caa2b6272918e21206b3b08186", + "0xdb0d7fe87810eb83bad89d04f279a06a316e9cc9afd6b249f77ff8da54dcffcf", + "0x04a1e3ca62cc77963b58ef79a9e2ad8ef54216034bd160728a7fa4806c0ccb62", + "0x3db1db1cc10010514a98f45142815604a945544ecb6438c63de232009f525ddf", + "0xfd6619df5d873b255c6e516cf0e12ec1114613a5d803e877fbfff779ec20a1a4", + "0x581ba19ac99cbbcc948c61e0614c64008eda6a58604e9197aa8470266821f331", + "0x316dc2404582e1ab45bef960907fc16e6223639d1875f6cb7dca9c7744cbdd30", + "0xa5c585326fda6f89e33d470abeeeb12a6a65ce9624cf01c5e2ffe5e397ec8efd", + "0xf08862fef3ea5a98b6b4bcbf0b57b482dfa149ba4d5e530829eecef1b5e0ecf9", + "0x7bcb4c42db39ab193745ac34c75e68ab457aa03c83da11f7396df2491a300666", + "0x69424ab7bf19ccf3583048e9c315a5a5d4a7d85359d6b4a3a7ec001be96d7212", + "0xa686da5793c201b92867db72a5f8671ff473cc12617437874644012ff242984c", + "0xf8c11302b69a3b2ad86e7826f8cc85d0ebe21e6420ebab0a7093feb7f15b985c", + "0x6ed81186ae9545a36b50f9a0fa0c82f2f52bbda7e8e936819628629e29402018", + "0xa91851b0638a92d2733b63125085982e5ff2acfffe66f71d3b218ac4ddb4d268", + "0x895ec76e33463b1e9f6a38a15a787ba84812d8d3fa6385824618b7de7f8235d7", + "0xa2c45ceebbb227ca7396e407e26c88bbf0432483608dfd169a085c5372ebbe5d", + "0x8cd8558d7c920df4bff9226cb91dc674d8788376c694ecd27bd84291255b237a", + "0xd9e3c84a853e9b551d296c560048283aff22e0ea3a0853e60505932f06fc0b40", + "0x5148cbb68497c824a428f87cac9512dbe313abf6f4c2b9fe6ee78cf909d4322c", + "0xd5d0a750818cd28793a1238c194503635e07870a65d5a8eae084a6a7d152069e", + "0x83c94a89524371c5bfc66e3ebfdab49eafaeb77fddd5b31bf3eba609cdccb083", + "0x4c3e549fbc7854bb417e50dd281890c745e9748ac7d830acd9c867a2abc64db5", + "0x642f75489711b36d89b0432f92f1ee19d3b8cc1fa99d2c55e8659426068da0c0", + "0xa4a944abbeff1a3d718e28a194bee6bc066f01aafcd0d674919e19c4ce1f473e", + "0xc9336cd020b35855fc7c4c3febdc2a19d4466e22d76ea44977f50fcf00d30772", + "0x0ea3c8090512fea72c5d457e0f3aa72fa0fdda928124177fc07587db60ee4c8a", + "0x4792e45b5fe8a3e2179b0745521a8269d887f8751be3f2c8e1cc8aa9ea0ecb7c", + "0x7ecb169f378c9577eb1af269377c16d25b09dd2aae49705bef1d143b099ffd48", + "0xf9722b9bd88dd8712c2df0826798b903e4e46ebea1caacec33e626b1954bda88", + "0xc7596d6ba28215314a8c0cdda3929284a0f98b14b67eee8bdeeb245a042bf5b9", + "0xb14ae9ee5e30cdf8fcaa8839e06f1dd1c273b9a7f8aa33d6a7f8a2761d6411b6", + "0x160de9ec9947611c32bed5b39fb688fd8521e0be0c992f318e8ea596e932aa85", + "0x166b7e4682502a245b971d27420a50d028febe29a06ada52709290dce6ff65c0", + "0xb3c6774d9d1415508baa55827001283840a3cde35900f0274eb78cc169b20e48", + "0x067c6e4818cb6dc6e098d2f41a0f0d4d555d3079a271e15e24b40c2b33d48c91", + "0x5f43937304d8f1c5915bed915daf11310fe77358a83b3dd2579986e9e63a418d", + "0x361e8400ee55784c4edb63507bc047de04fef5e5c96c4f70c9a61cb5d2fd3f5d", + "0xd6e24a0733e82cdd74b1ac6ec0a54ef3bbad0f68461f804cefe07a4d7e15b359", + "0xa3ef3d7ed01caca083c8cd24b0b2e6b93f307ab3bcd7fb15cc49de6e76a85054", + "0xcb22fe8e323ef120f5ea5f6604ccf7d84adeef7b15f3d81247a676604d127979", + "0x39094ded1f8ba3edb8f9628d72375ba2700942e0870a267ccfa75419231f8ef5", + "0xcdcde1fbcfc0138689d35a44fc9dd9f0b9b43f6bfeb9fe29ca02018ee5e2c358", + "0x75759de7eafcd4114962bde0db7b64e175787ea56aecb37f5b1045900ee8cc0d", + "0x53cc30b0160d81c37e5b9ace29a55bf07beef84f1cd71307b140e2bfb533d0b0", + "0xea48a27931ef94e6babd0342424cafdc835663b381983dd325b00c8b12ef9f28", + "0x3189d2f6c9623c4570d93e4c26ec30cad659f8482fd4bfae5325932fe57afda0", + "0xf0822c0d02fdfa65e48362ca1915c07797df6f87e0a98391ab4046ee4266b758", + "0x4245d5e75abe515824bebc31ec8e2ed9e5ab027fae1c9c74b49e9522c496f00e", + "0xe4c84eb52baf4e9bade65b3711b6bab7e16fd8a21d1162a24911ecdda4ec4c97", + "0xd73d7c7f12b4dc0ef75f4aa6f006a2efd64a6f54f848daa05efaf9fbbc1743c9", + "0x3e73cab1286dcb25621a108bf70103b8a67aad50d03b2a27b15f32e74d2ecf76", + "0xeb61a019301e6d597516b59bc2314f75afd9f8c76ce5ee4b2abcea2d5af65d22", + "0x6e1beb679490b6480aea261f776194bc2943aa7b4aed0edcc06a96472b6a5012", + "0x5c753161fc23f9bb1fc76df8bdfaab24fe0091337a36a56d0f5f959e4a72d903", + "0xc60ec5c3fd1986c8478f5714691a31acf469a5ad47d31e1e6137969328e86707", + "0xae9bfdfb4a7e54835186e3f161249d435420f83a238786f23c261ff0705cefc0", + "0x3a7ca5b57771c703881e05743b76622360ffec308e21b649fa9d2b77eb0485e3", + "0x093ffff3c8d30950e82d67887d44844d21f5d0d333534c65115146d92d667778", + "0x6b460d7cdcced9aa43dd87660e073e6ad6c068c7ff84aeb86decae8a18f0b0ed", + "0x1e23074207fa45234ca76dff1a5b4d78ee87839029b9bf4235cf5484a14a2ef0", + "0x4236c643b14fe734a6fb1e4f9ccd7b6b502ee5d24fee3af1201d6fcd5e2a4991", + "0xebf1cabb6606d20194f82bdfc22fef39e8b73691c802c6421015615cb8651ae4", + "0xa065c07d917d768a40ef583dba8570be0e67c5c067286fa6ea55183ed17aff9e", + "0x2ffce3fba6265f1a82be15315ed6fbaf8710133f2b8242c6a3a3b40da66e98c4", + "0xc814a7b871102332fe8d4daf0c8f7333a9751e3f29b7b02ed4d15a8c217d1490", + "0x29a0b87325be7115d4605df2b65991421f6594b3d3348238a6101deccc88742c", + "0x1fa4239e68c4fb68ec4e8786801d25ccf225336d095888879953c4543a47ca57", + "0x2bc5a052f0832c656a03210175d28fdd0109676e5cd6daf08614b6d9380e0156", + "0xfbea1e39f1d77d1cab4b111962e1b0bc8580fa4d353efe89b95d1ff5f9d249ce", + "0x4e3c512ca97b1d6dc6ad8f0c17e336aadb740ac907924ca6e037c3820d484a90", + "0x26e3d31503539f6fb1220ec960fa450ba15db330a82b97584f48af03e71d3fe7", + "0x37c3e1d006c31c06526b0c02df45329ce4ecbae209231a2222dd835ead7bd813", + "0x9eec04ec09974b5bcea99b021c6fca264f32b3ac895dda421482b865e9d0c340", + "0xa7a9d9fee641431f2b2f217a57a32ec61f03a1c692304768d58d48ee1c7411c6", + "0x87a5638751fc6b716bc25e92292a977f0de1b5f53fabc89b342a3f8c096e509d", + "0x084dfd89d9e63f625d7bc139a9584182937321d0a5e2b61e280cfcce053813db", + "0x30b73b647de41f3e753770f967615d695df8b77fc0e1f770d9cfd8a8b7bfc1cf", + "0x8b05b1906879d64f6534f7231ae5aef00d86c62915537ee54956b2cadccd9c7f", + "0xf1c883baf6073d2244d5b1a40b7e7ab99a22252e6ed34627fdca985ab87d94cd", + "0xb6c207b47b98f0b550eec7dafb5e6bb23a4f1061055542bc1805b6e89dfe763f", + "0xb5a37524abfd343f821cef4a3d6c66d5343bb56dbb4f5217f7c32b888d72c3fe", + "0x326124edc233211d1dec747ca38045125b3891938e8b449b0980be57fab79a26", + "0x4857dc3260a16bba60639a37fe309f46351d2bdc15c1689b6b86c16ee8b4d2b0", + "0x6728195d486a624099eee5c9b07ff62cb8abc7a66aa7f2aa3cbc565ee614a17f", + "0x0a7ac687337258206323a3c49d88ad4ed495e9a18c848a3d8ff51be0eebfaf68", + "0xe0c1882697acb508290737788cfab9880ed09469e4093f6c95e7282f4bdae4cd", + "0x80f763c0e43b60aad58f01aac1275f310b3cde5e3e8f2fb47dc6587b4a5b21c3", + "0xf7b62180b642b826340dd1f69477a136146d341983e4bd875823d804ba205c94", + "0x6e775aba73a0596d398c5ccb9d0adb8d6236cd7dc235e833e69a0a2a369d225f", + "0xa3c65ff864601acedf9ebea681039ae9d19b961b84c39c40561c2ab42b9956dc", + "0x5f5dd206d841a2a0a85186e2dff2f7d862e47e1bc11fdf0c883412643cff72d2", + "0x39df5dbc5ebeb3d6e94e02e90f987070d9f73060e3751cb5fb6c00d737d53a24", + "0xf3a78e92493d0fdf6430671c820949fc39729a366b8b3355634522bccc6fc7fa", + "0xd12bf11fcd9ad2026a340671edf4e0fcdc6d107f338b5e8cd1e110ce8b2b1f97", + "0xf69a0ce968327b516a50bbad9d035e3eaf78e501c11807516ffbe6d847103c12", + "0xbdbe28bf74fbfc5eedbd363cf4cc2792e948ffd66df8006372396ab2b901d9b7", + "0x10fed02d557ad1ba3794d9e97efaa8bf7d6ec86b08c04c1a3c63e099ac3c6fdc", + "0x0735058d7226f806a87f80fe5a55bc6756c96da1fb92b058c08bb2dc6356f4a2", + "0x9c63cf37aa1e235f4fde0cf88c13c3e87396646136de26757dfce9373bbad078", + "0x54105bc5dae2cfc5860308caa5efddaf6d6fa16b6506900851bf8d9311d85945", + "0x26a920994c14e7ca38d62bbecc09c4885acd455160910ad3b778338fe08dba20", + "0xb7d2bd9ec2f0c1824ed85476d70eb3ae85c132545b09b5a3fc89bb647db61c29", + "0x44f8a25051ce2d5c3b6edd22364657af990fd2b327acdd258bd818dcea5d8f10", + "0xc504b1cc18b99305f83cfb82a9452ef1b6650acc7a7513771a9f1b9c4d258894", + "0xae14ce142031a2a1500aefe7d5bb5f2c48fef2d40bcb3cebc4465b5f588dec0d", + "0x26a6a67c3642f7b63505fba8bc8f4f2db35875820853a7e93b7015cb59ad5288", + "0xef2cebfed16dc3ec1ed7adf4d31a907b1c48986f3bc678f0e0d42260f3e5366d", + "0xcde8bd5a558e4b4aca53d0d164ab030a9206e0a3dc3d52750454cd5dbde67a87", + "0x80213b7c8404bcb599c6acd3d0c7b97c821f9eb36d1a261c7d59c66aaf783557", + "0x84974ac71d8599e8b481f4ef1ddd2365540c97d8a14bc55b036477b8b930a1b0", + "0x22d700ec6faf569754dace5bd720287156b44a7c647338568df8316e4a3a1590", + "0x0f174bb7672e56e087429fc4ada9fdfd4dea9f94abd976a2d9c1b3b2103883d8", + "0xa31dce1e1597f2603aba9b84f545c56947496b648b770ee9bee76b26b076ed0a", + "0x3bcdc44880d4cf88f9d3a107bb254607cd799cab841346ea3dd2e10dc461947e", + "0x54d99c8c46ffb8d4a6c2453cb2ef92abbea6cf8d666f627afcb1f7383e248c9b", + "0x4bad0aac0f99bbe49041b0d7b7da2d0b379cd9a1a4e845f04ee6c399020062f4", + "0xadb0bb1b69fb15d78f835ef5d2de20273faef16889952c0578d3be609573ad68", + "0x04adca8a68fa1db84b226f2e46d3328be74cb9596e037d9e2bc612e5bfa0910a", + "0x9630ded627a97f9641e9606a5ea8eb5e04e0a7e52dea484b2498049e26a596c9", + "0x146544215d83359045dd52eb7821325178f25f950585174c97ce6431e84c432b", + "0x743b7f7b7e0e4bd94ce1cf7fd26a42fe3e60946b46f12094336624b22799abfa", + "0xbe5842fcf8d27fd42b2dd344f4fa80a5ec75576ab0d3bf7df076d2c62c87ee63", + "0x0913189b9ea0086155d331989622986163ceb9d8df937b013466350d5b6cb9f0", + "0x179863d8ee06cc5012fde594f93fabd674cd718e529214acf0855ba7920e0e5d", + "0xaba24275c0e3fc84593d75c0ed0ef64562b2ca29a63c9651ce2972f466f588c6", + "0x59953a3a63270197712f70bc8c1f3fbb974f3373967c76c6ecb05b36624c4e9e", + "0xb03b28ea463ee70e33fe1431556e4186a773476100a61200a72dae7b5a917400", + "0xbe29685ad0f0e4f4e06f7aef6ac68716345a503096669c02f9a4cf2645b20fb4", + "0x77349196f4b655fdf90ac091bf217cb4afc46efd8b3738438fafea3ec8bf6afa", + "0xe0f3c1b6b1f9a822f765a8657ba73b6dac6856b86d73aee29ac8c67870cb5d49", + "0x1e9967c1aa6cae9e6d6ce588cc7be4458e30f004f07f0886bcea9f1894409541", + "0x48e90887d177e254c035c4e6341e43e2fd4b69934f357ef0633a4876af886ba2", + "0x18b962c2749d6fcc59615c7fe48242c4593b18d9c777bc8929f663bb2e500a62", + "0x437628a508e2589d87073ae2cce6867feceab7ed948913a5f367aba70ac752d8", + "0xc76db66e84e99a50d9d43255bd34937dd98666850f01c7abb61a59c61c48a51e", + "0x9c97b43a11c959976be2dfa43d3e427c81c9f65f0cec38a30174753911a0aa62", + "0xe7a8db25a547dc1ec612c3270d98ecc5d358edf0093e9a47f97bc162e2563c56", + "0xf8e9f99e26b147e30bd22a71a02c2e87a4f816947b23be23d7a998bab0bf42e3", + "0x9cc232de33ef4d9c2701403ee75627560a4a290ec00e9fe2bc3e48d22729e4f6", + "0x83b328313a8256d67a76a199607871c9d7d91ac4bba03e4c7eed2850b863f014", + "0xf785f6f42d160759627f956c381c0b2afe133191361126e1dfdcef8ef96a19b6", + "0xba15c02abdb13795b7ffbd05ae808df3ba6dd49d3f6bdbb7594301fdcdafefce", + "0x7cf481f442daaf09047af092254ea96b3e6fceff47e7354dca59ce92a7f0192f", + "0xaa09cc16199e82bf7ca1c664df1683dd68f60392383aa86f7a4d70db4fcc9ae5", + "0xf48584eb70849f03500c2992ca9d8a25c6b4af1dc6b267bf96b8daa844653671", + "0xaaea21fc3ffc8af49d5b6c8ff06d212fd5cecdcf1ee8bbbf11081b610e5efd56", + "0xc3b611e4a4769a4cd86fb97594b05eeaa1438a531661d0c46498ad1d5ff0533b", + "0x86ed5238ab44b097b901bbf7a2f76c4e554227377fd05cbde62ad678b9b40521", + "0xcecc96f7e1da3a85044251681174c283cdf818549338d0ac8c55ac32941c4c52", + "0x8e476a409ebebb50a6b4ea63a57fb97a94325048b98e9038155f44cad234c5b3", + "0xb0cdd01f69adb4482f4a95869c27e7f488b8d645e9da2a1eed7c50db91bddef4", + "0xd59c2ef502068560309402eeafba81b6104e4481d08d294fec8f4a14ebe421f8", + "0x117637dcdf602facd5ba4ebfb788cc6e894172a41ccd461371fb6dc3b29ed1e3", + "0x2088af0cc8a2d219cea2658be188bce545e095d526152531ae04a0c1026e15f7", + "0xbe9d09c236fc2464f9e96468304cb107c1015618c0777414048260ecf3073a80", + "0x0e21d49b429787ecc39920a7b1e57bbef8b54f6dff555afa96c6d664eba18002", + "0xe93a96a4f59c51c991822d4ee0ce843f194df8ef1df1aaa3b15ffd4a3deb2902", + "0xfe432910348f2ae69089ab89571297f755f70d9e52918b761b7cf059bc8fbfcd", + "0x7589450a89b93dd85dda9fad10249d5662653eeb34135a8c5dcfeee2723e714e", + "0xdbcbd8f60a88aec563061478b12c5ab4ceabe1deb3f2df53fd862fd6742c69ac", + "0x4c77ea8aa197a0446c2c85bac546f8eeb7bbce07abb092450f11bb3fb6410575", + "0x465ecdf71fee3c0e42f2dbddafa3cbfb53f4c9a886777cf13dc55064dd29b07b", + "0xd220779d8eba431d33a23b369241b357b399875205cc432069b445426d7a3099", + "0xc6b84a981cf211d41e16ad44b1e90fdcb71a92230c9ac679874f0cecaeb25254", + "0x31841dbf1cfba19ac78cd40136a8ed9f35a77d48fc927e049d58d62b3ff7592e", + "0x0dc4eef3839d33dd5a516a3d4227a3ce23a9a5532d146f37dee88898ee75e7f9", + "0x6859f52e3c1ceab008c2fd85fba4901d7543c99ce5aaf36ccd6534f4898894e6", + "0xd16539f006277c2a3dcd96d3f7e9fac7d5bb0d63afb1d208960e597ce29ac429", + "0xe0ef33cdd414f24ac2e67ab2329d3d728f3924c50032857e57dcc9999e37a182", + "0xf50b311a95bb72916c6d4dad0db9779144a85915a12f895829ca5de9d697fa52", + "0x3f773b516c1779a4c5cec58f6e3a0c1bbbefb939db70bd84ea4370548df29c06", + "0xa3348605b4ee98db29b6bf80eb8181f4200d691e27345732cdcdd09c395f0256", + "0x4f2970a9d6dac5eaabfbb17a916bef4571e1147ffb5e241360c6941ec5628815", + "0x1b7f448f52b39279d47b572e55bfbcf893e7d106436a46db2a0ecd888d7806c2", + "0x89196aa22dbf319c88fadac3c051c445c6d59eb60a62ee71158e4893bdff8706", + "0x1ecc71d15d386ece87caaab915d0a10ad763cdd38bdac269108e17da3183d0ec", + "0x99b80ec779eb253869cc4351371ac8f1896016de0c501271a0a15bc4130f40e0", + "0x09d601e2ef7b509d5343a8b6de63d70f99a453540138d0596b80e2f39212fe4d", + "0x2e0412de93ff148a1365719ef562f54addcfaffa64a630d2bebbe48275377d14", + "0xfcde011b08437d8db6c4e8661b98ec829e204729badd675782a7792648a32c40", + "0x075e3439595f2e5953419638c391ad68d634da037df91cd75ab062f5635232a0", + "0xe1c770b2b8f17b25736880a7d28e09845626879f61fa7bae77202178d26e2db4", + "0x10eb4649692dc022f7542da5156c8005f2a9d6c4b0ac81b5ef087bd989a83534", + "0x612745b3b43e42cb44d302016ab33eeb1924b8ed1a1bc4ea86985d88184a1704", + "0xbc23be71d7cc509307ebd055d02e396e867e74ff401583b5801546b12cfbce30", + "0x55be4d6f914bf5041a111b949ba61807b53707ad6aaaecb347e9bd53251cfc98", + "0x6207ddddfa073ecbeac270e0490bd4f1b126e25523350e45713f8f76074035ea", + "0x7c2806322ae925abe44606def3a91a9546ce5557e61517d22c94a6eb358aeea8", + "0x2660eb9fe82891120afbbf8d17c3a0c6e71a7373bdc961b398fb3924d769534c", + "0x8e94fda030985bee8161a349c74a10715ab29b4c404c4200332a124f8e6c8eb6", + "0x77c264bbd45e806388df32d1d30b7567af8463c310b2e00ac075f202594df289", + "0x11307dbd441966c22a78712e8026ef0be95c009a075b1d75881f45a9547c9469", + "0xd487cb10ea6f81c67836eefb9cf326cb01464b8a4c640359da0ffd0dfb5ddfab", + "0x32e5ceb716c69e4aa115de40404f0406841a43b9d1a7503629edfd830b8070c4", + "0xfc69abcbaaac051ad68462b2b6fb289f093cc8f965a31e4914fc1c3ecca0a62a", + "0xdb2c7749b7f5e8e60861730a3f39531c9fae68bc6d5cfd884b054b14ddfea8a3", + "0xa641637ef64ad91eaa7cb24851870874c04c74e3c57825cc00bcfca56cd671d5", + "0x6e55a7184ed79701a582293b72c847df32be67859a34cb73d1efddcf92c7f1ae", + "0x0d30de75a74723ccaf326a096048686a6236a5d9728e398b531ea34a20273e35", + "0xaf9e881b47ab25b2b667a9232cf562ddb07d30194f6a3358cd6aacc414e98f3a", + "0xbda5685b8567d1c43530fca95e4c671d4f090e50d0ae631eb7082f260036d5d9", + "0x21fe5a7e105e0e2f68698e20f88a9662bceb20bfcc884d493cfbed72fc78ae8a", + "0x1b45a77d8ce14a769f196ac4a195207a63241ac8c8ee42e17c3e0b340b1c1492", + "0xf8fc91a39b6e08d874500e240a6abea002794f104592d18ea01449589b06dc22", + "0x45d9330d6eecf2eaca322e83df77277c76f9a95b99c5fddd55bd77697cd1159d", + "0xbbd726c3aedf917c4741952ee3a21d3c1655aa27cdd98f44d15dddeda185c520", + "0xbce90dfdf79213f5e6c69adfd7efeabe74edd6e2f07a1af7324cea9d70615386", + "0xe50e0dbb2106fa5433506694325d6ebdfdf5270c17bfd255bf3e5e7c0177015f", + "0x22ff7ec5117adf2f0aae8532dd371ad9d902a69babe3b26cfce4a324854092a9", + "0x638b7c73e85e4aa5074daf2daf66c002c00de5e8196c2c01e6945d7aef6661a2", + "0x322d5f71ce4a0e743ce017f6ce76944023e858109a0c36fbab41c796b6f9c8ba", + "0xb55e7340a551bc76ec89ff3ce1c7bda807c75b6a89f0e97ff4a4ea59d232e91b", + "0xe7084bc046f4975a04be1ae50f4e46e69b7d0a3a3886e60f989ebac4a7d3ccd8", + "0xc540174cecd421363ed6b4a95fc554f0ed0a7e4622cb2c0643555eaddebf287a", + "0x03e84b7ce420aa276d9adce1da92c950688839cdd3dd621f797eba5b6986b3f8", + "0xb75090e43bc5790bdfc86a5c9eac4384d099daef3d40e9fde443409f4efe91ca", + "0x7e72b4a7ece28fef076331bac790e49ebf926423f2414c9cd78788c8cca28761", + "0x9b9b702deaa509fface95de5048fb864b80d7891fabdc7a9770af1b24777f5dc", + "0x1b056b381e1c60a3c126f2e5c4ed98252755a5d3b7f3528584dfd128eedfc89f", + "0x8711c4892f49f2c1fb0739de8eaf08ae8c8c279ec73e42fb4da5b25f22d73fc6", + "0x70ae1c1cd310003a4b4e36dfb0dc7351b6f49aafa2cfb5d691fb59a724fbd387", + "0x796d8689110932ef6582af180818bd11bb9df2b06ab1107879612dccc190c334", + "0x58ba45b6ff40da3f3b76da55a0ea9ca63aa135ce308c5d262886e6b1e8869621", + "0x8c2a83da544b209010c6b52618c3137c1066e4fec0e1731d6be408ee881d5844", + "0x1591af374ba5612ece1d642e9bd280a9318c5bda73ed67bc1e7d65ef5616cf6e", + "0x666b3f1a401843af2bfde18ce659965b5c200972da47752fc2b4bfce55625af8", + "0x23331ecfd36f8dc53c388ec3d97a1f364a55b8d701389fd56b867a828eedd187", + "0xd995e1e27b596233e33acabfe03adfeed6d34b421b16d5700fa4b3c234b91ef9", + "0x819d8d3a0471a292c89d0093c3458d12bf83b60394f8c03053bdde51cc08b217", + "0xca27ca64436b71096f37d6e0442a9a93097029d5f4b6d042e2a6bdb3edf94103", + "0x65d5ed59626e98c2bbd6350e4a10e3e45d7479eb2cb6538c5e020fbcb900fef9", + "0x812b423882226db0bfcf2bcb9f1bac80eec3388755dbcf6b613c9f6faf1517ff", + "0x000182526c28c1fb862e74300fa89181cb137a39dcc02fea67bd3a03900fdf4a", + "0x1cfc60d220c883c273603f885193858926f072d3e0094a337d12268007644d5d", + "0x453d43c8dfc8df47751045173fe9e5d200fff28042282d67c0ca9230728329be", + "0x591091aad61a44c41c91b9ddbd1b6159fc9eec6e9c5839c6a0252dfa11436e08", + "0x464a2b049caf36d77652c2d721850d1f8db2fa70ca0964c7f020152612bea380", + "0x8ba06aad1a433193692ffeba643a481e2932f8a2ac35ebeb04c9ff81866d294f", + "0x4d915cf4c14d518463805c6bc92edbec4e8e8689e141c542d743c40640559bab", + "0x0e72daf5ad4857e563921671bcc26eb186f37b9f9d44655341311a6b529200ed", + "0x07ee736bd010d419da4e5c37ed17cf5739a56a78947b4257264acea62b5d6334", + "0xfa03e571d821780ce501373b529ca3de36a53f58e197d64b57f0941288487734", + "0x3293babf49116d584283c915c0c8a26f9c696eff261e74d107dff21e8b2d08ac", + "0xb2f169d84ee6d4ba54b1d526282ab04b7539f216e62362fb20a569f129d2f89f", + "0xdfbdf7d63f67a6986a6c5f9ea2b49d375147b224dc1e489a45fd7731230038cb", + "0x827d46b120f6b1501977fd5ad96fd96090fda549d59922d8607c90ada10ec8c0", + "0x8e15c4714f44297868b988e72b2326eec72e148a849cd39c0447862a9f34fc9a", + "0x311aaecf73140d37dc35479828c96923690265c3591fca9b01b8cad0aa411f23", + "0x47de3df6c970ea79568dc7b2c65cdf8bb630d427d67ec9552cdc928b749a113e", + "0x72e70bd58cd9fe64b27016ea29637bc6d5f13507a803431a14465cdf371dd9f4", + "0x46367ab41a9815df566c20f6f0223ddfec61f02e087e5498402688770739f94e", + "0xf3238ded6fc3b6f389a84766a8ee6663f26a54c077b49ceab1661bd08b4a37af", + "0x0770db8ba56663e8590afb552b42e4db3748e44ff33cf19c483c2bd5cab61742", + "0xe88be10da232234c33a267b9b534417385bd21f9d670fdc0b3e73ad155871ec4", + "0x725cd4f97cd34753d7c39a5a072d2de361f41a4489720a99974df1b821e576ac", + "0x10778832a2f1bfb25ce014c78a2aadddfa245e5e539719fad270cbbed5958e55", + "0x4467fe919d607e0dfd78119a648aae22fc56e508eb68052ad1c9bae0d7c5a2e0", + "0xedcb7a0986dd70d8fed81c4a50c864bc3086a3b34ddaf437be7f445f454d7c88", + "0xb278f42c1518ba3b6d6aec679936d2130915f02f8002f8563b855d7cb3b79ff6", + "0xaa4b012061ef7e6073c95147a118266c6d3417ccd0133eb57d7fdb7b1ba3a5c4", + "0xaa263496af99304030953d11d771ae5e337bcc24050e9c944c9e89650f6ae256", + "0x3f99f4bb34f441ea82655d5ac40ae0a307c6ea000ae1a2eeb2709ffc0c624362", + "0xeedc934109c18a446c42cf36bb5d0b9755b439eb62c18c7d334c13c38d379707", + "0x663b6e16d36687a79cb14792580fd32a7c35bd15df6e6fd36bb498ca12b98b93", + "0xa4c2d103e57cc53f50c63066fb7802b6d77c474ef603e6e6b8ecd759c8161737", + "0x3d381365e830f7fcefa8a466f348f5be81a3dd5c72d918501881244417c67594", + "0xe3ee1ee45c13527eada86f390f69d112b97bb0bd20b40e609ac6be9dee116de4", + "0x9479836ff23cafc57b92900c5349180e90afc75571ec738021dff05f9e2681e3", + "0x7ec50e215e840a94aea029294fd6a48d27905886e53a1239699558631661dfd2", + "0x8c58dc1ee71c06c9a94d5fd15aa8fa4f7d90c8bc8d0eaab7d8d0bb2baa9ae4e5", + "0x017a3cf0c797ceedf53dec3cd522ffd6ad4f10ebf709b20dfe669ba1fe0a3287", + "0xe733cb71d8dca2d6e3c71d9cfdf792c8a6fd242af91fb17bf599eea1b6b75cfd", + "0x6e820e5269a6b6fb9e9c2f477cf796078a3c2edfb7ac8b99150d6660ffd22f0f", + "0xbf1d3b3dae3b10422e2c354533f8bd504b1f5852c942618a0f6b415c3b162175", + "0x12fc9bd3a29e5ceae601c6a4e7c92bfe6b22684cc1f828dbd2127ea56e1aa300", + "0xc19e28d20c121a0345d89b097acbb6c15d97253895d06b8dec219f11f84159a5", + "0x73f03ac8b09a769db2a30f44b77d4d5dd6d61fa97afebe6795acc9c5c10cd7a5", + "0xa92cac86cf8bfc4fda37a94e5f55763840084dabe413f2432c4b50ddcd3523b7", + "0xf7eb6d87cdbb534507ca9ce4cc42a03eb843d608d6e2bb42c79bde78d0dd05b9", + "0x3bffe93f111e1883a29b897fc4b33c50f32db2470d819316577bc38e1a5ed179", + "0xe44f4633ce949bd8312b23178b6ff0e3d72b30dabc546ed5b5f2dd97b490be38", + "0x5e6dd4f45c09aebeff5c87b5e8c3b7b77ce4991f230dc7f0dc62f460e684f371", + "0xf1e0440dc83803d73ae9a3bb6454a824194bf9ce4670adc598ee97d1e150dbe8", + "0xef43649067273a56948dcae0271f9a336067610769b2ca4553eb7bd891ff6731", + "0xd9bf0ef6e8c057bea8046402e5bdf0977eb34bfbfc9f14a37576a8ba09232dae", + "0x38196dcd11fd1c406b5201be0286eed3a94a263a1990b66272c9b8764a5f2f43", + "0xa7e55d25456b2cb9541239879d751e489adfc4c0e232445a9232f4462aa17294", + "0x379ea9b1194e78792ddb00740e0c87585ab9a1060e6a2239fa6c5a9130a2a490", + "0xea0d1449333060d955f4dbbd0c0e70593489585465b37202cb4936164296addd", + "0xac2adc5be7eae9e0a63b5758c964ed5b203f37309d92ffb1d22aaae041fd9f0b", + "0x37be79f2f0ebbd92f82502d12dfe42f98f2e75517f444a295426b6829a6b0739", + "0x51a86fba7b41a59b84cc56d264f5d6d83a40f233f7d316c143c29bf424fbf6d3", + "0x248215d9d66288e4c2ee0c182abece81ffdeabea2b16eb986c14d10d69ae4efe", + "0xd8affec4833fd827b2ec6d4c1905e8cc3266e8a825a7502b59585fe7d5ee653c", + "0x00cdc19f0fa69766a3aeae1dd17cd9f61afe15ef6128a957f72fb3cec4cdc02d", + "0x8c8b43d75591539f17fd442b604a58763abbf17a408958ca181c3593dcf0afe6", + "0x055f6cd0e80234feb885657182cd2fc44fea12c6041d20cad8d257f2b4f16319", + "0x487a48fce29c08736e352e4217ba5714f361f02fb8500ce6a2e9ece79b1ac783", + "0x807974b9c1da9879f8967e7dfe02e8e3fa23d08526963c8b22688ef10de36374", + "0x080fcd507842ea3176b14ca52d844df2f9796b4f1281f7d03180c0461d28b801", + "0x95e5e32410daebb3a023678845b2e1fb9097161681c150450c7b76fb8c5c1311", + "0x420611006cd3a391071c6fa22e82d836b5db225fc266b99e126934d5fdf4ac84", + "0x4bcb71688e5ac4271354485f2a28a3c63d67e028183db2a16b15dd718bb89762", + "0xd428d57137d70ec31c6299ed366f69057d9bf93ad06e62332db04db5c3cb425a", + "0xa384c72f5ac5864dca1aef91fb19d3233e4ae3333d68bb320a583f532cd7766e", + "0x9df6e7ec6a1f455ade59bf1cebf6ae1ffb94d1b05249c35964aece90f2ec9f80", + "0xe53ec67b4d7c04b2c7cc7abd797d6a7c8b759b24c8389d103222f3fc83ade921", + "0xf6031d3cc54fe050642891cb57466ad51e0e8f24a8ac52d592e531b0fb87c971", + "0x842c6b20d8a93c3b23e679094fa903feee295c933c9092ca444bb12f966dd650", + "0x38b30dce467bc4347f65f7c7cc4c8a17f58d58b1779e302954fea9e061bb16d4", + "0xe23303957fac2f117e5749e48e11842d6f5a03e97acefb4667630d281351da5a", + "0x47a9c1072f12cf0f42d209cdd33ec885e6e21d13587cd8f75eeb1f879ab55f05", + "0xaed88507af6c779fdce8b5afe124a51528828e734744d8c12cc289c21d7eaa47", + "0x1b6146a607cdc5dac7cc1a88f260ccc2f5883c8a95665b2c9761d9a119b09009", + "0x6ed83952b5bc9b18ea070cddbcca46e42d1f4419c17a51a2dbbe47a0fe7df731", + "0x7544a913c1e6bebe68a6c04dc903860e5e6fb66d4845dd0d98b3ff4e5c33e3ea", + "0xfb6eea6e7399be0c2673dda0ab64a6802d6b2eef1550341d894f1f4146ce9270", + "0xddb39bcae9dc685e7bee0757743f2dd67b56d26247931f4f184f9e8f0f603f28", + "0x363c1bca93f3ff58a48f7d233bf4617769da4774faef4154abc84a99f39c05d0", + "0xd3a56170fd60ab7c75b33943a5f56ec935471b45e9b31825da160498eeee4c69", + "0x347834e86b3ae5fba9a7873e36bd780317cbf7649c8c01875dce04db8e97f450", + "0xe2295dc1850609e564a072b4592b62ec6a0781477d929c9293e65ec494ff027c", + "0x4ecca654f4c6f701c975301f051efc05e9adf0e908fba6dbeec42dc99ea0c2f1", + "0x6b2662a790d931d1f22062a5dd2518b30d980c84d3bf5b69ff0182aaabb124cf", + "0xcf838b75182078fdd33855bec6cd789f0d4975edc3387aa04246cc73f423da0d", + "0x791a7252fa21bf3183b621d65d6a7b584ce1de93a05da8e44a52572fb72a4b4f", + "0x82cbedcb5b48e87ed79935f8a2f93fa5367c32fb14de3ffd2e8947fc8a61fd76", + "0x84a1a28a08d0b6cf71128636355ea3a045d564cacdf67fc29868deb32ba0df3b", + "0xf97f154b9d62135748f94d714ed0b87012584d784df893ad581c36b5b04ef2f5", + "0xc03cec8562c67e6bbf59f97590560141778f5a265b314a6213c440f5703db388", + "0x50735a0e040ca5596ded470e5068b9b7d93676d8f3d181edfc26b5a52981cf0f", + "0xbbb1b6b1366bef92cc978ce644cfcb951ed00d7969e7d89b77bf2de745210797", + "0x116d30e2696ee09337bf9e1a78ab4d8e2cee7c53505afe2b8f027cdeb34640cd", + "0x294855f629441397876e7a0649a1e5ec1cc3ae8f425c24be34ca45e005bcc3ae", + "0xe54763eb5c965fc0c6ff3e975802f9a5049fc3404fe790c31df8a3dd5b366a24", + "0x0413d30f913089871fa15d643ec78f2503d13d025d2b73a6b1a879a910da2ec1", + "0xa430e9153e8e0d9fbb50f0764a0b70e5add25fbd6d5d29bafa77ee93c483e4fd", + "0xa4c61e3928031abbc4b02a892f19706a313bbdfd5bb413eaf852ce84005f186c", + "0x4e242ca7106cf988584cc61bba6e2185f6b6c377a2c4db291e6a801a5b66e1d3", + "0x23b37072cd63dfe8ae9b84b9bb74130a90bd603a5b992ce78b6e2c068ef35b43", + "0xef7e50ea520ca6a595541606ad895beb80bd06cb68984572396e1ea0ceb2428e", + "0x29e48294e6dfc86bea2bf76ee9daa816a59840ad1c0878d77cca43a67a217891", + "0x419809205842b124efb16d84b5defd6985b3c774fb6bd443f1ef72a2801fffa9", + "0xb25461244545d4b6f9c1c846dd09dbf25459d6492b1209814f22a3323ba74832", + "0xee26501773c29c20a4e860047ce14e4af4f6234736e1156002ddfceadde41c79", + "0x3705a24875542eb6b893c0b48266b141af1b5eac2826e88ca4645cff47a75400", + "0xeeb8999c6eff73cee7ae33ddc065e3b3857f213e80a94d832693356f0bddf504", + "0xcddca06cab74354633b9fa50fcd22c838a9d69a129fbb3c17dd0008df9b23524", + "0xfdb23fdaaf80f26f0e95aee174446f7e7182283d652a332ec075d86f6f3f8730", + "0xb3cf34c2dde0952c0d46633ec3e4fca78a3ee8242f2b46b4fc4444afac7d611e", + "0x2d9485c467207fc78b2de05decaffb155b01446050b7a6679923181dc05a646f", + "0x508eb22f40e6e60ecefdde86c50c81f9e73253ca0658a63ffee65f6fa39d898f", + "0x4af2ccccefa90b3028576e09f522bb667a428560f8c94cb159477313b551e384", + "0xd85f3073e44e61bc52696ff86194679a1ebc3e7dce62805c8b03372e03dbafa8", + "0x86ed94dbc666a541088ec977764bc543ae892d73feb39b0b09dd47664768a53d", + "0x36934b9186a56e71ed0c0f51331a99b3f16f07d5b50a1b770fd0ad91562bd0c1", + "0xebe80ebae860665714be6e5b9e8e7cd5608c8b4466453a15ca2fdf5d21b193eb", + "0xcbdccd3919f1b52732a89ff592a6f1dc34da53f5dc409cfec7fc01ef1f61cfd8", + "0xac2a1fc08c3d4b20db35ed4f879921df5e61a6596e655dfb2c6d5ec916ad6bde", + "0x4e072a9ed4432b5f205808f79515fa1d023cf0e6c2137a2a8876b5aaebee28b5", + "0x096aaf5a90b5e6ed00510bb1af1c475c32fd3de2c800b281d2558c20c0288e08", + "0x0f60a5da86c795d88bc025909c8f4c9484ea6489e900c4070d851e91f27afbe5", + "0xc6532945ae1b3fe27002f5d035eff11c62f6b1e9866f23c52af52cdfc8c19c2e", + "0x7404e33f0864651428778f7a39fdaf11a236c8a68a30674d619546518c380928", + "0xc44a5ea175a1d64b02326e7e49782968d9f808a7854c1e338314766bd96b95d0", + "0x435c5d7e5f41b84a55a11606992a4d8ec543cb5062b46f897954035755f9c9ba", + "0x854e9945fb93e485d4da05069f354093750e8eae98a4ef140a4018f3baacd246", + "0xd9e43cac6d5ec4f110baa3c940c5cf35125ab44a102a621e78d824f1abfacde3", + "0x99e780c379a3a94186a99ce600fe88963e58d61d851c6437f7a5ec3c2a4cf6fa", + "0x32786b25ba696ca57c302d136bb7453a5dfc065fcd17e8c38a47a3806e8d4990", + "0xe4d0e757ec64fc8f485839bd34c5caa72ad0f33405fdea6fe437280b427ee6b1", + "0x65e36e757ffb5386f130d783da437e3c7eba37e80ecb8e3017fa6753cef1753b", + "0x3b5be8acf141f95673e207a7c4df7c81fe88767ade0f785f5165c7f03e284008", + "0x988ccc28f0fe0f667ccab304d7cd0d56354419ef8b7149099d1515aa384a0ab2", + "0xeb198fa97ce093081073e2f6d531df421a9692d086387221f215677e9626c6f0", + "0xd6b98b2c6ffbf467dfd0a6365ccc478aefdd8872cfff6f8176023be4ac1d00bc", + "0xa14078605f856243d5195898a5f1e91878bd5ce04458d2a64b0a6ea7f608a18f", + "0x9ccc3a6730ffaa7488c75a31772c956f911eb7002fc245d803e2ca8d45810a13", + "0xc220e09c2646b44edbc09b43748855653861e2211eadc84e7a9cf9b233c85483", + "0x64ffdfad8e5becd8a87aa11a5feec484fa9bf13ea9e73beb7d92e396589a4f93", + "0x791b62a9fec44f975f11e5e5ee56ca70202d0de728eb6a7acd7c40cdeabf0088", + "0xe0359eae31308bf682f09147977b20f40425ae465fddea0515c89a75cd569305", + "0x16199dc2b3e744a4928b767467d02053576f98a5963a9c123dc760c0e4944987", + "0xbb0a149368f44e9b033245d758f1d906d061bd7b226adc1ddffb9f6118e85339", + "0xc600086572f4ecef9f3388a1fc242b099807e61463a934a42dd6bb683193b8d5", + "0x5adca1ea45a4113c166eb85779efc6836c072293e47d2c746b73b2956237b05f", + "0x0bc8f8aa233108727de0e439264f9220a6d5f085112521868c10934dd4100f7c", + "0xeb9edb2bfc6d973c762e283348290da7f3ea45ac449a521e0b3bc41e818aa702", + "0x4684a177b066091979171a6d0ad0a3eab2e7fb19c1bd173786d2db8b1795e49b", + "0xc877565ea3cee7cc08aef811c986cb58d31358c5bc1595bf8f41da9d2b6833df", + "0xe56178ad5772adca0b3f5eebdaa03af33df4451e2797892d12ccc98caee4f401", + "0x3f02d423f1769519c746b6ff632ecc88f6c6161300579c05b704353a13225814", + "0xc2cb58c5152a16f20d9489af5c259483e46ea76f76778947dadf653fb17703cd", + "0x9598d6265c31d75e15323b7125eedb124361b08f1e695e573b4743a3b54bf137", + "0xd401867574d59042a58837137cae986c1ccf45051165816a28f77274d78e6e1c", + "0xd5bd34c381e34dc538839a4a20a5de9e5c87d944f05f889a6c0bf0abf39b583d", + "0x5802fa750e2a8b4ace972d927c4fee3db2c1c3e12f52a20bcc17a04d1f15b01b", + "0x9b13a2989252a0e796ee57e61889ca55bfcfa49d9285ec859e20ddbc8ae59f57", + "0x134da834b7cc2f81f2582366d270d566dd95fa1ad867c795fedc1d74f1dd78c0", + "0x3cc3ddced0ac6b0833ff5bc9763e5323c375a6c32d588b53b98c7e30b2660c05", + "0x8f79d40ed56567479f2510c4e1e81edaee9eb15c3fab934bbfb6c19583032f45", + "0x423e59300c8a57adb8a20cf17b6686238d3d24ed6b0887573539772d209c03f8", + "0xfb633f9f16d9d9f3889495193d5d5250c533b2d2feacfa8b77a598bd1573e59c", + "0x1a2c990aac12d4e85479edd998b7cd84419e64e1d64b71b6e5de354ac220aa5e", + "0x7d37124ba47aed15bd9f12aba6eb1e4ba760965cdb0b0b8049a2dd1a4590bd0d", + "0x5305defebd2a61fee315fbd92c33a971f901310a837b78a89132a3e6757d9ad5", + "0x90c9890e4e15d5285b15596d61471c5e699222bcab2c40d613a20b1e4d0a448a", + "0xa9f12a1a2b93a8f62ce5c31eafeaabd0f3053ca10382048f5493e2f4a3def390", + "0xd32998eb20d224ebfa0f2c87c23cf9cf707dea92f12dbb5c1cce2ee1ef010573", + "0x58259819f210344220294ce925298a770d4b945f69bf6e310d74428943d513a7", + "0x7a7e8cf127d88a93a5ab3e59f9fec2e0a35d9ddbf90396830c37c0a29352099a", + "0x27a39ae87afd6ea727aa75062cf53d35aa420787f0679a9817b15b77c2fd4243", + "0xea8404bc312c47dc19ecfd815780e1fddabed7e1c2268194de2755767f8c6c2b", + "0x2726489dedccf450d85a877501537c51b0037fd7fa3f46150bd5004160c56d24", + "0x1a6752f65e4199b1d7bfa5385a4de60ac0786a0c2276fcd98ec12480ce9ab3f6", + "0x2d6c57ca96d71f4d23b37bfcd63f70c8877afdcd20b9061372c5a9f4f5ec883b", + "0xd7d2d6c6b39a8bd276806810d77303e1fffbc2065f971462d3549b0841bc5159", + "0x72389b3e6dbb07c0cd4ec60f80d67ea24c5997e36457896c7047dba6bd388c0c", + "0xa683c35204e5d8378c5994a2b2cb66ef7cea7f72ce4a014f9de96e270d141f93", + "0xe73c7804f0a92e71739f049cc6d1f4296d6763694ce0f02222cce3a802b95e0c", + "0xe1d2a0db423aae642cf9e0d0a3a0e033ec287d72ad5d6775fb2ca0b754b5ccd1", + "0x2836a91b6f0a5da378fdcb358773b86fe4e2a497b5a8b0c6ea770f8168950cf5", + "0x207c070a56e477b151ac222d7d5582e4233a84f1760561b2c5ec26b6913b5be1", + "0xc6b82e66925ef9ac29b147459a0c7cf6810167b81d5a0d8119409bfde901e5fa", + "0x54f789a01b71afa8ea9a693866109c0fdbed99cbe60e976593a45ecaa2c51d86", + "0x67428f7da1b0ec6712491af063524e25bf846d1bcf1341fb5cd16de664e55253", + "0x9cb30239c73ca41a78aa23de7a5259e5c5320cb742d86e248e800cd4b7842f47", + "0x4ec478de462ba0bb5ee4f2bfcaafb9ee3fd65e2bcc18b39624db625d72ebbdb9", + "0xe9ba31abc5a0305325522cedfd3106cd0994a1be4462264ae630190ea3fd24e9", + "0xa293c713fa4280c0bc8febf0625bb7abe075f875e923cdeea554a48511eb1e57", + "0xa75d09ee8fa14ef49c5dbe05589f169ef70ee94963b7099fe61e4cc8b4c013ab", + "0xf0942330d11fdae546533e347054610329e3ea14b4f219d510f7e6535c9a3ee7", + "0x026d67e672413886db8a70f720b14cfdfb41adb82b7f439d5ba21b589b54e122", + "0xd49061710cb1c459d4a3386b2885cf835e9817d10381382ef8b4212c6d56d4a0", + "0xda04b4d64907968d284ca3072752af0cfc15ef3e5b866a22477bda9b1ad4bcf9", + "0xc3132e5a5899adf1daf3af4215cae7871cace74e8d876f450ebf0fdebe5372da", + "0x5305450d6a19385eec8c77fbf5be40e36551d7febcf1f7ebe6cabf3190e8fd76", + "0xbd7583e3d3d1af3619f54ae1824316f6d23a780647fb2b357db18076e602ae1b", + "0xcd515185622f58e69ad4f90618097d4c81177daad8719f046d3c14d6ce8375c3", + "0x5d518bf18a83f88660fdba41c8996b1e73dedd6cf5f0debd51703edb9e79296e", + "0xae7b3276b47d580f0275b8aeea0ed17f341a455275b5d8c321525a1258629dd5", + "0xf04a5b0379da532ef5a47e391f9db4a0224bd5de6661840ed9fea3b498bb3f69", + "0x617a8557906db76f6fbe284ef9df52298ecf840346589fc51f624b9686d5e218", + "0xc194d85f5a618d76aab6e49f5de491da2f602429dd772f364fe7fdfd3c6f0daf", + "0x6b138060c922aceeb0254e17c3a3548dd3e6904c61a67e058f961e080b3d9ad5", + "0x4de0534ace9c02822d3cf3d81d6dfbfcbd0964114503b56fba7db23b5f2befe9", + "0x06633e9de11b22610b6ef1fc1e8b952252099961f34d71789d8aee0e2f5785b6", + "0x8bfc843363eeb99dae04524455ae4df46ed6e6664edbb640c835305005dad194", + "0xf2f6f86a2e67a269cfdb62df43b9740b42a6eae3f52639acc93e9a8035194628", + "0x1584d00e4fa8d3f0e989f87002f9ff1851351044f99e6194fca52262da38f447", + "0xdc0801def9cf3897fd30f8200f0b6dc4966209e8879f26a7993154b135b4513d", + "0xb1b0fc31bfedf7bfbe445412e84ebdd76c3a09821a4436e72b95ffde019b955d", + "0x3c4e13e63d1bd76e1db089bec2acdc6fe39bbc6588bf4f4af117682aa8a7235f", + "0x2a6bb94e42fc21a26dff4db8004e9043a7a98d6d9583016cecad2baf37b4e882", + "0x7a0981e129e50d8abf6b5a8e0375b8631ca58ef7f9d39a455a4a4913b8951494", + "0x026e94b9b4b3fd407c2c39f8de81e0d0ecbdc0fc82c9ee8675e1a211ab24dc2f", + "0x60b20d6f87e1f3005df1b1bd5fb68ffe20f1fa54f21843ba5510c8169b917d72", + "0x8fa31f4aa8e666c9bd9d42395e08260525bf5ad2ff5719071ca84bdf6b671740", + "0x3e1e9d1a96c083b9e8c07e1ce163a13e5917db9731b6e29f51e2571fb4a8aadd", + "0x36645bfddd95120b6fbcdc9ad54ef1b1ffc8d0a3ab45851b692351ce2327d22d", + "0xc4589b30dc638fd5699e5e26300aac149843985846cec28590df72ab210c7145", + "0x6a050a8820f15c057644330083fa0b93deaf677a5569caeda70bc641051f9a38", + "0x9e2adb3df7bbb722d9ae61237166ba29ec84075f1e1c0b69077119222326803f", + "0x2e41470d47f517c606fe7cd40eb625fa20e07688e40cb1f9caddd80f27877547", + "0x248391e2db6d16b0d1fff77cfaafa82dd191e83ec7991c9a594a78b15b30183c", + "0x484e31e2b718d4803e71ce2223d1d24f1ea1e882ef0a01cc7704d6b306912e3b", + "0x0a14dc947165f37c01a8e225df6c0449347d987533f3aadcb25abe8066a31f5c", + "0x822ea0893ce74adf36d3138df4a6916e27d622abc1cb055ea8c82ddeb6f1b6c3", + "0x72ef874be609700ae58ae6706b6f4d6aadd5bd3fbfa5e017ac88125250ced8f0", + "0xf7e54a1ed7a15b3c5d99f09c5748d9e0944d93e88c7dbff78d33a9f0174f7856", + "0x5ae68f0dc97744f54a5e4aa402beaa4af17f8dedc81e5e98da566d802f6251df", + "0xa378c978831cf0853bdcd75e74218d0401eba6e8879a280d0f6552b7d4681c21", + "0x5229296eb8b7f594144a34635c87f1bf97f070249800af63827b8c3efc0d8426", + "0x3cecae54847f7732bd075cc4546c97d38963f633aeab68cac58a7d5a3177e6eb", + "0x7c14a4b4bd76b14f95a3cc9c046d609902090d7f15c694be9651ad437ac52683", + "0xb3f4b86defe35acb24a651602124c0595702de42fb3eed8d1366196e6c16402d", + "0xe50e7c9bf26de635ae23f434127b15f7640694988221b210969978a3fe8601e1", + "0xdd2fb9e00863ee8bd9e7f9b1f797aaa2127e66aa8d4cf6feeb7936fa3d46acbb", + "0xc543bb209f2682fbdefa8dacf51720954f37734dc3b1a34af1adfb6f0476bec1", + "0xd377c42d4e61fecde1ef150b4f2fd6fdbab18fc3c13bd6d3cda845e69516d3cb", + "0x622b34f8f3a6e6cdc035ae3359530551437c1e04aaa48c85d3da759b3afc7325", + "0x3e56eb277800889b4ca4a12a20eb33e17c78736636ed761882682ec91468de47", + "0x9c704ca0434b69c8c5731c139bb15f7fad0ac71b8c6863d5f85181e98d08a224", + "0x68499ddc9a08d967055b2e2faa974c93ec7da5d362912f7a164e8a022787f8bc", + "0xd2bb02824aba917a5ba22255e64f8576c72befd94daa60b7aad3065babbcebc8", + "0x8f6cb9bc8007964e4beca887943dc2ce64bd4bec91afb62d9d4449c5705c7086", + "0xd553a7e7d878b1747b87e6306b3a822167a945bc63ce650c57e194d8cd41beb2", + "0xc62ac1e135b490551bc99c70ca634bc3e47502b4be25d7a0e406cb26ba03ca18", + "0x4327232514afa77b8fe208a7a2094051b78b8c16b8eaf9da6dc30403c4c9896d", + "0x6b888ffa7a69d53fa6f70a9b083f7b49de19f680e29f838309aeec7f1821b00e", + "0xd3019c640f0413a1b787e99cbdf7f9d45f9a2c0afcce3288402cc797ce4f06f3", + "0x1baa3e5575457458859b2f2fc0f2bb09ae3f593787c62f1479e84842f69de91e", + "0xad1b8e08cf8cbf3d717e6766123974cf2450dcc0bf746133d71c2f15077eb8d1", + "0x817174986957d2d04f538fe5ca307d1f524a69c80cf97831002d1ddfe56bcb5f", + "0xaa2892eb967f4e588dfc6b6634e5b2aa88263f4b1e1e85998bea7f54f5015664", + "0x7bcaef11f9680e02b0008fc057819f06a1d117e318a43aee196dcdbc6b991dce", + "0xe56ad921fe297cdf000f04756cefabd75d309add549622cf3a7604d0d02d4d1f", + "0x988d447115c47d44f9d7abfdb380fe8927bce830a37b9be320d5154db934df2b", + "0x431001a2fc696bdc0e682f591434dde3344d994232191931c0a6e5d2e5498e90", + "0x6ed8c0e4597fca7c1c74ac524dedfb830714330b020dc1d1b2aea51bc311c4e4", + "0x8fb32fdb2670a4796df796379fb142e6ed6fa2e5f1fd51fb582a60befaf7df55", + "0xfcb88679cc8b85dbdb25dfc1b9f0a4602aa0d787e9e70ebd0a5728ff2e3b9572", + "0x00d82f45bf1088446a2706e923d8f43c800071c8f988239cfce7ad6a8c31b6dd", + "0xdf684190b2ce730df2b1cd78563dde0cab5539b30d0a06247d79f3aec73d617e", + "0xb0f93511970266249814b3073424d5ecf9b47edf7133009deacd317435940676", + "0x073ec7ff65ee722dcc829b69e80791a856a2200560f992316be6bdf497b5eac4", + "0x2d2a90d480df14e521db3dd380b470c29232e44e12838b54b51216a95659733c", + "0xd72e78f576726e546906e0e936baa1fc6625777edebf69da76c489b9ac057029", + "0x03ff5273dc2b190a1f52fa97e28945dda7b88c6d866551c9928a73d6ffb3f133", + "0xe23267e18401d49d5c2d130d91757d17d7dc074d055665fb33d4778559504f17", + "0x89fd9be047d599e128f9ab20b96fc506ddb8c30dd5a9b6782b05f18165f939a4", + "0x732b8ef837394ff6a580c3c21e72a72a2976fa7ee07a7152e0ba5101d5891f7c", + "0xe9999336ab64957ddaea70edad6e72a29b37bec1498deabc5d8341a93ee67197", + "0x49f60577477613545b37efb5317d9142d9f5d6d081908e1c061f6be452216b73", + "0x6fff08789f48c852189fcfb0327acce4e20281ae54c3b821790b2856c7ec1ff3", + "0x447f89ebe76365d8e308034e90241562bde8834dc1075eac89e28183b2a4769b", + "0x469eb409c46e96cd0e75878cde67974e319f00b0d336bdfedc098021ddc4f407", + "0xdd8365129aa6aa4ce914b5f1a917a573b7ee3a3ced4de5318859e8ea2d512de4", + "0x1ccda602493afe6ec11be1d523d3d76c7e79bb93aaa8dcb298e8bf3b9d5a13bd", + "0xfa3a4de9d5c620eb4d160ca7b49e86d99d109bf7866f2baa3d9c99346174dad9", + "0x7b9fb6a8d32f956fe50bec11e142cbfc320221a89e25ea1f579d76b4b2c9bf1a", + "0x01bacc1068711052a28f3e4f7e9fd80b996fe89a0a2bac647ecdc9d9b83e8b1e", + "0xd24d7c8b06dbf1db024c250d7ac4c8d2bfc8be39a0e8990de46b0ddd79aa4cec", + "0x422fd18a2b8735f348c092ca2bda2b69c676613b595f3906944f869e28070d23", + "0x938a51069120a3b4f3081fe083d9246d32b811d9f2e37a0fe6e1cef0e7ff4792", + "0xa9116e660bfc36372df2d1b87c309781403b48116c95f2f73669048bebddf81b", + "0x858728b26fcc100ae1a2bf373e2cac05537fc347790a9169710974efea7be830", + "0xe17c0bafaf4a96427becb15242bed29534970937cebbf3b6759bf470a9884b4e", + "0xe40f175756e1815e0d514af34a8da49518173c7f0b9fe1ef24b1a46d2aeb1ee9", + "0xc29562af361c92883d4ce12f04170e189eb62f473c2a24ccef7145a26e1de030", + "0xf8d3f3f63b252b8bd0a7ec90d5694c36cc1472c261bd45382bb485d11ede5a56", + "0xfcf7d3ab6cc4ea23882638e9de6531459ee27a3140ab491f756c723a52378ab4", + "0xe74cf40070946b562555a93e868313d46613164c5e23236851c8c35a7258947c", + "0xa79ccf4a86e8a34faa518079edabfc8884c52aa41571c45e05b171acb2c53f15", + "0xbcbc83dab8dbcf748bcad7f14c08340ca4f07318a09c9a32399f47dab5e60a47", + "0x51dd90b2af2f1766134ae9b2a82d885a4a194bce1213369ebf3e315d03ebaa73", + "0xcf18e42db84f9501927d969e9a7e4b42553473c63c3995d8e761b76f79c6d3f4", + "0x95d14b250f97721031748210fb7845f4ec78e05804a87e1ddd1269a220758643", + "0x1c73593545255b2bea59520ee29d30291b4731112d39f507ccb8c98252a8d39e", + "0xf6d582117cabecb8408ae4e9520369d72dbca7eaab8ce6842d2febb5a1b22354", + "0xa2c0b519f6b635f06e64f697948248e57eddcdc5919be502ec1a53e7501297b6", + "0xf2268cc03cba0244623a414fc7550f868157deef46a8c424bc1e6f4b70595975", + "0x16f40825d69784d4299039d7b361f075d1336f29b93947e57ae963f119de68aa", + "0x7d63f07c24dc55307dcfc3160433e7d382272ea411b931221ae30dcebc3068c2", + "0xe469c2b1e0a2370b5a9fd6db791e0ffc5bed870df922684706fc6dd425176c02", + "0x13c52a53e3d7d5524f163d70de3be5dc4a5c8bc95c64041aa21fbd14fc0bddb4", + "0x094a9ed475b0cf2c3d845cfbed5104adbb97b8e233c860470bd9c2f967fafc81", + "0x15f1e7ff285656c4b445af048f4c95224345c4879ebe4c753f3f7b3ba4e625c1", + "0x58128af04dd68678ec8a9cdc54183f495fea8353a89fb304ecb674d1312dbc2e", + "0x32081afac331a70b6174ec52c776de2ec27369136dee0a25b58985a4607a7935", + "0x7f48dc400b525c33b2ea17d47260032965a03b6d076ab4d02cebb7b571d82549", + "0x3321b772ad4ffbb3466734db9ab81e4aa749916ce8ae56349698dcc0834dfa1b", + "0x79846e34b081b22517d5514f26bd67190812501c430042b28e510d5fea386442", + "0x8fa6d5ca4cd3b175ba6fee940a941bd149b050c46a0661ac52774652fbef045d", + "0x506db869b12f2c0b153f314477ecaffa9b7c53df20d5b2dbcdcd073a3c76141b", + "0xe69339d7a63e25eac8dcdd9a70c621561bf32ccc1f89624e235819d39cfe5ca4", + "0xd506504ddbcfd1f91ec9d5d71fb5eb6c05566da7c4631f58cb99d20e7bc1d846", + "0xf20c78eb7a7560c9933d6a583ea23f403e6cb9176e0fc9807752633fce2bff7b", + "0x16392a1f31ba9f84eab7172705e01567853808f17748c87d3d2b112bd297696c", + "0xf55d43b56a371be8e174d3f617d662e7b45eb1326c8cc878409180cb516abb00", + "0xf9df7d04c863b1aa10e03c68dee16d0e17f7e514de9847a20a63affc6e1211ba", + "0xef814a0a1681df3972a6b20187ffbf58ca58f9fea6df0de32c1036723164d9fb", + "0xf8b49fffd0ffb70ff19c3c3781ab43e121f90c447d73ce242dd0a0e2bce56336", + "0xa6e89a02913d0e909104b67e7422339d3c93a564b97171db0260c3a8540be2ab", + "0x5216d9be46b9697a34181ca7b0d4627ad99311fe84c8fbf1da4e804bdd91d39e", + "0xd30d40124a55222fd69799407da38503c04f742b45f0127fc273be3fd5cb35ee", + "0xcf121f66227509e3829949153738f6cd1eba7210a4f4b960510a86d999cb9118", + "0x2e1f8a60fc9427a0325fd8150a8ea6fdcde91a13b40e999400c586c672798a49", + "0xb014af1c33675b75ff8c965b0f7f8eeb32320e42ba14db790a5c60896d774282", + "0xbc4867d1c344c81c33554abdf3384b544ee616f5909143ddb6b2bf4a0ba3d41d", + "0x0079e37734bb661b5bed93acfaa18179fda2617c4c37bedcee6654f79f0b2d9a", + "0x2d3cc57aff3730fcfb2e5552376cdff7cbd452842e5256dbe115aa3b1ad18dee", + "0x15288da0a82c6d0146bd29b8d31aa31b6f516f9997156ce91fdb367399e5b81d", + "0xb344ac87a84a52e90de58bab979ec4a2e5fd935836405880dd1151e5683085e4", + "0xde8156dd2e7abb20044a23844a06ddc1590c9ac6732923c21269dabc36bb246a", + "0x6580171454e664a67c320e63ffe7b950df9173af211983c730f40888db58643a", + "0x5ad58caa9bb6f379dc30ef06b339d724a91000acc92a15486c86b2271396bb3e", + "0x0479a5fdaf588b170bc2d8c11301a463448249c848a4f2ecd39cdd5f6fd94a09", + "0xed9335181e2fefe38459807029ae5614e98d1ed80fc5bcad68046d63fa7bd965", + "0xacef0d3fad5cc33c98daff6f5580a7e843c5445007b3edd4508372f221992901", + "0xa147d774480b83904768d78b654f01de94c50d54c2112900b23cc18df088c14e", + "0x620ce3590e2996f10089121597a6c05f2f8ccc94dde95fda12a194492f4a96a0", + "0x606815f9dcd9fc31a2485fd5bb82ab9c4e9edf31c7e31770e89365d643f32a71", + "0x0a8b6fc63adbc84796423326834fb9876a91b585300310964119019182d420b1", + "0xded997869b600c4fcc61119595da1b8574027d64f9c678f442e9f7a33ac90fef", + "0x448ee745b1cab75979a3ac3f99e941ec291c921af8f65f10cec4707fab2aa97c", + "0xa3c7a6580857935652f73fdfdffc5a315020a22a778e584e0b78eddd70a6f59c", + "0xd56555316bb971bcd4ed2dc26b53a667e0def14eec160230b3bc18cd03a3c65a", + "0x030f8abafc222277b1c9e39e2b75ca6c09afeda33517d8cb5fbba73af7e1e1de", + "0xce35fea1dbc514f8d540a72295e2457863d7ae2afb76ee3bf1cfae1a8ef91fcd", + "0x8d890590196c7af780fdd854989e2c776d472a6e04c82b4fc3c3bd3e30d01aa1", + "0x7fbdddf9f6d14fbd3e6217b184e9b43450ac3109da621c919a499db6575dd34a", + "0x41e0a2e9ca2781a6722b1ea5b302e1f01d1b34c80c6f494e248c030f375ba1ec", + "0x7991a805d4f1237190f5b28a55fa603dd5c7a7cf3325024bd2eaad981ca0d70b", + "0x27537dd0a5d7084451cedb82bbba192fc59dfb60bee59bfecb5f26c49019396f", + "0xd3e67cc97c90c09f19b528908d9a60fef68fde3335c041434960405210ccf860", + "0x68b51ea61f57127d3a75b46e44c97d588904bfb880f5774e21440b902c1b7831", + "0xce0b41fa28c47f7a420ea5efe6ec77e413f22b6f67e9fd8f6728ddd73e5c6baa", + "0x9e7b2c49c92a224a444f4f91221ac2173993decf40b21118ff5962dea3969fd1", + "0x6a611eaca85f609f1f79bfce34df97fb975f450e87e1f24d9a93b59ee0b0083f", + "0x70ec7e2b800c43d093f7b1dec60e6743244b4516394ff861e8fa9f265efdd28d" + ] + }, "accounts": { "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, "0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 6aad92505d9..065e3364438 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -52,6 +52,1528 @@ "extraData": "0x3535353535353535353535353535353535353535353535353535353535353535", "gasLimit": "0x1000000" }, + "hardcodedSync": { + "header": "f90214a0e11154bd22ac6a45e9569882d75fca57d12e44e5def1050de0a7b99452fb80d9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794006b2b96ab71a8df73dfabc11ae790f9c8c259a1a0d6216dd88ad006659c6214fd81887150e1bd1f87b248316d3a58cbfe40f521eea026802d5f81a58db8519436e768eae8b11f7de071d7f274487e5b5dd9e6954d7fa03ab8cae24350c9290ed5bb29777ae22498e0b8aa87f0ca85f2bfa74fd95c61b3b901000000000000004002000001000010000004000000000000010000001060000000000000040000000000000000004000040202000c0000000000000421002681102000000001000000000000080010000000010400000410900000000000000210000000025040080000000100000220100010000010000000200000100048008000000000000400800420020004000000208010000000002000000000800000000000000000005000800000000100200000100000000000000000000000000220802180020000000100040000010200000200000000000000000904000000420000008000000022000000000000000000001800000000100000000000008000108412d5f8f8832f60018347b78483449c5b845ae0127896d5830109058650617269747986312e32342e31827769a04a1c4062b2593568cf5fe861cd1b9b9024189927a3c75d09471efa029f7483b08863e584beff5c7905", + "totalDifficulty": "8154014315272113", + "CHTs": [ + "0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a", + "0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc", + "0x6fdc50234f74fd6eb5b8bb28378583da28963d26c7226e1254e04b676951c4b4", + "0x0d40b71e8f08c4d93a0f62d93eaee4c6ba92ee1ff6e46dab57dc64c992873245", + "0x7f129d232456d600332b59fb30434e4c71aa95b0e3a4f9328c74ec5b97102ecc", + "0x0aff522a9d28bb1a32af4524d049ce9b3e66149e8d2644efbad5736c9fa044ba", + "0xf9adf08eb7bca9237babc37df559297c6e1b54b585867867a2aed7c10cd191b9", + "0x5b90ca8fa35cad63ad662e3696f41c4159fa871e5f77637e018595a626282150", + "0xf33aa648935eb7dd99906d0855c71893b4c0d0c9b32ab8c8b7ae316e503ba35f", + "0x79946d20c81f7aae18f427d991f21888169c96424813461d04a61758bbe9f214", + "0x80950805fc209691ddaea24e8afecd0096e84e3c465940508131f41f569d559e", + "0xd58de59cb3b7f0323ff3edaf9e3af56843258c457f490346cf25a73a35163ed1", + "0xcf52cf0f195caa769e2d5857231f31bf17efed369c358e7ade257f6278b1df0b", + "0xce570fce622e9f3bd03942c63537417f96250bb3605d2182e5a567e961739e46", + "0xe6add695b25d4b06bfa08a80e9e9295c84948fc34202cf24b42c1cc325075d04", + "0x4699a5f1df0d7b2dab8ba282b6e83af0d0b31b604443e13ccf097fd46f346bcb", + "0x1a16f27083787c5dc1dd8f0be868338c78ce147d0cc043b299870f568de20a3b", + "0x2dc5c4538c1812e892e0a53c112e8e4c3fd9f6f60d1e8531a9df5419df86d013", + "0x40de720fa5ec3b58b3be838f189ae59bc4f21bc8d8f406e569339ff054f93459", + "0xc7274c13bc7462d09cbe60044ea6c9e92622204c41dfddfe864d388f830ab35e", + "0xfb6b099472c5457a813698944d4901b766b4bb8a177c4d357897f1974ba6c431", + "0x9e6104a79f7bbf96d117607ec87be8604417d80af11f558ef1e74067168dff0d", + "0xb8deb38b0b58be7b3eb89a5a3ca1eedc5726ab14186baba17ac520a592f68827", + "0x59a58beef1250fb3315291f0b84480b947672deb331980cda261c94ba544e22f", + "0x0fa4b28513f4a3639b427b5abb87902273fdc4077cc0a51361c3dddc264871f5", + "0xf9e1e92a1de2346fbd8b54987960f08a8b21cb0a8a6c561edcccd6cdfacb46b0", + "0x89f4a9590d0865e126622cc47ce2a1ba50aad880161335e8c88c8a24af709fd9", + "0x5f014ca414e0663c92fcbda0c7250153445a04808c7d062859d000c970003834", + "0xbdfc2347806fb9641788978b5d0a6bccc81b11203cd751dfae45a8dfd3bde7ea", + "0x41420d311b7b527ec68770306d97ce3352d7fee50fdba3b05bb54e70c7250459", + "0x3ad7001f1b2b2635266141327ed45b017f334fc3a5f410e3e99624492c489def", + "0x2beb717939cc0404dc173e50dfbe1477ff32c1ccb59f40d7900c2337021e2d6e", + "0x558b53c5eda0866f7515f113ea3254cb85424b739a5dd6ad48bd4d9221006985", + "0x294c62ce078bf950361111adbca5ebc963d5f12c7014b04e3d86d3cc95c6faba", + "0xec18a7c338bbebfdfbd03f1896d726dbb1d21a29e32e92fd9949478078bb19d9", + "0x6e61bb0641c13be0e0858bc3da3a0b06f6a8ac462301a33fab7425e99d6ae14e", + "0x7a4378c70cb339cb4e3805d013f6ecd66ebcfed3dd1df972c8124bd7b888c8e3", + "0x5911bdce0868655abb581c9ce87a51b85b449101d6d52350c05ff1db30deb900", + "0x081f65d017c48967f02efec9781ac4bc124f42a31ad20104cf4ac6553fe788e4", + "0x89a055c33ecf13f71637fc1dd818c6c26e86f4751c2e09c5b8970195b39ddcfe", + "0x83d33e35f31824d849e27d2cd1d4d02812cb84c8508bbb391ba563264ba2a429", + "0x144d66cd98cbac72f3dd9af9b2656529a00fe7fda8f70e02d0ee025fdf2de9d1", + "0x35d44c6849d379e58398189d06b149eee34a267e94230ae5e24a0c58ba3b7d30", + "0xe4d67e58b9be3711015ac016983bcbfeaf2ec71ee85bc08fc2e53e6d173ff348", + "0x67f7bfc9457f1a1566d9acd3700c399a2fbeb2e1071b3f5c908eb56f2bbb9716", + "0x2546b96a4a88411aa7b3aaffd71a0e22484cf526a099d58f1dd330b3209e4aca", + "0x91f9c4aa8357a4835ae2fc913ff21eb4790b711d2a813e94b38fbf52ced0c4f6", + "0xb4623b136bd01bbf2dfe3ccdcda850cdbc6da79b69324a582d3e1c29703a70ac", + "0x68649bddb9b142d43905ef85df986ccc35c5b0796d860b367c21085c9f1d0220", + "0xa007ebec8e3242c209a178e01eb7aac3666fe09370dc1064bfbc46651c5c4e01", + "0x614125ba7478c7ba2ecd062eb8014ad3b50f4d9a7ba546c932e3f0a3c43c13c9", + "0xfa579127b6d13731bddb5c27cff6bea2d0ec13bb6d17679d4d9e1ffce8d7dc2e", + "0xdb11e78fced06b1bd768da0d345f19c023d5708e7b57bf09c37009887e0bcde8", + "0xda9a47b636cebceb2f378d9149a4a5bdeb6841746e7f677942c26629d3d1d4ba", + "0xeaf7cf3816297b48236ea2cf3f60ece988ca7cc97f5c8efaac1433d23c3a5ae2", + "0x1b7746aeeeb0651a867a3f1d34eb0662660aa667847c04d6761507f043d0eb71", + "0x4e6a1631fc6702fef39cc0e383f4fb5608e8a1f0c721b1622c8f25ea14aa86ce", + "0x9e96f3b348c2170685fbaa99c968fadb4bd9dd621f6e913784851ab1bcad60a2", + "0x65df62cc768c87ec256f7308d9f199040aafc24c03d5c6d527bdaef9da365e4e", + "0xdf067410f903d878471fc3b53d020bce9d0b672ebd51df16ad65f4a3468be124", + "0x358cecbaca6506567a60b08d00c888c7b1dd66ccc292ba7c4c9aa3e37b018391", + "0x5102782ac246337226e6527ce651294bb5c3787cc68219208d6dfe6ce398f0b5", + "0xe6a48cff6189dc26c3d7242eacaf1e34c81503327b18087840a755c322665ca7", + "0xbf599651ec19034ca45bec20673f41813b43387ebbc596a57384a813eb6a21b2", + "0xa5a5242eb4e6fecf1b497a62de8138401cae35cad4a9c136d9efdfc12fd53d60", + "0x05eddef47694a7dfc61e79f78b65bcf9c5e0e65513cfadd2957ac3a324f54b55", + "0xa4b5589bca8121c6bc00a846ec459faa99441d0ffa4b577a45984c32d63128ac", + "0xc8a2f9d7974a1aa77b35188d9dbb3fd56d5a2f6c796d2a665360374886c5a386", + "0xe9d430f782c0275eab831108f934ea3bd589c6c72f9da930e9fd392de833e486", + "0x71e85321e2d1a4b0eb48d8493a97ee3634fe153f30a85d1dd55fb0f5f8c82b91", + "0xfed03a8dffe6cb8043a11ccad791096151f0803b020e4dcf33adc4b180551fa1", + "0xaf1beb7795169537916bf4c9b1515effd365cc0e3988cd3e296fa075831fb63d", + "0x06ffb84050198793b580803a41e78d4a6fbcaaba0901a6f938a5ac5f9982f1e2", + "0xb416bb6b94d5076df719edfd2e2bb9237eb2171b9ebbcdb082e1bb1016244371", + "0x60d6170c0fe77eada1dd85af74079ea0387a167341df0ee8ae110d0047c00fef", + "0x15f03d5f617db0bbf963d2daa06816a768b21794d05873131deb677bc3ff2a07", + "0x0b9fa1e7fb11e3c0b33cc609a87dba8c1acca7476a15da2116518d72ea019e0e", + "0x9bba5ba8b88b76613a52504bdde96ccc1064f3e868881cfb4b155d24d237e093", + "0xa8a77eb3fa43914feb609274d1ed96d51ae29028fa59e7f0d174b085d106fd27", + "0x142d2e126b1faaa6997553835ce1933083a5c2cfc9818ae71d559c8571757fab", + "0xe9241f795bd887173fa93f9e72bd7f07ee58d69dede512fc31f9faf0ddea8e29", + "0x526d5379c00d1a318409ea42ceeb7fa9d33a4bdb71793c940e0d1b42cc848d36", + "0x2045cd5b32670fc4c36fd32e45437db69f468aab51e10e32da423ad28bdf85b1", + "0xf0d0bdc64abd76e66be96239efbd0f25ae30bcad096a4cf28b8b5bd9658c8c3c", + "0xfa5cf979a921b2c5ba8fddc330cf1df7a445936f7bc990553c578dc3ca45de49", + "0xdf2ccce3cf15b30d7bef7ca83b45875e96f02e41c6aee9a1a97025f0dc75585a", + "0xb61fe42d47707d473a2ba8483dbd4b9a40c1e7b79c2bff15ff52aec560d505a6", + "0x068ce2cc3d65a152aa574be6f0617ff7e2f688db97b020d8ba84e81ae9037f57", + "0xef3c631c846ef30f6dfdaa901d8d1424cd100710335805e14226976e719cc2b2", + "0xd582c2e6adb0d112786bdf27dbf1c77fc7bd002511e53d0a10f4dbe780156478", + "0x8a028e29f728e414cf7e3d403bce9de7766feae6090ae0f7f787944569f2b001", + "0xafa8f78b22031dfb0b06004d32b6699421586ae779624fdb7153854d1ea5bd4a", + "0x7ff5e562415a97c4f731c7f8a6b82e401705e34a78751a6e8039b0930eb0dc59", + "0x4cff7c84dfe821e917e48089d3a25a88a84983fa5836d7a78fe050915ea86374", + "0x2ba7416bb329d81424f9fb12b43a285eb3077799e71cd21f0095845d2d165c87", + "0x613ca539b0ec3a5819424d8df2f4ee08e03e5e95a2607503bfaa8574270d163d", + "0x3f6ce1315b8feca300da0bd990b582c647b4440d4a218fb4bb6c841a789da37e", + "0xba8b0c45d55e44cec801c724ad6b6b699fa78505d87a5f356f6ef054628f0e0f", + "0xed1069e471b099408ceb19fdca42cb57bca2389dec54b8fd283db0a53ebe2c30", + "0xcbb375230e9aa4f7aa8536f42f4df3a6bd7572f603c03e716a934b0d3bbe475e", + "0xa8954ae2e84ed2c0f45db6e41731a09ebffec9b064cbd12e020e66b7575d2c9a", + "0x9229f2300310a0675f281f76c695b06214960621aaa4592e3bba558c23b5bad3", + "0xe821e771c08bd42b6d926bc1ecef87dd846110693f59d71cc79a55d7bdec4cf4", + "0xa7e54537a3a01524894a0f602bf010043a52c8c7ac7f6cba10a6ebf86ca11820", + "0x3ef166570a593e608afe6b848ab8543957963e63448b7a1d0febb8127003b527", + "0x1308ea66fbc0fdf84680f227d6425e63dd850286de1783300b64ce77deb696ce", + "0x14676109d2f68c5cee4f58c27f40579cc04663dcd01017963402aa2f06fd315b", + "0xfb9434241629e83ec929e1f3feeb1943945e8ce87590eb69a9ae44e3fdbdcb4e", + "0xb695c39514548fe5240723355a6a2eb2d233a48018485435b2d9a63a1097ef55", + "0x9caf7a3660201b0118736033e479b74e488f64a07a79e33f4782048af424840d", + "0x82f188de672c6e1826d70aa5f7d54f499aac011139ecde9d4d05360cd8b9aed7", + "0xdf7367edfa34b79be80c06aab16a54e7d1f74eb9f813a080a8c4af916e3a61c5", + "0xbd7cf6ed130f745c853777d762706e9050c2a45d01839b124d517e3e73206c6f", + "0x474b7557c158d93d732fa0b8829b40c2d9e593206c3c36d7743b6eadb0067689", + "0x1ff6d56aa85903b2a9710b56ad4760825edc5343cab855bc966cad9bd11aef7b", + "0x52c4c3990413706a86714b1dcac8d9c4e55a36eddd176dc55066cc39e308175c", + "0x7a63b6427abc9780a14a4826c45a313fa2d020ea33ae91d48e4cea28ebda51a5", + "0xfa7ec58ce730e3d66c79b2616e14f11b87077c5d911db6bd89cf7c69f9fb2559", + "0x58f1b88f3ae0b76dbaae0ac58673ab38118f5253b07ee2a309cffa1c3f9f3a30", + "0xca98407f9cbb2911422f5a0716c325e1c2ef053355796e47eb619094790da45f", + "0xad072d0b4fcb8ab2662e3d27f6c6baa2f914bedcb91d178a9ab02b9646e6203a", + "0xd8319f885666fd19a5a9801005530e4a490fe29765f9d60c38b60c5b9ea92d5e", + "0xe95daec9ea36ec00b4f9f7478ae136c1453bbbc3530f839e93483fdef4a61cc9", + "0x6eeb1a044cf3cddaa87f70dbca704fe9cad675e82659380fb733153ad452761d", + "0x89c53801a896ebb9cb6c3a881269a93f610122fe9c3132ec19d64a6f22e9f7bf", + "0x81e57e25ce8817d0cf3ca17d099ec20e75f11d32464c2480d2f63a53a22dbe47", + "0x42ddde6c79ae71e64ab091b24e3db68c0c3b560669aeda58107d07f61d9bd39d", + "0x6936a2002771717810dacc23da43097c7c1bf5c2619975f55132b5f450c03047", + "0x0dbc448620312bdf04e118caad4ce1fc5058d0c14b1bf655b650677a2d1eaaa6", + "0x108dc62f87065752fb77f6a3f00e9141e1fd170b9c0538124739bc75d5632b4b", + "0x9b555f75bbc6b9fa5ab1b63b5e7a4f6efc7e9c659a8829a69ec591b968133478", + "0x3f31b6d6e18c7afa96a95ba0855b52a2b0e3158d338ce3a20f14c14078abbeff", + "0x78940ccb7637be74bf6f1735c615054e632ce53410b77e9b1d9f256699a54861", + "0x71b5505cf3b75c328113ffdc94e8ef89b673838a26bee4bd7ce582049592e54a", + "0x68ecd3b26c50447e6483aa0adfd4187a4f99bd1b8517772a9b90f939b322687e", + "0x6c291cfad552325bb806ce314f066f3a7af0ccb5950fede839023b8140b3d06a", + "0xa32f442c4134ff4559c3411aafc87649ba6776f54e0148469b7538c243c19787", + "0x06ab81f6da34fadcc2d1b52982cfc69e20d9451801da18672dbbabe4abfb6983", + "0x8ad902710d008f2b7bf8dc50b66a11045c7e10f80be12f6c5e622c05ad48f2dc", + "0xb85a2abe729f4f7bfebc6a7eddf085c99992d6af700f487a9a2a64164dd14abe", + "0x11039611b2f406125519fa4d3f1cc7f4a89a284be02f0d23971b2990883b4b1b", + "0x69e21960b1ed6da34778848a92b200c8275ec8ae1763e07b8edab481cbd5c1cb", + "0xab4a7ffbe54a07e8b1af0eccdd1fda88d72a25d61bf6b12c9f5022afae936fc1", + "0x8d8fef9f7b0df3e2cbe6cd99ae3ec231c3bf7a583028c0f6accc38d2ac294019", + "0xf8c75352c289c74a797e8673193c505600611433730e415ed877087cad99d3fd", + "0x28b756fe2c8e5c6cfb5df29e8c4f3a9ae149c9d7408efc31c57e5164e9333da1", + "0x3912bfa54cdcb8e6eb1900d7b8d464fab0aa97593b9795802d8a084d66d82288", + "0x0db191d64e9a75039a2fe0817308692f3a163bcd1cd6b476fb5e04cdc8af7808", + "0x7df00cf34abc055979b1dd70e38b364f0b1f9b6ca8a2cdaa8e72dc1c30bf5471", + "0xc4ebe3625665babdf6b8862da0ab84be8fd7b5c1e4849e9c0c2277df99c1ce4e", + "0xd6b86c60afd43553bced67a5e202b5dfdd62e668359eb25e29c4768328136fb8", + "0x46be2d0335c8157496ce74edc96bba09b3873acbe46c285c54e6985615519fb7", + "0x876940ef8cbf54dfda6ffe0d469ac0fc9adb375fdfeaafe3da8345a9db0c964d", + "0xde7c02533643f05dcefdefa9c7cce1f0583a655fa2a9b4a5040ba6a7489c650e", + "0xdfb9bea572e6a60edf6406a5e87ef3fe60f5e5884ff2fdbd9ab5ccc7f0bc602b", + "0x56b30ee04caa1d1e8367f58855c361b43c2c17361e5b242e3b6dc1e53778df5e", + "0x5da53224eafabe23f1a5637ae74cac54adffca2f18fb4a2f506a617370f06378", + "0xe1f7ba27cc89f68862c9cdefcebd4b63419d01e6cc49122f7e6187912f3298df", + "0x67d0b1d84379e0f67466a6ea295a94cd55ed67392e51a6012994218be921d805", + "0x9db5e16e54e0f9310e578d5dc943a5e45ef5b3f5e66bf758d99eb8a7528d2013", + "0x4e0b154a0b06d6544950634de6bbdf511735226649bd694b4194c43aa7e89bc6", + "0x8146ae0e77da83a036ed8b78046f204defbc771ae61bff4016cda3ccb6597cc2", + "0x00cd2da8855d464a368ccbd92907baef0fd0fe2aa8c24e48e4bb6854a011d746", + "0x261fe32ea2985be3ac260b68aea223c4b8e4db240e5fb182490407a062acea5d", + "0x65eee7ac2b1b90a0f5a4e0950b2a0f3a9b32e0928aad7f4243d4bea2f056641a", + "0x7d9e7db3a97919ff2204736eb3920587d8fdbdc97d91f14049f1d41a1eeb78d7", + "0x9c2edb4a5bb85fe484094b0e033cd7d31408a2e2d4b801a001f6f886b92e73ef", + "0x1e191b4674a3a80e09b68efe4c4dd4f38d344ac0b42a1fa152aa1242a5b53e1d", + "0xf498295a3d4e3b72ae1a11fc1d1f031cdcb68aed705be3fd698b5b92bcdc8cf3", + "0xcc89f9c163149bc17d5b0a1d79bf5538a86c4aaa3374e202a7b41cd4a562c6e1", + "0x11b5219b9b2daa6832f206bba106c64a2b9c3aba39f7dbad1feaefd788c9ee42", + "0xd936254f54f45c34c79c8a1ded63133c9437e82c99a26a8bf3efb95ad9b5cf54", + "0x8e8b502743a0ea7075c89a88bd149b8f97846dd915918ab8cb21c7b7b710a4da", + "0xdf0e67381564465619d90165d5677c19a396674d832530c18cef2a348f9671bf", + "0x6481f7abc12e1a5655b0c88a693ecbbe5ab2685c776eb5a9a3485167eeaf95c2", + "0xe9ebad32fa87a2a77c82a6d276a18b0efd6f615361f0d6e72c0a037b35bb396a", + "0x3e052b0aed9cee87f4d70626837c1a49ec169b2e8e03c37fc5616bb0573fe35a", + "0x15245833a84147b5df07f999c6baf27655bda682a5a4db93879f41a2ea023f31", + "0x4820d25f27aec110817a81bea0d7b9bedeeb8d9af55ace79de81380093a02176", + "0x4e156aedc00095dfff29092326b02fe2863a6aba3ebf8add79485096f20267ff", + "0x3b63cf9b1decf710ac331a5db829a5fd2eb0a7da6724c0a90b9525334092d6e9", + "0xb54145d2b41dd0142f5d2487b0db7fa96f42621c08d63edc036dee4b072eda08", + "0x8084c6690651740db4e67dbb0623b5d1342cec0ce95b6349058d7051fbf186c9", + "0x9c6b1c3b15784111ae80cdf7398e1283f4d68a9c2a6a2cd95b8594e0acee752d", + "0x71322541265c9b5d5404e9f089e505ef1814fcad641a81ba3e1bec009abcb920", + "0x1e028666b6fe44f8c8b2c9f3fa8c8ae5f062a7e117d79d661446fcb8a72b5db7", + "0x3a6cd5395b4be2aa1ee4f7d24d1d1433f46db1307c7ae823803ca1df7843ac6c", + "0x64b8b040c6c0cc2ebb2f011039dcb091d4c8f4d338b82fc1a68235c6eeb8c8a1", + "0x89f98b1f7e78b539f83d45c5ce8cb455e8ad7686f42d39f9c195d37ee9cf5fe4", + "0x14abc82071dae6f563f272da9e1ba7f9ac6f0547544cf9cdec088ac6283eb464", + "0x6aa6490aa64733dab57d954b9907f421c6c571ab2b2cebbd833d59d74ba19be3", + "0x62e4524b07b9b8d8a53cd29e457a58dd9f940141797f847b889023c22330db0d", + "0x534a4c4ffd28cc8c3f9823826644138c9207255958f3dac5d0a5f279d57508d5", + "0x3e7f74f25707ae6686334c585603253a21764cc1adc730353c02a56f6b7f3e81", + "0x59cc225b1c9cee2ece86b3093a8bf6ad3ae0260ee760384f1299b5af75eaa1ff", + "0x15ee9a6c566674f1f7742d1e07015fcd66e22d7648ba25be50428006efccd026", + "0xc0668ec3f88e6a9f1097050e999f0082e9a39ba43fccb194790e51a41602e704", + "0x03b0cdd4ca4ca3d8b1270eb9b73dd28f22ce5681c3e0dd5d11107719d2614de5", + "0xffad54056c851b02f83948e7d665980f623643ef40aebe91936c3bf0d24a3a2e", + "0xdd587650149a81f7a5e92739c18af1216bf32ff2cd7b1c908a6d3100c052b0b0", + "0x1fb346da4fa3c0b7d1acf87e4e8b9c0b05cf41d21794d9db58b14e321f9b6bbb", + "0xc15a230b3105e4c549291228b28a3ded073e7061f56bd31a8bbe4570e2e11910", + "0x9c01dbeda0dd9cfb4e70e8b63551c590edf5be26c879d319781154c44520aba9", + "0x8b418cd11db8823868c9495d213b9e5c5e0d8b25d5f7c262f21b3d2b9f591ea2", + "0xff7cbadcb60f8e9574e1a1ca57c0cf1b5b26725a7683a870b581734ce906df73", + "0x0efe88c68a8404cf9e1cee6d4b863c48ba502c5b5f504dd8a6f251122138e651", + "0x87994dbe88b7749a347e438c76273ba5a7b8835449d32ba75bbc877979e5a3b8", + "0x366779f7f70fc10da80427ba5f0f6af0e1b5d60c37c0c7e524e408a1e2f261eb", + "0x616c1a9eeb13a026372b099a101eece0cf0d1715dddf192147d401c722b6a6f8", + "0xb35494e9758f3bd7bb23fdd9c86f60a8bc73e3422cc9be80c7f592fbcef26b9e", + "0xbfcf52fcbd301f4b5d32e62f284f95d01bc545e16f806ab64038d11be74f8638", + "0x3f155939a40b556e30ccc4b32273a3586fd5aa89c4209337da1ecf145416c6f6", + "0xc23227be04320beca30ce9ee2b9f74bc8802414ee78754d7af1bc887e1e260f0", + "0xbc45e7b6bab510e72479ed0a675a05217244a9879be26d24780a39537c233f10", + "0xf651ff7ae3c7570a95245216c9461fbf90293a3962f8883d502a92277f0e4ecc", + "0x92b1b6ba3f6bb8a949225e51a480dd63152147e98d96ff5aca2ddc81eadac6c5", + "0x368b2b21a1411fd2d651c12cba2f2c3d4d9dee020e98a63aeea861e4b6837e12", + "0xe52565a7d159275cbe9e024130faeec3ddc3c3e27507d35d92565c8a56e13c64", + "0x3252703f9e4b7ba715810126ba57d87bf585fbec8e5928aa598c577f11daf792", + "0x6283fbe3a436d7860c0b564f2c7a32814c189093c775a8d800ae24160dd3e72e", + "0xe76378b3adf8f756728c553a5d822afa016d8117cb04a24b1c2a1eadd62421a3", + "0xc0a2504fcbb69d1adce70da836a73fe8e8fd74aa7aa4cb7d22bf844e7b91aa89", + "0x4d3e70bd5f122962b3cf64de57c69d85194126d71e79c964fc4397afe252da25", + "0x7efda1eb1564ba1d295eb6d403d9900b3336f081f2bb6de2c375889883f64097", + "0x6bdce19bc957c2bfc7e49f91d436367374847fdc6daae2e621f00aa024f78094", + "0xf42d152632eb0a55173ce7ce4cca3a91c7d7971a7456eb6ffe88dea54c3182df", + "0xa6a2353ab4a3bda46687cfd3ec8e349f2ed61e449875b9d1580d9a2370ccd54d", + "0x3aa4b80ff21dc79fac0b4f913d46687c4f991e5005fa6af731c9b2d10dad9c81", + "0x7d1022dc5a7fad9c0291448c56eb99283e1e64c37f6a55431843644102959d6b", + "0xa918366830e62330c423ce2f03f99206f6f3c1bf7660e01fafdddc40c8a0b650", + "0xace8ee8ad7fb40d481f20b165ac8012f3ff69f0bd8fd3ee290d894236549d065", + "0xb03858a13f584d7128989a47ae71d945dd67a3c2f54ecb3368ab76371d944c6d", + "0x56c78acc4c4dab9994018a969c3d3451300f8229d018f6af2de91fa4da6d4230", + "0xfb4313d83488e1003d38869fd8e8788d7e74c124542774ad7fa75971bdc61131", + "0x1decf505cb4473ffb91dc428710d2a2188d57bbcca71b7b5e277eaba0c7252cd", + "0x9db499b44cf0bd96713ec99cc769c8454fba3729014d87b67c18b55f0b4b9fc0", + "0x3cc717a489465b21a09c3fa19453d2a8cddb914b7d2789c21db6c311386e0f80", + "0xce4868287d923f8b22aca7a1df1ee11685d7c50c6384994ded2e99fcd2c01906", + "0x06b502cc70d1ae3c79e44a421b6ffb9a1a6f0bc647b4421cb375ab5d8474c713", + "0x4803b5e78af29ff140e37b23bd2f3de9fa6cda3a1bea2361e838061490708d0f", + "0x874051f592d34ea3684460f094a78d0e1be3bcf49586b1467be0386f1f9e3d94", + "0x8b66caf3a57d9998e2d88b0e4ff296825b6dbafbded01e384fd87bf4a92c5bbb", + "0x61f6244709692f492cf345586212374f4b209f1d2f92d3ba0e4000ad0634bda2", + "0xc58788c015dda34717586db2395a654f49ef0bfb4642459cc0ac5a5d74a2fb67", + "0x5161b49a84d5c614d72bb3e220878afa94d9acd30cdeef78873dcd91233de390", + "0x5e358365657197bab7481eab0dfbf8a6d66eec8dc62aa345c5364f75c07b8675", + "0xb358c9e7d218bdbb42f91752d03365945a474d49e84dbb15982e368def01cffc", + "0x908bf24327cfa0001d13fb5a0a73b536132e7ecf66d47f2c77215b03bb5b1693", + "0xb041e9e1a1087afbf41d87aa9e56195cc548527c81023d43416720c025b896ef", + "0x48ff5fcf252fa38a00aaf887e108928755932f45d7cef5a8fa0b72d711789f66", + "0x16f99b5d528b9ea7a92e5f7ac59e60d4305b71c9b20485c7911f84e3ddd1802a", + "0xeadc395d16b240b8412e14d5065a33847fcf8ae122d22f24438d7f79d8cfc40f", + "0x560faaf4e0471cfe39aafa10c9660d61c8489d2c5d49eff2a8e62ab31b7ec08d", + "0xf1c8bac46e0764d0faf89556b0080cc7b16433070e1e945e83f1ae36595da7fe", + "0xcb7409cbd3d3104a4b5d856887fe6d390643b4c433de855644f2184218631662", + "0x6eec345c4baf4e699f0ea48bdf54b2e74f98020395759e275e7cda0138424ab0", + "0x48a8bb061ad00561541b4e19009d3e8c2e2b9064337ef431fde45fb2988136c3", + "0x458b21c6ca362ec731487499486c4c0ea69905c8f36617810009edac608b9e20", + "0xb338584ad517b679ea52ea9abfc8d786ce1eb55cd3f221782de658f75b23ed47", + "0xdfe64bd8632a87d995972376311f78a0fd390fd2635e002e3dcd7838a3b28516", + "0x49d9ca4420847c21e2969911b7b5f321fbdac5037d0d8644d6f357444f91238f", + "0xd654571d72fc11d7a86ed2408cd1f78e8009dcd117323c8970614ed8731d66d4", + "0x2133c8e084efa57df6e1b4f1af5515a4662809d722ec002676eaa99987a2607d", + "0x5bc530b5fae32bc84127fbe7feb7eb07432313915e2d579a668f46fdbe46bd1d", + "0x8070890263bff747db0122240249361f5aa66cf121c3b6c4ac40deff6e42af5a", + "0xecd7aef2e4b4419539fa40570a61a967a0f296f524c25de9cdbb012b03d8d837", + "0x4376d56fa5e09c64156c6d1371151a33f7ac1e46635afb37823ed75287083bf1", + "0x50d32b39873466597d5fd29a2bc3596f54051d064559c46510f643f2c24e6319", + "0xc44c4284e5cb873846761cd012e0d221763c972242c0c4a161f3fe0e2da74026", + "0x141d2894e4cebe94df908cf463d5aa6a95e22624f5183d03cb60011c0677eaab", + "0x1bb68700d0f6e052ca64c983352731ccb0c3947ec73d67ecbbcb72c5ae3791e5", + "0x73095bc9acdbad7044390e72ae6c471c8636dc0116e2ec322198bc080af7fb11", + "0x66bbec6ab32528486c3ad89c36fe750d9c6e5bec862ea683988ba578302db503", + "0x979820d20c32a076297e3a940ef4b9f3ef02c9ed551996fa106b6db778852e52", + "0x4da1d4babd26763bb29976f0f2c439d3cdc06089951d0eeab7df2da59c128454", + "0x4c70dd6d755e7fe3da5f94dd2af53d037bda9d7b1eabb68bdb75111ecd190e04", + "0x87ff13d01ebf46a5a45f5b29e7026117e8b41d135829457d80918dc00a325f0b", + "0x78d573b16ad8a3c3b0a704a01fa79915907fbddeaca6c7e189c5c586855ea882", + "0x95b9c87ed9b7365b1ac15b02a388d47f75ae8036bf658850ebbd8b829ded9186", + "0x812fb8d5c2d962725245a182d0d267fbf97358d5c236cfece3fb398fe641f78b", + "0x31db1fe9db91df6684660f1eed0928bbdac477bd1bd376399e27a53ce760ffd8", + "0x4bb0cc2765ae336b21fd1f983f21464e907c6fa4831b047386f64e021550b2e7", + "0x7f6317d849a40784edf0d2c7b32f57569e561efcb4fb3c5f857b30319a93e2e6", + "0x5921a9e8ccdb11e574a012cafcb05a6dcf86ff8006595837fce805675202b8df", + "0x5357bc6834cde24334aa697f050c51c0456f7b03f938819baaf8c5be1dc10df5", + "0x8fb8b01b64eab496c9496179016adac0dae5ff6793970b3c307202fb17a93af1", + "0xd4ad4478bee0d5bb0852461107c3bef946f147f66a478789b39f7efb517b3bea", + "0x630bd6a0422ab626b28f205ec9bca83c499462556cd8116556bb40ad0cdf0e66", + "0xb2d07716e5e20312f314cde99480110794d3cf70ccc786828fa25ebf97ffdcad", + "0x87fc5c3371e3ed8f9201f61768fb2683bdadf8c3f6a3039c3504107b07b508d0", + "0x9e67bf7118e42faff0aaf8aae3118867c692b27c35efcbfd057d562e8d4390d9", + "0xd96833f813ac20074274531949bce0637e06636b6ee8b875b4811f09cbc8c116", + "0x4e9f29f98bee2fdb5c5692d94bad8f87b6b2904258549a937603da0ab5d36b65", + "0x77c3b0bee822bab79529cbe96d6847649d9528399a488ba9e94484f7059c46c4", + "0x948d3eca01db52a52679fbc33ca30aceb7e3ff6449463a2748fad0982b75313b", + "0xb3084fdf4a2ea5228c35adb20017039f4ef01e97d99aae08d4adf591b96330c0", + "0x5bfb4369df41aa75c957c1fffd6b498be3e7ae858cd53f67c1c688b9c78afc4e", + "0x6a2092f54cfb6c26b0d5c8f559e5e9995c79873db7631a8f6397ef5ef815352c", + "0xb286ce1787331698f1f860e1232f6766a658d27390b7623d460136a6be90a444", + "0xf84ba9ae60fe7bae5d3eb5be6c6b85aa564f8d0a7ffc479d4b0d1c8bd69a2adf", + "0x467550339dad58cba021e3fe967bd5d81be04e6670488adfcfeeb0dab07d6b2f", + "0x5150476eb3075df5b6ab3fb54ded34ce76e06660ee401951652e484e9a3fbd62", + "0x80845f54e9c21ee96f4aebacad6d199416a6b30fd741d6e6c9966f58c54f1364", + "0x8264045a020782a7dfc047efdfaa103bc186e88c920f2c25a016911fcf33fa2c", + "0x52399e942b721929b9875c274ec6b5034c26f7749f6d26eddd99972370dad3ca", + "0xf03d8bd2bdb8ea0b6ae2e7bb55703520cff714143501f291a3e7199be5d466a8", + "0x40eed1aa25f1a87c849f5e02f846c991e7473af9fa0985e3d61bdee01cf0a5b8", + "0x3d18c888cc8729f63ee415348121e10b5d990c8f091fccce7e2d8f5c0132a20a", + "0x2e72d969de06d28196506263e6dba8310b6854b5069fdf94317a6d3e90752560", + "0x2bf249dd628dec9d4cb267a9013e050f0710daa2915e468a623748dde1a036e1", + "0x91c578ed45a55d0108656d1533d209de851f77d9abdb58265bf867d7aeeac5e9", + "0x88dabe83eea11db59d67db99a159c623498cbc648c79d829a317719b836540bf", + "0x5fac0c3efa49004a1af631263097978f16f7e6710ee7a1557432aa727e44e09d", + "0xa8506487d3c54e70b3d6e83eb72af7858f583527ba6f6a6aee6a3eb33750e538", + "0x62641830df38adc76a043baad1fbbdd8e49356c11b6565ae0b04429743011b08", + "0xf053195e1bc2db0d0451ab69471520d0a03370a8f27a4f62a1885702a36d583d", + "0x7197d7a7897505dde22c7a518054d9df7f3368fcbd109cb596872d92f6a86fcf", + "0xa5092fedfd64b4985e70ffbcd7b4522eb45f9bcabe4c478b1f1452b063d6d551", + "0x027251c22748451514c27aed0f091e7589600bdfe816ffb0a5ba99d55265b65e", + "0x590271f52852c220ae38b56cca9960a1fb94d5343a0090bfeca5e8b5bf82b2c5", + "0xf8df310ab62fd52c452122deb0f2e79bfb85bbcd0bcba7e6aa5a99a541233431", + "0x5d313f0071f2d885da1b1b5d104b8d78ae49842ff9a636ad2613ad9e90b4ea52", + "0x2672988155e5c27a3af3ae26e74d164d9f52b4c71b74905ae90466113e991692", + "0x330c8cb081da0372f6dded08c0036199e11aa8ab51f6f9869995cecd3eb16f24", + "0xd65721d9678bf4667c6688af76d2dba106fc51e8396b0af78bcc80bf4149629a", + "0xf5019f4da39e5ca6102679e5a0388a3850eae7bcd91c632d26515caef12c472f", + "0xe9c747dfd6af4dc29b5836495be42673a20bb2475264a2f9bed00eb8250fea7f", + "0x2486ab886ced7bbdd774371aa0ed1c177d6d187bda235a4a8fa390b704eeee8e", + "0xa91824527f5a40050aafe359817594b43cfddbe3977113207a7d5868507caa19", + "0xd44591357b62e80b8f5606eebd4cac5052efddfc3e6a8c5689660d6617f93b33", + "0xfe5628e6d9dc75f413cb12ee1004e1514769ad7085b5434f762e93db9115b78e", + "0xd0393986e30a8961e01ede613787fd2e6fab42db329d0e57bfd16b42cacc4045", + "0xbe40cc6ffd2d51f7658f48359d4b726c64a354a9d1becf189ed83775f8fb4086", + "0x1d06de0ea61fd233ed701c9520f18012143277ca9b379d39db62fcd0a4e7681c", + "0x463ffe1d54544945f4abd7e35cb7c90a4a809c25e1919215207b7d2a8d3b4fe9", + "0xdf128c4d6c4048d4fb0f7db6db091ce4de10d509c45736f5521ebc4ac93a7ddc", + "0x5ed827eae4b7e95cac552d60b60fa209157f1a8c6e3611c1a5f6f7a49e8a6a92", + "0xd7fd28964beb50a410de115f290a0140fbc78d0d4c47ba02afe9f47d80df5e53", + "0x1996f9b8f7efa3d860233141774f46c00b63f207219c2eac5e61318a9464d7a7", + "0x4cfccfc8a9623fc9b5ab38c991999f8a52c6537d984ecbb0c490ff37559cc51b", + "0x4aeec05c7d47781008273281bd01b36c5ce21916cf7fc9dbf79aa2c477923c1f", + "0x96cb38c2449f97c92c81f5f4317b15267c9c2f4ab62240885280ced5f54bbc53", + "0xab5e6b9e4c4a27aa725183699ae30a6f8bc8148bfe85d1e4d0bb8565502e6e73", + "0x23fcdee9cd75706e640aa55c4e8acccd7ba9591e724bf351a7070104cdc698bf", + "0x5f3433fb2aff1e3843785b2f2cba22811cac84061803a2c5fd045b1983c8ba81", + "0x5613366fa3c323b091a44d10ffdfb1f485160fb45094cbd52707484f820cdae5", + "0xfc43bffcd36963706e2bac564dea4d593c35c5156de02eb747bc557988d628cb", + "0x4f23fab93388bc79a879f85c3efe0f15606828e6034cdc6b66810a90cdacb793", + "0x62ebc41d0592d1569001358ff3f1641c0a6ad89e66b0fd1e784f060c9101dee3", + "0x12bc43cf16c8965f106f3749bb6b5d9ff3936a205d2ef5719ee637308f81ea24", + "0xe991829e5d9c26cd365f6907de1fe2f2153cd88a7d7e8e56224c9dacce442fa8", + "0x55679ce947be929966abf9953031fd172480b7da8be0b34344512406d93764ac", + "0xae1f80cf386c6cbdd1ee0a1241e738c245eb12665f2fd1a614391ba54c741847", + "0xad12a941df30e25584f19f5aa65069d919a2e0dcbcce73de8724f975abdceef9", + "0xb3478980a68ed409b58d35759d4648ce21ed97758a1eaa0d0f1ce6b059b6da41", + "0xbec5fc3e9184d2e46bf0ae39c408a7cc243a41b69a923fb2d1224638153b3ce0", + "0xec95c1df965aef7e6061a770e0c82b6dab0027dccca5ea3791ed207b868098ed", + "0x2bd64bac83283cbb0bb5f7c1d461261a089a40904574e2daaee97110425092cd", + "0xeed53a58f04a07af388b098bb8c1e49abab852736c84d69bcbb78b945f23b86e", + "0x2c2c81b8a0c362105ccd0251119ddb406b65562611b2c3b3fb9825dba0cf6ac7", + "0x91c93ff5548a0462f1cc7cdf0a5c57dfc1f21932dee38e25759c9e5719036fbe", + "0xbb1c1bea058893b30e38cf0ea2f53b943fd6bcafb86b0eb647ccd152aa42dad8", + "0x079da567e28f61687250a49aa9fca4c465245cb0ce02ff075b500b203c459605", + "0x691de81b04aab67b3276168be7dc43e220114005a4d66a1ce9ef2665cd2bc867", + "0x3deccfb1fdf3e57aa2d63d0692cb37f375aa457da52d88cc9cf277c32021bf45", + "0x6cd1a84bb6976f2599898aa46fc67627663738cdeeb815ef1f45762cbb14dae5", + "0x29c96ea5d11a5a761ff7c64b24a0892daeed506b8f7ab33e93d6eb6023b9b37c", + "0x0bd8890f06cc6187a1d1a029cb319df75018b067bf796591b0b0a07a2c33c008", + "0x6a3d0b949241a493d2eab974adb173daee1e3c791c2dce6bfe59b127f8557ba8", + "0xd102ccc0476081c8d399083930dfa59486a51f83d33096ce77897b9b0fe41b1b", + "0xf9ddd66ee324bc7f06544cd53f792dba6697c1ecfd4c40a44733944f7e7ebc91", + "0xc14b245a2f2d02ecb944acb218d76e311659cfabcf72f9eb49db59541550b6d9", + "0x190781209df0cb64a4ed6ceb15428699e6b67f3cff28b7a987988a8e29829171", + "0x46605aba1cbee0bfdf90b57e320823ad4607d9ea1d6698005820021128c472b0", + "0xfac04645717514b9ec56f85cf0e6cae5aab46e25e69e3cd010513d9598d56609", + "0xfd0c9f959513a72149bfa23b32c5006ea766ba2e41edd47f450090568d44cef6", + "0xf0560a14936e66cced54d4002599808b127f9e56260f04f144fe9da412577c61", + "0xc9448c9e8a3b09fd51ee93b77feecb8a8ba03e1781a3f5bccc93b4d1815232fd", + "0x3c41d49f2aa53e90f5fed6f372c620fff5a80f442894c71bd7b6c2f55ed76f47", + "0x0d9517fddbd945294c72ed49bf6bcbd88d84c9b3b2e257c05f64bb69c4d7815f", + "0x1a67fe64cb906429f47250e1a30858366e0204c3f39b7d4b3f121a46a51566a4", + "0x9833e385110465d72ab133f02348cb33433f38454f6e985b022720a9836e5015", + "0x89f653efbe7bdc469e2896aedb2a22ce5982b919a7c6dd14046db4eee3950b6d", + "0xe92427a7878630f65cd4f38dcee4c5d87ea0dc3d0ba1720c0d9f53cd84411b7f", + "0x1f692c127e4d0e37f55f24f5c20516c804dad968b5dfcfa000595b4682aabab6", + "0xa3557041302da75734accb2e95db335abb208626e1b9d20a54ec0e0d23a5e003", + "0x96bfe30b54d1f39b5693272ec7cea523e0531cb7fb805e69a820888ea747b3ba", + "0xca8f5d8fdd17be423ad5bf84d7f591466137a54388b65f5d853aa83ef25e9b42", + "0xafd729d01c437b299b29da02e34eef0b8a762a24447b96c0499231a17a84fe7b", + "0xf95f528a8abcdc0eeb66250fc3d1df11d0831a08b30d11f0f6f0f96b02f7ef82", + "0x483de90f340fd0035676305359fb8c83b709374676796c86c4d4b615ac779b5e", + "0x433f6ce08d28351388ef6310847d7949f4e92ec99d585c3cbb5fd7152baa507f", + "0x77dc56a6b802ffae812c3e4d8768fc3d80bf96b95a55b1b9736a9073ed0093ab", + "0x5c3c2bfb8cda1218a08084c4645e2a84fde3aad03ce00c3310b3ae5d80e25be2", + "0x3321f6475c8ed111a1373bdeb68609f52c4740f22e4f13952e8a6d98fbfae542", + "0x7a0c172b717acba8a7b874e6c88257cfe68d41855506ee909d84d23b028a7ffb", + "0x7ae3757e9cb71b9063d79db76109af96ff1a5e6aa1183b1b70150757243a94e1", + "0x4ce794f4c0c9273c14e6faa680e8837247c6a0ab503a82432f69529d4f5530b0", + "0x8a0ff3d87111ac19f2d95d813e384a96dae3cb15caf12e50b99816393db3a374", + "0x35adc4577b9532f5e821d6a39029cb898886ec9a8b938bde92ccb1df67d2dc2c", + "0x84976050b7ccc3c953976162a6406d125edae798bc1bf850b8867b3242076a30", + "0xa64d9c9681b1192185c9570a6512d8b21483534bf0ca7f457acc96f91070358d", + "0xb27f0ed2428dde6c5506770651e3cab0fc62b71be0f245a8f6a84c326ebdf327", + "0x4f71b19b200ccaf3d359eee3ad5d7c155616b86495a43e2a7c18d0740304aa2a", + "0xf22988f8c5443f4400af9895f655a84b31e871a68e74a396ea5334297c0fa190", + "0x37dbed2e2f7408ce439ab0ab09af040972021ecd606f517af45c195a80e3f3f6", + "0x5165c41b008baa5fdd010a9a17f0c2fae2a0f16b4d230c21bdcfc737e9279c23", + "0x96ebfdbfbc02fbf12acdf622ad7ffb8dc10299ee66c4ca956eacebc6073fad75", + "0x47ff8c523b69bd123ebc4ee8a81240f2bc1c4e8dafcf9b9cb5db5b7a8f4c884c", + "0xcc3a09c1108d216199d7b3412f86d73d4fa7585c393dd3ed95ef0320f0f9bba6", + "0xa79133fa77c790f4f12a9bebaf21531c831c72db93e4a36a8f2ea672260d74a6", + "0xfaaa6544245fbf22f3016befbd4acf93135e64f69a7aeab07599af3a52f6323a", + "0xf489992872d1dddbba3c6b2fee1eed0f604f02e7350d747398944bcf4fac3171", + "0xb49c4387382e339ed00cba9469275920e116ea556bbefeecfc9c154d2f1c1f77", + "0xfff493a58d86d6160d9bdaf60504b07d6f33412fee522af09c1a7de8ec9fcb05", + "0x584d1e0a2569cff0fc1b71c850eee0c1f680037cbb678bbaff035c49ea5a6275", + "0x91682c3606944042c10a5fed5e6b5662c39cf980471b8bc603042cf0d455842c", + "0xb979f301dc2bed6c7e60bafb112b92b22b5f173f1d9e8fd665415bace1a580e0", + "0x71d439075aede2a781f1a872dcb8c89846056f5317be5df5dbf47904d106938b", + "0x9c2353de49861c4d10309f99457e6f6d9e5b7a57360837aaf0a1942c0440fe9a", + "0xc2c08c3e2d8741a4b4bb180fee1b1d0cb54f87f2739aa3881d534a9c73fd2d1d", + "0xcd75923a659ed6e79c9a1e22201374bada6bb2e030e3664763dda54552bddb15", + "0x60749dd09da7517a03cf6baa9b4623198f4209f1274c00bfb234c61d467da12d", + "0x11b1893d89913c9c57f32ab875ed403fd9802475e3c861472dab770d4882192c", + "0x26ddfbfde82876e17d6872f31aca7f233f790b3ec0618d6b5c51871c9700039f", + "0x8c9ceba1e4cc81ee6103acda0bceebf5b0413023966dd5c3c5641453c96c29b4", + "0xf30e9e6f8456fb427f96f356eac399fbee64dee3ec4a2806701c3484608c0edb", + "0x7773f80e3cadcae69cabda956228cac8cf774bfa84e2ce92ab2872ed19946858", + "0x4d510670cd4036f534fda9c7b4ddc14aba28ac985b90a0bc831483621d44996b", + "0x4e7d6a0fef6ac54f4f0336961561398600d0c6a04862f613ed6eb648d45bd348", + "0x55c0bb04ee6e1aa15ae55e1de229ab5a4b553864c43cf527f2ee42d441bb0bd6", + "0x92a9c4000171a6534d7546749d7392a9a18974be969bd773b4ff3f5c39c91a17", + "0x892daebee1b6c833ad425d5606ac7562c135688ba8e83178c0f8438679e84e7f", + "0xfb1438e6e00a88a26dc46bdb1ff1696cfac94bebd02f16891c08b52de7accd84", + "0x46404590a94fdd59cdd4ce607c1ba016a78be8bfd8dac361b8cccf6191aa0bdb", + "0xc1a63495f12681da588396c2d30096cdc8c52fafbc0bb0d6f11de5ee2c5a7c51", + "0x86ce595e0805026d106024d9d13e0fca7b208155901b67cb0011138b31bd947d", + "0x7bd81277da5da97359e67e2d5c12cb238daa009f4220166e13ba1f067125888e", + "0x2dbf4b23c2178c8dea6066d43b5f1285894d9e74a8b1056d0ee02091b84dee50", + "0xe983e1211c5b12ccb547dffe850e4adff01eadbb6717adb150248900332482ae", + "0x2f42bd119e06fde6cf7e95c59caeb189afcec85ee9968196f7a15917f98962c9", + "0x1e54e7e17e28b7c2de1c8391684a938e1adc2011fdf8f4a6da900f3664f2f25a", + "0x657e31fe41599356929abc24f7d751e49aa769ef9a4b9d5b37e6bf019dd567a7", + "0x33de4f2776dcd8b17b846816e02c4dd1694891b6827f87a80b31ed37ac0c6048", + "0x2b3b692269fd869b7797c78de9a521705aa223d78652dfbb32c1b8b612bc4351", + "0xa57d205b64565acb103e962a83d300a302efdcd96a13f4c79e80e2733341a70c", + "0xbcdcd2d22c7e21d24e48d28c43d09186a15568feaa24f44f126e5bb96ffbde99", + "0x3a6de68513eb363878604d054f46224e8567f2654cbcc0d9f81fd37fda804a65", + "0xb762285a5d8172a6df584ed15e954f432ddd8f41ca342db7d1d14c54af21e420", + "0x97702988d087056b85f9046bb8d3e37365f4e5811507c1e2daf544af76f1825b", + "0x8d1dbce8efa6eeb4269e22b45c2a9e7c53f7ecafb83e8219b14d43f66b6fa68b", + "0x54a2b87cc430e350eba1271a9161fd08157e196a4d4a7ea29a7461dfab6370a1", + "0x253d68032f383891fbf9c1898fe7d41c6362ebf759b3e3216bc14bad63250181", + "0x175102f1ccd3712675505c3d74609f2c46053c2501998a91b69b2eac9e1e476b", + "0xb07dfe916a1c61b07571327de80a478aeccd3f6f26aa4ecd7081a5f16556e946", + "0x0c87d079935642a1d3673d9b41ed2d3da33ef124acc081e236b23c50d78ac968", + "0x0f3718936f3be6ac78445fe56dc92e4806032d67e014cbe0a92e3193999c8acf", + "0x88bc8add9c916ec21c2f83e398bee626533eb038900c787eed34cdc1ef273a2c", + "0xccd4eebce003d0415c0ecf2d40916651b5f336e5ac64652b69a2ef653d777995", + "0xb9bbc12a4b92aad64875c00d7536c7dee7d62b87813b99a9a77bdc066c169a89", + "0x9ec43027a7229ab550391eb6dfd0cd5cc9b3b103eeb0b79dc9d2f4d8ce3c0aa3", + "0xb4e8c06e7424fdeee2f241365828d9a407f117a0811cced5ac35dbe9abe70a81", + "0xa5a9149f1002457f7c9c3dc2a4aebf7d5453f20c1d7e3a3a732ae92b04b8c00a", + "0x28d20d654b1e7a024956a6c8f53bd1c097d1df3a6de91036092c88c8070474f4", + "0xa11eebe47ce50f4076209307fd58c75b0ff725469ea0875c658119f7abc644de", + "0xfff2020661ecfbb50cd6263686f903127b9d1e5f43dd8bd2d5ecb09eccf6090c", + "0x253576932466ee619cbd3f012915380f1e7a79972864fa0e98a755f902f1199c", + "0x554258855ef348fa770e3af434da722350e998e930f234b5b8c33d3d2f806595", + "0xad11b76ad542ca1e825b251a6cf410b6f86c8c4b42b3c8690a2871e7cfb27882", + "0x3c3d7cddca90448af6119481e08b388df75389ac3c7dcc26ac532680b23ce2a3", + "0x94c4ede45ad5b27c5a6b051fca3b055d548e4c29d2541a9cb4c37bcfff4f19a2", + "0xabf8f7c1b9828d61e3aa72ded1ceeafd6ad539b79b5d56c5eb93c3327b9d83ee", + "0x6e2aa49e5942f19f19181ae911e7951534aec1a7fe295bbf921d8f28a4b7c0aa", + "0x0f49df5c80ca4ff33623bcab40e9ded6159d3f167f7754c3dfaa2eea0ccc368f", + "0x070b14922cfbdf78ead68019e520a08b987ad203db005f4085cd25e6ab587016", + "0x8501cdc568d6c64cef9b87e639d5a0e3f5a4b7d77e8510df07bf0fc50d89d020", + "0xacb70d4cd2010d149f382dbc0f7fc1b74f0fa6bfb5e770017fad960aeb7c80e8", + "0xf49878d3473b21f4ff2c331fe48074ba47ff78198f839dfc7d1d69abab81e499", + "0x9a11ca4ae2a7a68bfdbf54d7f0978150176aa4012ccb8d1781c10b58e01b851c", + "0x58729c03b10b2ec8b4abd91b876ab57a2c0bf05ff02218bae9765a90037562b3", + "0x3b5b033d76798ad041842b9ecbe223dbcfc2d5babdbe864480126dd932d29fa5", + "0xe08ce9149dae8cbc8968dbabbd97624f917148f26f45b858e49c2c389bb22f20", + "0x6b532db41ccc7cdd970d5cb0166dee2272346f23e0acfd8d751491d0c3ecaec0", + "0x99fbdf39928b3f855b2390bb845a96478221330b7c350e83e7b4dbf7a35e2685", + "0xd2a2a108c0a4dfe5ba0d0488da0de7f6d15994f6c14b511712dff4af33bbcf8d", + "0x75ddbc2ad15fc25c2ae71750f1d5bde5e825b40d29d631a27d8801590d5e1321", + "0x226995d806f5d03722266554109395921f63ba1f66f5ed1ece7341bd860a635f", + "0xf78d4178efcc128e86b2e1df767e59c76a4bc9db0ea294bec79b08448133568c", + "0x160e1fa8fde835d6e91187a3da5caee245d4d0b9ee30894170617b680d275166", + "0x361d71c972953283f8ddbab4a45a01b39f30290dc1dbf1b6b744af5afb2e70d0", + "0xb8394cc0d42a0b60ec40984f753b8eb5b9175022bc2ca7f80d64d26106ce86b5", + "0xa0f6ff5ee727a3106e045468b5ed9ee8ef387eb9a0355f2249a71441819b7bd8", + "0xf441bc00d94f06485368e043f933ec9f8e181b11ab0212d728d83e2d039edfb6", + "0x1da12d2213cd65f5fce71c06e44b40a487d5e676558e6f617372244f8e98d549", + "0x7d988011d5c7da97b37c6a6936aa499a70aee8b38f8ed60959f576c108c54d1a", + "0x3d5ff693e4ec163fecbfffc95024cdddc4d2c561297124bb69c8d6aad4ae85b9", + "0xf7db67de101d00409e1ce3430445fe3d38a073e1c81e1453d63f4228a51615ce", + "0x335a94506606e70ca259348ae7157066b55faf09a4ac11bcc34a0b865f4a8057", + "0x137d0de6cfa1e475f6d94248c1e30bc10c17b98d40829974ed4ccfd7de0ffec4", + "0x1d63a7c1c54bc740875f3b5d8750aa6bc85d1c10e3caa4c9d67b4b010a83c29a", + "0x04e0208220bd1218b6180dcdfada95b3a8391bb380b0b0ad5a1a8a02f1a3687b", + "0x02a3dbb2d221bb8e8be58e12982445246928b9965caee73383e54edadc017315", + "0x549dfa1efb8c32071dac220aa4c76ccc038cde6ec9a39e2745a2d55e92bc0890", + "0x1f9bec0a6b3415194528a23443c9904f578d57d7024ceb964ab09a9e8e3d9c03", + "0xbfb25a68c40fcc0dd996e992b18dc73a48525a323995a0eee03a0a04c572b68f", + "0x7244057fe32846105479bf704b871bd1a081acefc57b37aea76116442805a70d", + "0xe6a48159dc041cc9a0d8eb124aebcffad394a400724410e956f8f46e1d89e8b7", + "0x812d9147b6661f54af0c39c1f4de79588ad9cb62b25befd4334ef5f3ebbc2cff", + "0xf9aa945fe2eb3d1e2a01db68d4502a4f33afcfa967fc06944e035c582dbf383f", + "0x63a437b920c6b916eed44003b8d35872acbd0d1859b6596b4f45e39d04057e0c", + "0xffbaa46c582530498f30e51d18deb6973824b850d09bf4a4535699890a548eca", + "0x6ab7423011299d3a82d2037cfac752bc0e88a82696f6aead69ae940bf202792a", + "0x2fc6f5dbcccf16340f2b3a5e341e364c3cb1dbb3e899c7acd6e50e7ab333f45a", + "0xd354b48b2d3cf13487ac8138caca0740408b42613b50f056ea595741ba275d7c", + "0x8e1cbf4bb7a83b1e47f69c08f3fbb133bd36d8fbce923db79a248c21e9657f8e", + "0x414c7f4d86ecf78c3988723ab584ff735633a37267b1f5986d0c2e6375f878b8", + "0xe0b0dc519fccf20ef45b2b185d791575d88f93011bcf5205f4880f7ed755a54d", + "0x528a7ac7c6a17775d207a983b76ff54f8fbb84b8ceb3f6fbb60a80d9f306c497", + "0x458bfe441e32d15fd95a33de1665a94ff4f2a4c357f4fdef5c9e7c82013f59be", + "0xd478a55408477b3559d50bcc4b5c4cc2713e0666f40d87c5faa7328c5b7db489", + "0x9977a36db4a48e7e1f4029efc494a341b8eb2e40c73fa9ed3be2f16065df8900", + "0xe2cb22eaad423da374bbe1cfb8f4f353eab0f9874084aac4f42578525e26586c", + "0x0225069114efef02e188a1a35320d6522c115706c7b87b3b54805aeeb9e60db7", + "0xf82e17b405c2e19957b63706c0d7405e09be93b129ecf850e1941d62f1c309eb", + "0xe26f6f439b0d33f00a973b12f5d3c619bc4cae8662ba25173fa3398b8fa19d02", + "0xeec38666a51fc161736b7b48c8befc98cf9683975abb8432cf735edb907b05d7", + "0x8d8c5ec1f83108372f361b0679a65bc72f1b5055a3b9a12f01855a61437c9ebf", + "0xb53f85551f811c60b17b48df2125648aacef9a74af403cbd877c1e539c045ede", + "0x498d608f0ebf85809b9f5a9270e481d03f4e26cfa38600e50347b968cc05b13c", + "0x8e6d9c2693bb876101c2c0ced0976fe71db31b0a725fcccc88cf9a69b47cc9bd", + "0x5ac71d4859c028d90da98406f2c739ce6280cc227529ef8f1be3d3547ef84da0", + "0x5e72e33c2d66fb9b31bfd4d423aa1ae7d4aa88a30758e29610eaaee778ad75ef", + "0x97345508a573bf5036243f384e1584dea6a723ae342a876b572526cf992f956e", + "0xccb2773ad04c605e9b4a6dede3cc41d69f43439f19e4cd97f54de3a28052d0e6", + "0x0d48cd6317b72fcdd315a6f912646831ed52257ebeb03fa70576a918282e43ae", + "0x688754d57dc88205d6223c88e802461852c5f930252bf74e08b73a79e4f0ebd9", + "0x2860c5f26b4eb0896b4ce041582a8d38b1c8aa21b6c163784277df2658d7e191", + "0x35257fb9aa6c9e8ac16068786fda9c06ece1cb2219106da3216ef4648d28be29", + "0x1b81179c25932e14098aad725e59bcb8da8867dc4a5d145e90103beff868f2ca", + "0x60309b91add03a291fce9fc3f8804eeb993508d7cd5ec4c13a41d31b71d09997", + "0x04d2e5e78c8d8c0059d829c16ea7397834cff5914a5c0618e5904a9037338deb", + "0xd6d345d35827336d086eeb801e331fe77491d47f0df668234e05c3755e413e13", + "0x7f29ddcbfc971fa8ec8e73ed1e77301310e99f677c17320a62fa32ca225e3e97", + "0x036d5fdecca68a54be820fd086e1185312bc9d434b332db547d65d9fd0adc5d8", + "0x07d7ebf143ec977f4134d782bbb3da778b1add224fc3617987d9b21c7bf7d09c", + "0xf27fcee747ad3f1acfee97988403537b85f51ac1157aba723ace11945bcb5115", + "0x5cb6c6cf872823930abb5798d4f1db9d0ae200d21ca3716445fcfe675432cb68", + "0x8226cce1ff6639ac646ec09fd71a0de3d6ffd323df6ea24446dbae7eba66a69c", + "0x6e07367cd7df8d5e756e9e4c535f0933df76941640a7bee501f8af8b653543b0", + "0xa60f86078624b3c727784d4a95bd6dee72210c801e7cd0a4fb01a2ef5f7e24e5", + "0xe3ff30fa3e754fec8605305377cf6a3842d2cb323950db58e5bf02794135bb2a", + "0x74203c76eba1b90e3e76fd493f66fe46130e13359547ce4c94919e9c8909ddec", + "0x4ad657902a564df2f15d7fcad6e4171c96c65798d8b49d3976c7d77869c06ab9", + "0x043cf965b0b5b2dae096d8c73190ad9b834b665097e6b77212359c5029fe8f1a", + "0xb370bc64167f8c6be57238f35a56b840688138e860b08c2c8694401ca32d22ad", + "0x1c242203268f4d543b7087b0b4506f4b5e5e6fa4f4b495c6bd15f94c7ccad31b", + "0x1250c4ef1fd54888a4e377127c9f27889fc5bae3455010733e8f48d7aef65c99", + "0x83bd5c6109c0937f109307dfae9b347fe7da69fceac9444da2d6394d26911956", + "0xbc25fde0522d9ded3c69f9ce8233145b5b15242a8f5d6d6feb2b7aaf0aec5cc8", + "0x0b7fd860e34f21a54293ba2dbd61b28fe5ea3399a29ff7af4f577e681ed579c5", + "0xb2d96f1f4fd0f26e226386aa94e306d8a4a2a3be2860951e0c2e39c77dc31bb8", + "0x4b9794e3a3fa08b8a71f55afd71f2c5ba34fc9d773c32242246c721c87e4b14d", + "0x01d6ab151bd597e2681e9c67a0c3f445c85bfca4f8cd73e3d088f49dd669ed2c", + "0x686280902ed294c99c49b8c2366686af45b9c6ad0e7bfdb1c52f1c901a6be2b6", + "0xe0a05a29c78f04794b3957ccb343be88cf11b00f5d2454a6003e2b363f88d5aa", + "0x798aead8eccab3a4d4dc1283cda04057038bbf80944a87c9e796fa7565e34ad8", + "0x866ba6664beb3b953f5b5524190685eacdd1830248bcb5b0cdcf686101be0ab0", + "0xf31b7929f0cd73d652d1ded75d5ac19d95720b386fdc660e0829d122e66a576f", + "0x20fb041619114e9beb6d70ed0a488a1ed8aa149ab506e7bf62244934441fe0a2", + "0x91f9dfc54ea16eea1700cf1d729e77408d037f43238545136f6cd9c72bb2d260", + "0x7f633029a0d96a3e4232ca3b02189b59b10e6edeafa9756f8db1e8844e9cba44", + "0x0b4f8a2e3547fb13fb7ee5555281ee325d068a76a67ddb1dcef60a6ae4b41597", + "0x35b3e9e377449e7b1a023573123f5d132b50a829091183d279590edc73df67a3", + "0x8ac0d74f10c0f6a60d2e5729d150ffef0467934f8c3e0b37eb7112eaff246a60", + "0xa8f65245b7fea166560a0d775db32688a0249ae3df937a42847f4f0f358af085", + "0x6d5812337f22e0e436ee2dee8bd3a45b237df7e045a4bee1458c55a1a269cfbb", + "0x6f79965282b544af683f2cd74cb056c092d5aeadea1d16e34382cd97113f4436", + "0xf91f555495a762ed98f946487f9aac89b4485c71fde9d700cf562164773b119f", + "0x92397cb86fcd4bdfd448fce9e3fd6fcda60586482217ab74884182d91f3a33e2", + "0x3f694bc4515ce3389bb57feb21ffeb3078e67c3a13bb53a345f7d837d92e91d4", + "0x81694d138eb5afbb7137ed7de9e4fd7010528da30014d06feded8cb2db307994", + "0x56d59ea9f640664f6a1ea3d92860f15ac38ec313d520b24b0ff4e365dff53b4b", + "0x5056000d0e11cf10bf36c57b44eff8fe9560e261264ba2b29e97323c3fdda5b6", + "0x427230af29e403291fed2784ea8852a68d4bb0c07a514dba4797644c8150ddad", + "0x21d5f70bde1ffe09c38545103cb9e6a349e62c1316f1e7e78c2f93e577a6dad1", + "0x385df64391152fe6e1f574efc1be371bf46606ba571420c601877dacfc3d1458", + "0x4076eeac8e1b22684b6fd996a11db49ef6b52539e481c1dbee3f1ad3f59d4872", + "0xa8239c7d2d32a3ef6f887799bef8b470dc52d0c82af8de31bf3a8e4a6bdf3535", + "0x52a6ab7c89019f8fed6761845f9071bed1748aa461b87b0a587b7f59489b2dbd", + "0xbf80c8df3c0202192d1b888f80668c5ebb9d4f8c7d168570afc54276af4de578", + "0xddb5784df235570dcbb1a08fd293d58f63b7afac494b1f8f947677f2dd36a87d", + "0xa741791df39f377bec8cede1f1c491eae35a710de095b5ca5c56d77f4431e87b", + "0xb119d39b47e1cdffe5a4f912d7bb19c6e7776803a386ef62226f08ac1fa0f4ad", + "0xf71e68699da769cf06d77c0432ecff635cedbed284256336c682d542e33c96ac", + "0xb600381fb3bbfa7f7c3b555c51999446b148a1507bd6279752e7059e2e0052a9", + "0xa596f51a92c38e63a7172461962834dd700bc847b1e29c03e27b8e49cca19b4a", + "0xee28f2ef5162f0dedb5de1c4b38a1049e98c82a34570b8bfa19735e915909579", + "0x1672d010862647d074aeddc4189a5bc3a128b8084eba6d011046b11ad23f445b", + "0xc99102d4079edccd947367846ae35e2b40ab3f0e1aae8d68885b1753c2c64177", + "0xcd1003ed721269cc94a0736f70714394c191e7a663191268e2daadeeae2790f9", + "0xd33a0f2338d2d95eff701d0bd287e70e0093c6954455bbc63be7de7c39f6d9c1", + "0x97fb57fab06fee889ca8db09d5dad12007024c3dc59f867170d65540d64808e5", + "0xc4a6963627634d4baf5697343904c4c803b2f875f05260602d9ecd45e0e34d4b", + "0xdf3bafd9380eda31fa5f606fa915253ee8b9a41cdbc0ad12e2dc1cbdb76ccf88", + "0x141dc873ceca100df1127451dbd96e117ffefd054076327b68b1c76a4651cb92", + "0xebcfc5da5a1e1882637b9714fd899d59fb957dc9e4afdaac199264e8d29fe5a3", + "0x087504ed686f8e598560ba1f70dbfc72eeefb7cbee9559927a98bbb31b7bb9fd", + "0x767d65e905169fc44546a7c7828c2f1b76898d93df663291db08a0a6f0fd8610", + "0x0ce5170b5c9ec6377c3ef465d986159f12e65c32ad577d8005fba498fc6e5d9f", + "0x76a78e8c3799f93f1359313a6b42f3a4bf92a9c52c7b495b8d82946d471ca965", + "0x1b5006aceffd1d61936cb327b7420f3a88ecc4ed8808db9f245cabdcf3da6fe0", + "0x5588ef96fb1e960284211b143bb5b5a1e431a015b5ae8aad1a86ba1b49fad459", + "0xce5cf0c647eadd6de376cfa52e4a3008bdc0ea3e09beef3be5e2369978bdadf2", + "0x2e55c31e3dec040cbf0f2bd0816bcf6d41ea29376b9958a40bd799c7c788d8d5", + "0x871c62991b05eaece3ac9fd843c62f6a635230d885b075df28f3421c64fafa55", + "0x36004f4df1cd2809aa89c4edfe3ce3df7a70c1cea1b99d906a64491f002b0374", + "0x91ce82776a39a4a32979f0df16d17c4ca0544e7086c90562c66868b588058106", + "0x23d8c25e9c94779c445bc7aa84ed86189617463e3a9e62dd974a23a29eada969", + "0x249e41cd4fd36f6bd6860286bd29945bb98cf66c0348f73b26bb4a28c3103a52", + "0xf158ef6bbe5a54a85f11c58e5c569dc927089ebb641c9d0f6a4641770e551cca", + "0x4e30a215bc185573c02cddf66c40a1c829b86dc639c2eca7e6a4026fd8a27933", + "0x15f0ad2cf92788cf0905aa6f8d092b1350e3f1530f1b06e07ffd8f37d9d867ee", + "0xe7d081057d6d3f5d85be6e28cff22e4f4e2c842d31599885f4e3f1c96049c101", + "0x342f966910c67104f934395a34ffddb97260920bd9043e2f1aace5062520ceee", + "0xd09b337b1ec7e7a3188b2a8981d14dfb89bed807807a6fc40a21ce82a3814b63", + "0x5bfcb62ce51ed31f94636e5e55a4fbbb8d63342818814d9167d690f96ebd9153", + "0x9f46f879a2b469812d61674250053eb01ff91b3d61b66ccffcf8b0566bb0ab0a", + "0x9e7c1698af64e08be4d5d2bc9262a7e0d2ddbab9b5c9499b505245869a1e791e", + "0xddc3dde6d397fdc437fc95bdc98b1bac052a1b4fb1bd81b90d18d63093bc0efc", + "0xb8180ff01aa196209573375a70c590e9ca8fb5eb94c921436c534fa57b93c802", + "0x795c03cb817afda30f993770ee0718774aaec6d0c9c01cb91ab2061539ab7349", + "0x45cbd728f2329f5bca7f7d188e64b9b307eabbd816365d0352e2ea661d923511", + "0xbc1e8acc0b620fe7c44f4d661950981e8388e3f8bbd58546157a1dc716d43414", + "0x4e796ee801061efacf4d84372f6daab14a98c3e91b569a0d580217442e1b821f", + "0xda432dc7a649547983d6ccba6ad31b7cf97ba3c7eebb5eab05f34561759e6090", + "0xd51b0632c736b3403bcc07399e9be4e40e04928ee4e63e87710002b066e462ff", + "0xa3076a6242b4e2e450f227294940d5aaef5b62ad68d63affc390f874958c0c0a", + "0xeed1d4e115039d92f2d82401aa631248a9c5b8de06bcf784adb918ff28d70bd2", + "0x6267b83c5d6acf41cbe965d1bbb8871228a060e46435a29c6a7ade18e44f3ce7", + "0xbe79880b453639b576dfc891353dcabbff3d16479ceb74ad2184a1dc89daadeb", + "0xd5356e5ff86c455718ddc8527750b69b3658c9746c0e47ac93291b039bc2db8a", + "0x079545539cfb2ab2b1d5341de50c6c71b8725cbf3a6ef168869d392c2e6f6ad5", + "0x0e3aaea1d36e3945580c3cd8e26456260a19ec0630476dc3ed444c517baaf5dd", + "0x28d6d2c1e9e4080e0bfdfa907f6d7c9f533cc477a729eb83ffd0f96f6d6f5018", + "0xebb8535debdfb417acf2c13e3ce6107d7e286cc573ec1c06ea28ef4cf3729c8c", + "0x96440ac46648fcf69de403e4c146dd1a37eecea957370f223753ec93f32298e3", + "0xca28ae763d5602c91d437349aebdb5cf9dbc89e6cfc53c124370b67e31fe8f9f", + "0xe27ba10642ff994e47ab1fc5a29ce071d80b82d6f584eaa56ac1a62a771eb21a", + "0x34e7db6c5ad2d646e6791b58ec4d429b8bfd69f76b1d9bf71f860b1faa4911ad", + "0x0b83663dee1daa173203e106ee4996ef147a9940f2318b912364bcfefcb07271", + "0xb164c1d879ad665dafe81929e0db557cf2c573f188cd86fe35ef24271cfd9b26", + "0x6587efc2bfa2ebd6da9816538e3abc5f03c75b5bc425f7e5e9c676f97b1449ff", + "0x668316bbac3e4cfd0c4fee48957d9c8fda962bc556c5ca35246b88b6c43fe291", + "0x264917f66c2d927b7f632744f9dd7b844514af80bf3729f30832b222410a08aa", + "0x38b162eecc129bb2e1c82e65d785e84b5a4a9822bf1e6506492a25b082309bf6", + "0xeaa3ee39cfaed2aca6c1560608bc1a2ae32805812d792471c9c6a9ebc80aabe2", + "0xd7738ea58e4319f98250874c16bc4ba12f2362a8f09a7158ca4e2ecacd954d99", + "0xd26d6e2dd1b62f7086673cf153c3249b15c652a7bd43a4ef7b796dcc2bc44a96", + "0x11a9a4f1f8d10712e79a219eac2fc81b3360c60aaa9bf179e720ec04d69956ec", + "0x6ea3422e40bbd52abd6660d9ee8ff351ccc61d997082e470197a474509ae1383", + "0x1ab854452eb96365cc3ab33c6c45b296864ee61b3a477716dd9eb715529787b6", + "0xeecb8949e3be53db9ab660c71d1bf702d8e919ae6487812181858992e7668c8b", + "0x2a2ee4c33009656e5e38e44a7314c40254639bd46e32cb09eb1b9643d92f9ffb", + "0xa14c5b1993fb968f7e1dfe4ad24716e8d9a5be662cb0af13f43e174e0bc2c5b6", + "0xd5603250b1933ef1cd1b27932627f27599f81ca29c9f02e3627eb621f613c935", + "0xcca950815341af147085a53b4108ce368db1a634f204ad75f3c687b5b7ea3985", + "0xe14e1ce237fe627e8047d5d8f8153157ff1ff3d2650e0e2ba870ece940421470", + "0xfe2bd09d81d1525b996c67fb8407636e06723b4327803a106c19ee60a4a960ce", + "0x995cd4b1f16450b64098fda2e678b14833a3b382f76e14cea71a0d297ade2080", + "0xefbf5dfa769a1e6132741600fa9459b8a1d11b11c3b2563b22c79cddb34b2ff3", + "0x1618c918d173a9af0daf3af314d576a6419456636a46e2c6b8126f2365d627ec", + "0x3b9a773b1c0e16037a429ab42fa3883803f320beb9a34c8e36c80b2b7b814331", + "0xbe3b816b72cc63cdb63e2897064965c1b4e9cbca1ae26c770a20508be1d9695a", + "0xc57f2c5ff8087d6cc2039910f00323a90a0bdc3d2164e0f52bbfa920d62a15a0", + "0x0f11a1d5bf509afb2694bc08584718bb93288355a7bf0f801e478eeb9ef52da2", + "0x829bcd6a2392c957300253f7e9abcba7513908d3013a74387e918dc57053c035", + "0xae4d9d51eabed53e9ba4dcfecfc449bc165b3bd40d87830fe044811f4056580d", + "0x2a8a21d59547009a533695b5808d928992547937478ff9a61fa4388e9afc1147", + "0xcca2ff6985f20f7d1633c35447f45a5b27fd5a93802688e2afe494a2c350917f", + "0x2b8a2080fdcdafddc5d94292ab4fde01d91e7ad2c1b5b5a2f04dca9a729c3778", + "0x211074e33dcaf13183115f89252435b4efd8e1f01c38ed484ca69c14bac72eaf", + "0x5de84a9ddb48a4e2134be8cdd5c274471055234d428daaa1039ae2500e59ebd3", + "0x3f71bb8768f5c8d0db2ec8360278279f4382f3a50a939842d80be98685c536df", + "0xd26b7cf7c6f987f4975010eb9e77becf7c0c93ace9eb53d289beab868ab5c93b", + "0x889d8c294f942cc322a197b4f746c688a15e1692cad0d2d9fa9a125f4998a6d8", + "0x7a0c807c41e209d12128445df83dc1931d5a24923b38d259a7bb9e8e4459db43", + "0x564e904caabec0630b52e056ef9ac08a2fd276ec99d81644bf38dc0b09eaf820", + "0xd5804d2547786f7d26282726d3f9f22e53e0ee2390ff0de8b97c33a4e4237535", + "0x5999f87486f0c721b038c659831c836980a2f7ee9c887c759710d62691588670", + "0x9fa08ce53c180bb53d5352dbb2312603a0c3a5087cb32f81bcff368c457a498b", + "0xb1279296a8cef2e6b80117a48db7291169ad35b39140debe3ee71465b2a93f85", + "0xd3ca8ebe2a6ce6db208b4bf1853b8625e8b12f7792df1ece14f696d1694addbc", + "0x7fea211ff413b60098ababd9e3077f58325ec14d9fe23bbb1cea0025d95896dc", + "0x270f61667793c26f67cbae50931919b8370c0b395704640837d66aba90a393b3", + "0xe81214151eae79a310d5bd8fbee6358a3d897b2b9ed1282337b71a653db17384", + "0x5f2928cf34dc3da9a559ab89d7496510b3c2b5d00d8de730b6df083d03103abd", + "0x619e0c1627f0802d660f1b06bb55c39c0b570514e71c69d5de41232fc6bca961", + "0xc8384233eaacb714f29163a0a9b507b9c9d0ad537dd64c25bce91cec6fa6c2c9", + "0x54c2e035312faaff2fd08fea36df91f2add2ce39298a1987f4286f3592405e8d", + "0x32bd9a7d486a43926319510505b5018b9ae951f4ff0837f8b9058e93bc303876", + "0x6df5062af0c06aed44dc45026fd74a287e15f5a60f122e49343e5a1d10e5f371", + "0x6b3ffbe23bec6a576dcac6756375e6420123ef1eb39750aa6fdce9d874ab790b", + "0xcdd08aecaa642133a9b93ef888c5a808cb2c84c48943e7ffb6d531dfc1c6c205", + "0x563f9e429bcfdaca1ec2ee7007f286b1b3e4358b76d12d94015d9989dd50b2da", + "0xd3a709568bc87059c1a11909396d655c2f107c999bd75ff5104449f53d590f99", + "0xaadf85b25fd426d50f3a22404616141211dbe541eb116b71c6ad960fa453e172", + "0xc411d65a0dd44d5725a401d4a479f9b5aec10334938bbec7ec216572bddd84fb", + "0x4ba49c0fcf4dc7858eb6b77c942b528a349ad39859a2a1f8995593f04ae8cb2e", + "0x17f327906a7bcee96532e912374523b88f474beca4e40661113121ea626a209f", + "0xb0fce9690ee2a2cd55a0e088c0e96fa0e922b4119df230d4b903c4b18cd6da7d", + "0xf7070d16a82595a5782717429dc6d00b1f8abf6778db1836a23954cf66bcdac9", + "0xceae3600d842c5d03611dcdfd0a0231e469c65b151e247b2205cba2916324707", + "0x6d1e0d4ef9387d070ccfb68f0866937d44ffe7d9c4059a21bbb4b0c87b7a6461", + "0xa7c125405cda699de778318152df327cfe79cfbd999c5cc45db15bfed216b146", + "0x5d90e851ff50eff60b8c92d63274c9f9b5efec6efec3c2a412b003693ff014c6", + "0x03efe16b91c66ac58204c952a9cd24818ca61fc6b1ce4d81a31263a7c045aabb", + "0xfe9324d99b23bd0502d6c1020564a850c932a0d010593e1894ae21641ac5c248", + "0x969138be8e3cf0bf9bd0963d2cc6467d8690fc40797bb2c2950de0df1a8329bd", + "0xdefc0e0c25782165aeca15723fb74d95d96d1ed7420be7f3c85ce7cf7440322e", + "0x0bf69f52b595f75df550078e4293602593e3bc2d7ac528b7be44f556435d9e42", + "0x142f2883383cb22f5aa8e863756bcdd154ff3ed8a02d5cde8fc1572db65003bf", + "0x0fc8980e2ce7498656aa9012eff375b6b32216a3142fb974c357a553bc9b248d", + "0x2714b77d484d7639adb40e1158734058dc02dc761c7349c4f3818c70347b348d", + "0xaac5d4ca615ede62571ea4150e4c01cf31dc410b06d5b443267117197e60478a", + "0xcf9f45357d06955730a934d2de24b859d39ac0ac40c8b29430ffe061e3bbe4e7", + "0x52330a846f5d2fbfc26c48a5a95c9d2e3c88a654ee8f5fcb7f9eeed39b2eeb17", + "0x807c2b8bbeec7e6d43bb781f2d7405f9389cef647751c1fd30fccde0f004aaaa", + "0x8cceb13ddcdb1b080075083091120c394a94d6f8f00a2eb4c4498a3b1a7d2f5e", + "0xef770e4d62f2912430987ad5ea59974aae40a81771295fa1380e417b3df88562", + "0x92cefcd22fbf95dbfa766e7c49a4e211596cc6d997976b04efd818ba8ab49bd9", + "0x809d91cdc51f42438312ae27ea1fa94fea4bcb2c9341c274ea18513ba20ec931", + "0x10538534fabee44df110346114f62797a31cf363d4979f881b721043b2250e82", + "0xe252558398e892e85351274a5064fff650f0323f38b0a4456b14a435c9a40d82", + "0x7d313335d362826f589dae0164a04ea681cfcd54f10d8e339ad1978ee63d7045", + "0x713414b22fd3719c42775449895089e6122064b90258a1b495704fbc4677d92c", + "0x748b6883462e9706a8fcab3b0c71272fb0bedac622144d5d81fe710562b8dedd", + "0x2945d4809258eba164089c2a5605a7c9e72759bf615bdce0aacf96ceb7d6ec12", + "0xfd89a991d0e20bc05d484b9cab61d27a0406fa741e0be6c8c1c2655d1310cdf6", + "0xaa296f6295ade70466ed9c185480e186596f2183947f65bd04fb5644dec93d33", + "0x5286efb4ae287693b85bb3eb47ac0b697ceb72ed6331aaaa521d58ad7dcd7974", + "0x6b3a5802ba251becdf8ba2508a6fb1d3db0b5b99646465b12844b8bc23f062fe", + "0xfbeff1e7cea22e0563407d57d9b16518a0355b676c48605adfb13945d7bb2f60", + "0x7c0764932e56518167f4ee45d912c1a7c78f30271b41ee16038f358d9865258b", + "0xfcb998af040eb99c3393b165dbc904a197341fb7dec2d8430346b7772935dfd0", + "0xe46aec72c95d0accef6ebf564e9264de932458fc1143570ddc28eef3801430c0", + "0x08f97afe124dfb2a18c6c624d9d1bac4cdb5dd102da6bec9c676e7fa000a43fb", + "0x50a62c4cd65e3591651f8fa56831ddb37ff966cba87c12d83708aba72591a060", + "0x1abe248da61411aa6b6801dc188e3f834c3fc4600ccef36ad9d7bc517441a61d", + "0x07e38e7dee4062c20f4b3f221df72590c0838619617e051243087250defd0028", + "0xbab90921cb56563d69347a4197b869a8c8bc34d01d753b509eeb5895e77eac81", + "0x620404dca85a89624483cdd7e2b143b12a38b737c0eb783f5e4b378fa1d578e9", + "0xd70f44dbb657c8fcdb90bcc24a47485fdc99c35ce746d8eb2302d529be43bdf0", + "0x425c47cba9cde3b337c451eb7828b0789a76bdbe1f86757292e7c3768cc51b6f", + "0x11b521b56aecb173dff0358678298ac7f55015dd8b217d81dfe52129d03b54b7", + "0x98ef31c7277a68ba0a2a2809f8e7b4099c0e50cd47ab030f5e1c3ea38b92d39e", + "0x82ae5ef4f71c43cc296f1f6279eddc71766102997b0534ca737c0c1a63b0b3cf", + "0x44e2f38922e64f0aaf27607673724e5c91ed5a8176899e935c73c0fc09826355", + "0xa0361b8e3d7709c4a68ff24623856c54d16ead1762578eb562c295f86f453b14", + "0x91726ead73260dcf30eb478615968be91e4e2b6aee522ff6d814bae4aa595c64", + "0x8afe8954bd7cf7a6c40e3903015830f516ecb1a98c1b028b6799e1605892b49c", + "0x142bfadd2c9e988cb07d36bab795231b9582fe424a62de129a24fac85fc47b88", + "0xe369b5c6a44aa592c1d2c55a6fb9e2a0ec3274be74fea84d2e05451db7ff9b8c", + "0x10030041949c30aed18afceb0b6ba1b9bf58c338e275ae6ed9f2dead02a1b6d1", + "0x993fb9325d7be082347cf9361f665efd4d38466de4234233f272b1c09854657a", + "0xe2cdddac0a6984c0ed9d4232d8b58bc2c61e404c3e60b58b90b5876640e8e19d", + "0x4adb2f59c6704b8be33a046a07d2585328465dc1b45a41bf30fba1ebf6b2f7a4", + "0x2c47e906f61c60bbe994a54e3d0a68ba8dfb519928cf350b6cf8421e5c1779f2", + "0x4b712c7fc97f4784b2f562ffad648d29884ce68c505644e2eb4195fc43c00d9a", + "0xcc0fd5276fae744a1ebf274df70eeefbf301ca7e3d1bdd6cbaf425fe0d400758", + "0x0d3e81f37d9d96efad22ded24f6cb7174606c3b2d294259f37e4f754b28fa2e1", + "0xf80aae34aff371a9911fefdcae1289c126c5876b3e4d2477784196a4ed6dc156", + "0x916469d84a13c2971d02ceb166dbe0c9cdaa88c23e57772cd3c260db7d2f9ea0", + "0x37a5b98e5934c2bf16b048f76c06b4ab17945c1f549a20b76ecbf99ac99c3698", + "0x1dcff6c4816141355ac06f9e31a73f31e4b1cd947de42a078eb60ae828d5cf58", + "0x099bbbaa5915dcbc3f975ef1ee1e5da2bf248e96e87856323151a08dee9b5e7d", + "0xd0f2f3478ed51f2454d21cb838b89a3569b3b2704af4d702526af646b42dfbfb", + "0xd906aac9b70f76522bdaff3840df5d9714d352c8a632f44e52370786ab631167", + "0x7f99f6d3add64e2381d7ddbdee1306e6f6749ce116642f993bc4c06970295663", + "0x58988b3a6a1437814e0057b08ce6e86f58cef845f8df78a6ec563d056592b81f", + "0x7476333d9709b4295a63b55e1d5eeb7c23a752c4211bc8696016b70a4c13dadf", + "0xcbe4bdbaa8e34a22b883371b21d5e7cd474368ef0df5ccfeea3edcb377e071ac", + "0xffc358eec58c4c6cc0031562809154edc13b9aa091674e473304682dcc4c2c1e", + "0x9dadda32c544767bd65dce5804a695b8e5c35d2f96c203c350001e5be78c044a", + "0xce2a6bb7c0bceedce3111d97294b8672d0f6ae8eb537ea785398fdf06d6ca2a8", + "0x5ed79a31acc649619c09c9b5df4d595c806a02e93e92c4fdbe882899832f3cff", + "0xb3e94be6cf733ad114b1c1fe76565c448faa9f14131b30aa79aa36a0edc615c8", + "0xeb33e3a43cc5068b611f7a95fef45d5a83d0219906515a9ff02e31c0f1aa4e39", + "0x63a2f545af614f075469aa9f8d4e49fcac12336722936def26c0a4cd01a31b6c", + "0xa6d5ba412c63ff5903e2f30bdf2d1e93118514a8c82b532fda0259b5c3c21986", + "0xd170edc5d55910ee2671397a9b04890faf8b4a3aed0e98852d5732af897989d5", + "0x508e7b9e80ea2fee221ee8a527ded1d480d6bda70d7fcc2d8d521e35c184deec", + "0xeb07494e1b639b09c49b145d51ecb9c2f8b98ea596779d1a14a71e2eed22975d", + "0x50b37a16f4233ba9287fcda52030e2a7d92db254746bc42f7358c9fa0d4e3116", + "0x447b12ecbd02d12bc80c990d632cc2032b72a441b418b74dcbcf3a76ad8d69a0", + "0xdfa6b21b930c94454ae6845041fb6f4e345a11440077c905b4f3386bf4824ecf", + "0x7eab803353df60fa522a5c1c7d155939e1059ce4d6c83d7e4e3ca756bd0fd9d0", + "0x25a35bba3fb585339e9c9df30a10246774a72f47e99fc329d64d36c67df4fa59", + "0x17ca37df7ec4f94f41dfa272553fd5dd3d641a986fa5a9dbb262fc395dac8ea2", + "0x766bb71133abdf384d8c24aac3f663f858bc8283817ec2dc082bb008739eeb37", + "0x5748e015a55f336461f5b1c4bfc80e5d76dcd9bb3c72d583cb7e585c35d67111", + "0x39909825449948d25a7f9346dd07d83f087e50c82e9fe9b9d474c10eb7bab0ea", + "0x441bf9c03a11ecb3b0472fcbed6aff62ce1c44b237c3357a4c3f5e8ca190dba7", + "0xa0456b6f725f0c4cd0917cc463ad42e8d7ac9496cb0c34f067b691d89dc1f2dd", + "0x6571a9b298c2180c91a8436c7ed81da8a69cde6c1a20c78f8327e9cb7bf9d929", + "0x152f3642af6d21630770d739d3f86b5a0a8b8ae5806be4e1b568499349d36882", + "0xa7dad74a9ed1bde34b6cb0baa940b7d565afb8dd6c4e2bb7fabcc30673f255b5", + "0xaa829dc659ea777c2d84851ca7eeaf8fa1e1409df8ec151ff9d9a87bbc8cd848", + "0xf70ff1f39678b75cd7e9c7cf7de35bab6d54997cce23b769ae452cbaf13db690", + "0x2ebfa2e52ab6f68c8b7f2a8d656c1fd997df4cb680ab4106cacbc50c4f1beec7", + "0xdcc2ac91b7ba5294b3de1eb7db158cfa53db057a4956d403732be9aee6899fbb", + "0x65dd99a245b52befb5099b69afa332a9a529bdb5c3b57dedb3fee52bc11ec426", + "0x83f08c95ecaee8710f687b9ef06fdae143fb7581ff1498bce187acdcc1af566e", + "0xffd22fe4049110b55b117b38f5ea4c268737db4fe92b9b5fe691630b39092dfc", + "0x7b4dbfce2925a674b0de23746b226bd901b7aa49140e400af6209e9877d11617", + "0x8c8d8762e05effacf2e70742f9c563458065f7a0abcf9cb6d6f605450aef08bd", + "0xb97df188cf546690574e316b144c8db55c7fee2d241ebfdba1424739b96a4197", + "0x83cb74821c0295a9d11e4be54cb7f2fd4fdcdeecf9a61a3cf7d168338194342e", + "0xc05d2a626a448cd6b89824fc6ceca1b2295361d7e94ce86005f7d527a0bbf10c", + "0xd0fb8122dfe38416a100bbf00ec04cfb14526296e746da85dc4487f2c7597efd", + "0xdef0c26f8ac9f6704a016635dc46386a95e014a8637733f054cbe87e59e0089b", + "0x084e741565cde3ad7fb2c60e0cb1244b1f8f6b87b210993abf2959fd380127c5", + "0x7986d8c793b5bcf0977260c761f5ab4af1d0bdec8a5dc49230f63258f6a0f403", + "0x584a5726cfe9772deb22093a30ff2b9b30ebc018cf861b8aa0fb28bed97ee0ed", + "0xf046b4649898fbdce79870896dbc2752050b5f654faeff320ed2184c7bab659e", + "0x744c1495610301a14d82e49dafbfce8c70f7f78bc0679f2c6fb964a476fcbecf", + "0x4edf5a73306621d2c4966d4aa6cb2935cd9484f1f0ba709ed5d5b91160a5de2c", + "0xb5faa128c00d7f97a3e5204995065e99aebc76706e2e96ccf4b37d7641690045", + "0x729bbb468965401fbb0f2ad1ba0b8ffc7072f9b18ef63e95f47cd98285b89854", + "0x0550d90dc0f6e8d2017e14324d404ec8a200c45ab4a17ac24cb17ca9b68881c2", + "0xdbc02a7ebd9bf74121fa2b4b05c1abf4bdf00a973b43e27faefd095d6cf80390", + "0xabd6ef9629eaafe2d8170d511a39ea29c30d9ca0f071d5ea0b80fcbaffbebabd", + "0xa9dad7abbf1bdbc32d229a67dac65cb5a14cb0e25e8dc57ef7538122471909fb", + "0xd1e063a59f032a9e0ccd9b926bcd6639e197fce15e28dc6b1bb1a4aae5862e75", + "0xe3187db1ce4e4faf95ae3b2136c34ec2ecf028e4054995fa59aacb94d0e16d75", + "0x4aaff2417ccb6bb6be1e3bb759f745053a3d45ce144db0fb627edd9900000276", + "0x3b108aeee36e6fef8d74ec08c937143facb90cfa5616ab7af6d37c00b3a4f1b1", + "0x1ad317c91fcc12235526ed9d6a45c3854f2fd421ce36a2d475fdf92d8afcb524", + "0xe39f66c3ab33ddb0d1fb51b969bacda7ce0f0f53af7012dcd4530435666b7dae", + "0xe071c158a9c418c34270cf27035afb0896251616ebbc57e7e5a2fbd503cb30c2", + "0x41dae0f056d18719bb5568f0893fae512f623e16effae772d35398da2bd8931f", + "0x426b1e3b67fb576cca9a180523ef9979aaf4d14649637f69347ad3876bdb6fee", + "0x2678a16324ded3abcc20b8545ad9a4155184e63b12d1d3a1959fc9d08dda781c", + "0x3f18f5def267a73abf0543135da57d752c57e4344ea941199055a38a46758ae3", + "0x031b50935a859999c1de5b772eb4363615388dbb9d12bfa6ca72111a069052a2", + "0x57bfecf554524f9dee811f59e9ddb287b04338323e4932c44b208913611533ea", + "0x870b1bf5feb1bb5297f34a80b058c81db9c97cb79609c537641f02753f665b68", + "0x3bcadf9d3dba81c74a178f533c75f1e77c64baa6ae274bd25a0cee762da43a26", + "0x38cb775e5437c113ad72ee04f0721390b7b8fdec2efd0eeae24d22cfd3f0abb0", + "0xc6b545762e567ad0fb73b49e3af783035e77e252f5f26fb56c39f2ba280e4937", + "0x922ba1cbae3ae6beb2e01ce1ac2b3a73383aeda9cd3825cdc6206d04fa04cbf4", + "0x9e5899be114b856b51e0de7a25cc1c5c6247fd2c06f0381d5cedb2c26c2081e4", + "0xc7c57fa4cfd2f5d2df0bbca134f48d152d8e284f1c0d946fcab4fdfde9235b22", + "0xf35e4daf46b5b181b6c6adb53f5d2f93acc93b76b422ad82ad996fcf95d5a942", + "0x0cf08cbe8ab573727328f5e5809baba6b8620536053d023dddbb9cc310df3246", + "0x6ab0f99c1cb99bd763af36647d29d6caafafa4aa119ec34527999f992de25104", + "0xa8aabd97d98e4a657980b581b26abbc9280a288301c33c45961f5e35303c31fd", + "0x3c92814886acb8f2af1342904d0b2688be4f269a24849507ffc0a7fd0d67584d", + "0x582781b1bfd4cd4d619ee98db64eed9a11c0562565fedb6613accc03670dc376", + "0x832c0574c81bc58cadbedff928fd08fcf1b4c80d7b323670bf67a29e312f4151", + "0x932b7bd4b919fdd18acaad39228563d65d19da6c7e8737f9c34fa3d58a57c7fe", + "0x153059b97cc89de7bdf0171150670085b850a63125d3e51525bba6765be313b0", + "0xba341526b613c0f3927d604bac37232dcd5ac104bf256720c62ed14ab05370a4", + "0x2b015d7a5486e2023aa93a00261be3ab97d38a1e7e1b14d8878e6c109d28ba51", + "0x554e29e53bd94dfe253d703050d8f54c703a009b412232847fe01e1b138f64db", + "0xfc603400b18e2570276dd994aa168b7ebf2fa9c8a3d7f4edcc8bd6bf5c008109", + "0x66e1cb6677eb595cad35fd028a36aa416f698b6366c73d179b8bd451b0dc3ce2", + "0x9219571b2c2860cfd4bf49b92439dd76304c2b5b2542f036392566b2b431db86", + "0x84c510b2dcbadb5562a66a1312b6016a4d6fdba205b5ee698978f2570fa191a7", + "0x483e7d9599fe6da557b4f5e35bc66b9d4bbaee82e2bcf29aa245c4aa679918e8", + "0x84dddf3ab9a135de68eb188476c23d1460c45c377e9a62c14015b2fcae515d94", + "0xe03b4b8470073abefcb0d4db364624116a046e85be9a28a52bd6fa5b4d2264a9", + "0x342a467e79121dae9c3d203615f772383d1e700fb05ff8ccb5a48961b423ec9e", + "0x025c53fc663b8cb0bae6a439bc0d4f3996618926337bd80797510b67000c6f94", + "0x0ebcae3ede50801c88b517af406fec7a3922b4876f28b3096425d4dec3f2ec1c", + "0xff78e7b509fbac13400ebbb8955bfadc0f35a4b568549dae44b55d15bdcf2a9f", + "0xe19e3bb2648377f25d4a190fc44b14e80b3e2c8dd17427fdcf50451af8b5a8b9", + "0x50ad2c5b2732b7f2c34fc0e2e103884effb23f7672a5290c7a3ee7f7c4609fd7", + "0xe5a000a849f39efb9bfa550d959e86d2d0d92b6f4034a3e75a84a4bcd34b647a", + "0x56fe17466ab440baaa576898ffb22735f4fb680db4ccb9a7dc6f19a060fe81e0", + "0x1ba71ed6a71d823c35464cafd2f4b35a047de73666f0bddc272398d1758b4aa0", + "0x801ac73a07eb37ee08ec538f723dcf2c41ba8f0f0e553c740a73c1b486b29567", + "0x732703b2b96778d10970cd6f90634e8e383d41f3b863c424a71aacdf3d567ef0", + "0x5295a9cea073059a0c806b5d84e95dd449bd15e081ec1543f04709737e12665a", + "0x25aa778a07dfa614a7554d7b00ed9c5360e1bda16df694279d45fb4c0a4ce11f", + "0x3a9e9b5dcda51fd92f8dbd18caa817f53f096f3b66f953a1f731adf41577eef9", + "0x554d4c03a8f7f4b16bee2ecc809a4a03b3e6bec0b0dfeffb45acbeac698241cf", + "0x567f2220013d4694394b054b9f93fd33f9b24d165ec92eb86eb216f2658a35a6", + "0xfec8e9f64cbf08d5dd3e19ecf7e685ac89e8430221f05166f84eed16e6e42935", + "0x1398f794bb66f9bb26eb2a17b32bcff6c6c8796df52e7a5f8c2b58a94e2d8912", + "0xd32d51d30aa51d571b89bea7eadbb3d32792c5971832880053e6da18a6644f77", + "0x753244cb3d3813f9a59b396fff82253ecafa836b37dd4f4572d2ae033142436c", + "0x74077018c89bbebdba21b096ddeb988a40943985fd479a4a95b172d6d89b3f12", + "0x20ca619770c23b5522ee50b629697763767a61f17652ae06f3f30bef7f300605", + "0xbe0de8f6eef387c01546944519c3bd9761c69bce0e9620d9995dfd4dc66e10ec", + "0x101bc2c69d14c170de6b3ecab9208f68b7b1b8ff0001a400f7373b77454113a7", + "0x8cf7437d2474278b2646a71baf196c21994f640e9baf0be059d820f57e0c66cc", + "0xc5751a0d6f9f5b859382b9840127d837a015a7b33d0a775e935ac2f2e57b1488", + "0xbabcfa88c03ae1d413a6165c7dfbf204d5511999a4fc74ea33a694aabb55e054", + "0x66b70f7c56c40e818fb1cb842a13be3e44d864d9ac5f1a4336dd00330685cb80", + "0x790a401845ed04ea517fe4721da3cda115adba8cbd28775e8fdc9bbe7a5bc670", + "0x2696bb11d905914f93ed07d71b99a6a4f2e90aa7bd5eca5e32275bd4870ac95d", + "0x5aea5a8a2b8586491f85ba8a387e6a6cfe8970c5f47a77f517afafef9a009fc1", + "0x7ccf035e2483a2dfdf068c0cbba769d25e21347dbb40302dd2a5c396cc082237", + "0xc7cfd5568e4d9769465645a1726b4889656c99befb7aa02a5b8ef8daaa8b03b4", + "0x5d5436654bf6c9b428c8ad12645ea5d5fe95aeb5e639ec46d4324dd54b0e7e8f", + "0x82f4a8a018dffaa850312b375503a6325562e75786393810a383498e71dc2c6c", + "0xcb82be0f881fb2794314fc3e2cfdd57ea5e12fa7105a824ed033615c4ae22f34", + "0xefe0e3f97c4e6b5be518d58f398ded35421d54c33e0c93e3ca0b527ca50e927b", + "0xe6ebb787f18f2d0d042eec05f2886020262ac20f3c14e8c03885e04136028823", + "0x1e41e40d2da6017775457223d1cdfb06bf41762b8bf47040357592315f627dea", + "0xada6d7bcc5013069b5d0676df3b067110db631d07020104a556b61423a26d3b3", + "0x8e0840f9e38908e49fd12635be7735c7293833c65929d5aeb5035d45942301d0", + "0xb01ea85a249d3c640f5e2ae43b340a5f0455350719b13cc8bf1a50c8941a8ad3", + "0x4e5524cca029a2729d27a3d2a712979f35e07cf9d436ca7dfc8c414eaf5d5a52", + "0x72208f2a837b1fe9e7445a72f7d57e414db9e0bd87f7e5daa8de14752a2a87c2", + "0xfcf05de95385cee5449c1ffc63cff009b585ea5896b2ad96d43e747bed4aec71", + "0xb9ba0e212f4dc38e5a0c2b62bd0c1bda73459e72233ea38cae8f4a91f0a6d764", + "0xa8946ec7aef9ee1402442e7cfb4363df529b915c96698110ec1e3c15d445299d", + "0x07349344fc0ac74be9acd9f616a08b3d1bcfbb08c2f95d079c235f52a0322fcc", + "0x223fbcf9b3a552057f728cc0e4dd283176735668beabba942f62006a902249b3", + "0x0e28903b5f5db741536eaff97cca54fb98357ffa69b84bbe365312d77374e47e", + "0x6588620c06642d029a1f8dc0b95a14c198b7af2648acdf1c8d73c80d87cdfda6", + "0x021f66c28e1fc7678af4f05726d8670bd88a143e749a96edcf7cf8239607e9f3", + "0x339ca9feebab8de1672036fe85ef63bb591f5466da074793436a07919a7740d5", + "0xee504bd35830555e345301e108b4ee3698c9a0739a8d4210ac975f1aebdfb944", + "0x61a020081cf4fd487b0e9b694465b94016d461897d4e18990e2d34a26e6a6541", + "0x539ed46b92da9b97e94f0bb089b034af3e6c85b9812f5ac18b64026906ef4f33", + "0xd244eaa108e905c9160cba9f75b3d4f46e428749c0a2de7b165e95992e63caf5", + "0xd88315191813c72230222f636d5de64bf5ed7bbeefd574b1d0c2fa61e16d5919", + "0xd428f280ca6b4ba0ff8bdc58a1b5c8ca5991f9d2dcb8522b17b3c09647a9c8a4", + "0x0744cac8522e0366aa470de75f1dc92e307f82e2e300fac1f8adb359e7f5d9ef", + "0x6e504ac6d3e63679f9db61c3e37bc9416d687156354d1fe82f7f434c4e43708a", + "0x34a5c50161a9b06229234a23f210458cf64fbb5531298735826599bc46179e87", + "0x03a94978bc793490395c9cbbae9fba0f7a725f5de2737e65f7e4f55763631585", + "0x183f981a62d19c3a4edc055aba9d04e642f89f203381a4e63ed7496ba7a1074c", + "0xae5492ed7758112e7fd6c21582df31dfe0b1d6b3fcece4d2e8bcb7d5bf56a00d", + "0x8f5062a00e823791785fac6c0eb7c1aa732a70cb1fdd23d4336b2323a99d9f5e", + "0x74584b0ad5236526dc1a4dce8f4e65f87ba3d529749a702217f46ac9a6acef7d", + "0x06f7debcf4fa4511a1182d992fb0ee265714e70354a08fd496f2550a9e268b70", + "0x8a6b101b16aefa233c158e0392f0897efea6b4144a98ab3050551f8f530ffc94", + "0xc65d3267fb49c21636e1cee8d39c515b9028058e8b9e0ec5c2d6e7adc9293e45", + "0xb9286dcd79def251104af4f3b68de8b9e5717ad5275665b6c079f49afab7770d", + "0xfa735c22373482f2017aea5547def3bbe6f0b8f08b7054b775dcd04c3a3b8597", + "0xe3d360213b5720573864c6a1d9204151491bad4235e56c35b340b22e8c29f5c4", + "0x87ee0e69a5db0bf2dcf753e2e1dccb92725f9d1d597aae378743038121071b9b", + "0xda446379789bac65f03bc0d2bddf4da37867069743ddbc4f2e846c90db8ab568", + "0x553465cc2c0ab7fca15424c8507d216d95f53a25e053657fd8eaad58efd45346", + "0xd3eda9aac5e84aa9cb845cbbaa180854868f497fb79c5053becd16f6d9ff13a2", + "0xf8bff7af9e6fc79a875bd7cc4c1a0a347572c5f83c8a6864313e5f182a8bcd96", + "0x3d49c1fc6ca0f9eef57064a5c125c24464d1ae6f29989f2e7f4942c50128f31c", + "0xfa78f4fff3ce4c2b34935ec5692b9bb0f326a65ec6b14299f990e697ceb89a34", + "0xd7de5c5c86a0ada9f328e8b67393f4002714c5d5f0d1ff68129c68b882d5c6d3", + "0x89f2fb3dc33363365ce597c0e5c4d14c0f66b60a8c6ae3f6d45d72af301cef4b", + "0x218c78843492895ae5ab088ed80e82eed320cb6f98595a211340b19428d94985", + "0x5380a88382839684d7d9fc7047eca486ec0383966b262e5e46b9aa0859ec1547", + "0x19cc514f0518b3cedbe31529f8506fe60c93122cc7da49ac6f855abdbb729e9d", + "0x93e2d29e5c272ba8dd20f621132c60ddeea7779309a4d14fde6e6d58b0643f98", + "0x3158d8140bea277184329a7f2f2bd7e956725dc80573ccb169c40bfdcf3f2c70", + "0x7505475407491f5a4619a25b97b1d5cc1e1ba38764be61b694b6c1d3ca51c216", + "0x40c556618336fdf46e581183b7e57a2f6e2665d8adf0d44b39d9a5150a56a13c", + "0xe8d0da5275d1280e0906d62421bd64a3397b5fade799a701e0a37111d13602f9", + "0x28fc4cfdd74093fc78d100681b770d7aead4d57552c9366d56bee6e7776653ce", + "0x81eb57db158fe3ae4e62785ab8a5c4fa07bf5a7815f1dcbe25bb997b89392691", + "0x361a76dda932befd901f101507a238fe1dd43ab563d09e5e3c6ca43e6de48f19", + "0x9931f8e7444209b91572ff581bee13380706e6d6de933ad96f185f71eeb1ca9f", + "0xf9b544a3c3090c494eda2657a527288e48b5f4c9032ed26eba3dcc6558508d79", + "0x16936de0caabfbe2e395583091c3b90305cd1fa734a5ecacc8db0ba8c40fa89b", + "0x998492ec7efc0178ad691288e36758800b139a26aa493bef28f2e96c460be402", + "0x626f93a0163fffb94c1cf227e6a0ef125f7930f3a21971dd3a9d443162a0b176", + "0x64a7ed78b519d1f04b5b3b46c6804c0647889475d4fe991c8a7e405a4a2334f8", + "0x4aedeb8f7470b9c97c2fec75b4c44252a855d36b73c6a4550d15368dbee9d0c2", + "0x17095f0fb67a7d24910c086ad4cac72e493bd7276afef463d05e26fec1f39381", + "0x05b5fc483f428f6c854403b365ad11f4cb170a2229ec66ba671b94ed50686858", + "0x76bd14300b8f845500b2991e8a78df8dca3054016ef6b5069b77ef05b806caab", + "0x718aafdcb0223d7010c9b6c012c38aaf82e02c8737488bace9a7f8db15c60047", + "0xeedb09efda45baaa9034a18259f1aae1275a86fc81a218d9982e0b17f8d743fe", + "0x2608c1d2f2f8513ff1ac6e33d21659624c16e00218f984ce971eb9bee4825101", + "0xa5331637e8221d95d318cd4f32d5d37698731f569c4879c151086974e2cd4e95", + "0x2f9faaf3d219ae56a94fb4ab12f940d63a1d86776aef6541d40ed63d03d44682", + "0xd91d881ed4fd4b6197d77713d2c42758d9e550343ab67fd761c7c3e7a3724fe5", + "0x2404c00a40e6d67254ded0ff5a5413776351b8587ab1fdc4cde74c316435a9df", + "0x8591c719906e31c2150ff3183382f665f756c9a324ed470d0916deaddc240edf", + "0x8d670ef59f2237573019bb60cceb14f7198698773b572f6acfe3d3bad6c33d3a", + "0x3631004b8ebaff324494cc7320bb3c0deca53480a21d2d7fdd516271af7c97ab", + "0x4dc37b8650d5e49ab1a87a9e88912a98a60099cdcfc33a5c21627f0bb05ff124", + "0x95a8b189f6335a7d1523c470aedd2fd41f66043019da9a1ea46b379372ad4d6b", + "0x7219f1318a197b919a83dd51417803c752c24dc3a005cd08c091b0339634e806", + "0x81d850ed79388dd32265463d5283b02b11f012e08eddddfe389d55790cd1ff52", + "0xe170a7511431b18ed7330446569a253047f4fd0653915e107104380ac40affb3", + "0x9c38e78c1851edfe159971a455a70e1d61b1ae71ea0cf828ef40d4166741fad4", + "0x1ee49fd6dc9fc4f6e8bdee61a3e010a0eb9d06597c256200538ec73580c42bec", + "0xc0e415e7a108c241fe301e6ac22c81738470b499aa65317fb9344d59ed763a09", + "0x4fd8e4224aa6f2863ec655c10e829e113882646230a3dc753d80c111093ba167", + "0xcd7f4ab1b3900488068618eca688f2fbf85e58b265ec0dc4c0ea55f8892be5a4", + "0xddcfaa6613a08b4d0a5f4259abae86cbe95fd5ec5ec77fad9ff2c5662efd4025", + "0xf8bc573cc98ace8805ea12e49c664d8d9cccd650038a4c6ad559780d1d2392cc", + "0x65d8dda84a5666f872d4a744a7c98b6dac5e1082e06625d49d32212a37bb1291", + "0xffc19cd76943cd82bd7aeb8d25d6dc4bb71f834cafe50a5ca2ae257d76a93db2", + "0x3efd8f977e31b77007ae5f290a63c22cb417b52d9bb36899baf826049d169785", + "0x9e225513beea6034be1edc5c51a3f12718713578a2a69bafe7af00bdfc477d02", + "0xebd0e1994eb8dc81f7ed767aa664ee7fc0514caf96fa5080c1ea120bc9803ce0", + "0x340d016d76c6f0db1853ef43ac32c2ebcca11a936c19f0f6814d64aff8d63ee7", + "0x57ba48a6bee7cc99a609f5ec1c9dc2aa1ad26589b292d0e913bbb7e6700895f4", + "0xb0b3f638edd6161784754f858844e77f9dc13a52943120680171deba7272e9d4", + "0x901ab47b6f412b57c0b09020defa44b5375c4e80749199c084f6ce0ecb89ab0c", + "0xb8c7e255dffdbe496fa3d949ed552e36ebdd6d14acc4049491ec6a033c086616", + "0x2f1780d8df1d77937e6dc3ec8483d39e3722eee9b102d84cb412b6765e1de74e", + "0x88712075a1174fbe444b715cad257d16547968ac267142ef293897332feac87f", + "0x6287016bcf8d4d4b67412f0b94b080d6b09b35d2a969d333fec03a114f49852e", + "0x7bae2942ac4d0c98a53feae67f5486415b9a59305b6adb3c7fdbf78642004eb7", + "0xe2dcb80caabe834c0897449540154ba5102f7c7a534c40f05dad77d42e26c571", + "0xc1856ba8c970c81104603472986449d9a6ad17f56cf67dd243c707c689e2faf0", + "0x3dc698054a61289b4b39f89c7f09dfdcf72c4a5a54276e508b095374cbbdf69a", + "0x0b27594e85ee0393ee4b16ac44751b9a1d8a9e7d704f42cc7c46bc1cb30dda54", + "0xfd47f64c6b87363b36d1de4950c72a7ae7fc61d941d6d046f89eec5bd63d863d", + "0xa420ed29af2c8a076098250c29704638476fd014558fdc68524d7a1c9b4043cc", + "0x20e516a19060c4f95559484dcff148812ba875407c1e0548714b630439985f65", + "0x779971f5b6aeb2717e6e336f91b3babc6b96621fd93352f0444b96043c34c1f0", + "0xa57891c1f318ee62a989a151b1be70176b8a86466e3f1669a87b3131b3f7190f", + "0xb09340884952e9fce0a543bd8e98617caacc63d4c87485da51cdb906aefd479f", + "0xff2c2dc309fb4c05b90a80a3fc715427f540be0788b33525a5ea00f0376ecf8a", + "0xaff098da407d643f4d60ce864184a0cd2001301833da3f379659ea4462da737d", + "0x0650daa5593e4d835532cb1cc353bd2e93fbae818e1f334491539ef4d363c2c0", + "0x1d6e8666bf720b0cc1fab78d8ea982ecd2b44305dac8edb2f5b9b9881722399a", + "0x673a6337982d71675566e7e6acf703f9c5b18718856bfae59edac11f4cf2ad3a", + "0x6f68da412db64aea7ea33dd930e145f45b36cce9d285ccb878d33594bceafdb7", + "0xbcc221ad6460fb4066d8c630720a519557064183fd3ff3feffce36b0d80b8da3", + "0xe671736f8a72834e5944c296f64a0d35743edaf75becef65203409bd369615d0", + "0xe4b50f9724453eef07bb00e56c32f6e056bddf38fed0cc80d3d9d2f86258810e", + "0xfa0594818b10ecd7be1deba272ee23b3cce007382e6974645a505df7d289ca39", + "0x35cfa0772e326b9325a613ac39ec350241a62d9f51cc0a1b0de4875d2ce48059", + "0xb6575e9d2cdfe08b13fce3badd0a991f5d331cff4444821932973767677ca13a", + "0xd4821ae28196784c066b254b2fb3b6230d5f4a0e769d8b85fc7ba453d3e93f1a", + "0xfd9f762aa42f1eb43e75c3c00d292f9afe393a14e272037d072872f820e710a8", + "0x9f78b0168eddb9acecaeb07fea85080fb638aca8874a9ff15d3bca7e3e4f9e73", + "0x8c2f0986e10039e96cc6695884401991d714adf5c445e9bb0f90a14cb4a12477", + "0xb7059b47417c4a06bcb11c6ab78221835279d130f52f5cfc316e80f87977b87a", + "0x56fcf49a8a7a69d4f8604190d79eae7e2957a1d129cfd813c9447249ace909fa", + "0x9401c3ee1a458253b3da8820c1e9b8945710839a826582f3a86e8a482dbca0f2", + "0xff3f9e5724cfbba1f837a10f3844cd437c0f1b5e31ddf61c4e56ec504fafac55", + "0x8787e48bce6ac94e62c13b82c544c2265b42ec08d959c18722c3f722cc8ff2d4", + "0x18cfd60669f16555f0b0a429a6b98bb64e936863d5524e23c3d263dce8177866", + "0x33a19dfb8f79494cd2b1b5983884992f637099735e67b2197ff48b00fa28ed0a", + "0xcd2d1272d5982579a63f951c3678c5ec440dcbdc2a5fe4ee8c765fd16ff07353", + "0xa7bd53be4ffe9029d5bf0c15051158d4fa1d9857861d9b3fa63dd0d5052ac98f", + "0x6e039f06324bfe8b9604711719bee4c840526f8c3ce9bc5c3c5584315362f0e8", + "0xafd6c666917c47aeae4d44703d891a3498211054535295178903665328d24291", + "0xc0f0dcd1102ae4eb932e3ee71f1417dc852f3f1ba6a8f2b12cfd8b86ceb3c335", + "0x6845dbf33355716e4161cd3e03ad296a4bec741255d91bcdb6e36950c7010c75", + "0x832d9dfedc39989c97066d465f256ceb8922f99e01c730865f62bba3a0aa786b", + "0xdf99981c644b3dd68728aa9801d5ae41579cc499a534d5213797b3fc35bb64d6", + "0x0115b4118eaf40a9f0fc1cdb8f26ed41e88de8c99e572f72d79dffad9a776e20", + "0x8b09da2fa7f9bd66158c3d469cd22d3f8ade9d86d0cfbc49ccb48335eac53df1", + "0x1edaf123ca42fef6c94b334ab5584c2837949abf3b3ad0b05de4e1da16a5fdeb", + "0xa7bf42422c1beb01742120f78b46ac1eae595f442b0f246f53a919343b4b3b37", + "0xcf72cd32a99afad5a5d9db18819131219a92c1404b57f64215a9e9e891c9428c", + "0xb0d4dc75898e16ff0c4b8bb317669eaba1e54f8d1a1cced03e6565ef3063fde2", + "0xde58a7597969ab3d35a4269d0623ba77254fa140ee0dc00f85e1d256f515c26c", + "0xc0c52dbd3d1febd3e5b4a59d9a6c1a4023d612160bccc5733f2006738baeb149", + "0x42759b763eef5c70b4fbb982cd247c29b0570dcfcba9649084622bc93bf0440b", + "0x02b44944241f25120667fd0c83797915239018c4b370378719be93a809d0fe31", + "0x176572271efc8297d8472120996569abdc26e0b2695cc1c69f72d8e27fd927d6", + "0x2c2f7eb653428b3a5329b339094caeeb4924d322b4362546ade060f8ce89ba65", + "0x3b548a06156cb3ce3ee222cd68a95ecd69bce5914a699b020f0890719a5f97fe", + "0xe74cc69a92f69d63c16a4baae5cb692e57f2e2efde17e0c46fc4cb338eadf215", + "0x9b2a05590bcfc56c432ddda8607b7902c1195ac72fae25c7f18e547a20fc1654", + "0x52f4d9509d31fa6100c7fa8d644dbfe2122581e8a277c6fe80b68aec78035ce6", + "0x380c3d4f876907fed243d11a8caf436445ac5ec55bfb3596091791bfd80ab8d3", + "0x386a91979bb6c8e42d282132f6903e517204fb9ce1379fe5f2a90b66b1f708c2", + "0x333d6dcba02dc8418059d95d43e22b9bc33539bda31f424c762c5b62676b04b1", + "0x50b91f399926865ca64ef68dfa540257f660759ced1276da1033bba6c2500da1", + "0x78266d3dde661a3b10f43d31375993ff002a7b49717a075c6367259baaa58fb1", + "0xb5066418dc050952f056082ef0f6d6b47fb423e9e5458176296aaa6edb7e7af0", + "0x3b8320734691ac54f2a231b296b889c9c8511843984a9ad80f3c43b8fdfb2391", + "0xf85d88e47f6b7ec5f5107785f80fd8b51ad6d5488be9b147e03b5697567ec932", + "0xc352f5af398bf837c89b42eeb48c322ac8eafdbf57af5c1c33ab0880623c7599", + "0x450a16022ae364a4f3ffd5e554aa9a324ebf8b9e6e635e753f4872ed6f63051f", + "0x0438e9c7d357912b1527a7fa5d6e30ec428e472a617d30e33946e47a1f648dac", + "0x4cea137040ab131bca9c9cdd41760c181244c736ca1d9d19370012935de0de6f", + "0x757728e69874bcea324af5348e76db22c3eaf8348843f61b82271570a5a96a93", + "0xf45bd1383b1d53e95dd4d0515f20035cecfb0707442c525c0f06b55e7ff52a61", + "0x156d898c3abc5a55d9860d679d97c36b2e48f833c1342bbf455b13874743b1bd", + "0xb3e80e0fe51cd1ab5d8ef201a011bf6a0a5878d070eabfdb4a6d7c77d06dfbe2", + "0xf7302c6bf2d04fff65957a18c8b988bf0e3dd7f3933229a6f1700e6447560d5f", + "0x73ad7c6627035301b9815d82626fe958ec0ddae62060f0c7f431865dc1b9f6b5", + "0xf10b5b53d915c1bb2eb9979dabd2e917dfbcfff17f1d09cb616b2a5179014ce8", + "0x93570e1d259272e6b825a5ed34a103fffcd27f792fb5b09a2442cc83a3bd172a", + "0x8c5538b8ff9ce17625018bc309af258e4f5acbf9c7c2d4e948cee8b30b336f92", + "0xe9a6cf047c81e965dd32c57edb680c2aaffe2e367976eaf49da5dfc957fac2f4", + "0x7b972cd72e31473b463ae197e30b121afdda7878b9bf0e1961d3813734663435", + "0x9690c83cc3a1b1b8649a89a9bb1e1fed606e4c949d46ab8f66f16c8320ff5127", + "0x8326afe249d762313e5e089474f174825821099a5e9136a7783c3eca7a160d05", + "0x240410eba6ddc5b60a0bdc83fca59d615d95c64b0afaed0a7f17b96ea65684b4", + "0xc48969c8f72df638ef2e8b98f0d67dc6d9eae1d5bfba2b02e584ac2dab51f3e9", + "0xc4fa4b201243c20d35df1ba466a4c40139471ec86bb55f872d54f6404d4bb05b", + "0xfd085495f4ebfd30f7ee4ad9f122ff3da3932fb87ee9aeaa7c8103602671b96d", + "0x17ef24bb8c605d6a27b3b44744353bfcd127488be96ac77a3d8c706015889040", + "0xfc2fa0f9a8aabf5fe515cb5b4a4ec6047f08e6140e81bab8624b02dbb3f99d71", + "0x3ea5269fd6cc38f8a2167cb1619d643ec9de3deb9ece6c19542626f7284b7b0d", + "0xd6ae9f4d8afee0374c662a86b489c603b4e16fb82dee3f57ddfa971e68531fbc", + "0xcdc97e7c7aba5cc5939382dc37142c9d59683d3188d642009edb492ccba1ed77", + "0x847886244064d2edd6791561638b63acd09336b4c88eecdb09493e8ee5324dc6", + "0xc3695209de581e3e3ee849b3dfd93d8102c9e047edc1596aa332d8137d0bc3e4", + "0xdf1399b24c2588519cbf19e2e7218d0fdd793cae1eeec52f9fda7c729a0d4e02", + "0x9718b2e289feaf4a2acff80f5d1c61400e917200fe97b5b9b6200d4c48e7a526", + "0x6fbd4948fdbf124fd0a9c958953abf372854bb6e29adfe9190b0101b97a342f9", + "0xb54aabb1fcf4c8b701734624fb68c842b500f5e71c39dd04083f8a3eaf7d7c51", + "0xc3710e6042dce5652464ec6891ec5b9f436208c12afeda5fd3f454edd8b5d79b", + "0xb6e3d629f78477b79bb9368f1611b62d717b3214675c64f1eb737dfa17b03b04", + "0x6fa6a372c4f33ec50d56a4039c0eb7d6652fb934b24ca468c1fa8f034aa043f5", + "0x51ae789b75938201ca463bd4e7c36152aeafc4b63544293e689e15ec80ed94a2", + "0x4fbb4816f1ea23ea83a425969223be5b9cbcd69113ff43e622ba9753a3a25901", + "0xb2df755c413220d7b684b063f81a800072f2f552e37fc057f555b252f70e858d", + "0xb5d01c218c65539914a8b01c40bcf629c83bbb4ef0c6289c127f583b133aa4ca", + "0x1489588ee88b1922296b2ba27abdd0d393a774009941f4779a63d3ccc015c34f", + "0x093c64995cd670084f2a908be6d6a508f490641474bfc722eb8605e0600d246e", + "0x9addbfaec75c7de95a89691ac3c23ac7c557c278155ba6026aa73258870847f4", + "0xedc09711042a5e3e94a1fff57e7d00e0193f1fb292e3625c6c230c66bfadf1e5", + "0x99a935be3a0aeeef44a096fc8b18ed302bf7224b6b7abcf5e897ad7fd44ad9b5", + "0x00d804cff32284e41ec123482da2a86019ad97d8b36c0b743873438e0cc7438d", + "0x669eabe8771c02c109a7d46ec07b346be0901078f5cd4419b05f3f62442f0b1d", + "0xbf26eeacefd0dfe498f7672aab4a5262d75af5a7e8f5a5dbf0a3e9cce3573b1e", + "0x9b43c92edad88c5825f99c8490b627b68602701a8358baa22103d2b11ced2d77", + "0x8e8988d54263d7e2d9692ad884d44575d3fcb7bfc37333a814ad19328df3c690", + "0x208d671c12795da6d89847247d9707cade2dad378a840d281a637e2af57d137e", + "0xfe83e593e005e58c47571fa00075d440286e02674394eb46956a25ac2e2d3622", + "0x41a61f08717bcb479edd0ed1fc9d8bcc13b9ca3ddede35dee6e0d0fc347c4c45", + "0xe9fa1018977dcb1a2dd82ef24105dcd827bf815985fa97afc0d294711997f686", + "0x7deebf65689aefa15a6d15f7b6e4818547f56b01f622f94fbc42ef968762ebf4", + "0xa8fad9841e2c5d7c1131c16145c57829f22b62566b5a7366d6653157dbddbc83", + "0xe0614431ceb7f622aa4f43c03fae28318aa726dc1ce0f95d69aae011eb62a017", + "0xc731b4b0341ff915979233c76f3562e8a28f268b5d3e531d8d4f3c927837f123", + "0xef265f9c899303b2afcf6cf2418cfc8f9c71d4254321aed87827c0c749f51546", + "0x40edf9f2122834fdbfa84483c376a6bd8b67eac8b8bf454258dc7810f8e849e9", + "0x63093778c25926c58ca06014bd1b668b4d89e641acbb94bcb13c9ca0519fdcc6", + "0xd8b930be700bbc53228755ecb5074d16308f8dd3187cd3a0efe0c2414001458e", + "0x75b0cc9e892313d9c1ecfef4bf4b3f5976f1c830a7283a82fc331277a4a97eb8", + "0x4f102fe9ed705a74524f2598ee6f22adfc1d4186e2ebcc7331bb48e900795cdd", + "0x48a257229a0e91207cc31ef82f00532ec12cb605abaeabf1235676dc57306357", + "0x9ed64622acf60a2bc6fdb2bb738517aae8dad9cffa738ed4f95b02d3be04176d", + "0xd23a29871a1fe22d8bb7e7749aadf6d77c0140fd383cab55b099714af617a371", + "0x79c92002b2077df1c7127a4c49575d7caea872ca1175011d47e019ff14ed8535", + "0x9a9434b2d09c181c7d9f8ce3e10fafd8c3b1e27b807243d74075e747570fb391", + "0xd3c946d1ed5a76e6e17a599d06bbae3319dedfa047e8443f9df3c4b09aca3b88", + "0x4f3ef090e35ccddb78598a581800ea6f2709c691e3024c2f5d13635d3fdba27a", + "0xf958691aa9a520e8e399e466e390679ce3781b82f1d0dfc62bb53d0b3f640176", + "0x4a7faaf47a5031e0a798dc00ab8248aae16866cf74935ac0703d3f1730617d79", + "0x6d350d1568d7db6c029f32d7c8fe47cfbe99984d5d24a9470800f4b70207f653", + "0x6553729bf5616496d7d3ff3e120ddf1c4e64857c53303003e4c9c2546f8458c2", + "0x05491ee727fefe4ef46b9922856a5282c4ba27a90150b967a04e62d85cb3dce4", + "0x61e8d5b5143c0c532adc9f466dde430afc1d1755775dd39095a51a5aa2d4422a", + "0x2b5a26a051940c5f804db637ca77a835ab50f6c62648adb5da7ea05b39b04b38", + "0xbc391789c853b9ed06fa0d2533f1f56b55937a49061f1cd1a102fbe88657a764", + "0x4206d3b075128ba118dd06bc273999ab5ec097f1690c2abfdab351efcfddaca8", + "0x78075f3f0420f490386d419fe2b187d8c6a3b0bbb2158e0f9bf04071ad235bb2", + "0x0cf1b70db8922a59f11eb3a40ee22264a231905cabcb270dc3df11d22c8cb780", + "0x093ca9659cfc716634b38ccc97cb8193baabdb6569f4b33e56e3d8ec1157dbbb", + "0xfb17fcc35e7609264b5dde51f3847f98f555808c693fc345e6b4da55dec4fb9e", + "0x7b6ff07aa7bd0decf690c24d510a2d08ec07fa78276311205004b521f15a161f", + "0x2323e4a69094bff2e821a49caf30ccd91717bfd9eef8609331621071d4fcca2d", + "0x9f05738aa053bd67194099d8bf7baf3166c4cc18b76aaf7cc1a197d4af911765", + "0xb46c0513fd784d2ef4029eb3352e4423d627861431c160988bdc901c01957114", + "0xe1b5c3328267a91718980d369530a7ce76c6f7e404030e880c5dd57508abb03e", + "0x66d908a91b10d229bd478a9ae64021757a22edebf9d41e4a58e2168e8445d137", + "0x9de8289dc95f5b61cdea4a32c7064750adaf034123380c68251df2b816790893", + "0xf9de4b4229f1d152bf4d00864d8d5c37e8cf38264b2fe304931392f848fbe8ec", + "0x356654f74408077036e642d6ae98d7d3893190f6169110c682bbeffad006e33c", + "0xe5a731364889cf98c6136de7365fc53b3f8cd622ae7480fc35a9aca8f4e615fc", + "0xecb8b7af4e850d0854aacb48f034d96a74a81e588f900e1acf0f421e8ea2e59a", + "0xd3d25554bfe2217268be1364b9f74ece500ba8e49260218f22bdb86558edeea2", + "0xee9e40ade104510e4d04b9141864d3d14ddf947f7dd8d05ca29fb3b4d4efce7c", + "0x440556c74bba8c2d89d9eae72f713529f0694a72a741951d5144f7f977ba745a", + "0xfb63981c40b30bc7675280cec8063e7f64f44eb60d983b462cbfbd923a18c46f", + "0x666810ed3d8a8cb87b9d3d908285b7428380cbffeaa2ac9f50b9acfe3727a334", + "0xf87e07add78b9ff8c8b8c4e81b1086ae1fc9f97903a0b8d5e30442781abf5747", + "0x7919d5dac99d403b646b4785205c3ec2635023816e534eef9f14aefe01a0c8e5", + "0x99e1935acf142897bcc10ca07285849b08e5d8f0f8ab73bfb5b6f79cc65f4919", + "0x182a38b8286b5a6ecc93b431a20356a178cba89ac025327e28b7bab5e815ae1c", + "0x666d49f7785b6d3db5ad92f1403e2e447743351bfd31f1b3b61665a79037a1ea", + "0x898f91e453cb2349f6a222f23aa848bf01426fb40fc7c00fea3015847da37edd", + "0x6919143735b6f85a9d0e37bc4b81a92d664b5ef75e40be58fd1b269f5627fdc1", + "0xb854a51fa1ac7182b6f92d48cd90d8a576e75f769147916565acfbeeead664e7", + "0x3924e051c439c6a49a7af5d5a07d3b9b193eb1a6c1511ef406aee6f8e94b2f94", + "0xc6a2b425de2dd99bfa1c0970d29df185045a56cfd3b4021a3eaf630d4e87c6b4", + "0xe66104bd368ce9ce40920c6a0a1dace7be55bdd5ec594cb9169e42cf07282168", + "0x876d3a55345136b3079c260cdb312f8c708f9ae8afd3a6a90f8c018ba58be19b", + "0x5c0849ab35f38121bfceec816cdcc2525e88530ad874086bfa4056c8dedb1e77", + "0x3028fba2e7ff0c70acf12e33e744a881b94865d6f373a50d5d5eef23202568f5", + "0x9ac128a61197f07dd4b0fbac847b864a6496f1047a085e9a26f1618e9ae83406", + "0x55c9428bc7a5017957e025f046231005d4199c8e92627074923280cc3f6e3cc1", + "0x474004a4237145fc86484ae385c21523250746c662e791d5c366441c3b9d2189", + "0xa53ff4b977a2417289f9b532a20b758a2b0bbaa84e71c82e783c7ef045f16eec", + "0x0418a7320d961c5dede728027a0be6f4979211ec600b564edd408a1e9377d5b9", + "0xc8ed8d992f2b75be024eafc15ff7d7c5c0b0599cdd6b603437b4e737a60993e8", + "0x3f5e222d8b28b38a8c7b190448286d4a14afd1b0cb2697fd9356158f5215a0e8", + "0xcfc961c5ff3b8615089248635d900fbea9ae9f7b4d86ebee3703453567a67485", + "0xcb88b820997d440812da7192f44c6debd27da3a41f04b595f515e65cf8a80d50", + "0xce6f3fa44aa7a177ea56d97f00ba344852f614951e665e3742429a6aaf698c37", + "0x21bee516e3366f5770dc4f6af36f799a5c967eaf398f2b70c3a8ca694096a9d5", + "0xe5a99d3fddf70f8e732f7f4a14fe81de8cf1ffc945a47d9eaa7a28c5eaf6ef84", + "0x0d9e3847d768c28783981c6313bc9b0e60ef4c2a8693cc25d399e9db50f393da", + "0x728f54d10e7b531b464ec7e86f3320a4e853967c14061e727f58ee3c115cf65b", + "0xe1a0b9237f50b5e47c98190589842f0b72be2acb3b6a57c075b0c9933ee23100", + "0xe42d8bd36eb740ad018367109ad59f8a74ab017eee893be54a4d1b04b7cf37f7", + "0x72bd0949deab66aed968e725b4434158741c70007855105dd17ab9cec2cb1a91", + "0x450177933434050053831a4c162399286a92c18f9899c413d1c579ef95379fad", + "0x8c950374baef552acae9affd2238ce1b0a1c27e463a03e518b99f23f269f805c", + "0x7a09cddc74127b837571d245fc039489cd0be46ef3618460013de17c2bbf7933", + "0x6ad520bcc098e50d371d504a1e4f4e37b63484066606556debb14c1341880f9d", + "0xca0232939f26cf17430ab3299f1970c334f8dc132724c6e6b01a2467f4dbc149", + "0x9edc115c3af74d77a3267df2b87a77d82b825d07993b74fc31668a09915ae070", + "0x0147d798bf772842ca2e33c28b65fc6934e41e8775b5cfd566dd2f60641da26a", + "0xca005d851a4c27070a0706bfb3b95303b7d79008f49a681f052700c1b4275c57", + "0xc365df99690cb05b89c7efc60a7af3bb4e01c22e5f6d51c9631cf737717965c6", + "0x80aac988930e5f1de8d1db964645abb114e145f301db96925bb02cae2f6bbdc2", + "0x7c67c1aa7d047bbb20131ba231a55d0b596394b06b89c574d23b8aee7231b65d", + "0xd2e03510fc847b2890ea18eba3ed90ebdaaed83b55bf9cb5eb37b9fac10517bf", + "0x4047b15bafa722bf1f5ed69691e671a64c54eda20f11d25143ac7e5dd4e9ccad", + "0x746ab5985f0ef9bc18cf60d1216c69d1fd40df2c1bec2262bae7438acdcd42b2", + "0x7fdfec7be4c42f0d16b66818334e49c97d7b06ea6a2befa361a4aba3c511cb7f", + "0xaedb8c3201c978069b5b2b562252cf617e2a0b0cdae62dabef3a04badce1a084", + "0x24dc7b367353aa7ac0c386f4f5768ef1212fa2cb0de8317300ee54b6b8e420fc", + "0x6bf5c551d97c93ed425eefb8f2998b5fb3735f96bd71b1384799a3330347074b", + "0x9d0be98f9e31ad94e6badd0bbaeb85dc69322649b825f8c41dccc8f9a8d0b4a0", + "0x0d1e4ef567e933a591dd361bb254c080f91351b04ded52e022ed296c2c06580f", + "0xb80d22650285ec257007fb6ff1de2c209cc6be02303b3e2bac43c6a57c0d7004", + "0xe2cd2f349288db25e7315e3c8b4257367f082a377ba4384275a506e814940caa", + "0xf56100200b9fee76191568e49bbfa0eba66887f24cbd6cfc0145db6f31da07b9", + "0x13beb775c7a572d1c54631405b45f3e96938af0d5c740c4762d5ebe5f7ceb1b6", + "0xb5b20d1527a14d733fdb3a94f178dcbecfc9f4312e2c3c0dbfe57996e143682b", + "0x5153bf8c2d061de36ebbc21a31c3755f96296936e79584d03ea169d7450700f7", + "0x8d59bf8350b7eb84d5cceecbf735db04270e4d76b66eb9961243af61317a30e3", + "0x90e0af4b3a2806ea91799ee9d973fe9a2a3c7c07574acb7c72665af11a515bc2", + "0x171fc19c2c2e6fa95af7789a01078a34a628f998ed882884e6f514d45642cd6e", + "0x5f73cd024051e26bf239f11b35b757e896dffc144a2cfabb50aee58e2b4c8afd", + "0xdb7401010dd1db0e8af735200f9bfea39f868425afa01bcc404e5136db7cafad", + "0x809dfd2cc6df05328ef813bc5ab86b6ae90bfadf37107dade647e5a49fbda950", + "0xc731c27a9d048ff7ac2f08d1d68d46fa57e61e620e044b929dcd7d076d157eb6", + "0x1d443d7c2a3974ce9d3211aa39efb84d779dde08e132628c77d72cf092ece1ec", + "0x71410564b523d40ccd091e3e19deaad26d74d97963a171cd6e2f739abfacf63e", + "0xab33110fe291f5cc2f469cec31c7d21409345545446ac33c0f49e1e004542f6d", + "0xa775e97c8fb2b70449066c1d33efbc44a10ed6c931b7d4a193e649b853f23794", + "0xf07dd49b627af4aa3253f0403aeef8a3bb452dc2c69a1227325a1c88731ada5b", + "0xfc648f6b75782491734b7d24fde9c7b4bd939d0b338a74a0b36daab26ca3555e", + "0xaa88a296c0cd44bbaaf8148c005f180d7a2757b4ddcc623a43a88a43deeee936", + "0x1ee2fb788d4dc943f726b8455957bc175ebac3e4b8427177a053d7f299a3598b", + "0x13e7c4da8f8982f0ad250a425a24ea8f8b8574abe033e236dfbf596fe2efac0e", + "0x8acdcc6356fc748e03c06ff4878d0fa96f18e4f03272ce01f02ad29d8211f611", + "0x230d99e6323448f1ebcf7e6792e2978a5d74ef654234be97ebaec5c56a684457", + "0xad35598f4bcf7bfa1852a9265a59d0f9914b3b6289a7aa3015e3d808d504aca6", + "0x4d9956ec8c5887e8cce4bab5b6819cc13a8703cb527f14a5e9db99cbfd83b665", + "0x99a277612b78515fd153c88e0060c274b1ab4a60202b575a9b9892420ae657a3", + "0x656acdfdfdf9b76d499176bc3a259aa9722b31c7f3f4ae5c2da8bc3833c12d66", + "0xd06448c98e529a17170aae72cf359a1e2808ff529ca9f37df3360b92790f925e", + "0x9afd24c01afe4856a47db81a6818899d93a5096853b395a24cb9edd693bd24e0", + "0x03b7a5d8eb6ae24ebe158e411df31514229a2f302108984597317196f6226ccf", + "0x6f97a76567724eecec6c55e811085e7a83cd5f6551924f6f8de590b16cd255cc", + "0x5fa0d567d50e49df1d24f243a2ff97feecaacacb6a5d7e34620a9f7e18cb3f84", + "0x727b25a1d44fa0eaea544ac593fd8bbde356a71a48162160feace5596251f1e9", + "0x3d8340ffdc8e124785dcbf85d3b12a65808c49d91a77ed7a1ef54e404acb56cf", + "0x9057ce97cd01e362ac771d04ecdc45b10cfd45d0c3a1070e2c0fbbc81fcdcbd4", + "0x016b166a2ff70c7beec4ecf9a408a8fa4c556e0e4382911057a984454fd9ab45", + "0x9c2a27134a95f9f28d9f313ed2ff1dba33d5a080cd2d00626b8b6efab87d6957", + "0x66f3583ab4095411135af58756f72480d888a24aeda166136e18e25f42d56e39", + "0xf2cbde4bb5fef74ce2342be3f2178a7ec92ec819721456687705025708a2ddcb", + "0x5ce0fddd2a1a63fbe9bb28c01ba7d1c120f2eab2eacb0dc6200fea8c170e5d2d", + "0xeee2051e5b3a37bed40c32e05f141ea33283556a20e42cac05e5efded1b046a4", + "0x0a38951aeda2ad0227d5db28597901dd2f15fb8a53027241941f705f84f3462d", + "0xd532a9afec12700d8a6976dd148621347df54aa5f78fd64581835027a88ef6f1", + "0x2e328120b2bdbe717d673b04c9fe2c66d9320f668798b9fa11c257a5719c12ca", + "0x46a2cc57ba5798731135b891a9cb9af4b1f780a168d91a9d745f5eb39bdf72f8", + "0xe350043ef30f36168e8f68da553667cccd2eaaa4a1ef85c187163b9e5ab243a0", + "0x183ba0d0cdc68e3ac433eae5822bf39e1e351bac9faa4ec279fe9d3304bc6dd7", + "0xdbbfda6ab37d6b32188cbfa975f513f6024e84364bd6c59d513357598c92f80f", + "0xa44361a80cd53311a9e2de8e244013ea6a926cbd5854920ae3e162bd25d8ea21", + "0xd832af8bb66b36e85828711a95a77a2b6f4b42a5865bebbca59209e6585e8c9b", + "0xc7f64dc286ba1f7b6ddb15638662314813113bf058c7a9065597aaa4452c752a", + "0x178b152e9820020d4245e8a997deb02767796841a0220ac22544aa1250f84296", + "0xa182cbcf24b7d477c0efb568a8b120ca341c4b82ff0fd0d6d0b856a65dcf1083", + "0xb1f0f8c06b2743e1f8149ce4dc215f5dfb89f8f1da9718f3f312e500ef06aacb", + "0x5027caa12ed653330800d4de4014e24fe9251ddbcafea58e2c27012dac58c371", + "0x35a7801cd57644a1df91656b0566c62265159106b963368cdaf429472913c189", + "0xe80e4e8f12abcd5a79aeca6efc64bafe1893075bbec001338f625642fc047bee", + "0x994fb4f27b15427028aba87c42b08eb0919e12870a05405e0ef8f2458cc2b279", + "0x67cc00cc4591d984d9c2270fbdadb8c0d4ec9b40c6879aad8176f9cc7131e31b", + "0xd73e02e0c536cabfda569a8da06c99a28f3314d2761e7c0271aa5480dfad3246", + "0x8d709e7a8435b1d5507859d0e4406589b03d1b3ca646f9f26ec3004c6b2d973a", + "0xd5b64c36bc4614f9ee9bdfadab6c095ad183a8cdfa87a9e6858c4b12d9067aac", + "0x9d1d6d5c1eedbffcfcfc2af6aa9a6df958897cd81cac630dcb998f41a6b14638", + "0x39a3945ad321e02ffda18c8072e74f0dae525a57c7197dfeb86453ad208ecd98", + "0x878708a865debc222b72daa2611b7cb8368313c05f7f41e7f8fbbf33f602a582", + "0x305cf1edcfb804a104d777371850939c7c028f50d45f2fc4791524e24b6adfa7", + "0x6f5dac19867a9f14de66769c9a8f0813d7ac7fc4590eb3a862cd14ef63381491", + "0xdd7d64e12a1391437a07fa88b6ea7184676cacfc7cc8db544ab1808dfae8c87e", + "0x1e97a0e1992b75202522362a4edd8004a430f99c024a6503105cc55bcc7b843a", + "0xcc78f11a9f6996cf742875333c8274c68800658fd5a7465bdbf9c13cf2cf72f1", + "0x1fcfc22ea13dc96c9f8f3546f3f1b8f458bf7d1d46445c92deadd848bfee0c09", + "0xaa5d6969d152ebbb075a97c4a051195db68d90a75c37c104321131c073fdd843", + "0xf4f6e0c5bd269c7de9d1473c5074b3bd4d42b207742b918ab1481c633d05a38a", + "0xbba5eb96150613be2e45e1ea8ecad915415cb1e091a85b6858a7d1d5a8a005f4", + "0x1cdd61d797c519d6295196df06cffd0c9819ce0d9315c66e5309f14eacab63ce", + "0xb49771b39eefe9791d25ff5a1c94f0dc7d560a90cd9ca9c997625c05c0299783", + "0x5232fc02627cf406984a2f4f2e3813ad6260c1b07da797c2d1b7218d7eb05ad3", + "0xecc5ee2ea8e3956d964bed681f61323f608bbfe52397b5b28ef26f660e3c214b", + "0x49ce943abece2026b0c51a5ad5bd35613c92f480027bc47954eb9bc7cca5bb0b", + "0x27f731e278a0221daf21ab225b0297276db74ab79edc4806aa6a794e730f615e", + "0x55a9b21ac8387ad6aff87660d889be69d8b506a5de230043fe5937d0bfa53771", + "0xdd2ba4ff24bd512d48b553d031130799e46f3812c4b782c9423235ccebd7e655", + "0xffff9cc54e4484d4e70a6b3770d11fb9e13e583522ab4bc376cd6c7498021d65", + "0xb4bfa3c62b210ad81177faf4f6a170dd801713e5f9e3e4bcb7301c81cf60d083", + "0x5c3f5d4c0836dc02a32d7059c9598bfe46a813684f3576ec24aa8215a5de6270", + "0xd6d8e57c79dc17f19eebdce62de1adc0940d881d61c4a1099d51e6cf0b1009b4", + "0x2d3b6873546a1e6d026249e0cc45ad822fbdbb2ebcbb13832b7862ba9bc09982", + "0xd0d2b37a28cd798dd9d1a1e0892e86d90ebd54e6be912ff122402f6d923becb1", + "0x0345ca4471a47d8d12421bb39b0b0f7e8475d04181abfaa9050b95cde9aa4a8e", + "0x78a603e3f62c47845e657de355bc40d877612062b2f42b63c50645f3c12c4b15", + "0x1e973f2f79722999a5caa72528d1920917d7e7eb6839976ca19165c3a8bd26fb", + "0x3f5242f783e2336e5cf0cfee1427fbb15a833930b22187b3659367563a529039", + "0x181667e480e8017caf91681eb04cfaf0560254028a903b620485cb9771cc26d1", + "0xeaf92b93fcc996d886bca5fec1f6a7dcdb58cd7acd8033637a8fd9d4bda169b0", + "0xe5164f795fac046d3106dd707c4628d731bb73a3fed8d15ecf915de5b2f0a48a", + "0x556f9c42a01e441bf0e74c4a89323bdea6ce402dbbc1f500d5b00146be5439fa", + "0xe59b25cc5415f5b84b41ab7085b854f64f6d839085e85e6b2a30c41e6f689494", + "0x9e2c804effa40cd7a92ac8901798c03a5e66f47496cd89fd3b8314e7973f3d06", + "0xad4eec2bac36a3ea837c95bef538000dbc75374a4c4f8ffa7d2705ba300aebd9", + "0x12212ae8872a77a5d57a4f5fd91797c2fbf64ac2fa5af09aa55742b3950d8e88", + "0xd987ccc0c413e4390b5b5b69370f54b5d35f79c9cf4c1c534598a7e383399ebb", + "0x8d30d2dc8afe7f50e160fb4d3cfc5c54a962f31ae5b4f65c2362ceb7b8cc4733", + "0x617cb9b3cab2b8c43b11bc3412cab6f889197ba608c068dba2eaf1fa051b0f26", + "0x75bf3d53043c8375f1e51194be0942f3ec73ffbd61926d33910fdd00dddf5b87", + "0x72bd67478fa033abe7905125b728485f401aaa31694bf9ae7eb1184adff2db12", + "0x23d7a73706b970688eac1e8affa5524f0f563228aa7601fe7d790f844c186bbf", + "0xea350aacae57df34a533519b3448435879faf637e3f4a7cd3bbc891489d31caa", + "0xbff826ed9cc685de15275d59a299f5272cfab31750d39141e5ceb8f5d3645741", + "0x020ecefd03dde3543cea261d265a265898f6804230e95f044360d4aedfe031a6", + "0x71645432ccbc0826c83dfdf044ad7e3b2df4bc979e68513ca382ff93e24d1d77", + "0xfcd3731fa2259ace8cce5eb1a3fd74c723f997cfd8d4192105c41f2874d22d55", + "0xf13985444c5a6873217da182e9784fa87576829b9e841dc209a2592f0f5522ad", + "0x0e065da66efc90bd88217d6e9a5721280c4037de294d9e6ee8c1207b664217af", + "0xc6f893863ef60cf57991974de8edfa93c28c55c3af96f94cef9360be9a3a05b8", + "0xae2bfbe04bfe046166f0d6871d689a809fe443c9a6cdebdd5b2e32a36d7fa67c", + "0x733fbd82f21056a2e402ab050e32cc83aae96a67dfd3fa9c50732a3fd576e7d5", + "0xf4e29375a5f989dfebdbc9101d411f062c1090a9869058f6b87fe19b3a259489", + "0x95f902f47c21700bb030841890c47d759dbeca59983f1f2d5353674a4f45088f", + "0xb02a6050eaa94106ee9d4577b10f6adbfe7705a3ef9c3019412c4f60ee8d0e1a", + "0x20d64b55c9e4c2eb51e5af544ed068ce9d323c194c5b18bebea4bb0182344ea2", + "0xb6e40dd521e524b30139719580bd7441a35a1bc304c338c426b706673e179320", + "0xc54752027833b57236b5f043fed133b2461f199b75d52da8578c6e98dc2fc5da", + "0xfd3f9c65d1b05ccbf980a35cd433da01443ff8fc7be680892ea3185914d86727", + "0x7175b164364820f36d10f9e079707a40b21004d0687f90bab1b132c9c34ee2a9", + "0xe4c4df954bf0d3d0eff516775d60cfd29d0e780da4f07589ece3f11ba8925b2f", + "0xa927f17776d750c0b6996f1d8d0db22547fffdb006c0cff367d0a0edc41ddb01", + "0x27050f4807ec856a205518e9d13821b2cda0231cd8959f47ee34832181eaf8fa", + "0x4ebe3a5760406a59770cce09a0a44225dd5a2fade1d877b219558029e30ac4e1", + "0x290c328e60c366b0d18e55c5578b9b3bd83bf1b0600faf0822a1f6f1ae85edb5", + "0xd7bab11bbd83da583e3fcceb0f84bb551cda363c33c67f93e02800176c29bcee", + "0x3cdcfb49d11cfa3ba1809271869fdd9071017e5498f8acb01c595dedcd3ff109", + "0xc75582264ee66717ee40ff52a6689d03121ce0f1abb2c354cff6d92e532a81e5", + "0xe7004c5a4d09fc89e8737a5535221b552e67c3a0fb5851021e9f9a0de4672ab1", + "0xd6b8f94deccddb6d4f8b066c0302faa4b562f7a04e3a092b7d87b3a08485d933", + "0x2e726cd7212cdfd26cf0d928932b05ac8258003254e6558c87eca8a82cf6bb02", + "0x6c8786a64069e3f422dc5000e6a614adf14215ebce0aa8ab8e22c5f239a3714d", + "0x2f736729adc62370324b478cacfc6256fa0cb9119219a2a000d2c34c3293f6c8", + "0x8afc8743b959ab340dc86c6ddd9ca1726cf4bbd13054616b3d1d64bf656e0827", + "0x661832363afb109885055ee90663ea7514059a2c6d69144f8892138e89ed037f", + "0x2279ecda37192639297242d97723c6b635456cb2c98266493552e618067fc5ea", + "0xec7b510975a50daf40effbc94c977f508c84a9712cdb28d60c80b30adb3fd24c", + "0xcaea827e123419fe48b7f72dd67eb8c3965a4504f13e4ad7443bc8e87bd7c832", + "0xff012579799171dada6dc819977c222836b9cbb4f521142e74e9ef0762f73131", + "0x70ec4b383c92a8bb37f733825d60e76e75469a71b1d5361a84e37b38e3b8a34b", + "0x4dc584e8bce8efed0a55021d334b87dc5973de45effbc43e84acbfc03592532a", + "0x0fdabd0093aaf388fdc53d49570d3304c8c583415eadabc98635dc472f366b90", + "0x1b29d10d1443bb37e47668c9b6a124a1964a3f12075ab9be1620891579d8db31", + "0x3d350137648ba1e593182918a4ddb6b5983001356d6e406bcb88753449ea55f6", + "0xfc3911c59399e8c329db2dadcb5f7a58855f19401f513b9f6bdeca01e73edbcd", + "0x89a4277d6bf214c50fc0a7219ae59bdb719b71094d6a02c4ef5e07b50501e74e", + "0x7158b6d3debe3b6ef5dc0d40616691c804581d5614714f2284e63df42b5ea578", + "0x46d73cd458ee5a26724a68b2f8186930104aa9674fe4d94ce75215c61d0ede81", + "0x100c71337ae5379ca5d43f2177f2f6e6e57c628bbae4bfb70abdd1f23279787c", + "0x3c9e2e0161341c82207498608091846726ee4dba0fe1fe69c07a92a0ff7675c2", + "0x5c4885fe3f85ee61e50378943a48732843d47184619f40954daf24a165f2ba9b", + "0xce300dbdbc2c8eb91c75f7e0e8e91dc03ba8894478a9e65529241ff462abf713", + "0xebcc160dcb2f38f4607cfd3ae74a15286eb0aae05c8fc4f87abb751ca88a699a", + "0x91aa4f2af47471ac51160d0d1c81137c7c6a22ada295356668427a45d21c6a07", + "0xf30c1a0842faa5df4ef896e192d5902445ed7b01cfc83dc287492b1896126310", + "0x0e069a0772dd736ea68fbbef47302ed6e802868d0847518ea5ea2eb34a79705a", + "0xb49c6e624b584d49ba226f31611a0c4f3ff0033a746b370890533b209da2ac3f", + "0xf2a4cb9c4877795e0ee2964e5aec8828941bef07777ff4db07423b4a2eae5a31", + "0x2e9cee7389233b6b4937f5997be0a6f37a8c347c58886b75e3013060c10c4a82", + "0xd2318412b7dd0eb4f6b3da69c2c3cb7d8a6b7028ea8f0a39bc3bd513ec7c6d3c", + "0x74c00a1f66bbe517e7166993e18a1564d43877110c54be28053321721e619e86", + "0x37de40b83aff733b4792e27dd6211687ad891f8d95e397e3a3e07d481a5c44a7", + "0xb607adc39f83da6b0a7da38893a95cf33582d836c967496ea7636e61c6cb7191", + "0x518708d6d86b3a15dfd50d0003c340998be42ff59d533703be30763aa080c547", + "0xc9cc7282488774cbdb9d6511ebae8f6eb9947cc5360585d75197532e37e9c7ae", + "0x9c73d1c1a937f888d29da748772785d1a8269282003e7cbab2af4140039312ed", + "0xadc5c8b549e56222f6634a308348eda613afa171b5991ede1b127f241d25c570", + "0x0bcab0832ec43772bb1aa95f8ba9eac83b4b47bfa776876276b47722aaf5c3c5", + "0x8b37849d079adedcba7ed2be598a6d84464ccdd807ccdef2d711e5ef7bdc003b", + "0x8e2e677e5f20a78caa0ab3726528209bca791551d0d33346144c5e7b1c8c6bf7", + "0xda0666298d3184c66e54af103e988fa0c9a80a12e32921e5bea0233a8638e23a", + "0x1ffb4873b85e71b067e3ac99bb26e7f5ee5e036bba4835989f1477ac8b03466f", + "0xfc89d4900e3e7a475b8923bad15bf68f4cb967cb50fae648c2efb3d90cde84f9", + "0xb62eb8ea8e54ed6358a752943acd7a2a1fef9553533b56ca17f3cfc0ba719ec8", + "0x795e2eecc65f357e0b7a9c97d2c028b7503524809adc6e783f05eb0423362980", + "0xdb06a90870bce8df7a88118d485eb691a0043c695ceb64af565ed62d37770c98", + "0xa28bb65d12c4875edd64e643da53c1b65a154d9e40a4cd37c6f770940235740f", + "0x136902f6e7104043a9d828a027df5f23c61a7d085e49907042c55d99d72c16d7", + "0x058424a9554f7a52bb6516ee51653aee32ea09d96247fce31dd8b31af52a07aa", + "0xcce2dbdca699f427d620870ae23b96b38da3414c57e71990ba8af36a58e6b936", + "0xd1feadaa1927f77eae9bb7260fe84ada5d524bdf1239a6e688080da9f7b71af0", + "0xebe906165c9808c0b368392dd2cd950b55e1f95394d28255d7cb9848bd4f3839", + "0x639198f58b4712fde6064dc49f73b3db52726e76ab9bdc00f6ef9a0487fd6d5b", + "0xe9e2f1d0afa3d3b0883fc7269618ca1a50ea5aa828ea07f92fae48b2b2fc54fd", + "0x811ee53510a20a012a10ed6a02407dcaf98099823a35e54849b381d4a6e5b5e8", + "0x221c81c3c384717eabd545830b62427d11fc62bd1df260921a8e121456d719e0", + "0xdc62196c03031dfd983ad4a211a514e25c4c97c9cd9ca62ac18b44cc0da4e0ea", + "0x3f60edc7443b2ae2a4ede7f52c2c4de9d58f90d6be2f0fb25772b51c352aee17", + "0xb5cdbf0eda83613a613ea26b14401361a2de1be89412367f39d4ab01449a87f5", + "0x10d0156c9a828e9b8d61e615079beebbaa525a07f32d792e5a67d4f03846bf4c", + "0x4be38f1cac74f26e2e5bed0d2b416482a74aa425564ccfd3e0ef10b5f57a7d59", + "0x814aa2e560adae5e7192ada4ee11567bfebf3ff8a2a93aa8dd432df30c77f44f", + "0x187c004ce45887043188c222842da10e062a9be8a3db326d3ebdf860209e723e", + "0x60036829b2cce1932f2d4198b5207d70a2e0634c929a63df122ea38f620f89eb", + "0xc323959ae94b9d4e5246a35ccb887b8fcdd2b5de43ab581e53fd3090b4dc88b8", + "0x37a114fb8c7c973708d5dba9c37df501db5e0d074c757954e52ef716299239ec", + "0x8cb29fadf7071a43d8208036d986abe64a1974786c4ab573f4dcca88f8db83a9", + "0xfc4485a7b2ddece8cefbc0f45c949920b9412a47b3e21efa9aa381e0cba0ee72", + "0xfdd52d72e5f42cc1cf1bdcbdc97b15f623b78d78425c338fe588e890be995597", + "0x92e26312a466aff28597bf3444b0bd298b12872f099885ab10949c0d263446a5", + "0x420d6f0581dc5c914b0da7339fb69bb5c9094ea8715c778e9dccd922317c36da", + "0xdd8641edece5a0ab2b024b4ceefdc3f524cb0cc9549c200528962eb0fa341310", + "0x740c0963ec5c29ca9fa48445ddc604bec138df538edb18844182556924d09fa6", + "0xe66653af6368613260ba344cc051d6086a2e08331e8bc5ddc2d25ab06ead9eec", + "0x86e1aa0ab7a4e47828216a25073d6c355e2f4ac4773cf1d2d859f62fd8fb8a24", + "0x3be2cdbd947172907f5605beb7863e2edc5f176e0960904550358ed6c2670704", + "0xc7d4869adae5a7593dbea4f802ab068044dab40fe0063d5b7c7727a3bf288525", + "0x620611d92e256bf7cc471c8883801be5d64fc8b77c1f39682bf840031e0dcd3e", + "0xd89f0456b5a3d041d5309ef623e259003383277f7f509096ae5dd02d312543d6", + "0x7d91689ff4e212d6f2c7d62cdef0593686ba04aaf455c576535d097120f1353d", + "0x568a6763698a23b4b2289b851b46907ec5777284741d3a7304d7df297fa4129e", + "0xb9dec1f84c9b71d5939f40982fe5c88d15f868e265d4fd9fa0560c2b64191998", + "0x6620f3e9e7fae45ca0178116a9e478f95bc0a69fab3a8341dca673453741bb6d", + "0xbb418a7f8415e5378cca2ee7056c6c78641b085e30bb9f9da033ea193bbfc77f", + "0x002fe11d761d3135edbb3dcb50533a1b143593145f7b4cd914d84494b1df652e", + "0x5f76ba2c72c3e4d93d98668455def3d335b03f517648c6cfde1d0a37178a0ec1", + "0xda49060ebc8b7963a9ff4095c9777d902075967d75c47ee3e9f86f03031b0a3e", + "0xde325b667d85828b7416d437a91c19a14b0217323650dd5880a8a40ea85f451c", + "0x9c14e5953fe56c60599dea8284b0948603334fc7aa795cae80308eff4cbd67da", + "0xa9e82869a1be8247c665d86f52900784005853c5249393fadabe37d08752ac9b", + "0x3feff38ddc1917cd5cace417b4e86762126997a5420ac2cb32abafa769f91ac5", + "0x01144f9a6fa0b4396560cdee8bc6e873bdf3ec5c3ab3f7409e59884e6d2dbd05", + "0x96778169c9f2b805e67cf18324c292c8b67c57db72aeebfe5369d91aca0983b3", + "0x373f81dd55fb3bdc9de4c42028a5bdc970cfda825723b6f0f7804b50a1754bda", + "0x3af64226f4eb3ea6bd6d0dae027bce6b361b30c50b4a65a4e1661577268953d0", + "0x35b96aa54e1c50049a0c91281c75d3d06c4b609a2d3d92cb22d1328369adcdc6", + "0xb02c9650fc610b3f5a0b547e8bc505b4a840e1dea123b4cb2c8af6232ae1359f", + "0xae53d65eebce31c14b787f1df5b021334312e8d5b8302b84f6a56b6608e25d97", + "0x4901a419abac1937602d98c21e937a03db8a48d088e56895788da845829225cd", + "0xf5636fb8f3a381476267e6713f10763cef51071b6d981a8f661a24ff6d368e71", + "0x059e8319866374d8eb8372e71998cc9277c5f5e5968c126a81d87d0d7a6fe8fa", + "0xd5fbcd3d7a4387000e014e67ef61d4a7ce09a70374ad4fcdb6ca0b6b50b13ea5", + "0xc37ef88d74d307090a0dd49b69d5705c8e65ad606548b0880eef33b8346c2af8", + "0xa316c8a8ac949af5957fc905ba39c247a477224cd9c4cbabccd0671dbc1e17e7", + "0xdb313f10f0dfb56b8684e6ded5e89c4d5a3cd958a99b1773680db8682645b9f4", + "0x0c81ab956b95426f5c327c6ac6db2fbbaa8fd0f41cc9f58971d5089a0f3c52c5", + "0xb09827a7c1bfba1fb7e5c7acee1da5d8fda1c10da19046151f55ef7fefb784b9", + "0x4332b07750799b436dc5b8521feb0927d7e59b25832ac83876da4eb9df333aec", + "0xdf6895278968d74b85e4bb2c53d70772a6176322200f864b004ed914bcc3cf2c", + "0x9a4a6427c038efbb77e255b8e74df6f897590f734328e5be0ab6b16a6ca58e46", + "0xcf683bc5fd50f6c444a84a5524b3e6ba381fe62c39828650f8c70d9b5b6e8d47", + "0x3282bab4eea18b9a8147d6dbf26073882e7f859b498b2d17608cc96548f5ba7f", + "0x04684c3e47911134ccfa142c85d283f26ed315b5818a523a79e9be31c17b4dcc", + "0xa8efff633914b0ed52a2eb3b75d6efbe1efb0f640136807db13d8809289e40a4", + "0x4502554b0b48e3230e24efafc4f8eef7ff50347cea1a27a15ba46187ed0fb2a9", + "0xe0d6508774e4d8772bfed391286d5f13b986518dfe49d6cc9fd55c415e2382f8", + "0xeefb070835b6cacf8237566bfbc77b177ad0e3e6293587d76904f5cf56cfe62d", + "0x06162414a2b278bf48122286cfd04e83ab148c91ff45d5b90bb3a55d374debb1", + "0xf87fcab4bf30f560c5359ee594e263859f1160f3ddd4186918093275e271d520", + "0xf3ea8332782f88dfa789e42eebba3ec9672589d090c557e36e05c7eda9c7372c", + "0xf05f9c5ec95884e6da30f95d56ad58a025dd696215ff57683d6946ebce25d497", + "0x6738c17f58a1e7d41a634984b98a5efa47e910640da0fcd80d2ad0603c0ec9f9", + "0x8c2029217e14a9bd4dd88eefbe6ddf886d30c56df42035464a5acfe567406dcd", + "0x5d0434b926b112a81e7276b96d1dcff0391e782dd68003173a5d11701a8fc190", + "0x4d9a5c9209364544eddbc545822bea83af527fa1f7b24dbedbdda61b69e18250", + "0x3e5800a59c58a56bd2cb7659db0705f45b6b8e827cf06eb0fe98586abfc83368", + "0xbc3f4d3a46d5fe6df5ded66fc47b5b73baa878c9b8fc3798e87a17995614c515", + "0xf715cbf347c5308a4d50c99eeb4882c6244a03ca77349d126337ed3861e454a0", + "0xe831c5b327832f9440cfc795e7f703cae82648704d05f7bd41b2acd4e07b2c1f", + "0x46c6926581d617ac8384583726ec7088f1e0df60bb075a1b43ab51fbdaa108b7", + "0x236eb9d731c98bc8407bcb9954e3297c51ed6a116f90f6d1ccdd8f4c89bf5dd0", + "0x6ea6994bc6b93be59e0e8f48e32f2afbbcc653d4c1b845625b8a5e280db809bd", + "0x3af35cfbcdd184c7579a273a73361271ae9e1a97ef89fb1f0e6dfe89a776c237", + "0x7553093da896b06cda700a41c0233274a089e633dcb5fd8d81ff0393491db2c6", + "0xc555ae61e8f86c775768be4a07045042a8d5898ca6dac14687327b89303d9ad2", + "0x4fc388b57b8d35c704e8c03be70f1c9ba03e638ffac704791c0aeec6d3dd8e2c", + "0xfd0ec61b6a525012d03781c254697a98ac0d4b1e55f46e3aa1ab819e7a90436f", + "0x1d7e68aa18a225ddede2856f421613f88872e89a7024919590930c43326a5bf4", + "0x37865c43f2db20bbfd51a1440e7cf95923c6b980ac6b7e3173d3f867d60d9b32", + "0x44de3419b85216c1d2ab63cf3a002c28835dd084c2e3ee0eb4ba92dc49d5a1b5", + "0xd5fd4d94d504e021eb7865b8aff7ed53c6afa96970fbacd678c2b78fd8c5badf", + "0x479043958f7b84ee3c20a9503fb10b3ecbb895b2b4eb4f69b3ea0b5243f881c8", + "0x683669e82fd55e4162c00a97b2af897395e3a1d3dc51c7f12f4e01e4e3cc3ef6", + "0x9dfc309c9a3382fad72a40825cf621e1dfe095aa77e3b00bd5a0f0c5445d6a34", + "0x63def4af1a927f696cf1abaeba3c172de583cdff6278d8db46e23ac8063ac042", + "0x682e98b0482b1282c896bc2920ce48328246d8d3301b5059988325950f19e0ae", + "0x929abbe6a8ebc0ac32f5ec6a8c1f728d733284e81c02477f606163521d86f642", + "0xd3deb41a543048541beb8b96a1f5b029da6ddb513327d025a5176e95dd4ab1ed", + "0x886432bd185ec9c30a459182ac4467aa9c0f590de8825712c8fe3d9cf7bef9eb", + "0xcc9f64743d0672261a614e9e5c09e9f8416d754f9c536e456a08ef885569a39d", + "0x55bd4b7d2d2ffe8ffd7054d1c8f912119ae793a23dd2d9a10f0ba94ee4b8ac9c", + "0x00a86e2d5dcaec027c9c49853eba467e910f39b4cae50bee85c40b48d34313c6", + "0x89ebc269c4a123f9622e89fd221d22776def13c4a9637a7f69176504ed48ac2e", + "0x808d7a4793aa0afd91d35a6a46eb4f3ed522c77716fbd27765ad2104d2638d75", + "0x5766e58d79181a27639e4e2b1c141de7825e6abe3996d3d06a518bc87044abb0", + "0x53e304b2ae212fac8b059d283f8f97553cb16fb3332e8833305a32db18abb5fa" + ] + }, "nodes": [ "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@52.232.243.152:30303", "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@192.81.208.223:30303", From f135c09b3616a450289002b5f61f5be028b147fc Mon Sep 17 00:00:00 2001 From: Sergey Pepyakin Date: Thu, 26 Apr 2018 15:00:42 +0300 Subject: [PATCH 19/95] Update wasmi and pwasm-utils (#8493) * Update wasmi to 0.2 New wasmi supports 32bit platforms and no longer requires a special feature to build for such platforms. * Update pwasm-utils to 0.1.5 --- Cargo.lock | 19 +++++++++++++------ ethcore/wasm/Cargo.toml | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb7936297e5..4587085dc0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1770,6 +1770,11 @@ dependencies = [ "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nan-preserving-float" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "net2" version = "0.2.31" @@ -2586,7 +2591,7 @@ dependencies = [ [[package]] name = "pwasm-utils" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3625,18 +3630,19 @@ dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)", - "pwasm-utils 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pwasm-utils 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", - "wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasmi" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3888,6 +3894,7 @@ dependencies = [ "checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729" "checksum multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9c35dac080fd6e16a99924c8dfdef0af89d797dd851adab25feaffacf7850d6" "checksum multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d49add5f49eb08bfc4d01ff286b84a48f53d45314f165c2d6efe477222d24f3" +"checksum nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34d4f00fcc2f4c9efa8cc971db0da9e28290e28e97af47585e48691ef10ff31f" "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum ntp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "143149743832c6543b60a8ef2a26cd9122dfecec2b767158e852a7beecf6d7a0" @@ -3928,7 +3935,7 @@ dependencies = [ "checksum proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "388d7ea47318c5ccdeb9ba6312cee7d3f65dd2804be8580a170fce410d50b786" "checksum protobuf 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40e2484e639dcae0985fc483ad76ce7ad78ee5aa092751d7d538f0b20d76486b" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" -"checksum pwasm-utils 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "54d440c3b56eee028aa5d4f18cbed8c6e0c9ae23563b93f344beb7e73854ea02" +"checksum pwasm-utils 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d51e9954a77aab7b4b606dc315a49cbed187924f163b6750cdf6d5677dbf0839" "checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3" "checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4" "checksum quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29cec87bc2816766d7e4168302d505dd06b0a825aed41b00633d296e922e02dd" @@ -4033,7 +4040,7 @@ dependencies = [ "checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d" "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb" +"checksum wasmi 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46df76793c28cd8f590d5667f540a81c1c245440a17b03560e381226e27cf348" "checksum webpki 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1622384bcb5458c6a3e3fa572f53ea8fef1cc85e535a2983dea87e9154fac2" "checksum webpki-roots 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155d4060e5befdf3a6076bd28c22513473d9900b763c9e4521acc6f78a75415c" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/ethcore/wasm/Cargo.toml b/ethcore/wasm/Cargo.toml index a39e6ee5292..a0362955d1d 100644 --- a/ethcore/wasm/Cargo.toml +++ b/ethcore/wasm/Cargo.toml @@ -12,4 +12,4 @@ libc = "0.2" pwasm-utils = "0.1" vm = { path = "../vm" } ethcore-logger = { path = "../../logger" } -wasmi = { version = "0.1.3", features = ["opt-in-32bit"] } +wasmi = { version = "0.2" } From 9376796bdb7c5c9aa8631acca8373a8df60f3ccb Mon Sep 17 00:00:00 2001 From: David Dorgan Date: Fri, 27 Apr 2018 14:01:47 +0100 Subject: [PATCH 20/95] Remove three old warp boot nodes. (#8497) --- ethcore/res/ethereum/foundation.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 4438718711a..6658b5e5227 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -2873,9 +2873,6 @@ "enode://00526537cb7e1aa6cf49714f0635fd0f608904d8d0693b949eea2dcdfdb0abbe4c794003a5fe57aa662d0a9215e8dfa4d2deb6ef0101c5e185e2617721813d43@40.65.122.44:30303", "enode://4a456b4b6e6ee1f51389763e51b80fe04782c762445d96c32a96ebd34bd9178c1894924d5101123eacfd4f0fc4da25b5e1ee7f18832ac0bf4c6d6ac81442d698@40.71.6.49:3030", "enode://68f85e7403976aa92318eff804cbe9bc988e0f5230d9d07ae4def030cbae16603262638e272d19875b7e5c54e296ba88ab6ec6e98face9e2537346c4dce78882@52.243.47.211:30303", - "enode://dc72806c3aa8fda207c8c018aba8d6cf143728b3628b6ded8d5e8cdeb8aa05cbd53f710ecd014c9a8f0d1e98f2874bff8afb15a229202f510a9c0258d1f6d109@159.203.210.80:30303", - "enode://5a62f19d35c0da8b576c9414568c728d4744e6e9d436c0f9db27456400011414f515871f13a6b8e0468534b5116cfe765d7630f680f1707a38467940a9f62511@45.55.33.62:30303", - "enode://605e04a43b1156966b3a3b66b980c87b7f18522f7f712035f84576016be909a2798a438b2b17b1a8c58db314d88539a77419ca4be36148c086900fba487c9d39@188.166.255.12:30303", "enode://1d1f7bcb159d308eb2f3d5e32dc5f8786d714ec696bb2f7e3d982f9bcd04c938c139432f13aadcaf5128304a8005e8606aebf5eebd9ec192a1471c13b5e31d49@138.201.223.35:30303", "enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303", "enode://3f1d12044546b76342d59d4a05532c14b85aa669704bfe1f864fe079415aa2c02d743e03218e57a33fb94523adb54032871a6c51b2cc5514cb7c7e35b3ed0a99@13.93.211.84:30303", From 01d399ad667b54a6fbe912dd04cadf7a3966251a Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Fri, 27 Apr 2018 15:02:45 +0200 Subject: [PATCH 21/95] Return error if RLP size of transaction exceeds the limit (#8473) * Return error if RLP size of transaction exceeds the limit * Review comments fixed * RLP check moved to verifier, corresponding pool test added --- Cargo.lock | 1 + ethcore/src/client/client.rs | 3 +-- ethcore/src/engines/mod.rs | 5 +++++ ethcore/src/machine.rs | 11 +++++++++++ ethcore/src/miner/pool_client.rs | 4 ++++ ethcore/src/spec/spec.rs | 5 +++++ ethcore/sync/src/chain.rs | 5 ----- ethcore/transaction/src/error.rs | 13 +++++++++++++ json/src/spec/params.rs | 3 +++ miner/Cargo.toml | 1 + miner/src/lib.rs | 1 + miner/src/pool/client.rs | 4 ++++ miner/src/pool/res/big_transaction.data | 1 + miner/src/pool/tests/client.rs | 14 ++++++++++++++ miner/src/pool/tests/mod.rs | 10 ++++++++++ miner/src/pool/tests/tx.rs | 13 +++++++++++++ miner/src/pool/verifier.rs | 7 +++++++ rpc/src/v1/helpers/errors.rs | 2 ++ 18 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 miner/src/pool/res/big_transaction.data diff --git a/Cargo.lock b/Cargo.lock index 4587085dc0e..48a0ab0d945 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -684,6 +684,7 @@ dependencies = [ "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "price-info 1.12.0", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "trace-time 0.1.0", "transaction-pool 1.12.0", diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 6ec318a03f9..ebc8961cd06 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -62,7 +62,6 @@ use ethcore_miner::pool::VerifiedTransaction; use parking_lot::{Mutex, RwLock}; use rand::OsRng; use receipt::{Receipt, LocalizedReceipt}; -use rlp::Rlp; use snapshot::{self, io as snapshot_io}; use spec::Spec; use state_db::StateDB; @@ -995,7 +994,7 @@ impl Client { let txs: Vec = transactions .iter() - .filter_map(|bytes| Rlp::new(bytes).as_val().ok()) + .filter_map(|bytes| self.engine().decode_transaction(bytes).ok()) .collect(); self.notify(|notify| { diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 8556879f95a..a17ae356e6f 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -426,6 +426,11 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> { fn additional_params(&self) -> HashMap { self.machine().additional_params() } + + /// Performs pre-validation of RLP decoded transaction before other processing + fn decode_transaction(&self, transaction: &[u8]) -> Result { + self.machine().decode_transaction(transaction) + } } // convenience wrappers for existing functions. diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index 7d488e0d0c9..e3bf7d340ca 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -34,6 +34,7 @@ use tx_filter::TransactionFilter; use ethereum_types::{U256, Address}; use bytes::BytesRef; +use rlp::Rlp; use vm::{CallType, ActionParams, ActionValue, ParamsType}; use vm::{EnvInfo, Schedule, CreateContractAddress}; @@ -376,6 +377,16 @@ impl EthereumMachine { "registrar".to_owned() => format!("{:x}", self.params.registrar) ] } + + /// Performs pre-validation of RLP decoded transaction before other processing + pub fn decode_transaction(&self, transaction: &[u8]) -> Result { + let rlp = Rlp::new(&transaction); + if rlp.as_raw().len() > self.params().max_transaction_size { + debug!("Rejected oversized transaction of {} bytes", rlp.as_raw().len()); + return Err(transaction::Error::TooBig) + } + rlp.as_val().map_err(|e| transaction::Error::InvalidRlp(e.to_string())) + } } /// Auxiliary data fetcher for an Ethereum machine. In Ethereum-like machines diff --git a/ethcore/src/miner/pool_client.rs b/ethcore/src/miner/pool_client.rs index 61153be0256..dfcdec684f8 100644 --- a/ethcore/src/miner/pool_client.rs +++ b/ethcore/src/miner/pool_client.rs @@ -145,6 +145,10 @@ impl<'a, C: 'a> pool::client::Client for PoolClient<'a, C> where } } } + + fn decode_transaction(&self, transaction: &[u8]) -> Result { + self.engine.decode_transaction(transaction) + } } impl<'a, C: 'a> NonceClient for PoolClient<'a, C> where diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 7f6d650dd4f..156ab8f15a8 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -48,6 +48,8 @@ use trace::{NoopTracer, NoopVMTracer}; pub use ethash::OptimizeFor; +const MAX_TRANSACTION_SIZE: usize = 300 * 1024; + // helper for formatting errors. fn fmt_err(f: F) -> String { format!("Spec json is invalid: {}", f) @@ -123,6 +125,8 @@ pub struct CommonParams { pub max_code_size_transition: BlockNumber, /// Transaction permission managing contract address. pub transaction_permission_contract: Option

, + /// Maximum size of transaction's RLP payload + pub max_transaction_size: usize, } impl CommonParams { @@ -238,6 +242,7 @@ impl From for CommonParams { registrar: p.registrar.map_or_else(Address::new, Into::into), node_permission_contract: p.node_permission_contract.map(Into::into), max_code_size: p.max_code_size.map_or(u64::max_value(), Into::into), + max_transaction_size: p.max_transaction_size.map_or(MAX_TRANSACTION_SIZE, Into::into), max_code_size_transition: p.max_code_size_transition.map_or(0, Into::into), transaction_permission_contract: p.transaction_permission_contract.map(Into::into), wasm_activation_transition: p.wasm_activation_transition.map_or( diff --git a/ethcore/sync/src/chain.rs b/ethcore/sync/src/chain.rs index eaab13b6f4b..25d9a09f6bc 100644 --- a/ethcore/sync/src/chain.rs +++ b/ethcore/sync/src/chain.rs @@ -140,7 +140,6 @@ const MAX_PEERS_PROPAGATION: usize = 128; const MAX_PEER_LAG_PROPAGATION: BlockNumber = 20; const MAX_NEW_HASHES: usize = 64; const MAX_NEW_BLOCK_AGE: BlockNumber = 20; -const MAX_TRANSACTION_SIZE: usize = 300*1024; // maximal packet size with transactions (cannot be greater than 16MB - protocol limitation). const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024; // Maximal number of transactions in sent in single packet. @@ -1517,10 +1516,6 @@ impl ChainSync { let mut transactions = Vec::with_capacity(item_count); for i in 0 .. item_count { let rlp = r.at(i)?; - if rlp.as_raw().len() > MAX_TRANSACTION_SIZE { - debug!("Skipped oversized transaction of {} bytes", rlp.as_raw().len()); - continue; - } let tx = rlp.as_raw().to_vec(); transactions.push(tx); } diff --git a/ethcore/transaction/src/error.rs b/ethcore/transaction/src/error.rs index e38dc3ac675..eeeba4e53a9 100644 --- a/ethcore/transaction/src/error.rs +++ b/ethcore/transaction/src/error.rs @@ -18,6 +18,7 @@ use std::{fmt, error}; use ethereum_types::U256; use ethkey; +use rlp; use unexpected::OutOfBounds; #[derive(Debug, PartialEq, Clone)] @@ -74,6 +75,10 @@ pub enum Error { NotAllowed, /// Signature error InvalidSignature(String), + /// Transaction too big + TooBig, + /// Invalid RLP encoding + InvalidRlp(String), } impl From for Error { @@ -82,6 +87,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: rlp::DecoderError) -> Self { + Error::InvalidRlp(format!("{}", err)) + } +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::Error::*; @@ -106,6 +117,8 @@ impl fmt::Display for Error { InvalidChainId => "Transaction of this chain ID is not allowed on this chain.".into(), InvalidSignature(ref err) => format!("Transaction has invalid signature: {}.", err), NotAllowed => "Sender does not have permissions to execute this type of transction".into(), + TooBig => "Transaction too big".into(), + InvalidRlp(ref err) => format!("Transaction has invalid RLP structure: {}.", err), }; f.write_fmt(format_args!("Transaction error ({})", msg)) diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 4a1efe2a7f9..ce47086df17 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -113,6 +113,9 @@ pub struct Params { /// See main EthashParams docs. #[serde(rename="maxCodeSize")] pub max_code_size: Option, + /// Maximum size of transaction RLP payload. + #[serde(rename="maxTransactionSize")] + pub max_transaction_size: Option, /// See main EthashParams docs. #[serde(rename="maxCodeSizeTransition")] pub max_code_size_transition: Option, diff --git a/miner/Cargo.toml b/miner/Cargo.toml index 95dd888dc9a..707352484e2 100644 --- a/miner/Cargo.toml +++ b/miner/Cargo.toml @@ -28,6 +28,7 @@ log = "0.3" parking_lot = "0.5" price-info = { path = "../price-info" } rayon = "1.0" +rlp = { path = "../util/rlp" } trace-time = { path = "../util/trace-time" } transaction-pool = { path = "../transaction-pool" } diff --git a/miner/src/lib.rs b/miner/src/lib.rs index 197823aec79..08ea7d204fb 100644 --- a/miner/src/lib.rs +++ b/miner/src/lib.rs @@ -30,6 +30,7 @@ extern crate linked_hash_map; extern crate parking_lot; extern crate price_info; extern crate rayon; +extern crate rlp; extern crate trace_time; extern crate transaction_pool as txpool; diff --git a/miner/src/pool/client.rs b/miner/src/pool/client.rs index 4243e8d26bf..622e9a84927 100644 --- a/miner/src/pool/client.rs +++ b/miner/src/pool/client.rs @@ -62,6 +62,10 @@ pub trait Client: fmt::Debug + Sync { /// Classify transaction (check if transaction is filtered by some contracts). fn transaction_type(&self, tx: &transaction::SignedTransaction) -> TransactionType; + + /// Performs pre-validation of RLP decoded transaction + fn decode_transaction(&self, transaction: &[u8]) + -> Result; } /// State nonce client diff --git a/miner/src/pool/res/big_transaction.data b/miner/src/pool/res/big_transaction.data new file mode 100644 index 00000000000..15703f893ad --- /dev/null +++ b/miner/src/pool/res/big_transaction.data @@ -0,0 +1 @@ +6060604052341561000f57600080fd5b604051610b0d380380610b0d833981016040528080518201919060200180518201919060200180518201919050508260009080519060200190610053929190610092565b50816002908051906020019061006a92919061011c565b50806001908051906020019061008192919061011c565b506001600381905550505050610204565b82805482825590600052602060002090810192821561010b579160200282015b8281111561010a5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906100b2565b5b509050610118919061019c565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061015d57805160ff191683800117855561018b565b8280016001018555821561018b579182015b8281111561018a57825182559160200191906001019061016f565b5b50905061019891906101df565b5090565b6101dc91905b808211156101d857600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016101a2565b5090565b90565b61020191905b808211156101fd5760008160009055506001016101e5565b5090565b90565b6108fa806102136000396000f300606060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806317ac53a21461007d57806324c12bf61461019a57806335aa2e4414610228578063affed0e01461028b578063b7ab4db5146102b4578063c19d93fb1461031e575b600080fd5b341561008857600080fd5b610198600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506103ac565b005b34156101a557600080fd5b6101ad610600565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101ed5780820151818401526020810190506101d2565b50505050905090810190601f16801561021a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561023357600080fd5b610249600480803590602001909190505061069e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561029657600080fd5b61029e6106dd565b6040518082815260200191505060405180910390f35b34156102bf57600080fd5b6102c76106e3565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561030a5780820151818401526020810190506102ef565b505050509050019250505060405180910390f35b341561032957600080fd5b610331610777565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610371578082015181840152602081019050610356565b50505050905090810190601f16801561039e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000806040805190810160405280876040518082805190602001908083835b6020831015156103f057805182526020820191506020810190506020830392506103cb565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191660001916815260200160035460010260001916600019168152506040518082600260200280838360005b8381101561046657808201518184015260208101905061044b565b5050505090500191505060405180910390209150600090505b6000805490508110156105d55760008181548110151561049b57fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660018387848151811015156104ee57fe5b90602001906020020151878581518110151561050657fe5b90602001906020020151878681518110151561051e57fe5b90602001906020020151604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156105a057600080fd5b50506020604051035173ffffffffffffffffffffffffffffffffffffffff161415156105c857fe5b808060010191505061047f565b85600190805190602001906105eb929190610815565b50600160035401600381905550505050505050565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106965780601f1061066b57610100808354040283529160200191610696565b820191906000526020600020905b81548152906001019060200180831161067957829003601f168201915b505050505081565b6000818154811015156106ad57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60035481565b6106eb610895565b600080548060200260200160405190810160405280929190818152602001828054801561076d57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610723575b5050505050905090565b60018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561080d5780601f106107e25761010080835404028352916020019161080d565b820191906000526020600020905b8154815290600101906020018083116107f057829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061085657805160ff1916838001178555610884565b82800160010185558215610884579182015b82811115610883578251825591602001919060010190610868565b5b50905061089191906108a9565b5090565b602060405190810160405280600081525090565b6108cb91905b808211156108c75760008160009055506001016108af565b5090565b905600a165627a7a723058200ae0215fae320b646a22fdd58278b328f46d915bd65ddbfeb5b4a09643d6e0220029000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000010000000000000000000000007ffbe3512782069be388f41be4d8eb350672d3a500000000000000000000000000000000000000000000000000000000000000e88b98f0e95488c3849ba24320a00a047c39b3ca3af8f066d82d849104eb0218150baf61620b321c8d2db0c8e351fd17826cd2cd13296287fb02cab742db410ba4346b4c13c1f81cc52dd5ee3dd7773e23842fe5d8e29db6da6f8f6f42964f118486b0c8d7971cfb8ed4926622774c92e495ae47dd481eb03090ad09a1fb4a2cd0ad4b108efeb408f160f34fae6f6d9843574f3e37dd11ec54dd69fa7dfa919257e760a78d6cccec92785381f9554b3da1249c4844e259b0f57180034fb63bd6136132f822f6472a31c68b8a60646bcbddfa4ddd3be0fe4457a4f691a6542bf798a4fa6b0990284166000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001056e81f171bcc55a6ff8345e692c0f86e000000000000000000000000000000006060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d833981016060604052341561000f57600080fd5b604051610b0d380380610b0d83398101 diff --git a/miner/src/pool/tests/client.rs b/miner/src/pool/tests/client.rs index 7f7be64cc8d..a00cc541ebc 100644 --- a/miner/src/pool/tests/client.rs +++ b/miner/src/pool/tests/client.rs @@ -15,17 +15,21 @@ // along with Parity. If not, see . use ethereum_types::{U256, H256, Address}; +use rlp::Rlp; use transaction::{self, Transaction, SignedTransaction, UnverifiedTransaction}; use pool; use pool::client::AccountDetails; +const MAX_TRANSACTION_SIZE: usize = 15 * 1024; + #[derive(Debug, Clone)] pub struct TestClient { account_details: AccountDetails, gas_required: U256, is_service_transaction: bool, local_address: Address, + max_transaction_size: usize, } impl Default for TestClient { @@ -39,6 +43,7 @@ impl Default for TestClient { gas_required: 21_000.into(), is_service_transaction: false, local_address: Default::default(), + max_transaction_size: MAX_TRANSACTION_SIZE, } } } @@ -116,6 +121,15 @@ impl pool::client::Client for TestClient { pool::client::TransactionType::Regular } } + + fn decode_transaction(&self, transaction: &[u8]) -> Result { + let rlp = Rlp::new(&transaction); + if rlp.as_raw().len() > self.max_transaction_size { + return Err(transaction::Error::TooBig) + } + rlp.as_val().map_err(|e| transaction::Error::InvalidRlp(e.to_string())) + } + } impl pool::client::NonceClient for TestClient { diff --git a/miner/src/pool/tests/mod.rs b/miner/src/pool/tests/mod.rs index 340cb751586..0d8e38a6e11 100644 --- a/miner/src/pool/tests/mod.rs +++ b/miner/src/pool/tests/mod.rs @@ -755,3 +755,13 @@ fn should_clear_cache_after_timeout_for_local() { // then assert_eq!(txq.pending(TestClient::new(), 0, 1002, None).len(), 2); } + +#[test] +fn should_reject_big_transaction() { + let txq = new_queue(); + let big_tx = Tx::default().big_one(); + let res = txq.import(TestClient::new(), vec![ + verifier::Transaction::Local(PendingTransaction::new(big_tx, transaction::Condition::Timestamp(1000).into())) + ]); + assert_eq!(res, vec![Err(transaction::Error::TooBig)]); +} \ No newline at end of file diff --git a/miner/src/pool/tests/tx.rs b/miner/src/pool/tests/tx.rs index ee0a7390eed..c0f8751ebba 100644 --- a/miner/src/pool/tests/tx.rs +++ b/miner/src/pool/tests/tx.rs @@ -87,6 +87,19 @@ impl Tx { nonce: self.nonce.into() } } + + pub fn big_one(self) -> SignedTransaction { + let keypair = Random.generate().unwrap(); + let tx = Transaction { + action: transaction::Action::Create, + value: U256::from(100), + data: include_str!("../res/big_transaction.data").from_hex().unwrap(), + gas: self.gas.into(), + gas_price: self.gas_price.into(), + nonce: self.nonce.into() + }; + tx.sign(keypair.secret(), None) + } } pub trait TxExt: Sized { type Out; diff --git a/miner/src/pool/verifier.rs b/miner/src/pool/verifier.rs index 92d2eb9c86b..0a89a784b11 100644 --- a/miner/src/pool/verifier.rs +++ b/miner/src/pool/verifier.rs @@ -27,6 +27,7 @@ use std::sync::Arc; use std::sync::atomic::{self, AtomicUsize}; use ethereum_types::{U256, H256}; +use rlp::Encodable; use transaction; use txpool; @@ -222,6 +223,12 @@ impl txpool::Verifier for Verifier { Transaction::Local(tx) => tx, }; + // Verify RLP payload + if let Err(err) = self.client.decode_transaction(&transaction.rlp_bytes()) { + debug!(target: "txqueue", "[{:?}] Rejected transaction's rlp payload", err); + bail!(err) + } + let sender = transaction.sender(); let account_details = self.client.account_details(&sender); diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index acff796646e..4f3289a116b 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -338,6 +338,8 @@ pub fn transaction_message(error: &TransactionError) -> String { RecipientBanned => "Recipient is banned in local queue.".into(), CodeBanned => "Code is banned in local queue.".into(), NotAllowed => "Transaction is not permitted.".into(), + TooBig => "Transaction is too big, see chain specification for the limit.".into(), + InvalidRlp(ref descr) => format!("Invalid RLP data: {}", descr), } } From e36c4ecc9814ee098431c4cb54f5c2c7efb219da Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Fri, 27 Apr 2018 15:04:27 +0200 Subject: [PATCH 22/95] `duration_ns: u64 -> duration: Duration` (#8457) * duration_ns: u64 -> duration: Duration * format on millis {:.2} -> {} --- ethcore/private-tx/src/lib.rs | 3 ++- ethcore/src/client/chain_notify.rs | 3 ++- ethcore/src/client/client.rs | 24 +++++++------------ ethcore/src/snapshot/watcher.rs | 9 ++++--- ethcore/sync/src/api.rs | 6 ++--- ethcore/sync/src/tests/helpers.rs | 3 ++- parity/informant.rs | 4 ++-- rpc/src/v1/impls/eth_pubsub.rs | 3 ++- rpc/src/v1/tests/mocked/eth_pubsub.rs | 12 ++++++---- secret_store/src/acl_storage.rs | 3 ++- secret_store/src/key_server_set.rs | 3 ++- .../src/listener/service_contract_listener.rs | 3 ++- updater/src/updater.rs | 2 +- 13 files changed, 43 insertions(+), 35 deletions(-) diff --git a/ethcore/private-tx/src/lib.rs b/ethcore/private-tx/src/lib.rs index 12028ddf121..26a31fc7ae3 100644 --- a/ethcore/private-tx/src/lib.rs +++ b/ethcore/private-tx/src/lib.rs @@ -66,6 +66,7 @@ pub use error::{Error, ErrorKind}; use std::sync::{Arc, Weak}; use std::collections::{HashMap, HashSet}; +use std::time::Duration; use ethereum_types::{H128, H256, U256, Address}; use hash::keccak; use rlp::*; @@ -667,7 +668,7 @@ fn find_account_password(passwords: &Vec, account_provider: &AccountProv } impl ChainNotify for Provider { - fn new_blocks(&self, imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: u64) { + fn new_blocks(&self, imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: Duration) { if !imported.is_empty() { trace!("New blocks imported, try to prune the queue"); if let Err(err) = self.process_queue() { diff --git a/ethcore/src/client/chain_notify.rs b/ethcore/src/client/chain_notify.rs index ccfb2558d61..a1f84d2a139 100644 --- a/ethcore/src/client/chain_notify.rs +++ b/ethcore/src/client/chain_notify.rs @@ -17,6 +17,7 @@ use bytes::Bytes; use ethereum_types::H256; use transaction::UnverifiedTransaction; +use std::time::Duration; /// Messages to broadcast via chain pub enum ChainMessageType { @@ -40,7 +41,7 @@ pub trait ChainNotify : Send + Sync { _sealed: Vec, // Block bytes. _proposed: Vec, - _duration: u64, + _duration: Duration, ) { // does nothing by default } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index ebc8961cd06..8d305fc0572 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -18,7 +18,7 @@ use std::collections::{HashSet, HashMap, BTreeMap, VecDeque}; use std::str::FromStr; use std::sync::{Arc, Weak}; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; -use std::time::{Instant}; +use std::time::{Instant, Duration}; use itertools::Itertools; // util @@ -32,7 +32,7 @@ use util_error::UtilError; // other use ethereum_types::{H256, Address, U256}; use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock}; -use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute, TransactionAddress}; +use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute, TransactionAddress}; use client::ancient_import::AncientVerifier; use client::Error as ClientError; use client::{ @@ -120,7 +120,7 @@ impl<'a> ::std::ops::Sub<&'a ClientReport> for ClientReport { self.blocks_imported -= other.blocks_imported; self.transactions_applied -= other.transactions_applied; self.gas_processed = self.gas_processed - other.gas_processed; - self.state_db_mem = higher_mem - lower_mem; + self.state_db_mem = higher_mem - lower_mem; self } @@ -331,11 +331,7 @@ impl Importer { self.block_queue.mark_as_bad(&invalid_blocks); } let is_empty = self.block_queue.mark_as_good(&imported_blocks); - let duration_ns = { - let elapsed = start.elapsed(); - elapsed.as_secs() * 1_000_000_000 + elapsed.subsec_nanos() as u64 - }; - (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration_ns, is_empty) + (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, start.elapsed(), is_empty) }; { @@ -1434,7 +1430,7 @@ impl ImportBlock for Client { bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain)); } let status = self.block_status(BlockId::Hash(header.parent_hash())); - if status == BlockStatus::Unknown || status == BlockStatus::Pending { + if status == BlockStatus::Unknown || status == BlockStatus::Pending { bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(header.parent_hash()))); } } @@ -1497,7 +1493,7 @@ impl Call for Client { } fn estimate_gas(&self, t: &SignedTransaction, state: &Self::State, header: &Header) -> Result { - let (mut upper, max_upper, env_info) = { + let (mut upper, max_upper, env_info) = { let init = *header.gas_limit(); let max = init * U256::from(10); @@ -2096,10 +2092,7 @@ impl ImportSealedBlock for Client { retracted.clone(), vec![h.clone()], vec![], - { - let elapsed = start.elapsed(); - elapsed.as_secs() * 1_000_000_000 + elapsed.subsec_nanos() as u64 - }, + start.elapsed(), ); }); self.db.read().flush().expect("DB flush failed."); @@ -2109,6 +2102,7 @@ impl ImportSealedBlock for Client { impl BroadcastProposalBlock for Client { fn broadcast_proposal_block(&self, block: SealedBlock) { + const DURATION_ZERO: Duration = Duration::from_millis(0); self.notify(|notify| { notify.new_blocks( vec![], @@ -2117,7 +2111,7 @@ impl BroadcastProposalBlock for Client { vec![], vec![], vec![block.rlp_bytes()], - 0, + DURATION_ZERO, ); }); } diff --git a/ethcore/src/snapshot/watcher.rs b/ethcore/src/snapshot/watcher.rs index 841fa1982ac..936feaefba8 100644 --- a/ethcore/src/snapshot/watcher.rs +++ b/ethcore/src/snapshot/watcher.rs @@ -24,7 +24,7 @@ use io::IoChannel; use ethereum_types::H256; use bytes::Bytes; -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; // helper trait for transforming hashes to numbers and checking if syncing. trait Oracle: Send + Sync { @@ -107,7 +107,7 @@ impl ChainNotify for Watcher { _: Vec, _: Vec, _: Vec, - _duration: u64) + _duration: Duration) { if self.oracle.is_major_importing() { return } @@ -136,6 +136,7 @@ mod tests { use ethereum_types::{H256, U256}; use std::collections::HashMap; + use std::time::Duration; struct TestOracle(HashMap); @@ -158,6 +159,8 @@ mod tests { // helper harness for tests which expect a notification. fn harness(numbers: Vec, period: u64, history: u64, expected: Option) { + const DURATION_ZERO: Duration = Duration::from_millis(0); + let hashes: Vec<_> = numbers.clone().into_iter().map(|x| H256::from(U256::from(x))).collect(); let map = hashes.clone().into_iter().zip(numbers).collect(); @@ -175,7 +178,7 @@ mod tests { vec![], vec![], vec![], - 0, + DURATION_ZERO, ); } diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index c66a1c6a625..5e96f11cf37 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -413,7 +413,7 @@ impl ChainNotify for EthSync { retracted: Vec, sealed: Vec, proposed: Vec, - _duration: u64) + _duration: Duration) { use light::net::Announcement; @@ -452,7 +452,7 @@ impl ChainNotify for EthSync { fn start(&self) { match self.network.start().map_err(Into::into) { - Err(ErrorKind::Io(ref e)) if e.kind() == io::ErrorKind::AddrInUse => warn!("Network port {:?} is already in use, make sure that another instance of an Ethereum client is not running or change the port using the --port option.", self.network.config().listen_address.expect("Listen address is not set.")), + Err(ErrorKind::Io(ref e)) if e.kind() == io::ErrorKind::AddrInUse => warn!("Network port {:?} is already in use, make sure that another instance of an Ethereum client is not running or change the port using the --port option.", self.network.config().listen_address.expect("Listen address is not set.")), Err(err) => warn!("Error starting network: {}", err), _ => {}, } @@ -625,7 +625,7 @@ impl NetworkConfiguration { config_path: self.config_path, net_config_path: self.net_config_path, listen_address: match self.listen_address { None => None, Some(addr) => Some(SocketAddr::from_str(&addr)?) }, - public_address: match self.public_address { None => None, Some(addr) => Some(SocketAddr::from_str(&addr)?) }, + public_address: match self.public_address { None => None, Some(addr) => Some(SocketAddr::from_str(&addr)?) }, udp_port: self.udp_port, nat_enabled: self.nat_enabled, discovery_enabled: self.discovery_enabled, diff --git a/ethcore/sync/src/tests/helpers.rs b/ethcore/sync/src/tests/helpers.rs index 086dc503bba..54467adb775 100644 --- a/ethcore/sync/src/tests/helpers.rs +++ b/ethcore/sync/src/tests/helpers.rs @@ -16,6 +16,7 @@ use std::collections::{VecDeque, HashSet, HashMap}; use std::sync::Arc; +use std::time::Duration; use ethereum_types::H256; use parking_lot::{RwLock, Mutex}; use bytes::Bytes; @@ -538,7 +539,7 @@ impl ChainNotify for EthPeer { retracted: Vec, sealed: Vec, proposed: Vec, - _duration: u64) + _duration: Duration) { self.new_blocks_queue.write().push_back(NewBlockMessage { imported, diff --git a/parity/informant.rs b/parity/informant.rs index 896e80ec53d..29f732e0853 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -351,7 +351,7 @@ impl Informant { } impl ChainNotify for Informant { - fn new_blocks(&self, imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, duration: u64) { + fn new_blocks(&self, imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, duration: Duration) { let mut last_import = self.last_import.lock(); let client = &self.target.client; @@ -373,7 +373,7 @@ impl ChainNotify for Informant { Colour::White.bold().paint(format!("{}", header_view.hash())), Colour::Yellow.bold().paint(format!("{}", block.transactions_count())), Colour::Yellow.bold().paint(format!("{:.2}", header_view.gas_used().low_u64() as f32 / 1000000f32)), - Colour::Purple.bold().paint(format!("{:.2}", duration as f32 / 1000000f32)), + Colour::Purple.bold().paint(format!("{}", duration.as_milliseconds())), Colour::Blue.bold().paint(format!("{:.2}", size as f32 / 1024f32)), if skipped > 0 { format!(" + another {} block(s) containing {} tx(s)", diff --git a/rpc/src/v1/impls/eth_pubsub.rs b/rpc/src/v1/impls/eth_pubsub.rs index d7e6112a93a..1a872f5600a 100644 --- a/rpc/src/v1/impls/eth_pubsub.rs +++ b/rpc/src/v1/impls/eth_pubsub.rs @@ -18,6 +18,7 @@ use std::sync::{Arc, Weak}; use std::collections::BTreeMap; +use std::time::Duration; use jsonrpc_core::{BoxFuture, Result, Error}; use jsonrpc_core::futures::{self, Future, IntoFuture}; @@ -227,7 +228,7 @@ impl ChainNotify for ChainNotificationHandler { _sealed: Vec, // Block bytes. _proposed: Vec, - _duration: u64, + _duration: Duration, ) { const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed"; let headers = enacted diff --git a/rpc/src/v1/tests/mocked/eth_pubsub.rs b/rpc/src/v1/tests/mocked/eth_pubsub.rs index 15b178d504e..fb28ba31274 100644 --- a/rpc/src/v1/tests/mocked/eth_pubsub.rs +++ b/rpc/src/v1/tests/mocked/eth_pubsub.rs @@ -20,11 +20,15 @@ use jsonrpc_core::MetaIoHandler; use jsonrpc_core::futures::{self, Stream, Future}; use jsonrpc_pubsub::Session; +use std::time::Duration; + use v1::{EthPubSub, EthPubSubClient, Metadata}; use ethcore::client::{TestBlockChainClient, EachBlockWith, ChainNotify}; use parity_reactor::EventLoop; +const DURATION_ZERO: Duration = Duration::from_millis(0); + #[test] fn should_subscribe_to_new_heads() { // given @@ -53,13 +57,13 @@ fn should_subscribe_to_new_heads() { assert_eq!(io.handle_request_sync(request, metadata.clone()), Some(response.to_owned())); // Check notifications - handler.new_blocks(vec![], vec![], vec![h1], vec![], vec![], vec![], 0); + handler.new_blocks(vec![], vec![], vec![h1], vec![], vec![], vec![], DURATION_ZERO); let (res, receiver) = receiver.into_future().wait().unwrap(); let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x1","extraData":"0x","gasLimit":"0xf4240","gasUsed":"0x0","hash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x1","parentHash":"0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x1c9","stateRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","timestamp":"0x0","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},"subscription":"0x416d77337e24399d"}}"#; assert_eq!(res, Some(response.into())); // Notify about two blocks - handler.new_blocks(vec![], vec![], vec![h2, h3], vec![], vec![], vec![], 0); + handler.new_blocks(vec![], vec![], vec![h2, h3], vec![], vec![], vec![], DURATION_ZERO); // Receive both let (res, receiver) = receiver.into_future().wait().unwrap(); @@ -125,7 +129,7 @@ fn should_subscribe_to_logs() { assert_eq!(io.handle_request_sync(request, metadata.clone()), Some(response.to_owned())); // Check notifications (enacted) - handler.new_blocks(vec![], vec![], vec![h1], vec![], vec![], vec![], 0); + handler.new_blocks(vec![], vec![], vec![h1], vec![], vec![], vec![], DURATION_ZERO); let (res, receiver) = receiver.into_future().wait().unwrap(); let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"address":"0x0000000000000000000000000000000000000005","blockHash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","blockNumber":"0x1","data":"0x","logIndex":"0x0","topics":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"transactionHash":""#.to_owned() + &format!("0x{:x}", tx_hash) @@ -133,7 +137,7 @@ fn should_subscribe_to_logs() { assert_eq!(res, Some(response.into())); // Check notifications (retracted) - handler.new_blocks(vec![], vec![], vec![], vec![h1], vec![], vec![], 0); + handler.new_blocks(vec![], vec![], vec![], vec![h1], vec![], vec![], DURATION_ZERO); let (res, receiver) = receiver.into_future().wait().unwrap(); let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"address":"0x0000000000000000000000000000000000000005","blockHash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","blockNumber":"0x1","data":"0x","logIndex":"0x0","topics":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"transactionHash":""#.to_owned() + &format!("0x{:x}", tx_hash) diff --git a/secret_store/src/acl_storage.rs b/secret_store/src/acl_storage.rs index 58d9bc47756..6399660aff3 100644 --- a/secret_store/src/acl_storage.rs +++ b/secret_store/src/acl_storage.rs @@ -16,6 +16,7 @@ use std::sync::Arc; use std::collections::{HashMap, HashSet}; +use std::time::Duration; use parking_lot::{Mutex, RwLock}; use ethcore::client::{BlockId, ChainNotify, CallContract, RegistryInfo}; use ethereum_types::{H256, Address}; @@ -75,7 +76,7 @@ impl AclStorage for OnChainAclStorage { } impl ChainNotify for OnChainAclStorage { - fn new_blocks(&self, _imported: Vec, _invalid: Vec, enacted: Vec, retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: u64) { + fn new_blocks(&self, _imported: Vec, _invalid: Vec, enacted: Vec, retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: Duration) { if !enacted.is_empty() || !retracted.is_empty() { self.contract.lock().update() } diff --git a/secret_store/src/key_server_set.rs b/secret_store/src/key_server_set.rs index 7697408557e..cb324dbc9ba 100644 --- a/secret_store/src/key_server_set.rs +++ b/secret_store/src/key_server_set.rs @@ -17,6 +17,7 @@ use std::sync::Arc; use std::net::SocketAddr; use std::collections::{BTreeMap, HashSet}; +use std::time::Duration; use parking_lot::Mutex; use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify, CallContract, RegistryInfo}; use ethcore::filter::Filter; @@ -162,7 +163,7 @@ impl KeyServerSet for OnChainKeyServerSet { } impl ChainNotify for OnChainKeyServerSet { - fn new_blocks(&self, _imported: Vec, _invalid: Vec, enacted: Vec, retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: u64) { + fn new_blocks(&self, _imported: Vec, _invalid: Vec, enacted: Vec, retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: Duration) { if !enacted.is_empty() || !retracted.is_empty() { self.contract.lock().update(enacted, retracted) } diff --git a/secret_store/src/listener/service_contract_listener.rs b/secret_store/src/listener/service_contract_listener.rs index 2975eaa134c..1e17be8e557 100644 --- a/secret_store/src/listener/service_contract_listener.rs +++ b/secret_store/src/listener/service_contract_listener.rs @@ -17,6 +17,7 @@ use std::collections::HashSet; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::time::Duration; use std::thread; use parking_lot::Mutex; use ethcore::client::ChainNotify; @@ -428,7 +429,7 @@ impl Drop for ServiceContractListener { } impl ChainNotify for ServiceContractListener { - fn new_blocks(&self, _imported: Vec, _invalid: Vec, enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: u64) { + fn new_blocks(&self, _imported: Vec, _invalid: Vec, enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: Duration) { let enacted_len = enacted.len(); if enacted_len == 0 { return; diff --git a/updater/src/updater.rs b/updater/src/updater.rs index 3b5ce01a935..c5f45c7658a 100644 --- a/updater/src/updater.rs +++ b/updater/src/updater.rs @@ -660,7 +660,7 @@ impl Updater, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: u64) { + fn new_blocks(&self, _imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: Duration) { match (self.client.upgrade(), self.sync.as_ref().and_then(Weak::upgrade)) { (Some(ref c), Some(ref s)) if !s.status().is_syncing(c.queue_info()) => self.poll(), _ => {}, From 44c68221a8e45a7e1fab9c3e3326459a92e0c154 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Fri, 27 Apr 2018 17:46:17 +0200 Subject: [PATCH 23/95] Remove unused dependency `bigint` (#8505) * remove unused dependency bigint in * remove bigint in rpc_cli --- Cargo.lock | 13 ------------- rpc_cli/Cargo.toml | 1 - util/memorydb/Cargo.toml | 1 - 3 files changed, 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48a0ab0d945..3176c3ab3d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,16 +102,6 @@ dependencies = [ "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bigint" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bincode" version = "0.8.0" @@ -1634,7 +1624,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "memorydb" version = "0.1.1" dependencies = [ - "bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1", @@ -2806,7 +2795,6 @@ dependencies = [ name = "rpc-cli" version = "1.4.0" dependencies = [ - "bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "parity-rpc 1.12.0", "parity-rpc-client 1.4.0", @@ -3783,7 +3771,6 @@ dependencies = [ "checksum base32 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b9605ba46d61df0410d8ac686b0007add8172eba90e8e909c347856fe794d8c" "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" "checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4" -"checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd" "checksum bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e103c8b299b28a9c6990458b7013dc4a8356a9b854c51b9883241f5866fac36e" "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c" "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" diff --git a/rpc_cli/Cargo.toml b/rpc_cli/Cargo.toml index 0bda94ab674..7d4652c38cb 100644 --- a/rpc_cli/Cargo.toml +++ b/rpc_cli/Cargo.toml @@ -9,6 +9,5 @@ version = "1.4.0" [dependencies] futures = "0.1" rpassword = "1.0" -bigint = "4.0" parity-rpc = { path = "../rpc" } parity-rpc-client = { path = "../rpc_client" } diff --git a/util/memorydb/Cargo.toml b/util/memorydb/Cargo.toml index da832278146..41c41bb628e 100644 --- a/util/memorydb/Cargo.toml +++ b/util/memorydb/Cargo.toml @@ -6,7 +6,6 @@ description = "in-memory implementation of hashdb" license = "GPL-3.0" [dependencies] -bigint = "4.0" elastic-array = "0.10" heapsize = "0.4" ethereum-types = "0.3" From 2a829b1f1a68f07ba3b235bb6692fc7799092308 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 1 May 2018 20:16:03 +0800 Subject: [PATCH 24/95] Show imported messages for light client (#8517) --- ethcore/light/src/client/service.rs | 7 ++++++- parity/informant.rs | 29 ++++++++++++++++++++++++++++- parity/run.rs | 2 +- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/ethcore/light/src/client/service.rs b/ethcore/light/src/client/service.rs index 3d13be16b4a..a3ec8a36866 100644 --- a/ethcore/light/src/client/service.rs +++ b/ethcore/light/src/client/service.rs @@ -30,7 +30,7 @@ use kvdb::KeyValueDB; use cache::Cache; use parking_lot::Mutex; -use super::{ChainDataFetcher, Client, Config as ClientConfig}; +use super::{ChainDataFetcher, LightChainNotify, Client, Config as ClientConfig}; /// Errors on service initialization. #[derive(Debug)] @@ -86,6 +86,11 @@ impl Service { }) } + /// Set the actor to be notified on certain chain events + pub fn add_notify(&self, notify: Arc) { + self.client.add_listener(Arc::downgrade(¬ify)); + } + /// Register an I/O handler on the service. pub fn register_handler(&self, handler: Arc + Send>) -> Result<(), IoError> { self.io_service.register_handler(handler) diff --git a/parity/informant.rs b/parity/informant.rs index 29f732e0853..5c2e0ab89d3 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -33,7 +33,7 @@ use ethcore::snapshot::service::Service as SnapshotService; use sync::{LightSyncProvider, LightSync, SyncProvider, ManageNetwork}; use io::{TimerToken, IoContext, IoHandler}; use light::Cache as LightDataCache; -use light::client::LightChainClient; +use light::client::{LightChainClient, LightChainNotify}; use number_prefix::{binary_prefix, Standalone, Prefixed}; use parity_rpc::{is_major_importing}; use parity_rpc::informant::RpcStats; @@ -395,6 +395,33 @@ impl ChainNotify for Informant { } } +impl LightChainNotify for Informant { + fn new_headers(&self, good: &[H256]) { + let mut last_import = self.last_import.lock(); + let client = &self.target.client; + + let importing = self.target.is_major_importing(); + let ripe = Instant::now() > *last_import + Duration::from_secs(1) && !importing; + + if ripe { + if let Some(header) = good.last().and_then(|h| client.block_header(BlockId::Hash(*h))) { + info!(target: "import", "Imported {} {} ({} Mgas){}", + Colour::White.bold().paint(format!("#{}", header.number())), + Colour::White.bold().paint(format!("{}", header.hash())), + Colour::Yellow.bold().paint(format!("{:.2}", header.gas_used().low_u64() as f32 / 1000000f32)), + if good.len() > 1 { + format!(" + another {} header(s)", + Colour::Red.bold().paint(format!("{}", good.len() - 1))) + } else { + String::new() + } + ); + *last_import = Instant::now(); + } + } + } +} + const INFO_TIMER: TimerToken = 0; impl IoHandler for Informant { diff --git a/parity/run.rs b/parity/run.rs index f07f67caa83..fdb32293b9c 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -412,7 +412,7 @@ fn execute_light_impl(cmd: RunCmd, logger: Arc) -> Result Date: Tue, 1 May 2018 20:47:04 +0800 Subject: [PATCH 25/95] Directly return None if tracing is disabled (#8504) * Directly return None if tracing is disabled * Address gumbles: release read locks as fast as possible --- ethcore/src/client/client.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 8d305fc0572..bc20de3dd86 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1868,6 +1868,10 @@ impl BlockChainClient for Client { } fn filter_traces(&self, filter: TraceFilter) -> Option> { + if !self.tracedb.read().tracing_enabled() { + return None; + } + let start = self.block_number(filter.range.start)?; let end = self.block_number(filter.range.end)?; @@ -1887,6 +1891,10 @@ impl BlockChainClient for Client { } fn trace(&self, trace: TraceId) -> Option { + if !self.tracedb.read().tracing_enabled() { + return None; + } + let trace_address = trace.address; self.transaction_address(trace.transaction) .and_then(|tx_address| { @@ -1896,6 +1904,10 @@ impl BlockChainClient for Client { } fn transaction_traces(&self, transaction: TransactionId) -> Option> { + if !self.tracedb.read().tracing_enabled() { + return None; + } + self.transaction_address(transaction) .and_then(|tx_address| { self.block_number(BlockId::Hash(tx_address.block_hash)) @@ -1904,6 +1916,10 @@ impl BlockChainClient for Client { } fn block_traces(&self, block: BlockId) -> Option> { + if !self.tracedb.read().tracing_enabled() { + return None; + } + self.block_number(block) .and_then(|number| self.tracedb.read().block_traces(number)) } From 849f5d9a4449ea3631cc49f43f7d8dd04a03831d Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Tue, 1 May 2018 15:01:49 +0200 Subject: [PATCH 26/95] Hardware Wallet trait (#8071) * getting started with replacing HardwareWalletManager * trezor and ledger impls the new trait with some drawbacks * Everything move to the new trait * It required lifetime annotations in the trait because [u8] in unsized * Lets now start moving entry point from HardwareWalletManager * rename trait to Wallet * move thread management to the actual wallets * Moved thread management to each respective Wallet * Cleaned up pub items that is needed to be pub * Wallet trait more or less finished * Cleaned up docs * fix tests * omit removed docs * fix spelling, naming och remove old comments * ledger test is broken, add correct logging format * So locally on my machine Linux Ubuntu 17.10 the test doesn't panic but on the CI server libusb::Context::new() fails which I don't understand because it has worked before * Additionally the ledger test is optional so I lean toward ignoring it the CI Server * ignore hardware tests by default * more verbose checking in ledger test --- hw/src/ledger.rs | 397 ++++++++++++++++++++++++++--------------------- hw/src/lib.rs | 132 ++++++++-------- hw/src/trezor.rs | 344 +++++++++++++++++++++------------------- 3 files changed, 473 insertions(+), 400 deletions(-) diff --git a/hw/src/ledger.rs b/hw/src/ledger.rs index e7d616d4f9f..e31d49f1304 100644 --- a/hw/src/ledger.rs +++ b/hw/src/ledger.rs @@ -20,8 +20,11 @@ use std::cmp::min; use std::fmt; use std::str::FromStr; +use std::sync::atomic; +use std::sync::atomic::AtomicBool; use std::sync::{Arc, Weak}; use std::time::{Duration, Instant}; +use std::thread; use ethereum_types::{H256, Address}; use ethkey::Signature; @@ -29,12 +32,12 @@ use hidapi; use libusb; use parking_lot::{Mutex, RwLock}; -use super::{WalletInfo, KeyPath}; +use super::{WalletInfo, KeyPath, Device, Wallet, USB_DEVICE_CLASS_DEVICE}; /// Ledger vendor ID -pub const LEDGER_VID: u16 = 0x2c97; -/// Legder product IDs: [Nano S and Blue] -pub const LEDGER_PIDS: [u16; 2] = [0x0000, 0x0001]; +const LEDGER_VID: u16 = 0x2c97; +/// Ledger product IDs: [Nano S and Blue] +const LEDGER_PIDS: [u16; 2] = [0x0000, 0x0001]; const ETH_DERIVATION_PATH_BE: [u8; 17] = [4, 0x80, 0, 0, 44, 0x80, 0, 0, 60, 0x80, 0, 0, 0, 0, 0, 0, 0]; // 44'/60'/0'/0 const ETC_DERIVATION_PATH_BE: [u8; 21] = [5, 0x80, 0, 0, 44, 0x80, 0, 0, 60, 0x80, 0x02, 0x73, 0xd0, 0x80, 0, 0, 0, 0, 0, 0, 0]; // 44'/60'/160720'/0'/0 @@ -64,8 +67,10 @@ pub enum Error { KeyNotFound, /// Signing has been cancelled by user. UserCancel, - /// Invalid Device + /// Invalid device InvalidDevice, + /// Impossible error + ImpossibleError, } impl fmt::Display for Error { @@ -77,6 +82,7 @@ impl fmt::Display for Error { Error::KeyNotFound => write!(f, "Key not found"), Error::UserCancel => write!(f, "Operation has been cancelled"), Error::InvalidDevice => write!(f, "Unsupported product was entered"), + Error::ImpossibleError => write!(f, "Placeholder error"), } } } @@ -100,157 +106,43 @@ pub struct Manager { key_path: RwLock, } -#[derive(Debug)] -struct Device { - path: String, - info: WalletInfo, -} - impl Manager { /// Create a new instance. - pub fn new(hidapi: Arc>) -> Manager { - Manager { + pub fn new(hidapi: Arc>, exiting: Arc) -> Result, libusb::Error> { + let manager = Arc::new(Manager { usb: hidapi, devices: RwLock::new(Vec::new()), key_path: RwLock::new(KeyPath::Ethereum), - } - } - - /// Re-populate device list. Only those devices that have Ethereum app open will be added. - pub fn update_devices(&self) -> Result { - let mut usb = self.usb.lock(); - usb.refresh_devices(); - let devices = usb.devices(); - let mut new_devices = Vec::new(); - let mut num_new_devices = 0; - for device in devices { - trace!("Checking device: {:?}", device); - if device.vendor_id != LEDGER_VID || !LEDGER_PIDS.contains(&device.product_id) { - continue; - } - match self.read_device_info(&usb, &device) { - Ok(info) => { - debug!("Found device: {:?}", info); - if !self.devices.read().iter().any(|d| d.path == info.path) { - num_new_devices += 1; + }); + + let usb_context = Arc::new(libusb::Context::new()?); + let m = manager.clone(); + + // Subscribe to all Ledger devices + // This means that we need to check that the given productID is supported + // None => LIBUSB_HOTPLUG_MATCH_ANY, in other words that all are subscribed to + // More info can be found: + usb_context.register_callback( + Some(LEDGER_VID), None, Some(USB_DEVICE_CLASS_DEVICE), + Box::new(EventHandler::new(Arc::downgrade(&manager)))).expect("usb_callback"); + + // Ledger event handler thread + thread::Builder::new() + .spawn(move || { + if let Err(e) = m.update_devices() { + debug!(target: "hw", "Ledger couldn't connect at startup, error: {}", e); + } + loop { + usb_context.handle_events(Some(Duration::from_millis(500))) + .unwrap_or_else(|e| debug!(target: "hw", "Ledger event handler error: {}", e)); + if exiting.load(atomic::Ordering::Acquire) { + break; } - new_devices.push(info); - } - Err(e) => debug!("Error reading device info: {}", e), - }; - } - *self.devices.write() = new_devices; - Ok(num_new_devices) - } + }) + .ok(); - /// Select key derivation path for a known chain. - pub fn set_key_path(&self, key_path: KeyPath) { - *self.key_path.write() = key_path; - } - - fn read_device_info(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result { - let mut handle = self.open_path(|| usb.open_path(&dev_info.path))?; - let address = Self::read_wallet_address(&mut handle, *self.key_path.read())?; - let manufacturer = dev_info.manufacturer_string.clone().unwrap_or("Unknown".to_owned()); - let name = dev_info.product_string.clone().unwrap_or("Unknown".to_owned()); - let serial = dev_info.serial_number.clone().unwrap_or("Unknown".to_owned()); - Ok(Device { - path: dev_info.path.clone(), - info: WalletInfo { - name: name, - manufacturer: manufacturer, - serial: serial, - address: address, - }, - }) - } - - fn read_wallet_address(handle: &hidapi::HidDevice, key_path: KeyPath) -> Result { - let ver = Self::send_apdu(handle, commands::GET_APP_CONFIGURATION, 0, 0, &[])?; - if ver.len() != 4 { - return Err(Error::Protocol("Version packet size mismatch")); - } - - let (major, minor, patch) = (ver[1], ver[2], ver[3]); - if major < 1 || (major == 1 && minor == 0 && patch < 3) { - return Err(Error::Protocol("App version 1.0.3 is required.")); - } - - let eth_path = Ð_DERIVATION_PATH_BE[..]; - let etc_path = &ETC_DERIVATION_PATH_BE[..]; - let derivation_path = match key_path { - KeyPath::Ethereum => eth_path, - KeyPath::EthereumClassic => etc_path, - }; - let key_and_address = Self::send_apdu(handle, commands::GET_ETH_PUBLIC_ADDRESS, 0, 0, derivation_path)?; - if key_and_address.len() != 107 { // 1 + 65 PK + 1 + 40 Addr (ascii-hex) - return Err(Error::Protocol("Key packet size mismatch")); - } - let address_string = ::std::str::from_utf8(&key_and_address[67..107]) - .map_err(|_| Error::Protocol("Invalid address string"))?; - - let address = Address::from_str(&address_string) - .map_err(|_| Error::Protocol("Invalid address string"))?; - - Ok(address) - } - - /// List connected wallets. This only returns wallets that are ready to be used. - pub fn list_devices(&self) -> Vec { - self.devices.read().iter().map(|d| d.info.clone()).collect() - } - - /// Get wallet info. - pub fn device_info(&self, address: &Address) -> Option { - self.devices.read().iter().find(|d| &d.info.address == address).map(|d| d.info.clone()) - } - - /// Sign transaction data with wallet managing `address`. - pub fn sign_transaction(&self, address: &Address, data: &[u8]) -> Result { - let usb = self.usb.lock(); - let devices = self.devices.read(); - let device = devices.iter().find(|d| &d.info.address == address).ok_or(Error::KeyNotFound)?; - let handle = self.open_path(|| usb.open_path(&device.path))?; - - let eth_path = Ð_DERIVATION_PATH_BE[..]; - let etc_path = &ETC_DERIVATION_PATH_BE[..]; - let derivation_path = match *self.key_path.read() { - KeyPath::Ethereum => eth_path, - KeyPath::EthereumClassic => etc_path, - }; - const MAX_CHUNK_SIZE: usize = 255; - let mut chunk: [u8; MAX_CHUNK_SIZE] = [0; MAX_CHUNK_SIZE]; - &mut chunk[0..derivation_path.len()].copy_from_slice(derivation_path); - let mut dest_offset = derivation_path.len(); - let mut data_pos = 0; - let mut result; - loop { - let p1 = if data_pos == 0 { 0x00 } else { 0x80 }; - let dest_left = MAX_CHUNK_SIZE - dest_offset; - let chunk_data_size = min(dest_left, data.len() - data_pos); - &mut chunk[dest_offset..][0..chunk_data_size].copy_from_slice(&data[data_pos..][0..chunk_data_size]); - result = Self::send_apdu(&handle, commands::SIGN_ETH_TRANSACTION, p1, 0, &chunk[0..(dest_offset + chunk_data_size)])?; - dest_offset = 0; - data_pos += chunk_data_size; - if data_pos == data.len() { - break; - } - } - - if result.len() != 65 { - return Err(Error::Protocol("Signature packet size mismatch")); - } - let v = (result[0] + 1) % 2; - let r = H256::from_slice(&result[1..33]); - let s = H256::from_slice(&result[33..65]); - Ok(Signature::from_rsv(&r, &s, v)) - } - - fn open_path(&self, f: F) -> Result - where F: Fn() -> Result - { - f().map_err(Into::into) + Ok(manager) } fn send_apdu(handle: &hidapi::HidDevice, command: u8, p1: u8, p2: u8, data: &[u8]) -> Result, Error> { @@ -285,7 +177,7 @@ impl Manager { chunk_index += 1; } - // read response + // Read response chunk_index = 0; let mut message_size = 0; let mut message = Vec::new(); @@ -303,7 +195,7 @@ impl Manager { let mut offset = 5; if seq == 0 { - // read message size and status word. + // Read message size and status word. if chunk_size < 7 { return Err(Error::Protocol("Unexpected chunk header")); } @@ -321,7 +213,7 @@ impl Manager { return Err(Error::Protocol("No status word")); } let status = (message[message.len() - 2] as usize) << 8 | (message[message.len() - 1] as usize); - debug!("Read status {:x}", status); + debug!(target: "hw", "Read status {:x}", status); match status { 0x6700 => Err(Error::Protocol("Incorrect length")), 0x6982 => Err(Error::Protocol("Security status not satisfied (Canceled by user)")), @@ -365,18 +257,166 @@ fn try_connect_polling(ledger: Arc, timeout: Duration) -> bool { false } +impl <'a>Wallet<'a> for Manager { + type Error = Error; + type Transaction = &'a [u8]; + + fn sign_transaction(&self, address: &Address, transaction: Self::Transaction) -> Result { + let usb = self.usb.lock(); + let devices = self.devices.read(); + let device = devices.iter().find(|d| &d.info.address == address).ok_or(Error::KeyNotFound)?; + let handle = self.open_path(|| usb.open_path(&device.path))?; + + let eth_path = Ð_DERIVATION_PATH_BE[..]; + let etc_path = &ETC_DERIVATION_PATH_BE[..]; + let derivation_path = match *self.key_path.read() { + KeyPath::Ethereum => eth_path, + KeyPath::EthereumClassic => etc_path, + }; + const MAX_CHUNK_SIZE: usize = 255; + let mut chunk: [u8; MAX_CHUNK_SIZE] = [0; MAX_CHUNK_SIZE]; + &mut chunk[0..derivation_path.len()].copy_from_slice(derivation_path); + let mut dest_offset = derivation_path.len(); + let mut data_pos = 0; + let mut result; + loop { + let p1 = if data_pos == 0 { 0x00 } else { 0x80 }; + let dest_left = MAX_CHUNK_SIZE - dest_offset; + let chunk_data_size = min(dest_left, transaction.len() - data_pos); + &mut chunk[dest_offset..][0..chunk_data_size].copy_from_slice(&transaction[data_pos..][0..chunk_data_size]); + result = Self::send_apdu(&handle, commands::SIGN_ETH_TRANSACTION, p1, 0, &chunk[0..(dest_offset + chunk_data_size)])?; + dest_offset = 0; + data_pos += chunk_data_size; + if data_pos == transaction.len() { + break; + } + } + + if result.len() != 65 { + return Err(Error::Protocol("Signature packet size mismatch")); + } + let v = (result[0] + 1) % 2; + let r = H256::from_slice(&result[1..33]); + let s = H256::from_slice(&result[33..65]); + Ok(Signature::from_rsv(&r, &s, v)) + } + + fn set_key_path(&self, key_path: KeyPath) { + *self.key_path.write() = key_path; + } + + fn update_devices(&self) -> Result { + let mut usb = self.usb.lock(); + usb.refresh_devices(); + let devices = usb.devices(); + let mut new_devices = Vec::new(); + let mut num_new_devices = 0; + for device in devices { + trace!("Checking device: {:?}", device); + if device.vendor_id != LEDGER_VID || !LEDGER_PIDS.contains(&device.product_id) { + continue; + } + match self.read_device(&usb, &device) { + Ok(info) => { + debug!(target: "hw", "Found device: {:?}", info); + if !self.devices.read().iter().any(|d| d.path == info.path) { + num_new_devices += 1; + } + new_devices.push(info); + + } + Err(e) => debug!(target: "hw", "Error reading device info: {}", e), + }; + } + *self.devices.write() = new_devices; + Ok(num_new_devices) + } + + fn read_device(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result { + let handle = self.open_path(|| usb.open_path(&dev_info.path))?; + let manufacturer = dev_info.manufacturer_string.clone().unwrap_or("Unknown".to_owned()); + let name = dev_info.product_string.clone().unwrap_or("Unknown".to_owned()); + let serial = dev_info.serial_number.clone().unwrap_or("Unknown".to_owned()); + match self.get_address(&handle) { + Ok(Some(addr)) => { + Ok(Device { + path: dev_info.path.clone(), + info: WalletInfo { + name: name, + manufacturer: manufacturer, + serial: serial, + address: addr, + }, + }) + } + // This variant is not possible, but the trait forces this return type + Ok(None) => Err(Error::ImpossibleError), + Err(e) => Err(e), + } + } + + fn list_devices(&self) -> Vec { + self.devices.read().iter().map(|d| d.info.clone()).collect() + } + + // Not used because it is not supported by Ledger + fn list_locked_devices(&self) -> Vec { + vec![] + } + + fn get_wallet(&self, address: &Address) -> Option { + self.devices.read().iter().find(|d| &d.info.address == address).map(|d| d.info.clone()) + } + + fn get_address(&self, device: &hidapi::HidDevice) -> Result, Self::Error> { + let ver = Self::send_apdu(device, commands::GET_APP_CONFIGURATION, 0, 0, &[])?; + if ver.len() != 4 { + return Err(Error::Protocol("Version packet size mismatch")); + } + + let (major, minor, patch) = (ver[1], ver[2], ver[3]); + if major < 1 || (major == 1 && minor == 0 && patch < 3) { + return Err(Error::Protocol("App version 1.0.3 is required.")); + } + + let eth_path = Ð_DERIVATION_PATH_BE[..]; + let etc_path = &ETC_DERIVATION_PATH_BE[..]; + let derivation_path = match *self.key_path.read() { + KeyPath::Ethereum => eth_path, + KeyPath::EthereumClassic => etc_path, + }; + let key_and_address = Self::send_apdu(device, commands::GET_ETH_PUBLIC_ADDRESS, 0, 0, derivation_path)?; + if key_and_address.len() != 107 { // 1 + 65 PK + 1 + 40 Addr (ascii-hex) + return Err(Error::Protocol("Key packet size mismatch")); + } + let address_string = ::std::str::from_utf8(&key_and_address[67..107]) + .map_err(|_| Error::Protocol("Invalid address string"))?; + + let address = Address::from_str(&address_string) + .map_err(|_| Error::Protocol("Invalid address string"))?; + + Ok(Some(address)) + } + + fn open_path(&self, f: F) -> Result + where F: Fn() -> Result + { + f().map_err(Into::into) + } +} + /// Ledger event handler -/// A seperate thread is hanedling incoming events +/// A separate thread is handling incoming events /// /// Note, that this run to completion and race-conditions can't occur but this can /// therefore starve other events for being process with a spinlock or similar -pub struct EventHandler { +struct EventHandler { ledger: Weak, } impl EventHandler { /// Ledger event handler constructor - pub fn new(ledger: Weak) -> Self { + fn new(ledger: Weak) -> Self { Self { ledger: ledger } } } @@ -402,27 +442,34 @@ impl libusb::Hotplug for EventHandler { } #[test] +#[ignore] +/// This test can't be run without an actual ledger device connected fn smoke() { use rustc_hex::FromHex; - let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().unwrap())); - let manager = Manager::new(hidapi.clone()); - manager.update_devices().unwrap(); - for d in &*manager.devices.read() { - println!("Device: {:?}", d); - } - - if let Some(address) = manager.list_devices().first().map(|d| d.address.clone()) { - let tx = FromHex::from_hex("eb018504a817c80082520894a6ca2e6707f2cc189794a9dd459d5b05ed1bcd1c8703f26fcfb7a22480018080").unwrap(); - let signature = manager.sign_transaction(&address, &tx); - println!("Got {:?}", signature); - assert!(signature.is_ok()); - let large_tx = FromHex::from_hex("f8cb81968504e3b2920083024f279475b02a3c39710d6a3f2870d0d788299d48e790f180b8a4b61d27f6000000000000000000000000e1af840a5a1cb1efdf608a97aa632f4aa39ed199000000000000000000000000000000000000000000000000105ff43f46a9a800000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018080").unwrap(); - let signature = manager.sign_transaction(&address, &large_tx); - println!("Got {:?}", signature); - assert!(signature.is_ok()); - let huge_tx = FromHex::from_hex("f935e98201048505d21dba00833b82608080b935946103e86003908155620d2f00600455601460055560a060405260608190527f2e2e2e00000000000000000000000000000000000000000000000000000000006080908152600d805460008290527f2e2e2e00000000000000000000000000000000000000000000000000000000068255909260008051602062003474833981519152602060026001851615610100026000190190941693909304601f0192909204820192909190620000dc565b82800160010185558215620000dc579182015b82811115620000dc578251825591602001919060010190620000bf565b5b50620001009291505b80821115620000fc5760008155600101620000e6565b5090565b5050600e8054600360ff199182168117909255604080518082019091528281527f2e2e2e00000000000000000000000000000000000000000000000000000000006020918201908152600f80546000829052825160069516949094178155937f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac80260026101006001871615026000190190951694909404601f019290920483019290620001d7565b82800160010185558215620001d7579182015b82811115620001d7578251825591602001919060010190620001ba565b5b50620001fb9291505b80821115620000fc5760008155600101620000e6565b5090565b50506010805460ff19166001179055346200000057604051620034943803806200349483398101604090815281516020830151918301516060840151919390810191015b5b5b60068054600160a060020a0319166c01000000000000000000000000338102041790558151600d80546000829052909160008051602062003474833981519152602060026101006001861615026000190190941693909304601f908101849004820193870190839010620002c157805160ff1916838001178555620002f1565b82800160010185558215620002f1579182015b82811115620002f1578251825591602001919060010190620002d4565b5b50620003159291505b80821115620000fc5760008155600101620000e6565b5090565b505080600f9080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200036557805160ff191683800117855562000395565b8280016001018555821562000395579182015b828111156200039557825182559160200191906001019062000378565b5b50620003b99291505b80821115620000fc5760008155600101620000e6565b5090565b5050600980546c01000000000000000000000000808602819004600160a060020a0319928316179092556007805487840293909304929091169190911790555b505050505b613066806200040e6000396000f300606060405236156102035760e060020a600035046306fdde03811461034b578063095ea7b3146103c65780630b0b6d5b146103ed5780631b1ccc47146103fc57806320e870931461047757806323b872dd1461049657806325b29d84146104c057806327187991146104df578063277ccde2146104f15780632e1fbfcd14610510578063308b2fdc14610532578063313ce5671461055457806338cc48311461057757806340eddc4e146105a057806341f4793a146105bf578063467ed261146105de578063471ad963146105fd5780634e860ebb1461060f5780634efbe9331461061e57806354786b4e1461064257806354e35ba2146106bd57806358793ad4146106d25780635abedab21461073f5780635af2f8211461074e57806360483a3f1461076d57806360d12fa0146107da578063698f2e84146108035780636a749986146108155780636d5f66391461082a5780636e9c36831461083c57806370a082311461085e5780637a290fe5146108805780637e7541461461088f57806394c41bdb1461090a57806395d89b4114610929578063962a64cd146109a4578063a0b6533214610a09578063a9059cbb14610a2b578063ab62438f14610a52578063b63ca98114610aa9578063b7c54c6f14610abb578063c4e41b2214610ada578063ca7c4dba14610af9578063cb79e31b14610b18578063dd62ed3e14610b3a575b6103495b60006000600c546000141561021b57610000565b600354600c54670de0b6b3a764000091349091020204915060009050816001600030600160a060020a031681526020019081526020016000205410156102c557600160a060020a033016600090815260016020526040902054600c54909250828115610000570466038d7ea4c68000023403905033600160a060020a03166108fc829081150290604051809050600060405180830381858888f1935050505015156102c557610000565b5b600160a060020a03338116600081815260016020908152604080832080548801905530909416825283822080548790039055601380543487900301908190559154600c548551908152918201879052845190949293927f5a0391f2a67f11ed0034b68f8cf14e7e41d6f86e0a7622f2af5ea8f07b488396928290030190a45b5050565b005b3461000057610358610b5f565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103b85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576103d9600435602435610bed565b604080519115158252519081900360200190f35b3461000057610349610c58565b005b3461000057610358610dbc565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103b85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3461000057610484610e5a565b60408051918252519081900360200190f35b34610000576103d9600435602435604435610ef9565b604080519115158252519081900360200190f35b3461000057610484610ff3565b60408051918252519081900360200190f35b3461000057610349600435611002565b005b346100005761048461105a565b60408051918252519081900360200190f35b3461000057610484600435611061565b60408051918252519081900360200190f35b346100005761048460043561108d565b60408051918252519081900360200190f35b34610000576105616110b9565b6040805160ff9092168252519081900360200190f35b34610000576105846110c2565b60408051600160a060020a039092168252519081900360200190f35b34610000576104846110c7565b60408051918252519081900360200190f35b34610000576104846110ce565b60408051918252519081900360200190f35b34610000576104846110d5565b60408051918252519081900360200190f35b3461000057610349600435611174565b005b34610000576103496113b5565b005b34610000576103d9600435611407565b604080519115158252519081900360200190f35b3461000057610358611549565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103b85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576103496004356024356115e7565b005b346100005760408051602060046024803582810135601f8101859004850286018501909652858552610726958335959394604494939290920191819084018382808284375094965061167e95505050505050565b6040805192835290151560208301528051918290030190f35b3461000057610349611c13565b005b3461000057610484611d46565b60408051918252519081900360200190f35b346100005760408051602060046024803582810135601f81018590048502860185019096528585526107269583359593946044949392909201918190840183828082843750949650611d4d95505050505050565b6040805192835290151560208301528051918290030190f35b3461000057610584612303565b60408051600160a060020a039092168252519081900360200190f35b3461000057610349600435612313565b005b3461000057610349600435602435612347565b005b346100005761034960043561252f565b005b3461000057610484600435612941565b60408051918252519081900360200190f35b346100005761048460043561298d565b60408051918252519081900360200190f35b34610000576103496129ac565b005b3461000057610358612a13565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103b85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3461000057610484612ab1565b60408051918252519081900360200190f35b3461000057610358612ab8565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103b85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3461000057610484600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843750949650612b4695505050505050565b60408051918252519081900360200190f35b3461000057610484600435612b63565b60408051918252519081900360200190f35b34610000576103d9600435602435612b8c565b604080519115158252519081900360200190f35b3461000057610349600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437509496505093359350612c3c92505050565b005b3461000057610349600435612f38565b005b3461000057610484612f90565b60408051918252519081900360200190f35b346100005761048461300c565b60408051918252519081900360200190f35b3461000057610484613013565b60408051918252519081900360200190f35b346100005761048460043561301a565b60408051918252519081900360200190f35b3461000057610484600435602435613039565b60408051918252519081900360200190f35b600d805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b601a54600090600160a060020a03161515610c7257610000565b600160a060020a0333166000908152600a60205260409020541515610c9657610000565b600160a060020a0333166000908152601d602052604090205460ff1615610cbc57610000565b601b54426212750090910111610cd157610000565b600160a060020a0333166000818152601d60209081526040808320805460ff19166001179055600a8252918290208054601c805490910190555482519384529083015280517f475c7605c08471fdc551a58d2c318b163628c5852f69323a1b91c34eb0bb09339281900390910190a150601154601c54606490910490604682029010610db857601a5460068054600160a060020a031916606060020a600160a060020a0393841681020417908190556040805191909216815290517f6b8184e23a898262087be50aa3ea5de648451e63f94413e810586c25282d58c2916020908290030190a15b5b50565b604080516020808201835260008252600d8054845160026001831615610100026000190190921691909104601f810184900484028201840190955284815292939091830182828015610e4f5780601f10610e2457610100808354040283529160200191610e4f565b820191906000526020600020905b815481529060010190602001808311610e3257829003601f168201915b505050505090505b90565b600f805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152600093610ef39391929091830182828015610ee95780601f10610ebe57610100808354040283529160200191610ee9565b820191906000526020600020905b815481529060010190602001808311610ecc57829003601f168201915b5050505050612b46565b90505b90565b600160a060020a038316600090815260016020526040812054829010801590610f495750600160a060020a0380851660009081526002602090815260408083203390941683529290522054829010155b8015610f555750600082115b15610fe757600160a060020a03808516600081815260016020908152604080832080548890039055878516808452818420805489019055848452600283528184203390961684529482529182902080548790039055815186815291517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3506001610feb56610feb565b5060005b5b9392505050565b600160a060020a033016315b90565b60065433600160a060020a0390811691161461101d57610000565b600c8190556040805182815290517f0bbd501ef336990995d82b5e3fd82a15abe1ff10c982757a1698ac5d1c3e79579181900360200190a15b5b50565b600b545b90565b6000601882815481101561000057906000526020600020906007020160005b506004015490505b919050565b6000601882815481101561000057906000526020600020906007020160005b506001015490505b919050565b600e5460ff1681565b305b90565b6013545b90565b601c545b90565b600d805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152600093610ef39391929091830182828015610ee95780601f10610ebe57610100808354040283529160200191610ee9565b820191906000526020600020905b815481529060010190602001808311610ecc57829003601f168201915b5050505050612b46565b90505b90565b600654600090819033600160a060020a0390811691161461119457610000565b60008381526014602052604090205415156111ae57610000565b60008381526014602052604090206005015433600160a060020a039081169116146111d857610000565b60008381526014602052604090206005015460a060020a900460ff16156111fe57610000565b601154600084815260146020526040902060040154606490910460370292508290111561122a57610000565b60008381526014602052604081206005015460a860020a900460ff16600181116100005714156112eb57600954600084815260146020908152604080832060058101546001909101548251840185905282517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201526024810191909152915194169363a9059cbb93604480840194938390030190829087803b156100005760325a03f1156100005750611389915050565b60008381526014602052604080822060058101546001909101549151600160a060020a039091169282156108fc02929190818181858888f160008881526014602090815260409182902060058101546001909101548351600160a060020a0390921682529181019190915281519297507f2648a7e2f9c34700b91370233666e5118fa8be3e0c21fed4f7402b941df8efdd9650829003019350915050a15b6000838152601460205260409020600501805460a060020a60ff02191660a060020a1790555b5b505050565b60065433600160a060020a039081169116146113d057610000565b6010805460ff191690556040517fb48c7f694f0a3b9b22d7e61c60ff8aebbb107314b6b698fc489ff3f017cb57e090600090a15b5b565b600060006000600760009054906101000a9004600160a060020a0316600160a060020a031663d4884b566000604051602001526040518160e060020a028152600401809050602060405180830381600087803b156100005760325a03f115610000575050604051514210905061147c57610000565b60085433600160a060020a0390811691161461149757610000565b5050600b54600160a060020a03328181166000908152600a6020526040902080549386029384019055601180548401905560128054860190556008549092916114e39130911683610ef9565b506114ee8282612b8c565b50600054601154600b5460408051918252602082018590528051600160a060020a038716927fb4d6befef2def3d17bcb13c2b882ec4fa047f33157446d3e0e6094b2a21609ac92908290030190a4600192505b5b5050919050565b604080516020808201835260008252600f8054845160026001831615610100026000190190921691909104601f810184900484028201840190955284815292939091830182828015610e4f5780601f10610e2457610100808354040283529160200191610e4f565b820191906000526020600020905b815481529060010190602001808311610e3257829003601f168201915b505050505090505b90565b60065433600160a060020a0390811691161461160257610000565b60105460ff16151561161357610000565b600160a060020a0330166000908152600160209081526040808320805485019055600c859055825484019283905580518481529051839286927f10cb430288a1696de11938bc5362c6f8c60e58808237bce4436b93a8573e00c3929081900390910190a45b5b5b5050565b6040805161010081018252600080825260208083018290528351908101845281815292820192909252606081018290526080810182905260a0810182905260c0810182905260e08101829052600654829182918291829133600160a060020a039081169116146116ed57610000565b60115460649004935060056016541115801561170c5750836005540288115b1561171657610000565b61171e612f90565b8811156117305761172d612f90565b97505b60003642604051808484808284378201915050828152602001935050505060405180910390209250600454420191506101006040519081016040528084815260200189815260200188815260200183815260200160008152602001338152602001600081526020016000815260200150905080601460008560001916815260200190815260200160002060008201518160000155602082015181600101556040820151816002019080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061182057805160ff191683800117855561184d565b8280016001018555821561184d579182015b8281111561184d578251825591602001919060010190611832565b5b5061186e9291505b8082111561186a5760008155600101611856565b5090565b5050606082015160038201556080820151600482015560a08201516005909101805460c084015160e09094015160f860020a90810281900460a860020a0260a860020a60ff02199582029190910460a060020a0260a060020a60ff0219606060020a95860295909504600160a060020a031990931692909217939093161792909216179055601880546001810180835582818380158290116119c9576007028160070283600052602060002091820191016119c991905b8082111561186a5760006000820160009055600182016000905560028201805460018160011615610100020316600290046000825580601f10611968575061199a565b601f01602090049060005260206000209081019061199a91905b8082111561186a5760008155600101611856565b5090565b5b50506000600382018190556004820155600581018054600160b060020a0319169055600701611925565b5090565b5b505050916000526020600020906007020160005b83909190915060008201518160000155602082015181600101556040820151816002019080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611a4a57805160ff1916838001178555611a77565b82800160010185558215611a77579182015b82811115611a77578251825591602001919060010190611a5c565b5b50611a989291505b8082111561186a5760008155600101611856565b5090565b5050606082015181600301556080820151816004015560a08201518160050160006101000a815481600160a060020a030219169083606060020a90810204021790555060c08201518160050160146101000a81548160ff021916908360f860020a90810204021790555060e08201518160050160156101000a81548160ff021916908360f860020a90810204021790555050505060166000815460010191905081905550426017819055507f1a1eea7d2a0f099c2f19efb4e101fcf220558c9f4fbc6961b33fbe02d3a7be908389848a3360405180866000191681526020018581526020018481526020018060200183600160a060020a031681526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015611bee5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a1826001955095505b5b505050509250929050565b60065460009033600160a060020a03908116911614611c3157610000565b600760009054906101000a9004600160a060020a0316600160a060020a031663d4884b566000604051602001526040518160e060020a028152600401809050602060405180830381600087803b156100005760325a03f1156100005750506040515162dd7c00014210159050611ca657610000565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1600954909550600160a060020a0316935063a9059cbb9250339150611cef9050612f90565b6000604051602001526040518360e060020a0281526004018083600160a060020a0316815260200182815260200192505050602060405180830381600087803b156100005760325a03f115610000575050505b5b50565b6016545b90565b6040805161010081018252600080825260208083018290528351908101845281815292820192909252606081018290526080810182905260a0810182905260c0810182905260e08101829052600654829182918291829133600160a060020a03908116911614611dbc57610000565b60105460ff1615611dcc57610000565b6000611dd73061298d565b1115611de257610000565b6017546212750001421015611df657610000565b6013546064900493508360055402881115611e1057610000565b30600160a060020a031631881115611e305730600160a060020a03163197505b60003642604051808484808284378201915050828152602001935050505060405180910390209250600454420191506101006040519081016040528084815260200189815260200188815260200183815260200160008152602001338152602001600081526020016001815260200150905080601460008560001916815260200190815260200160002060008201518160000155602082015181600101556040820151816002019080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611f2057805160ff1916838001178555611f4d565b82800160010185558215611f4d579182015b82811115611f4d578251825591602001919060010190611f32565b5b50611f6e9291505b8082111561186a5760008155600101611856565b5090565b5050606082015160038201556080820151600482015560a08201516005909101805460c084015160e09094015160f860020a90810281900460a860020a0260a860020a60ff02199582029190910460a060020a0260a060020a60ff0219606060020a95860295909504600160a060020a031990931692909217939093161792909216179055601880546001810180835582818380158290116120c9576007028160070283600052602060002091820191016120c991905b8082111561186a5760006000820160009055600182016000905560028201805460018160011615610100020316600290046000825580601f10612068575061209a565b601f01602090049060005260206000209081019061209a91905b8082111561186a5760008155600101611856565b5090565b5b50506000600382018190556004820155600581018054600160b060020a0319169055600701612025565b5090565b5b505050916000526020600020906007020160005b83909190915060008201518160000155602082015181600101556040820151816002019080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061214a57805160ff1916838001178555612177565b82800160010185558215612177579182015b8281111561217757825182559160200191906001019061215c565b5b506121989291505b8082111561186a5760008155600101611856565b5090565b5050606082015181600301556080820151816004015560a08201518160050160006101000a815481600160a060020a030219169083606060020a90810204021790555060c08201518160050160146101000a81548160ff021916908360f860020a90810204021790555060e08201518160050160156101000a81548160ff021916908360f860020a908102040217905550505050426017819055507f1a1eea7d2a0f099c2f19efb4e101fcf220558c9f4fbc6961b33fbe02d3a7be908389848a3360405180866000191681526020018581526020018481526020018060200183600160a060020a031681526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015611bee5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a1826001955095505b5b505050509250929050565b600654600160a060020a03165b90565b600854600160a060020a03161561232957610000565b60088054600160a060020a031916606060020a838102041790555b50565b60065433600160a060020a0390811691161461236257610000565b60105460ff16151561237357610000565b600760009054906101000a9004600160a060020a0316600160a060020a031663d4884b566000604051602001526040518160e060020a028152600401809050602060405180830381600087803b156100005760325a03f11561000057505060405151421090506123e257610000565b600760009054906101000a9004600160a060020a0316600160a060020a031663cdd933326000604051602001526040518160e060020a028152600401809050602060405180830381600087803b156100005760325a03f11561000057505060405151421015905061245257610000565b600854600160a060020a0316151561246957610000565b6000805482018155600160a060020a03308116808352600160209081526040808520805487019055600b8790556002825280852060088054861687529083529481902080548701905593548451868152945193169391927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3600054601154600b546040805185815290517f10cb430288a1696de11938bc5362c6f8c60e58808237bce4436b93a8573e00c39181900360200190a45b5b5b5b5b5050565b604080516101008082018352600080835260208084018290528451808201865282815284860152606084018290526080840182905260a0840182905260c0840182905260e0840182905285825260148152848220855180850187528154815260018083015482850152600280840180548a51600019948216159099029390930190921604601f8101859004850287018501895280875296979496879692959394938601938301828280156126245780601f106125f957610100808354040283529160200191612624565b820191906000526020600020905b81548152906001019060200180831161260757829003601f168201915b505050918352505060038201546020820152600482015460408201526005820154600160a060020a038116606083015260ff60a060020a820481161515608084015260a09092019160a860020a909104166001811161000057905250600085815260146020526040902054909350151561269d57610000565b60008481526014602052604090206005015460a060020a900460ff16156126c357610000565b60008481526014602052604090206003015442106126e057610000565b6000848152601460209081526040808320600160a060020a033316845260060190915290205460ff161561271357610000565b600160a060020a0333166000818152600a6020908152604080832054888452601483528184206004810180548301905594845260069094019091529020805460ff19166001179055915061276684612941565b6000858152601460205260409020601880549293509091839081101561000057906000526020600020906007020160005b50600082015481600001556001820154816001015560028201816002019080546001816001161561010002031660029004828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612801578054855561283d565b8280016001018555821561283d57600052602060002091601f016020900482015b8281111561283d578254825591600101919060010190612822565b5b5061285e9291505b8082111561186a5760008155600101611856565b5090565b5050600382810154908201556004808301549082015560059182018054929091018054600160a060020a031916606060020a600160a060020a0394851681020417808255825460a060020a60ff021990911660f860020a60a060020a9283900460ff908116820282900490930291909117808455935460a860020a60ff021990941660a860020a9485900490921681020490920291909117905560408051868152339092166020830152818101849052517f8f8bbb8c1937f844f6a094cd4c6eeab8ed5e36f83952e6306ffb2c11fffe5bce916060908290030190a15b50505050565b6000805b60185481101561298657601881815481101561000057906000526020600020906007020160005b505483141561297d57809150612986565b5b600101612945565b5b50919050565b600160a060020a0381166000908152600160205260409020545b919050565b60065433600160a060020a039081169116146129c757610000565b600160a060020a03301660009081526001602052604080822080548354038355829055517fe0987873419fe09d3c9a3e0267f4daf163e812d512f867abaf6bf9822f141a8b9190a15b5b565b60408051602080820183526000825260198054845160026001831615610100026000190190921691909104601f810184900484028201840190955284815292939091830182828015610e4f5780601f10610e2457610100808354040283529160200191610e4f565b820191906000526020600020905b815481529060010190602001808311610e3257829003601f168201915b505050505090505b90565b6011545b90565b600f805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505081565b6000602082511115612b5757610000565b5060208101515b919050565b6000601882815481101561000057906000526020600020906007020160005b505490505b919050565b600160a060020a033316600090815260016020526040812054829010801590612bb55750600082115b15612c2d57600160a060020a03338116600081815260016020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a3506001610c5256610c52565b506000610c52565b5b92915050565b600160a060020a0333166000908152600a60205260409020541515612c6057610000565b600760009054906101000a9004600160a060020a0316600160a060020a031663d4884b566000604051602001526040518160e060020a028152600401809050602060405180830381600087803b156100005760325a03f11561000057505060405151626ebe00014210159050612cd557610000565b601b5415801590612cef5750426019600201546212750001115b15612cf957610000565b6040805160808101825283815260208082018490524262127500018284015233600160a060020a03166000908152600a8252928320546060830152815180516019805495819052939484937f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c969560026001841615610100026000190190931692909204601f90810182900483019490910190839010612da257805160ff1916838001178555612dcf565b82800160010185558215612dcf579182015b82811115612dcf578251825591602001919060010190612db4565b5b50612df09291505b8082111561186a5760008155600101611856565b5090565b505060208201518160010160006101000a815481600160a060020a030219169083606060020a908102040217905550604082015181600201556060820151816003015590505060016019600401600033600160a060020a0316815260200190815260200160002060006101000a81548160ff021916908360f860020a9081020402179055507f854a9cc4d907d23cd8dcc72af48dc0e6a87e6f76376a309a0ffa3231ce8e13363383426212750001846040518085600160a060020a031681526020018060200184815260200183600160a060020a031681526020018281038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015612f235780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a15b5050565b60065433600160a060020a03908116911614612f5357610000565b600b819055600080546011546040519192909184917f17a7f53ef43da32c3936b4ac2b060caff5c4b03cd24b1c8e96a191eb1ec48d1591a45b5b50565b6000600960009054906101000a9004600160a060020a0316600160a060020a03166370a08231306000604051602001526040518260e060020a0281526004018082600160a060020a03168152602001915050602060405180830381600087803b156100005760325a03f115610000575050604051519150505b90565b6000545b90565b600c545b90565b600160a060020a0381166000908152600a60205260409020545b919050565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b9291505056d7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb500000000000000000000000069381683bde924cef65f1c97f7c8fb769a20409300000000000000000000000014f37b574242d366558db61f3335289a5035c506000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000018546573742074657374657220746573746573742063616d700000000000000000000000000000000000000000000000000000000000000000000000000000000354455300000000000000000000000000000000000000000000000000000000001ba033230fce515bea9de982fe85e0ec8fe892984bc3070ad633daab20eb370864d5a05deb41870e2117197b84cb71110fc0508fa7457165cb8cb82cb8d4d801e6e3f1").unwrap(); - let signature = manager.sign_transaction(&address, &huge_tx); - println!("Got {:?}", signature); - assert!(signature.is_ok()); - } + let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().expect("HidApi"))); + let manager = Manager::new(hidapi.clone(), Arc::new(AtomicBool::new(false))).expect("Ledger Manager"); + + // Update device list + assert_eq!(try_connect_polling(manager.clone(), Duration::from_millis(500)), true); + + // Fetch the ethereum address of a connected ledger device + let address = manager.list_devices() + .iter() + .filter(|d| d.manufacturer == "Ledger".to_string()) + .nth(0) + .map(|d| d.address.clone()) + .expect("No ledger device detected"); + + let tx = FromHex::from_hex("eb018504a817c80082520894a6ca2e6707f2cc189794a9dd459d5b05ed1bcd1c8703f26fcfb7a22480018080").unwrap(); + let signature = manager.sign_transaction(&address, &tx); + println!("Got {:?}", signature); + assert!(signature.is_ok()); + let large_tx = FromHex::from_hex("f8cb81968504e3b2920083024f279475b02a3c39710d6a3f2870d0d788299d48e790f180b8a4b61d27f6000000000000000000000000e1af840a5a1cb1efdf608a97aa632f4aa39ed199000000000000000000000000000000000000000000000000105ff43f46a9a800000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018080").unwrap(); + let signature = manager.sign_transaction(&address, &large_tx); + println!("Got {:?}", signature); + assert!(signature.is_ok()); + let huge_tx = FromHex::from_hex("f935e98201048505d21dba00833b82608080b935946103e86003908155620d2f00600455601460055560a060405260608190527f2e2e2e00000000000000000000000000000000000000000000000000000000006080908152600d805460008290527f2e2e2e00000000000000000000000000000000000000000000000000000000068255909260008051602062003474833981519152602060026001851615610100026000190190941693909304601f0192909204820192909190620000dc565b82800160010185558215620000dc579182015b82811115620000dc578251825591602001919060010190620000bf565b5b50620001009291505b80821115620000fc5760008155600101620000e6565b5090565b5050600e8054600360ff199182168117909255604080518082019091528281527f2e2e2e00000000000000000000000000000000000000000000000000000000006020918201908152600f80546000829052825160069516949094178155937f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac80260026101006001871615026000190190951694909404601f019290920483019290620001d7565b82800160010185558215620001d7579182015b82811115620001d7578251825591602001919060010190620001ba565b5b50620001fb9291505b80821115620000fc5760008155600101620000e6565b5090565b50506010805460ff19166001179055346200000057604051620034943803806200349483398101604090815281516020830151918301516060840151919390810191015b5b5b60068054600160a060020a0319166c01000000000000000000000000338102041790558151600d80546000829052909160008051602062003474833981519152602060026101006001861615026000190190941693909304601f908101849004820193870190839010620002c157805160ff1916838001178555620002f1565b82800160010185558215620002f1579182015b82811115620002f1578251825591602001919060010190620002d4565b5b50620003159291505b80821115620000fc5760008155600101620000e6565b5090565b505080600f9080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200036557805160ff191683800117855562000395565b8280016001018555821562000395579182015b828111156200039557825182559160200191906001019062000378565b5b50620003b99291505b80821115620000fc5760008155600101620000e6565b5090565b5050600980546c01000000000000000000000000808602819004600160a060020a0319928316179092556007805487840293909304929091169190911790555b505050505b613066806200040e6000396000f300606060405236156102035760e060020a600035046306fdde03811461034b578063095ea7b3146103c65780630b0b6d5b146103ed5780631b1ccc47146103fc57806320e870931461047757806323b872dd1461049657806325b29d84146104c057806327187991146104df578063277ccde2146104f15780632e1fbfcd14610510578063308b2fdc14610532578063313ce5671461055457806338cc48311461057757806340eddc4e146105a057806341f4793a146105bf578063467ed261146105de578063471ad963146105fd5780634e860ebb1461060f5780634efbe9331461061e57806354786b4e1461064257806354e35ba2146106bd57806358793ad4146106d25780635abedab21461073f5780635af2f8211461074e57806360483a3f1461076d57806360d12fa0146107da578063698f2e84146108035780636a749986146108155780636d5f66391461082a5780636e9c36831461083c57806370a082311461085e5780637a290fe5146108805780637e7541461461088f57806394c41bdb1461090a57806395d89b4114610929578063962a64cd146109a4578063a0b6533214610a09578063a9059cbb14610a2b578063ab62438f14610a52578063b63ca98114610aa9578063b7c54c6f14610abb578063c4e41b2214610ada578063ca7c4dba14610af9578063cb79e31b14610b18578063dd62ed3e14610b3a575b6103495b60006000600c546000141561021b57610000565b600354600c54670de0b6b3a764000091349091020204915060009050816001600030600160a060020a031681526020019081526020016000205410156102c557600160a060020a033016600090815260016020526040902054600c54909250828115610000570466038d7ea4c68000023403905033600160a060020a03166108fc829081150290604051809050600060405180830381858888f1935050505015156102c557610000565b5b600160a060020a03338116600081815260016020908152604080832080548801905530909416825283822080548790039055601380543487900301908190559154600c548551908152918201879052845190949293927f5a0391f2a67f11ed0034b68f8cf14e7e41d6f86e0a7622f2af5ea8f07b488396928290030190a45b5050565b005b3461000057610358610b5f565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103b85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576103d9600435602435610bed565b604080519115158252519081900360200190f35b3461000057610349610c58565b005b3461000057610358610dbc565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103b85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3461000057610484610e5a565b60408051918252519081900360200190f35b34610000576103d9600435602435604435610ef9565b604080519115158252519081900360200190f35b3461000057610484610ff3565b60408051918252519081900360200190f35b3461000057610349600435611002565b005b346100005761048461105a565b60408051918252519081900360200190f35b3461000057610484600435611061565b60408051918252519081900360200190f35b346100005761048460043561108d565b60408051918252519081900360200190f35b34610000576105616110b9565b6040805160ff9092168252519081900360200190f35b34610000576105846110c2565b60408051600160a060020a039092168252519081900360200190f35b34610000576104846110c7565b60408051918252519081900360200190f35b34610000576104846110ce565b60408051918252519081900360200190f35b34610000576104846110d5565b60408051918252519081900360200190f35b3461000057610349600435611174565b005b34610000576103496113b5565b005b34610000576103d9600435611407565b604080519115158252519081900360200190f35b3461000057610358611549565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103b85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576103496004356024356115e7565b005b346100005760408051602060046024803582810135601f8101859004850286018501909652858552610726958335959394604494939290920191819084018382808284375094965061167e95505050505050565b6040805192835290151560208301528051918290030190f35b3461000057610349611c13565b005b3461000057610484611d46565b60408051918252519081900360200190f35b346100005760408051602060046024803582810135601f81018590048502860185019096528585526107269583359593946044949392909201918190840183828082843750949650611d4d95505050505050565b6040805192835290151560208301528051918290030190f35b3461000057610584612303565b60408051600160a060020a039092168252519081900360200190f35b3461000057610349600435612313565b005b3461000057610349600435602435612347565b005b346100005761034960043561252f565b005b3461000057610484600435612941565b60408051918252519081900360200190f35b346100005761048460043561298d565b60408051918252519081900360200190f35b34610000576103496129ac565b005b3461000057610358612a13565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103b85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3461000057610484612ab1565b60408051918252519081900360200190f35b3461000057610358612ab8565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156103b85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3461000057610484600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843750949650612b4695505050505050565b60408051918252519081900360200190f35b3461000057610484600435612b63565b60408051918252519081900360200190f35b34610000576103d9600435602435612b8c565b604080519115158252519081900360200190f35b3461000057610349600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437509496505093359350612c3c92505050565b005b3461000057610349600435612f38565b005b3461000057610484612f90565b60408051918252519081900360200190f35b346100005761048461300c565b60408051918252519081900360200190f35b3461000057610484613013565b60408051918252519081900360200190f35b346100005761048460043561301a565b60408051918252519081900360200190f35b3461000057610484600435602435613039565b60408051918252519081900360200190f35b600d805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b601a54600090600160a060020a03161515610c7257610000565b600160a060020a0333166000908152600a60205260409020541515610c9657610000565b600160a060020a0333166000908152601d602052604090205460ff1615610cbc57610000565b601b54426212750090910111610cd157610000565b600160a060020a0333166000818152601d60209081526040808320805460ff19166001179055600a8252918290208054601c805490910190555482519384529083015280517f475c7605c08471fdc551a58d2c318b163628c5852f69323a1b91c34eb0bb09339281900390910190a150601154601c54606490910490604682029010610db857601a5460068054600160a060020a031916606060020a600160a060020a0393841681020417908190556040805191909216815290517f6b8184e23a898262087be50aa3ea5de648451e63f94413e810586c25282d58c2916020908290030190a15b5b50565b604080516020808201835260008252600d8054845160026001831615610100026000190190921691909104601f810184900484028201840190955284815292939091830182828015610e4f5780601f10610e2457610100808354040283529160200191610e4f565b820191906000526020600020905b815481529060010190602001808311610e3257829003601f168201915b505050505090505b90565b600f805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152600093610ef39391929091830182828015610ee95780601f10610ebe57610100808354040283529160200191610ee9565b820191906000526020600020905b815481529060010190602001808311610ecc57829003601f168201915b5050505050612b46565b90505b90565b600160a060020a038316600090815260016020526040812054829010801590610f495750600160a060020a0380851660009081526002602090815260408083203390941683529290522054829010155b8015610f555750600082115b15610fe757600160a060020a03808516600081815260016020908152604080832080548890039055878516808452818420805489019055848452600283528184203390961684529482529182902080548790039055815186815291517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3506001610feb56610feb565b5060005b5b9392505050565b600160a060020a033016315b90565b60065433600160a060020a0390811691161461101d57610000565b600c8190556040805182815290517f0bbd501ef336990995d82b5e3fd82a15abe1ff10c982757a1698ac5d1c3e79579181900360200190a15b5b50565b600b545b90565b6000601882815481101561000057906000526020600020906007020160005b506004015490505b919050565b6000601882815481101561000057906000526020600020906007020160005b506001015490505b919050565b600e5460ff1681565b305b90565b6013545b90565b601c545b90565b600d805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152600093610ef39391929091830182828015610ee95780601f10610ebe57610100808354040283529160200191610ee9565b820191906000526020600020905b815481529060010190602001808311610ecc57829003601f168201915b5050505050612b46565b90505b90565b600654600090819033600160a060020a0390811691161461119457610000565b60008381526014602052604090205415156111ae57610000565b60008381526014602052604090206005015433600160a060020a039081169116146111d857610000565b60008381526014602052604090206005015460a060020a900460ff16156111fe57610000565b601154600084815260146020526040902060040154606490910460370292508290111561122a57610000565b60008381526014602052604081206005015460a860020a900460ff16600181116100005714156112eb57600954600084815260146020908152604080832060058101546001909101548251840185905282517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201526024810191909152915194169363a9059cbb93604480840194938390030190829087803b156100005760325a03f1156100005750611389915050565b60008381526014602052604080822060058101546001909101549151600160a060020a039091169282156108fc02929190818181858888f160008881526014602090815260409182902060058101546001909101548351600160a060020a0390921682529181019190915281519297507f2648a7e2f9c34700b91370233666e5118fa8be3e0c21fed4f7402b941df8efdd9650829003019350915050a15b6000838152601460205260409020600501805460a060020a60ff02191660a060020a1790555b5b505050565b60065433600160a060020a039081169116146113d057610000565b6010805460ff191690556040517fb48c7f694f0a3b9b22d7e61c60ff8aebbb107314b6b698fc489ff3f017cb57e090600090a15b5b565b600060006000600760009054906101000a9004600160a060020a0316600160a060020a031663d4884b566000604051602001526040518160e060020a028152600401809050602060405180830381600087803b156100005760325a03f115610000575050604051514210905061147c57610000565b60085433600160a060020a0390811691161461149757610000565b5050600b54600160a060020a03328181166000908152600a6020526040902080549386029384019055601180548401905560128054860190556008549092916114e39130911683610ef9565b506114ee8282612b8c565b50600054601154600b5460408051918252602082018590528051600160a060020a038716927fb4d6befef2def3d17bcb13c2b882ec4fa047f33157446d3e0e6094b2a21609ac92908290030190a4600192505b5b5050919050565b604080516020808201835260008252600f8054845160026001831615610100026000190190921691909104601f810184900484028201840190955284815292939091830182828015610e4f5780601f10610e2457610100808354040283529160200191610e4f565b820191906000526020600020905b815481529060010190602001808311610e3257829003601f168201915b505050505090505b90565b60065433600160a060020a0390811691161461160257610000565b60105460ff16151561161357610000565b600160a060020a0330166000908152600160209081526040808320805485019055600c859055825484019283905580518481529051839286927f10cb430288a1696de11938bc5362c6f8c60e58808237bce4436b93a8573e00c3929081900390910190a45b5b5b5050565b6040805161010081018252600080825260208083018290528351908101845281815292820192909252606081018290526080810182905260a0810182905260c0810182905260e08101829052600654829182918291829133600160a060020a039081169116146116ed57610000565b60115460649004935060056016541115801561170c5750836005540288115b1561171657610000565b61171e612f90565b8811156117305761172d612f90565b97505b60003642604051808484808284378201915050828152602001935050505060405180910390209250600454420191506101006040519081016040528084815260200189815260200188815260200183815260200160008152602001338152602001600081526020016000815260200150905080601460008560001916815260200190815260200160002060008201518160000155602082015181600101556040820151816002019080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061182057805160ff191683800117855561184d565b8280016001018555821561184d579182015b8281111561184d578251825591602001919060010190611832565b5b5061186e9291505b8082111561186a5760008155600101611856565b5090565b5050606082015160038201556080820151600482015560a08201516005909101805460c084015160e09094015160f860020a90810281900460a860020a0260a860020a60ff02199582029190910460a060020a0260a060020a60ff0219606060020a95860295909504600160a060020a031990931692909217939093161792909216179055601880546001810180835582818380158290116119c9576007028160070283600052602060002091820191016119c991905b8082111561186a5760006000820160009055600182016000905560028201805460018160011615610100020316600290046000825580601f10611968575061199a565b601f01602090049060005260206000209081019061199a91905b8082111561186a5760008155600101611856565b5090565b5b50506000600382018190556004820155600581018054600160b060020a0319169055600701611925565b5090565b5b505050916000526020600020906007020160005b83909190915060008201518160000155602082015181600101556040820151816002019080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611a4a57805160ff1916838001178555611a77565b82800160010185558215611a77579182015b82811115611a77578251825591602001919060010190611a5c565b5b50611a989291505b8082111561186a5760008155600101611856565b5090565b5050606082015181600301556080820151816004015560a08201518160050160006101000a815481600160a060020a030219169083606060020a90810204021790555060c08201518160050160146101000a81548160ff021916908360f860020a90810204021790555060e08201518160050160156101000a81548160ff021916908360f860020a90810204021790555050505060166000815460010191905081905550426017819055507f1a1eea7d2a0f099c2f19efb4e101fcf220558c9f4fbc6961b33fbe02d3a7be908389848a3360405180866000191681526020018581526020018481526020018060200183600160a060020a031681526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015611bee5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a1826001955095505b5b505050509250929050565b60065460009033600160a060020a03908116911614611c3157610000565b600760009054906101000a9004600160a060020a0316600160a060020a031663d4884b566000604051602001526040518160e060020a028152600401809050602060405180830381600087803b156100005760325a03f1156100005750506040515162dd7c00014210159050611ca657610000565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1600954909550600160a060020a0316935063a9059cbb9250339150611cef9050612f90565b6000604051602001526040518360e060020a0281526004018083600160a060020a0316815260200182815260200192505050602060405180830381600087803b156100005760325a03f115610000575050505b5b50565b6016545b90565b6040805161010081018252600080825260208083018290528351908101845281815292820192909252606081018290526080810182905260a0810182905260c0810182905260e08101829052600654829182918291829133600160a060020a03908116911614611dbc57610000565b60105460ff1615611dcc57610000565b6000611dd73061298d565b1115611de257610000565b6017546212750001421015611df657610000565b6013546064900493508360055402881115611e1057610000565b30600160a060020a031631881115611e305730600160a060020a03163197505b60003642604051808484808284378201915050828152602001935050505060405180910390209250600454420191506101006040519081016040528084815260200189815260200188815260200183815260200160008152602001338152602001600081526020016001815260200150905080601460008560001916815260200190815260200160002060008201518160000155602082015181600101556040820151816002019080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611f2057805160ff1916838001178555611f4d565b82800160010185558215611f4d579182015b82811115611f4d578251825591602001919060010190611f32565b5b50611f6e9291505b8082111561186a5760008155600101611856565b5090565b5050606082015160038201556080820151600482015560a08201516005909101805460c084015160e09094015160f860020a90810281900460a860020a0260a860020a60ff02199582029190910460a060020a0260a060020a60ff0219606060020a95860295909504600160a060020a031990931692909217939093161792909216179055601880546001810180835582818380158290116120c9576007028160070283600052602060002091820191016120c991905b8082111561186a5760006000820160009055600182016000905560028201805460018160011615610100020316600290046000825580601f10612068575061209a565b601f01602090049060005260206000209081019061209a91905b8082111561186a5760008155600101611856565b5090565b5b50506000600382018190556004820155600581018054600160b060020a0319169055600701612025565b5090565b5b505050916000526020600020906007020160005b83909190915060008201518160000155602082015181600101556040820151816002019080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061214a57805160ff1916838001178555612177565b82800160010185558215612177579182015b8281111561217757825182559160200191906001019061215c565b5b506121989291505b8082111561186a5760008155600101611856565b5090565b5050606082015181600301556080820151816004015560a08201518160050160006101000a815481600160a060020a030219169083606060020a90810204021790555060c08201518160050160146101000a81548160ff021916908360f860020a90810204021790555060e08201518160050160156101000a81548160ff021916908360f860020a908102040217905550505050426017819055507f1a1eea7d2a0f099c2f19efb4e101fcf220558c9f4fbc6961b33fbe02d3a7be908389848a3360405180866000191681526020018581526020018481526020018060200183600160a060020a031681526020018281038252848181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015611bee5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a1826001955095505b5b505050509250929050565b600654600160a060020a03165b90565b600854600160a060020a03161561232957610000565b60088054600160a060020a031916606060020a838102041790555b50565b60065433600160a060020a0390811691161461236257610000565b60105460ff16151561237357610000565b600760009054906101000a9004600160a060020a0316600160a060020a031663d4884b566000604051602001526040518160e060020a028152600401809050602060405180830381600087803b156100005760325a03f11561000057505060405151421090506123e257610000565b600760009054906101000a9004600160a060020a0316600160a060020a031663cdd933326000604051602001526040518160e060020a028152600401809050602060405180830381600087803b156100005760325a03f11561000057505060405151421015905061245257610000565b600854600160a060020a0316151561246957610000565b6000805482018155600160a060020a03308116808352600160209081526040808520805487019055600b8790556002825280852060088054861687529083529481902080548701905593548451868152945193169391927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3600054601154600b546040805185815290517f10cb430288a1696de11938bc5362c6f8c60e58808237bce4436b93a8573e00c39181900360200190a45b5b5b5b5b5050565b604080516101008082018352600080835260208084018290528451808201865282815284860152606084018290526080840182905260a0840182905260c0840182905260e0840182905285825260148152848220855180850187528154815260018083015482850152600280840180548a51600019948216159099029390930190921604601f8101859004850287018501895280875296979496879692959394938601938301828280156126245780601f106125f957610100808354040283529160200191612624565b820191906000526020600020905b81548152906001019060200180831161260757829003601f168201915b505050918352505060038201546020820152600482015460408201526005820154600160a060020a038116606083015260ff60a060020a820481161515608084015260a09092019160a860020a909104166001811161000057905250600085815260146020526040902054909350151561269d57610000565b60008481526014602052604090206005015460a060020a900460ff16156126c357610000565b60008481526014602052604090206003015442106126e057610000565b6000848152601460209081526040808320600160a060020a033316845260060190915290205460ff161561271357610000565b600160a060020a0333166000818152600a6020908152604080832054888452601483528184206004810180548301905594845260069094019091529020805460ff19166001179055915061276684612941565b6000858152601460205260409020601880549293509091839081101561000057906000526020600020906007020160005b50600082015481600001556001820154816001015560028201816002019080546001816001161561010002031660029004828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10612801578054855561283d565b8280016001018555821561283d57600052602060002091601f016020900482015b8281111561283d578254825591600101919060010190612822565b5b5061285e9291505b8082111561186a5760008155600101611856565b5090565b5050600382810154908201556004808301549082015560059182018054929091018054600160a060020a031916606060020a600160a060020a0394851681020417808255825460a060020a60ff021990911660f860020a60a060020a9283900460ff908116820282900490930291909117808455935460a860020a60ff021990941660a860020a9485900490921681020490920291909117905560408051868152339092166020830152818101849052517f8f8bbb8c1937f844f6a094cd4c6eeab8ed5e36f83952e6306ffb2c11fffe5bce916060908290030190a15b50505050565b6000805b60185481101561298657601881815481101561000057906000526020600020906007020160005b505483141561297d57809150612986565b5b600101612945565b5b50919050565b600160a060020a0381166000908152600160205260409020545b919050565b60065433600160a060020a039081169116146129c757610000565b600160a060020a03301660009081526001602052604080822080548354038355829055517fe0987873419fe09d3c9a3e0267f4daf163e812d512f867abaf6bf9822f141a8b9190a15b5b565b60408051602080820183526000825260198054845160026001831615610100026000190190921691909104601f810184900484028201840190955284815292939091830182828015610e4f5780601f10610e2457610100808354040283529160200191610e4f565b820191906000526020600020905b815481529060010190602001808311610e3257829003601f168201915b505050505090505b90565b6011545b90565b600f805460408051602060026001851615610100026000190190941693909304601f81018490048402820184019092528181529291830182828015610be55780601f10610bba57610100808354040283529160200191610be5565b820191906000526020600020905b815481529060010190602001808311610bc857829003601f168201915b505050505081565b6000602082511115612b5757610000565b5060208101515b919050565b6000601882815481101561000057906000526020600020906007020160005b505490505b919050565b600160a060020a033316600090815260016020526040812054829010801590612bb55750600082115b15612c2d57600160a060020a03338116600081815260016020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a3506001610c5256610c52565b506000610c52565b5b92915050565b600160a060020a0333166000908152600a60205260409020541515612c6057610000565b600760009054906101000a9004600160a060020a0316600160a060020a031663d4884b566000604051602001526040518160e060020a028152600401809050602060405180830381600087803b156100005760325a03f11561000057505060405151626ebe00014210159050612cd557610000565b601b5415801590612cef5750426019600201546212750001115b15612cf957610000565b6040805160808101825283815260208082018490524262127500018284015233600160a060020a03166000908152600a8252928320546060830152815180516019805495819052939484937f944998273e477b495144fb8794c914197f3ccb46be2900f4698fd0ef743c969560026001841615610100026000190190931692909204601f90810182900483019490910190839010612da257805160ff1916838001178555612dcf565b82800160010185558215612dcf579182015b82811115612dcf578251825591602001919060010190612db4565b5b50612df09291505b8082111561186a5760008155600101611856565b5090565b505060208201518160010160006101000a815481600160a060020a030219169083606060020a908102040217905550604082015181600201556060820151816003015590505060016019600401600033600160a060020a0316815260200190815260200160002060006101000a81548160ff021916908360f860020a9081020402179055507f854a9cc4d907d23cd8dcc72af48dc0e6a87e6f76376a309a0ffa3231ce8e13363383426212750001846040518085600160a060020a031681526020018060200184815260200183600160a060020a031681526020018281038252858181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f168015612f235780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a15b5050565b60065433600160a060020a03908116911614612f5357610000565b600b819055600080546011546040519192909184917f17a7f53ef43da32c3936b4ac2b060caff5c4b03cd24b1c8e96a191eb1ec48d1591a45b5b50565b6000600960009054906101000a9004600160a060020a0316600160a060020a03166370a08231306000604051602001526040518260e060020a0281526004018082600160a060020a03168152602001915050602060405180830381600087803b156100005760325a03f115610000575050604051519150505b90565b6000545b90565b600c545b90565b600160a060020a0381166000908152600a60205260409020545b919050565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b9291505056d7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb500000000000000000000000069381683bde924cef65f1c97f7c8fb769a20409300000000000000000000000014f37b574242d366558db61f3335289a5035c506000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000018546573742074657374657220746573746573742063616d700000000000000000000000000000000000000000000000000000000000000000000000000000000354455300000000000000000000000000000000000000000000000000000000001ba033230fce515bea9de982fe85e0ec8fe892984bc3070ad633daab20eb370864d5a05deb41870e2117197b84cb71110fc0508fa7457165cb8cb82cb8d4d801e6e3f1").unwrap(); + let signature = manager.sign_transaction(&address, &huge_tx); + println!("Got {:?}", signature); + assert!(signature.is_ok()); } diff --git a/hw/src/lib.rs b/hw/src/lib.rs index 9bfec83410b..f51be356ae1 100644 --- a/hw/src/lib.rs +++ b/hw/src/lib.rs @@ -16,7 +16,8 @@ //! Hardware wallet management. -#![warn(missing_docs)] +#[warn(missing_docs)] +#[warn(warnings)] extern crate ethereum_types; extern crate ethkey; @@ -38,12 +39,60 @@ use std::fmt; use std::sync::Arc; use std::sync::atomic; use std::sync::atomic::AtomicBool; -use std::thread; -use std::time::Duration; use ethereum_types::U256; const USB_DEVICE_CLASS_DEVICE: u8 = 0; +#[derive(Debug)] +pub struct Device { + path: String, + info: WalletInfo, +} + +pub trait Wallet<'a> { + /// Error + type Error; + /// Transaction data format + type Transaction; + + /// Sign transaction data with wallet managing `address`. + fn sign_transaction(&self, address: &Address, transaction: Self::Transaction) -> Result; + + /// Set key derivation path for a chain. + fn set_key_path(&self, key_path: KeyPath); + + /// Re-populate device list + /// Note, this assumes all devices are iterated over and updated + fn update_devices(&self) -> Result; + + /// Read device info + fn read_device(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result; + + /// List connected and acknowledged wallets + fn list_devices(&self) -> Vec; + + /// List locked wallets + /// This may be moved if it is the wrong assumption, for example this is not supported by Ledger + /// Then this method return a empty vector + fn list_locked_devices(&self) -> Vec; + + /// Get wallet info. + fn get_wallet(&self, address: &Address) -> Option; + + /// Generate ethereum address for a Wallet + fn get_address(&self, device: &hidapi::HidDevice) -> Result, Self::Error>; + + /// Open a device using `device path` + /// Note, f - is a closure that borrows HidResult + /// HidDevice is in turn a type alias for a `c_void function pointer` + /// For further information see: + /// * + /// * + fn open_path(&self, f: F) -> Result + where F: Fn() -> Result; +} + + /// Hardware wallet error. #[derive(Debug)] pub enum Error { @@ -144,70 +193,13 @@ pub struct HardwareWalletManager { trezor: Arc, } - impl HardwareWalletManager { /// Hardware wallet constructor pub fn new() -> Result { - let usb_context_trezor = Arc::new(libusb::Context::new()?); - let usb_context_ledger = Arc::new(libusb::Context::new()?); - let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().map_err(|e| Error::Hid(e.to_string().clone()))?)); - let ledger = Arc::new(ledger::Manager::new(hidapi.clone())); - let trezor = Arc::new(trezor::Manager::new(hidapi.clone())); - - // Subscribe to TREZOR V1 - // Note, this support only TREZOR V1 becasue TREZOR V2 has another vendorID for some reason - // Also, we now only support one product as the second argument specifies - usb_context_trezor.register_callback( - Some(trezor::TREZOR_VID), Some(trezor::TREZOR_PIDS[0]), Some(USB_DEVICE_CLASS_DEVICE), - Box::new(trezor::EventHandler::new(Arc::downgrade(&trezor))))?; - - // Subscribe to all Ledger Devices - // This means that we need to check that the given productID is supported - // None => LIBUSB_HOTPLUG_MATCH_ANY, in other words that all are subscribed to - // More info can be found: http://libusb.sourceforge.net/api-1.0/group__hotplug.html#gae6c5f1add6cc754005549c7259dc35ea - usb_context_ledger.register_callback( - Some(ledger::LEDGER_VID), None, Some(USB_DEVICE_CLASS_DEVICE), - Box::new(ledger::EventHandler::new(Arc::downgrade(&ledger))))?; - let exiting = Arc::new(AtomicBool::new(false)); - let thread_exiting_ledger = exiting.clone(); - let thread_exiting_trezor = exiting.clone(); - let l = ledger.clone(); - let t = trezor.clone(); - - // Ledger event thread - thread::Builder::new() - .name("hw_wallet_ledger".to_string()) - .spawn(move || { - if let Err(e) = l.update_devices() { - debug!(target: "hw", "Ledger couldn't connect at startup, error: {}", e); - } - loop { - usb_context_ledger.handle_events(Some(Duration::from_millis(500))) - .unwrap_or_else(|e| debug!(target: "hw", "Ledger event handler error: {}", e)); - if thread_exiting_ledger.load(atomic::Ordering::Acquire) { - break; - } - } - }) - .ok(); - - // Trezor event thread - thread::Builder::new() - .name("hw_wallet_trezor".to_string()) - .spawn(move || { - if let Err(e) = t.update_devices() { - debug!(target: "hw", "Trezor couldn't connect at startup, error: {}", e); - } - loop { - usb_context_trezor.handle_events(Some(Duration::from_millis(500))) - .unwrap_or_else(|e| debug!(target: "hw", "Trezor event handler error: {}", e)); - if thread_exiting_trezor.load(atomic::Ordering::Acquire) { - break; - } - } - }) - .ok(); + let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().map_err(|e| Error::Hid(e.to_string().clone()))?)); + let ledger = ledger::Manager::new(hidapi.clone(), exiting.clone())?; + let trezor = trezor::Manager::new(hidapi.clone(), exiting.clone())?; Ok(HardwareWalletManager { exiting: exiting, @@ -217,6 +209,8 @@ impl HardwareWalletManager { } /// Select key derivation path for a chain. + /// Currently, only one hard-coded keypath is supported + /// It is managed by `ethcore/account_provider` pub fn set_key_path(&self, key_path: KeyPath) { self.ledger.set_key_path(key_path); self.trezor.set_key_path(key_path); @@ -231,24 +225,26 @@ impl HardwareWalletManager { } /// Return a list of paths to locked hardware wallets + /// This is only applicable to Trezor because Ledger only appears as + /// a device when it is unlocked pub fn list_locked_wallets(&self) -> Result, Error> { Ok(self.trezor.list_locked_devices()) } /// Get connected wallet info. pub fn wallet_info(&self, address: &Address) -> Option { - if let Some(info) = self.ledger.device_info(address) { + if let Some(info) = self.ledger.get_wallet(address) { Some(info) } else { - self.trezor.device_info(address) + self.trezor.get_wallet(address) } } /// Sign transaction data with wallet managing `address`. pub fn sign_transaction(&self, address: &Address, t_info: &TransactionInfo, encoded_transaction: &[u8]) -> Result { - if self.ledger.device_info(address).is_some() { + if self.ledger.get_wallet(address).is_some() { Ok(self.ledger.sign_transaction(address, encoded_transaction)?) - } else if self.trezor.device_info(address).is_some() { + } else if self.trezor.get_wallet(address).is_some() { Ok(self.trezor.sign_transaction(address, t_info)?) } else { Err(Error::KeyNotFound) @@ -256,6 +252,8 @@ impl HardwareWalletManager { } /// Send a pin to a device at a certain path to unlock it + /// This is only applicable to Trezor because Ledger only appears as + /// a device when it is unlocked pub fn pin_matrix_ack(&self, path: &str, pin: &str) -> Result { self.trezor.pin_matrix_ack(path, pin).map_err(Error::TrezorDevice) } diff --git a/hw/src/trezor.rs b/hw/src/trezor.rs index 7db226718bc..044e5487b40 100644 --- a/hw/src/trezor.rs +++ b/hw/src/trezor.rs @@ -19,12 +19,15 @@ //! and https://github.com/trezor/trezor-common/blob/master/protob/protocol.md //! for protocol details. -use super::{WalletInfo, TransactionInfo, KeyPath}; +use super::{WalletInfo, TransactionInfo, KeyPath, Wallet, Device, USB_DEVICE_CLASS_DEVICE}; use std::cmp::{min, max}; use std::fmt; use std::sync::{Arc, Weak}; +use std::sync::atomic; +use std::sync::atomic::AtomicBool; use std::time::{Duration, Instant}; +use std::thread; use ethereum_types::{U256, H256, Address}; use ethkey::Signature; @@ -37,9 +40,9 @@ use protobuf::{Message, ProtobufEnum}; use trezor_sys::messages::{EthereumAddress, PinMatrixAck, MessageType, EthereumTxRequest, EthereumSignTx, EthereumGetAddress, EthereumTxAck, ButtonAck}; /// Trezor v1 vendor ID -pub const TREZOR_VID: u16 = 0x534c; +const TREZOR_VID: u16 = 0x534c; /// Trezor product IDs -pub const TREZOR_PIDS: [u16; 1] = [0x0001]; +const TREZOR_PIDS: [u16; 1] = [0x0001]; const ETH_DERIVATION_PATH: [u32; 5] = [0x8000002C, 0x8000003C, 0x80000000, 0, 0]; // m/44'/60'/0'/0/0 const ETC_DERIVATION_PATH: [u32; 5] = [0x8000002C, 0x8000003D, 0x80000000, 0, 0]; // m/44'/61'/0'/0/0 @@ -94,12 +97,6 @@ pub struct Manager { key_path: RwLock, } -#[derive(Debug)] -struct Device { - path: String, - info: WalletInfo, -} - /// HID Version used for the Trezor device enum HidVersion { V1, @@ -108,102 +105,42 @@ enum HidVersion { impl Manager { /// Create a new instance. - pub fn new(hidapi: Arc>) -> Manager { - Manager { + pub fn new(hidapi: Arc>, exiting: Arc) -> Result, libusb::Error> { + let manager = Arc::new(Manager { usb: hidapi, devices: RwLock::new(Vec::new()), locked_devices: RwLock::new(Vec::new()), key_path: RwLock::new(KeyPath::Ethereum), - } - } - - /// Re-populate device list - pub fn update_devices(&self) -> Result { - let mut usb = self.usb.lock(); - usb.refresh_devices(); - let devices = usb.devices(); - let mut new_devices = Vec::new(); - let mut locked_devices = Vec::new(); - let mut error = None; - for usb_device in devices { - let is_trezor = usb_device.vendor_id == TREZOR_VID; - let is_supported_product = TREZOR_PIDS.contains(&usb_device.product_id); - let is_valid = usb_device.usage_page == 0xFF00 || usb_device.interface_number == 0; - - trace!( - "Checking device: {:?}, trezor: {:?}, prod: {:?}, valid: {:?}", - usb_device, - is_trezor, - is_supported_product, - is_valid, - ); - if !is_trezor || !is_supported_product || !is_valid { - continue; - } - match self.read_device_info(&usb, &usb_device) { - Ok(device) => new_devices.push(device), - Err(Error::LockedDevice(path)) => locked_devices.push(path.to_string()), - Err(e) => { - warn!("Error reading device: {:?}", e); - error = Some(e); + }); + + let usb_context = Arc::new(libusb::Context::new()?); + let m = manager.clone(); + + // Subscribe to TREZOR V1 + // Note, this support only TREZOR V1 because TREZOR V2 has a different vendorID for some reason + // Also, we now only support one product as the second argument specifies + usb_context.register_callback( + Some(TREZOR_VID), Some(TREZOR_PIDS[0]), Some(USB_DEVICE_CLASS_DEVICE), + Box::new(EventHandler::new(Arc::downgrade(&manager))))?; + + // Trezor event thread + thread::Builder::new() + .name("hw_wallet_trezor".to_string()) + .spawn(move || { + if let Err(e) = m.update_devices() { + debug!(target: "hw", "Trezor couldn't connect at startup, error: {}", e); } - } - } - let count = new_devices.len(); - trace!("Got devices: {:?}, closed: {:?}", new_devices, locked_devices); - *self.devices.write() = new_devices; - *self.locked_devices.write() = locked_devices; - match error { - Some(e) => Err(e), - None => Ok(count), - } - } - - fn read_device_info(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result { - let handle = self.open_path(|| usb.open_path(&dev_info.path))?; - let manufacturer = dev_info.manufacturer_string.clone().unwrap_or("Unknown".to_owned()); - let name = dev_info.product_string.clone().unwrap_or("Unknown".to_owned()); - let serial = dev_info.serial_number.clone().unwrap_or("Unknown".to_owned()); - match self.get_address(&handle) { - Ok(Some(addr)) => { - Ok(Device { - path: dev_info.path.clone(), - info: WalletInfo { - name: name, - manufacturer: manufacturer, - serial: serial, - address: addr, - }, - }) - } - Ok(None) => Err(Error::LockedDevice(dev_info.path.clone())), - Err(e) => Err(e), - } - } - - /// Select key derivation path for a known chain. - pub fn set_key_path(&self, key_path: KeyPath) { - *self.key_path.write() = key_path; - } - - /// List connected wallets. This only returns wallets that are ready to be used. - pub fn list_devices(&self) -> Vec { - self.devices.read().iter().map(|d| d.info.clone()).collect() - } - - pub fn list_locked_devices(&self) -> Vec { - (*self.locked_devices.read()).clone() - } - - /// Get wallet info. - pub fn device_info(&self, address: &Address) -> Option { - self.devices.read().iter().find(|d| &d.info.address == address).map(|d| d.info.clone()) - } + loop { + usb_context.handle_events(Some(Duration::from_millis(500))) + .unwrap_or_else(|e| debug!(target: "hw", "Trezor event handler error: {}", e)); + if exiting.load(atomic::Ordering::Acquire) { + break; + } + } + }) + .ok(); - fn open_path(&self, f: F) -> Result - where F: Fn() -> Result - { - f().map_err(Into::into) + Ok(manager) } pub fn pin_matrix_ack(&self, device_path: &str, pin: &str) -> Result { @@ -227,61 +164,6 @@ impl Manager { unlocked } - fn get_address(&self, device: &hidapi::HidDevice) -> Result, Error> { - let typ = MessageType::MessageType_EthereumGetAddress; - let mut message = EthereumGetAddress::new(); - match *self.key_path.read() { - KeyPath::Ethereum => message.set_address_n(ETH_DERIVATION_PATH.to_vec()), - KeyPath::EthereumClassic => message.set_address_n(ETC_DERIVATION_PATH.to_vec()), - } - message.set_show_display(false); - self.send_device_message(&device, &typ, &message)?; - - let (resp_type, bytes) = self.read_device_response(&device)?; - match resp_type { - MessageType::MessageType_EthereumAddress => { - let response: EthereumAddress = protobuf::core::parse_from_bytes(&bytes)?; - Ok(Some(From::from(response.get_address()))) - } - _ => Ok(None), - } - } - - /// Sign transaction data with wallet managing `address`. - pub fn sign_transaction(&self, address: &Address, t_info: &TransactionInfo) -> Result { - let usb = self.usb.lock(); - let devices = self.devices.read(); - let device = devices.iter().find(|d| &d.info.address == address).ok_or(Error::KeyNotFound)?; - let handle = self.open_path(|| usb.open_path(&device.path))?; - let msg_type = MessageType::MessageType_EthereumSignTx; - let mut message = EthereumSignTx::new(); - match *self.key_path.read() { - KeyPath::Ethereum => message.set_address_n(ETH_DERIVATION_PATH.to_vec()), - KeyPath::EthereumClassic => message.set_address_n(ETC_DERIVATION_PATH.to_vec()), - } - message.set_nonce(self.u256_to_be_vec(&t_info.nonce)); - message.set_gas_limit(self.u256_to_be_vec(&t_info.gas_limit)); - message.set_gas_price(self.u256_to_be_vec(&t_info.gas_price)); - message.set_value(self.u256_to_be_vec(&t_info.value)); - - match t_info.to { - Some(addr) => { - message.set_to(addr.to_vec()) - } - None => (), - } - let first_chunk_length = min(t_info.data.len(), 1024); - let chunk = &t_info.data[0..first_chunk_length]; - message.set_data_initial_chunk(chunk.to_vec()); - message.set_data_length(t_info.data.len() as u32); - if let Some(c_id) = t_info.chain_id { - message.set_chain_id(c_id as u32); - } - - self.send_device_message(&handle, &msg_type, &message)?; - - self.signing_loop(&handle, &t_info.chain_id, &t_info.data[first_chunk_length..]) - } fn u256_to_be_vec(&self, val: &U256) -> Vec { let mut buf = [0u8; 32]; @@ -400,6 +282,152 @@ impl Manager { } } +impl <'a>Wallet<'a> for Manager { + type Error = Error; + type Transaction = &'a TransactionInfo; + + fn sign_transaction(&self, address: &Address, t_info: Self::Transaction) -> + Result { + let usb = self.usb.lock(); + let devices = self.devices.read(); + let device = devices.iter().find(|d| &d.info.address == address).ok_or(Error::KeyNotFound)?; + let handle = self.open_path(|| usb.open_path(&device.path))?; + let msg_type = MessageType::MessageType_EthereumSignTx; + let mut message = EthereumSignTx::new(); + match *self.key_path.read() { + KeyPath::Ethereum => message.set_address_n(ETH_DERIVATION_PATH.to_vec()), + KeyPath::EthereumClassic => message.set_address_n(ETC_DERIVATION_PATH.to_vec()), + } + message.set_nonce(self.u256_to_be_vec(&t_info.nonce)); + message.set_gas_limit(self.u256_to_be_vec(&t_info.gas_limit)); + message.set_gas_price(self.u256_to_be_vec(&t_info.gas_price)); + message.set_value(self.u256_to_be_vec(&t_info.value)); + + match t_info.to { + Some(addr) => { + message.set_to(addr.to_vec()) + } + None => (), + } + let first_chunk_length = min(t_info.data.len(), 1024); + let chunk = &t_info.data[0..first_chunk_length]; + message.set_data_initial_chunk(chunk.to_vec()); + message.set_data_length(t_info.data.len() as u32); + if let Some(c_id) = t_info.chain_id { + message.set_chain_id(c_id as u32); + } + + self.send_device_message(&handle, &msg_type, &message)?; + + self.signing_loop(&handle, &t_info.chain_id, &t_info.data[first_chunk_length..]) + } + + fn set_key_path(&self, key_path: KeyPath) { + *self.key_path.write() = key_path; + } + + fn update_devices(&self) -> Result { + let mut usb = self.usb.lock(); + usb.refresh_devices(); + let devices = usb.devices(); + let mut new_devices = Vec::new(); + let mut locked_devices = Vec::new(); + let mut error = None; + for usb_device in devices { + let is_trezor = usb_device.vendor_id == TREZOR_VID; + let is_supported_product = TREZOR_PIDS.contains(&usb_device.product_id); + let is_valid = usb_device.usage_page == 0xFF00 || usb_device.interface_number == 0; + + trace!( + "Checking device: {:?}, trezor: {:?}, prod: {:?}, valid: {:?}", + usb_device, + is_trezor, + is_supported_product, + is_valid, + ); + if !is_trezor || !is_supported_product || !is_valid { + continue; + } + match self.read_device(&usb, &usb_device) { + Ok(device) => new_devices.push(device), + Err(Error::LockedDevice(path)) => locked_devices.push(path.to_string()), + Err(e) => { + warn!("Error reading device: {:?}", e); + error = Some(e); + } + } + } + let count = new_devices.len(); + trace!("Got devices: {:?}, closed: {:?}", new_devices, locked_devices); + *self.devices.write() = new_devices; + *self.locked_devices.write() = locked_devices; + match error { + Some(e) => Err(e), + None => Ok(count), + } + } + + fn read_device(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result { + let handle = self.open_path(|| usb.open_path(&dev_info.path))?; + let manufacturer = dev_info.manufacturer_string.clone().unwrap_or("Unknown".to_owned()); + let name = dev_info.product_string.clone().unwrap_or("Unknown".to_owned()); + let serial = dev_info.serial_number.clone().unwrap_or("Unknown".to_owned()); + match self.get_address(&handle) { + Ok(Some(addr)) => { + Ok(Device { + path: dev_info.path.clone(), + info: WalletInfo { + name: name, + manufacturer: manufacturer, + serial: serial, + address: addr, + }, + }) + } + Ok(None) => Err(Error::LockedDevice(dev_info.path.clone())), + Err(e) => Err(e), + } + } + + fn list_devices(&self) -> Vec { + self.devices.read().iter().map(|d| d.info.clone()).collect() + } + + fn list_locked_devices(&self) -> Vec { + (*self.locked_devices.read()).clone() + } + + fn get_wallet(&self, address: &Address) -> Option { + self.devices.read().iter().find(|d| &d.info.address == address).map(|d| d.info.clone()) + } + + fn get_address(&self, device: &hidapi::HidDevice) -> Result, Error> { + let typ = MessageType::MessageType_EthereumGetAddress; + let mut message = EthereumGetAddress::new(); + match *self.key_path.read() { + KeyPath::Ethereum => message.set_address_n(ETH_DERIVATION_PATH.to_vec()), + KeyPath::EthereumClassic => message.set_address_n(ETC_DERIVATION_PATH.to_vec()), + } + message.set_show_display(false); + self.send_device_message(&device, &typ, &message)?; + + let (resp_type, bytes) = self.read_device_response(&device)?; + match resp_type { + MessageType::MessageType_EthereumAddress => { + let response: EthereumAddress = protobuf::core::parse_from_bytes(&bytes)?; + Ok(Some(From::from(response.get_address()))) + } + _ => Ok(None), + } + } + + fn open_path(&self, f: F) -> Result + where F: Fn() -> Result + { + f().map_err(Into::into) + } +} + // Try to connect to the device using polling in at most the time specified by the `timeout` fn try_connect_polling(trezor: Arc, duration: Duration) -> bool { let start_time = Instant::now(); @@ -412,11 +440,11 @@ fn try_connect_polling(trezor: Arc, duration: Duration) -> bool { } /// Trezor event handler -/// A separate thread is handeling incoming events +/// A separate thread is handling incoming events /// /// Note, that this run to completion and race-conditions can't occur but this can /// therefore starve other events for being process with a spinlock or similar -pub struct EventHandler { +struct EventHandler { trezor: Weak, } @@ -455,10 +483,10 @@ fn test_signature() { use ethereum_types::{H160, H256, U256}; let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().unwrap())); - let manager = Manager::new(hidapi.clone()); + let manager = Manager::new(hidapi.clone(), Arc::new(AtomicBool::new(false))).unwrap(); let addr: Address = H160::from("some_addr"); - manager.update_devices().unwrap(); + assert_eq!(try_connect_polling(manager.clone(), Duration::from_millis(500)), true); let t_info = TransactionInfo { nonce: U256::from(1), From d1f5284fe665665a98f36ad73606c4a72c25f3d3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Tue, 1 May 2018 16:02:14 +0300 Subject: [PATCH 27/95] SecretStore: merge two types of errors into single one + Error::is_non_fatal (#8357) * SecretStore: error unify initial commit SecretStore: pass real error in error messages SecretStore: is_internal_error -> Error::is_non_fatal warnings SecretStore: ConsensusTemporaryUnreachable fix after merge removed comments removed comments SecretStore: updated HTTP error responses SecretStore: more ConsensusTemporaryUnreachable tests fix after rebase * fixed grumbles * use HashSet in tests --- secret_store/src/acl_storage.rs | 4 +- secret_store/src/key_server.rs | 4 +- .../key_version_negotiation_session.rs | 51 +++-- .../key_server_cluster/admin_sessions/mod.rs | 6 + .../servers_set_change_session.rs | 24 ++- .../admin_sessions/share_add_session.rs | 24 ++- .../client_sessions/decryption_session.rs | 29 ++- .../client_sessions/encryption_session.rs | 5 +- .../client_sessions/generation_session.rs | 63 +----- .../client_sessions/signing_session_ecdsa.rs | 25 ++- .../signing_session_schnorr.rs | 27 ++- .../src/key_server_cluster/cluster.rs | 36 +++- .../key_server_cluster/cluster_sessions.rs | 6 +- .../cluster_sessions_creator.rs | 21 +- .../key_server_cluster/connection_trigger.rs | 2 +- .../connection_trigger_with_migration.rs | 2 +- .../jobs/consensus_session.rs | 62 +++--- .../key_server_cluster/jobs/decryption_job.rs | 2 +- .../key_server_cluster/jobs/job_session.rs | 108 ++++++++-- .../jobs/signing_job_ecdsa.rs | 4 +- .../jobs/signing_job_schnorr.rs | 2 +- .../src/key_server_cluster/message.rs | 20 +- secret_store/src/key_server_cluster/mod.rs | 132 +----------- secret_store/src/key_server_set.rs | 2 +- secret_store/src/key_storage.rs | 4 +- secret_store/src/lib.rs | 2 +- secret_store/src/listener/http_listener.rs | 23 +- secret_store/src/listener/mod.rs | 2 +- .../src/listener/service_contract_listener.rs | 28 +-- secret_store/src/serialization.rs | 2 +- secret_store/src/traits.rs | 2 +- secret_store/src/types/all.rs | 88 +------- secret_store/src/types/error.rs | 199 ++++++++++++++++++ secret_store/src/types/mod.rs | 6 +- 34 files changed, 577 insertions(+), 440 deletions(-) create mode 100644 secret_store/src/types/error.rs diff --git a/secret_store/src/acl_storage.rs b/secret_store/src/acl_storage.rs index 6399660aff3..50414eff26c 100644 --- a/secret_store/src/acl_storage.rs +++ b/secret_store/src/acl_storage.rs @@ -22,7 +22,7 @@ use ethcore::client::{BlockId, ChainNotify, CallContract, RegistryInfo}; use ethereum_types::{H256, Address}; use bytes::Bytes; use trusted_client::TrustedClient; -use types::all::{Error, ServerKeyId}; +use types::{Error, ServerKeyId}; use_contract!(acl_storage, "AclStorage", "res/acl_storage.json"); @@ -113,7 +113,7 @@ impl CachedContract { self.contract.functions() .check_permissions() .call(requester, document.clone(), &do_call) - .map_err(|e| Error::Internal(e.to_string())) + .map_err(|e| Error::Internal(format!("ACL checker call error: {}", e.to_string()))) }, None => Err(Error::Internal("ACL checker contract is not configured".to_owned())), } diff --git a/secret_store/src/key_server.rs b/secret_store/src/key_server.rs index ea3a3c0a571..f11a157c00d 100644 --- a/secret_store/src/key_server.rs +++ b/secret_store/src/key_server.rs @@ -27,7 +27,7 @@ use super::key_storage::KeyStorage; use super::key_server_set::KeyServerSet; use key_server_cluster::{math, ClusterCore}; use traits::{AdminSessionsServer, ServerKeyGenerator, DocumentKeyServer, MessageSigner, KeyServer, NodeKeyPair}; -use types::all::{Error, Public, RequestSignature, Requester, ServerKeyId, EncryptedDocumentKey, EncryptedDocumentKeyShadow, +use types::{Error, Public, RequestSignature, Requester, ServerKeyId, EncryptedDocumentKey, EncryptedDocumentKeyShadow, ClusterConfiguration, MessageHash, EncryptedMessageSignature, NodeId}; use key_server_cluster::{ClusterClient, ClusterConfiguration as NetClusterConfiguration}; @@ -238,7 +238,7 @@ pub mod tests { use key_server_set::tests::MapKeyServerSet; use key_server_cluster::math; use ethereum_types::{H256, H520}; - use types::all::{Error, Public, ClusterConfiguration, NodeAddress, RequestSignature, ServerKeyId, + use types::{Error, Public, ClusterConfiguration, NodeAddress, RequestSignature, ServerKeyId, EncryptedDocumentKey, EncryptedDocumentKeyShadow, MessageHash, EncryptedMessageSignature, Requester, NodeId}; use traits::{AdminSessionsServer, ServerKeyGenerator, DocumentKeyServer, MessageSigner, KeyServer}; diff --git a/secret_store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs b/secret_store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs index 15abdce89df..6c39fd8e7ed 100644 --- a/secret_store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs +++ b/secret_store/src/key_server_cluster/admin_sessions/key_version_negotiation_session.rs @@ -143,6 +143,10 @@ pub struct FastestResultComputer { self_node_id: NodeId, /// Threshold (if known). threshold: Option, + /// Count of all configured key server nodes. + configured_nodes_count: usize, + /// Count of all connected key server nodes. + connected_nodes_count: usize, } /// Selects version with most support, waiting for responses from all nodes. @@ -185,7 +189,7 @@ impl SessionImpl where T: SessionTransport { /// Return result computer reference. pub fn version_holders(&self, version: &H256) -> Result, Error> { Ok(self.data.lock().versions.as_ref().ok_or(Error::InvalidStateForRequest)? - .get(version).ok_or(Error::KeyStorage("key version not found".into()))? + .get(version).ok_or(Error::ServerKeyIsNotFound)? .clone()) } @@ -236,7 +240,7 @@ impl SessionImpl where T: SessionTransport { // try to complete session Self::try_complete(&self.core, &mut *data); if no_confirmations_required && data.state != SessionState::Finished { - return Err(Error::MissingKeyShare); + return Err(Error::ServerKeyIsNotFound); } else if data.state == SessionState::Finished { return Ok(()); } @@ -266,7 +270,7 @@ impl SessionImpl where T: SessionTransport { &KeyVersionNegotiationMessage::KeyVersions(ref message) => self.on_key_versions(sender, message), &KeyVersionNegotiationMessage::KeyVersionsError(ref message) => { - self.on_session_error(sender, Error::Io(message.error.clone())); + self.on_session_error(sender, message.error.clone()); Ok(()) }, } @@ -388,7 +392,7 @@ impl ClusterSession for SessionImpl where T: SessionTransport { if data.state != SessionState::Finished { warn!("{}: key version negotiation session failed with timeout", self.core.meta.self_node_id); - data.result = Some(Err(Error::ConsensusUnreachable)); + data.result = Some(Err(Error::ConsensusTemporaryUnreachable)); self.core.completed.notify_all(); } } @@ -431,11 +435,13 @@ impl SessionTransport for IsolatedSessionTransport { } impl FastestResultComputer { - pub fn new(self_node_id: NodeId, key_share: Option<&DocumentKeyShare>) -> Self { + pub fn new(self_node_id: NodeId, key_share: Option<&DocumentKeyShare>, configured_nodes_count: usize, connected_nodes_count: usize) -> Self { let threshold = key_share.map(|ks| ks.threshold); FastestResultComputer { - self_node_id: self_node_id, - threshold: threshold, + self_node_id, + threshold, + configured_nodes_count, + connected_nodes_count, } }} @@ -443,7 +449,7 @@ impl SessionResultComputer for FastestResultComputer { fn compute_result(&self, threshold: Option, confirmations: &BTreeSet, versions: &BTreeMap>) -> Option> { match self.threshold.or(threshold) { // if there's no versions at all && we're not waiting for confirmations anymore - _ if confirmations.is_empty() && versions.is_empty() => Some(Err(Error::MissingKeyShare)), + _ if confirmations.is_empty() && versions.is_empty() => Some(Err(Error::ServerKeyIsNotFound)), // if we have key share on this node Some(threshold) => { // select version this node have, with enough participants @@ -459,7 +465,17 @@ impl SessionResultComputer for FastestResultComputer { .find(|&(_, ref n)| n.len() >= threshold + 1) .map(|(version, nodes)| Ok((version.clone(), nodes.iter().cloned().nth(0) .expect("version is only inserted when there's at least one owner; qed")))) - .unwrap_or(Err(Error::ConsensusUnreachable))), + // if there's no version consensus among all connected nodes + // AND we're connected to ALL configured nodes + // OR there are less than required nodes for key restore + // => this means that we can't restore key with CURRENT configuration => respond with fatal error + // otherwise we could try later, after all nodes are connected + .unwrap_or_else(|| Err(if self.configured_nodes_count == self.connected_nodes_count + || self.configured_nodes_count < threshold + 1 { + Error::ConsensusUnreachable + } else { + Error::ConsensusTemporaryUnreachable + }))), } }, // if we do not have share, then wait for all confirmations @@ -469,7 +485,11 @@ impl SessionResultComputer for FastestResultComputer { .max_by_key(|&(_, ref n)| n.len()) .map(|(version, nodes)| Ok((version.clone(), nodes.iter().cloned().nth(0) .expect("version is only inserted when there's at least one owner; qed")))) - .unwrap_or(Err(Error::ConsensusUnreachable))), + .unwrap_or_else(|| Err(if self.configured_nodes_count == self.connected_nodes_count { + Error::ConsensusUnreachable + } else { + Error::ConsensusTemporaryUnreachable + }))), } } } @@ -480,7 +500,7 @@ impl SessionResultComputer for LargestSupportResultComputer { return None; } if versions.is_empty() { - return Some(Err(Error::MissingKeyShare)); + return Some(Err(Error::ServerKeyIsNotFound)); } versions.iter() @@ -552,12 +572,15 @@ mod tests { id: Default::default(), self_node_id: node_id.clone(), master_node_id: master_node_id.clone(), + configured_nodes_count: nodes.len(), + connected_nodes_count: nodes.len(), }, sub_session: sub_sesion.clone(), key_share: key_storage.get(&Default::default()).unwrap(), result_computer: Arc::new(FastestResultComputer::new( node_id.clone(), key_storage.get(&Default::default()).unwrap().as_ref(), + nodes.len(), nodes.len() )), transport: DummyTransport { cluster: cluster, @@ -723,13 +746,15 @@ mod tests { let computer = FastestResultComputer { self_node_id: Default::default(), threshold: None, + configured_nodes_count: 1, + connected_nodes_count: 1, }; - assert_eq!(computer.compute_result(Some(10), &Default::default(), &Default::default()), Some(Err(Error::MissingKeyShare))); + assert_eq!(computer.compute_result(Some(10), &Default::default(), &Default::default()), Some(Err(Error::ServerKeyIsNotFound))); } #[test] fn largest_computer_returns_missing_share_if_no_versions_returned() { let computer = LargestSupportResultComputer; - assert_eq!(computer.compute_result(Some(10), &Default::default(), &Default::default()), Some(Err(Error::MissingKeyShare))); + assert_eq!(computer.compute_result(Some(10), &Default::default(), &Default::default()), Some(Err(Error::ServerKeyIsNotFound))); } } diff --git a/secret_store/src/key_server_cluster/admin_sessions/mod.rs b/secret_store/src/key_server_cluster/admin_sessions/mod.rs index 01655653a2c..11c01cac53e 100644 --- a/secret_store/src/key_server_cluster/admin_sessions/mod.rs +++ b/secret_store/src/key_server_cluster/admin_sessions/mod.rs @@ -32,6 +32,10 @@ pub struct ShareChangeSessionMeta { pub master_node_id: NodeId, /// Id of node, on which this session is running. pub self_node_id: NodeId, + /// Count of all configured key server nodes. + pub configured_nodes_count: usize, + /// Count of all connected key server nodes. + pub connected_nodes_count: usize, } impl ShareChangeSessionMeta { @@ -42,6 +46,8 @@ impl ShareChangeSessionMeta { master_node_id: self.master_node_id, self_node_id: self.self_node_id, threshold: all_nodes_set_len.checked_sub(1).ok_or(Error::ConsensusUnreachable)?, + configured_nodes_count: self.configured_nodes_count, + connected_nodes_count: self.connected_nodes_count, }) } } diff --git a/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs b/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs index e9aacdfbb4e..698872aadc2 100644 --- a/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs +++ b/secret_store/src/key_server_cluster/admin_sessions/servers_set_change_session.rs @@ -282,7 +282,7 @@ impl SessionImpl { &ServersSetChangeMessage::ServersSetChangeShareAddMessage(ref message) => self.on_share_add_message(sender, message), &ServersSetChangeMessage::ServersSetChangeError(ref message) => { - self.on_session_error(sender, Error::Io(message.error.clone())); + self.on_session_error(sender, message.error.clone()); Ok(()) }, &ServersSetChangeMessage::ServersSetChangeCompleted(ref message) => @@ -416,12 +416,14 @@ impl SessionImpl { match &message.message { &KeyVersionNegotiationMessage::RequestKeyVersions(ref message) if sender == &self.core.meta.master_node_id => { let key_id = message.session.clone().into(); - let key_share = self.core.key_storage.get(&key_id).map_err(|e| Error::KeyStorage(e.into()))?; + let key_share = self.core.key_storage.get(&key_id)?; let negotiation_session = KeyVersionNegotiationSessionImpl::new(KeyVersionNegotiationSessionParams { meta: ShareChangeSessionMeta { id: key_id.clone(), self_node_id: self.core.meta.self_node_id.clone(), master_node_id: sender.clone(), + configured_nodes_count: self.core.meta.configured_nodes_count, + connected_nodes_count: self.core.meta.connected_nodes_count, }, sub_session: message.sub_session.clone().into(), key_share: key_share, @@ -492,7 +494,7 @@ impl SessionImpl { // on nodes, holding selected key share version, we could check if master node plan is correct let master_node_id = message.master_node_id.clone().into(); - if let Some(key_share) = self.core.key_storage.get(&key_id).map_err(|e| Error::KeyStorage(e.into()))? { + if let Some(key_share) = self.core.key_storage.get(&key_id)? { let version = message.version.clone().into(); if let Ok(key_version) = key_share.version(&version) { let key_share_owners = key_version.id_numbers.keys().cloned().collect(); @@ -660,7 +662,7 @@ impl SessionImpl { if !data.new_nodes_set.as_ref() .expect("new_nodes_set is filled during initialization; session is completed after initialization; qed") .contains(&self.core.meta.self_node_id) { - self.core.key_storage.clear().map_err(|e| Error::KeyStorage(e.into()))?; + self.core.key_storage.clear()?; } data.state = SessionState::Finished; @@ -709,6 +711,8 @@ impl SessionImpl { id: key_id, self_node_id: core.meta.self_node_id.clone(), master_node_id: master_node_id, + configured_nodes_count: core.meta.configured_nodes_count, + connected_nodes_count: core.meta.connected_nodes_count, }, cluster: core.cluster.clone(), key_storage: core.key_storage.clone(), @@ -731,12 +735,14 @@ impl SessionImpl { Some(Ok(key_id)) => key_id, }; - let key_share = core.key_storage.get(&key_id).map_err(|e| Error::KeyStorage(e.into()))?; + let key_share = core.key_storage.get(&key_id)?; let negotiation_session = KeyVersionNegotiationSessionImpl::new(KeyVersionNegotiationSessionParams { meta: ShareChangeSessionMeta { id: key_id, self_node_id: core.meta.self_node_id.clone(), master_node_id: core.meta.self_node_id.clone(), + configured_nodes_count: core.meta.configured_nodes_count, + connected_nodes_count: core.meta.connected_nodes_count, }, sub_session: math::generate_random_scalar()?, key_share: key_share, @@ -888,7 +894,7 @@ impl SessionImpl { if !data.new_nodes_set.as_ref() .expect("new_nodes_set is filled during initialization; session is completed after initialization; qed") .contains(&core.meta.self_node_id) { - core.key_storage.clear().map_err(|e| Error::KeyStorage(e.into()))?; + core.key_storage.clear()?; } data.state = SessionState::Finished; @@ -1011,9 +1017,9 @@ impl KeyVersionNegotiationTransport for ServersSetChangeKeyVersionNegotiationTra } fn check_nodes_set(all_nodes_set: &BTreeSet, new_nodes_set: &BTreeSet) -> Result<(), Error> { - // all new nodes must be a part of all nodes set + // all_nodes_set is the set of nodes we're currently connected to (and configured for) match new_nodes_set.iter().any(|n| !all_nodes_set.contains(n)) { - true => Err(Error::InvalidNodesConfiguration), + true => Err(Error::NodeDisconnected), false => Ok(()) } } @@ -1104,6 +1110,8 @@ pub mod tests { self_node_id: master_node_id.clone(), master_node_id: master_node_id.clone(), id: SessionId::default(), + configured_nodes_count: all_nodes_set.len(), + connected_nodes_count: all_nodes_set.len(), }; let old_nodes = gml.nodes.iter().map(|n| create_node(meta.clone(), admin_public.clone(), all_nodes_set.clone(), n.1)); diff --git a/secret_store/src/key_server_cluster/admin_sessions/share_add_session.rs b/secret_store/src/key_server_cluster/admin_sessions/share_add_session.rs index 7da73543bea..abe34edeab2 100644 --- a/secret_store/src/key_server_cluster/admin_sessions/share_add_session.rs +++ b/secret_store/src/key_server_cluster/admin_sessions/share_add_session.rs @@ -155,9 +155,7 @@ pub struct IsolatedSessionTransport { impl SessionImpl where T: SessionTransport { /// Create new share addition session. pub fn new(params: SessionParams) -> Result { - let key_share = params.key_storage - .get(¶ms.meta.id) - .map_err(|e| Error::KeyStorage(e.into()))?; + let key_share = params.key_storage.get(¶ms.meta.id)?; Ok(SessionImpl { core: SessionCore { @@ -257,8 +255,8 @@ impl SessionImpl where T: SessionTransport { let admin_public = self.core.admin_public.as_ref().cloned().ok_or(Error::ConsensusUnreachable)?; // key share version is required on ShareAdd master node - let key_share = self.core.key_share.as_ref().ok_or_else(|| Error::KeyStorage("key share is not found on master node".into()))?; - let key_version = key_share.version(&version).map_err(|e| Error::KeyStorage(e.into()))?; + let key_share = self.core.key_share.as_ref().ok_or_else(|| Error::ServerKeyIsNotFound)?; + let key_version = key_share.version(&version)?; // old nodes set is all non-isolated owners of version holders let non_isolated_nodes = self.core.transport.nodes(); @@ -326,7 +324,7 @@ impl SessionImpl where T: SessionTransport { &ShareAddMessage::NewKeysDissemination(ref message) => self.on_new_keys_dissemination(sender, message), &ShareAddMessage::ShareAddError(ref message) => { - self.on_session_error(sender, Error::Io(message.error.clone().into())); + self.on_session_error(sender, message.error.clone()); Ok(()) }, } @@ -714,10 +712,10 @@ impl SessionImpl where T: SessionTransport { // save encrypted data to the key storage data.state = SessionState::Finished; if core.key_share.is_some() { - core.key_storage.update(core.meta.id.clone(), refreshed_key_share.clone()) + core.key_storage.update(core.meta.id.clone(), refreshed_key_share.clone())?; } else { - core.key_storage.insert(core.meta.id.clone(), refreshed_key_share.clone()) - }.map_err(|e| Error::KeyStorage(e.into()))?; + core.key_storage.insert(core.meta.id.clone(), refreshed_key_share.clone())?; + } // signal session completion data.state = SessionState::Finished; @@ -851,7 +849,7 @@ impl SessionTransport for IsolatedSessionTransport { #[cfg(test)] pub mod tests { use std::sync::Arc; - use std::collections::{VecDeque, BTreeMap, BTreeSet}; + use std::collections::{VecDeque, BTreeMap, BTreeSet, HashSet}; use ethkey::{Random, Generator, Public, KeyPair, Signature, sign}; use ethereum_types::H256; use key_server_cluster::{NodeId, SessionId, Error, KeyStorage, DummyKeyStorage}; @@ -952,6 +950,8 @@ pub mod tests { id: SessionId::default(), self_node_id: NodeId::default(), master_node_id: master_node_id, + configured_nodes_count: new_nodes_set.iter().chain(old_nodes_set.iter()).collect::>().len(), + connected_nodes_count: new_nodes_set.iter().chain(old_nodes_set.iter()).collect::>().len(), }; let new_nodes = new_nodes_set.iter() .filter(|n| !old_nodes_set.contains(&n)) @@ -992,6 +992,8 @@ pub mod tests { id: SessionId::default(), self_node_id: NodeId::default(), master_node_id: master_node_id, + configured_nodes_count: new_nodes_set.iter().chain(ml.nodes.keys()).collect::>().len(), + connected_nodes_count: new_nodes_set.iter().chain(ml.nodes.keys()).collect::>().len(), }; let old_nodes_set = ml.nodes.keys().cloned().collect(); let nodes = ml.nodes.iter() @@ -1102,7 +1104,7 @@ pub mod tests { assert_eq!(ml.nodes[&master_node_id].session.initialize(Some(ml.version), Some(new_nodes_set), Some(ml.old_set_signature.clone()), Some(ml.new_set_signature.clone()) - ).unwrap_err(), Error::KeyStorage("key share is not found on master node".into())); + ).unwrap_err(), Error::ServerKeyIsNotFound); } #[test] diff --git a/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs b/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs index c47dd26bad7..083acb64800 100644 --- a/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs +++ b/secret_store/src/key_server_cluster/client_sessions/decryption_session.rs @@ -154,7 +154,7 @@ impl SessionImpl { if let Some(key_share) = params.key_share.as_ref() { // encrypted data must be set if key_share.common_point.is_none() || key_share.encrypted_point.is_none() { - return Err(Error::NotStartedSessionId); + return Err(Error::DocumentKeyIsNotFound); } } @@ -290,7 +290,7 @@ impl SessionImpl { // check if version exists let key_version = match self.core.key_share.as_ref() { None => return Err(Error::InvalidMessage), - Some(key_share) => key_share.version(&version).map_err(|e| Error::KeyStorage(e.into()))?, + Some(key_share) => key_share.version(&version)?, }; let mut data = self.data.lock(); @@ -337,7 +337,7 @@ impl SessionImpl { &DecryptionMessage::PartialDecryption(ref message) => self.on_partial_decryption(sender, message), &DecryptionMessage::DecryptionSessionError(ref message) => - self.process_node_error(Some(&sender), Error::Io(message.error.clone())), + self.process_node_error(Some(&sender), message.error.clone()), &DecryptionMessage::DecryptionSessionCompleted(ref message) => self.on_session_completed(sender, message), &DecryptionMessage::DecryptionSessionDelegation(ref message) => @@ -432,8 +432,7 @@ impl SessionImpl { }; let mut data = self.data.lock(); - let key_version = key_share.version(data.version.as_ref().ok_or(Error::InvalidMessage)?) - .map_err(|e| Error::KeyStorage(e.into()))?.hash.clone(); + let key_version = key_share.version(data.version.as_ref().ok_or(Error::InvalidMessage)?)?.hash.clone(); let requester_public = data.consensus_session.consensus_job().executor().requester() .ok_or(Error::InvalidStateForRequest)? .public(&self.core.meta.id) @@ -564,7 +563,7 @@ impl SessionImpl { match { match node { - Some(node) => data.consensus_session.on_node_error(node), + Some(node) => data.consensus_session.on_node_error(node, error.clone()), None => data.consensus_session.on_session_timeout(), } } { @@ -601,7 +600,7 @@ impl SessionImpl { Some(key_share) => key_share, }; - let key_version = key_share.version(version).map_err(|e| Error::KeyStorage(e.into()))?.hash.clone(); + let key_version = key_share.version(version)?.hash.clone(); let requester = data.consensus_session.consensus_job().executor().requester().ok_or(Error::InvalidStateForRequest)?.clone(); let requester_public = requester.public(&core.meta.id).map_err(Error::InsufficientRequesterData)?; let consensus_group = data.consensus_session.select_consensus_group()?.clone(); @@ -637,6 +636,8 @@ impl SessionImpl { master_node_id: core.meta.self_node_id.clone(), self_node_id: core.meta.self_node_id.clone(), threshold: core.meta.threshold, + configured_nodes_count: core.meta.configured_nodes_count, + connected_nodes_count: core.meta.connected_nodes_count, }, job, transport); job_session.initialize(consensus_group, self_response, core.meta.self_node_id != core.meta.master_node_id)?; data.broadcast_job_session = Some(job_session); @@ -881,6 +882,8 @@ mod tests { self_node_id: id_numbers.iter().nth(i).clone().unwrap().0, master_node_id: id_numbers.iter().nth(0).clone().unwrap().0, threshold: encrypted_datas[i].threshold, + configured_nodes_count: 5, + connected_nodes_count: 5, }, access_key: access_key.clone(), key_share: Some(encrypted_datas[i].clone()), @@ -944,6 +947,8 @@ mod tests { self_node_id: self_node_id.clone(), master_node_id: self_node_id.clone(), threshold: 0, + configured_nodes_count: 1, + connected_nodes_count: 1, }, access_key: Random.generate().unwrap().secret().clone(), key_share: Some(DocumentKeyShare { @@ -976,6 +981,8 @@ mod tests { self_node_id: self_node_id.clone(), master_node_id: self_node_id.clone(), threshold: 0, + configured_nodes_count: 1, + connected_nodes_count: 1, }, access_key: Random.generate().unwrap().secret().clone(), key_share: None, @@ -998,6 +1005,8 @@ mod tests { self_node_id: self_node_id.clone(), master_node_id: self_node_id.clone(), threshold: 2, + configured_nodes_count: 1, + connected_nodes_count: 1, }, access_key: Random.generate().unwrap().secret().clone(), key_share: Some(DocumentKeyShare { @@ -1131,7 +1140,7 @@ mod tests { let (_, _, _, sessions) = prepare_decryption_sessions(); assert!(sessions[0].decrypted_secret().is_none()); sessions[0].on_session_timeout(); - assert_eq!(sessions[0].decrypted_secret().unwrap().unwrap_err(), Error::ConsensusUnreachable); + assert_eq!(sessions[0].decrypted_secret().unwrap().unwrap_err(), Error::ConsensusTemporaryUnreachable); } #[test] @@ -1141,7 +1150,7 @@ mod tests { // 1 node disconnects => we still can recover secret sessions[0].on_node_timeout(sessions[1].node()); - assert!(sessions[0].data.lock().consensus_session.consensus_job().rejects().contains(sessions[1].node())); + assert!(sessions[0].data.lock().consensus_session.consensus_job().rejects().contains_key(sessions[1].node())); assert!(sessions[0].state() == ConsensusSessionState::EstablishingConsensus); // 2 node are disconnected => we can not recover secret @@ -1208,7 +1217,7 @@ mod tests { let disconnected = sessions[0].data.lock().consensus_session.computation_job().requests().iter().cloned().nth(0).unwrap(); sessions[0].on_node_timeout(&disconnected); assert_eq!(sessions[0].state(), ConsensusSessionState::EstablishingConsensus); - assert!(sessions[0].data.lock().consensus_session.computation_job().rejects().contains(&disconnected)); + assert!(sessions[0].data.lock().consensus_session.computation_job().rejects().contains_key(&disconnected)); assert!(!sessions[0].data.lock().consensus_session.computation_job().requests().contains(&disconnected)); } diff --git a/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs b/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs index ca8bac38154..3c863d1cb93 100644 --- a/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs +++ b/secret_store/src/key_server_cluster/client_sessions/encryption_session.rs @@ -306,7 +306,7 @@ impl ClusterSession for SessionImpl { &EncryptionMessage::ConfirmEncryptionInitialization(ref message) => self.on_confirm_initialization(sender.clone(), message), &EncryptionMessage::EncryptionSessionError(ref message) => { - self.on_session_error(sender, Error::Io(message.error.clone().into())); + self.on_session_error(sender, message.error.clone()); Ok(()) }, }, @@ -326,7 +326,7 @@ pub fn check_encrypted_data(key_share: Option<&DocumentKeyShare>) -> Result<(), if let Some(key_share) = key_share { // check that common_point and encrypted_point are still not set yet if key_share.common_point.is_some() || key_share.encrypted_point.is_some() { - return Err(Error::CompletedSessionId); + return Err(Error::DocumentKeyAlreadyStored); } } @@ -344,5 +344,4 @@ pub fn update_encrypted_data(key_storage: &Arc, key_id: ServerKeyId, key_share.common_point = Some(common_point); key_share.encrypted_point = Some(encrypted_point); key_storage.update(key_id, key_share) - .map_err(|e| Error::KeyStorage(e.into())) } diff --git a/secret_store/src/key_server_cluster/client_sessions/generation_session.rs b/secret_store/src/key_server_cluster/client_sessions/generation_session.rs index 0afe618246d..c2effe6c26d 100644 --- a/secret_store/src/key_server_cluster/client_sessions/generation_session.rs +++ b/secret_store/src/key_server_cluster/client_sessions/generation_session.rs @@ -354,7 +354,7 @@ impl SessionImpl { &GenerationMessage::PublicKeyShare(ref message) => self.on_public_key_share(sender.clone(), message), &GenerationMessage::SessionError(ref message) => { - self.on_session_error(sender, Error::Io(message.error.clone().into())); + self.on_session_error(sender, message.error.clone()); Ok(()) }, &GenerationMessage::SessionCompleted(ref message) => @@ -474,7 +474,7 @@ impl SessionImpl { // simulate failure, if required if data.simulate_faulty_behaviour { - return Err(Error::Io("simulated error".into())); + return Err(Error::Internal("simulated error".into())); } // check state @@ -592,8 +592,7 @@ impl SessionImpl { }; if let Some(ref key_storage) = self.key_storage { - key_storage.insert(self.id.clone(), encrypted_data.clone()) - .map_err(|e| Error::KeyStorage(e.into()))?; + key_storage.insert(self.id.clone(), encrypted_data.clone())?; } // then respond with confirmation @@ -790,8 +789,7 @@ impl SessionImpl { // then save encrypted data to the key storage if let Some(ref key_storage) = self.key_storage { - key_storage.insert(self.id.clone(), encrypted_data.clone()) - .map_err(|e| Error::KeyStorage(e.into()))?; + key_storage.insert(self.id.clone(), encrypted_data.clone())?; } // then distribute encrypted data to every other node @@ -925,23 +923,15 @@ impl Debug for SessionImpl { } } -pub fn check_cluster_nodes(self_node_id: &NodeId, nodes: &BTreeSet) -> Result<(), Error> { - // at least two nodes must be in cluster - if nodes.len() < 1 { - return Err(Error::InvalidNodesCount); - } - // this node must be a part of cluster - if !nodes.contains(self_node_id) { - return Err(Error::InvalidNodesConfiguration); - } - +fn check_cluster_nodes(self_node_id: &NodeId, nodes: &BTreeSet) -> Result<(), Error> { + assert!(nodes.contains(self_node_id)); Ok(()) } -pub fn check_threshold(threshold: usize, nodes: &BTreeSet) -> Result<(), Error> { +fn check_threshold(threshold: usize, nodes: &BTreeSet) -> Result<(), Error> { // at least threshold + 1 nodes are required to collectively decrypt message if threshold >= nodes.len() { - return Err(Error::InvalidThreshold); + return Err(Error::NotEnoughNodesForThreshold); } Ok(()) @@ -1096,25 +1086,10 @@ pub mod tests { assert!(l.master().initialize(Default::default(), Default::default(), false, 0, l.nodes.keys().cloned().collect::>().into()).is_ok()); } - #[test] - fn fails_to_initialize_if_not_a_part_of_cluster() { - let node_id = math::generate_random_point().unwrap(); - let cluster = Arc::new(DummyCluster::new(node_id.clone())); - let session = SessionImpl::new(SessionParams { - id: SessionId::default(), - self_node_id: node_id.clone(), - key_storage: Some(Arc::new(DummyKeyStorage::default())), - cluster: cluster, - nonce: Some(0), - }); - let cluster_nodes: BTreeSet<_> = (0..2).map(|_| math::generate_random_point().unwrap()).collect(); - assert_eq!(session.initialize(Default::default(), Default::default(), false, 0, cluster_nodes.into()).unwrap_err(), Error::InvalidNodesConfiguration); - } - #[test] fn fails_to_initialize_if_threshold_is_wrong() { match make_simple_cluster(2, 2) { - Err(Error::InvalidThreshold) => (), + Err(Error::NotEnoughNodesForThreshold) => (), _ => panic!("unexpected"), } } @@ -1193,24 +1168,6 @@ pub mod tests { assert!(l.master().derived_point().unwrap() != passed_point.into()); } - #[test] - fn fails_to_complete_initialization_if_not_a_part_of_cluster() { - let (sid, m, _, l) = make_simple_cluster(0, 2).unwrap(); - let mut nodes = BTreeMap::new(); - nodes.insert(m, math::generate_random_scalar().unwrap()); - nodes.insert(math::generate_random_point().unwrap(), math::generate_random_scalar().unwrap()); - assert_eq!(l.first_slave().on_initialize_session(m, &message::InitializeSession { - session: sid.into(), - session_nonce: 0, - origin: None, - author: Address::default().into(), - nodes: nodes.into_iter().map(|(k, v)| (k.into(), v.into())).collect(), - is_zero: false, - threshold: 0, - derived_point: math::generate_random_point().unwrap().into(), - }).unwrap_err(), Error::InvalidNodesConfiguration); - } - #[test] fn fails_to_complete_initialization_if_threshold_is_wrong() { let (sid, m, s, l) = make_simple_cluster(0, 2).unwrap(); @@ -1226,7 +1183,7 @@ pub mod tests { is_zero: false, threshold: 2, derived_point: math::generate_random_point().unwrap().into(), - }).unwrap_err(), Error::InvalidThreshold); + }).unwrap_err(), Error::NotEnoughNodesForThreshold); } #[test] diff --git a/secret_store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs b/secret_store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs index 02c20bc20e1..b0d465343bd 100644 --- a/secret_store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs +++ b/secret_store/src/key_server_cluster/client_sessions/signing_session_ecdsa.rs @@ -187,6 +187,8 @@ impl SessionImpl { master_node_id: params.meta.master_node_id, self_node_id: params.meta.self_node_id, threshold: params.meta.threshold * 2, + configured_nodes_count: params.meta.configured_nodes_count, + connected_nodes_count: params.meta.connected_nodes_count, }, consensus_executor: match requester { Some(requester) => KeyAccessJob::new_on_master(params.meta.id.clone(), params.acl_storage.clone(), requester), @@ -259,7 +261,7 @@ impl SessionImpl { // check if version exists let key_version = match self.core.key_share.as_ref() { None => return Err(Error::InvalidMessage), - Some(key_share) => key_share.version(&version).map_err(|e| Error::KeyStorage(e.into()))?, + Some(key_share) => key_share.version(&version)?, }; // select nodes to participate in consensus etablish session @@ -311,7 +313,7 @@ impl SessionImpl { &EcdsaSigningMessage::EcdsaPartialSignature(ref message) => self.on_partial_signature(sender, message), &EcdsaSigningMessage::EcdsaSigningSessionError(ref message) => - self.process_node_error(Some(&sender), Error::Io(message.error.clone())), + self.process_node_error(Some(&sender), message.error.clone()), &EcdsaSigningMessage::EcdsaSigningSessionCompleted(ref message) => self.on_session_completed(sender, message), &EcdsaSigningMessage::EcdsaSigningSessionDelegation(ref message) => @@ -386,8 +388,7 @@ impl SessionImpl { let key_share = self.core.key_share.as_ref() .expect("this is master node; master node is selected so that it has key version; qed"); let key_version = key_share.version(data.version.as_ref() - .expect("this is master node; master node is selected so that it has key version; qed") - ).map_err(|e| Error::KeyStorage(e.into()))?; + .expect("this is master node; master node is selected so that it has key version; qed"))?; let consensus_group = data.consensus_session.select_consensus_group()?.clone(); let mut other_consensus_group_nodes = consensus_group.clone(); @@ -680,7 +681,7 @@ impl SessionImpl { let inv_nonce_share = data.inv_nonce_generation_session.as_ref().expect(nonce_exists_proof).joint_public_and_secret().expect(nonce_exists_proof)?.2; let version = data.version.as_ref().ok_or(Error::InvalidMessage)?.clone(); - let key_version = key_share.version(&version).map_err(|e| Error::KeyStorage(e.into()))?.hash.clone(); + let key_version = key_share.version(&version)?.hash.clone(); let signing_job = EcdsaSigningJob::new_on_slave(key_share.clone(), key_version, sig_nonce_public, inv_nonce_share)?; let signing_transport = self.core.signing_transport(); @@ -744,7 +745,7 @@ impl SessionImpl { match { match node { - Some(node) => data.consensus_session.on_node_error(node), + Some(node) => data.consensus_session.on_node_error(node, error.clone()), None => data.consensus_session.on_session_timeout(), } } { @@ -970,6 +971,14 @@ impl Cluster for NonceGenerationTransport where F: Fn(SessionId, Secret, u fn nodes(&self) -> BTreeSet { self.cluster.nodes() } + + fn configured_nodes_count(&self) -> usize { + self.cluster.configured_nodes_count() + } + + fn connected_nodes_count(&self) -> usize { + self.cluster.connected_nodes_count() + } } impl SessionCore { @@ -988,7 +997,7 @@ impl SessionCore { Some(key_share) => key_share, }; - let key_version = key_share.version(version).map_err(|e| Error::KeyStorage(e.into()))?.hash.clone(); + let key_version = key_share.version(version)?.hash.clone(); let signing_job = EcdsaSigningJob::new_on_master(key_share.clone(), key_version, nonce_public, inv_nonce_share, inversed_nonce_coeff, message_hash)?; consensus_session.disseminate_jobs(signing_job, self.signing_transport(), false).map(|_| ()) } @@ -1099,6 +1108,8 @@ mod tests { self_node_id: gl_node_id.clone(), master_node_id: master_node_id.clone(), threshold: gl_node.key_storage.get(&session_id).unwrap().unwrap().threshold, + configured_nodes_count: gl.nodes.len(), + connected_nodes_count: gl.nodes.len(), }, access_key: "834cb736f02d9c968dfaf0c37658a1d86ff140554fc8b59c9fdad5a8cf810eec".parse().unwrap(), key_share: Some(gl_node.key_storage.get(&session_id).unwrap().unwrap()), diff --git a/secret_store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs b/secret_store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs index ed7164ca3a9..013748827c0 100644 --- a/secret_store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs +++ b/secret_store/src/key_server_cluster/client_sessions/signing_session_schnorr.rs @@ -246,7 +246,7 @@ impl SessionImpl { // check if version exists let key_version = match self.core.key_share.as_ref() { None => return Err(Error::InvalidMessage), - Some(key_share) => key_share.version(&version).map_err(|e| Error::KeyStorage(e.into()))?, + Some(key_share) => key_share.version(&version)?, }; let mut data = self.data.lock(); @@ -313,7 +313,7 @@ impl SessionImpl { &SchnorrSigningMessage::SchnorrPartialSignature(ref message) => self.on_partial_signature(sender, message), &SchnorrSigningMessage::SchnorrSigningSessionError(ref message) => - self.process_node_error(Some(&sender), Error::Io(message.error.clone())), + self.process_node_error(Some(&sender), message.error.clone()), &SchnorrSigningMessage::SchnorrSigningSessionCompleted(ref message) => self.on_session_completed(sender, message), &SchnorrSigningMessage::SchnorrSigningSessionDelegation(ref message) => @@ -500,8 +500,7 @@ impl SessionImpl { .expect("session key is generated before signature is computed; we are in SignatureComputing state; qed") .joint_public_and_secret() .expect("session key is generated before signature is computed; we are in SignatureComputing state; qed")?; - let key_version = key_share.version(data.version.as_ref().ok_or(Error::InvalidMessage)?) - .map_err(|e| Error::KeyStorage(e.into()))?.hash.clone(); + let key_version = key_share.version(data.version.as_ref().ok_or(Error::InvalidMessage)?)?.hash.clone(); let signing_job = SchnorrSigningJob::new_on_slave(self.core.meta.self_node_id.clone(), key_share.clone(), key_version, joint_public_and_secret.0, joint_public_and_secret.1)?; let signing_transport = self.core.signing_transport(); @@ -564,7 +563,7 @@ impl SessionImpl { match { match node { - Some(node) => data.consensus_session.on_node_error(node), + Some(node) => data.consensus_session.on_node_error(node, error.clone()), None => data.consensus_session.on_session_timeout(), } } { @@ -717,6 +716,14 @@ impl Cluster for SessionKeyGenerationTransport { fn nodes(&self) -> BTreeSet { self.cluster.nodes() } + + fn configured_nodes_count(&self) -> usize { + self.cluster.configured_nodes_count() + } + + fn connected_nodes_count(&self) -> usize { + self.cluster.connected_nodes_count() + } } impl SessionCore { @@ -735,7 +742,7 @@ impl SessionCore { Some(key_share) => key_share, }; - let key_version = key_share.version(version).map_err(|e| Error::KeyStorage(e.into()))?.hash.clone(); + let key_version = key_share.version(version)?.hash.clone(); let signing_job = SchnorrSigningJob::new_on_master(self.meta.self_node_id.clone(), key_share.clone(), key_version, session_public, session_secret_share, message_hash)?; consensus_session.disseminate_jobs(signing_job, self.signing_transport(), false).map(|_| ()) @@ -851,6 +858,8 @@ mod tests { self_node_id: gl_node_id.clone(), master_node_id: master_node_id.clone(), threshold: gl_node.key_storage.get(&session_id).unwrap().unwrap().threshold, + configured_nodes_count: gl.nodes.len(), + connected_nodes_count: gl.nodes.len(), }, access_key: "834cb736f02d9c968dfaf0c37658a1d86ff140554fc8b59c9fdad5a8cf810eec".parse().unwrap(), key_share: Some(gl_node.key_storage.get(&session_id).unwrap().unwrap()), @@ -971,6 +980,8 @@ mod tests { self_node_id: self_node_id.clone(), master_node_id: self_node_id.clone(), threshold: 0, + configured_nodes_count: 1, + connected_nodes_count: 1, }, access_key: Random.generate().unwrap().secret().clone(), key_share: Some(DocumentKeyShare { @@ -1003,6 +1014,8 @@ mod tests { self_node_id: self_node_id.clone(), master_node_id: self_node_id.clone(), threshold: 0, + configured_nodes_count: 1, + connected_nodes_count: 1, }, access_key: Random.generate().unwrap().secret().clone(), key_share: None, @@ -1025,6 +1038,8 @@ mod tests { self_node_id: self_node_id.clone(), master_node_id: self_node_id.clone(), threshold: 2, + configured_nodes_count: 1, + connected_nodes_count: 1, }, access_key: Random.generate().unwrap().secret().clone(), key_share: Some(DocumentKeyShare { diff --git a/secret_store/src/key_server_cluster/cluster.rs b/secret_store/src/key_server_cluster/cluster.rs index 26f0e7ef1fa..d782ccd035f 100644 --- a/secret_store/src/key_server_cluster/cluster.rs +++ b/secret_store/src/key_server_cluster/cluster.rs @@ -109,6 +109,10 @@ pub trait Cluster: Send + Sync { fn is_connected(&self, node: &NodeId) -> bool; /// Get a set of connected nodes. fn nodes(&self) -> BTreeSet; + /// Get total count of configured key server nodes (valid at the time of ClusterView creation). + fn configured_nodes_count(&self) -> usize; + /// Get total count of connected key server nodes (valid at the time of ClusterView creation). + fn connected_nodes_count(&self) -> usize; } /// Cluster initialization parameters. @@ -160,6 +164,8 @@ pub struct ClusterClientImpl { /// Network cluster view. It is a communication channel, required in single session. pub struct ClusterView { core: Arc>, + configured_nodes_count: usize, + connected_nodes_count: usize, } /// Cross-thread shareable cluster data. @@ -554,7 +560,7 @@ impl ClusterCore { let is_initialization_message = message.is_initialization_message(); let is_delegation_message = message.is_delegation_message(); match is_initialization_message || is_delegation_message { - false => sessions.get(&session_id, true).ok_or(Error::InvalidSessionId), + false => sessions.get(&session_id, true).ok_or(Error::NoActiveSessionWithId), true => { let creation_data = SC::creation_data_from_message(&message)?; let master = if is_initialization_message { sender.clone() } else { data.self_key_pair.public().clone() }; @@ -652,7 +658,7 @@ impl ClusterConnections { let trigger: Box = match config.auto_migrate_enabled { false => Box::new(SimpleConnectionTrigger::new(config.key_server_set.clone(), config.self_key_pair.clone(), config.admin_public.clone())), true if config.admin_public.is_none() => Box::new(ConnectionTriggerWithMigration::new(config.key_server_set.clone(), config.self_key_pair.clone())), - true => return Err(Error::Io("secret store admininstrator public key is specified with auto-migration enabled".into())), // TODO [Refac]: Io -> Internal + true => return Err(Error::Internal("secret store admininstrator public key is specified with auto-migration enabled".into())), }; let connector = trigger.servers_set_change_creator_connector(); @@ -835,8 +841,10 @@ impl Connection { } impl ClusterView { - pub fn new(cluster: Arc, nodes: BTreeSet) -> Self { + pub fn new(cluster: Arc, nodes: BTreeSet, configured_nodes_count: usize) -> Self { ClusterView { + configured_nodes_count: configured_nodes_count, + connected_nodes_count: nodes.len(), core: Arc::new(Mutex::new(ClusterViewCore { cluster: cluster, nodes: nodes, @@ -871,6 +879,14 @@ impl Cluster for ClusterView { fn nodes(&self) -> BTreeSet { self.core.lock().nodes.clone() } + + fn configured_nodes_count(&self) -> usize { + self.configured_nodes_count + } + + fn connected_nodes_count(&self) -> usize { + self.connected_nodes_count + } } impl ClusterClientImpl { @@ -1125,7 +1141,7 @@ pub mod tests { fn cluster_state(&self) -> ClusterState { unimplemented!("test-only") } fn new_generation_session(&self, _session_id: SessionId, _origin: Option
, _author: Address, _threshold: usize) -> Result, Error> { self.generation_requests_count.fetch_add(1, Ordering::Relaxed); - Err(Error::Io("test-errror".into())) + Err(Error::Internal("test-error".into())) } fn new_encryption_session(&self, _session_id: SessionId, _requester: Requester, _common_point: Public, _encrypted_point: Public) -> Result, Error> { unimplemented!("test-only") } fn new_decryption_session(&self, _session_id: SessionId, _origin: Option
, _requester: Requester, _version: Option, _is_shadow_decryption: bool, _is_broadcast_session: bool) -> Result, Error> { unimplemented!("test-only") } @@ -1197,6 +1213,14 @@ pub mod tests { fn nodes(&self) -> BTreeSet { self.data.lock().nodes.iter().cloned().collect() } + + fn configured_nodes_count(&self) -> usize { + self.data.lock().nodes.len() + } + + fn connected_nodes_count(&self) -> usize { + self.data.lock().nodes.len() + } } pub fn loop_until(core: &mut Core, timeout: Duration, predicate: F) where F: Fn() -> bool { @@ -1365,11 +1389,11 @@ pub mod tests { { // try to start generation session => fail in initialization assert_eq!(clusters[0].client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 100).map(|_| ()), - Err(Error::InvalidThreshold)); + Err(Error::NotEnoughNodesForThreshold)); // try to start generation session => fails in initialization assert_eq!(clusters[0].client().new_generation_session(SessionId::default(), Default::default(), Default::default(), 100).map(|_| ()), - Err(Error::InvalidThreshold)); + Err(Error::NotEnoughNodesForThreshold)); assert!(clusters[0].data.sessions.generation_sessions.is_empty()); } diff --git a/secret_store/src/key_server_cluster/cluster_sessions.rs b/secret_store/src/key_server_cluster/cluster_sessions.rs index e67458f766d..780c947fc37 100644 --- a/secret_store/src/key_server_cluster/cluster_sessions.rs +++ b/secret_store/src/key_server_cluster/cluster_sessions.rs @@ -547,8 +547,9 @@ impl ClusterSession for AdminSession { } } pub fn create_cluster_view(data: &Arc, requires_all_connections: bool) -> Result, Error> { + let disconnected_nodes_count = data.connections.disconnected_nodes().len(); if requires_all_connections { - if !data.connections.disconnected_nodes().is_empty() { + if disconnected_nodes_count != 0 { return Err(Error::NodeDisconnected); } } @@ -556,7 +557,8 @@ pub fn create_cluster_view(data: &Arc, requires_all_connections: bo let mut connected_nodes = data.connections.connected_nodes(); connected_nodes.insert(data.self_key_pair.public().clone()); - Ok(Arc::new(ClusterView::new(data.clone(), connected_nodes))) + let connected_nodes_count = connected_nodes.len(); + Ok(Arc::new(ClusterView::new(data.clone(), connected_nodes, connected_nodes_count + disconnected_nodes_count))) } #[cfg(test)] diff --git a/secret_store/src/key_server_cluster/cluster_sessions_creator.rs b/secret_store/src/key_server_cluster/cluster_sessions_creator.rs index 86e40853e22..a56f51f8fbc 100644 --- a/secret_store/src/key_server_cluster/cluster_sessions_creator.rs +++ b/secret_store/src/key_server_cluster/cluster_sessions_creator.rs @@ -115,7 +115,7 @@ impl SessionCreatorCore { /// Read key share && remove disconnected nodes. fn read_key_share(&self, key_id: &SessionId) -> Result, Error> { - self.key_storage.get(key_id).map_err(|e| Error::KeyStorage(e.into())) + self.key_storage.get(key_id) } } @@ -146,7 +146,7 @@ impl ClusterSessionCreator for GenerationSessionCreat fn create(&self, cluster: Arc, master: NodeId, nonce: Option, id: SessionId, _creation_data: Option<()>) -> Result, Error> { // check that there's no finished encryption session with the same id if self.core.key_storage.contains(&id) { - return Err(Error::DuplicateSessionId); + return Err(Error::ServerKeyAlreadyGenerated); } let nonce = self.core.check_session_nonce(&master, nonce)?; @@ -232,6 +232,8 @@ impl ClusterSessionCreator for DecryptionSessi self_node_id: self.core.self_node_id.clone(), master_node_id: master, threshold: encrypted_data.as_ref().map(|ks| ks.threshold).unwrap_or_default(), + configured_nodes_count: cluster.configured_nodes_count(), + connected_nodes_count: cluster.connected_nodes_count(), }, access_key: id.access_key, key_share: encrypted_data, @@ -278,6 +280,8 @@ impl ClusterSessionCreator for SchnorrSign self_node_id: self.core.self_node_id.clone(), master_node_id: master, threshold: encrypted_data.as_ref().map(|ks| ks.threshold).unwrap_or_default(), + configured_nodes_count: cluster.configured_nodes_count(), + connected_nodes_count: cluster.connected_nodes_count(), }, access_key: id.access_key, key_share: encrypted_data, @@ -324,6 +328,8 @@ impl ClusterSessionCreator for EcdsaSigningS self_node_id: self.core.self_node_id.clone(), master_node_id: master, threshold: encrypted_data.as_ref().map(|ks| ks.threshold).unwrap_or_default(), + configured_nodes_count: cluster.configured_nodes_count(), + connected_nodes_count: cluster.connected_nodes_count(), }, access_key: id.access_key, key_share: encrypted_data, @@ -351,14 +357,19 @@ impl ClusterSessionCreator, master: NodeId, nonce: Option, id: SessionIdWithSubSession, _creation_data: Option<()>) -> Result>, Error> { + let configured_nodes_count = cluster.configured_nodes_count(); + let connected_nodes_count = cluster.connected_nodes_count(); let encrypted_data = self.core.read_key_share(&id.id)?; let nonce = self.core.check_session_nonce(&master, nonce)?; - let computer = Arc::new(FastestResultKeyVersionsResultComputer::new(self.core.self_node_id.clone(), encrypted_data.as_ref())); + let computer = Arc::new(FastestResultKeyVersionsResultComputer::new(self.core.self_node_id.clone(), encrypted_data.as_ref(), + configured_nodes_count, configured_nodes_count)); Ok(Arc::new(KeyVersionNegotiationSessionImpl::new(KeyVersionNegotiationSessionParams { meta: ShareChangeSessionMeta { id: id.id.clone(), self_node_id: self.core.self_node_id.clone(), master_node_id: master, + configured_nodes_count: configured_nodes_count, + connected_nodes_count: connected_nodes_count, }, sub_session: id.access_key.clone(), key_share: encrypted_data, @@ -419,6 +430,8 @@ impl ClusterSessionCreator for AdminSess id: id.clone(), self_node_id: self.core.self_node_id.clone(), master_node_id: master, + configured_nodes_count: cluster.configured_nodes_count(), + connected_nodes_count: cluster.connected_nodes_count(), }, transport: ShareAddTransport::new(id.clone(), Some(version), nonce, cluster), key_storage: self.core.key_storage.clone(), @@ -435,6 +448,8 @@ impl ClusterSessionCreator for AdminSess id: id.clone(), self_node_id: self.core.self_node_id.clone(), master_node_id: master, + configured_nodes_count: cluster.configured_nodes_count(), + connected_nodes_count: cluster.connected_nodes_count(), }, cluster: cluster.clone(), key_storage: self.core.key_storage.clone(), diff --git a/secret_store/src/key_server_cluster/connection_trigger.rs b/secret_store/src/key_server_cluster/connection_trigger.rs index e0172b89aca..66612f044be 100644 --- a/secret_store/src/key_server_cluster/connection_trigger.rs +++ b/secret_store/src/key_server_cluster/connection_trigger.rs @@ -23,7 +23,7 @@ use ethkey::Public; use key_server_cluster::{KeyServerSet, KeyServerSetSnapshot}; use key_server_cluster::cluster::{ClusterClient, ClusterConnectionsData}; use key_server_cluster::cluster_sessions::AdminSession; -use types::all::{Error, NodeId}; +use types::{Error, NodeId}; use {NodeKeyPair}; #[derive(Debug, Clone, Copy, PartialEq)] diff --git a/secret_store/src/key_server_cluster/connection_trigger_with_migration.rs b/secret_store/src/key_server_cluster/connection_trigger_with_migration.rs index 91679928fb6..40a4b5028eb 100644 --- a/secret_store/src/key_server_cluster/connection_trigger_with_migration.rs +++ b/secret_store/src/key_server_cluster/connection_trigger_with_migration.rs @@ -26,7 +26,7 @@ use key_server_cluster::cluster_sessions::{AdminSession, ClusterSession}; use key_server_cluster::jobs::servers_set_change_access_job::ordered_nodes_hash; use key_server_cluster::connection_trigger::{Maintain, ConnectionsAction, ConnectionTrigger, ServersSetChangeSessionCreatorConnector, TriggerConnections}; -use types::all::{Error, NodeId}; +use types::{Error, NodeId}; use {NodeKeyPair}; /// Key servers set change trigger with automated migration procedure. diff --git a/secret_store/src/key_server_cluster/jobs/consensus_session.rs b/secret_store/src/key_server_cluster/jobs/consensus_session.rs index cc4ebc6d9f4..5d780a48ebf 100644 --- a/secret_store/src/key_server_cluster/jobs/consensus_session.rs +++ b/secret_store/src/key_server_cluster/jobs/consensus_session.rs @@ -232,38 +232,42 @@ impl Result { + pub fn on_node_error(&mut self, node: &NodeId, error: Error) -> Result { let is_self_master = self.meta.master_node_id == self.meta.self_node_id; let is_node_master = self.meta.master_node_id == *node; let (is_restart_needed, timeout_result) = match self.state { ConsensusSessionState::WaitingForInitialization if is_self_master => { // it is strange to receive error before session is initialized && slave doesn't know access_key - // => fatal error + // => unreachable self.state = ConsensusSessionState::Failed; (false, Err(Error::ConsensusUnreachable)) } ConsensusSessionState::WaitingForInitialization if is_node_master => { - // can not establish consensus - // => fatal error + // error from master node before establishing consensus + // => unreachable self.state = ConsensusSessionState::Failed; - (false, Err(Error::ConsensusUnreachable)) + (false, Err(if !error.is_non_fatal() { + Error::ConsensusUnreachable + } else { + Error::ConsensusTemporaryUnreachable + })) }, ConsensusSessionState::EstablishingConsensus => { debug_assert!(is_self_master); // consensus still can be established // => try to live without this node - (false, self.consensus_job.on_node_error(node)) + (false, self.consensus_job.on_node_error(node, error)) }, ConsensusSessionState::ConsensusEstablished => { // we could try to continue without this node, if enough nodes left - (false, self.consensus_job.on_node_error(node)) + (false, self.consensus_job.on_node_error(node, error)) }, ConsensusSessionState::WaitingForPartialResults => { // check if *current* computation job can continue without this node let is_computation_node = self.computation_job.as_mut() .expect("WaitingForPartialResults state is only set when computation_job is created; qed") - .on_node_error(node) + .on_node_error(node, error.clone()) .is_err(); if !is_computation_node { // it is not used by current computation job @@ -275,7 +279,7 @@ impl return Ok(false), @@ -312,7 +316,7 @@ impl Result, Error> { - let key_version = self.key_share.version(&self.key_version).map_err(|e| Error::KeyStorage(e.into()))?; + let key_version = self.key_share.version(&self.key_version)?; if partial_request.other_nodes_ids.len() != self.key_share.threshold || partial_request.other_nodes_ids.contains(&self.self_node_id) || partial_request.other_nodes_ids.iter().any(|n| !key_version.id_numbers.contains_key(n)) { diff --git a/secret_store/src/key_server_cluster/jobs/job_session.rs b/secret_store/src/key_server_cluster/jobs/job_session.rs index 82f387d7b99..d3a765bf5bc 100644 --- a/secret_store/src/key_server_cluster/jobs/job_session.rs +++ b/secret_store/src/key_server_cluster/jobs/job_session.rs @@ -101,8 +101,8 @@ struct JobSessionData { struct ActiveJobSessionData { /// Active partial requests. requests: BTreeSet, - /// Rejects to partial requests. - rejects: BTreeSet, + /// Rejects to partial requests (maps to true, if reject is fatal). + rejects: BTreeMap, /// Received partial responses. responses: BTreeMap, } @@ -149,7 +149,7 @@ impl JobSession where Executor: JobExe /// Get rejects. #[cfg(test)] - pub fn rejects(&self) -> &BTreeSet { + pub fn rejects(&self) -> &BTreeMap { debug_assert!(self.meta.self_node_id == self.meta.master_node_id); &self.data.active_data.as_ref() @@ -201,7 +201,11 @@ impl JobSession where Executor: JobExe debug_assert!(self.meta.self_node_id == self.meta.master_node_id); if nodes.len() < self.meta.threshold + 1 { - return Err(Error::ConsensusUnreachable); + return Err(if self.meta.configured_nodes_count < self.meta.threshold + 1 { + Error::ConsensusUnreachable + } else { + Error::ConsensusTemporaryUnreachable + }); } if self.data.state != JobSessionState::Inactive { @@ -211,7 +215,7 @@ impl JobSession where Executor: JobExe // result from self let active_data = ActiveJobSessionData { requests: nodes.clone(), - rejects: BTreeSet::new(), + rejects: BTreeMap::new(), responses: BTreeMap::new(), }; let waits_for_self = active_data.requests.contains(&self.meta.self_node_id); @@ -295,13 +299,14 @@ impl JobSession where Executor: JobExe match self.executor.check_partial_response(node, &response)? { JobPartialResponseAction::Ignore => Ok(()), JobPartialResponseAction::Reject => { - active_data.rejects.insert(node.clone()); + // direct reject is always considered as fatal + active_data.rejects.insert(node.clone(), true); if active_data.requests.len() + active_data.responses.len() >= self.meta.threshold + 1 { return Ok(()); } self.data.state = JobSessionState::Failed; - Err(Error::ConsensusUnreachable) + Err(consensus_unreachable(&active_data.rejects)) }, JobPartialResponseAction::Accept => { active_data.responses.insert(node.clone(), response); @@ -316,22 +321,26 @@ impl JobSession where Executor: JobExe } /// When error from node is received. - pub fn on_node_error(&mut self, node: &NodeId) -> Result<(), Error> { + pub fn on_node_error(&mut self, node: &NodeId, error: Error) -> Result<(), Error> { if self.meta.self_node_id != self.meta.master_node_id { if node != &self.meta.master_node_id { return Ok(()); } self.data.state = JobSessionState::Failed; - return Err(Error::ConsensusUnreachable); + return Err(if !error.is_non_fatal() { + Error::ConsensusUnreachable + } else { + Error::ConsensusTemporaryUnreachable + }); } if let Some(active_data) = self.data.active_data.as_mut() { - if active_data.rejects.contains(node) { + if active_data.rejects.contains_key(node) { return Ok(()); } if active_data.requests.remove(node) || active_data.responses.remove(node).is_some() { - active_data.rejects.insert(node.clone()); + active_data.rejects.insert(node.clone(), !error.is_non_fatal()); if self.data.state == JobSessionState::Finished && active_data.responses.len() < self.meta.threshold + 1 { self.data.state = JobSessionState::Active; } @@ -340,7 +349,7 @@ impl JobSession where Executor: JobExe } self.data.state = JobSessionState::Failed; - return Err(Error::ConsensusUnreachable); + return Err(consensus_unreachable(&active_data.rejects)); } } @@ -354,7 +363,8 @@ impl JobSession where Executor: JobExe } self.data.state = JobSessionState::Failed; - Err(Error::ConsensusUnreachable) + // we have started session => consensus is possible in theory, but now it has failed with timeout + Err(Error::ConsensusTemporaryUnreachable) } } @@ -368,6 +378,16 @@ impl JobPartialRequestAction { } } +/// Returns appropriate 'consensus unreachable' error. +fn consensus_unreachable(rejects: &BTreeMap) -> Error { + // when >= 50% of nodes have responded with fatal reject => ConsensusUnreachable + if rejects.values().filter(|r| **r).count() >= rejects.len() / 2 { + Error::ConsensusUnreachable + } else { + Error::ConsensusTemporaryUnreachable + } +} + #[cfg(test)] pub mod tests { use std::collections::{VecDeque, BTreeMap, BTreeSet}; @@ -414,11 +434,27 @@ pub mod tests { } pub fn make_master_session_meta(threshold: usize) -> SessionMeta { - SessionMeta { id: SessionId::default(), master_node_id: NodeId::from(1), self_node_id: NodeId::from(1), threshold: threshold } + SessionMeta { id: SessionId::default(), master_node_id: NodeId::from(1), self_node_id: NodeId::from(1), threshold: threshold, + configured_nodes_count: 5, connected_nodes_count: 5 } } pub fn make_slave_session_meta(threshold: usize) -> SessionMeta { - SessionMeta { id: SessionId::default(), master_node_id: NodeId::from(1), self_node_id: NodeId::from(2), threshold: threshold } + SessionMeta { id: SessionId::default(), master_node_id: NodeId::from(1), self_node_id: NodeId::from(2), threshold: threshold, + configured_nodes_count: 5, connected_nodes_count: 5 } + } + + #[test] + fn job_initialize_fails_if_not_enough_nodes_for_threshold_total() { + let mut job = JobSession::new(make_master_session_meta(1), SquaredSumJobExecutor, DummyJobTransport::default()); + job.meta.configured_nodes_count = 1; + assert_eq!(job.initialize(vec![Public::from(1)].into_iter().collect(), None, false).unwrap_err(), Error::ConsensusUnreachable); + } + + #[test] + fn job_initialize_fails_if_not_enough_nodes_for_threshold_connected() { + let mut job = JobSession::new(make_master_session_meta(1), SquaredSumJobExecutor, DummyJobTransport::default()); + job.meta.connected_nodes_count = 3; + assert_eq!(job.initialize(vec![Public::from(1)].into_iter().collect(), None, false).unwrap_err(), Error::ConsensusTemporaryUnreachable); } #[test] @@ -528,7 +564,7 @@ pub mod tests { fn job_node_error_ignored_when_slave_disconnects_from_slave() { let mut job = JobSession::new(make_slave_session_meta(1), SquaredSumJobExecutor, DummyJobTransport::default()); assert_eq!(job.state(), JobSessionState::Inactive); - job.on_node_error(&NodeId::from(3)).unwrap(); + job.on_node_error(&NodeId::from(3), Error::AccessDenied).unwrap(); assert_eq!(job.state(), JobSessionState::Inactive); } @@ -536,7 +572,7 @@ pub mod tests { fn job_node_error_leads_to_fail_when_slave_disconnects_from_master() { let mut job = JobSession::new(make_slave_session_meta(1), SquaredSumJobExecutor, DummyJobTransport::default()); assert_eq!(job.state(), JobSessionState::Inactive); - assert_eq!(job.on_node_error(&NodeId::from(1)).unwrap_err(), Error::ConsensusUnreachable); + assert_eq!(job.on_node_error(&NodeId::from(1), Error::AccessDenied).unwrap_err(), Error::ConsensusUnreachable); assert_eq!(job.state(), JobSessionState::Failed); } @@ -546,7 +582,7 @@ pub mod tests { job.initialize(vec![Public::from(1), Public::from(2), Public::from(3)].into_iter().collect(), None, false).unwrap(); assert_eq!(job.state(), JobSessionState::Active); job.on_partial_response(&NodeId::from(2), 3).unwrap(); - job.on_node_error(&NodeId::from(2)).unwrap(); + job.on_node_error(&NodeId::from(2), Error::AccessDenied).unwrap(); assert_eq!(job.state(), JobSessionState::Active); } @@ -555,7 +591,7 @@ pub mod tests { let mut job = JobSession::new(make_master_session_meta(1), SquaredSumJobExecutor, DummyJobTransport::default()); job.initialize(vec![Public::from(1), Public::from(2)].into_iter().collect(), None, false).unwrap(); assert_eq!(job.state(), JobSessionState::Active); - job.on_node_error(&NodeId::from(3)).unwrap(); + job.on_node_error(&NodeId::from(3), Error::AccessDenied).unwrap(); assert_eq!(job.state(), JobSessionState::Active); } @@ -564,7 +600,7 @@ pub mod tests { let mut job = JobSession::new(make_master_session_meta(1), SquaredSumJobExecutor, DummyJobTransport::default()); job.initialize(vec![Public::from(1), Public::from(2), Public::from(3)].into_iter().collect(), None, false).unwrap(); assert_eq!(job.state(), JobSessionState::Active); - job.on_node_error(&NodeId::from(3)).unwrap(); + job.on_node_error(&NodeId::from(3), Error::AccessDenied).unwrap(); assert_eq!(job.state(), JobSessionState::Active); } @@ -573,7 +609,7 @@ pub mod tests { let mut job = JobSession::new(make_master_session_meta(1), SquaredSumJobExecutor, DummyJobTransport::default()); job.initialize(vec![Public::from(1), Public::from(2)].into_iter().collect(), None, false).unwrap(); assert_eq!(job.state(), JobSessionState::Active); - assert_eq!(job.on_node_error(&NodeId::from(2)).unwrap_err(), Error::ConsensusUnreachable); + assert_eq!(job.on_node_error(&NodeId::from(2), Error::AccessDenied).unwrap_err(), Error::ConsensusUnreachable); assert_eq!(job.state(), JobSessionState::Failed); } @@ -592,4 +628,34 @@ pub mod tests { assert_eq!(job.state(), JobSessionState::Active); assert!(job.transport().is_empty_response()); } + + #[test] + fn job_fails_with_temp_error_if_more_than_half_nodes_respond_with_temp_error() { + let mut job = JobSession::new(make_master_session_meta(2), SquaredSumJobExecutor, DummyJobTransport::default()); + job.initialize(vec![Public::from(1), Public::from(2), Public::from(3), Public::from(4)].into_iter().collect(), None, false).unwrap(); + job.on_node_error(&NodeId::from(2), Error::NodeDisconnected).unwrap(); + assert_eq!(job.on_node_error(&NodeId::from(3), Error::NodeDisconnected).unwrap_err(), Error::ConsensusTemporaryUnreachable); + } + + #[test] + fn job_fails_with_temp_error_if_more_than_half_rejects_are_temp() { + let mut job = JobSession::new(make_master_session_meta(2), SquaredSumJobExecutor, DummyJobTransport::default()); + job.initialize(vec![Public::from(1), Public::from(2), Public::from(3), Public::from(4)].into_iter().collect(), None, false).unwrap(); + job.on_node_error(&NodeId::from(2), Error::NodeDisconnected).unwrap(); + assert_eq!(job.on_node_error(&NodeId::from(3), Error::NodeDisconnected).unwrap_err(), Error::ConsensusTemporaryUnreachable); + } + + #[test] + fn job_fails_if_more_than_half_rejects_are_non_temp() { + let mut job = JobSession::new(make_master_session_meta(2), SquaredSumJobExecutor, DummyJobTransport::default()); + job.initialize(vec![Public::from(1), Public::from(2), Public::from(3), Public::from(4)].into_iter().collect(), None, false).unwrap(); + job.on_node_error(&NodeId::from(2), Error::AccessDenied).unwrap(); + assert_eq!(job.on_node_error(&NodeId::from(3), Error::AccessDenied).unwrap_err(), Error::ConsensusUnreachable); + } + + #[test] + fn job_fails_with_temp_error_when_temp_error_is_reported_by_master_node() { + let mut job = JobSession::new(make_slave_session_meta(2), SquaredSumJobExecutor, DummyJobTransport::default()); + assert_eq!(job.on_node_error(&NodeId::from(1), Error::NodeDisconnected).unwrap_err(), Error::ConsensusTemporaryUnreachable); + } } diff --git a/secret_store/src/key_server_cluster/jobs/signing_job_ecdsa.rs b/secret_store/src/key_server_cluster/jobs/signing_job_ecdsa.rs index 561a8e0f87c..8f4ab1d68eb 100644 --- a/secret_store/src/key_server_cluster/jobs/signing_job_ecdsa.rs +++ b/secret_store/src/key_server_cluster/jobs/signing_job_ecdsa.rs @@ -108,7 +108,7 @@ impl JobExecutor for EcdsaSigningJob { fn process_partial_request(&mut self, partial_request: EcdsaPartialSigningRequest) -> Result, Error> { let inversed_nonce_coeff_mul_nonce = math::compute_secret_mul(&partial_request.inversed_nonce_coeff, &self.inv_nonce_share)?; - let key_version = self.key_share.version(&self.key_version).map_err(|e| Error::KeyStorage(e.into()))?; + let key_version = self.key_share.version(&self.key_version)?; let signature_r = math::compute_ecdsa_r(&self.nonce_public)?; let inv_nonce_mul_secret = math::compute_secret_mul(&inversed_nonce_coeff_mul_nonce, &key_version.secret_share)?; let partial_signature_s = math::compute_ecdsa_s_share( @@ -134,7 +134,7 @@ impl JobExecutor for EcdsaSigningJob { } fn compute_response(&self, partial_responses: &BTreeMap) -> Result { - let key_version = self.key_share.version(&self.key_version).map_err(|e| Error::KeyStorage(e.into()))?; + let key_version = self.key_share.version(&self.key_version)?; if partial_responses.keys().any(|n| !key_version.id_numbers.contains_key(n)) { return Err(Error::InvalidMessage); } diff --git a/secret_store/src/key_server_cluster/jobs/signing_job_schnorr.rs b/secret_store/src/key_server_cluster/jobs/signing_job_schnorr.rs index 6246a728de9..54225a6cf57 100644 --- a/secret_store/src/key_server_cluster/jobs/signing_job_schnorr.rs +++ b/secret_store/src/key_server_cluster/jobs/signing_job_schnorr.rs @@ -107,7 +107,7 @@ impl JobExecutor for SchnorrSigningJob { } fn process_partial_request(&mut self, partial_request: SchnorrPartialSigningRequest) -> Result, Error> { - let key_version = self.key_share.version(&self.key_version).map_err(|e| Error::KeyStorage(e.into()))?; + let key_version = self.key_share.version(&self.key_version)?; if partial_request.other_nodes_ids.len() != self.key_share.threshold || partial_request.other_nodes_ids.contains(&self.self_node_id) || partial_request.other_nodes_ids.iter().any(|n| !key_version.id_numbers.contains_key(n)) { diff --git a/secret_store/src/key_server_cluster/message.rs b/secret_store/src/key_server_cluster/message.rs index e08d6761a61..cc49e56fdb5 100644 --- a/secret_store/src/key_server_cluster/message.rs +++ b/secret_store/src/key_server_cluster/message.rs @@ -18,8 +18,8 @@ use std::fmt; use std::collections::{BTreeSet, BTreeMap}; use ethkey::Secret; use key_server_cluster::SessionId; -use super::{SerializableH256, SerializablePublic, SerializableSecret, SerializableSignature, - SerializableMessageHash, SerializableRequester, SerializableAddress}; +use super::{Error, SerializableH256, SerializablePublic, SerializableSecret, + SerializableSignature, SerializableMessageHash, SerializableRequester, SerializableAddress}; pub type MessageSessionId = SerializableH256; pub type MessageNodeId = SerializablePublic; @@ -346,7 +346,7 @@ pub struct SessionError { /// Session-level nonce. pub session_nonce: u64, /// Error message. - pub error: String, + pub error: Error, } /// When session is completed. @@ -390,7 +390,7 @@ pub struct EncryptionSessionError { /// Session-level nonce. pub session_nonce: u64, /// Error message. - pub error: String, + pub error: Error, } /// Node is asked to be part of consensus group. @@ -509,7 +509,7 @@ pub struct SchnorrSigningSessionError { /// Session-level nonce. pub session_nonce: u64, /// Error message. - pub error: String, + pub error: Error, } /// Schnorr signing session completed. @@ -662,7 +662,7 @@ pub struct EcdsaSigningSessionError { /// Session-level nonce. pub session_nonce: u64, /// Error message. - pub error: String, + pub error: Error, } /// ECDSA signing session completed. @@ -769,7 +769,7 @@ pub struct DecryptionSessionError { /// Session-level nonce. pub session_nonce: u64, /// Error message. - pub error: String, + pub error: Error, } /// When decryption session is completed. @@ -936,7 +936,7 @@ pub struct ServersSetChangeError { /// Session-level nonce. pub session_nonce: u64, /// Error message. - pub error: String, + pub error: Error, } /// When servers set change session is completed. @@ -999,7 +999,7 @@ pub struct ShareAddError { /// Session-level nonce. pub session_nonce: u64, /// Error message. - pub error: String, + pub error: Error, } /// Key versions are requested. @@ -1038,7 +1038,7 @@ pub struct KeyVersionsError { /// Session-level nonce. pub session_nonce: u64, /// Error message. - pub error: String, + pub error: Error, } impl Message { diff --git a/secret_store/src/key_server_cluster/mod.rs b/secret_store/src/key_server_cluster/mod.rs index 94386d0510a..d5ac85b3dea 100644 --- a/secret_store/src/key_server_cluster/mod.rs +++ b/secret_store/src/key_server_cluster/mod.rs @@ -14,14 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::fmt; -use std::io::Error as IoError; -use ethkey; -use crypto; -use super::types::all::ServerKeyId; +use super::types::ServerKeyId; pub use super::traits::NodeKeyPair; -pub use super::types::all::{NodeId, Requester, EncryptedDocumentKeyShadow}; +pub use super::types::{Error, NodeId, Requester, EncryptedDocumentKeyShadow}; pub use super::acl_storage::AclStorage; pub use super::key_storage::{KeyStorage, DocumentKeyShare, DocumentKeyShareVersion}; pub use super::key_server_set::{is_migration_required, KeyServerSet, KeyServerSetSnapshot, KeyServerSetMigration}; @@ -53,126 +49,10 @@ pub struct SessionMeta { pub self_node_id: NodeId, /// Session threshold. pub threshold: usize, -} - -/// Errors which can occur during encryption/decryption session -#[derive(Clone, Debug, PartialEq)] -pub enum Error { - /// Invalid node address has been passed. - InvalidNodeAddress, - /// Invalid node id has been passed. - InvalidNodeId, - /// Session with the given id already exists. - DuplicateSessionId, - /// Session with the same id already completed. - CompletedSessionId, - /// Session is not ready to start yet (required data is not ready). - NotStartedSessionId, - /// Session with the given id is unknown. - InvalidSessionId, - /// Invalid number of nodes. - /// There must be at least two nodes participating in encryption. - /// There must be at least one node participating in decryption. - InvalidNodesCount, - /// Node which is required to start encryption/decryption session is not a part of cluster. - InvalidNodesConfiguration, - /// Invalid threshold value has been passed. - /// Threshold value must be in [0; n - 1], where n is a number of nodes participating in the encryption. - InvalidThreshold, - /// Current state of encryption/decryption session does not allow to proceed request. - /// Reschedule this request for later processing. - TooEarlyForRequest, - /// Current state of encryption/decryption session does not allow to proceed request. - /// This means that either there is some comm-failure or node is misbehaving/cheating. - InvalidStateForRequest, - /// Request cannot be sent/received from this node. - InvalidNodeForRequest, - /// Message or some data in the message was recognized as invalid. - /// This means that node is misbehaving/cheating. - InvalidMessage, - /// Message version is not supported. - InvalidMessageVersion, - /// Message is invalid because of replay-attack protection. - ReplayProtection, - /// Connection to node, required for this session is not established. - NodeDisconnected, - /// Node is missing requested key share. - MissingKeyShare, - /// Cryptographic error. - EthKey(String), - /// I/O error has occured. - Io(String), - /// Deserialization error has occured. - Serde(String), - /// Key storage error. - KeyStorage(String), - /// Consensus is unreachable. - ConsensusUnreachable, - /// Acl storage error. - AccessDenied, - /// Can't start session, because exclusive session is active. - ExclusiveSessionActive, - /// Can't start exclusive session, because there are other active sessions. - HasActiveSessions, - /// Insufficient requester data. - InsufficientRequesterData(String), -} - -impl From for Error { - fn from(err: ethkey::Error) -> Self { - Error::EthKey(err.into()) - } -} - -impl From for Error { - fn from(err: crypto::Error) -> Self { - Error::EthKey(err.into()) - } -} - -impl From for Error { - fn from(err: IoError) -> Self { - Error::Io(err.to_string()) - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Error::InvalidNodeAddress => write!(f, "invalid node address has been passed"), - Error::InvalidNodeId => write!(f, "invalid node id has been passed"), - Error::DuplicateSessionId => write!(f, "session with the same id is already registered"), - Error::CompletedSessionId => write!(f, "session with the same id is already completed"), - Error::NotStartedSessionId => write!(f, "not enough data to start session with the given id"), - Error::InvalidSessionId => write!(f, "invalid session id has been passed"), - Error::InvalidNodesCount => write!(f, "invalid nodes count"), - Error::InvalidNodesConfiguration => write!(f, "invalid nodes configuration"), - Error::InvalidThreshold => write!(f, "invalid threshold value has been passed"), - Error::TooEarlyForRequest => write!(f, "session is not yet ready to process this request"), - Error::InvalidStateForRequest => write!(f, "session is in invalid state for processing this request"), - Error::InvalidNodeForRequest => write!(f, "invalid node for this request"), - Error::InvalidMessage => write!(f, "invalid message is received"), - Error::InvalidMessageVersion => write!(f, "unsupported message is received"), - Error::ReplayProtection => write!(f, "replay message is received"), - Error::NodeDisconnected => write!(f, "node required for this operation is currently disconnected"), - Error::MissingKeyShare => write!(f, "requested key share version is not found"), - Error::EthKey(ref e) => write!(f, "cryptographic error {}", e), - Error::Io(ref e) => write!(f, "i/o error {}", e), - Error::Serde(ref e) => write!(f, "serde error {}", e), - Error::KeyStorage(ref e) => write!(f, "key storage error {}", e), - Error::ConsensusUnreachable => write!(f, "Consensus unreachable"), - Error::AccessDenied => write!(f, "Access denied"), - Error::ExclusiveSessionActive => write!(f, "Exclusive session active"), - Error::HasActiveSessions => write!(f, "Unable to start exclusive session"), - Error::InsufficientRequesterData(ref e) => write!(f, "Insufficient requester data: {}", e), - } - } -} - -impl Into for Error { - fn into(self) -> String { - format!("{}", self) - } + /// Count of all configured key server nodes (valid at session start time). + pub configured_nodes_count: usize, + /// Count of all connected key server nodes (valid at session start time). + pub connected_nodes_count: usize, } mod admin_sessions; diff --git a/secret_store/src/key_server_set.rs b/secret_store/src/key_server_set.rs index cb324dbc9ba..25651bb4cad 100644 --- a/secret_store/src/key_server_set.rs +++ b/secret_store/src/key_server_set.rs @@ -25,7 +25,7 @@ use ethkey::public_to_address; use hash::keccak; use ethereum_types::{H256, Address}; use bytes::Bytes; -use types::all::{Error, Public, NodeAddress, NodeId}; +use types::{Error, Public, NodeAddress, NodeId}; use trusted_client::TrustedClient; use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED}; use {NodeKeyPair}; diff --git a/secret_store/src/key_storage.rs b/secret_store/src/key_storage.rs index fee73c2ae1a..4f78bc338c2 100644 --- a/secret_store/src/key_storage.rs +++ b/secret_store/src/key_storage.rs @@ -21,7 +21,7 @@ use tiny_keccak::Keccak; use ethereum_types::{H256, Address}; use ethkey::{Secret, Public, public_to_address}; use kvdb::KeyValueDB; -use types::all::{Error, ServerKeyId, NodeId}; +use types::{Error, ServerKeyId, NodeId}; use serialization::{SerializablePublic, SerializableSecret, SerializableH256, SerializableAddress}; /// Key of version value. @@ -419,7 +419,7 @@ pub mod tests { use ethereum_types::{Address, H256}; use ethkey::{Random, Generator, Public, Secret, public_to_address}; use kvdb_rocksdb::Database; - use types::all::{Error, ServerKeyId}; + use types::{Error, ServerKeyId}; use super::{DB_META_KEY_VERSION, CURRENT_VERSION, KeyStorage, PersistentKeyStorage, DocumentKeyShare, DocumentKeyShareVersion, CurrentSerializableDocumentKeyShare, upgrade_db, SerializableDocumentKeyShareV0, SerializableDocumentKeyShareV1, SerializableDocumentKeyShareV2, SerializableDocumentKeyShareVersionV2}; diff --git a/secret_store/src/lib.rs b/secret_store/src/lib.rs index 8e1278e425b..80b15318a9f 100644 --- a/secret_store/src/lib.rs +++ b/secret_store/src/lib.rs @@ -76,7 +76,7 @@ use ethcore::client::Client; use ethcore::miner::Miner; use sync::SyncProvider; -pub use types::all::{ServerKeyId, EncryptedDocumentKey, RequestSignature, Public, +pub use types::{ServerKeyId, EncryptedDocumentKey, RequestSignature, Public, Error, NodeAddress, ContractAddress, ServiceConfiguration, ClusterConfiguration}; pub use traits::{NodeKeyPair, KeyServer}; pub use self::node_key_pair::{PlainNodeKeyPair, KeyStoreNodeKeyPair}; diff --git a/secret_store/src/listener/http_listener.rs b/secret_store/src/listener/http_listener.rs index bf293a44eb4..074052fae47 100644 --- a/secret_store/src/listener/http_listener.rs +++ b/secret_store/src/listener/http_listener.rs @@ -29,7 +29,7 @@ use url::percent_encoding::percent_decode; use traits::KeyServer; use serialization::{SerializableEncryptedDocumentKeyShadow, SerializableBytes, SerializablePublic}; -use types::all::{Error, Public, MessageHash, NodeAddress, RequestSignature, ServerKeyId, +use types::{Error, Public, MessageHash, NodeAddress, RequestSignature, ServerKeyId, EncryptedDocumentKey, EncryptedDocumentKeyShadow, NodeId}; /// Key server http-requests listener. Available requests: @@ -271,15 +271,16 @@ fn return_bytes(req_uri: &Uri, result: Result, Error>) - } fn return_error(err: Error) -> HttpResponse { - let mut res = match err { - Error::InsufficientRequesterData(_) => HttpResponse::new().with_status(HttpStatusCode::BadRequest), - Error::AccessDenied => HttpResponse::new().with_status(HttpStatusCode::Forbidden), - Error::DocumentNotFound => HttpResponse::new().with_status(HttpStatusCode::NotFound), - Error::Hyper(_) => HttpResponse::new().with_status(HttpStatusCode::BadRequest), - Error::Serde(_) => HttpResponse::new().with_status(HttpStatusCode::BadRequest), - Error::Database(_) => HttpResponse::new().with_status(HttpStatusCode::InternalServerError), - Error::Internal(_) => HttpResponse::new().with_status(HttpStatusCode::InternalServerError), - }; + let mut res = HttpResponse::new().with_status(match err { + Error::AccessDenied | Error::ConsensusUnreachable | Error::ConsensusTemporaryUnreachable => + HttpStatusCode::Forbidden, + Error::ServerKeyIsNotFound | Error::DocumentKeyIsNotFound => + HttpStatusCode::NotFound, + Error::InsufficientRequesterData(_) | Error::Hyper(_) | Error::Serde(_) + | Error::DocumentKeyAlreadyStored | Error::ServerKeyAlreadyGenerated => + HttpStatusCode::BadRequest, + _ => HttpStatusCode::InternalServerError, + }); // return error text. ignore errors when returning error let error_text = format!("\"{}\"", err); @@ -377,7 +378,7 @@ mod tests { use ethkey::Public; use traits::KeyServer; use key_server::tests::DummyKeyServer; - use types::all::NodeAddress; + use types::NodeAddress; use super::{parse_request, Request, KeyServerHttpListener}; #[test] diff --git a/secret_store/src/listener/mod.rs b/secret_store/src/listener/mod.rs index 2c4fbaf4cb7..0d1f3f26753 100644 --- a/secret_store/src/listener/mod.rs +++ b/secret_store/src/listener/mod.rs @@ -23,7 +23,7 @@ mod tasks_queue; use std::collections::BTreeSet; use std::sync::Arc; use traits::{ServerKeyGenerator, DocumentKeyServer, MessageSigner, AdminSessionsServer, KeyServer}; -use types::all::{Error, Public, MessageHash, EncryptedMessageSignature, RequestSignature, ServerKeyId, +use types::{Error, Public, MessageHash, EncryptedMessageSignature, RequestSignature, ServerKeyId, EncryptedDocumentKey, EncryptedDocumentKeyShadow, NodeId, Requester}; /// Available API mask. diff --git a/secret_store/src/listener/service_contract_listener.rs b/secret_store/src/listener/service_contract_listener.rs index 1e17be8e557..0e273b3eeee 100644 --- a/secret_store/src/listener/service_contract_listener.rs +++ b/secret_store/src/listener/service_contract_listener.rs @@ -315,7 +315,7 @@ impl ServiceContractListener { Ok(Some(server_key)) => { data.contract.publish_generated_server_key(&origin, server_key_id, server_key) }, - Err(ref error) if is_internal_error(error) => Err(format!("{}", error)), + Err(ref error) if error.is_non_fatal() => Err(format!("{}", error)), Err(ref error) => { // ignore error as we're already processing an error let _ = data.contract.publish_server_key_generation_error(&origin, server_key_id) @@ -335,7 +335,7 @@ impl ServiceContractListener { Ok(None) => { data.contract.publish_server_key_retrieval_error(&origin, server_key_id) } - Err(ref error) if is_internal_error(error) => Err(format!("{}", error)), + Err(ref error) if error.is_non_fatal() => Err(format!("{}", error)), Err(ref error) => { // ignore error as we're already processing an error let _ = data.contract.publish_server_key_retrieval_error(&origin, server_key_id) @@ -349,7 +349,7 @@ impl ServiceContractListener { /// Store document key. fn store_document_key(data: &Arc, origin: Address, server_key_id: &ServerKeyId, author: &Address, common_point: &Public, encrypted_point: &Public) -> Result<(), String> { let store_result = data.key_storage.get(server_key_id) - .and_then(|key_share| key_share.ok_or(Error::DocumentNotFound)) + .and_then(|key_share| key_share.ok_or(Error::ServerKeyIsNotFound)) .and_then(|key_share| check_encrypted_data(Some(&key_share)).map(|_| key_share).map_err(Into::into)) .and_then(|key_share| update_encrypted_data(&data.key_storage, server_key_id.clone(), key_share, author.clone(), common_point.clone(), encrypted_point.clone()).map_err(Into::into)); @@ -357,7 +357,7 @@ impl ServiceContractListener { Ok(()) => { data.contract.publish_stored_document_key(&origin, server_key_id) }, - Err(ref error) if is_internal_error(&error) => Err(format!("{}", error)), + Err(ref error) if error.is_non_fatal() => Err(format!("{}", error)), Err(ref error) => { // ignore error as we're already processing an error let _ = data.contract.publish_document_key_store_error(&origin, server_key_id) @@ -372,17 +372,16 @@ impl ServiceContractListener { fn retrieve_document_key_common(data: &Arc, origin: Address, server_key_id: &ServerKeyId, requester: &Address) -> Result<(), String> { let retrieval_result = data.acl_storage.check(requester.clone(), server_key_id) .and_then(|is_allowed| if !is_allowed { Err(Error::AccessDenied) } else { Ok(()) }) - .and_then(|_| data.key_storage.get(server_key_id).and_then(|key_share| key_share.ok_or(Error::DocumentNotFound))) + .and_then(|_| data.key_storage.get(server_key_id).and_then(|key_share| key_share.ok_or(Error::ServerKeyIsNotFound))) .and_then(|key_share| key_share.common_point - .ok_or(Error::DocumentNotFound) - .and_then(|common_point| math::make_common_shadow_point(key_share.threshold, common_point) - .map_err(|e| Error::Internal(e.into()))) + .ok_or(Error::DocumentKeyIsNotFound) + .and_then(|common_point| math::make_common_shadow_point(key_share.threshold, common_point)) .map(|common_point| (common_point, key_share.threshold))); match retrieval_result { Ok((common_point, threshold)) => { data.contract.publish_retrieved_document_key_common(&origin, server_key_id, requester, common_point, threshold) }, - Err(ref error) if is_internal_error(&error) => Err(format!("{}", error)), + Err(ref error) if error.is_non_fatal() => Err(format!("{}", error)), Err(ref error) => { // ignore error as we're already processing an error let _ = data.contract.publish_document_key_retrieval_error(&origin, server_key_id, requester) @@ -406,7 +405,7 @@ impl ServiceContractListener { Ok(Some((participants, decrypted_secret, shadow))) => { data.contract.publish_retrieved_document_key_personal(&origin, server_key_id, &requester, &participants, decrypted_secret, shadow) }, - Err(ref error) if is_internal_error(error) => Err(format!("{}", error)), + Err(ref error) if error.is_non_fatal() => Err(format!("{}", error)), Err(ref error) => { // ignore error as we're already processing an error let _ = data.contract.publish_document_key_retrieval_error(&origin, server_key_id, &requester) @@ -511,15 +510,6 @@ impl ::std::fmt::Display for ServiceTask { } } -/// Is internal error? Internal error means that it is SS who's responsible for it, like: connectivity, db failure, ... -/// External error is caused by SS misuse, like: trying to generate duplicated key, access denied, ... -/// When internal error occurs, we just ignore request for now and will retry later. -/// When external error occurs, we reject request. -fn is_internal_error(_error: &Error) -> bool { - // TODO [Reliability]: implement me after proper is passed through network - false -} - /// Log service task result. fn log_service_task_result(task: &ServiceTask, self_id: &Public, result: Result<(), String>) -> Result<(), String> { match result { diff --git a/secret_store/src/serialization.rs b/secret_store/src/serialization.rs index 95f67909677..42209e0de4a 100644 --- a/secret_store/src/serialization.rs +++ b/secret_store/src/serialization.rs @@ -22,7 +22,7 @@ use serde::de::{Visitor, Error as SerdeError}; use ethkey::{Public, Secret, Signature}; use ethereum_types::{H160, H256}; use bytes::Bytes; -use types::all::Requester; +use types::Requester; macro_rules! impl_bytes_deserialize { ($name: ident, $value: expr, true) => { diff --git a/secret_store/src/traits.rs b/secret_store/src/traits.rs index ea09a3d9067..04f2fa1294e 100644 --- a/secret_store/src/traits.rs +++ b/secret_store/src/traits.rs @@ -17,7 +17,7 @@ use std::collections::BTreeSet; use ethkey::{KeyPair, Signature, Error as EthKeyError}; use ethereum_types::{H256, Address}; -use types::all::{Error, Public, ServerKeyId, MessageHash, EncryptedMessageSignature, RequestSignature, Requester, +use types::{Error, Public, ServerKeyId, MessageHash, EncryptedMessageSignature, RequestSignature, Requester, EncryptedDocumentKey, EncryptedDocumentKeyShadow, NodeId}; /// Node key pair. diff --git a/secret_store/src/types/all.rs b/secret_store/src/types/all.rs index b9940268144..bfc58779a6b 100644 --- a/secret_store/src/types/all.rs +++ b/secret_store/src/types/all.rs @@ -14,13 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::fmt; -use std::io; -use std::net; use std::collections::BTreeMap; -use serde_json; -use {ethkey, kvdb, bytes, ethereum_types, key_server_cluster}; +use {ethkey, bytes, ethereum_types}; /// Node id. pub type NodeId = ethkey::Public; @@ -37,25 +33,6 @@ pub type RequestSignature = ethkey::Signature; /// Public key type. pub use ethkey::Public; -/// Secret store error -#[derive(Debug, PartialEq)] -pub enum Error { - /// Insufficient requester data - InsufficientRequesterData(String), - /// Access to resource is denied - AccessDenied, - /// Requested document not found - DocumentNotFound, - /// Hyper error - Hyper(String), - /// Serialization/deserialization error - Serde(String), - /// Database-related error - Database(String), - /// Internal error - Internal(String), -} - /// Secret store configuration #[derive(Debug, Clone)] pub struct NodeAddress { @@ -136,69 +113,6 @@ pub enum Requester { Address(ethereum_types::Address), } -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Error::InsufficientRequesterData(ref e) => write!(f, "Insufficient requester data: {}", e), - Error::AccessDenied => write!(f, "Access dened"), - Error::DocumentNotFound => write!(f, "Document not found"), - Error::Hyper(ref msg) => write!(f, "Hyper error: {}", msg), - Error::Serde(ref msg) => write!(f, "Serialization error: {}", msg), - Error::Database(ref msg) => write!(f, "Database error: {}", msg), - Error::Internal(ref msg) => write!(f, "Internal error: {}", msg), - } - } -} - -impl From for Error { - fn from(err: serde_json::Error) -> Self { - Error::Serde(err.to_string()) - } -} - -impl From for Error { - fn from(err: ethkey::Error) -> Self { - Error::Internal(err.into()) - } -} - -impl From for Error { - fn from(err: io::Error) -> Error { - Error::Internal(err.to_string()) - } -} - -impl From for Error { - fn from(err: net::AddrParseError) -> Error { - Error::Internal(err.to_string()) - } -} - -impl From for Error { - fn from(err: kvdb::Error) -> Self { - Error::Database(err.to_string()) - } -} - -impl From for Error { - fn from(err: key_server_cluster::Error) -> Self { - match err { - key_server_cluster::Error::InsufficientRequesterData(err) - => Error::InsufficientRequesterData(err), - key_server_cluster::Error::ConsensusUnreachable - | key_server_cluster::Error::AccessDenied => Error::AccessDenied, - key_server_cluster::Error::MissingKeyShare => Error::DocumentNotFound, - _ => Error::Internal(err.into()), - } - } -} - -impl Into for Error { - fn into(self) -> String { - format!("{}", self) - } -} - impl Default for Requester { fn default() -> Self { Requester::Signature(Default::default()) diff --git a/secret_store/src/types/error.rs b/secret_store/src/types/error.rs new file mode 100644 index 00000000000..6469585facb --- /dev/null +++ b/secret_store/src/types/error.rs @@ -0,0 +1,199 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use std::fmt; +use std::net; +use std::io::Error as IoError; + +use {ethkey, crypto, kvdb}; + +/// Secret store error. +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum Error { + /// Invalid node address has been passed. + InvalidNodeAddress, + /// Invalid node id has been passed. + InvalidNodeId, + /// Session with the given id already exists. + DuplicateSessionId, + /// No active session with given id. + NoActiveSessionWithId, + /// Invalid threshold value has been passed. + /// Threshold value must be in [0; n - 1], where n is a number of nodes participating in the encryption. + NotEnoughNodesForThreshold, + /// Current state of encryption/decryption session does not allow to proceed request. + /// Reschedule this request for later processing. + TooEarlyForRequest, + /// Current state of encryption/decryption session does not allow to proceed request. + /// This means that either there is some comm-failure or node is misbehaving/cheating. + InvalidStateForRequest, + /// Request cannot be sent/received from this node. + InvalidNodeForRequest, + /// Message or some data in the message was recognized as invalid. + /// This means that node is misbehaving/cheating. + InvalidMessage, + /// Message version is not supported. + InvalidMessageVersion, + /// Message is invalid because of replay-attack protection. + ReplayProtection, + /// Connection to node, required for this session is not established. + NodeDisconnected, + /// Server key with this ID is already generated. + ServerKeyAlreadyGenerated, + /// Server key with this ID is not yet generated. + ServerKeyIsNotFound, + /// Document key with this ID is already stored. + DocumentKeyAlreadyStored, + /// Document key with this ID is not yet stored. + DocumentKeyIsNotFound, + /// Consensus is temporary unreachable. Means that something is currently blocking us from either forming + /// consensus group (like disconnecting from too many nodes, which are AGREE to partticipate in consensus) + /// or from rejecting request (disconnecting from AccessDenied-nodes). + ConsensusTemporaryUnreachable, + /// Consensus is unreachable. It doesn't mean that it will ALWAYS remain unreachable, but right NOW we have + /// enough nodes confirmed that they do not want to be a part of consensus. Example: we're connected to 10 + /// of 100 nodes. Key threshold is 6 (i.e. 7 nodes are required for consensus). 4 nodes are responding with + /// reject => consensus is considered unreachable, even though another 90 nodes still can respond with OK. + ConsensusUnreachable, + /// Acl storage error. + AccessDenied, + /// Can't start session, because exclusive session is active. + ExclusiveSessionActive, + /// Can't start exclusive session, because there are other active sessions. + HasActiveSessions, + /// Insufficient requester data. + InsufficientRequesterData(String), + /// Cryptographic error. + EthKey(String), + /// I/O error has occured. + Io(String), + /// Deserialization error has occured. + Serde(String), + /// Hyper error. + Hyper(String), + /// Database-related error. + Database(String), + /// Internal error. + Internal(String), +} + +impl Error { + /// Is this a fatal error? Non-fatal means that it is possible to replay the same request with a non-zero + /// chance to success. I.e. the error is not about request itself (or current environment factors that + /// are affecting request processing), but about current SecretStore state. + pub fn is_non_fatal(&self) -> bool { + match *self { + // non-fatal errors: + + // session start errors => restarting session is a solution + Error::DuplicateSessionId | Error::NoActiveSessionWithId | + // unexpected message errors => restarting session/excluding node is a solution + Error::TooEarlyForRequest | Error::InvalidStateForRequest | Error::InvalidNodeForRequest | + // invalid message errors => restarting/updating/excluding node is a solution + Error::InvalidMessage | Error::InvalidMessageVersion | Error::ReplayProtection | + // connectivity problems => waiting for reconnect && restarting session is a solution + Error::NodeDisconnected | + // temporary (?) consensus problems, related to other non-fatal errors => restarting is probably (!) a solution + Error::ConsensusTemporaryUnreachable | + // exclusive session errors => waiting && restarting is a solution + Error::ExclusiveSessionActive | Error::HasActiveSessions => true, + + // fatal errors: + + // config-related errors + Error::InvalidNodeAddress | Error::InvalidNodeId | + // wrong session input params errors + Error::NotEnoughNodesForThreshold | Error::ServerKeyAlreadyGenerated | Error::ServerKeyIsNotFound | + Error::DocumentKeyAlreadyStored | Error::DocumentKeyIsNotFound | Error::InsufficientRequesterData(_) | + // access denied/consensus error + Error::AccessDenied | Error::ConsensusUnreachable | + // indeterminate internal errors, which could be either fatal (db failure, invalid request), or not (network error), + // but we still consider these errors as fatal + Error::EthKey(_) | Error::Serde(_) | Error::Hyper(_) | Error::Database(_) | Error::Internal(_) | Error::Io(_) => false, + } + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Error::InvalidNodeAddress => write!(f, "invalid node address has been passed"), + Error::InvalidNodeId => write!(f, "invalid node id has been passed"), + Error::DuplicateSessionId => write!(f, "session with the same id is already registered"), + Error::NoActiveSessionWithId => write!(f, "no active session with given id"), + Error::NotEnoughNodesForThreshold => write!(f, "not enough nodes for passed threshold"), + Error::TooEarlyForRequest => write!(f, "session is not yet ready to process this request"), + Error::InvalidStateForRequest => write!(f, "session is in invalid state for processing this request"), + Error::InvalidNodeForRequest => write!(f, "invalid node for this request"), + Error::InvalidMessage => write!(f, "invalid message is received"), + Error::InvalidMessageVersion => write!(f, "unsupported message is received"), + Error::ReplayProtection => write!(f, "replay message is received"), + Error::NodeDisconnected => write!(f, "node required for this operation is currently disconnected"), + Error::ServerKeyAlreadyGenerated => write!(f, "Server key with this ID is already generated"), + Error::ServerKeyIsNotFound => write!(f, "Server key with this ID is not found"), + Error::DocumentKeyAlreadyStored => write!(f, "Document key with this ID is already stored"), + Error::DocumentKeyIsNotFound => write!(f, "Document key with this ID is not found"), + Error::ConsensusUnreachable => write!(f, "Consensus unreachable"), + Error::ConsensusTemporaryUnreachable => write!(f, "Consensus temporary unreachable"), + Error::AccessDenied => write!(f, "Access dened"), + Error::ExclusiveSessionActive => write!(f, "Exclusive session active"), + Error::HasActiveSessions => write!(f, "Unable to start exclusive session"), + Error::InsufficientRequesterData(ref e) => write!(f, "Insufficient requester data: {}", e), + Error::EthKey(ref e) => write!(f, "cryptographic error {}", e), + Error::Hyper(ref msg) => write!(f, "Hyper error: {}", msg), + Error::Serde(ref msg) => write!(f, "Serialization error: {}", msg), + Error::Database(ref msg) => write!(f, "Database error: {}", msg), + Error::Internal(ref msg) => write!(f, "Internal error: {}", msg), + Error::Io(ref msg) => write!(f, "IO error: {}", msg), + } + } +} + +impl From for Error { + fn from(err: ethkey::Error) -> Self { + Error::EthKey(err.into()) + } +} + +impl From for Error { + fn from(err: kvdb::Error) -> Self { + Error::Database(err.to_string()) + } +} + +impl From for Error { + fn from(err: crypto::Error) -> Self { + Error::EthKey(err.into()) + } +} + +impl From for Error { + fn from(err: IoError) -> Self { + Error::Io(err.to_string()) + } +} + +impl Into for Error { + fn into(self) -> String { + format!("{}", self) + } +} + +impl From for Error { + fn from(err: net::AddrParseError) -> Error { + Error::Internal(err.to_string()) + } +} diff --git a/secret_store/src/types/mod.rs b/secret_store/src/types/mod.rs index dc5bd3d8a08..9da7f6ef985 100644 --- a/secret_store/src/types/mod.rs +++ b/secret_store/src/types/mod.rs @@ -16,4 +16,8 @@ //! Types used in the public api -pub mod all; +mod all; +mod error; + +pub use self::all::*; +pub use self::error::*; From 10a346476a4135dd979379cc3c2529e9080ecda4 Mon Sep 17 00:00:00 2001 From: ellaismer <31844524+ellaismer@users.noreply.github.com> Date: Tue, 1 May 2018 14:41:46 -0400 Subject: [PATCH 28/95] Enable WebAssembly and Byzantium for Ellaism (#8520) * Enable WebAssembly and Byzantium for Ellaism * Fix indentation * Remove empty lines --- ethcore/res/ethereum/ellaism.json | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ethcore/res/ethereum/ellaism.json b/ethcore/res/ethereum/ellaism.json index 3650e68df52..96c2016e55a 100644 --- a/ethcore/res/ethereum/ellaism.json +++ b/ethcore/res/ethereum/ellaism.json @@ -13,9 +13,9 @@ "eip150Transition": "0x0", "eip160Transition": "0x0", "ecip1017EraRounds": 10000000, - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "eip161dTransition": "0x7fffffffffffffff", + "eip100bTransition": 2000000 } } }, @@ -29,7 +29,12 @@ "chainID": "0x40", "eip155Transition": "0x0", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip86Transition": "0x7fffffffffffff", + "wasmActivationTransition": 2000000, + "eip140Transition": 2000000, + "eip211Transition": 2000000, + "eip214Transition": 2000000, + "eip658Transition": 2000000 }, "genesis": { "seal": { @@ -60,6 +65,10 @@ "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 2000000, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 2000000, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 2000000, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 2000000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } } } From 629da8f8bf39da2e3a32f178954604a89de898d1 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Wed, 2 May 2018 09:20:59 +0200 Subject: [PATCH 29/95] More changes for Android (#8421) --- .gitlab-ci.yml | 17 +++++++++++++++++ Cargo.lock | 22 +++++++++++----------- docker/android/Dockerfile | 2 ++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2c216496f67..347b5a57ba4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -180,6 +180,23 @@ windows: paths: - parity.zip name: "x86_64-pc-windows-msvc_parity" +android-armv7: + stage: build + image: parity/parity-android:latest + only: + - beta + - tags + - stable + - triggers + script: + - cargo build --target=armv7-linux-androideabi + # TODO: check that `arm-linux-androideabi-objdump -x ./target/armv7-linux-androideabi/release/parity | grep c++_shared` is empty + tags: + - rust-arm + artifacts: + paths: + - parity.zip + name: "armv7-linux-androideabi_parity" docker-build: stage: build only: diff --git a/Cargo.lock b/Cargo.lock index 3176c3ab3d7..741cc3832ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,7 +70,7 @@ name = "backtrace-sys" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -184,7 +184,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -432,7 +432,7 @@ version = "0.5.7" source = "git+https://github.com/paritytech/rust-secp256k1#db81cfea59014b4d176f10f86ed52e1a130b6822" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1203,7 +1203,7 @@ name = "hidapi" version = "0.3.1" source = "git+https://github.com/paritytech/hidapi-rs#70ec4bd1b755ec5dd32ad2be0c8345864147c8bc" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1436,7 +1436,7 @@ dependencies = [ name = "keccak-hash" version = "0.1.0" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1524,7 +1524,7 @@ name = "libusb-sys" version = "0.2.4" source = "git+https://github.com/paritytech/libusb-sys#14bdb698003731b6344a79e1d814704e44363e7c" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1678,7 +1678,7 @@ name = "miniz_oxide_c_api" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2723,7 +2723,7 @@ name = "ring" version = "0.12.1" source = "git+https://github.com/paritytech/ring#b98d7f586c0467d68e9946a5f47b4a04b9a86b4a" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2774,7 +2774,7 @@ name = "rocksdb-sys" version = "0.3.0" source = "git+https://github.com/paritytech/rust-rocksdb#ecf06adf3148ab10f6f7686b724498382ff4f36e" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)", @@ -3010,7 +3010,7 @@ name = "snappy-sys" version = "0.1.0" source = "git+https://github.com/paritytech/rust-snappy#40ac9a0d9fd613e7f38df800a11a589b7296da73" dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3782,7 +3782,7 @@ dependencies = [ "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" "checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9" -"checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc" +"checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum cid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d85ee025368e69063c420cbb2ed9f852cb03a5e69b73be021e65726ce03585b6" "checksum clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8f4a2b3bb7ef3c672d7c13d15613211d5a6976b6892c598b0fcb5d40765f19c2" diff --git a/docker/android/Dockerfile b/docker/android/Dockerfile index 5769cd13bc8..7783781b4ca 100644 --- a/docker/android/Dockerfile +++ b/docker/android/Dockerfile @@ -75,3 +75,5 @@ ENV CFLAGS_arm_linux_androideabi -std=gnu11 -fPIC -D OS_ANDROID ENV CFLAGS_armv7_linux_androideabi -std=gnu11 -fPIC -D OS_ANDROID ENV CXXFLAGS_arm_linux_androideabi -std=gnu++11 -fPIC -fexceptions -frtti -static-libstdc++ -D OS_ANDROID ENV CXXFLAGS_armv7_linux_androideabi -std=gnu++11 -fPIC -fexceptions -frtti -static-libstdc++ -D OS_ANDROID +ENV CXXSTDLIB_arm_linux_androideabi "" +ENV CXXSTDLIB_armv7_linux_androideabi "" From 8e8679807dbb8df6456172fdfa1396b7f091d267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 2 May 2018 09:31:06 +0200 Subject: [PATCH 30/95] Transaction Pool improvements (#8470) * Don't use ethereum_types in transaction pool. * Hide internal insertion_id. * Fix tests. * Review grumbles. --- miner/src/pool/mod.rs | 13 ++- miner/src/pool/queue.rs | 4 +- miner/src/pool/ready.rs | 12 +-- miner/src/pool/scoring.rs | 11 ++- transaction-pool/Cargo.toml | 2 + transaction-pool/src/error.rs | 16 ++-- transaction-pool/src/lib.rs | 23 +++-- transaction-pool/src/pool.rs | 113 +++++++++++++++-------- transaction-pool/src/ready.rs | 4 +- transaction-pool/src/scoring.rs | 34 ++++--- transaction-pool/src/tests/helpers.rs | 10 +- transaction-pool/src/tests/mod.rs | 13 +-- transaction-pool/src/tests/tx_builder.rs | 10 -- transaction-pool/src/transactions.rs | 46 +++++---- 14 files changed, 173 insertions(+), 138 deletions(-) diff --git a/miner/src/pool/mod.rs b/miner/src/pool/mod.rs index 7950510c6d0..45d28f3c121 100644 --- a/miner/src/pool/mod.rs +++ b/miner/src/pool/mod.rs @@ -105,6 +105,11 @@ impl VerifiedTransaction { self.priority } + /// Gets transaction insertion id. + pub(crate) fn insertion_id(&self) -> usize { + self.insertion_id + } + /// Gets wrapped `SignedTransaction` pub fn signed(&self) -> &transaction::SignedTransaction { &self.transaction @@ -114,9 +119,13 @@ impl VerifiedTransaction { pub fn pending(&self) -> &transaction::PendingTransaction { &self.transaction } + } impl txpool::VerifiedTransaction for VerifiedTransaction { + type Hash = H256; + type Sender = Address; + fn hash(&self) -> &H256 { &self.hash } @@ -128,8 +137,4 @@ impl txpool::VerifiedTransaction for VerifiedTransaction { fn sender(&self) -> &Address { &self.sender } - - fn insertion_id(&self) -> u64 { - self.insertion_id as u64 - } } diff --git a/miner/src/pool/queue.rs b/miner/src/pool/queue.rs index edc092a119f..8cf4534b763 100644 --- a/miner/src/pool/queue.rs +++ b/miner/src/pool/queue.rs @@ -282,11 +282,11 @@ impl TransactionQueue { // We want to clear stale transactions from the queue as well. // (Transactions that are occuping the queue for a long time without being included) let stale_id = { - let current_id = self.insertion_id.load(atomic::Ordering::Relaxed) as u64; + let current_id = self.insertion_id.load(atomic::Ordering::Relaxed); // wait at least for half of the queue to be replaced let gap = self.pool.read().options().max_count / 2; // but never less than 100 transactions - let gap = cmp::max(100, gap) as u64; + let gap = cmp::max(100, gap); current_id.checked_sub(gap) }; diff --git a/miner/src/pool/ready.rs b/miner/src/pool/ready.rs index 54b5aec3a9f..c2829b34a9a 100644 --- a/miner/src/pool/ready.rs +++ b/miner/src/pool/ready.rs @@ -54,14 +54,14 @@ pub struct State { nonces: HashMap, state: C, max_nonce: Option, - stale_id: Option, + stale_id: Option, } impl State { /// Create new State checker, given client interface. pub fn new( state: C, - stale_id: Option, + stale_id: Option, max_nonce: Option, ) -> Self { State { @@ -91,10 +91,10 @@ impl txpool::Ready for State { match tx.transaction.nonce.cmp(nonce) { // Before marking as future check for stale ids cmp::Ordering::Greater => match self.stale_id { - Some(id) if tx.insertion_id() < id => txpool::Readiness::Stalled, + Some(id) if tx.insertion_id() < id => txpool::Readiness::Stale, _ => txpool::Readiness::Future, }, - cmp::Ordering::Less => txpool::Readiness::Stalled, + cmp::Ordering::Less => txpool::Readiness::Stale, cmp::Ordering::Equal => { *nonce = *nonce + 1.into(); txpool::Readiness::Ready @@ -178,7 +178,7 @@ mod tests { let res = State::new(TestClient::new().with_nonce(125), None, None).is_ready(&tx); // then - assert_eq!(res, txpool::Readiness::Stalled); + assert_eq!(res, txpool::Readiness::Stale); } #[test] @@ -190,7 +190,7 @@ mod tests { let res = State::new(TestClient::new(), Some(1), None).is_ready(&tx); // then - assert_eq!(res, txpool::Readiness::Stalled); + assert_eq!(res, txpool::Readiness::Stale); } #[test] diff --git a/miner/src/pool/scoring.rs b/miner/src/pool/scoring.rs index b9f074ecb0f..eaf06983328 100644 --- a/miner/src/pool/scoring.rs +++ b/miner/src/pool/scoring.rs @@ -28,7 +28,6 @@ //! from our local node (own transactions). use std::cmp; -use std::sync::Arc; use ethereum_types::U256; use txpool; @@ -69,7 +68,7 @@ impl txpool::Scoring for NonceAndGasPrice { } } - fn update_scores(&self, txs: &[Arc], scores: &mut [U256], change: txpool::scoring::Change) { + fn update_scores(&self, txs: &[txpool::Transaction], scores: &mut [U256], change: txpool::scoring::Change) { use self::txpool::scoring::Change; match change { @@ -79,7 +78,7 @@ impl txpool::Scoring for NonceAndGasPrice { assert!(i < txs.len()); assert!(i < scores.len()); - scores[i] = txs[i].transaction.gas_price; + scores[i] = txs[i].transaction.transaction.gas_price; let boost = match txs[i].priority() { super::Priority::Local => 15, super::Priority::Retracted => 10, @@ -116,6 +115,7 @@ impl txpool::Scoring for NonceAndGasPrice { mod tests { use super::*; + use std::sync::Arc; use pool::tests::tx::{Tx, TxExt}; use txpool::Scoring; @@ -131,7 +131,10 @@ mod tests { 1 => ::pool::Priority::Retracted, _ => ::pool::Priority::Regular, }; - Arc::new(verified) + txpool::Transaction { + insertion_id: 0, + transaction: Arc::new(verified), + } }).collect::>(); let initial_scores = vec![U256::from(0), 0.into(), 0.into()]; diff --git a/transaction-pool/Cargo.toml b/transaction-pool/Cargo.toml index b8630781123..342c376f63c 100644 --- a/transaction-pool/Cargo.toml +++ b/transaction-pool/Cargo.toml @@ -10,4 +10,6 @@ error-chain = "0.11" log = "0.3" smallvec = "0.4" trace-time = { path = "../util/trace-time" } + +[dev-dependencies] ethereum-types = "0.3" diff --git a/transaction-pool/src/error.rs b/transaction-pool/src/error.rs index 2e8ac739897..4cf221a71e4 100644 --- a/transaction-pool/src/error.rs +++ b/transaction-pool/src/error.rs @@ -14,24 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethereum_types::H256; +/// Error chain doesn't let us have generic types. +/// So the hashes are converted to debug strings for easy display. +type Hash = String; error_chain! { errors { /// Transaction is already imported - AlreadyImported(hash: H256) { + AlreadyImported(hash: Hash) { description("transaction is already in the pool"), - display("[{:?}] already imported", hash) + display("[{}] already imported", hash) } /// Transaction is too cheap to enter the queue - TooCheapToEnter(hash: H256, min_score: String) { + TooCheapToEnter(hash: Hash, min_score: String) { description("the pool is full and transaction is too cheap to replace any transaction"), - display("[{:?}] too cheap to enter the pool. Min score: {}", hash, min_score) + display("[{}] too cheap to enter the pool. Min score: {}", hash, min_score) } /// Transaction is too cheap to replace existing transaction that occupies the same slot. - TooCheapToReplace(old_hash: H256, hash: H256) { + TooCheapToReplace(old_hash: Hash, hash: Hash) { description("transaction is too cheap to replace existing transaction in the pool"), - display("[{:?}] too cheap to replace: {:?}", hash, old_hash) + display("[{}] too cheap to replace: {}", hash, old_hash) } } } diff --git a/transaction-pool/src/lib.rs b/transaction-pool/src/lib.rs index 33d17f4b0fc..4a1bdcde142 100644 --- a/transaction-pool/src/lib.rs +++ b/transaction-pool/src/lib.rs @@ -69,14 +69,15 @@ #![warn(missing_docs)] extern crate smallvec; -extern crate ethereum_types; +extern crate trace_time; #[macro_use] extern crate error_chain; #[macro_use] extern crate log; -extern crate trace_time; +#[cfg(test)] +extern crate ethereum_types; #[cfg(test)] mod tests; @@ -95,27 +96,29 @@ pub mod scoring; pub use self::error::{Error, ErrorKind}; pub use self::listener::{Listener, NoopListener}; pub use self::options::Options; -pub use self::pool::{Pool, PendingIterator}; +pub use self::pool::{Pool, PendingIterator, Transaction}; pub use self::ready::{Ready, Readiness}; pub use self::scoring::Scoring; pub use self::status::{LightStatus, Status}; pub use self::verifier::Verifier; use std::fmt; - -use ethereum_types::{H256, Address}; +use std::hash::Hash; /// Already verified transaction that can be safely queued. pub trait VerifiedTransaction: fmt::Debug { + /// Transaction hash type. + type Hash: fmt::Debug + fmt::LowerHex + Eq + Clone + Hash; + + /// Transaction sender type. + type Sender: fmt::Debug + Eq + Clone + Hash; + /// Transaction hash - fn hash(&self) -> &H256; + fn hash(&self) -> &Self::Hash; /// Memory usage fn mem_usage(&self) -> usize; /// Transaction sender - fn sender(&self) -> &Address; - - /// Unique index of insertion (lower = older). - fn insertion_id(&self) -> u64; + fn sender(&self) -> &Self::Sender; } diff --git a/transaction-pool/src/pool.rs b/transaction-pool/src/pool.rs index fa28cdcdfe5..5cb6e479b8e 100644 --- a/transaction-pool/src/pool.rs +++ b/transaction-pool/src/pool.rs @@ -17,8 +17,6 @@ use std::sync::Arc; use std::collections::{HashMap, BTreeSet}; -use ethereum_types::{H160, H256}; - use error; use listener::{Listener, NoopListener}; use options::Options; @@ -29,21 +27,51 @@ use transactions::{AddResult, Transactions}; use {VerifiedTransaction}; -type Sender = H160; +/// Internal representation of transaction. +/// +/// Includes unique insertion id that can be used for scoring explictly, +/// but internally is used to resolve conflicts in case of equal scoring +/// (newer transactionsa are preferred). +#[derive(Debug)] +pub struct Transaction { + /// Sequential id of the transaction + pub insertion_id: u64, + /// Shared transaction + pub transaction: Arc, +} + +impl Clone for Transaction { + fn clone(&self) -> Self { + Transaction { + insertion_id: self.insertion_id, + transaction: self.transaction.clone(), + } + } +} + +impl ::std::ops::Deref for Transaction { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.transaction + } +} /// A transaction pool. #[derive(Debug)] -pub struct Pool, L = NoopListener> { +pub struct Pool, L = NoopListener> { listener: L, scoring: S, options: Options, mem_usage: usize, - transactions: HashMap>, - by_hash: HashMap>, + transactions: HashMap>, + by_hash: HashMap>, best_transactions: BTreeSet>, worst_transactions: BTreeSet>, + + insertion_id: u64, } impl + Default> Default for Pool { @@ -89,6 +117,7 @@ impl Pool where by_hash, best_transactions: Default::default(), worst_transactions: Default::default(), + insertion_id: 0, } } @@ -104,10 +133,16 @@ impl Pool where /// If any limit is reached the transaction with the lowest `Score` is evicted to make room. /// /// The `Listener` will be informed on any drops or rejections. - pub fn import(&mut self, mut transaction: T) -> error::Result> { + pub fn import(&mut self, transaction: T) -> error::Result> { let mem_usage = transaction.mem_usage(); - ensure!(!self.by_hash.contains_key(transaction.hash()), error::ErrorKind::AlreadyImported(*transaction.hash())); + ensure!(!self.by_hash.contains_key(transaction.hash()), error::ErrorKind::AlreadyImported(format!("{:?}", transaction.hash()))); + + self.insertion_id += 1; + let mut transaction = Transaction { + insertion_id: self.insertion_id, + transaction: Arc::new(transaction), + }; // TODO [ToDr] Most likely move this after the transaction is inserted. // Avoid using should_replace, but rather use scoring for that. @@ -115,7 +150,7 @@ impl Pool where let remove_worst = |s: &mut Self, transaction| { match s.remove_worst(&transaction) { Err(err) => { - s.listener.rejected(&Arc::new(transaction), err.kind()); + s.listener.rejected(&transaction, err.kind()); Err(err) }, Ok(removed) => { @@ -138,7 +173,7 @@ impl Pool where } let (result, prev_state, current_state) = { - let transactions = self.transactions.entry(*transaction.sender()).or_insert_with(Transactions::default); + let transactions = self.transactions.entry(transaction.sender().clone()).or_insert_with(Transactions::default); // get worst and best transactions for comparison let prev = transactions.worst_and_best(); let result = transactions.add(transaction, &self.scoring, self.options.max_per_sender); @@ -153,31 +188,31 @@ impl Pool where AddResult::Ok(tx) => { self.listener.added(&tx, None); self.finalize_insert(&tx, None); - Ok(tx) + Ok(tx.transaction) }, AddResult::PushedOut { new, old } | AddResult::Replaced { new, old } => { self.listener.added(&new, Some(&old)); self.finalize_insert(&new, Some(&old)); - Ok(new) + Ok(new.transaction) }, AddResult::TooCheap { new, old } => { - let error = error::ErrorKind::TooCheapToReplace(*old.hash(), *new.hash()); - self.listener.rejected(&Arc::new(new), &error); + let error = error::ErrorKind::TooCheapToReplace(format!("{:x}", old.hash()), format!("{:x}", new.hash())); + self.listener.rejected(&new, &error); bail!(error) }, AddResult::TooCheapToEnter(new, score) => { - let error = error::ErrorKind::TooCheapToEnter(*new.hash(), format!("{:?}", score)); - self.listener.rejected(&Arc::new(new), &error); + let error = error::ErrorKind::TooCheapToEnter(format!("{:x}", new.hash()), format!("{:?}", score)); + self.listener.rejected(&new, &error); bail!(error) } } } /// Updates state of the pool statistics if the transaction was added to a set. - fn finalize_insert(&mut self, new: &Arc, old: Option<&Arc>) { + fn finalize_insert(&mut self, new: &Transaction, old: Option<&Transaction>) { self.mem_usage += new.mem_usage(); - self.by_hash.insert(*new.hash(), new.clone()); + self.by_hash.insert(new.hash().clone(), new.clone()); if let Some(old) = old { self.finalize_remove(old.hash()); @@ -185,23 +220,23 @@ impl Pool where } /// Updates the pool statistics if transaction was removed. - fn finalize_remove(&mut self, hash: &H256) -> Option> { + fn finalize_remove(&mut self, hash: &T::Hash) -> Option> { self.by_hash.remove(hash).map(|old| { - self.mem_usage -= old.mem_usage(); - old + self.mem_usage -= old.transaction.mem_usage(); + old.transaction }) } /// Updates best and worst transactions from a sender. fn update_senders_worst_and_best( &mut self, - previous: Option<((S::Score, Arc), (S::Score, Arc))>, - current: Option<((S::Score, Arc), (S::Score, Arc))>, + previous: Option<((S::Score, Transaction), (S::Score, Transaction))>, + current: Option<((S::Score, Transaction), (S::Score, Transaction))>, ) { let worst_collection = &mut self.worst_transactions; let best_collection = &mut self.best_transactions; - let is_same = |a: &(S::Score, Arc), b: &(S::Score, Arc)| { + let is_same = |a: &(S::Score, Transaction), b: &(S::Score, Transaction)| { a.0 == b.0 && a.1.hash() == b.1.hash() }; @@ -238,19 +273,19 @@ impl Pool where } /// Attempts to remove the worst transaction from the pool if it's worse than the given one. - fn remove_worst(&mut self, transaction: &T) -> error::Result> { + fn remove_worst(&mut self, transaction: &Transaction) -> error::Result> { let to_remove = match self.worst_transactions.iter().next_back() { // No elements to remove? and the pool is still full? None => { warn!("The pool is full but there are no transactions to remove."); - return Err(error::ErrorKind::TooCheapToEnter(*transaction.hash(), "unknown".into()).into()); + return Err(error::ErrorKind::TooCheapToEnter(format!("{:?}", transaction.hash()), "unknown".into()).into()); }, Some(old) => if self.scoring.should_replace(&old.transaction, transaction) { // New transaction is better than the worst one so we can replace it. old.clone() } else { // otherwise fail - return Err(error::ErrorKind::TooCheapToEnter(*transaction.hash(), format!("{:?}", old.score)).into()) + return Err(error::ErrorKind::TooCheapToEnter(format!("{:?}", transaction.hash()), format!("{:?}", old.score)).into()) }, }; @@ -263,7 +298,7 @@ impl Pool where } /// Removes transaction from sender's transaction `HashMap`. - fn remove_from_set, &S) -> R>(&mut self, sender: &Sender, f: F) -> Option { + fn remove_from_set, &S) -> R>(&mut self, sender: &T::Sender, f: F) -> Option { let (prev, next, result) = if let Some(set) = self.transactions.get_mut(sender) { let prev = set.worst_and_best(); let result = f(set, &self.scoring); @@ -286,14 +321,14 @@ impl Pool where self.worst_transactions.clear(); for (_hash, tx) in self.by_hash.drain() { - self.listener.dropped(&tx, None) + self.listener.dropped(&tx.transaction, None) } } /// Removes single transaction from the pool. /// Depending on the `is_invalid` flag the listener /// will either get a `cancelled` or `invalid` notification. - pub fn remove(&mut self, hash: &H256, is_invalid: bool) -> Option> { + pub fn remove(&mut self, hash: &T::Hash, is_invalid: bool) -> Option> { if let Some(tx) = self.finalize_remove(hash) { self.remove_from_set(tx.sender(), |set, scoring| { set.remove(&tx, scoring) @@ -310,7 +345,7 @@ impl Pool where } /// Removes all stalled transactions from given sender. - fn remove_stalled>(&mut self, sender: &Sender, ready: &mut R) -> usize { + fn remove_stalled>(&mut self, sender: &T::Sender, ready: &mut R) -> usize { let removed_from_set = self.remove_from_set(sender, |transactions, scoring| { transactions.cull(ready, scoring) }); @@ -329,7 +364,7 @@ impl Pool where } /// Removes all stalled transactions from given sender list (or from all senders). - pub fn cull>(&mut self, senders: Option<&[Sender]>, mut ready: R) -> usize { + pub fn cull>(&mut self, senders: Option<&[T::Sender]>, mut ready: R) -> usize { let mut removed = 0; match senders { Some(senders) => { @@ -349,13 +384,13 @@ impl Pool where } /// Returns a transaction if it's part of the pool or `None` otherwise. - pub fn find(&self, hash: &H256) -> Option> { - self.by_hash.get(hash).cloned() + pub fn find(&self, hash: &T::Hash) -> Option> { + self.by_hash.get(hash).map(|t| t.transaction.clone()) } /// Returns worst transaction in the queue (if any). pub fn worst_transaction(&self) -> Option> { - self.worst_transactions.iter().next().map(|x| x.transaction.clone()) + self.worst_transactions.iter().next().map(|x| x.transaction.transaction.clone()) } /// Returns an iterator of pending (ready) transactions. @@ -368,7 +403,7 @@ impl Pool where } /// Returns pending (ready) transactions from given sender. - pub fn pending_from_sender>(&self, ready: R, sender: &Sender) -> PendingIterator { + pub fn pending_from_sender>(&self, ready: R, sender: &T::Sender) -> PendingIterator { let best_transactions = self.transactions.get(sender) .and_then(|transactions| transactions.worst_and_best()) .map(|(_, best)| ScoreWithRef::new(best.0, best.1)) @@ -387,7 +422,7 @@ impl Pool where } /// Update score of transactions of a particular sender. - pub fn update_scores(&mut self, sender: &Sender, event: S::Event) { + pub fn update_scores(&mut self, sender: &T::Sender, event: S::Event) { let res = if let Some(set) = self.transactions.get_mut(sender) { let prev = set.worst_and_best(); set.update_scores(&self.scoring, event); @@ -410,7 +445,7 @@ impl Pool where let len = transactions.len(); for (idx, tx) in transactions.iter().enumerate() { match ready.is_ready(tx) { - Readiness::Stalled => status.stalled += 1, + Readiness::Stale => status.stalled += 1, Readiness::Ready => status.pending += 1, Readiness::Future => { status.future += len - idx; @@ -485,7 +520,7 @@ impl<'a, T, R, S, L> Iterator for PendingIterator<'a, T, R, S, L> where self.best_transactions.insert(ScoreWithRef::new(score, tx)); } - return Some(best.transaction) + return Some(best.transaction.transaction) }, state => trace!("[{:?}] Ignoring {:?} transaction.", best.transaction.hash(), state), } diff --git a/transaction-pool/src/ready.rs b/transaction-pool/src/ready.rs index 73524443227..aa913a9eb58 100644 --- a/transaction-pool/src/ready.rs +++ b/transaction-pool/src/ready.rs @@ -17,8 +17,8 @@ /// Transaction readiness. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Readiness { - /// The transaction is stalled (and should/will be removed from the pool). - Stalled, + /// The transaction is stale (and should/will be removed from the pool). + Stale, /// The transaction is ready to be included in pending set. Ready, /// The transaction is not yet ready. diff --git a/transaction-pool/src/scoring.rs b/transaction-pool/src/scoring.rs index 4e7a9833a16..2acfb337485 100644 --- a/transaction-pool/src/scoring.rs +++ b/transaction-pool/src/scoring.rs @@ -17,9 +17,7 @@ //! A transactions ordering abstraction. use std::{cmp, fmt}; -use std::sync::Arc; - -use {VerifiedTransaction}; +use pool::Transaction; /// Represents a decision what to do with /// a new transaction that tries to enter the pool. @@ -98,7 +96,7 @@ pub trait Scoring: fmt::Debug { /// Updates the transaction scores given a list of transactions and a change to previous scoring. /// NOTE: you can safely assume that both slices have the same length. /// (i.e. score at index `i` represents transaction at the same index) - fn update_scores(&self, txs: &[Arc], scores: &mut [Self::Score], change: Change); + fn update_scores(&self, txs: &[Transaction], scores: &mut [Self::Score], change: Change); /// Decides if `new` should push out `old` transaction from the pool. fn should_replace(&self, old: &T, new: &T) -> bool; @@ -110,7 +108,14 @@ pub struct ScoreWithRef { /// Score pub score: S, /// Shared transaction - pub transaction: Arc, + pub transaction: Transaction, +} + +impl ScoreWithRef { + /// Creates a new `ScoreWithRef` + pub fn new(score: S, transaction: Transaction) -> Self { + ScoreWithRef { score, transaction } + } } impl Clone for ScoreWithRef { @@ -122,30 +127,23 @@ impl Clone for ScoreWithRef { } } -impl ScoreWithRef { - /// Creates a new `ScoreWithRef` - pub fn new(score: S, transaction: Arc) -> Self { - ScoreWithRef { score, transaction } - } -} - -impl Ord for ScoreWithRef { +impl Ord for ScoreWithRef { fn cmp(&self, other: &Self) -> cmp::Ordering { other.score.cmp(&self.score) - .then(other.transaction.insertion_id().cmp(&self.transaction.insertion_id())) + .then(other.transaction.insertion_id.cmp(&self.transaction.insertion_id)) } } -impl PartialOrd for ScoreWithRef { +impl PartialOrd for ScoreWithRef { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl PartialEq for ScoreWithRef { +impl PartialEq for ScoreWithRef { fn eq(&self, other: &Self) -> bool { - self.score == other.score && self.transaction.insertion_id() == other.transaction.insertion_id() + self.score == other.score && self.transaction.insertion_id == other.transaction.insertion_id } } -impl Eq for ScoreWithRef {} +impl Eq for ScoreWithRef {} diff --git a/transaction-pool/src/tests/helpers.rs b/transaction-pool/src/tests/helpers.rs index ab5b2a334b0..cfc6641b5eb 100644 --- a/transaction-pool/src/tests/helpers.rs +++ b/transaction-pool/src/tests/helpers.rs @@ -17,9 +17,9 @@ use std::cmp; use std::collections::HashMap; -use ethereum_types::U256; -use {scoring, Scoring, Ready, Readiness, Address as Sender}; -use super::{Transaction, SharedTransaction}; +use ethereum_types::{H160 as Sender, U256}; +use {pool, scoring, Scoring, Ready, Readiness}; +use super::Transaction; #[derive(Debug, Default)] pub struct DummyScoring; @@ -44,7 +44,7 @@ impl Scoring for DummyScoring { } } - fn update_scores(&self, txs: &[SharedTransaction], scores: &mut [Self::Score], change: scoring::Change) { + fn update_scores(&self, txs: &[pool::Transaction], scores: &mut [Self::Score], change: scoring::Change) { if let scoring::Change::Event(_) = change { // In case of event reset all scores to 0 for i in 0..txs.len() { @@ -84,7 +84,7 @@ impl Ready for NonceReady { *nonce = *nonce + 1.into(); Readiness::Ready }, - cmp::Ordering::Less => Readiness::Stalled, + cmp::Ordering::Less => Readiness::Stale, } } } diff --git a/transaction-pool/src/tests/mod.rs b/transaction-pool/src/tests/mod.rs index 5113a4663c3..b21ea31807c 100644 --- a/transaction-pool/src/tests/mod.rs +++ b/transaction-pool/src/tests/mod.rs @@ -32,15 +32,16 @@ pub struct Transaction { pub gas_price: U256, pub gas: U256, pub sender: Address, - pub insertion_id: u64, pub mem_usage: usize, } impl VerifiedTransaction for Transaction { + type Hash = H256; + type Sender = Address; + fn hash(&self) -> &H256 { &self.hash } fn mem_usage(&self) -> usize { self.mem_usage } fn sender(&self) -> &Address { &self.sender } - fn insertion_id(&self) -> u64 { self.insertion_id } } pub type SharedTransaction = Arc; @@ -123,7 +124,7 @@ fn should_reject_if_above_count() { // Reject second let tx1 = b.tx().nonce(0).new(); let tx2 = b.tx().nonce(1).new(); - let hash = *tx2.hash(); + let hash = format!("{:?}", tx2.hash()); txq.import(tx1).unwrap(); assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash, "0x0".into())); assert_eq!(txq.light_status().transaction_count, 1); @@ -149,7 +150,7 @@ fn should_reject_if_above_mem_usage() { // Reject second let tx1 = b.tx().nonce(1).mem_usage(1).new(); let tx2 = b.tx().nonce(2).mem_usage(2).new(); - let hash = *tx2.hash(); + let hash = format!("{:?}", tx2.hash()); txq.import(tx1).unwrap(); assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash, "0x0".into())); assert_eq!(txq.light_status().transaction_count, 1); @@ -175,7 +176,7 @@ fn should_reject_if_above_sender_count() { // Reject second let tx1 = b.tx().nonce(1).new(); let tx2 = b.tx().nonce(2).new(); - let hash = *tx2.hash(); + let hash = format!("{:x}", tx2.hash()); txq.import(tx1).unwrap(); assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash, "0x0".into())); assert_eq!(txq.light_status().transaction_count, 1); @@ -185,7 +186,7 @@ fn should_reject_if_above_sender_count() { // Replace first let tx1 = b.tx().nonce(1).new(); let tx2 = b.tx().nonce(2).gas_price(2).new(); - let hash = *tx2.hash(); + let hash = format!("{:x}", tx2.hash()); txq.import(tx1).unwrap(); // This results in error because we also compare nonces assert_eq!(txq.import(tx2).unwrap_err().kind(), &error::ErrorKind::TooCheapToEnter(hash, "0x0".into())); diff --git a/transaction-pool/src/tests/tx_builder.rs b/transaction-pool/src/tests/tx_builder.rs index e9c1c1d5fcd..88a881aca8a 100644 --- a/transaction-pool/src/tests/tx_builder.rs +++ b/transaction-pool/src/tests/tx_builder.rs @@ -14,9 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::rc::Rc; -use std::cell::Cell; - use super::{Transaction, U256, Address}; #[derive(Debug, Default, Clone)] @@ -26,7 +23,6 @@ pub struct TransactionBuilder { gas: U256, sender: Address, mem_usage: usize, - insertion_id: Rc>, } impl TransactionBuilder { @@ -55,11 +51,6 @@ impl TransactionBuilder { } pub fn new(self) -> Transaction { - let insertion_id = { - let id = self.insertion_id.get() + 1; - self.insertion_id.set(id); - id - }; let hash = self.nonce ^ (U256::from(100) * self.gas_price) ^ (U256::from(100_000) * U256::from(self.sender.low_u64())); Transaction { hash: hash.into(), @@ -67,7 +58,6 @@ impl TransactionBuilder { gas_price: self.gas_price, gas: 21_000.into(), sender: self.sender, - insertion_id, mem_usage: self.mem_usage, } } diff --git a/transaction-pool/src/transactions.rs b/transaction-pool/src/transactions.rs index c839d9e6853..f1a91ff4f83 100644 --- a/transaction-pool/src/transactions.rs +++ b/transaction-pool/src/transactions.rs @@ -15,28 +15,28 @@ // along with Parity. If not, see . use std::{fmt, mem}; -use std::sync::Arc; use smallvec::SmallVec; use ready::{Ready, Readiness}; use scoring::{self, Scoring}; +use pool::Transaction; #[derive(Debug)] pub enum AddResult { - Ok(Arc), + Ok(T), TooCheapToEnter(T, S), TooCheap { - old: Arc, + old: T, new: T, }, Replaced { - old: Arc, - new: Arc, + old: T, + new: T, }, PushedOut { - old: Arc, - new: Arc, + old: T, + new: T, }, } @@ -45,7 +45,7 @@ const PER_SENDER: usize = 8; #[derive(Debug)] pub struct Transactions> { // TODO [ToDr] Consider using something that doesn't require shifting all records. - transactions: SmallVec<[Arc; PER_SENDER]>, + transactions: SmallVec<[Transaction; PER_SENDER]>, scores: SmallVec<[S::Score; PER_SENDER]>, } @@ -67,11 +67,11 @@ impl> Transactions { self.transactions.len() } - pub fn iter(&self) -> ::std::slice::Iter> { + pub fn iter(&self) -> ::std::slice::Iter> { self.transactions.iter() } - pub fn worst_and_best(&self) -> Option<((S::Score, Arc), (S::Score, Arc))> { + pub fn worst_and_best(&self) -> Option<((S::Score, Transaction), (S::Score, Transaction))> { let len = self.scores.len(); self.scores.get(0).cloned().map(|best| { let worst = self.scores[len - 1].clone(); @@ -82,7 +82,7 @@ impl> Transactions { }) } - pub fn find_next(&self, tx: &T, scoring: &S) -> Option<(S::Score, Arc)> { + pub fn find_next(&self, tx: &T, scoring: &S) -> Option<(S::Score, Transaction)> { self.transactions.binary_search_by(|old| scoring.compare(old, &tx)).ok().and_then(|index| { let index = index + 1; if index < self.scores.len() { @@ -93,18 +93,17 @@ impl> Transactions { }) } - fn push_cheapest_transaction(&mut self, tx: T, scoring: &S, max_count: usize) -> AddResult { + fn push_cheapest_transaction(&mut self, tx: Transaction, scoring: &S, max_count: usize) -> AddResult, S::Score> { let index = self.transactions.len(); if index == max_count { let min_score = self.scores[index - 1].clone(); AddResult::TooCheapToEnter(tx, min_score) } else { - let shared = Arc::new(tx); - self.transactions.push(shared.clone()); + self.transactions.push(tx.clone()); self.scores.push(Default::default()); scoring.update_scores(&self.transactions, &mut self.scores, scoring::Change::InsertedAt(index)); - AddResult::Ok(shared) + AddResult::Ok(tx) } } @@ -112,28 +111,26 @@ impl> Transactions { scoring.update_scores(&self.transactions, &mut self.scores, scoring::Change::Event(event)); } - pub fn add(&mut self, tx: T, scoring: &S, max_count: usize) -> AddResult { - let index = match self.transactions.binary_search_by(|old| scoring.compare(old, &tx)) { + pub fn add(&mut self, new: Transaction, scoring: &S, max_count: usize) -> AddResult, S::Score> { + let index = match self.transactions.binary_search_by(|old| scoring.compare(old, &new)) { Ok(index) => index, Err(index) => index, }; // Insert at the end. if index == self.transactions.len() { - return self.push_cheapest_transaction(tx, scoring, max_count) + return self.push_cheapest_transaction(new, scoring, max_count) } // Decide if the transaction should replace some other. - match scoring.choose(&self.transactions[index], &tx) { + match scoring.choose(&self.transactions[index], &new) { // New transaction should be rejected scoring::Choice::RejectNew => AddResult::TooCheap { old: self.transactions[index].clone(), - new: tx, + new, }, // New transaction should be kept along with old ones. scoring::Choice::InsertNew => { - let new = Arc::new(tx); - self.transactions.insert(index, new.clone()); self.scores.insert(index, Default::default()); scoring.update_scores(&self.transactions, &mut self.scores, scoring::Change::InsertedAt(index)); @@ -153,7 +150,6 @@ impl> Transactions { }, // New transaction is replacing some other transaction already in the queue. scoring::Choice::ReplaceOld => { - let new = Arc::new(tx); let old = mem::replace(&mut self.transactions[index], new.clone()); scoring.update_scores(&self.transactions, &mut self.scores, scoring::Change::ReplacedAt(index)); @@ -181,7 +177,7 @@ impl> Transactions { return true; } - pub fn cull>(&mut self, ready: &mut R, scoring: &S) -> SmallVec<[Arc; PER_SENDER]> { + pub fn cull>(&mut self, ready: &mut R, scoring: &S) -> SmallVec<[Transaction; PER_SENDER]> { let mut result = SmallVec::new(); if self.is_empty() { return result; @@ -190,7 +186,7 @@ impl> Transactions { let mut first_non_stalled = 0; for tx in &self.transactions { match ready.is_ready(tx) { - Readiness::Stalled => { + Readiness::Stale => { first_non_stalled += 1; }, Readiness::Ready | Readiness::Future => break, From b10094508f3a149830199ed35ea5ad7850a43603 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 2 May 2018 15:40:27 +0800 Subject: [PATCH 31/95] Fetching logs by hash in blockchain database (#8463) * Fetch logs by hash in blockchain database * Fix tests * Add unit test for branch block logs fetching * Add docs that blocks must already be sorted * Handle branch block cases properly * typo: empty -> is_empty * Remove return_empty_if_none by using a closure * Use BTreeSet to avoid sorting again * Move is_canon to BlockChain * typo: pass value by reference * Use loop and wrap inside blocks to simplify the code Borrowed from https://github.com/paritytech/parity/pull/8463#discussion_r183453326 * typo: missed a comment --- ethcore/src/blockchain/blockchain.rs | 60 ++++++++++++++-- ethcore/src/client/client.rs | 91 +++++++++++++++++++----- ethcore/src/verification/verification.rs | 2 +- 3 files changed, 129 insertions(+), 24 deletions(-) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 6ad8bf8111a..57bcdf2bc28 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -57,6 +57,12 @@ pub trait BlockProvider { /// (though not necessarily a part of the canon chain). fn is_known(&self, hash: &H256) -> bool; + /// Returns true if the given block is known and in the canon chain. + fn is_canon(&self, hash: &H256) -> bool { + let is_canon = || Some(hash == &self.block_hash(self.block_number(hash)?)?); + is_canon().unwrap_or(false) + } + /// Get the first block of the best part of the chain. /// Return `None` if there is no gap and the first block is the genesis. /// Any queries of blocks which precede this one are not guaranteed to @@ -148,7 +154,7 @@ pub trait BlockProvider { fn blocks_with_bloom(&self, bloom: &Bloom, from_block: BlockNumber, to_block: BlockNumber) -> Vec; /// Returns logs matching given filter. - fn logs(&self, blocks: Vec, matches: F, limit: Option) -> Vec + fn logs(&self, blocks: Vec, matches: F, limit: Option) -> Vec where F: Fn(&LogEntry) -> bool + Send + Sync, Self: Sized; } @@ -332,16 +338,18 @@ impl BlockProvider for BlockChain { .collect() } - fn logs(&self, mut blocks: Vec, matches: F, limit: Option) -> Vec + /// Returns logs matching given filter. The order of logs returned will be the same as the order of the blocks + /// provided. And it's the callers responsibility to sort blocks provided in advance. + fn logs(&self, mut blocks: Vec, matches: F, limit: Option) -> Vec where F: Fn(&LogEntry) -> bool + Send + Sync, Self: Sized { // sort in reverse order - blocks.sort_by(|a, b| b.cmp(a)); + blocks.reverse(); let mut logs = blocks .chunks(128) .flat_map(move |blocks_chunk| { blocks_chunk.into_par_iter() - .filter_map(|number| self.block_hash(*number).map(|hash| (*number, hash))) + .filter_map(|hash| self.block_number(&hash).map(|r| (r, hash))) .filter_map(|(number, hash)| self.block_receipts(&hash).map(|r| (number, hash, r.receipts))) .filter_map(|(number, hash, receipts)| self.block_body(&hash).map(|ref b| (number, hash, receipts, b.transaction_hashes()))) .flat_map(|(number, hash, mut receipts, mut hashes)| { @@ -368,7 +376,7 @@ impl BlockProvider for BlockChain { .enumerate() .map(move |(i, log)| LocalizedLogEntry { entry: log, - block_hash: hash, + block_hash: *hash, block_number: number, transaction_hash: tx_hash, // iterating in reverse order @@ -1933,17 +1941,33 @@ mod tests { value: 103.into(), data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(), }.sign(&secret(), None); + let t4 = Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 100_000.into(), + action: Action::Create, + value: 104.into(), + data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(), + }.sign(&secret(), None); let tx_hash1 = t1.hash(); let tx_hash2 = t2.hash(); let tx_hash3 = t3.hash(); + let tx_hash4 = t4.hash(); let genesis = BlockBuilder::genesis(); let b1 = genesis.add_block_with_transactions(vec![t1, t2]); let b2 = b1.add_block_with_transactions(iter::once(t3)); + let b3 = genesis.add_block_with(|| BlockOptions { + transactions: vec![t4.clone()], + difficulty: U256::from(9), + ..Default::default() + }); // Branch block let b1_hash = b1.last().hash(); let b1_number = b1.last().number(); let b2_hash = b2.last().hash(); let b2_number = b2.last().number(); + let b3_hash = b3.last().hash(); + let b3_number = b3.last().number(); let db = new_db(); let bc = new_chain(&genesis.last().encoded(), db.clone()); @@ -1974,10 +1998,21 @@ mod tests { ], } ]); + insert_block(&db, &bc, &b3.last().encoded(), vec![ + Receipt { + outcome: TransactionOutcome::StateRoot(H256::default()), + gas_used: 10_000.into(), + log_bloom: Default::default(), + logs: vec![ + LogEntry { address: Default::default(), topics: vec![], data: vec![5], }, + ], + } + ]); // when - let logs1 = bc.logs(vec![1, 2], |_| true, None); - let logs2 = bc.logs(vec![1, 2], |_| true, Some(1)); + let logs1 = bc.logs(vec![b1_hash, b2_hash], |_| true, None); + let logs2 = bc.logs(vec![b1_hash, b2_hash], |_| true, Some(1)); + let logs3 = bc.logs(vec![b3_hash], |_| true, None); // then assert_eq!(logs1, vec![ @@ -2029,6 +2064,17 @@ mod tests { log_index: 0, } ]); + assert_eq!(logs3, vec![ + LocalizedLogEntry { + entry: LogEntry { address: Default::default(), topics: vec![], data: vec![5] }, + block_hash: b3_hash, + block_number: b3_number, + transaction_hash: tx_hash4, + transaction_index: 0, + transaction_log_index: 0, + log_index: 0, + } + ]); } #[test] diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index bc20de3dd86..5efdef3a4d6 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::collections::{HashSet, HashMap, BTreeMap, VecDeque}; +use std::collections::{HashSet, HashMap, BTreeMap, BTreeSet, VecDeque}; use std::str::FromStr; use std::sync::{Arc, Weak}; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; @@ -1848,23 +1848,82 @@ impl BlockChainClient for Client { } fn logs(&self, filter: Filter) -> Vec { - let (from, to) = match (self.block_number_ref(&filter.from_block), self.block_number_ref(&filter.to_block)) { - (Some(from), Some(to)) => (from, to), - _ => return Vec::new(), - }; + // Wrap the logic inside a closure so that we can take advantage of question mark syntax. + let fetch_logs = || { + let chain = self.chain.read(); - let chain = self.chain.read(); - let blocks = filter.bloom_possibilities().iter() - .map(move |bloom| { - chain.blocks_with_bloom(bloom, from, to) - }) - .flat_map(|m| m) - // remove duplicate elements - .collect::>() - .into_iter() - .collect::>(); + // First, check whether `filter.from_block` and `filter.to_block` is on the canon chain. If so, we can use the + // optimized version. + let is_canon = |id| { + match id { + // If it is referred by number, then it is always on the canon chain. + &BlockId::Earliest | &BlockId::Latest | &BlockId::Number(_) => true, + // If it is referred by hash, we see whether a hash -> number -> hash conversion gives us the same + // result. + &BlockId::Hash(ref hash) => chain.is_canon(hash), + } + }; + + let blocks = if is_canon(&filter.from_block) && is_canon(&filter.to_block) { + // If we are on the canon chain, use bloom filter to fetch required hashes. + let from = self.block_number_ref(&filter.from_block)?; + let to = self.block_number_ref(&filter.to_block)?; + + filter.bloom_possibilities().iter() + .map(|bloom| { + chain.blocks_with_bloom(bloom, from, to) + }) + .flat_map(|m| m) + // remove duplicate elements + .collect::>() + .into_iter() + .filter_map(|n| chain.block_hash(n)) + .collect::>() + + } else { + // Otherwise, we use a slower version that finds a link between from_block and to_block. + let from_hash = Self::block_hash(&chain, filter.from_block)?; + let from_number = chain.block_number(&from_hash)?; + let to_hash = Self::block_hash(&chain, filter.from_block)?; + + let blooms = filter.bloom_possibilities(); + let bloom_match = |header: &encoded::Header| { + blooms.iter().any(|bloom| header.log_bloom().contains_bloom(bloom)) + }; + + let (blocks, last_hash) = { + let mut blocks = Vec::new(); + let mut current_hash = to_hash; + + loop { + let header = chain.block_header_data(¤t_hash)?; + if bloom_match(&header) { + blocks.push(current_hash); + } + + // Stop if `from` block is reached. + if header.number() <= from_number { + break; + } + current_hash = header.parent_hash(); + } + + blocks.reverse(); + (blocks, current_hash) + }; + + // Check if we've actually reached the expected `from` block. + if last_hash != from_hash || blocks.is_empty() { + return None; + } + + blocks + }; + + Some(self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit)) + }; - self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit) + fetch_logs().unwrap_or_default() } fn filter_traces(&self, filter: TraceFilter) -> Option> { diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 814a12aadfe..92f3e77f902 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -476,7 +476,7 @@ mod tests { unimplemented!() } - fn logs(&self, _blocks: Vec, _matches: F, _limit: Option) -> Vec + fn logs(&self, _blocks: Vec, _matches: F, _limit: Option) -> Vec where F: Fn(&LogEntry) -> bool, Self: Sized { unimplemented!() } From eec7364760e760c798e744bba7c05f2ae9dd700a Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 2 May 2018 22:47:53 +0800 Subject: [PATCH 32/95] Pass on storage keys tracing to handle the case when it is not modified (#8491) * Pass on storage keys even if it is not modified * typo: account and storage query `to_pod_diff` builds both `touched_addresses` merge and storage keys merge. * Fix tests * Use state query directly because of suicided accounts * Fix a RefCell borrow issue * Add tests for unmodified storage trace * Address grumbles * typo: remove unwanted empty line * ensure_cached compiles with the original signature --- ethcore/src/state/mod.rs | 114 +++++++++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 27 deletions(-) diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 9fd3fd8525e..255dce5b5de 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -21,7 +21,7 @@ use std::cell::{RefCell, RefMut}; use std::collections::hash_map::Entry; -use std::collections::{HashMap, BTreeMap, HashSet}; +use std::collections::{HashMap, BTreeMap, BTreeSet, HashSet}; use std::fmt; use std::sync::Arc; use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY}; @@ -862,40 +862,65 @@ impl State { })) } - // Return a list of all touched addresses in cache. - fn touched_addresses(&self) -> Vec
{ + /// Populate a PodAccount map from this state, with another state as the account and storage query. + pub fn to_pod_diff(&mut self, query: &State) -> trie::Result { assert!(self.checkpoints.borrow().is_empty()); - self.cache.borrow().iter().map(|(add, _)| *add).collect() - } - fn query_pod(&mut self, query: &PodState, touched_addresses: &[Address]) -> trie::Result<()> { - let pod = query.get(); + // Merge PodAccount::to_pod for cache of self and `query`. + let all_addresses = self.cache.borrow().keys().cloned() + .chain(query.cache.borrow().keys().cloned()) + .collect::>(); + + Ok(PodState::from(all_addresses.into_iter().fold(Ok(BTreeMap::new()), |m: trie::Result<_>, address| { + let mut m = m?; + + let account = self.ensure_cached(&address, RequireCache::Code, true, |acc| { + acc.map(|acc| { + // Merge all modified storage keys. + let all_keys = { + let self_keys = acc.storage_changes().keys().cloned() + .collect::>(); + + if let Some(ref query_storage) = query.cache.borrow().get(&address) + .and_then(|opt| { + Some(opt.account.as_ref()?.storage_changes().keys().cloned() + .collect::>()) + }) + { + self_keys.union(&query_storage).cloned().collect::>() + } else { + self_keys.into_iter().collect::>() + } + }; - for address in touched_addresses { - if !self.ensure_cached(address, RequireCache::Code, true, |a| a.is_some())? { - continue - } + // Storage must be fetched after ensure_cached to avoid borrow problem. + (*acc.balance(), *acc.nonce(), all_keys, acc.code().map(|x| x.to_vec())) + }) + })?; - if let Some(pod_account) = pod.get(address) { - // needs to be split into two parts for the refcell code here - // to work. - for key in pod_account.storage.keys() { - self.storage_at(address, key)?; - } + if let Some((balance, nonce, storage_keys, code)) = account { + let storage = storage_keys.into_iter().fold(Ok(BTreeMap::new()), |s: trie::Result<_>, key| { + let mut s = s?; + + s.insert(key, self.storage_at(&address, &key)?); + Ok(s) + })?; + + m.insert(address, PodAccount { + balance, nonce, storage, code + }); } - } - Ok(()) + Ok(m) + })?)) } /// Returns a `StateDiff` describing the difference from `orig` to `self`. /// Consumes self. - pub fn diff_from(&self, orig: State) -> trie::Result { - let addresses_post = self.touched_addresses(); + pub fn diff_from(&self, mut orig: State) -> trie::Result { let pod_state_post = self.to_pod(); - let mut state_pre = orig; - state_pre.query_pod(&pod_state_post, &addresses_post)?; - Ok(pod_state::diff_pod(&state_pre.to_pod(), &pod_state_post)) + let pod_state_pre = orig.to_pod_diff(self)?; + Ok(pod_state::diff_pod(&pod_state_pre, &pod_state_post)) } // load required account data from the databases. @@ -2243,9 +2268,6 @@ mod tests { let original = state.clone(); state.kill_account(&a); - assert_eq!(original.touched_addresses(), vec![]); - assert_eq!(state.touched_addresses(), vec![a]); - let diff = state.diff_from(original).unwrap(); let diff_map = diff.get(); assert_eq!(diff_map.len(), 1); @@ -2258,4 +2280,42 @@ mod tests { storage: Default::default() }), None).as_ref()); } + + #[test] + fn should_trace_diff_unmodified_storage() { + use pod_account; + + let a = 10.into(); + let db = get_temp_state_db(); + + let (root, db) = { + let mut state = State::new(db, U256::from(0), Default::default()); + state.set_storage(&a, H256::from(&U256::from(1u64)), H256::from(&U256::from(20u64))).unwrap(); + state.commit().unwrap(); + state.drop() + }; + + let mut state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap(); + let original = state.clone(); + state.set_storage(&a, H256::from(&U256::from(1u64)), H256::from(&U256::from(100u64))).unwrap(); + + let diff = state.diff_from(original).unwrap(); + let diff_map = diff.get(); + assert_eq!(diff_map.len(), 1); + assert!(diff_map.get(&a).is_some()); + assert_eq!(diff_map.get(&a), + pod_account::diff_pod(Some(&PodAccount { + balance: U256::zero(), + nonce: U256::zero(), + code: Some(Default::default()), + storage: vec![(H256::from(&U256::from(1u64)), H256::from(&U256::from(20u64)))] + .into_iter().collect(), + }), Some(&PodAccount { + balance: U256::zero(), + nonce: U256::zero(), + code: Some(Default::default()), + storage: vec![(H256::from(&U256::from(1u64)), H256::from(&U256::from(100u64)))] + .into_iter().collect(), + })).as_ref()); + } } From 66c0638f3bddd262e4de19eb565413f82fda08fb Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Thu, 3 May 2018 08:01:13 +0100 Subject: [PATCH 33/95] Don't panic in import_block if invalid rlp (#8522) * Don't panic in import_block if invalid rlp * Remove redundant type annotation * Replace RLP header view usage with safe decoding Using the view will panic with invalid RLP. Here we use Rlp decoding directly which will return a `Result<_, DecoderError>`. While this path currently should not have any invalid RLP - it makes it safer if ever called with invalid RLP from other code paths. --- ethcore/src/client/client.rs | 14 ++++++-------- ethcore/src/error.rs | 2 ++ ethcore/src/tests/client.rs | 20 ++++++++++++++++++++ ethcore/src/verification/queue/kind.rs | 9 ++++----- ethcore/src/verification/queue/mod.rs | 23 ++++++++++++++--------- 5 files changed, 46 insertions(+), 22 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 5efdef3a4d6..a37d62a5911 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -447,9 +447,7 @@ impl Importer { /// /// The block is guaranteed to be the next best blocks in the /// first block sequence. Does no sealing or transaction validation. - fn import_old_block(&self, block_bytes: Bytes, receipts_bytes: Bytes, db: &KeyValueDB, chain: &BlockChain) -> Result { - let block = view!(BlockView, &block_bytes); - let header = block.header(); + fn import_old_block(&self, header: &Header, block_bytes: Bytes, receipts_bytes: Bytes, db: &KeyValueDB, chain: &BlockChain) -> Result { let receipts = ::rlp::decode_list(&receipts_bytes); let hash = header.hash(); let _import_lock = self.import_lock.lock(); @@ -1408,7 +1406,7 @@ impl ImportBlock for Client { use verification::queue::kind::blocks::Unverified; // create unverified block here so the `keccak` calculation can be cached. - let unverified = Unverified::new(bytes); + let unverified = Unverified::from_rlp(bytes)?; { if self.chain.read().is_known(&unverified.hash()) { @@ -1423,19 +1421,19 @@ impl ImportBlock for Client { } fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result { + let header: Header = ::rlp::Rlp::new(&block_bytes).val_at(0)?; { // check block order - let header = view!(BlockView, &block_bytes).header_view(); if self.chain.read().is_known(&header.hash()) { bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain)); } - let status = self.block_status(BlockId::Hash(header.parent_hash())); + let status = self.block_status(BlockId::Hash(*header.parent_hash())); if status == BlockStatus::Unknown || status == BlockStatus::Pending { - bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(header.parent_hash()))); + bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(*header.parent_hash()))); } } - self.importer.import_old_block(block_bytes, receipts_bytes, &**self.db.read(), &*self.chain.read()).map_err(Into::into) + self.importer.import_old_block(&header, block_bytes, receipts_bytes, &**self.db.read(), &*self.chain.read()).map_err(Into::into) } } diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index b68bf355347..561701e7620 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -190,6 +190,7 @@ error_chain! { foreign_links { Block(BlockError) #[doc = "Block error"]; + Decoder(::rlp::DecoderError) #[doc = "Rlp decoding error"]; } errors { @@ -206,6 +207,7 @@ impl From for BlockImportError { match e { Error(ErrorKind::Block(block_error), _) => BlockImportErrorKind::Block(block_error).into(), Error(ErrorKind::Import(import_error), _) => BlockImportErrorKind::Import(import_error.into()).into(), + Error(ErrorKind::Util(util_error::ErrorKind::Decoder(decoder_err)), _) => BlockImportErrorKind::Decoder(decoder_err).into(), _ => BlockImportErrorKind::Other(format!("other block import error: {:?}", e)).into(), } } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 0b8200e938a..6dcad9ba62f 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -36,6 +36,7 @@ use views::BlockView; use ethkey::KeyPair; use transaction::{PendingTransaction, Transaction, Action, Condition}; use miner::MinerService; +use rlp::{RlpStream, EMPTY_LIST_RLP}; use tempdir::TempDir; #[test] @@ -111,6 +112,25 @@ fn imports_good_block() { assert!(!block.into_inner().is_empty()); } +#[test] +fn fails_to_import_block_with_invalid_rlp() { + use error::{BlockImportError, BlockImportErrorKind}; + + let client = generate_dummy_client(6); + let mut rlp = RlpStream::new_list(3); + rlp.append_raw(&EMPTY_LIST_RLP, 1); // empty header + rlp.append_raw(&EMPTY_LIST_RLP, 1); + rlp.append_raw(&EMPTY_LIST_RLP, 1); + let invalid_header_block = rlp.out(); + + match client.import_block(invalid_header_block) { + Err(BlockImportError(BlockImportErrorKind::Decoder(_), _)) => (), // all good + Err(_) => panic!("Should fail with a decoder error"), + Ok(_) => panic!("Should not import block with invalid header"), + } +} + + #[test] fn query_none_block() { let tempdir = TempDir::new("").unwrap(); diff --git a/ethcore/src/verification/queue/kind.rs b/ethcore/src/verification/queue/kind.rs index 7007da5be1f..ce9bddf4efe 100644 --- a/ethcore/src/verification/queue/kind.rs +++ b/ethcore/src/verification/queue/kind.rs @@ -119,14 +119,13 @@ pub mod blocks { impl Unverified { /// Create an `Unverified` from raw bytes. - pub fn new(bytes: Bytes) -> Self { - use views::BlockView; + pub fn from_rlp(bytes: Bytes) -> Result { - let header = view!(BlockView, &bytes).header(); - Unverified { + let header = ::rlp::Rlp::new(&bytes).val_at(0)?; + Ok(Unverified { header: header, bytes: bytes, - } + }) } } diff --git a/ethcore/src/verification/queue/mod.rs b/ethcore/src/verification/queue/mod.rs index ca633b0f3de..f7a558f33d1 100644 --- a/ethcore/src/verification/queue/mod.rs +++ b/ethcore/src/verification/queue/mod.rs @@ -734,6 +734,7 @@ mod tests { use test_helpers::{get_good_dummy_block_seq, get_good_dummy_block}; use error::*; use views::BlockView; + use bytes::Bytes; // create a test block queue. // auto_scaling enables verifier adjustment. @@ -746,6 +747,10 @@ mod tests { BlockQueue::new(config, engine, IoChannel::disconnected(), true) } + fn new_unverified(bytes: Bytes) -> Unverified { + Unverified::from_rlp(bytes).expect("Should be valid rlp") + } + #[test] fn can_be_created() { // TODO better test @@ -757,7 +762,7 @@ mod tests { #[test] fn can_import_blocks() { let queue = get_test_queue(false); - if let Err(e) = queue.import(Unverified::new(get_good_dummy_block())) { + if let Err(e) = queue.import(new_unverified(get_good_dummy_block())) { panic!("error importing block that is valid by definition({:?})", e); } } @@ -765,11 +770,11 @@ mod tests { #[test] fn returns_error_for_duplicates() { let queue = get_test_queue(false); - if let Err(e) = queue.import(Unverified::new(get_good_dummy_block())) { + if let Err(e) = queue.import(new_unverified(get_good_dummy_block())) { panic!("error importing block that is valid by definition({:?})", e); } - let duplicate_import = queue.import(Unverified::new(get_good_dummy_block())); + let duplicate_import = queue.import(new_unverified(get_good_dummy_block())); match duplicate_import { Err(e) => { match e { @@ -786,7 +791,7 @@ mod tests { let queue = get_test_queue(false); let block = get_good_dummy_block(); let hash = view!(BlockView, &block).header().hash().clone(); - if let Err(e) = queue.import(Unverified::new(block)) { + if let Err(e) = queue.import(new_unverified(block)) { panic!("error importing block that is valid by definition({:?})", e); } queue.flush(); @@ -802,14 +807,14 @@ mod tests { let queue = get_test_queue(false); let block = get_good_dummy_block(); let hash = view!(BlockView, &block).header().hash().clone(); - if let Err(e) = queue.import(Unverified::new(block)) { + if let Err(e) = queue.import(new_unverified(block)) { panic!("error importing block that is valid by definition({:?})", e); } queue.flush(); queue.drain(10); queue.mark_as_good(&[ hash ]); - if let Err(e) = queue.import(Unverified::new(get_good_dummy_block())) { + if let Err(e) = queue.import(new_unverified(get_good_dummy_block())) { panic!("error importing block that has already been drained ({:?})", e); } } @@ -817,7 +822,7 @@ mod tests { #[test] fn returns_empty_once_finished() { let queue = get_test_queue(false); - queue.import(Unverified::new(get_good_dummy_block())) + queue.import(new_unverified(get_good_dummy_block())) .expect("error importing block that is valid by definition"); queue.flush(); queue.drain(1); @@ -835,7 +840,7 @@ mod tests { assert!(!queue.queue_info().is_full()); let mut blocks = get_good_dummy_block_seq(50); for b in blocks.drain(..) { - queue.import(Unverified::new(b)).unwrap(); + queue.import(new_unverified(b)).unwrap(); } assert!(queue.queue_info().is_full()); } @@ -863,7 +868,7 @@ mod tests { *queue.state.0.lock() = State::Work(0); for block in get_good_dummy_block_seq(5000) { - queue.import(Unverified::new(block)).expect("Block good by definition; qed"); + queue.import(new_unverified(block)).expect("Block good by definition; qed"); } // almost all unverified == bump verifier count. From f0c6d17ad81636d3ca02e1694d5ffe39941ad425 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 4 May 2018 10:06:54 +0200 Subject: [PATCH 34/95] Remove expect (#8536) * Remove expect and propagate rlp::DecoderErrors as TrieErrors --- util/patricia_trie/src/lib.rs | 8 ++++++++ util/patricia_trie/src/lookup.rs | 2 +- util/patricia_trie/src/triedb.rs | 27 +++++++++++++++++++++++++++ util/rlp/src/error.rs | 2 +- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/util/patricia_trie/src/lib.rs b/util/patricia_trie/src/lib.rs index 3a1d683c26c..d1563becff0 100644 --- a/util/patricia_trie/src/lib.rs +++ b/util/patricia_trie/src/lib.rs @@ -67,6 +67,8 @@ pub enum TrieError { InvalidStateRoot(H256), /// Trie item not found in the database, IncompleteDatabase(H256), + /// Corrupt Trie item + DecoderError(rlp::DecoderError), } impl fmt::Display for TrieError { @@ -75,6 +77,7 @@ impl fmt::Display for TrieError { TrieError::InvalidStateRoot(ref root) => write!(f, "Invalid state root: {}", root), TrieError::IncompleteDatabase(ref missing) => write!(f, "Database missing expected key: {}", missing), + TrieError::DecoderError(ref err) => write!(f, "Decoding failed with {}", err), } } } @@ -84,10 +87,15 @@ impl error::Error for TrieError { match *self { TrieError::InvalidStateRoot(_) => "Invalid state root", TrieError::IncompleteDatabase(_) => "Incomplete database", + TrieError::DecoderError(ref e) => e.description(), } } } +impl From for Box { + fn from(e: rlp::DecoderError) -> Self { Box::new(TrieError::DecoderError(e)) } +} + /// Trie result type. Boxed to avoid copying around extra space for `H256`s on successful queries. pub type Result = ::std::result::Result>; diff --git a/util/patricia_trie/src/lookup.rs b/util/patricia_trie/src/lookup.rs index 88d2bc66e02..2d63f7d00e1 100644 --- a/util/patricia_trie/src/lookup.rs +++ b/util/patricia_trie/src/lookup.rs @@ -55,7 +55,7 @@ impl<'a, Q: Query> Lookup<'a, Q> { // without incrementing the depth. let mut node_data = &node_data[..]; loop { - match Node::decoded(node_data).expect("rlp read from db; qed") { + match Node::decoded(node_data)? { Node::Leaf(slice, value) => { return Ok(match slice == key { true => Some(self.query.decode(value)), diff --git a/util/patricia_trie/src/triedb.rs b/util/patricia_trie/src/triedb.rs index 682f12467d3..aed683117d3 100644 --- a/util/patricia_trie/src/triedb.rs +++ b/util/patricia_trie/src/triedb.rs @@ -493,3 +493,30 @@ fn get_len() { assert_eq!(t.get_with(b"B", |x: &[u8]| x.len()), Ok(Some(5))); assert_eq!(t.get_with(b"C", |x: &[u8]| x.len()), Ok(None)); } + +// Test will work once https://github.com/paritytech/parity/pull/8527 is merged and rlp::decode returns Result instead of panicking +//#[test] +//fn test_lookup_with_corrupt_data_returns_decoder_error() { +// use memorydb::*; +// use super::TrieMut; +// use super::triedbmut::*; +// use rlp; +// use ethereum_types::H512; +// +// let mut memdb = MemoryDB::new(); +// let mut root = H256::new(); +// { +// let mut t = TrieDBMut::new(&mut memdb, &mut root); +// t.insert(b"A", b"ABC").unwrap(); +// t.insert(b"B", b"ABCBA").unwrap(); +// } +// +// let t = TrieDB::new(&memdb, &root).unwrap(); +// +// // query for an invalid data type to trigger an error +// let q = rlp::decode::; +// let lookup = Lookup{ db: t.db, query: q, hash: root }; +// let query_result = lookup.look_up(NibbleSlice::new(b"A")); +// let expected = Box::new(TrieError::DecoderError(::rlp::DecoderError::RlpIsTooShort)); +// assert_eq!(query_result.unwrap_err(), expected); +//} diff --git a/util/rlp/src/error.rs b/util/rlp/src/error.rs index 5113fdc17df..7aef6cfbf72 100644 --- a/util/rlp/src/error.rs +++ b/util/rlp/src/error.rs @@ -9,7 +9,7 @@ use std::fmt; use std::error::Error as StdError; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone)] /// Error concerning the RLP decoder. pub enum DecoderError { /// Data has additional bytes at the end of the valid RLP fragment. From a4c7843a073cceecf3d2adb8df26e96aa2e6bb6e Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sat, 5 May 2018 16:23:50 +0800 Subject: [PATCH 35/95] EIP 145: Bitwise shifting instructions in EVM (#8451) * Add SHL, SHR, SAR opcodes * Add have_bitwise_shifting schedule flag * Add all EIP tests for SHL * Add SHR implementation and tests * Implement SAR and add tests * Add eip145transition config param * Change map_or to map_or_else when possible --- ethcore/evm/src/instructions.rs | 10 +- ethcore/evm/src/interpreter/mod.rs | 55 +++++- ethcore/evm/src/tests.rs | 268 ++++++++++++++++++++++++++++- ethcore/src/spec/spec.rs | 39 +++-- ethcore/vm/src/schedule.rs | 12 +- ethcore/vm/src/tests.rs | 7 + json/src/spec/params.rs | 3 + 7 files changed, 374 insertions(+), 20 deletions(-) diff --git a/ethcore/evm/src/instructions.rs b/ethcore/evm/src/instructions.rs index 3fb9fb93396..6ecfc7f6730 100644 --- a/ethcore/evm/src/instructions.rs +++ b/ethcore/evm/src/instructions.rs @@ -187,6 +187,9 @@ lazy_static! { arr[OR as usize] = InstructionInfo::new("OR", 2, 1, GasPriceTier::VeryLow); arr[XOR as usize] = InstructionInfo::new("XOR", 2, 1, GasPriceTier::VeryLow); arr[BYTE as usize] = InstructionInfo::new("BYTE", 2, 1, GasPriceTier::VeryLow); + arr[SHL as usize] = InstructionInfo::new("SHL", 2, 1, GasPriceTier::VeryLow); + arr[SHR as usize] = InstructionInfo::new("SHR", 2, 1, GasPriceTier::VeryLow); + arr[SAR as usize] = InstructionInfo::new("SAR", 2, 1, GasPriceTier::VeryLow); arr[ADDMOD as usize] = InstructionInfo::new("ADDMOD", 3, 1, GasPriceTier::Mid); arr[MULMOD as usize] = InstructionInfo::new("MULMOD", 3, 1, GasPriceTier::Mid); arr[SIGNEXTEND as usize] = InstructionInfo::new("SIGNEXTEND", 2, 1, GasPriceTier::Low); @@ -354,6 +357,12 @@ pub const XOR: Instruction = 0x18; pub const NOT: Instruction = 0x19; /// retrieve single byte from word pub const BYTE: Instruction = 0x1a; +/// shift left operation +pub const SHL: Instruction = 0x1b; +/// logical shift right operation +pub const SHR: Instruction = 0x1c; +/// arithmetic shift right operation +pub const SAR: Instruction = 0x1d; /// compute SHA3-256 hash pub const SHA3: Instruction = 0x20; @@ -589,4 +598,3 @@ pub const REVERT: Instruction = 0xfd; pub const STATICCALL: Instruction = 0xfa; /// halt execution and register account for later deletion pub const SUICIDE: Instruction = 0xff; - diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 05d1fb78853..160a2e5b1d3 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -224,7 +224,8 @@ impl Interpreter { (instruction == instructions::CREATE2 && !schedule.have_create2) || (instruction == instructions::STATICCALL && !schedule.have_static_call) || ((instruction == instructions::RETURNDATACOPY || instruction == instructions::RETURNDATASIZE) && !schedule.have_return_data) || - (instruction == instructions::REVERT && !schedule.have_revert) { + (instruction == instructions::REVERT && !schedule.have_revert) || + ((instruction == instructions::SHL || instruction == instructions::SHR || instruction == instructions::SAR) && !schedule.have_bitwise_shifting) { return Err(vm::Error::BadInstruction { instruction: instruction @@ -871,6 +872,58 @@ impl Interpreter { }); } }, + instructions::SHL => { + const CONST_256: U256 = U256([256, 0, 0, 0]); + + let shift = stack.pop_back(); + let value = stack.pop_back(); + + let result = if shift >= CONST_256 { + U256::zero() + } else { + value << (shift.as_u32() as usize) + }; + stack.push(result); + }, + instructions::SHR => { + const CONST_256: U256 = U256([256, 0, 0, 0]); + + let shift = stack.pop_back(); + let value = stack.pop_back(); + + let result = if shift >= CONST_256 { + U256::zero() + } else { + value >> (shift.as_u32() as usize) + }; + stack.push(result); + }, + instructions::SAR => { + // We cannot use get_and_reset_sign/set_sign here, because the rounding looks different. + + const CONST_256: U256 = U256([256, 0, 0, 0]); + const CONST_HIBIT: U256 = U256([0, 0, 0, 0x8000000000000000]); + + let shift = stack.pop_back(); + let value = stack.pop_back(); + let sign = value & CONST_HIBIT != U256::zero(); + + let result = if shift >= CONST_256 { + if sign { + U256::max_value() + } else { + U256::zero() + } + } else { + let shift = shift.as_u32() as usize; + let mut shifted = value >> shift; + if sign { + shifted = shifted | (U256::max_value() << (256 - shift)); + } + shifted + }; + stack.push(result); + }, _ => { return Err(vm::Error::BadInstruction { instruction: instruction diff --git a/ethcore/evm/src/tests.rs b/ethcore/evm/src/tests.rs index 3758156e21a..9058d073e80 100644 --- a/ethcore/evm/src/tests.rs +++ b/ethcore/evm/src/tests.rs @@ -787,6 +787,273 @@ fn test_create_in_staticcall(factory: super::Factory) { assert_eq!(ext.calls.len(), 0); } +evm_test!{test_shl: test_shl_int} +fn test_shl(factory: super::Factory) { + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "0000000000000000000000000000000000000000000000000000000000000001", + "00", + "0000000000000000000000000000000000000000000000000000000000000001"); + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "0000000000000000000000000000000000000000000000000000000000000001", + "01", + "0000000000000000000000000000000000000000000000000000000000000002"); + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "0000000000000000000000000000000000000000000000000000000000000001", + "ff", + "8000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "0000000000000000000000000000000000000000000000000000000000000001", + "0100", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "0000000000000000000000000000000000000000000000000000000000000001", + "0101", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "00", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "01", + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "ff", + "8000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0100", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "0000000000000000000000000000000000000000000000000000000000000000", + "01", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1b, + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "01", + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); +} + +evm_test!{test_shr: test_shr_int} +fn test_shr(factory: super::Factory) { + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "0000000000000000000000000000000000000000000000000000000000000001", + "00", + "0000000000000000000000000000000000000000000000000000000000000001"); + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "0000000000000000000000000000000000000000000000000000000000000001", + "01", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "8000000000000000000000000000000000000000000000000000000000000000", + "01", + "4000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "8000000000000000000000000000000000000000000000000000000000000000", + "ff", + "0000000000000000000000000000000000000000000000000000000000000001"); + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "8000000000000000000000000000000000000000000000000000000000000000", + "0100", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "8000000000000000000000000000000000000000000000000000000000000000", + "0101", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "00", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "01", + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "ff", + "0000000000000000000000000000000000000000000000000000000000000001"); + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0100", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1c, + "0000000000000000000000000000000000000000000000000000000000000000", + "01", + "0000000000000000000000000000000000000000000000000000000000000000"); +} + +evm_test!{test_sar: test_sar_int} +fn test_sar(factory: super::Factory) { + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "0000000000000000000000000000000000000000000000000000000000000001", + "00", + "0000000000000000000000000000000000000000000000000000000000000001"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "0000000000000000000000000000000000000000000000000000000000000001", + "01", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "8000000000000000000000000000000000000000000000000000000000000000", + "01", + "c000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "8000000000000000000000000000000000000000000000000000000000000000", + "ff", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "8000000000000000000000000000000000000000000000000000000000000000", + "0100", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "8000000000000000000000000000000000000000000000000000000000000000", + "0101", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "00", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "01", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "ff", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0100", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "0000000000000000000000000000000000000000000000000000000000000000", + "01", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "4000000000000000000000000000000000000000000000000000000000000000", + "fe", + "0000000000000000000000000000000000000000000000000000000000000001"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "f8", + "000000000000000000000000000000000000000000000000000000000000007f"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "fe", + "0000000000000000000000000000000000000000000000000000000000000001"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "ff", + "0000000000000000000000000000000000000000000000000000000000000000"); + push_two_pop_one_constantinople_test( + &factory, + 0x1d, + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0100", + "0000000000000000000000000000000000000000000000000000000000000000"); +} + +fn push_two_pop_one_constantinople_test(factory: &super::Factory, opcode: u8, push1: &str, push2: &str, result: &str) { + let mut push1 = push1.from_hex().unwrap(); + let mut push2 = push2.from_hex().unwrap(); + assert!(push1.len() <= 32 && push1.len() != 0); + assert!(push2.len() <= 32 && push2.len() != 0); + + let mut code = Vec::new(); + code.push(0x60 + ((push1.len() - 1) as u8)); + code.append(&mut push1); + code.push(0x60 + ((push2.len() - 1) as u8)); + code.append(&mut push2); + code.push(opcode); + code.append(&mut vec![0x60, 0x00, 0x55]); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + let mut ext = FakeExt::new_constantinople(); + + let _ = { + let mut vm = factory.create(¶ms.gas); + test_finalize(vm.exec(params, &mut ext)).unwrap() + }; + + assert_store(&ext, 0, result); +} + fn assert_set_contains(set: &HashSet, val: &T) { let contains = set.contains(val); if !contains { @@ -799,4 +1066,3 @@ fn assert_set_contains(set: &HashSet, val: fn assert_store(ext: &FakeExt, pos: u64, val: &str) { assert_eq!(ext.store.get(&H256::from(pos)).unwrap(), &H256::from_str(val).unwrap()); } - diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 156ab8f15a8..ef69f4847bc 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -105,6 +105,8 @@ pub struct CommonParams { pub eip211_transition: BlockNumber, /// Number of first block where EIP-214 rules begin. pub eip214_transition: BlockNumber, + /// Number of first block where EIP-145 rules begin. + pub eip145_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. pub dust_protection_transition: BlockNumber, /// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled. @@ -152,6 +154,7 @@ impl CommonParams { schedule.have_revert = block_number >= self.eip140_transition; schedule.have_static_call = block_number >= self.eip214_transition; schedule.have_return_data = block_number >= self.eip211_transition; + schedule.have_bitwise_shifting = block_number >= self.eip145_transition; if block_number >= self.eip210_transition { schedule.blockhash_gas = 800; } @@ -198,16 +201,16 @@ impl From for CommonParams { eip155_transition: p.eip155_transition.map_or(0, Into::into), validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into), validate_chain_id_transition: p.validate_chain_id_transition.map_or(0, Into::into), - eip86_transition: p.eip86_transition.map_or( - BlockNumber::max_value(), + eip86_transition: p.eip86_transition.map_or_else( + BlockNumber::max_value, Into::into, ), - eip140_transition: p.eip140_transition.map_or( - BlockNumber::max_value(), + eip140_transition: p.eip140_transition.map_or_else( + BlockNumber::max_value, Into::into, ), - eip210_transition: p.eip210_transition.map_or( - BlockNumber::max_value(), + eip210_transition: p.eip210_transition.map_or_else( + BlockNumber::max_value, Into::into, ), eip210_contract_address: p.eip210_contract_address.map_or(0xf0.into(), Into::into), @@ -220,20 +223,24 @@ impl From for CommonParams { Into::into, ), eip210_contract_gas: p.eip210_contract_gas.map_or(1000000.into(), Into::into), - eip211_transition: p.eip211_transition.map_or( - BlockNumber::max_value(), + eip211_transition: p.eip211_transition.map_or_else( + BlockNumber::max_value, Into::into, ), - eip214_transition: p.eip214_transition.map_or( - BlockNumber::max_value(), + eip145_transition: p.eip145_transition.map_or_else( + BlockNumber::max_value, Into::into, ), - eip658_transition: p.eip658_transition.map_or( - BlockNumber::max_value(), + eip214_transition: p.eip214_transition.map_or_else( + BlockNumber::max_value, Into::into, ), - dust_protection_transition: p.dust_protection_transition.map_or( - BlockNumber::max_value(), + eip658_transition: p.eip658_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), + dust_protection_transition: p.dust_protection_transition.map_or_else( + BlockNumber::max_value, Into::into, ), nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into), @@ -245,8 +252,8 @@ impl From for CommonParams { max_transaction_size: p.max_transaction_size.map_or(MAX_TRANSACTION_SIZE, Into::into), max_code_size_transition: p.max_code_size_transition.map_or(0, Into::into), transaction_permission_contract: p.transaction_permission_contract.map(Into::into), - wasm_activation_transition: p.wasm_activation_transition.map_or( - BlockNumber::max_value(), + wasm_activation_transition: p.wasm_activation_transition.map_or_else( + BlockNumber::max_value, Into::into ), } diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index 6cfabed0df3..a0085ef1ece 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -109,6 +109,8 @@ pub struct Schedule { pub have_static_call: bool, /// RETURNDATA and RETURNDATASIZE opcodes enabled. pub have_return_data: bool, + /// SHL, SHR, SAR opcodes enabled. + pub have_bitwise_shifting: bool, /// Kill basic accounts below this balance if touched. pub kill_dust: CleanDustMode, /// Enable EIP-86 rules @@ -194,6 +196,7 @@ impl Schedule { have_create2: false, have_revert: false, have_return_data: false, + have_bitwise_shifting: false, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -250,6 +253,13 @@ impl Schedule { schedule } + /// Schedule for the Constantinople fork of the Ethereum main net. + pub fn new_constantinople() -> Schedule { + let mut schedule = Self::new_byzantium(); + schedule.have_bitwise_shifting = true; + schedule + } + fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule { Schedule { exceptional_failed_code_deposit: efcd, @@ -257,6 +267,7 @@ impl Schedule { have_create2: false, have_revert: false, have_return_data: false, + have_bitwise_shifting: false, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -328,4 +339,3 @@ fn schedule_evm_assumptions() { assert_eq!(s1.quad_coeff_div, 512); assert_eq!(s2.quad_coeff_div, 512); } - diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index ce47121458f..daf46be0f07 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -88,6 +88,13 @@ impl FakeExt { ext } + /// New fake externalities with constantinople schedule rules + pub fn new_constantinople() -> Self { + let mut ext = FakeExt::default(); + ext.schedule = Schedule::new_constantinople(); + ext + } + /// Alter fake externalities to allow wasm pub fn with_wasm(mut self) -> Self { self.schedule.wasm = Some(Default::default()); diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index ce47086df17..0addf52e4af 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -85,6 +85,9 @@ pub struct Params { #[serde(rename="eip211Transition")] pub eip211_transition: Option, /// See `CommonParams` docs. + #[serde(rename="eip145Transition")] + pub eip145_transition: Option, + /// See `CommonParams` docs. #[serde(rename="eip214Transition")] pub eip214_transition: Option, /// See `CommonParams` docs. From e30839e85ff74cd5eb087ef19a48d70afd1fd285 Mon Sep 17 00:00:00 2001 From: Toralf Wittner Date: Sat, 5 May 2018 11:02:33 +0200 Subject: [PATCH 36/95] Consolidate crypto functionality in `ethcore-crypto`. (#8432) * Consolidate crypto functionality in `ethcore-crypto`. - Move `ecdh`/`ecies` modules to `ethkey`. - Refactor `ethcore-crypto` to use file per module. - Replace `subtle` with `ethcore_crypto::is_equal`. - Add `aes_gcm` module to `ethcore-crypto`. * Rename `aes::{encrypt,decrypt,decrypt_cbc}` ... ... to `aes::{encrypt_128_ctr,decrypt_128_ctr,decrypt_128_cbc}`. --- Cargo.lock | 26 +- ethcore/Cargo.toml | 2 +- ethcore/benches/evm.rs | 9 +- ethcore/crypto/Cargo.toml | 10 +- ethcore/crypto/src/aes.rs | 54 ++++ ethcore/crypto/src/aes_gcm.rs | 199 ++++++++++++ ethcore/crypto/src/digest.rs | 109 +++++++ ethcore/crypto/src/error.rs | 83 +++++ ethcore/crypto/src/hmac.rs | 89 ++++++ ethcore/crypto/src/lib.rs | 299 +----------------- ethcore/crypto/src/pbkdf2.rs | 29 ++ ethcore/crypto/src/scrypt.rs | 39 +++ ethcore/private-tx/src/encryptor.rs | 7 +- ethcore/src/builtin.rs | 25 +- ethcore/src/lib.rs | 2 +- ethkey/Cargo.toml | 3 +- ethkey/src/crypto.rs | 189 +++++++++++ ethkey/src/extended.rs | 22 +- ethkey/src/lib.rs | 5 +- ethstore/Cargo.toml | 2 - ethstore/src/account/crypto.rs | 29 +- ethstore/src/account/safe_account.rs | 25 +- ethstore/src/accounts_dir/disk.rs | 6 +- ethstore/src/accounts_dir/vault.rs | 2 +- ethstore/src/error.rs | 25 +- ethstore/src/ethstore.rs | 2 +- ethstore/src/lib.rs | 2 - ethstore/src/presale.rs | 15 +- rpc/Cargo.toml | 1 - rpc/src/lib.rs | 1 - rpc/src/v1/helpers/ipfs.rs | 12 +- rpc/src/v1/helpers/secretstore.rs | 8 +- rpc/src/v1/impls/light/parity.rs | 4 +- rpc/src/v1/impls/parity.rs | 4 +- secret_store/src/key_server.rs | 35 +- .../client_sessions/decryption_session.rs | 4 +- .../src/key_server_cluster/io/handshake.rs | 2 +- .../src/key_server_cluster/io/message.rs | 4 +- .../key_server_cluster/jobs/decryption_job.rs | 2 +- secret_store/src/node_key_pair.rs | 5 +- secret_store/src/types/error.rs | 8 +- util/network-devp2p/src/connection.rs | 2 +- util/network-devp2p/src/handshake.rs | 2 +- util/network/src/error.rs | 16 +- whisper/Cargo.toml | 1 - whisper/src/lib.rs | 1 - whisper/src/rpc/crypto.rs | 109 ++----- whisper/src/rpc/filter.rs | 2 +- whisper/src/rpc/key_store.rs | 9 +- whisper/src/rpc/mod.rs | 4 +- 50 files changed, 1003 insertions(+), 542 deletions(-) create mode 100644 ethcore/crypto/src/aes.rs create mode 100644 ethcore/crypto/src/aes_gcm.rs create mode 100644 ethcore/crypto/src/digest.rs create mode 100644 ethcore/crypto/src/error.rs create mode 100644 ethcore/crypto/src/hmac.rs create mode 100644 ethcore/crypto/src/pbkdf2.rs create mode 100644 ethcore/crypto/src/scrypt.rs create mode 100644 ethkey/src/crypto.rs diff --git a/Cargo.lock b/Cargo.lock index 741cc3832ce..ceb14ff277c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -509,6 +509,7 @@ dependencies = [ "ethash 1.12.0", "ethcore-bloom-journal 0.1.0", "ethcore-bytes 0.1.0", + "ethcore-crypto 0.1.0", "ethcore-io 1.12.0", "ethcore-logger 1.12.0", "ethcore-miner 1.12.0", @@ -545,7 +546,6 @@ dependencies = [ "rlp 0.2.1", "rlp_compress 0.1.0", "rlp_derive 0.1.0", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", "stats 0.1.0", @@ -576,11 +576,10 @@ version = "0.1.0" name = "ethcore-crypto" version = "0.1.0" dependencies = [ - "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethkey 0.3.0", + "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.12.1 (git+https://github.com/paritytech/ring)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -925,13 +924,14 @@ dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", + "ethcore-crypto 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mem 0.1.0", "parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -966,13 +966,11 @@ dependencies = [ "parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2197,7 +2195,6 @@ dependencies = [ "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.2.1", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2362,7 +2359,6 @@ dependencies = [ "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.12.1 (git+https://github.com/paritytech/ring)", "rlp 0.2.1", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2621,6 +2617,11 @@ dependencies = [ "quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quick-error" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.5.1" @@ -3035,11 +3036,6 @@ name = "strsim" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "subtle" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "syn" version = "0.13.1" @@ -3927,6 +3923,7 @@ dependencies = [ "checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3" "checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4" "checksum quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29cec87bc2816766d7e4168302d505dd06b0a825aed41b00633d296e922e02dd" +"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" "checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" "checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" @@ -3973,7 +3970,6 @@ dependencies = [ "checksum snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7f6353c2ee5407358d063a14cccc1630804527090a6fb5a9489ce4924280fb" "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" "checksum syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a8f5e3aaa79319573d19938ea38d068056b826db9883a5d47f86c1cecc688f0e" "checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c" diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 147d9484c70..71c84a293f9 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -20,6 +20,7 @@ fetch = { path = "../util/fetch" } hashdb = { path = "../util/hashdb" } memorydb = { path = "../util/memorydb" } patricia-trie = { path = "../util/patricia_trie" } +ethcore-crypto = { path = "crypto" } error-chain = { version = "0.11", default-features = false } ethcore-io = { path = "../util/io" } ethcore-logger = { path = "../logger" } @@ -56,7 +57,6 @@ util-error = { path = "../util/error" } snappy = { git = "https://github.com/paritytech/rust-snappy" } stop-guard = { path = "../util/stop-guard" } macros = { path = "../util/macros" } -rust-crypto = "0.2.34" rustc-hex = "1.0" stats = { path = "../util/stats" } trace-time = { path = "../util/trace-time" } diff --git a/ethcore/benches/evm.rs b/ethcore/benches/evm.rs index 324e3382e57..9fe2657d614 100644 --- a/ethcore/benches/evm.rs +++ b/ethcore/benches/evm.rs @@ -20,7 +20,7 @@ extern crate test; extern crate ethcore_util as util; extern crate rand; extern crate bn; -extern crate crypto; +extern crate ethcore_crypto; extern crate ethkey; extern crate rustc_hex; extern crate ethcore_bigint; @@ -61,16 +61,13 @@ fn bn_128_mul(b: &mut Bencher) { #[bench] fn sha256(b: &mut Bencher) { - use crypto::sha2::Sha256; - use crypto::digest::Digest; + use ethcore_crypto::digest::sha256; let mut input: [u8; 256] = [0; 256]; let mut out = [0; 32]; b.iter(|| { - let mut sha = Sha256::new(); - sha.input(&input); - sha.result(&mut input[0..32]); + sha256(&input); }); } diff --git a/ethcore/crypto/Cargo.toml b/ethcore/crypto/Cargo.toml index c3a2191b55a..4fe023f25c4 100644 --- a/ethcore/crypto/Cargo.toml +++ b/ethcore/crypto/Cargo.toml @@ -4,13 +4,9 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] +ethereum-types = "0.3" +quick-error = "1.2" +ring = "0.12" rust-crypto = "0.2.36" tiny-keccak = "1.3" -eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", optional = true } -ethkey = { path = "../../ethkey", optional = true } -ethereum-types = "0.3" -subtle = "0.5" -[features] -default = ["secp256k1"] -secp256k1 = ["eth-secp256k1", "ethkey"] diff --git a/ethcore/crypto/src/aes.rs b/ethcore/crypto/src/aes.rs new file mode 100644 index 00000000000..79a8dcc86d6 --- /dev/null +++ b/ethcore/crypto/src/aes.rs @@ -0,0 +1,54 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use error::SymmError; +use rcrypto::blockmodes::{CtrMode, CbcDecryptor, PkcsPadding}; +use rcrypto::aessafe::{AesSafe128Encryptor, AesSafe128Decryptor}; +use rcrypto::symmetriccipher::{Encryptor, Decryptor}; +use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer, WriteBuffer}; + +/// Encrypt a message (CTR mode). +/// +/// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. +/// An error is returned if the input lengths are invalid. +pub fn encrypt_128_ctr(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) -> Result<(), SymmError> { + let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec()); + encryptor.encrypt(&mut RefReadBuffer::new(plain), &mut RefWriteBuffer::new(dest), true)?; + Ok(()) +} + +/// Decrypt a message (CTR mode). +/// +/// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. +/// An error is returned if the input lengths are invalid. +pub fn decrypt_128_ctr(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) -> Result<(), SymmError> { + let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec()); + encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true)?; + Ok(()) +} + +/// Decrypt a message (CBC mode). +/// +/// Key (`k`) length and initialisation vector (`iv`) length have to be 16 bytes each. +/// An error is returned if the input lengths are invalid. +pub fn decrypt_128_cbc(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) -> Result { + let mut encryptor = CbcDecryptor::new(AesSafe128Decryptor::new(k), PkcsPadding, iv.to_vec()); + let len = dest.len(); + let mut buffer = RefWriteBuffer::new(dest); + encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut buffer, true)?; + Ok(len - buffer.remaining()) +} + diff --git a/ethcore/crypto/src/aes_gcm.rs b/ethcore/crypto/src/aes_gcm.rs new file mode 100644 index 00000000000..178b5d1e12c --- /dev/null +++ b/ethcore/crypto/src/aes_gcm.rs @@ -0,0 +1,199 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use error::SymmError; +use ring; + +enum Mode { Aes128Gcm, Aes256Gcm } + +/// AES GCM encryptor. +pub struct Encryptor<'a> { + mode: Mode, + key: ring::aead::SealingKey, + ad: &'a [u8], + offset: usize, +} + +impl<'a> Encryptor<'a> { + pub fn aes_128_gcm(key: &[u8; 16]) -> Result, SymmError> { + let sk = ring::aead::SealingKey::new(&ring::aead::AES_128_GCM, key)?; + Ok(Encryptor { + mode: Mode::Aes128Gcm, + key: sk, + ad: &[], + offset: 0, + }) + } + + pub fn aes_256_gcm(key: &[u8; 32]) -> Result, SymmError> { + let sk = ring::aead::SealingKey::new(&ring::aead::AES_256_GCM, key)?; + Ok(Encryptor { + mode: Mode::Aes256Gcm, + key: sk, + ad: &[], + offset: 0, + }) + } + + /// Optional associated data which is not encrypted but authenticated. + pub fn associate(&mut self, data: &'a [u8]) -> &mut Self { + self.ad = data; + self + } + + /// Optional offset value. Only the slice `[offset..]` will be encrypted. + pub fn offset(&mut self, off: usize) -> &mut Self { + self.offset = off; + self + } + + /// Please note that the pair (key, nonce) must never be reused. Using random nonces + /// limits the number of messages encrypted with the same key to 2^32 (cf. [[1]]) + /// + /// [1]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf + pub fn encrypt(&self, nonce: &[u8; 12], mut data: Vec) -> Result, SymmError> { + if self.offset > data.len() { + return Err(SymmError::offset_error(self.offset)) + } + let tag_len = match self.mode { + Mode::Aes128Gcm => ring::aead::AES_128_GCM.tag_len(), + Mode::Aes256Gcm => ring::aead::AES_256_GCM.tag_len(), + }; + data.extend(::std::iter::repeat(0).take(tag_len)); + let len = ring::aead::seal_in_place(&self.key, nonce, self.ad, &mut data[self.offset ..], tag_len)?; + data.truncate(self.offset + len); + Ok(data) + } +} + +/// AES GCM decryptor. +pub struct Decryptor<'a> { + key: ring::aead::OpeningKey, + ad: &'a [u8], + offset: usize, +} + +impl<'a> Decryptor<'a> { + pub fn aes_128_gcm(key: &[u8; 16]) -> Result, SymmError> { + let ok = ring::aead::OpeningKey::new(&ring::aead::AES_128_GCM, key)?; + Ok(Decryptor { + key: ok, + ad: &[], + offset: 0, + }) + } + + pub fn aes_256_gcm(key: &[u8; 32]) -> Result, SymmError> { + let ok = ring::aead::OpeningKey::new(&ring::aead::AES_256_GCM, key)?; + Ok(Decryptor { + key: ok, + ad: &[], + offset: 0, + }) + } + + /// Optional associated data which is not encrypted but authenticated. + pub fn associate(&mut self, data: &'a [u8]) -> &mut Self { + self.ad = data; + self + } + + /// Optional offset value. Only the slice `[offset..]` will be decrypted. + pub fn offset(&mut self, off: usize) -> &mut Self { + self.offset = off; + self + } + + pub fn decrypt(&self, nonce: &[u8; 12], mut data: Vec) -> Result, SymmError> { + if self.offset > data.len() { + return Err(SymmError::offset_error(self.offset)) + } + let len = ring::aead::open_in_place(&self.key, nonce, self.ad, 0, &mut data[self.offset ..])?.len(); + data.truncate(self.offset + len); + Ok(data) + } +} + +#[cfg(test)] +mod tests { + use super::{Encryptor, Decryptor}; + + #[test] + fn aes_gcm_128() { + let secret = b"1234567890123456"; + let nonce = b"123456789012"; + let message = b"So many books, so little time"; + + let ciphertext = Encryptor::aes_128_gcm(secret) + .unwrap() + .encrypt(nonce, message.to_vec()) + .unwrap(); + + assert!(ciphertext != message); + + let plaintext = Decryptor::aes_128_gcm(secret) + .unwrap() + .decrypt(nonce, ciphertext) + .unwrap(); + + assert_eq!(plaintext, message) + } + + #[test] + fn aes_gcm_256() { + let secret = b"12345678901234567890123456789012"; + let nonce = b"123456789012"; + let message = b"So many books, so little time"; + + let ciphertext = Encryptor::aes_256_gcm(secret) + .unwrap() + .encrypt(nonce, message.to_vec()) + .unwrap(); + + assert!(ciphertext != message); + + let plaintext = Decryptor::aes_256_gcm(secret) + .unwrap() + .decrypt(nonce, ciphertext) + .unwrap(); + + assert_eq!(plaintext, message) + } + + #[test] + fn aes_gcm_256_offset() { + let secret = b"12345678901234567890123456789012"; + let nonce = b"123456789012"; + let message = b"prefix data; So many books, so little time"; + + let ciphertext = Encryptor::aes_256_gcm(secret) + .unwrap() + .offset(13) // length of "prefix data; " + .encrypt(nonce, message.to_vec()) + .unwrap(); + + assert!(ciphertext != &message[..]); + + let plaintext = Decryptor::aes_256_gcm(secret) + .unwrap() + .offset(13) // length of "prefix data; " + .decrypt(nonce, ciphertext) + .unwrap(); + + assert_eq!(plaintext, &message[..]) + } +} + diff --git a/ethcore/crypto/src/digest.rs b/ethcore/crypto/src/digest.rs new file mode 100644 index 00000000000..095a8ca2620 --- /dev/null +++ b/ethcore/crypto/src/digest.rs @@ -0,0 +1,109 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use rcrypto::ripemd160; +use ring::digest::{self, Context, SHA256, SHA512}; +use std::marker::PhantomData; +use std::ops::Deref; + +/// The message digest. +pub struct Digest(InnerDigest, PhantomData); + +enum InnerDigest { + Ring(digest::Digest), + Ripemd160([u8; 20]), +} + +impl Deref for Digest { + type Target = [u8]; + fn deref(&self) -> &Self::Target { + match self.0 { + InnerDigest::Ring(ref d) => d.as_ref(), + InnerDigest::Ripemd160(ref d) => &d[..] + } + } +} + +/// Single-step sha256 digest computation. +pub fn sha256(data: &[u8]) -> Digest { + Digest(InnerDigest::Ring(digest::digest(&SHA256, data)), PhantomData) +} + +/// Single-step sha512 digest computation. +pub fn sha512(data: &[u8]) -> Digest { + Digest(InnerDigest::Ring(digest::digest(&SHA512, data)), PhantomData) +} + +/// Single-step ripemd160 digest computation. +pub fn ripemd160(data: &[u8]) -> Digest { + let mut hasher = Hasher::ripemd160(); + hasher.update(data); + hasher.finish() +} + +pub enum Sha256 {} +pub enum Sha512 {} +pub enum Ripemd160 {} + +/// Stateful digest computation. +pub struct Hasher(Inner, PhantomData); + +enum Inner { + Ring(Context), + Ripemd160(ripemd160::Ripemd160) +} + +impl Hasher { + pub fn sha256() -> Hasher { + Hasher(Inner::Ring(Context::new(&SHA256)), PhantomData) + } +} + +impl Hasher { + pub fn sha512() -> Hasher { + Hasher(Inner::Ring(Context::new(&SHA512)), PhantomData) + } +} + +impl Hasher { + pub fn ripemd160() -> Hasher { + Hasher(Inner::Ripemd160(ripemd160::Ripemd160::new()), PhantomData) + } +} + +impl Hasher { + pub fn update(&mut self, data: &[u8]) { + match self.0 { + Inner::Ring(ref mut ctx) => ctx.update(data), + Inner::Ripemd160(ref mut ctx) => { + use rcrypto::digest::Digest; + ctx.input(data) + } + } + } + + pub fn finish(self) -> Digest { + match self.0 { + Inner::Ring(ctx) => Digest(InnerDigest::Ring(ctx.finish()), PhantomData), + Inner::Ripemd160(mut ctx) => { + use rcrypto::digest::Digest; + let mut d = [0; 20]; + ctx.result(&mut d); + Digest(InnerDigest::Ripemd160(d), PhantomData) + } + } + } +} diff --git a/ethcore/crypto/src/error.rs b/ethcore/crypto/src/error.rs new file mode 100644 index 00000000000..4de3b80036d --- /dev/null +++ b/ethcore/crypto/src/error.rs @@ -0,0 +1,83 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use rcrypto; +use ring; + +quick_error! { + #[derive(Debug)] + pub enum Error { + Scrypt(e: ScryptError) { + cause(e) + from() + } + Symm(e: SymmError) { + cause(e) + from() + } + } +} + +quick_error! { + #[derive(Debug)] + pub enum ScryptError { + // log(N) < r / 16 + InvalidN { + display("Invalid N argument of the scrypt encryption") + } + // p <= (2^31-1 * 32)/(128 * r) + InvalidP { + display("Invalid p argument of the scrypt encryption") + } + } +} + +quick_error! { + #[derive(Debug)] + pub enum SymmError wraps PrivSymmErr { + RustCrypto(e: rcrypto::symmetriccipher::SymmetricCipherError) { + display("symmetric crypto error") + from() + } + Ring(e: ring::error::Unspecified) { + display("symmetric crypto error") + cause(e) + from() + } + Offset(x: usize) { + display("offset {} greater than slice length", x) + } + } +} + +impl SymmError { + pub(crate) fn offset_error(x: usize) -> SymmError { + SymmError(PrivSymmErr::Offset(x)) + } +} + +impl From for SymmError { + fn from(e: ring::error::Unspecified) -> SymmError { + SymmError(PrivSymmErr::Ring(e)) + } +} + +impl From for SymmError { + fn from(e: rcrypto::symmetriccipher::SymmetricCipherError) -> SymmError { + SymmError(PrivSymmErr::RustCrypto(e)) + } +} + diff --git a/ethcore/crypto/src/hmac.rs b/ethcore/crypto/src/hmac.rs new file mode 100644 index 00000000000..7327250442d --- /dev/null +++ b/ethcore/crypto/src/hmac.rs @@ -0,0 +1,89 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use digest; +use ring::digest::{SHA256, SHA512}; +use ring::hmac::{self, SigningContext}; +use std::marker::PhantomData; +use std::ops::Deref; + +/// HMAC signature. +pub struct Signature(hmac::Signature, PhantomData); + +impl Deref for Signature { + type Target = [u8]; + fn deref(&self) -> &Self::Target { + self.0.as_ref() + } +} + +/// HMAC signing key. +pub struct SigKey(hmac::SigningKey, PhantomData); + +impl SigKey { + pub fn sha256(key: &[u8]) -> SigKey { + SigKey(hmac::SigningKey::new(&SHA256, key), PhantomData) + } +} + +impl SigKey { + pub fn sha512(key: &[u8]) -> SigKey { + SigKey(hmac::SigningKey::new(&SHA512, key), PhantomData) + } +} + +/// Compute HMAC signature of `data`. +pub fn sign(k: &SigKey, data: &[u8]) -> Signature { + Signature(hmac::sign(&k.0, data), PhantomData) +} + +/// Stateful HMAC computation. +pub struct Signer(SigningContext, PhantomData); + +impl Signer { + pub fn with(key: &SigKey) -> Signer { + Signer(hmac::SigningContext::with_key(&key.0), PhantomData) + } + + pub fn update(&mut self, data: &[u8]) { + self.0.update(data) + } + + pub fn sign(self) -> Signature { + Signature(self.0.sign(), PhantomData) + } +} + +/// HMAC signature verification key. +pub struct VerifyKey(hmac::VerificationKey, PhantomData); + +impl VerifyKey { + pub fn sha256(key: &[u8]) -> VerifyKey { + VerifyKey(hmac::VerificationKey::new(&SHA256, key), PhantomData) + } +} + +impl VerifyKey { + pub fn sha512(key: &[u8]) -> VerifyKey { + VerifyKey(hmac::VerificationKey::new(&SHA512, key), PhantomData) + } +} + +/// Verify HMAC signature of `data`. +pub fn verify(k: &VerifyKey, data: &[u8], sig: &[u8]) -> bool { + hmac::verify(&k.0, data, sig).is_ok() +} + diff --git a/ethcore/crypto/src/lib.rs b/ethcore/crypto/src/lib.rs index caa4cf77c4d..0ee42e35991 100644 --- a/ethcore/crypto/src/lib.rs +++ b/ethcore/crypto/src/lib.rs @@ -18,23 +18,22 @@ extern crate crypto as rcrypto; extern crate ethereum_types; -extern crate subtle; +#[macro_use] +extern crate quick_error; +extern crate ring; extern crate tiny_keccak; -#[cfg(feature = "secp256k1")] -extern crate secp256k1; -#[cfg(feature = "secp256k1")] -extern crate ethkey; +pub mod aes; +pub mod aes_gcm; +pub mod error; +pub mod scrypt; +pub mod digest; +pub mod hmac; +pub mod pbkdf2; -use std::fmt; -use tiny_keccak::Keccak; -use rcrypto::pbkdf2::pbkdf2; -use rcrypto::scrypt::{scrypt, ScryptParams}; -use rcrypto::sha2::Sha256; -use rcrypto::hmac::Hmac; +pub use error::Error; -#[cfg(feature = "secp256k1")] -use secp256k1::Error as SecpError; +use tiny_keccak::Keccak; pub const KEY_LENGTH: usize = 32; pub const KEY_ITERATIONS: usize = 10240; @@ -43,65 +42,6 @@ pub const KEY_LENGTH_AES: usize = KEY_LENGTH / 2; /// Default authenticated data to use (in RPC). pub const DEFAULT_MAC: [u8; 2] = [0, 0]; -#[derive(PartialEq, Debug)] -pub enum ScryptError { - // log(N) < r / 16 - InvalidN, - // p <= (2^31-1 * 32)/(128 * r) - InvalidP, -} - -impl fmt::Display for ScryptError { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let s = match *self { - ScryptError::InvalidN => "Invalid N argument of the scrypt encryption" , - ScryptError::InvalidP => "Invalid p argument of the scrypt encryption", - }; - - write!(f, "{}", s) - } -} - -#[derive(PartialEq, Debug)] -pub enum Error { - #[cfg(feature = "secp256k1")] - Secp(SecpError), - Scrypt(ScryptError), - InvalidMessage, -} - -impl From for Error { - fn from(err: ScryptError) -> Self { - Error::Scrypt(err) - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - let s = match *self { - #[cfg(feature = "secp256k1")] - Error::Secp(ref err) => err.to_string(), - Error::Scrypt(ref err) => err.to_string(), - Error::InvalidMessage => "Invalid message".into(), - }; - - write!(f, "{}", s) - } -} - -impl Into for Error { - fn into(self) -> String { - format!("{}", self) - } -} - -#[cfg(feature = "secp256k1")] -impl From for Error { - fn from(e: SecpError) -> Self { - Error::Secp(e) - } -} - pub trait Keccak256 { fn keccak256(&self) -> T where T: Sized; } @@ -117,33 +57,13 @@ impl Keccak256<[u8; 32]> for T where T: AsRef<[u8]> { } pub fn derive_key_iterations(password: &str, salt: &[u8; 32], c: u32) -> (Vec, Vec) { - let mut h_mac = Hmac::new(Sha256::new(), password.as_bytes()); - let mut derived_key = vec![0u8; KEY_LENGTH]; - pbkdf2(&mut h_mac, salt, c, &mut derived_key); + let mut derived_key = [0u8; KEY_LENGTH]; + pbkdf2::sha256(c, pbkdf2::Salt(salt), pbkdf2::Secret(password.as_bytes()), &mut derived_key); let derived_right_bits = &derived_key[0..KEY_LENGTH_AES]; let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH]; (derived_right_bits.to_vec(), derived_left_bits.to_vec()) } -pub fn derive_key_scrypt(password: &str, salt: &[u8; 32], n: u32, p: u32, r: u32) -> Result<(Vec, Vec), Error> { - // sanity checks - let log_n = (32 - n.leading_zeros() - 1) as u8; - if log_n as u32 >= r * 16 { - return Err(Error::Scrypt(ScryptError::InvalidN)); - } - - if p as u64 > ((u32::max_value() as u64 - 1) * 32)/(128 * (r as u64)) { - return Err(Error::Scrypt(ScryptError::InvalidP)); - } - - let mut derived_key = vec![0u8; KEY_LENGTH]; - let scrypt_params = ScryptParams::new(log_n, r, p); - scrypt(password.as_bytes(), salt, &scrypt_params, &mut derived_key); - let derived_right_bits = &derived_key[0..KEY_LENGTH_AES]; - let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH]; - Ok((derived_right_bits.to_vec(), derived_left_bits.to_vec())) -} - pub fn derive_mac(derived_left_bits: &[u8], cipher_text: &[u8]) -> Vec { let mut mac = vec![0u8; KEY_LENGTH_AES + cipher_text.len()]; mac[0..KEY_LENGTH_AES].copy_from_slice(derived_left_bits); @@ -151,194 +71,7 @@ pub fn derive_mac(derived_left_bits: &[u8], cipher_text: &[u8]) -> Vec { mac } -/// AES encryption -pub mod aes { - use rcrypto::blockmodes::{CtrMode, CbcDecryptor, PkcsPadding}; - use rcrypto::aessafe::{AesSafe128Encryptor, AesSafe128Decryptor}; - use rcrypto::symmetriccipher::{Encryptor, Decryptor, SymmetricCipherError}; - use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer, WriteBuffer}; - - /// Encrypt a message (CTR mode) - pub fn encrypt(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) { - let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec()); - encryptor.encrypt(&mut RefReadBuffer::new(plain), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding"); - } - - /// Decrypt a message (CTR mode) - pub fn decrypt(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) { - let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec()); - encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding"); - } - - - /// Decrypt a message using cbc mode - pub fn decrypt_cbc(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) -> Result { - let mut encryptor = CbcDecryptor::new(AesSafe128Decryptor::new(k), PkcsPadding, iv.to_vec()); - let len = dest.len(); - let mut buffer = RefWriteBuffer::new(dest); - encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut buffer, true)?; - Ok(len - buffer.remaining()) - } -} - -/// ECDH functions -#[cfg(feature = "secp256k1")] -pub mod ecdh { - use secp256k1::{ecdh, key, Error as SecpError}; - use ethkey::{Secret, Public, SECP256K1}; - use Error; - - /// Agree on a shared secret - pub fn agree(secret: &Secret, public: &Public) -> Result { - let context = &SECP256K1; - let pdata = { - let mut temp = [4u8; 65]; - (&mut temp[1..65]).copy_from_slice(&public[0..64]); - temp - }; - - let publ = key::PublicKey::from_slice(context, &pdata)?; - let sec = key::SecretKey::from_slice(context, &secret)?; - let shared = ecdh::SharedSecret::new_raw(context, &publ, &sec); - - Secret::from_unsafe_slice(&shared[0..32]) - .map_err(|_| Error::Secp(SecpError::InvalidSecretKey)) - } -} - -/// ECIES function -#[cfg(feature = "secp256k1")] -pub mod ecies { - use rcrypto::digest::Digest; - use rcrypto::sha2::Sha256; - use rcrypto::hmac::Hmac; - use rcrypto::mac::Mac; - use ethereum_types::H128; - use ethkey::{Random, Generator, Public, Secret}; - use {Error, ecdh, aes}; - - /// Encrypt a message with a public key, writing an HMAC covering both - /// the plaintext and authenticated data. - /// - /// Authenticated data may be empty. - pub fn encrypt(public: &Public, auth_data: &[u8], plain: &[u8]) -> Result, Error> { - let r = Random.generate() - .expect("context known to have key-generation capabilities; qed"); - - let z = ecdh::agree(r.secret(), public)?; - let mut key = [0u8; 32]; - let mut mkey = [0u8; 32]; - kdf(&z, &[0u8; 0], &mut key); - let mut hasher = Sha256::new(); - let mkey_material = &key[16..32]; - hasher.input(mkey_material); - hasher.result(&mut mkey); - let ekey = &key[0..16]; - - let mut msg = vec![0u8; 1 + 64 + 16 + plain.len() + 32]; - msg[0] = 0x04u8; - { - let msgd = &mut msg[1..]; - msgd[0..64].copy_from_slice(r.public()); - let iv = H128::random(); - msgd[64..80].copy_from_slice(&iv); - { - let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())]; - aes::encrypt(ekey, &iv, plain, cipher); - } - let mut hmac = Hmac::new(Sha256::new(), &mkey); - { - let cipher_iv = &msgd[64..(64 + 16 + plain.len())]; - hmac.input(cipher_iv); - } - hmac.input(auth_data); - hmac.raw_result(&mut msgd[(64 + 16 + plain.len())..]); - } - Ok(msg) - } - - /// Decrypt a message with a secret key, checking HMAC for ciphertext - /// and authenticated data validity. - pub fn decrypt(secret: &Secret, auth_data: &[u8], encrypted: &[u8]) -> Result, Error> { - let meta_len = 1 + 64 + 16 + 32; - if encrypted.len() < meta_len || encrypted[0] < 2 || encrypted[0] > 4 { - return Err(Error::InvalidMessage); //invalid message: publickey - } - - let e = &encrypted[1..]; - let p = Public::from_slice(&e[0..64]); - let z = ecdh::agree(secret, &p)?; - let mut key = [0u8; 32]; - kdf(&z, &[0u8; 0], &mut key); - let ekey = &key[0..16]; - let mkey_material = &key[16..32]; - let mut hasher = Sha256::new(); - let mut mkey = [0u8; 32]; - hasher.input(mkey_material); - hasher.result(&mut mkey); - - let clen = encrypted.len() - meta_len; - let cipher_with_iv = &e[64..(64+16+clen)]; - let cipher_iv = &cipher_with_iv[0..16]; - let cipher_no_iv = &cipher_with_iv[16..]; - let msg_mac = &e[(64+16+clen)..]; - - // Verify tag - let mut hmac = Hmac::new(Sha256::new(), &mkey); - hmac.input(cipher_with_iv); - hmac.input(auth_data); - let mut mac = [0u8; 32]; - hmac.raw_result(&mut mac); - - // constant time compare to avoid timing attack. - if ::subtle::slices_equal(&mac[..], msg_mac) != 1 { - return Err(Error::InvalidMessage); - } - - let mut msg = vec![0u8; clen]; - aes::decrypt(ekey, cipher_iv, cipher_no_iv, &mut msg[..]); - Ok(msg) - } - - fn kdf(secret: &Secret, s1: &[u8], dest: &mut [u8]) { - let mut hasher = Sha256::new(); - // SEC/ISO/Shoup specify counter size SHOULD be equivalent - // to size of hash output, however, it also notes that - // the 4 bytes is okay. NIST specifies 4 bytes. - let mut ctr = 1u32; - let mut written = 0usize; - while written < dest.len() { - let ctrs = [(ctr >> 24) as u8, (ctr >> 16) as u8, (ctr >> 8) as u8, ctr as u8]; - hasher.input(&ctrs); - hasher.input(secret); - hasher.input(s1); - hasher.result(&mut dest[written..(written + 32)]); - hasher.reset(); - written += 32; - ctr += 1; - } - } -} - -#[cfg(test)] -mod tests { - use ethkey::{Random, Generator}; - use ecies; - - #[test] - fn ecies_shared() { - let kp = Random.generate().unwrap(); - let message = b"So many books, so little time"; - - let shared = b"shared"; - let wrong_shared = b"incorrect"; - let encrypted = ecies::encrypt(kp.public(), shared, message).unwrap(); - assert!(encrypted[..] != message[..]); - assert_eq!(encrypted[0], 0x04); - - assert!(ecies::decrypt(kp.secret(), wrong_shared, &encrypted).is_err()); - let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap(); - assert_eq!(decrypted[..message.len()], message[..]); - } +pub fn is_equal(a: &[u8], b: &[u8]) -> bool { + ring::constant_time::verify_slices_are_equal(a, b).is_ok() } diff --git a/ethcore/crypto/src/pbkdf2.rs b/ethcore/crypto/src/pbkdf2.rs new file mode 100644 index 00000000000..b4c993c5133 --- /dev/null +++ b/ethcore/crypto/src/pbkdf2.rs @@ -0,0 +1,29 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use ring; + +pub struct Salt<'a>(pub &'a [u8]); +pub struct Secret<'a>(pub &'a [u8]); + +pub fn sha256(iter: u32, salt: Salt, sec: Secret, out: &mut [u8; 32]) { + ring::pbkdf2::derive(&ring::digest::SHA256, iter, salt.0, sec.0, &mut out[..]) +} + +pub fn sha512(iter: u32, salt: Salt, sec: Secret, out: &mut [u8; 64]) { + ring::pbkdf2::derive(&ring::digest::SHA512, iter, salt.0, sec.0, &mut out[..]) +} + diff --git a/ethcore/crypto/src/scrypt.rs b/ethcore/crypto/src/scrypt.rs new file mode 100644 index 00000000000..684ab2c572c --- /dev/null +++ b/ethcore/crypto/src/scrypt.rs @@ -0,0 +1,39 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use error::ScryptError; +use rcrypto::scrypt::{scrypt, ScryptParams}; +use super::{KEY_LENGTH_AES, KEY_LENGTH}; + +pub fn derive_key(pass: &str, salt: &[u8; 32], n: u32, p: u32, r: u32) -> Result<(Vec, Vec), ScryptError> { + // sanity checks + let log_n = (32 - n.leading_zeros() - 1) as u8; + if log_n as u32 >= r * 16 { + return Err(ScryptError::InvalidN); + } + + if p as u64 > ((u32::max_value() as u64 - 1) * 32)/(128 * (r as u64)) { + return Err(ScryptError::InvalidP); + } + + let mut derived_key = vec![0u8; KEY_LENGTH]; + let scrypt_params = ScryptParams::new(log_n, r, p); + scrypt(pass.as_bytes(), salt, &scrypt_params, &mut derived_key); + let derived_right_bits = &derived_key[0..KEY_LENGTH_AES]; + let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH]; + Ok((derived_right_bits.to_vec(), derived_left_bits.to_vec())) +} + diff --git a/ethcore/private-tx/src/encryptor.rs b/ethcore/private-tx/src/encryptor.rs index 5d592de6032..b15acbee71b 100644 --- a/ethcore/private-tx/src/encryptor.rs +++ b/ethcore/private-tx/src/encryptor.rs @@ -217,7 +217,8 @@ impl Encryptor for SecretStoreEncryptor { // encrypt data let mut cypher = Vec::with_capacity(plain_data.len() + initialisation_vector.len()); cypher.extend(repeat(0).take(plain_data.len())); - crypto::aes::encrypt(&key, initialisation_vector, plain_data, &mut cypher); + crypto::aes::encrypt_128_ctr(&key, initialisation_vector, plain_data, &mut cypher) + .map_err(|e| ErrorKind::Encrypt(e.to_string()))?; cypher.extend_from_slice(&initialisation_vector); Ok(cypher) @@ -243,8 +244,8 @@ impl Encryptor for SecretStoreEncryptor { let (cypher, iv) = cypher.split_at(cypher_len - INIT_VEC_LEN); let mut plain_data = Vec::with_capacity(cypher_len - INIT_VEC_LEN); plain_data.extend(repeat(0).take(cypher_len - INIT_VEC_LEN)); - crypto::aes::decrypt(&key, &iv, cypher, &mut plain_data); - + crypto::aes::decrypt_128_ctr(&key, &iv, cypher, &mut plain_data) + .map_err(|e| ErrorKind::Decrypt(e.to_string()))?; Ok(plain_data) } } diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index c18e1f3cd30..a0833cfb5e6 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -18,9 +18,7 @@ use std::cmp::{max, min}; use std::io::{self, Read}; use byteorder::{ByteOrder, BigEndian}; -use crypto::sha2::Sha256 as Sha256Digest; -use crypto::ripemd160::Ripemd160 as Ripemd160Digest; -use crypto::digest::Digest; +use ethcore_crypto::digest; use num::{BigUint, Zero, One}; use hash::keccak; @@ -295,28 +293,17 @@ impl Impl for EcRecover { impl Impl for Sha256 { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { - let mut sha = Sha256Digest::new(); - sha.input(input); - - let mut out = [0; 32]; - sha.result(&mut out); - - output.write(0, &out); - + let d = digest::sha256(input); + output.write(0, &*d); Ok(()) } } impl Impl for Ripemd160 { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { - let mut sha = Ripemd160Digest::new(); - sha.input(input); - - let mut out = [0; 32]; - sha.result(&mut out[12..32]); - - output.write(0, &out); - + let hash = digest::ripemd160(input); + output.write(0, &[0; 12][..]); + output.write(12, &hash); Ok(()) } } diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 9bb2e94c1cc..b1782cb1d6c 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -63,9 +63,9 @@ extern crate bn; extern crate byteorder; extern crate crossbeam; extern crate common_types as types; -extern crate crypto; extern crate ethash; extern crate ethcore_bloom_journal as bloom_journal; +extern crate ethcore_crypto; extern crate ethcore_io as io; extern crate ethcore_bytes as bytes; extern crate ethcore_logger; diff --git a/ethkey/Cargo.toml b/ethkey/Cargo.toml index 335f92fe15a..d6698f86d9f 100644 --- a/ethkey/Cargo.toml +++ b/ethkey/Cargo.toml @@ -6,13 +6,14 @@ authors = ["Parity Technologies "] [dependencies] byteorder = "1.0" edit-distance = "2.0" +ethcore-crypto = { path = "../ethcore/crypto" } eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" } ethereum-types = "0.3" lazy_static = "1.0" log = "0.3" mem = { path = "../util/mem" } parity-wordlist = "1.2" +quick-error = "1.2" rand = "0.4" -rust-crypto = "0.2" rustc-hex = "1.0" tiny-keccak = "1.3" diff --git a/ethkey/src/crypto.rs b/ethkey/src/crypto.rs new file mode 100644 index 00000000000..739a463c072 --- /dev/null +++ b/ethkey/src/crypto.rs @@ -0,0 +1,189 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use secp256k1; +use std::io; +use ethcore_crypto::error::SymmError; + +quick_error! { + #[derive(Debug)] + pub enum Error { + Secp(e: secp256k1::Error) { + display("secp256k1 error: {}", e) + cause(e) + from() + } + Io(e: io::Error) { + display("i/o error: {}", e) + cause(e) + from() + } + InvalidMessage { + display("invalid message") + } + Symm(e: SymmError) { + cause(e) + from() + } + } +} + +/// ECDH functions +pub mod ecdh { + use secp256k1::{self, ecdh, key}; + use super::Error; + use {Secret, Public, SECP256K1}; + + /// Agree on a shared secret + pub fn agree(secret: &Secret, public: &Public) -> Result { + let context = &SECP256K1; + let pdata = { + let mut temp = [4u8; 65]; + (&mut temp[1..65]).copy_from_slice(&public[0..64]); + temp + }; + + let publ = key::PublicKey::from_slice(context, &pdata)?; + let sec = key::SecretKey::from_slice(context, &secret)?; + let shared = ecdh::SharedSecret::new_raw(context, &publ, &sec); + + Secret::from_unsafe_slice(&shared[0..32]) + .map_err(|_| Error::Secp(secp256k1::Error::InvalidSecretKey)) + } +} + +/// ECIES function +pub mod ecies { + use ethcore_crypto::{aes, digest, hmac, is_equal}; + use ethereum_types::H128; + use super::{ecdh, Error}; + use {Random, Generator, Public, Secret}; + + /// Encrypt a message with a public key, writing an HMAC covering both + /// the plaintext and authenticated data. + /// + /// Authenticated data may be empty. + pub fn encrypt(public: &Public, auth_data: &[u8], plain: &[u8]) -> Result, Error> { + let r = Random.generate()?; + let z = ecdh::agree(r.secret(), public)?; + let mut key = [0u8; 32]; + kdf(&z, &[0u8; 0], &mut key); + + let ekey = &key[0..16]; + let mkey = hmac::SigKey::sha256(&digest::sha256(&key[16..32])); + + let mut msg = vec![0u8; 1 + 64 + 16 + plain.len() + 32]; + msg[0] = 0x04u8; + { + let msgd = &mut msg[1..]; + msgd[0..64].copy_from_slice(r.public()); + let iv = H128::random(); + msgd[64..80].copy_from_slice(&iv); + { + let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())]; + aes::encrypt_128_ctr(ekey, &iv, plain, cipher)?; + } + let mut hmac = hmac::Signer::with(&mkey); + { + let cipher_iv = &msgd[64..(64 + 16 + plain.len())]; + hmac.update(cipher_iv); + } + hmac.update(auth_data); + let sig = hmac.sign(); + msgd[(64 + 16 + plain.len())..].copy_from_slice(&sig); + } + Ok(msg) + } + + /// Decrypt a message with a secret key, checking HMAC for ciphertext + /// and authenticated data validity. + pub fn decrypt(secret: &Secret, auth_data: &[u8], encrypted: &[u8]) -> Result, Error> { + let meta_len = 1 + 64 + 16 + 32; + if encrypted.len() < meta_len || encrypted[0] < 2 || encrypted[0] > 4 { + return Err(Error::InvalidMessage); //invalid message: publickey + } + + let e = &encrypted[1..]; + let p = Public::from_slice(&e[0..64]); + let z = ecdh::agree(secret, &p)?; + let mut key = [0u8; 32]; + kdf(&z, &[0u8; 0], &mut key); + + let ekey = &key[0..16]; + let mkey = hmac::SigKey::sha256(&digest::sha256(&key[16..32])); + + let clen = encrypted.len() - meta_len; + let cipher_with_iv = &e[64..(64+16+clen)]; + let cipher_iv = &cipher_with_iv[0..16]; + let cipher_no_iv = &cipher_with_iv[16..]; + let msg_mac = &e[(64+16+clen)..]; + + // Verify tag + let mut hmac = hmac::Signer::with(&mkey); + hmac.update(cipher_with_iv); + hmac.update(auth_data); + let mac = hmac.sign(); + + if !is_equal(&mac.as_ref()[..], msg_mac) { + return Err(Error::InvalidMessage); + } + + let mut msg = vec![0u8; clen]; + aes::decrypt_128_ctr(ekey, cipher_iv, cipher_no_iv, &mut msg[..])?; + Ok(msg) + } + + fn kdf(secret: &Secret, s1: &[u8], dest: &mut [u8]) { + // SEC/ISO/Shoup specify counter size SHOULD be equivalent + // to size of hash output, however, it also notes that + // the 4 bytes is okay. NIST specifies 4 bytes. + let mut ctr = 1u32; + let mut written = 0usize; + while written < dest.len() { + let mut hasher = digest::Hasher::sha256(); + let ctrs = [(ctr >> 24) as u8, (ctr >> 16) as u8, (ctr >> 8) as u8, ctr as u8]; + hasher.update(&ctrs); + hasher.update(secret); + hasher.update(s1); + let d = hasher.finish(); + &mut dest[written..(written + 32)].copy_from_slice(&d); + written += 32; + ctr += 1; + } + } +} + +#[cfg(test)] +mod tests { + use super::ecies; + use {Random, Generator}; + + #[test] + fn ecies_shared() { + let kp = Random.generate().unwrap(); + let message = b"So many books, so little time"; + + let shared = b"shared"; + let wrong_shared = b"incorrect"; + let encrypted = ecies::encrypt(kp.public(), shared, message).unwrap(); + assert!(encrypted[..] != message[..]); + assert_eq!(encrypted[0], 0x04); + + assert!(ecies::decrypt(kp.secret(), wrong_shared, &encrypted).is_err()); + let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap(); + assert_eq!(decrypted[..message.len()], message[..]); + } +} diff --git a/ethkey/src/extended.rs b/ethkey/src/extended.rs index 55bae627542..d41ae54c532 100644 --- a/ethkey/src/extended.rs +++ b/ethkey/src/extended.rs @@ -207,9 +207,7 @@ impl ExtendedKeyPair { // Work is based on BIP0032 // https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki mod derivation { - use rcrypto::hmac::Hmac; - use rcrypto::mac::Mac; - use rcrypto::sha2::Sha512; + use ethcore_crypto::hmac; use ethereum_types::{U256, U512, H512, H256}; use secp256k1::key::{SecretKey, PublicKey}; use SECP256K1; @@ -242,10 +240,8 @@ mod derivation { let private: U256 = private_key.into(); // produces 512-bit derived hmac (I) - let mut hmac = Hmac::new(Sha512::new(), &*chain_code); - let mut i_512 = [0u8; 64]; - hmac.input(&data[..]); - hmac.raw_result(&mut i_512); + let skey = hmac::SigKey::sha512(&*chain_code); + let i_512 = hmac::sign(&skey, &data[..]); // left most 256 bits are later added to original private key let hmac_key: U256 = H256::from_slice(&i_512[0..32]).into(); @@ -321,10 +317,8 @@ mod derivation { index.store(&mut data[33..(33 + T::len())]); // HMAC512SHA produces [derived private(256); new chain code(256)] - let mut hmac = Hmac::new(Sha512::new(), &*chain_code); - let mut i_512 = [0u8; 64]; - hmac.input(&data[..]); - hmac.raw_result(&mut i_512); + let skey = hmac::SigKey::sha512(&*chain_code); + let i_512 = hmac::sign(&skey, &data[..]); let new_private = H256::from(&i_512[0..32]); let new_chain_code = H256::from(&i_512[32..64]); @@ -369,10 +363,8 @@ mod derivation { } pub fn seed_pair(seed: &[u8]) -> (H256, H256) { - let mut hmac = Hmac::new(Sha512::new(), b"Bitcoin seed"); - let mut i_512 = [0u8; 64]; - hmac.input(seed); - hmac.raw_result(&mut i_512); + let skey = hmac::SigKey::sha512(b"Bitcoin seed"); + let i_512 = hmac::sign(&skey, seed); let master_key = H256::from_slice(&i_512[0..32]); let chain_code = H256::from_slice(&i_512[32..64]); diff --git a/ethkey/src/lib.rs b/ethkey/src/lib.rs index 951179771b2..b5cf9845306 100644 --- a/ethkey/src/lib.rs +++ b/ethkey/src/lib.rs @@ -17,11 +17,13 @@ // #![warn(missing_docs)] extern crate byteorder; -extern crate crypto as rcrypto; extern crate edit_distance; +extern crate ethcore_crypto; extern crate ethereum_types; extern crate mem; extern crate parity_wordlist; +#[macro_use] +extern crate quick_error; extern crate rand; extern crate rustc_hex; extern crate secp256k1; @@ -44,6 +46,7 @@ mod secret; mod extended; pub mod brain_recover; +pub mod crypto; pub mod math; pub use self::parity_wordlist::Error as WordlistError; diff --git a/ethstore/Cargo.toml b/ethstore/Cargo.toml index d0524baeafd..6330ce97ce7 100644 --- a/ethstore/Cargo.toml +++ b/ethstore/Cargo.toml @@ -12,7 +12,6 @@ serde = "1.0" serde_json = "1.0" serde_derive = "1.0" rustc-hex = "1.0" -rust-crypto = "0.2.36" tiny-keccak = "1.3" time = "0.1.34" itertools = "0.5" @@ -22,7 +21,6 @@ ethereum-types = "0.3" dir = { path = "../util/dir" } smallvec = "0.4" parity-wordlist = "1.0" -subtle = "0.5" tempdir = "0.3" [dev-dependencies] diff --git a/ethstore/src/account/crypto.rs b/ethstore/src/account/crypto.rs index 967c92306ae..bd65bc927b0 100644 --- a/ethstore/src/account/crypto.rs +++ b/ethstore/src/account/crypto.rs @@ -21,7 +21,6 @@ use crypto::Keccak256; use random::Random; use smallvec::SmallVec; use account::{Cipher, Kdf, Aes128Ctr, Pbkdf2, Prf}; -use subtle; /// Encrypted data #[derive(Debug, PartialEq, Clone)] @@ -74,12 +73,12 @@ impl From for String { impl Crypto { /// Encrypt account secret - pub fn with_secret(secret: &Secret, password: &str, iterations: u32) -> Self { + pub fn with_secret(secret: &Secret, password: &str, iterations: u32) -> Result { Crypto::with_plain(&*secret, password, iterations) } /// Encrypt custom plain data - pub fn with_plain(plain: &[u8], password: &str, iterations: u32) -> Self { + pub fn with_plain(plain: &[u8], password: &str, iterations: u32) -> Result { let salt: [u8; 32] = Random::random(); let iv: [u8; 16] = Random::random(); @@ -93,12 +92,12 @@ impl Crypto { let mut ciphertext: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; plain_len]); // aes-128-ctr with initial vector of iv - crypto::aes::encrypt(&derived_left_bits, &iv, plain, &mut *ciphertext); + crypto::aes::encrypt_128_ctr(&derived_left_bits, &iv, plain, &mut *ciphertext)?; // KECCAK(DK[16..31] ++ ), where DK[16..31] - derived_right_bits let mac = crypto::derive_mac(&derived_right_bits, &*ciphertext).keccak256(); - Crypto { + Ok(Crypto { cipher: Cipher::Aes128Ctr(Aes128Ctr { iv: iv, }), @@ -110,7 +109,7 @@ impl Crypto { prf: Prf::HmacSha256, }), mac: mac, - } + }) } /// Try to decrypt and convert result to account secret @@ -132,13 +131,13 @@ impl Crypto { fn do_decrypt(&self, password: &str, expected_len: usize) -> Result, Error> { let (derived_left_bits, derived_right_bits) = match self.kdf { Kdf::Pbkdf2(ref params) => crypto::derive_key_iterations(password, ¶ms.salt, params.c), - Kdf::Scrypt(ref params) => crypto::derive_key_scrypt(password, ¶ms.salt, params.n, params.p, params.r)?, + Kdf::Scrypt(ref params) => crypto::scrypt::derive_key(password, ¶ms.salt, params.n, params.p, params.r)?, }; let mac = crypto::derive_mac(&derived_right_bits, &self.ciphertext).keccak256(); - if subtle::slices_equal(&mac, &self.mac) == 0 { - return Err(Error::InvalidPassword); + if !crypto::is_equal(&mac, &self.mac) { + return Err(Error::InvalidPassword) } let mut plain: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; expected_len]); @@ -149,7 +148,7 @@ impl Crypto { debug_assert!(expected_len >= self.ciphertext.len()); let from = expected_len - self.ciphertext.len(); - crypto::aes::decrypt(&derived_left_bits, ¶ms.iv, &self.ciphertext, &mut plain[from..]); + crypto::aes::decrypt_128_ctr(&derived_left_bits, ¶ms.iv, &self.ciphertext, &mut plain[from..])?; Ok(plain.into_iter().collect()) }, } @@ -164,7 +163,7 @@ mod tests { #[test] fn crypto_with_secret_create() { let keypair = Random.generate().unwrap(); - let crypto = Crypto::with_secret(keypair.secret(), "this is sparta", 10240); + let crypto = Crypto::with_secret(keypair.secret(), "this is sparta", 10240).unwrap(); let secret = crypto.secret("this is sparta").unwrap(); assert_eq!(keypair.secret(), &secret); } @@ -172,14 +171,14 @@ mod tests { #[test] fn crypto_with_secret_invalid_password() { let keypair = Random.generate().unwrap(); - let crypto = Crypto::with_secret(keypair.secret(), "this is sparta", 10240); + let crypto = Crypto::with_secret(keypair.secret(), "this is sparta", 10240).unwrap(); assert_matches!(crypto.secret("this is sparta!"), Err(Error::InvalidPassword)) } #[test] fn crypto_with_null_plain_data() { let original_data = b""; - let crypto = Crypto::with_plain(&original_data[..], "this is sparta", 10240); + let crypto = Crypto::with_plain(&original_data[..], "this is sparta", 10240).unwrap(); let decrypted_data = crypto.decrypt("this is sparta").unwrap(); assert_eq!(original_data[..], *decrypted_data); } @@ -187,7 +186,7 @@ mod tests { #[test] fn crypto_with_tiny_plain_data() { let original_data = b"{}"; - let crypto = Crypto::with_plain(&original_data[..], "this is sparta", 10240); + let crypto = Crypto::with_plain(&original_data[..], "this is sparta", 10240).unwrap(); let decrypted_data = crypto.decrypt("this is sparta").unwrap(); assert_eq!(original_data[..], *decrypted_data); } @@ -195,7 +194,7 @@ mod tests { #[test] fn crypto_with_huge_plain_data() { let original_data: Vec<_> = (1..65536).map(|i| (i % 256) as u8).collect(); - let crypto = Crypto::with_plain(&original_data, "this is sparta", 10240); + let crypto = Crypto::with_plain(&original_data, "this is sparta", 10240).unwrap(); let decrypted_data = crypto.decrypt("this is sparta").unwrap(); assert_eq!(&original_data, &decrypted_data); } diff --git a/ethstore/src/account/safe_account.rs b/ethstore/src/account/safe_account.rs index 478b796e646..069c997e101 100644 --- a/ethstore/src/account/safe_account.rs +++ b/ethstore/src/account/safe_account.rs @@ -14,10 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethkey::{KeyPair, sign, Address, Signature, Message, Public, Secret}; -use crypto::ecdh::agree; -use {json, Error, crypto}; +use ethkey::{self, KeyPair, sign, Address, Signature, Message, Public, Secret}; +use ethkey::crypto::ecdh::agree; +use {json, Error}; use account::Version; +use crypto; use super::crypto::Crypto; /// Account representation. @@ -61,16 +62,16 @@ impl SafeAccount { iterations: u32, name: String, meta: String - ) -> Self { - SafeAccount { + ) -> Result { + Ok(SafeAccount { id: id, version: Version::V3, - crypto: Crypto::with_secret(keypair.secret(), password, iterations), + crypto: Crypto::with_secret(keypair.secret(), password, iterations)?, address: keypair.address(), filename: None, name: name, meta: meta, - } + }) } /// Create a new `SafeAccount` from the given `json`; if it was read from a @@ -114,7 +115,7 @@ impl SafeAccount { meta: Some(self.meta), }; let meta_plain = meta_plain.write().map_err(|e| Error::Custom(format!("{:?}", e)))?; - let meta_crypto = Crypto::with_plain(&meta_plain, password, iterations); + let meta_crypto = Crypto::with_plain(&meta_plain, password, iterations)?; Ok(json::VaultKeyFile { id: self.id.into(), @@ -133,7 +134,7 @@ impl SafeAccount { /// Decrypt a message. pub fn decrypt(&self, password: &str, shared_mac: &[u8], message: &[u8]) -> Result, Error> { let secret = self.crypto.secret(password)?; - crypto::ecies::decrypt(&secret, shared_mac, message).map_err(From::from) + ethkey::crypto::ecies::decrypt(&secret, shared_mac, message).map_err(From::from) } /// Agree on shared key. @@ -154,7 +155,7 @@ impl SafeAccount { let result = SafeAccount { id: self.id.clone(), version: self.version.clone(), - crypto: Crypto::with_secret(&secret, new_password, iterations), + crypto: Crypto::with_secret(&secret, new_password, iterations)?, address: self.address.clone(), filename: self.filename.clone(), name: self.name.clone(), @@ -180,7 +181,7 @@ mod tests { let password = "hello world"; let message = Message::default(); let account = SafeAccount::create(&keypair, [0u8; 16], password, 10240, "Test".to_owned(), "{}".to_owned()); - let signature = account.sign(password, &message).unwrap(); + let signature = account.unwrap().sign(password, &message).unwrap(); assert!(verify_public(keypair.public(), &signature, &message).unwrap()); } @@ -191,7 +192,7 @@ mod tests { let sec_password = "this is sparta"; let i = 10240; let message = Message::default(); - let account = SafeAccount::create(&keypair, [0u8; 16], first_password, i, "Test".to_owned(), "{}".to_owned()); + let account = SafeAccount::create(&keypair, [0u8; 16], first_password, i, "Test".to_owned(), "{}".to_owned()).unwrap(); let new_account = account.change_password(first_password, sec_password, i).unwrap(); assert!(account.sign(first_password, &message).is_ok()); assert!(account.sign(sec_password, &message).is_err()); diff --git a/ethstore/src/accounts_dir/disk.rs b/ethstore/src/accounts_dir/disk.rs index 14461184406..29b7e524660 100644 --- a/ethstore/src/accounts_dir/disk.rs +++ b/ethstore/src/accounts_dir/disk.rs @@ -319,7 +319,7 @@ mod test { // when let account = SafeAccount::create(&keypair, [0u8; 16], password, 1024, "Test".to_owned(), "{}".to_owned()); - let res = directory.insert(account); + let res = directory.insert(account.unwrap()); // then assert!(res.is_ok(), "Should save account succesfuly."); @@ -339,7 +339,7 @@ mod test { let directory = RootDiskDirectory::create(dir.clone()).unwrap(); // when - let account = SafeAccount::create(&keypair, [0u8; 16], password, 1024, "Test".to_owned(), "{}".to_owned()); + let account = SafeAccount::create(&keypair, [0u8; 16], password, 1024, "Test".to_owned(), "{}".to_owned()).unwrap(); let filename = "test".to_string(); let dedup = true; @@ -424,7 +424,7 @@ mod test { let keypair = Random.generate().unwrap(); let password = "test pass"; let account = SafeAccount::create(&keypair, [0u8; 16], password, 1024, "Test".to_owned(), "{}".to_owned()); - directory.insert(account).expect("Account should be inserted ok"); + directory.insert(account.unwrap()).expect("Account should be inserted ok"); let new_hash = directory.files_hash().expect("New files hash should be calculated ok"); diff --git a/ethstore/src/accounts_dir/vault.rs b/ethstore/src/accounts_dir/vault.rs index 1ef85402a7a..27052626661 100644 --- a/ethstore/src/accounts_dir/vault.rs +++ b/ethstore/src/accounts_dir/vault.rs @@ -235,7 +235,7 @@ fn check_vault_name(name: &str) -> bool { /// Vault can be empty, but still must be pluggable => we store vault password in separate file fn create_vault_file

(vault_dir_path: P, key: &VaultKey, meta: &str) -> Result<(), Error> where P: AsRef { let password_hash = key.password.keccak256(); - let crypto = Crypto::with_plain(&password_hash, &key.password, key.iterations); + let crypto = Crypto::with_plain(&password_hash, &key.password, key.iterations)?; let mut vault_file_path: PathBuf = vault_dir_path.as_ref().into(); vault_file_path.push(VAULT_FILE_NAME); diff --git a/ethstore/src/error.rs b/ethstore/src/error.rs index f7e0b0bfadc..7c89473280b 100644 --- a/ethstore/src/error.rs +++ b/ethstore/src/error.rs @@ -16,8 +16,8 @@ use std::fmt; use std::io::Error as IoError; -use ethkey::Error as EthKeyError; -use crypto::Error as EthCryptoError; +use ethkey::{self, Error as EthKeyError}; +use crypto::{self, Error as EthCryptoError}; use ethkey::DerivationError; /// Account-related errors. @@ -49,6 +49,8 @@ pub enum Error { CreationFailed, /// `EthKey` error EthKey(EthKeyError), + /// `ethkey::crypto::Error` + EthKeyCrypto(ethkey::crypto::Error), /// `EthCrypto` error EthCrypto(EthCryptoError), /// Derivation error @@ -73,6 +75,7 @@ impl fmt::Display for Error { Error::VaultNotFound => "Vault not found".into(), Error::CreationFailed => "Account creation failed".into(), Error::EthKey(ref err) => err.to_string(), + Error::EthKeyCrypto(ref err) => err.to_string(), Error::EthCrypto(ref err) => err.to_string(), Error::Derivation(ref err) => format!("Derivation error: {:?}", err), Error::Custom(ref s) => s.clone(), @@ -94,12 +97,30 @@ impl From for Error { } } +impl From for Error { + fn from(err: ethkey::crypto::Error) -> Self { + Error::EthKeyCrypto(err) + } +} + impl From for Error { fn from(err: EthCryptoError) -> Self { Error::EthCrypto(err) } } +impl From for Error { + fn from(err: crypto::error::ScryptError) -> Self { + Error::EthCrypto(err.into()) + } +} + +impl From for Error { + fn from(err: crypto::error::SymmError) -> Self { + Error::EthCrypto(err.into()) + } +} + impl From for Error { fn from(err: DerivationError) -> Self { Error::Derivation(err) diff --git a/ethstore/src/ethstore.rs b/ethstore/src/ethstore.rs index 40a687fc988..46c81153c78 100644 --- a/ethstore/src/ethstore.rs +++ b/ethstore/src/ethstore.rs @@ -458,7 +458,7 @@ impl SimpleSecretStore for EthMultiStore { fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &str) -> Result { let keypair = KeyPair::from_secret(secret).map_err(|_| Error::CreationFailed)?; let id: [u8; 16] = Random::random(); - let account = SafeAccount::create(&keypair, id, password, self.iterations, "".to_owned(), "{}".to_owned()); + let account = SafeAccount::create(&keypair, id, password, self.iterations, "".to_owned(), "{}".to_owned())?; self.import(vault, account) } diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs index 75df0953ce4..b558126ada6 100644 --- a/ethstore/src/lib.rs +++ b/ethstore/src/lib.rs @@ -18,7 +18,6 @@ #![warn(missing_docs)] -extern crate crypto as rcrypto; extern crate dir; extern crate itertools; extern crate libc; @@ -28,7 +27,6 @@ extern crate rustc_hex; extern crate serde; extern crate serde_json; extern crate smallvec; -extern crate subtle; extern crate time; extern crate tiny_keccak; extern crate tempdir; diff --git a/ethstore/src/presale.rs b/ethstore/src/presale.rs index 0c3e72e31b8..555d00c1e98 100644 --- a/ethstore/src/presale.rs +++ b/ethstore/src/presale.rs @@ -1,11 +1,8 @@ use std::fs; use std::path::Path; -use rcrypto::pbkdf2::pbkdf2; -use rcrypto::sha2::Sha256; -use rcrypto::hmac::Hmac; use json; use ethkey::{Address, Secret, KeyPair}; -use crypto::Keccak256; +use crypto::{Keccak256, pbkdf2}; use {crypto, Error}; /// Pre-sale wallet. @@ -42,12 +39,14 @@ impl PresaleWallet { /// Decrypt the wallet. pub fn decrypt(&self, password: &str) -> Result { - let mut h_mac = Hmac::new(Sha256::new(), password.as_bytes()); - let mut derived_key = vec![0u8; 16]; - pbkdf2(&mut h_mac, password.as_bytes(), 2000, &mut derived_key); + let mut derived_key = [0u8; 32]; + let salt = pbkdf2::Salt(password.as_bytes()); + let sec = pbkdf2::Secret(password.as_bytes()); + pbkdf2::sha256(2000, salt, sec, &mut derived_key); let mut key = vec![0; self.ciphertext.len()]; - let len = crypto::aes::decrypt_cbc(&derived_key, &self.iv, &self.ciphertext, &mut key).map_err(|_| Error::InvalidPassword)?; + let len = crypto::aes::decrypt_128_cbc(&derived_key[0..16], &self.iv, &self.ciphertext, &mut key) + .map_err(|_| Error::InvalidPassword)?; let unpadded = &key[..len]; let secret = Secret::from_unsafe_slice(&unpadded.keccak256())?; diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index b8eb5254629..731544a55f2 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -17,7 +17,6 @@ multihash ="0.7" order-stat = "0.1" parking_lot = "0.5" rand = "0.4" -rust-crypto = "0.2" rustc-hex = "1.0" semver = "0.9" serde = "1.0" diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 7b5cc36447c..1fc3d0e2428 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -23,7 +23,6 @@ extern crate futures; extern crate ansi_term; extern crate cid; -extern crate crypto as rust_crypto; extern crate futures_cpupool; extern crate itertools; extern crate multihash; diff --git a/rpc/src/v1/helpers/ipfs.rs b/rpc/src/v1/helpers/ipfs.rs index 80ad1c207b0..da51f1fd549 100644 --- a/rpc/src/v1/helpers/ipfs.rs +++ b/rpc/src/v1/helpers/ipfs.rs @@ -18,21 +18,15 @@ use multihash; use cid::{Cid, Codec, Version}; -use rust_crypto::sha2::Sha256; -use rust_crypto::digest::Digest; +use crypto::digest; use jsonrpc_core::Error; use v1::types::Bytes; use super::errors; /// Compute CIDv0 from protobuf encoded bytes. pub fn cid(content: Bytes) -> Result { - let mut hasher = Sha256::new(); - hasher.input(&content.0); - let len = hasher.output_bytes(); - let mut buf = Vec::with_capacity(len); - buf.resize(len, 0); - hasher.result(&mut buf); - let mh = multihash::encode(multihash::Hash::SHA2256, &buf).map_err(errors::encoding)?; + let hash = digest::sha256(&content.0); + let mh = multihash::encode(multihash::Hash::SHA2256, &*hash).map_err(errors::encoding)?; let cid = Cid::new(Codec::DagProtobuf, Version::V0, &mh); Ok(cid.to_string().into()) } diff --git a/rpc/src/v1/helpers/secretstore.rs b/rpc/src/v1/helpers/secretstore.rs index fbcc167e239..019d2b1051f 100644 --- a/rpc/src/v1/helpers/secretstore.rs +++ b/rpc/src/v1/helpers/secretstore.rs @@ -16,7 +16,7 @@ use std::collections::BTreeSet; use rand::{Rng, OsRng}; -use ethkey::{Public, Secret, Random, Generator, math}; +use ethkey::{self, Public, Secret, Random, Generator, math}; use crypto; use bytes::Bytes; use jsonrpc_core::Error; @@ -36,7 +36,7 @@ pub fn generate_document_key(account_public: Public, server_key_public: Public) let (common_point, encrypted_point) = encrypt_secret(document_key.public(), &server_key_public)?; // ..and now encrypt document key with account public - let encrypted_key = crypto::ecies::encrypt(&account_public, &crypto::DEFAULT_MAC, document_key.public()) + let encrypted_key = ethkey::crypto::ecies::encrypt(&account_public, &crypto::DEFAULT_MAC, document_key.public()) .map_err(errors::encryption)?; Ok(EncryptedDocumentKey { @@ -57,7 +57,7 @@ pub fn encrypt_document(key: Bytes, document: Bytes) -> Result { { let (mut encryption_buffer, iv_buffer) = encrypted_document.split_at_mut(document.len()); - crypto::aes::encrypt(&key, &iv, &document, &mut encryption_buffer); + crypto::aes::encrypt_128_ctr(&key, &iv, &document, &mut encryption_buffer).map_err(errors::encryption)?; iv_buffer.copy_from_slice(&iv); } @@ -78,7 +78,7 @@ pub fn decrypt_document(key: Bytes, mut encrypted_document: Bytes) -> Result = decrypted_secret.decrypt_shadows.unwrap().into_iter() .map(|c| Secret::from_slice(&decrypt(key_pair.secret(), &DEFAULT_MAC, &c).unwrap()).unwrap()) .collect(); @@ -1423,7 +1423,7 @@ mod tests { // 4 nodes must be able to recover original secret use crypto::DEFAULT_MAC; - use crypto::ecies::decrypt; + use ethkey::crypto::ecies::decrypt; let result = sessions[0].decrypted_secret().unwrap().unwrap(); assert_eq!(3, sessions.iter().skip(1).filter(|s| s.decrypted_secret() == Some(Ok(result.clone()))).count()); let decrypt_shadows: Vec<_> = result.decrypt_shadows.unwrap().into_iter() diff --git a/secret_store/src/key_server_cluster/io/handshake.rs b/secret_store/src/key_server_cluster/io/handshake.rs index 838e48e1f74..af642956322 100644 --- a/secret_store/src/key_server_cluster/io/handshake.rs +++ b/secret_store/src/key_server_cluster/io/handshake.rs @@ -37,7 +37,7 @@ use std::sync::Arc; use std::collections::BTreeSet; use futures::{Future, Poll, Async}; use tokio_io::{AsyncRead, AsyncWrite}; -use crypto::ecdh::agree; +use ethkey::crypto::ecdh::agree; use ethkey::{Random, Generator, KeyPair, Public, Signature, verify_public, sign, recover}; use ethereum_types::H256; use key_server_cluster::{NodeId, Error, NodeKeyPair}; diff --git a/secret_store/src/key_server_cluster/io/message.rs b/secret_store/src/key_server_cluster/io/message.rs index 784b0b2b6a4..9925b789d24 100644 --- a/secret_store/src/key_server_cluster/io/message.rs +++ b/secret_store/src/key_server_cluster/io/message.rs @@ -19,7 +19,7 @@ use std::u16; use std::ops::Deref; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use serde_json; -use crypto::ecies; +use ethkey::crypto::ecies; use ethkey::{Secret, KeyPair}; use ethkey::math::curve_order; use ethereum_types::{H256, U256}; @@ -306,7 +306,7 @@ pub mod tests { use futures::Poll; use tokio_io::{AsyncRead, AsyncWrite}; use ethkey::{Random, Generator, KeyPair}; - use crypto::ecdh::agree; + use ethkey::crypto::ecdh::agree; use key_server_cluster::Error; use key_server_cluster::message::Message; use super::{MESSAGE_HEADER_SIZE, CURRENT_HEADER_VERSION, MessageHeader, fix_shared_key, encrypt_message, diff --git a/secret_store/src/key_server_cluster/jobs/decryption_job.rs b/secret_store/src/key_server_cluster/jobs/decryption_job.rs index 1f14a484daf..2c11fe0ab36 100644 --- a/secret_store/src/key_server_cluster/jobs/decryption_job.rs +++ b/secret_store/src/key_server_cluster/jobs/decryption_job.rs @@ -17,8 +17,8 @@ use std::collections::{BTreeSet, BTreeMap}; use ethereum_types::H256; use ethkey::{Public, Secret}; -use crypto::ecies::encrypt; use crypto::DEFAULT_MAC; +use ethkey::crypto::ecies::encrypt; use key_server_cluster::{Error, NodeId, DocumentKeyShare, EncryptedDocumentKeyShadow}; use key_server_cluster::math; use key_server_cluster::jobs::job_session::{JobPartialRequestAction, JobPartialResponseAction, JobExecutor}; diff --git a/secret_store/src/node_key_pair.rs b/secret_store/src/node_key_pair.rs index 55c2a8a28a1..428dba6c1a7 100644 --- a/secret_store/src/node_key_pair.rs +++ b/secret_store/src/node_key_pair.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::sync::Arc; -use crypto::ecdh::agree; +use ethkey::crypto::ecdh::agree; use ethkey::{KeyPair, Public, Signature, Error as EthKeyError, sign, public_to_address}; use ethcore::account_provider::AccountProvider; use ethereum_types::{H256, Address}; @@ -54,7 +54,8 @@ impl NodeKeyPair for PlainNodeKeyPair { } fn compute_shared_key(&self, peer_public: &Public) -> Result { - agree(self.key_pair.secret(), peer_public).map_err(|e| EthKeyError::Custom(e.into())) + agree(self.key_pair.secret(), peer_public) + .map_err(|e| EthKeyError::Custom(e.to_string())) .and_then(KeyPair::from_secret) } } diff --git a/secret_store/src/types/error.rs b/secret_store/src/types/error.rs index 6469585facb..1fceb120e82 100644 --- a/secret_store/src/types/error.rs +++ b/secret_store/src/types/error.rs @@ -168,6 +168,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: ethkey::crypto::Error) -> Self { + Error::EthKey(err.to_string()) + } +} + impl From for Error { fn from(err: kvdb::Error) -> Self { Error::Database(err.to_string()) @@ -176,7 +182,7 @@ impl From for Error { impl From for Error { fn from(err: crypto::Error) -> Self { - Error::EthKey(err.into()) + Error::EthKey(err.to_string()) } } diff --git a/util/network-devp2p/src/connection.rs b/util/network-devp2p/src/connection.rs index 2b390baf75e..5dbf71fa01c 100644 --- a/util/network-devp2p/src/connection.rs +++ b/util/network-devp2p/src/connection.rs @@ -34,7 +34,7 @@ use rcrypto::symmetriccipher::*; use rcrypto::buffer::*; use tiny_keccak::Keccak; use bytes::{Buf, BufMut}; -use crypto; +use ethkey::crypto; use network::{Error, ErrorKind}; const ENCRYPTED_HEADER_LEN: usize = 32; diff --git a/util/network-devp2p/src/handshake.rs b/util/network-devp2p/src/handshake.rs index 37c39eb618e..a203af5b4b4 100644 --- a/util/network-devp2p/src/handshake.rs +++ b/util/network-devp2p/src/handshake.rs @@ -25,7 +25,7 @@ use connection::{Connection}; use node_table::NodeId; use io::{IoContext, StreamToken}; use ethkey::{KeyPair, Public, Secret, recover, sign, Generator, Random}; -use crypto::{ecdh, ecies}; +use ethkey::crypto::{ecdh, ecies}; use network::{Error, ErrorKind, HostInfo}; #[derive(PartialEq, Eq, Debug)] diff --git a/util/network/src/error.rs b/util/network/src/error.rs index 48bcf759656..6342bfe4ad6 100644 --- a/util/network/src/error.rs +++ b/util/network/src/error.rs @@ -151,8 +151,14 @@ impl From for Error { } } -impl From for Error { - fn from(_err: crypto::Error) -> Self { +impl From for Error { + fn from(_err: ethkey::crypto::Error) -> Self { + ErrorKind::Auth.into() + } +} + +impl From for Error { + fn from(_err: crypto::error::SymmError) -> Self { ErrorKind::Auth.into() } } @@ -168,11 +174,11 @@ fn test_errors() { match *>::from(rlp::DecoderError::RlpIsTooBig).kind() { ErrorKind::Auth => {}, - _ => panic!("Unexpeceted error"), + _ => panic!("Unexpected error"), } - match *>::from(crypto::Error::InvalidMessage).kind() { + match *>::from(ethkey::crypto::Error::InvalidMessage).kind() { ErrorKind::Auth => {}, - _ => panic!("Unexpeceted error"), + _ => panic!("Unexpected error"), } } diff --git a/whisper/Cargo.toml b/whisper/Cargo.toml index bd1fc2dbb05..ed370e38a2d 100644 --- a/whisper/Cargo.toml +++ b/whisper/Cargo.toml @@ -17,7 +17,6 @@ mem = { path = "../util/mem" } ordered-float = "0.5" parking_lot = "0.5" rand = "0.4" -ring = "0.12" rlp = { path = "../util/rlp" } serde = "1.0" serde_derive = "1.0" diff --git a/whisper/src/lib.rs b/whisper/src/lib.rs index 4aa1a99b9e6..85ab55e0f46 100644 --- a/whisper/src/lib.rs +++ b/whisper/src/lib.rs @@ -28,7 +28,6 @@ extern crate ordered_float; extern crate parking_lot; extern crate rand; extern crate rlp; -extern crate ring; extern crate serde; extern crate slab; extern crate smallvec; diff --git a/whisper/src/rpc/crypto.rs b/whisper/src/rpc/crypto.rs index 8780045b472..667656d6bf3 100644 --- a/whisper/src/rpc/crypto.rs +++ b/whisper/src/rpc/crypto.rs @@ -16,11 +16,11 @@ //! Encryption schemes supported by RPC layer. -use crypto; +use crypto::aes_gcm::{Encryptor, Decryptor}; +use ethkey::crypto::ecies; use ethereum_types::H256; use ethkey::{self, Public, Secret}; use mem::Memzero; -use ring::aead::{self, AES_256_GCM, SealingKey, OpeningKey}; /// Length of AES key pub const AES_KEY_LEN: usize = 32; @@ -72,38 +72,15 @@ impl EncryptionInstance { } /// Encrypt the supplied plaintext - pub fn encrypt(self, plain: &[u8]) -> Vec { + pub fn encrypt(self, plain: &[u8]) -> Option> { match self.0 { EncryptionInner::AES(key, nonce, encode) => { - let sealing_key = SealingKey::new(&AES_256_GCM, &*key) - .expect("key is of correct len; qed"); - - let encrypt_plain = move |buf: &mut Vec| { - let out_suffix_capacity = AES_256_GCM.tag_len(); - - let prepend_len = buf.len(); - buf.extend(plain); - - buf.resize(prepend_len + plain.len() + out_suffix_capacity, 0); - - let out_size = aead::seal_in_place( - &sealing_key, - &nonce, - &[], // no authenticated data. - &mut buf[prepend_len..], - out_suffix_capacity, - ).expect("key, nonce, buf are valid and out suffix large enough; qed"); - - // truncate to the output size and return. - buf.truncate(prepend_len + out_size); - }; - match encode { AesEncode::AppendedNonce => { - let mut buf = Vec::new(); - encrypt_plain(&mut buf); + let mut enc = Encryptor::aes_256_gcm(&*key).ok()?; + let mut buf = enc.encrypt(&nonce, plain.to_vec()).ok()?; buf.extend(&nonce[..]); - buf + Some(buf) } AesEncode::OnTopics(topics) => { let mut buf = Vec::new(); @@ -111,14 +88,16 @@ impl EncryptionInstance { xor(&mut t.0, &key); buf.extend(&t.0); } - encrypt_plain(&mut buf); - buf + let mut enc = Encryptor::aes_256_gcm(&*key).ok()?; + enc.offset(buf.len()); + buf.extend(plain); + let ciphertext = enc.encrypt(&nonce, buf).ok()?; + Some(ciphertext) } } } EncryptionInner::ECIES(valid_public) => { - crypto::ecies::encrypt(&valid_public, &[], plain) - .expect("validity of public key an invariant of the type; qed") + ecies::encrypt(&valid_public, &[], plain).ok() } } } @@ -169,58 +148,36 @@ impl DecryptionInstance { pub fn decrypt(self, ciphertext: &[u8]) -> Option> { match self.0 { DecryptionInner::AES(extract) => { - let decrypt = | - key: Memzero<[u8; AES_KEY_LEN]>, - nonce: [u8; AES_NONCE_LEN], - ciphertext: &[u8] - | { - if ciphertext.len() < AES_256_GCM.tag_len() { return None } - - let opening_key = OpeningKey::new(&AES_256_GCM, &*key) - .expect("key length is valid for mode; qed"); - - let mut buf = ciphertext.to_vec(); - - // decrypted plaintext always ends up at the - // front of the buffer. - let maybe_decrypted = aead::open_in_place( - &opening_key, - &nonce, - &[], // no authenticated data - 0, // no header. - &mut buf, - ).ok().map(|plain_slice| plain_slice.len()); - - maybe_decrypted.map(move |len| { buf.truncate(len); buf }) - }; - match extract { AesExtract::AppendedNonce(key) => { - if ciphertext.len() < AES_NONCE_LEN { return None } - + if ciphertext.len() < AES_NONCE_LEN { + return None + } // nonce is the suffix of ciphertext. let mut nonce = [0; AES_NONCE_LEN]; let nonce_offset = ciphertext.len() - AES_NONCE_LEN; - nonce.copy_from_slice(&ciphertext[nonce_offset..]); - decrypt(key, nonce, &ciphertext[..nonce_offset]) + Decryptor::aes_256_gcm(&*key).ok()? + .decrypt(&nonce, Vec::from(&ciphertext[..nonce_offset])) + .ok() } AesExtract::OnTopics(num_topics, known_index, known_topic) => { - if ciphertext.len() < num_topics * 32 { return None } - + if ciphertext.len() < num_topics * 32 { + return None + } let mut salted_topic = H256::new(); salted_topic.copy_from_slice(&ciphertext[(known_index * 32)..][..32]); - let key = Memzero::from((salted_topic ^ known_topic).0); - let offset = num_topics * 32; - decrypt(key, BROADCAST_IV, &ciphertext[offset..]) + Decryptor::aes_256_gcm(&*key).ok()? + .decrypt(&BROADCAST_IV, Vec::from(&ciphertext[offset..])) + .ok() } } } DecryptionInner::ECIES(secret) => { // secret is checked for validity, so only fails on invalid message. - crypto::ecies::decrypt(&secret, &[], ciphertext).ok() + ecies::decrypt(&secret, &[], ciphertext).ok() } } } @@ -230,16 +187,6 @@ impl DecryptionInstance { mod tests { use super::*; - #[test] - fn aes_key_len_should_be_equal_to_constant() { - assert_eq!(::ring::aead::AES_256_GCM.key_len(), AES_KEY_LEN); - } - - #[test] - fn aes_nonce_len_should_be_equal_to_constant() { - assert_eq!(::ring::aead::AES_256_GCM.nonce_len(), AES_NONCE_LEN); - } - #[test] fn encrypt_asymmetric() { use ethkey::{Generator, Random}; @@ -247,7 +194,7 @@ mod tests { let key_pair = Random.generate().unwrap(); let test_message = move |message: &[u8]| { let instance = EncryptionInstance::ecies(key_pair.public().clone()).unwrap(); - let ciphertext = instance.encrypt(&message); + let ciphertext = instance.encrypt(&message).unwrap(); if !message.is_empty() { assert!(&ciphertext[..message.len()] != message) @@ -273,7 +220,7 @@ mod tests { let key = Memzero::from(rng.gen::<[u8; 32]>()); let instance = EncryptionInstance::aes(key.clone(), rng.gen()); - let ciphertext = instance.encrypt(message); + let ciphertext = instance.encrypt(message).unwrap(); if !message.is_empty() { assert!(&ciphertext[..message.len()] != message) @@ -303,7 +250,7 @@ mod tests { let key = Memzero::from(rng.gen::<[u8; 32]>()); let instance = EncryptionInstance::broadcast(key, all_topics); - let ciphertext = instance.encrypt(message); + let ciphertext = instance.encrypt(message).unwrap(); if !message.is_empty() { assert!(&ciphertext[..message.len()] != message) diff --git a/whisper/src/rpc/filter.rs b/whisper/src/rpc/filter.rs index 5a192ac04cd..8d125174ed7 100644 --- a/whisper/src/rpc/filter.rs +++ b/whisper/src/rpc/filter.rs @@ -402,7 +402,7 @@ mod tests { sign_with: Some(signing_pair.secret().unwrap()) }).unwrap(); - let encrypted = encryption_instance.encrypt(&payload); + let encrypted = encryption_instance.encrypt(&payload).unwrap(); let message = Message::create(CreateParams { ttl: 100, diff --git a/whisper/src/rpc/key_store.rs b/whisper/src/rpc/key_store.rs index 02781e20adc..1fb4e264ace 100644 --- a/whisper/src/rpc/key_store.rs +++ b/whisper/src/rpc/key_store.rs @@ -25,7 +25,6 @@ use ethereum_types::H256; use ethkey::{KeyPair, Public, Secret}; use mem::Memzero; use rand::{Rng, OsRng}; -use ring::error::Unspecified; use rpc::crypto::{AES_KEY_LEN, EncryptionInstance, DecryptionInstance}; @@ -54,10 +53,8 @@ impl Key { } /// From secret asymmetric key. Fails if secret is invalid. - pub fn from_secret(secret: Secret) -> Result { - KeyPair::from_secret(secret) - .map(Key::Asymmetric) - .map_err(|_| Unspecified) + pub fn from_secret(secret: Secret) -> Option { + KeyPair::from_secret(secret).map(Key::Asymmetric).ok() } /// From raw symmetric key. @@ -179,7 +176,7 @@ mod tests { #[test] fn rejects_invalid_secret() { let bad_secret = ::ethkey::Secret::from([0xff; 32]); - assert!(Key::from_secret(bad_secret).is_err()); + assert!(Key::from_secret(bad_secret).is_none()); } #[test] diff --git a/whisper/src/rpc/mod.rs b/whisper/src/rpc/mod.rs index e9e65770853..7daa3f45590 100644 --- a/whisper/src/rpc/mod.rs +++ b/whisper/src/rpc/mod.rs @@ -226,7 +226,7 @@ impl Whisper for WhisperClien fn add_private_key(&self, private: types::Private) -> Result { let key_pair = Key::from_secret(private.into_inner().into()) - .map_err(|_| whisper_error("Invalid private key"))?; + .ok_or_else(|| whisper_error("Invalid private key"))?; Ok(HexEncode(self.store.write().insert(key_pair))) } @@ -317,7 +317,7 @@ impl Whisper for WhisperClien sign_with: sign_with.as_ref(), }).map_err(whisper_error)?; - encryption.encrypt(&payload) + encryption.encrypt(&payload).ok_or(whisper_error("encryption error"))? }; // mining the packet is the heaviest item of work by far. From 32c32ecfdac7787ab8d4271b5245661bf253d471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Mon, 7 May 2018 11:57:03 +0100 Subject: [PATCH 37/95] ethcore, rpc, machine: refactor block reward application and tracing (#8490) --- ethcore/src/engines/authority_round/mod.rs | 9 ++++-- ethcore/src/engines/block_reward.rs | 34 +++++++++++++++++----- ethcore/src/engines/mod.rs | 2 +- ethcore/src/engines/null_engine.rs | 20 +++++-------- ethcore/src/engines/tendermint/mod.rs | 10 +++++-- ethcore/src/ethereum/ethash.rs | 25 ++++++++-------- ethcore/src/machine.rs | 24 ++++++++++----- ethcore/src/trace/types/trace.rs | 8 +++++ machine/src/lib.rs | 8 ----- rpc/src/v1/types/trace.rs | 8 +++++ 10 files changed, 93 insertions(+), 55 deletions(-) diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 4807d6c3fbb..c2aee7c6efc 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -1015,8 +1015,10 @@ impl Engine for AuthorityRound { let author = *block.header().author(); benefactors.push((author, RewardKind::Author)); - let rewards = match self.block_reward_contract { + let rewards: Vec<_> = match self.block_reward_contract { Some(ref c) if block.header().number() >= self.block_reward_contract_transition => { + // NOTE: this logic should be moved to a function when another + // engine needs support for block reward contract. let mut call = |to, data| { let result = self.machine.execute_as_system( block, @@ -1027,10 +1029,11 @@ impl Engine for AuthorityRound { result.map_err(|e| format!("{}", e)) }; - c.reward(&benefactors, &mut call)? + let rewards = c.reward(&benefactors, &mut call)?; + rewards.into_iter().map(|(author, amount)| (author, RewardKind::External, amount)).collect() }, _ => { - benefactors.into_iter().map(|(author, _)| (author, self.block_reward)).collect() + benefactors.into_iter().map(|(author, reward_kind)| (author, reward_kind, self.block_reward)).collect() }, }; diff --git a/ethcore/src/engines/block_reward.rs b/ethcore/src/engines/block_reward.rs index 510a5255f5f..9a9d54e4af1 100644 --- a/ethcore/src/engines/block_reward.rs +++ b/ethcore/src/engines/block_reward.rs @@ -14,13 +14,17 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! A module with types for declaring block rewards and a client interface for interacting with a +//! block reward contract. + use ethabi; use ethabi::ParamType; use ethereum_types::{H160, Address, U256}; -use block::ExecutedBlock; use error::Error; -use machine::EthereumMachine; +use machine::WithRewards; +use parity_machine::{Machine, WithBalances}; +use trace; use super::SystemCall; use_contract!(block_reward_contract, "BlockReward", "res/contracts/block_reward.json"); @@ -37,6 +41,8 @@ pub enum RewardKind { Uncle = 1, /// Reward attributed to the author(s) of empty step(s) included in the block (AuthorityRound engine). EmptyStep = 2, + /// Reward attributed by an external protocol (e.g. block reward contract). + External = 3, } impl From for u16 { @@ -45,6 +51,17 @@ impl From for u16 { } } +impl Into for RewardKind { + fn into(self) -> trace::RewardType { + match self { + RewardKind::Author => trace::RewardType::Block, + RewardKind::Uncle => trace::RewardType::Uncle, + RewardKind::EmptyStep => trace::RewardType::EmptyStep, + RewardKind::External => trace::RewardType::External, + } + } +} + /// A client for the block reward contract. pub struct BlockRewardContract { /// Address of the contract. @@ -112,14 +129,17 @@ impl BlockRewardContract { /// Applies the given block rewards, i.e. adds the given balance to each benefactors' address. /// If tracing is enabled the operations are recorded. -pub fn apply_block_rewards(rewards: &[(Address, U256)], block: &mut ExecutedBlock, machine: &EthereumMachine) -> Result<(), Error> { - use parity_machine::WithBalances; - - for &(ref author, ref block_reward) in rewards { +pub fn apply_block_rewards( + rewards: &[(Address, RewardKind, U256)], + block: &mut M::LiveBlock, + machine: &M, +) -> Result<(), M::Error> { + for &(ref author, _, ref block_reward) in rewards { machine.add_balance(block, author, block_reward)?; } - machine.note_rewards(block, &rewards, &[]) + let rewards: Vec<_> = rewards.into_iter().map(|&(a, k, r)| (a, k.into(), r)).collect(); + machine.note_rewards(block, &rewards) } #[cfg(test)] diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index a17ae356e6f..e019636f53a 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -18,7 +18,6 @@ mod authority_round; mod basic_authority; -mod block_reward; mod instant_seal; mod null_engine; mod signer; @@ -27,6 +26,7 @@ mod transition; mod validator_set; mod vote_collector; +pub mod block_reward; pub mod epoch; pub use self::authority_round::AuthorityRound; diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index f20a9cdfd9d..278eb037c06 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -16,7 +16,9 @@ use ethereum_types::U256; use engines::Engine; +use engines::block_reward::{self, RewardKind}; use header::BlockNumber; +use machine::WithRewards; use parity_machine::{Header, LiveBlock, WithBalances}; /// Params for a null engine. @@ -56,7 +58,7 @@ impl Default for NullEngine { } } -impl Engine for NullEngine { +impl Engine for NullEngine { fn name(&self) -> &str { "NullEngine" } @@ -74,26 +76,20 @@ impl Engine for NullEngine { let n_uncles = LiveBlock::uncles(&*block).len(); + let mut rewards = Vec::new(); + // Bestow block reward let result_block_reward = reward + reward.shr(5) * U256::from(n_uncles); - let mut uncle_rewards = Vec::with_capacity(n_uncles); - - self.machine.add_balance(block, &author, &result_block_reward)?; + rewards.push((author, RewardKind::Author, result_block_reward)); // bestow uncle rewards. for u in LiveBlock::uncles(&*block) { let uncle_author = u.author(); let result_uncle_reward = (reward * U256::from(8 + u.number() - number)).shr(3); - - uncle_rewards.push((*uncle_author, result_uncle_reward)); - } - - for &(ref a, ref reward) in &uncle_rewards { - self.machine.add_balance(block, a, reward)?; + rewards.push((*uncle_author, RewardKind::Uncle, result_uncle_reward)); } - // note and trace. - self.machine.note_rewards(block, &[(author, result_block_reward)], &uncle_rewards) + block_reward::apply_block_rewards(&rewards, block, &self.machine) } fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 } diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 289beaad0cc..d80a5e182f1 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -41,6 +41,7 @@ use ethkey::{self, Message, Signature}; use account_provider::AccountProvider; use block::*; use engines::{Engine, Seal, EngineError, ConstructedVerifier}; +use engines::block_reward::{self, RewardKind}; use io::IoService; use super::signer::EngineSigner; use super::validator_set::{ValidatorSet, SimpleList}; @@ -550,10 +551,13 @@ impl Engine for Tendermint { /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error>{ - use parity_machine::WithBalances; let author = *block.header().author(); - self.machine.add_balance(block, &author, &self.block_reward)?; - self.machine.note_rewards(block, &[(author, self.block_reward)], &[]) + + block_reward::apply_block_rewards( + &[(author, RewardKind::Author, self.block_reward)], + block, + &self.machine, + ) } fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> { diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 09e9caf727b..09151415c87 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -19,6 +19,7 @@ use std::cmp; use std::collections::BTreeMap; use std::sync::Arc; use hash::{KECCAK_EMPTY_LIST_RLP}; +use engines::block_reward::{self, RewardKind}; use ethash::{quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor}; use ethereum_types::{H256, H64, U256, Address}; use unexpected::{OutOfBounds, Mismatch}; @@ -233,11 +234,13 @@ impl Engine for Arc { /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { use std::ops::Shr; - use parity_machine::{LiveBlock, WithBalances}; + use parity_machine::LiveBlock; let author = *LiveBlock::header(&*block).author(); let number = LiveBlock::header(&*block).number(); + let mut rewards = Vec::new(); + // Applies EIP-649 reward. let reward = if number >= self.ethash_params.eip649_transition { self.ethash_params.eip649_reward.unwrap_or(self.ethash_params.block_reward) @@ -253,20 +256,21 @@ impl Engine for Arc { // Bestow block rewards. let mut result_block_reward = reward + reward.shr(5) * U256::from(n_uncles); - let mut uncle_rewards = Vec::with_capacity(n_uncles); if number >= self.ethash_params.mcip3_transition { result_block_reward = self.ethash_params.mcip3_miner_reward; + let ubi_contract = self.ethash_params.mcip3_ubi_contract; let ubi_reward = self.ethash_params.mcip3_ubi_reward; let dev_contract = self.ethash_params.mcip3_dev_contract; let dev_reward = self.ethash_params.mcip3_dev_reward; - self.machine.add_balance(block, &author, &result_block_reward)?; - self.machine.add_balance(block, &ubi_contract, &ubi_reward)?; - self.machine.add_balance(block, &dev_contract, &dev_reward)?; + rewards.push((author, RewardKind::Author, result_block_reward)); + rewards.push((ubi_contract, RewardKind::External, ubi_reward)); + rewards.push((dev_contract, RewardKind::External, dev_reward)); + } else { - self.machine.add_balance(block, &author, &result_block_reward)?; + rewards.push((author, RewardKind::Author, result_block_reward)); } // Bestow uncle rewards. @@ -278,15 +282,10 @@ impl Engine for Arc { reward.shr(5) }; - uncle_rewards.push((*uncle_author, result_uncle_reward)); - } - - for &(ref a, ref reward) in &uncle_rewards { - self.machine.add_balance(block, a, reward)?; + rewards.push((*uncle_author, RewardKind::Uncle, result_uncle_reward)); } - // Note and trace. - self.machine.note_rewards(block, &[(author, result_block_reward)], &uncle_rewards) + block_reward::apply_block_rewards(&rewards, block, &self.machine) } fn verify_local_seal(&self, header: &Header) -> Result<(), Error> { diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index e3bf7d340ca..4aa72b50d92 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -437,22 +437,30 @@ impl ::parity_machine::WithBalances for EthereumMachine { fn add_balance(&self, live: &mut ExecutedBlock, address: &Address, amount: &U256) -> Result<(), Error> { live.state_mut().add_balance(address, amount, CleanupMode::NoEmpty).map_err(Into::into) } +} + +/// A state machine that uses block rewards. +pub trait WithRewards: ::parity_machine::Machine { + /// Note block rewards, traces each reward storing information about benefactor, amount and type + /// of reward. + fn note_rewards( + &self, + live: &mut Self::LiveBlock, + rewards: &[(Address, RewardType, U256)], + ) -> Result<(), Self::Error>; +} +impl WithRewards for EthereumMachine { fn note_rewards( &self, live: &mut Self::LiveBlock, - direct: &[(Address, U256)], - indirect: &[(Address, U256)], + rewards: &[(Address, RewardType, U256)], ) -> Result<(), Self::Error> { if let Tracing::Enabled(ref mut traces) = *live.traces_mut() { let mut tracer = ExecutiveTracer::default(); - for &(address, amount) in direct { - tracer.trace_reward(address, amount, RewardType::Block); - } - - for &(address, amount) in indirect { - tracer.trace_reward(address, amount, RewardType::Uncle); + for &(address, ref reward_type, amount) in rewards { + tracer.trace_reward(address, amount, reward_type.clone()); } traces.push(tracer.drain().into()); diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index 06f24efac38..cdb00a52294 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -141,6 +141,10 @@ pub enum RewardType { Block, /// Uncle Uncle, + /// Empty step (AuthorityRound) + EmptyStep, + /// A reward directly attributed by an external protocol (e.g. block reward contract) + External, } impl Encodable for RewardType { @@ -148,6 +152,8 @@ impl Encodable for RewardType { let v = match *self { RewardType::Block => 0u32, RewardType::Uncle => 1, + RewardType::EmptyStep => 2, + RewardType::External => 3, }; Encodable::rlp_append(&v, s); } @@ -158,6 +164,8 @@ impl Decodable for RewardType { rlp.as_val().and_then(|v| Ok(match v { 0u32 => RewardType::Block, 1 => RewardType::Uncle, + 2 => RewardType::EmptyStep, + 3 => RewardType::External, _ => return Err(DecoderError::Custom("Invalid value of RewardType item")), })) } diff --git a/machine/src/lib.rs b/machine/src/lib.rs index 3a45c38d2ef..54ee403d954 100644 --- a/machine/src/lib.rs +++ b/machine/src/lib.rs @@ -106,12 +106,4 @@ pub trait WithBalances: Machine { /// Increment the balance of an account in the state of the live block. fn add_balance(&self, live: &mut Self::LiveBlock, address: &Address, amount: &U256) -> Result<(), Self::Error>; - - /// Note block rewards. "direct" rewards are for authors, "indirect" are for e.g. uncles. - fn note_rewards( - &self, - _live: &mut Self::LiveBlock, - _direct: &[(Address, U256)], - _indirect: &[(Address, U256)], - ) -> Result<(), Self::Error> { Ok(()) } } diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index a984c64ba80..6eb222f5e63 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -308,6 +308,12 @@ pub enum RewardType { /// Uncle #[serde(rename="uncle")] Uncle, + /// EmptyStep (AuthorityRound) + #[serde(rename="emptyStep")] + EmptyStep, + /// External (attributed as part of an external protocol) + #[serde(rename="external")] + External, } impl From for RewardType { @@ -315,6 +321,8 @@ impl From for RewardType { match c { trace::RewardType::Block => RewardType::Block, trace::RewardType::Uncle => RewardType::Uncle, + trace::RewardType::EmptyStep => RewardType::EmptyStep, + trace::RewardType::External => RewardType::External, } } } From 528497b86a93c64f317dd869da47010c2675e4ed Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 7 May 2018 18:58:25 +0800 Subject: [PATCH 38/95] Keep all enacted blocks notify in order (#8524) * Keep all enacted blocks notify in order * Collect is unnecessary * Update ChainNotify to use ChainRouteType * Fix all ethcore fn defs * Wrap the type within ChainRoute * Fix private-tx and sync api * Fix secret_store API * Fix updater API * Fix rpc api * Fix informant api * Eagerly cache enacted/retracted and remove contain_enacted/retracted * Fix indent * tests: should use full expr form for struct constructor * Use into_enacted_retracted to further avoid copy * typo: not a function * rpc/tests: ChainRoute -> ChainRoute::new --- ethcore/private-tx/src/lib.rs | 4 +- ethcore/src/blockchain/import_route.rs | 2 +- ethcore/src/client/chain_notify.rs | 88 ++++++++++++++++++- ethcore/src/client/client.rs | 49 +++-------- ethcore/src/client/mod.rs | 2 +- ethcore/src/snapshot/watcher.rs | 10 +-- ethcore/sync/src/api.rs | 9 +- ethcore/sync/src/tests/helpers.rs | 7 +- parity/informant.rs | 4 +- rpc/src/v1/impls/eth_pubsub.rs | 49 ++++++----- rpc/src/v1/tests/mocked/eth_pubsub.rs | 10 +-- secret_store/src/acl_storage.rs | 6 +- secret_store/src/key_server_set.rs | 6 +- .../src/listener/service_contract_listener.rs | 6 +- updater/src/updater.rs | 4 +- 15 files changed, 158 insertions(+), 98 deletions(-) diff --git a/ethcore/private-tx/src/lib.rs b/ethcore/private-tx/src/lib.rs index 26a31fc7ae3..723d4918298 100644 --- a/ethcore/private-tx/src/lib.rs +++ b/ethcore/private-tx/src/lib.rs @@ -79,7 +79,7 @@ use ethcore::executed::{Executed}; use transaction::{SignedTransaction, Transaction, Action, UnverifiedTransaction}; use ethcore::{contract_address as ethcore_contract_address}; use ethcore::client::{ - Client, ChainNotify, ChainMessageType, ClientIoMessage, BlockId, CallContract + Client, ChainNotify, ChainRoute, ChainMessageType, ClientIoMessage, BlockId, CallContract }; use ethcore::account_provider::AccountProvider; use ethcore::miner::{self, Miner, MinerService}; @@ -668,7 +668,7 @@ fn find_account_password(passwords: &Vec, account_provider: &AccountProv } impl ChainNotify for Provider { - fn new_blocks(&self, imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: Duration) { + fn new_blocks(&self, imported: Vec, _invalid: Vec, _route: ChainRoute, _sealed: Vec, _proposed: Vec, _duration: Duration) { if !imported.is_empty() { trace!("New blocks imported, try to prune the queue"); if let Err(err) = self.process_queue() { diff --git a/ethcore/src/blockchain/import_route.rs b/ethcore/src/blockchain/import_route.rs index cf5d3ca1e78..080d3b06824 100644 --- a/ethcore/src/blockchain/import_route.rs +++ b/ethcore/src/blockchain/import_route.rs @@ -20,7 +20,7 @@ use ethereum_types::H256; use blockchain::block_info::{BlockInfo, BlockLocation}; /// Import route for newly inserted block. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct ImportRoute { /// Blocks that were invalidated by new block. pub retracted: Vec, diff --git a/ethcore/src/client/chain_notify.rs b/ethcore/src/client/chain_notify.rs index a1f84d2a139..8330fb40d9e 100644 --- a/ethcore/src/client/chain_notify.rs +++ b/ethcore/src/client/chain_notify.rs @@ -17,7 +17,9 @@ use bytes::Bytes; use ethereum_types::H256; use transaction::UnverifiedTransaction; +use blockchain::ImportRoute; use std::time::Duration; +use std::collections::HashMap; /// Messages to broadcast via chain pub enum ChainMessageType { @@ -29,6 +31,89 @@ pub enum ChainMessageType { SignedPrivateTransaction(Vec), } +/// Route type to indicate whether it is enacted or retracted. +#[derive(Clone)] +pub enum ChainRouteType { + /// Enacted block + Enacted, + /// Retracted block + Retracted +} + +/// A complete chain enacted retracted route. +#[derive(Default, Clone)] +pub struct ChainRoute { + route: Vec<(H256, ChainRouteType)>, + enacted: Vec, + retracted: Vec, +} + +impl<'a> From<&'a [ImportRoute]> for ChainRoute { + fn from(import_results: &'a [ImportRoute]) -> ChainRoute { + ChainRoute::new(import_results.iter().flat_map(|route| { + route.retracted.iter().map(|h| (*h, ChainRouteType::Retracted)) + .chain(route.enacted.iter().map(|h| (*h, ChainRouteType::Enacted))) + }).collect()) + } +} + +impl ChainRoute { + /// Create a new ChainRoute based on block hash and route type pairs. + pub fn new(route: Vec<(H256, ChainRouteType)>) -> Self { + let (enacted, retracted) = Self::to_enacted_retracted(&route); + + Self { route, enacted, retracted } + } + + /// Gather all non-duplicate enacted and retracted blocks. + fn to_enacted_retracted(route: &[(H256, ChainRouteType)]) -> (Vec, Vec) { + fn map_to_vec(map: Vec<(H256, bool)>) -> Vec { + map.into_iter().map(|(k, _v)| k).collect() + } + + // Because we are doing multiple inserts some of the blocks that were enacted in import `k` + // could be retracted in import `k+1`. This is why to understand if after all inserts + // the block is enacted or retracted we iterate over all routes and at the end final state + // will be in the hashmap + let map = route.iter().fold(HashMap::new(), |mut map, route| { + match &route.1 { + &ChainRouteType::Enacted => { + map.insert(route.0, true); + }, + &ChainRouteType::Retracted => { + map.insert(route.0, false); + }, + } + map + }); + + // Split to enacted retracted (using hashmap value) + let (enacted, retracted) = map.into_iter().partition(|&(_k, v)| v); + // And convert tuples to keys + (map_to_vec(enacted), map_to_vec(retracted)) + } + + /// Consume route and return the enacted retracted form. + pub fn into_enacted_retracted(self) -> (Vec, Vec) { + (self.enacted, self.retracted) + } + + /// All non-duplicate enacted blocks. + pub fn enacted(&self) -> &[H256] { + &self.enacted + } + + /// All non-duplicate retracted blocks. + pub fn retracted(&self) -> &[H256] { + &self.retracted + } + + /// All blocks in the route. + pub fn route(&self) -> &[(H256, ChainRouteType)] { + &self.route + } +} + /// Represents what has to be handled by actor listening to chain events pub trait ChainNotify : Send + Sync { /// fires when chain has new blocks. @@ -36,8 +121,7 @@ pub trait ChainNotify : Send + Sync { &self, _imported: Vec, _invalid: Vec, - _enacted: Vec, - _retracted: Vec, + _route: ChainRoute, _sealed: Vec, // Block bytes. _proposed: Vec, diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index a37d62a5911..8119ebd35f6 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::collections::{HashSet, HashMap, BTreeMap, BTreeSet, VecDeque}; +use std::collections::{HashSet, BTreeMap, BTreeSet, VecDeque}; use std::str::FromStr; use std::sync::{Arc, Weak}; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; @@ -45,7 +45,7 @@ use client::{ use client::{ BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient, TraceFilter, CallAnalytics, BlockImportError, Mode, - ChainNotify, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType + ChainNotify, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType }; use encoded; use engines::{EthEngine, EpochTransition}; @@ -245,32 +245,6 @@ impl Importer { }) } - fn calculate_enacted_retracted(&self, import_results: &[ImportRoute]) -> (Vec, Vec) { - fn map_to_vec(map: Vec<(H256, bool)>) -> Vec { - map.into_iter().map(|(k, _v)| k).collect() - } - - // In ImportRoute we get all the blocks that have been enacted and retracted by single insert. - // Because we are doing multiple inserts some of the blocks that were enacted in import `k` - // could be retracted in import `k+1`. This is why to understand if after all inserts - // the block is enacted or retracted we iterate over all routes and at the end final state - // will be in the hashmap - let map = import_results.iter().fold(HashMap::new(), |mut map, route| { - for hash in &route.enacted { - map.insert(hash.clone(), true); - } - for hash in &route.retracted { - map.insert(hash.clone(), false); - } - map - }); - - // Split to enacted retracted (using hashmap value) - let (enacted, retracted) = map.into_iter().partition(|&(_k, v)| v); - // And convert tuples to keys - (map_to_vec(enacted), map_to_vec(retracted)) - } - /// This is triggered by a message coming from a block queue when the block is ready for insertion pub fn import_verified_blocks(&self, client: &Client) -> usize { @@ -336,18 +310,17 @@ impl Importer { { if !imported_blocks.is_empty() && is_empty { - let (enacted, retracted) = self.calculate_enacted_retracted(&import_results); + let route = ChainRoute::from(import_results.as_ref()); if is_empty { - self.miner.chain_new_blocks(client, &imported_blocks, &invalid_blocks, &enacted, &retracted, false); + self.miner.chain_new_blocks(client, &imported_blocks, &invalid_blocks, route.enacted(), route.retracted(), false); } client.notify(|notify| { notify.new_blocks( imported_blocks.clone(), invalid_blocks.clone(), - enacted.clone(), - retracted.clone(), + route.clone(), Vec::new(), proposed_blocks.clone(), duration, @@ -1421,7 +1394,7 @@ impl ImportBlock for Client { } fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result { - let header: Header = ::rlp::Rlp::new(&block_bytes).val_at(0)?; + let header: Header = ::rlp::Rlp::new(&block_bytes).val_at(0)?; { // check block order if self.chain.read().is_known(&header.hash()) { @@ -2155,14 +2128,13 @@ impl ImportSealedBlock for Client { self.state_db.write().sync_cache(&route.enacted, &route.retracted, false); route }; - let (enacted, retracted) = self.importer.calculate_enacted_retracted(&[route]); - self.importer.miner.chain_new_blocks(self, &[h.clone()], &[], &enacted, &retracted, true); + let route = ChainRoute::from([route].as_ref()); + self.importer.miner.chain_new_blocks(self, &[h.clone()], &[], route.enacted(), route.retracted(), true); self.notify(|notify| { notify.new_blocks( vec![h.clone()], vec![], - enacted.clone(), - retracted.clone(), + route.clone(), vec![h.clone()], vec![], start.elapsed(), @@ -2180,8 +2152,7 @@ impl BroadcastProposalBlock for Client { notify.new_blocks( vec![], vec![], - vec![], - vec![], + ChainRoute::default(), vec![], vec![block.rlp_bytes()], DURATION_ZERO, diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 1e4ccba585f..05e2018258f 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -31,7 +31,7 @@ pub use self::error::Error; pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactResult}; pub use self::io_message::ClientIoMessage; pub use self::test_client::{TestBlockChainClient, EachBlockWith}; -pub use self::chain_notify::{ChainNotify, ChainMessageType}; +pub use self::chain_notify::{ChainNotify, ChainRoute, ChainRouteType, ChainMessageType}; pub use self::traits::{ Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, PrepareOpenBlock, CallContract, TransactionInfo, RegistryInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock, StateClient, Call, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter diff --git a/ethcore/src/snapshot/watcher.rs b/ethcore/src/snapshot/watcher.rs index 936feaefba8..6e04fe6d16d 100644 --- a/ethcore/src/snapshot/watcher.rs +++ b/ethcore/src/snapshot/watcher.rs @@ -17,7 +17,7 @@ //! Watcher for snapshot-related chain events. use parking_lot::Mutex; -use client::{BlockInfo, Client, ChainNotify, ClientIoMessage}; +use client::{BlockInfo, Client, ChainNotify, ChainRoute, ClientIoMessage}; use ids::BlockId; use io::IoChannel; @@ -103,8 +103,7 @@ impl ChainNotify for Watcher { &self, imported: Vec, _: Vec, - _: Vec, - _: Vec, + _: ChainRoute, _: Vec, _: Vec, _duration: Duration) @@ -131,7 +130,7 @@ impl ChainNotify for Watcher { mod tests { use super::{Broadcast, Oracle, Watcher}; - use client::ChainNotify; + use client::{ChainNotify, ChainRoute}; use ethereum_types::{H256, U256}; @@ -174,8 +173,7 @@ mod tests { watcher.new_blocks( hashes, vec![], - vec![], - vec![], + ChainRoute::default(), vec![], vec![], DURATION_ZERO, diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index 5e96f11cf37..7690eeb864b 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -25,7 +25,7 @@ use network::{NetworkProtocolHandler, NetworkContext, HostInfo, PeerId, Protocol use ethereum_types::{H256, H512, U256}; use io::{TimerToken}; use ethcore::ethstore::ethkey::Secret; -use ethcore::client::{BlockChainClient, ChainNotify, ChainMessageType}; +use ethcore::client::{BlockChainClient, ChainNotify, ChainRoute, ChainMessageType}; use ethcore::snapshot::SnapshotService; use ethcore::header::BlockNumber; use sync_io::NetSyncIo; @@ -409,8 +409,7 @@ impl ChainNotify for EthSync { fn new_blocks(&self, imported: Vec, invalid: Vec, - enacted: Vec, - retracted: Vec, + route: ChainRoute, sealed: Vec, proposed: Vec, _duration: Duration) @@ -424,8 +423,8 @@ impl ChainNotify for EthSync { &mut sync_io, &imported, &invalid, - &enacted, - &retracted, + route.enacted(), + route.retracted(), &sealed, &proposed); }); diff --git a/ethcore/sync/src/tests/helpers.rs b/ethcore/sync/src/tests/helpers.rs index 54467adb775..dc52fdd8b85 100644 --- a/ethcore/sync/src/tests/helpers.rs +++ b/ethcore/sync/src/tests/helpers.rs @@ -23,7 +23,7 @@ use bytes::Bytes; use network::{self, PeerId, ProtocolId, PacketId, SessionInfo}; use tests::snapshot::*; use ethcore::client::{TestBlockChainClient, BlockChainClient, Client as EthcoreClient, - ClientConfig, ChainNotify, ChainMessageType, ClientIoMessage}; + ClientConfig, ChainNotify, ChainRoute, ChainMessageType, ClientIoMessage}; use ethcore::header::BlockNumber; use ethcore::snapshot::SnapshotService; use ethcore::spec::Spec; @@ -535,12 +535,13 @@ impl ChainNotify for EthPeer { fn new_blocks(&self, imported: Vec, invalid: Vec, - enacted: Vec, - retracted: Vec, + route: ChainRoute, sealed: Vec, proposed: Vec, _duration: Duration) { + let (enacted, retracted) = route.into_enacted_retracted(); + self.new_blocks_queue.write().push_back(NewBlockMessage { imported, invalid, diff --git a/parity/informant.rs b/parity/informant.rs index 5c2e0ab89d3..beeb258b522 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -25,7 +25,7 @@ use std::time::{Instant, Duration}; use atty; use ethcore::client::{ BlockId, BlockChainClient, ChainInfo, BlockInfo, BlockChainInfo, - BlockQueueInfo, ChainNotify, ClientReport, Client, ClientIoMessage + BlockQueueInfo, ChainNotify, ChainRoute, ClientReport, Client, ClientIoMessage }; use ethcore::header::BlockNumber; use ethcore::snapshot::{RestorationStatus, SnapshotService as SS}; @@ -351,7 +351,7 @@ impl Informant { } impl ChainNotify for Informant { - fn new_blocks(&self, imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, duration: Duration) { + fn new_blocks(&self, imported: Vec, _invalid: Vec, _route: ChainRoute, _sealed: Vec, _proposed: Vec, duration: Duration) { let mut last_import = self.last_import.lock(); let client = &self.target.client; diff --git a/rpc/src/v1/impls/eth_pubsub.rs b/rpc/src/v1/impls/eth_pubsub.rs index 1a872f5600a..30459594466 100644 --- a/rpc/src/v1/impls/eth_pubsub.rs +++ b/rpc/src/v1/impls/eth_pubsub.rs @@ -34,7 +34,7 @@ use v1::types::{pubsub, RichHeader, Log}; use ethcore::encoded; use ethcore::filter::Filter as EthFilter; -use ethcore::client::{BlockChainClient, ChainNotify, BlockId}; +use ethcore::client::{BlockChainClient, ChainNotify, ChainRoute, ChainRouteType, BlockId}; use sync::LightSync; use light::cache::Cache; use light::on_demand::OnDemand; @@ -141,19 +141,20 @@ impl ChainNotificationHandler { } } - fn notify_logs(&self, enacted: &[H256], logs: F) where - F: Fn(EthFilter) -> T, + fn notify_logs(&self, enacted: &[(H256, Ex)], logs: F) where + F: Fn(EthFilter, &Ex) -> T, + Ex: Send, T: IntoFuture, Error = Error>, T::Future: Send + 'static, { for &(ref subscriber, ref filter) in self.logs_subscribers.read().values() { let logs = futures::future::join_all(enacted .iter() - .map(|hash| { + .map(|&(hash, ref ex)| { let mut filter = filter.clone(); - filter.from_block = BlockId::Hash(*hash); + filter.from_block = BlockId::Hash(hash); filter.to_block = filter.from_block.clone(); - logs(filter).into_future() + logs(filter, ex).into_future() }) .collect::>() ); @@ -214,7 +215,7 @@ impl LightChainNotify for ChainNotificationHandler { .collect::>(); self.notify_heads(&headers); - self.notify_logs(&enacted, |filter| self.client.logs(filter)) + self.notify_logs(&enacted.iter().map(|h| (*h, ())).collect::>(), |filter, _| self.client.logs(filter)) } } @@ -223,17 +224,21 @@ impl ChainNotify for ChainNotificationHandler { &self, _imported: Vec, _invalid: Vec, - enacted: Vec, - retracted: Vec, + route: ChainRoute, _sealed: Vec, // Block bytes. _proposed: Vec, _duration: Duration, ) { const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed"; - let headers = enacted + let headers = route.route() .iter() - .filter_map(|hash| self.client.block_header(BlockId::Hash(*hash))) + .filter_map(|&(hash, ref typ)| { + match typ { + &ChainRouteType::Retracted => None, + &ChainRouteType::Enacted => self.client.block_header(BlockId::Hash(hash)) + } + }) .map(|header| { let hash = header.hash(); (header, self.client.block_extra_info(BlockId::Hash(hash)).expect(EXTRA_INFO_PROOF)) @@ -243,17 +248,17 @@ impl ChainNotify for ChainNotificationHandler { // Headers self.notify_heads(&headers); - // Enacted logs - self.notify_logs(&enacted, |filter| { - Ok(self.client.logs(filter).into_iter().map(Into::into).collect()) - }); - - // Retracted logs - self.notify_logs(&retracted, |filter| { - Ok(self.client.logs(filter).into_iter().map(Into::into).map(|mut log: Log| { - log.log_type = "removed".into(); - log - }).collect()) + // We notify logs enacting and retracting as the order in route. + self.notify_logs(route.route(), |filter, ex| { + match ex { + &ChainRouteType::Enacted => + Ok(self.client.logs(filter).into_iter().map(Into::into).collect()), + &ChainRouteType::Retracted => + Ok(self.client.logs(filter).into_iter().map(Into::into).map(|mut log: Log| { + log.log_type = "removed".into(); + log + }).collect()), + } }); } } diff --git a/rpc/src/v1/tests/mocked/eth_pubsub.rs b/rpc/src/v1/tests/mocked/eth_pubsub.rs index fb28ba31274..936695a9a13 100644 --- a/rpc/src/v1/tests/mocked/eth_pubsub.rs +++ b/rpc/src/v1/tests/mocked/eth_pubsub.rs @@ -24,7 +24,7 @@ use std::time::Duration; use v1::{EthPubSub, EthPubSubClient, Metadata}; -use ethcore::client::{TestBlockChainClient, EachBlockWith, ChainNotify}; +use ethcore::client::{TestBlockChainClient, EachBlockWith, ChainNotify, ChainRoute, ChainRouteType}; use parity_reactor::EventLoop; const DURATION_ZERO: Duration = Duration::from_millis(0); @@ -57,13 +57,13 @@ fn should_subscribe_to_new_heads() { assert_eq!(io.handle_request_sync(request, metadata.clone()), Some(response.to_owned())); // Check notifications - handler.new_blocks(vec![], vec![], vec![h1], vec![], vec![], vec![], DURATION_ZERO); + handler.new_blocks(vec![], vec![], ChainRoute::new(vec![(h1, ChainRouteType::Enacted)]), vec![], vec![], DURATION_ZERO); let (res, receiver) = receiver.into_future().wait().unwrap(); let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"author":"0x0000000000000000000000000000000000000000","difficulty":"0x1","extraData":"0x","gasLimit":"0xf4240","gasUsed":"0x0","hash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","number":"0x1","parentHash":"0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x1c9","stateRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","timestamp":"0x0","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"},"subscription":"0x416d77337e24399d"}}"#; assert_eq!(res, Some(response.into())); // Notify about two blocks - handler.new_blocks(vec![], vec![], vec![h2, h3], vec![], vec![], vec![], DURATION_ZERO); + handler.new_blocks(vec![], vec![], ChainRoute::new(vec![(h2, ChainRouteType::Enacted), (h3, ChainRouteType::Enacted)]), vec![], vec![], DURATION_ZERO); // Receive both let (res, receiver) = receiver.into_future().wait().unwrap(); @@ -129,7 +129,7 @@ fn should_subscribe_to_logs() { assert_eq!(io.handle_request_sync(request, metadata.clone()), Some(response.to_owned())); // Check notifications (enacted) - handler.new_blocks(vec![], vec![], vec![h1], vec![], vec![], vec![], DURATION_ZERO); + handler.new_blocks(vec![], vec![], ChainRoute::new(vec![(h1, ChainRouteType::Enacted)]), vec![], vec![], DURATION_ZERO); let (res, receiver) = receiver.into_future().wait().unwrap(); let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"address":"0x0000000000000000000000000000000000000005","blockHash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","blockNumber":"0x1","data":"0x","logIndex":"0x0","topics":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"transactionHash":""#.to_owned() + &format!("0x{:x}", tx_hash) @@ -137,7 +137,7 @@ fn should_subscribe_to_logs() { assert_eq!(res, Some(response.into())); // Check notifications (retracted) - handler.new_blocks(vec![], vec![], vec![], vec![h1], vec![], vec![], DURATION_ZERO); + handler.new_blocks(vec![], vec![], ChainRoute::new(vec![(h1, ChainRouteType::Retracted)]), vec![], vec![], DURATION_ZERO); let (res, receiver) = receiver.into_future().wait().unwrap(); let response = r#"{"jsonrpc":"2.0","method":"eth_subscription","params":{"result":{"address":"0x0000000000000000000000000000000000000005","blockHash":"0x3457d2fa2e3dd33c78ac681cf542e429becf718859053448748383af67e23218","blockNumber":"0x1","data":"0x","logIndex":"0x0","topics":["0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"transactionHash":""#.to_owned() + &format!("0x{:x}", tx_hash) diff --git a/secret_store/src/acl_storage.rs b/secret_store/src/acl_storage.rs index 50414eff26c..b3427fa1b20 100644 --- a/secret_store/src/acl_storage.rs +++ b/secret_store/src/acl_storage.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use std::collections::{HashMap, HashSet}; use std::time::Duration; use parking_lot::{Mutex, RwLock}; -use ethcore::client::{BlockId, ChainNotify, CallContract, RegistryInfo}; +use ethcore::client::{BlockId, ChainNotify, ChainRoute, CallContract, RegistryInfo}; use ethereum_types::{H256, Address}; use bytes::Bytes; use trusted_client::TrustedClient; @@ -76,8 +76,8 @@ impl AclStorage for OnChainAclStorage { } impl ChainNotify for OnChainAclStorage { - fn new_blocks(&self, _imported: Vec, _invalid: Vec, enacted: Vec, retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: Duration) { - if !enacted.is_empty() || !retracted.is_empty() { + fn new_blocks(&self, _imported: Vec, _invalid: Vec, route: ChainRoute, _sealed: Vec, _proposed: Vec, _duration: Duration) { + if !route.enacted().is_empty() || !route.retracted().is_empty() { self.contract.lock().update() } } diff --git a/secret_store/src/key_server_set.rs b/secret_store/src/key_server_set.rs index 25651bb4cad..d13017261c4 100644 --- a/secret_store/src/key_server_set.rs +++ b/secret_store/src/key_server_set.rs @@ -19,7 +19,7 @@ use std::net::SocketAddr; use std::collections::{BTreeMap, HashSet}; use std::time::Duration; use parking_lot::Mutex; -use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify, CallContract, RegistryInfo}; +use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify, ChainRoute, CallContract, RegistryInfo}; use ethcore::filter::Filter; use ethkey::public_to_address; use hash::keccak; @@ -163,7 +163,9 @@ impl KeyServerSet for OnChainKeyServerSet { } impl ChainNotify for OnChainKeyServerSet { - fn new_blocks(&self, _imported: Vec, _invalid: Vec, enacted: Vec, retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: Duration) { + fn new_blocks(&self, _imported: Vec, _invalid: Vec, route: ChainRoute, _sealed: Vec, _proposed: Vec, _duration: Duration) { + let (enacted, retracted) = route.into_enacted_retracted(); + if !enacted.is_empty() || !retracted.is_empty() { self.contract.lock().update(enacted, retracted) } diff --git a/secret_store/src/listener/service_contract_listener.rs b/secret_store/src/listener/service_contract_listener.rs index 0e273b3eeee..214235210fa 100644 --- a/secret_store/src/listener/service_contract_listener.rs +++ b/secret_store/src/listener/service_contract_listener.rs @@ -20,7 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Duration; use std::thread; use parking_lot::Mutex; -use ethcore::client::ChainNotify; +use ethcore::client::{ChainNotify, ChainRoute}; use ethkey::{Public, public_to_address}; use bytes::Bytes; use ethereum_types::{H256, U256, Address}; @@ -428,8 +428,8 @@ impl Drop for ServiceContractListener { } impl ChainNotify for ServiceContractListener { - fn new_blocks(&self, _imported: Vec, _invalid: Vec, enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: Duration) { - let enacted_len = enacted.len(); + fn new_blocks(&self, _imported: Vec, _invalid: Vec, route: ChainRoute, _sealed: Vec, _proposed: Vec, _duration: Duration) { + let enacted_len = route.enacted().len(); if enacted_len == 0 { return; } diff --git a/updater/src/updater.rs b/updater/src/updater.rs index c5f45c7658a..f8a98f3b0f4 100644 --- a/updater/src/updater.rs +++ b/updater/src/updater.rs @@ -28,7 +28,7 @@ use target_info::Target; use bytes::Bytes; use ethcore::BlockNumber; use ethcore::filter::Filter; -use ethcore::client::{BlockId, BlockChainClient, ChainNotify}; +use ethcore::client::{BlockId, BlockChainClient, ChainNotify, ChainRoute}; use ethereum_types::H256; use sync::{SyncProvider}; use hash_fetch::{self as fetch, HashFetch}; @@ -660,7 +660,7 @@ impl Updater, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: Duration) { + fn new_blocks(&self, _imported: Vec, _invalid: Vec, _route: ChainRoute, _sealed: Vec, _proposed: Vec, _duration: Duration) { match (self.client.upgrade(), self.sync.as_ref().and_then(Weak::upgrade)) { (Some(ref c), Some(ref s)) if !s.status().is_syncing(c.queue_info()) => self.poll(), _ => {}, From a7a46f425369fd662042cb4a1c9ffc301b3b5b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Mon, 7 May 2018 12:11:12 +0100 Subject: [PATCH 39/95] Node table sorting according to last contact data (#8541) * network-devp2p: sort nodes in node table using last contact data * network-devp2p: rename node contact types in node table json output * network-devp2p: fix node table tests * network-devp2p: note node failure when failed to establish connection * network-devp2p: handle UselessPeer error * network-devp2p: note failure when marking node as useless --- util/network-devp2p/src/host.rs | 28 +++- util/network-devp2p/src/node_table.rs | 230 +++++++++++++++++++------- 2 files changed, 188 insertions(+), 70 deletions(-) diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index 73ca2aca4bd..2de9a1884c8 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -105,10 +105,13 @@ pub struct NetworkContext<'s> { impl<'s> NetworkContext<'s> { /// Create a new network IO access point. Takes references to all the data that can be updated within the IO handler. - fn new(io: &'s IoContext, + fn new( + io: &'s IoContext, protocol: ProtocolId, - session: Option, sessions: Arc>>, - reserved_peers: &'s HashSet) -> NetworkContext<'s> { + session: Option, + sessions: Arc>>, + reserved_peers: &'s HashSet, + ) -> NetworkContext<'s> { let id = session.as_ref().map(|s| s.lock().token()); NetworkContext { io: io, @@ -585,10 +588,8 @@ impl Host { let address = { let mut nodes = self.nodes.write(); if let Some(node) = nodes.get_mut(id) { - node.attempts += 1; node.endpoint.address - } - else { + } else { debug!(target: "network", "Connection to expired node aborted"); return; } @@ -600,6 +601,7 @@ impl Host { }, Err(e) => { debug!(target: "network", "{}: Can't connect to address {:?}: {:?}", id, address, e); + self.nodes.write().note_failure(&id); return; } } @@ -685,10 +687,12 @@ impl Host { Err(e) => { let s = session.lock(); trace!(target: "network", "Session read error: {}:{:?} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); - if let ErrorKind::Disconnect(DisconnectReason::IncompatibleProtocol) = *e.kind() { + if let ErrorKind::Disconnect(DisconnectReason::UselessPeer) = *e.kind() { if let Some(id) = s.id() { if !self.reserved_nodes.read().contains(id) { - self.nodes.write().mark_as_useless(id); + let mut nodes = self.nodes.write(); + nodes.note_failure(&id); + nodes.mark_as_useless(id); } } } @@ -754,6 +758,10 @@ impl Host { } } } + + // Note connection success + self.nodes.write().note_success(&id); + for (p, _) in self.handlers.read().iter() { if s.have_capability(*p) { ready_data.push(*p); @@ -1024,7 +1032,9 @@ impl IoHandler for Host { if let Some(session) = session { session.lock().disconnect(io, DisconnectReason::DisconnectRequested); if let Some(id) = session.lock().id() { - self.nodes.write().mark_as_useless(id) + let mut nodes = self.nodes.write(); + nodes.note_failure(&id); + nodes.mark_as_useless(id); } } trace!(target: "network", "Disabling peer {}", peer); diff --git a/util/network-devp2p/src/node_table.rs b/util/network-devp2p/src/node_table.rs index fd18c10a12c..5079455866c 100644 --- a/util/network-devp2p/src/node_table.rs +++ b/util/network-devp2p/src/node_table.rs @@ -21,6 +21,8 @@ use std::net::{SocketAddr, ToSocketAddrs, SocketAddrV4, SocketAddrV6, Ipv4Addr, use std::path::PathBuf; use std::str::FromStr; use std::{fs, mem, slice}; +use std::time::{self, Duration, SystemTime}; +use rand::{self, Rng}; use ethereum_types::H512; use rlp::{Rlp, RlpStream, DecoderError}; use network::{Error, ErrorKind, AllowIP, IpFilter}; @@ -128,40 +130,64 @@ impl FromStr for NodeEndpoint { } } -#[derive(PartialEq, Eq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum PeerType { _Required, Optional } +/// A type for representing an interaction (contact) with a node at a given time +/// that was either a success or a failure. +#[derive(Clone, Copy, Debug)] +pub enum NodeContact { + Success(SystemTime), + Failure(SystemTime), +} + +impl NodeContact { + fn success() -> NodeContact { + NodeContact::Success(SystemTime::now()) + } + + fn failure() -> NodeContact { + NodeContact::Failure(SystemTime::now()) + } + + fn time(&self) -> SystemTime { + match *self { + NodeContact::Success(t) | NodeContact::Failure(t) => t + } + } + + /// Filters and old contact, returning `None` if it happened longer than a + /// week ago. + fn recent(&self) -> Option<&NodeContact> { + let t = self.time(); + if let Ok(d) = t.elapsed() { + if d < Duration::from_secs(60 * 60 * 24 * 7) { + return Some(self); + } + } + + None + } +} + +#[derive(Debug)] pub struct Node { pub id: NodeId, pub endpoint: NodeEndpoint, pub peer_type: PeerType, - pub attempts: u32, - pub failures: u32, + pub last_contact: Option, } -const DEFAULT_FAILURE_PERCENTAGE: usize = 50; - impl Node { pub fn new(id: NodeId, endpoint: NodeEndpoint) -> Node { Node { id: id, endpoint: endpoint, peer_type: PeerType::Optional, - attempts: 0, - failures: 0, - } - } - - /// Returns the node's failure percentage (0..100) in buckets of 5%. If there are 0 connection attempts for this - /// node the default failure percentage is returned (50%). - pub fn failure_percentage(&self) -> usize { - if self.attempts == 0 { - DEFAULT_FAILURE_PERCENTAGE - } else { - (self.failures * 100 / self.attempts / 5 * 5) as usize + last_contact: None, } } } @@ -191,8 +217,7 @@ impl FromStr for Node { id: id, endpoint: endpoint, peer_type: PeerType::Optional, - attempts: 0, - failures: 0, + last_contact: None, }) } } @@ -231,28 +256,61 @@ impl NodeTable { /// Add a node to table pub fn add_node(&mut self, mut node: Node) { - // preserve attempts and failure counter - let (attempts, failures) = - self.nodes.get(&node.id).map_or((0, 0), |n| (n.attempts, n.failures)); - - node.attempts = attempts; - node.failures = failures; - + // preserve node last_contact + node.last_contact = self.nodes.get(&node.id).and_then(|n| n.last_contact); self.nodes.insert(node.id.clone(), node); } + /// Returns a list of ordered nodes according to their most recent contact + /// and filtering useless nodes. The algorithm for creating the sorted nodes + /// is: + /// - Contacts that aren't recent (older than 1 week) are discarded + /// - (1) Nodes with a successful contact are ordered (most recent success first) + /// - (2) Nodes with unknown contact (older than 1 week or new nodes) are randomly shuffled + /// - (3) Nodes with a failed contact are ordered (oldest failure first) + /// - The final result is the concatenation of (1), (2) and (3) fn ordered_entries(&self) -> Vec<&Node> { - let mut refs: Vec<&Node> = self.nodes.values() - .filter(|n| !self.useless_nodes.contains(&n.id)) - .collect(); + let mut success = Vec::new(); + let mut failures = Vec::new(); + let mut unknown = Vec::new(); + + let nodes = self.nodes.values() + .filter(|n| !self.useless_nodes.contains(&n.id)); + + for node in nodes { + // discard contact points older that aren't recent + match node.last_contact.as_ref().and_then(|c| c.recent()) { + Some(&NodeContact::Success(_)) => { + success.push(node); + }, + Some(&NodeContact::Failure(_)) => { + failures.push(node); + }, + None => { + unknown.push(node); + }, + } + } - refs.sort_by(|a, b| { - a.failure_percentage().cmp(&b.failure_percentage()) - .then_with(|| a.failures.cmp(&b.failures)) - .then_with(|| b.attempts.cmp(&a.attempts)) // we use reverse ordering for number of attempts + success.sort_by(|a, b| { + let a = a.last_contact.expect("vector only contains values with defined last_contact; qed"); + let b = b.last_contact.expect("vector only contains values with defined last_contact; qed"); + // inverse ordering, most recent successes come first + b.time().cmp(&a.time()) }); - refs + failures.sort_by(|a, b| { + let a = a.last_contact.expect("vector only contains values with defined last_contact; qed"); + let b = b.last_contact.expect("vector only contains values with defined last_contact; qed"); + // normal ordering, most distant failures come first + a.time().cmp(&b.time()) + }); + + rand::thread_rng().shuffle(&mut unknown); + + success.append(&mut unknown); + success.append(&mut failures); + success } /// Returns node ids sorted by failure percentage, for nodes with the same failure percentage the absolute number of @@ -296,10 +354,17 @@ impl NodeTable { } } - /// Increase failure counte for a node + /// Set last contact as failure for a node pub fn note_failure(&mut self, id: &NodeId) { if let Some(node) = self.nodes.get_mut(id) { - node.failures += 1; + node.last_contact = Some(NodeContact::failure()); + } + } + + /// Set last contact as success for a node + pub fn note_success(&mut self, id: &NodeId) { + if let Some(node) = self.nodes.get_mut(id) { + node.last_contact = Some(NodeContact::success()); } } @@ -396,19 +461,38 @@ mod json { pub nodes: Vec, } + #[derive(Serialize, Deserialize)] + pub enum NodeContact { + #[serde(rename = "success")] + Success(u64), + #[serde(rename = "failure")] + Failure(u64), + } + + impl NodeContact { + pub fn into_node_contact(self) -> super::NodeContact { + match self { + NodeContact::Success(s) => super::NodeContact::Success( + time::UNIX_EPOCH + Duration::from_secs(s) + ), + NodeContact::Failure(s) => super::NodeContact::Failure( + time::UNIX_EPOCH + Duration::from_secs(s) + ), + } + } + } + #[derive(Serialize, Deserialize)] pub struct Node { pub url: String, - pub attempts: u32, - pub failures: u32, + pub last_contact: Option, } impl Node { pub fn into_node(self) -> Option { match super::Node::from_str(&self.url) { Ok(mut node) => { - node.attempts = self.attempts; - node.failures = self.failures; + node.last_contact = self.last_contact.map(|c| c.into_node_contact()); Some(node) }, _ => None, @@ -418,10 +502,18 @@ mod json { impl<'a> From<&'a super::Node> for Node { fn from(node: &'a super::Node) -> Self { + let last_contact = node.last_contact.and_then(|c| { + match c { + super::NodeContact::Success(t) => + t.duration_since(time::UNIX_EPOCH).ok().map(|d| NodeContact::Success(d.as_secs())), + super::NodeContact::Failure(t) => + t.duration_since(time::UNIX_EPOCH).ok().map(|d| NodeContact::Failure(d.as_secs())), + } + }); + Node { url: format!("{}", node), - attempts: node.attempts, - failures: node.failures, + last_contact } } } @@ -464,42 +556,54 @@ mod tests { } #[test] - fn table_failure_percentage_order() { + fn table_last_contact_order() { let node1 = Node::from_str("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap(); let node2 = Node::from_str("enode://b979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap(); let node3 = Node::from_str("enode://c979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap(); let node4 = Node::from_str("enode://d979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap(); + let node5 = Node::from_str("enode://e979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap(); + let node6 = Node::from_str("enode://f979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap(); let id1 = H512::from_str("a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c").unwrap(); let id2 = H512::from_str("b979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c").unwrap(); let id3 = H512::from_str("c979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c").unwrap(); let id4 = H512::from_str("d979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c").unwrap(); + let id5 = H512::from_str("e979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c").unwrap(); + let id6 = H512::from_str("f979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c").unwrap(); let mut table = NodeTable::new(None); table.add_node(node1); table.add_node(node2); table.add_node(node3); table.add_node(node4); + table.add_node(node5); + table.add_node(node6); - // node 1 - failure percentage 100% - table.get_mut(&id1).unwrap().attempts = 2; - table.note_failure(&id1); + // failures - nodes 1 & 2 table.note_failure(&id1); - - // node2 - failure percentage 33% - table.get_mut(&id2).unwrap().attempts = 3; table.note_failure(&id2); - // node3 - failure percentage 0% - table.get_mut(&id3).unwrap().attempts = 1; + // success - nodes 3 & 4 + table.note_success(&id3); + table.note_success(&id4); - // node4 - failure percentage 50% (default when no attempts) + // success - node 5 (old contact) + table.get_mut(&id5).unwrap().last_contact = Some(NodeContact::Success(time::UNIX_EPOCH)); + + // unknown - node 6 let r = table.nodes(IpFilter::default()); - assert_eq!(r[0][..], id3[..]); - assert_eq!(r[1][..], id2[..]); - assert_eq!(r[2][..], id4[..]); - assert_eq!(r[3][..], id1[..]); + assert_eq!(r[0][..], id4[..]); // most recent success + assert_eq!(r[1][..], id3[..]); + + // unknown (old contacts and new nodes), randomly shuffled + assert!( + r[2][..] == id5[..] && r[3][..] == id6[..] || + r[2][..] == id6[..] && r[3][..] == id5[..] + ); + + assert_eq!(r[4][..], id1[..]); // oldest failure + assert_eq!(r[5][..], id2[..]); } #[test] @@ -507,23 +611,27 @@ mod tests { let tempdir = TempDir::new("").unwrap(); let node1 = Node::from_str("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap(); let node2 = Node::from_str("enode://b979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap(); + let node3 = Node::from_str("enode://c979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap(); let id1 = H512::from_str("a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c").unwrap(); let id2 = H512::from_str("b979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c").unwrap(); + let id3 = H512::from_str("c979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c").unwrap(); + { let mut table = NodeTable::new(Some(tempdir.path().to_str().unwrap().to_owned())); table.add_node(node1); table.add_node(node2); + table.add_node(node3); - table.get_mut(&id1).unwrap().attempts = 1; - table.get_mut(&id2).unwrap().attempts = 1; - table.note_failure(&id2); + table.note_success(&id2); + table.note_failure(&id3); } { let table = NodeTable::new(Some(tempdir.path().to_str().unwrap().to_owned())); let r = table.nodes(IpFilter::default()); - assert_eq!(r[0][..], id1[..]); - assert_eq!(r[1][..], id2[..]); + assert_eq!(r[0][..], id2[..]); // latest success + assert_eq!(r[1][..], id1[..]); // unknown + assert_eq!(r[2][..], id3[..]); // oldest failure } } From 28c731881f2da0ceca4752dbcc1a8f9ad041f988 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 8 May 2018 11:22:12 +0200 Subject: [PATCH 40/95] Rlp decode returns Result (#8527) rlp::decode returns Result Make a best effort to handle decoding errors gracefully throughout the code, using `expect` where the value is guaranteed to be valid (and in other places where it makes sense). --- ethcore/light/src/client/header_chain.rs | 27 +++++++++++++----------- ethcore/light/src/net/request_credits.rs | 2 +- ethcore/light/src/types/request/mod.rs | 2 +- ethcore/src/blockchain/blockchain.rs | 4 ++-- ethcore/src/db.rs | 13 +++++------- ethcore/src/encoded.rs | 11 +++++----- ethcore/src/engines/tendermint/mod.rs | 6 ++++-- ethcore/src/header.rs | 4 ++-- ethcore/src/snapshot/account.rs | 6 +++--- ethcore/src/snapshot/mod.rs | 6 +++--- ethcore/src/snapshot/tests/helpers.rs | 2 +- ethcore/src/snapshot/tests/state.rs | 2 +- ethcore/src/state/account.rs | 23 +++++++++++--------- ethcore/src/state/mod.rs | 17 ++++++++++----- ethcore/src/trace/types/flat.rs | 2 +- ethcore/transaction/src/transaction.rs | 5 +++-- ethcore/types/src/receipt.rs | 4 ++-- ethcore/vm/src/call_type.rs | 2 +- rpc/src/v1/tests/mocked/eth.rs | 3 ++- util/journaldb/src/archivedb.rs | 13 ++++++------ util/journaldb/src/earlymergedb.rs | 2 +- util/journaldb/src/overlaydb.rs | 2 +- util/journaldb/src/overlayrecentdb.rs | 4 ++-- util/journaldb/src/refcounteddb.rs | 15 +++++++------ util/rlp/src/lib.rs | 6 +++--- util/rlp/tests/tests.rs | 6 ++++-- util/rlp_derive/tests/rlp.rs | 4 ++-- whisper/src/message.rs | 4 ++-- 28 files changed, 107 insertions(+), 90 deletions(-) diff --git a/ethcore/light/src/client/header_chain.rs b/ethcore/light/src/client/header_chain.rs index abcb04c3662..02a18a60dfe 100644 --- a/ethcore/light/src/client/header_chain.rs +++ b/ethcore/light/src/client/header_chain.rs @@ -228,7 +228,7 @@ impl HeaderChain { let decoded_header = spec.genesis_header(); let chain = if let Some(current) = db.get(col, CURRENT_KEY)? { - let curr : BestAndLatest = ::rlp::decode(¤t); + let curr : BestAndLatest = ::rlp::decode(¤t).expect("decoding db value failed"); let mut cur_number = curr.latest_num; let mut candidates = BTreeMap::new(); @@ -236,7 +236,7 @@ impl HeaderChain { // load all era entries, referenced headers within them, // and live epoch proofs. while let Some(entry) = db.get(col, era_key(cur_number).as_bytes())? { - let entry: Entry = ::rlp::decode(&entry); + let entry: Entry = ::rlp::decode(&entry).expect("decoding db value failed"); trace!(target: "chain", "loaded header chain entry for era {} with {} candidates", cur_number, entry.candidates.len()); @@ -524,7 +524,10 @@ impl HeaderChain { None } Ok(None) => panic!("stored candidates always have corresponding headers; qed"), - Ok(Some(header)) => Some((epoch_transition, ::rlp::decode(&header))), + Ok(Some(header)) => Some(( + epoch_transition, + ::rlp::decode(&header).expect("decoding value from db failed") + )), }; } } @@ -591,7 +594,7 @@ impl HeaderChain { in an inconsistent state", h_num); ErrorKind::Database(msg.into()) })?; - ::rlp::decode(&bytes) + ::rlp::decode(&bytes).expect("decoding db value failed") }; let total_difficulty = entry.candidates.iter() @@ -604,9 +607,9 @@ impl HeaderChain { .total_difficulty; break Ok(Some(SpecHardcodedSync { - header: header, - total_difficulty: total_difficulty, - chts: chts, + header, + total_difficulty, + chts, })); }, None => { @@ -742,7 +745,7 @@ impl HeaderChain { /// so including it within a CHT would be redundant. pub fn cht_root(&self, n: usize) -> Option { match self.db.get(self.col, cht_key(n as u64).as_bytes()) { - Ok(val) => val.map(|x| ::rlp::decode(&x)), + Ok(db_fetch) => db_fetch.map(|bytes| ::rlp::decode(&bytes).expect("decoding value from db failed")), Err(e) => { warn!(target: "chain", "Error reading from database: {}", e); None @@ -793,7 +796,7 @@ impl HeaderChain { pub fn pending_transition(&self, hash: H256) -> Option { let key = pending_transition_key(hash); match self.db.get(self.col, &*key) { - Ok(val) => val.map(|x| ::rlp::decode(&x)), + Ok(db_fetch) => db_fetch.map(|bytes| ::rlp::decode(&bytes).expect("decoding value from db failed")), Err(e) => { warn!(target: "chain", "Error reading from database: {}", e); None @@ -1192,7 +1195,7 @@ mod tests { let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); - let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).expect("failed to instantiate a new HeaderChain"); let mut parent_hash = genesis_header.hash(); let mut rolling_timestamp = genesis_header.timestamp(); @@ -1211,14 +1214,14 @@ mod tests { parent_hash = header.hash(); let mut tx = db.transaction(); - let pending = chain.insert(&mut tx, header, None).unwrap(); + let pending = chain.insert(&mut tx, header, None).expect("failed inserting a transaction"); db.write(tx).unwrap(); chain.apply_pending(pending); rolling_timestamp += 10; } - let hardcoded_sync = chain.read_hardcoded_sync().unwrap().unwrap(); + let hardcoded_sync = chain.read_hardcoded_sync().expect("failed reading hardcoded sync").expect("failed unwrapping hardcoded sync"); assert_eq!(hardcoded_sync.chts.len(), 3); assert_eq!(hardcoded_sync.total_difficulty, total_difficulty); let decoded: Header = hardcoded_sync.header.decode(); diff --git a/ethcore/light/src/net/request_credits.rs b/ethcore/light/src/net/request_credits.rs index abe609dabbd..29570b613cf 100644 --- a/ethcore/light/src/net/request_credits.rs +++ b/ethcore/light/src/net/request_credits.rs @@ -407,7 +407,7 @@ mod tests { let costs = CostTable::default(); let serialized = ::rlp::encode(&costs); - let new_costs: CostTable = ::rlp::decode(&*serialized); + let new_costs: CostTable = ::rlp::decode(&*serialized).unwrap(); assert_eq!(costs, new_costs); } diff --git a/ethcore/light/src/types/request/mod.rs b/ethcore/light/src/types/request/mod.rs index 8d911d3f555..bda992df975 100644 --- a/ethcore/light/src/types/request/mod.rs +++ b/ethcore/light/src/types/request/mod.rs @@ -1642,7 +1642,7 @@ mod tests { { // check as single value. let bytes = ::rlp::encode(&val); - let new_val: T = ::rlp::decode(&bytes); + let new_val: T = ::rlp::decode(&bytes).unwrap(); assert_eq!(val, new_val); // check as list containing single value. diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 57bcdf2bc28..0e18c5f889c 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -438,7 +438,7 @@ impl<'a> Iterator for EpochTransitionIter<'a> { return None } - let transitions: EpochTransitions = ::rlp::decode(&val[..]); + let transitions: EpochTransitions = ::rlp::decode(&val[..]).expect("decode error: the db is corrupted or the data structure has changed"); // if there are multiple candidates, at most one will be on the // canon chain. @@ -462,7 +462,7 @@ impl<'a> Iterator for EpochTransitionIter<'a> { impl BlockChain { /// Create new instance of blockchain from given Genesis. pub fn new(config: Config, genesis: &[u8], db: Arc) -> BlockChain { - // 400 is the avarage size of the key + // 400 is the average size of the key let cache_man = CacheManager::new(config.pref_cache_size, config.max_cache_size, 400); let mut bc = BlockChain { diff --git a/ethcore/src/db.rs b/ethcore/src/db.rs index d11adc7710d..a1c7d6b0f5e 100644 --- a/ethcore/src/db.rs +++ b/ethcore/src/db.rs @@ -218,15 +218,12 @@ impl Writable for DBTransaction { } impl Readable for KVDB { - fn read(&self, col: Option, key: &Key) -> Option where T: rlp::Decodable, R: Deref { - let result = self.get(col, &key.key()); + fn read(&self, col: Option, key: &Key) -> Option + where T: rlp::Decodable, R: Deref { + self.get(col, &key.key()) + .expect(&format!("db get failed, key: {:?}", &key.key() as &[u8])) + .map(|v| rlp::decode(&v).expect("decode db value failed") ) - match result { - Ok(option) => option.map(|v| rlp::decode(&v)), - Err(err) => { - panic!("db get failed, key: {:?}, err: {:?}", &key.key() as &[u8], err); - } - } } fn exists(&self, col: Option, key: &Key) -> bool where R: Deref { diff --git a/ethcore/src/encoded.rs b/ethcore/src/encoded.rs index 1f627666a90..01df386cc2e 100644 --- a/ethcore/src/encoded.rs +++ b/ethcore/src/encoded.rs @@ -24,13 +24,12 @@ //! decoded object where parts like the hash can be saved. use block::Block as FullBlock; -use header::{BlockNumber, Header as FullHeader}; -use transaction::UnverifiedTransaction; - +use ethereum_types::{H256, Bloom, U256, Address}; use hash::keccak; +use header::{BlockNumber, Header as FullHeader}; use heapsize::HeapSizeOf; -use ethereum_types::{H256, Bloom, U256, Address}; use rlp::{Rlp, RlpStream}; +use transaction::UnverifiedTransaction; use views::{self, BlockView, HeaderView, BodyView}; /// Owning header view. @@ -48,7 +47,7 @@ impl Header { pub fn new(encoded: Vec) -> Self { Header(encoded) } /// Upgrade this encoded view to a fully owned `Header` object. - pub fn decode(&self) -> FullHeader { ::rlp::decode(&self.0) } + pub fn decode(&self) -> FullHeader { ::rlp::decode(&self.0).expect("decoding failure") } /// Get a borrowed header view onto the data. #[inline] @@ -205,7 +204,7 @@ impl Block { pub fn header_view(&self) -> HeaderView { self.view().header_view() } /// Decode to a full block. - pub fn decode(&self) -> FullBlock { ::rlp::decode(&self.0) } + pub fn decode(&self) -> FullBlock { ::rlp::decode(&self.0).expect("decoding failure") } /// Decode the header. pub fn decode_header(&self) -> FullHeader { self.view().rlp().val_at(0) } diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index d80a5e182f1..93fc347e942 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -143,8 +143,10 @@ impl super::EpochVerifier for EpochVerifier } fn check_finality_proof(&self, proof: &[u8]) -> Option> { - let header: Header = ::rlp::decode(proof); - self.verify_light(&header).ok().map(|_| vec![header.hash()]) + match ::rlp::decode(proof) { + Ok(header) => self.verify_light(&header).ok().map(|_| vec![header.hash()]), + Err(_) => None // REVIEW: log perhaps? Not sure what the policy is. + } } } diff --git a/ethcore/src/header.rs b/ethcore/src/header.rs index a31aa029b31..ba71eb30497 100644 --- a/ethcore/src/header.rs +++ b/ethcore/src/header.rs @@ -398,7 +398,7 @@ mod tests { let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap(); let nonce_decoded = "ab4e252a7e8c2a23".from_hex().unwrap(); - let header: Header = rlp::decode(&header_rlp); + let header: Header = rlp::decode(&header_rlp).expect("error decoding header"); let seal_fields = header.seal.clone(); assert_eq!(seal_fields.len(), 2); assert_eq!(seal_fields[0], mix_hash); @@ -415,7 +415,7 @@ mod tests { // that's rlp of block header created with ethash engine. let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap(); - let header: Header = rlp::decode(&header_rlp); + let header: Header = rlp::decode(&header_rlp).expect("error decoding header"); let encoded_header = rlp::encode(&header).into_vec(); assert_eq!(header_rlp, encoded_header); diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index 6c9e0f3d6e8..49f45136e9b 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -236,7 +236,7 @@ mod tests { }; let thin_rlp = ::rlp::encode(&account); - assert_eq!(::rlp::decode::(&thin_rlp), account); + assert_eq!(::rlp::decode::(&thin_rlp).unwrap(), account); let fat_rlps = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap(); let fat_rlp = Rlp::new(&fat_rlps[0]).at(1).unwrap(); @@ -261,7 +261,7 @@ mod tests { }; let thin_rlp = ::rlp::encode(&account); - assert_eq!(::rlp::decode::(&thin_rlp), account); + assert_eq!(::rlp::decode::(&thin_rlp).unwrap(), account); let fat_rlp = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap(); let fat_rlp = Rlp::new(&fat_rlp[0]).at(1).unwrap(); @@ -286,7 +286,7 @@ mod tests { }; let thin_rlp = ::rlp::encode(&account); - assert_eq!(::rlp::decode::(&thin_rlp), account); + assert_eq!(::rlp::decode::(&thin_rlp).unwrap(), account); let fat_rlps = to_fat_rlps(&keccak(addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 500, 1000).unwrap(); let mut root = KECCAK_NULL_RLP; diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index fbf0c5ca5ec..94236e9e95d 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -281,7 +281,7 @@ pub fn chunk_state<'a>(db: &HashDB, root: &H256, writer: &Mutex(rlp).storage_root); + known_storage_roots.insert(*hash, ::rlp::decode::(rlp)?.storage_root); } if let Some(&(ref hash, ref rlp)) = out_chunk.iter().next() { - known_storage_roots.insert(*hash, ::rlp::decode::(rlp).storage_root); + known_storage_roots.insert(*hash, ::rlp::decode::(rlp)?.storage_root); } Ok(status) } diff --git a/ethcore/src/snapshot/tests/helpers.rs b/ethcore/src/snapshot/tests/helpers.rs index 51f417149bf..067a3abab07 100644 --- a/ethcore/src/snapshot/tests/helpers.rs +++ b/ethcore/src/snapshot/tests/helpers.rs @@ -75,7 +75,7 @@ impl StateProducer { // sweep once to alter storage tries. for &mut (ref mut address_hash, ref mut account_data) in &mut accounts_to_modify { - let mut account: BasicAccount = ::rlp::decode(&*account_data); + let mut account: BasicAccount = ::rlp::decode(&*account_data).expect("error decoding basic account"); let acct_db = AccountDBMut::from_hash(db, *address_hash); fill_storage(acct_db, &mut account.storage_root, &mut self.storage_seed); *account_data = DBValue::from_vec(::rlp::encode(&account).into_vec()); diff --git a/ethcore/src/snapshot/tests/state.rs b/ethcore/src/snapshot/tests/state.rs index f17fa7dde5a..05926a7e662 100644 --- a/ethcore/src/snapshot/tests/state.rs +++ b/ethcore/src/snapshot/tests/state.rs @@ -114,7 +114,7 @@ fn get_code_from_prev_chunk() { // first one will have code inlined, // second will just have its hash. let thin_rlp = acc_stream.out(); - let acc: BasicAccount = ::rlp::decode(&thin_rlp); + let acc: BasicAccount = ::rlp::decode(&thin_rlp).expect("error decoding basic account"); let mut make_chunk = |acc, hash| { let mut db = MemoryDB::new(); diff --git a/ethcore/src/state/account.rs b/ethcore/src/state/account.rs index f9c8f258e60..ff7d70bd3aa 100644 --- a/ethcore/src/state/account.rs +++ b/ethcore/src/state/account.rs @@ -21,6 +21,7 @@ use std::sync::Arc; use std::collections::{HashMap, BTreeMap}; use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak}; use ethereum_types::{H256, U256, Address}; +use error::Error; use hashdb::HashDB; use kvdb::DBValue; use bytes::{Bytes, ToPretty}; @@ -144,9 +145,10 @@ impl Account { } /// Create a new account from RLP. - pub fn from_rlp(rlp: &[u8]) -> Account { - let basic: BasicAccount = ::rlp::decode(rlp); - basic.into() + pub fn from_rlp(rlp: &[u8]) -> Result { + ::rlp::decode::(rlp) + .map(|ba| ba.into()) + .map_err(|e| e.into()) } /// Create a new contract account. @@ -202,8 +204,8 @@ impl Account { return Ok(value); } let db = SecTrieDB::new(db, &self.storage_root)?; - - let item: U256 = db.get_with(key, ::rlp::decode)?.unwrap_or_else(U256::zero); + let panicky_decoder = |bytes:&[u8]| ::rlp::decode(&bytes).expect("decoding db value failed"); + let item: U256 = db.get_with(key, panicky_decoder)?.unwrap_or_else(U256::zero); let value: H256 = item.into(); self.storage_cache.borrow_mut().insert(key.clone(), value.clone()); Ok(value) @@ -478,7 +480,8 @@ impl Account { let trie = TrieDB::new(db, &self.storage_root)?; let item: U256 = { - let query = (&mut recorder, ::rlp::decode); + let panicky_decoder = |bytes:&[u8]| ::rlp::decode(bytes).expect("decoding db value failed"); + let query = (&mut recorder, panicky_decoder); trie.get_with(&storage_key, query)?.unwrap_or_else(U256::zero) }; @@ -528,7 +531,7 @@ mod tests { a.rlp() }; - let a = Account::from_rlp(&rlp); + let a = Account::from_rlp(&rlp).expect("decoding db value failed"); assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); assert_eq!(a.storage_at(&db.immutable(), &0x00u64.into()).unwrap(), 0x1234u64.into()); assert_eq!(a.storage_at(&db.immutable(), &0x01u64.into()).unwrap(), H256::default()); @@ -546,10 +549,10 @@ mod tests { a.rlp() }; - let mut a = Account::from_rlp(&rlp); + let mut a = Account::from_rlp(&rlp).expect("decoding db value failed"); assert!(a.cache_code(&db.immutable()).is_some()); - let mut a = Account::from_rlp(&rlp); + let mut a = Account::from_rlp(&rlp).expect("decoding db value failed"); assert_eq!(a.note_code(vec![0x55, 0x44, 0xffu8]), Ok(())); } @@ -609,7 +612,7 @@ mod tests { #[test] fn rlpio() { let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new()); - let b = Account::from_rlp(&a.rlp()); + let b = Account::from_rlp(&a.rlp()).unwrap(); assert_eq!(a.balance(), b.balance()); assert_eq!(a.nonce(), b.nonce()); assert_eq!(a.code_hash(), b.code_hash()); diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 255dce5b5de..20d564588c5 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -605,7 +605,8 @@ impl State { // account is not found in the global cache, get from the DB and insert into local let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR); - let maybe_acc = db.get_with(address, Account::from_rlp)?; + let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed"); + let maybe_acc = db.get_with(address, from_rlp)?; let r = maybe_acc.as_ref().map_or(Ok(H256::new()), |a| { let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); a.storage_at(account_db.as_hashdb(), key) @@ -983,7 +984,8 @@ impl State { // not found in the global cache, get from the DB and insert into local let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?; - let mut maybe_acc = db.get_with(a, Account::from_rlp)?; + let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed"); + let mut maybe_acc = db.get_with(a, from_rlp)?; if let Some(ref mut account) = maybe_acc.as_mut() { let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()); @@ -1012,7 +1014,8 @@ impl State { None => { let maybe_acc = if !self.db.is_known_null(a) { let db = self.factories.trie.readonly(self.db.as_hashdb(), &self.root)?; - AccountEntry::new_clean(db.get_with(a, Account::from_rlp)?) + let from_rlp = |b:&[u8]| { Account::from_rlp(b).expect("decoding db value failed") }; + AccountEntry::new_clean(db.get_with(a, from_rlp)?) } else { AccountEntry::new_clean(None) }; @@ -1064,7 +1067,10 @@ impl State { let mut recorder = Recorder::new(); let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; let maybe_account: Option = { - let query = (&mut recorder, ::rlp::decode); + let panicky_decoder = |bytes: &[u8]| { + ::rlp::decode(bytes).expect(&format!("prove_account, could not query trie for account key={}", &account_key)) + }; + let query = (&mut recorder, panicky_decoder); trie.get_with(&account_key, query)? }; let account = maybe_account.unwrap_or_else(|| BasicAccount { @@ -1086,7 +1092,8 @@ impl State { // TODO: probably could look into cache somehow but it's keyed by // address, not keccak(address). let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; - let acc = match trie.get_with(&account_key, Account::from_rlp)? { + let from_rlp = |b: &[u8]| Account::from_rlp(b).expect("decoding db value failed"); + let acc = match trie.get_with(&account_key, from_rlp)? { Some(acc) => acc, None => return Ok((Vec::new(), H256::new())), }; diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs index e2746ca7f7d..00cf517df80 100644 --- a/ethcore/src/trace/types/flat.rs +++ b/ethcore/src/trace/types/flat.rs @@ -244,7 +244,7 @@ mod tests { ]); let encoded = ::rlp::encode(&block_traces); - let decoded = ::rlp::decode(&encoded); + let decoded = ::rlp::decode(&encoded).expect("error decoding block traces"); assert_eq!(block_traces, decoded); } } diff --git a/ethcore/transaction/src/transaction.rs b/ethcore/transaction/src/transaction.rs index 571dec3faeb..6152e61acb6 100644 --- a/ethcore/transaction/src/transaction.rs +++ b/ethcore/transaction/src/transaction.rs @@ -576,7 +576,8 @@ mod tests { #[test] fn sender_test() { - let t: UnverifiedTransaction = rlp::decode(&::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); + let bytes = ::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap(); + let t: UnverifiedTransaction = rlp::decode(&bytes).expect("decoding UnverifiedTransaction failed"); assert_eq!(t.data, b""); assert_eq!(t.gas, U256::from(0x5208u64)); assert_eq!(t.gas_price, U256::from(0x01u64)); @@ -645,7 +646,7 @@ mod tests { use rustc_hex::FromHex; let test_vector = |tx_data: &str, address: &'static str| { - let signed = rlp::decode(&FromHex::from_hex(tx_data).unwrap()); + let signed = rlp::decode(&FromHex::from_hex(tx_data).unwrap()).expect("decoding tx data failed"); let signed = SignedTransaction::new(signed).unwrap(); assert_eq!(signed.sender(), address.into()); println!("chainid: {:?}", signed.chain_id()); diff --git a/ethcore/types/src/receipt.rs b/ethcore/types/src/receipt.rs index c1defbc151f..8846d27c027 100644 --- a/ethcore/types/src/receipt.rs +++ b/ethcore/types/src/receipt.rs @@ -193,7 +193,7 @@ mod tests { ); let encoded = ::rlp::encode(&r); assert_eq!(&encoded[..], &expected[..]); - let decoded: Receipt = ::rlp::decode(&encoded); + let decoded: Receipt = ::rlp::decode(&encoded).expect("decoding receipt failed"); assert_eq!(decoded, r); } @@ -211,7 +211,7 @@ mod tests { ); let encoded = ::rlp::encode(&r); assert_eq!(&encoded[..], &expected[..]); - let decoded: Receipt = ::rlp::decode(&encoded); + let decoded: Receipt = ::rlp::decode(&encoded).expect("decoding receipt failed"); assert_eq!(decoded, r); } } diff --git a/ethcore/vm/src/call_type.rs b/ethcore/vm/src/call_type.rs index 83260825f3c..dc00b2b8392 100644 --- a/ethcore/vm/src/call_type.rs +++ b/ethcore/vm/src/call_type.rs @@ -64,7 +64,7 @@ mod tests { fn should_encode_and_decode_call_type() { let original = CallType::Call; let encoded = encode(&original); - let decoded = decode(&encoded); + let decoded = decode(&encoded).expect("failure decoding CallType"); assert_eq!(original, decoded); } } diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index badf5bff728..39a2e842db1 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -566,7 +566,8 @@ fn rpc_eth_pending_transaction_by_hash() { let tester = EthTester::default(); { - let tx = rlp::decode(&FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); + let bytes = FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap(); + let tx = rlp::decode(&bytes).expect("decoding failure"); let tx = SignedTransaction::new(tx).unwrap(); tester.miner.pending_transactions.lock().insert(H256::zero(), tx); } diff --git a/util/journaldb/src/archivedb.rs b/util/journaldb/src/archivedb.rs index e00b37d3c4a..b58558a332a 100644 --- a/util/journaldb/src/archivedb.rs +++ b/util/journaldb/src/archivedb.rs @@ -45,14 +45,15 @@ pub struct ArchiveDB { impl ArchiveDB { /// Create a new instance from a key-value db. - pub fn new(backing: Arc, col: Option) -> ArchiveDB { - let latest_era = backing.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") - .map(|val| decode::(&val)); + pub fn new(backing: Arc, column: Option) -> ArchiveDB { + let latest_era = backing.get(column, &LATEST_ERA_KEY) + .expect("Low-level database error.") + .map(|val| decode::(&val).expect("decoding db value failed")); ArchiveDB { overlay: MemoryDB::new(), - backing: backing, - latest_era: latest_era, - column: col, + backing, + latest_era, + column, } } diff --git a/util/journaldb/src/earlymergedb.rs b/util/journaldb/src/earlymergedb.rs index bb8e49d41ed..e76cdcd313a 100644 --- a/util/journaldb/src/earlymergedb.rs +++ b/util/journaldb/src/earlymergedb.rs @@ -263,7 +263,7 @@ impl EarlyMergeDB { let mut refs = HashMap::new(); let mut latest_era = None; if let Some(val) = db.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") { - let mut era = decode::(&val); + let mut era = decode::(&val).expect("decoding db value failed"); latest_era = Some(era); loop { let mut db_key = DatabaseKey { diff --git a/util/journaldb/src/overlaydb.rs b/util/journaldb/src/overlaydb.rs index fa7ff04596e..54d0bb12d76 100644 --- a/util/journaldb/src/overlaydb.rs +++ b/util/journaldb/src/overlaydb.rs @@ -137,7 +137,7 @@ impl OverlayDB { fn payload(&self, key: &H256) -> Option { self.backing.get(self.column, key) .expect("Low-level database error. Some issue with your hard disk?") - .map(|d| decode(&d)) + .map(|d| decode(&d).expect("decoding db value failed")) } /// Put the refs and value of the given key, possibly deleting it from the db. diff --git a/util/journaldb/src/overlayrecentdb.rs b/util/journaldb/src/overlayrecentdb.rs index fdc178350e6..2c9ce5cb1dd 100644 --- a/util/journaldb/src/overlayrecentdb.rs +++ b/util/journaldb/src/overlayrecentdb.rs @@ -186,7 +186,7 @@ impl OverlayRecentDB { let mut earliest_era = None; let mut cumulative_size = 0; if let Some(val) = db.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") { - let mut era = decode::(&val); + let mut era = decode::(&val).expect("decoding db value failed"); latest_era = Some(era); loop { let mut db_key = DatabaseKey { @@ -195,7 +195,7 @@ impl OverlayRecentDB { }; while let Some(rlp_data) = db.get(col, &encode(&db_key)).expect("Low-level database error.") { trace!("read_overlay: era={}, index={}", era, db_key.index); - let value = decode::(&rlp_data); + let value = decode::(&rlp_data).expect(&format!("read_overlay: Error decoding DatabaseValue era={}, index{}", era, db_key.index)); count += value.inserts.len(); let mut inserted_keys = Vec::new(); for (k, v) in value.inserts { diff --git a/util/journaldb/src/refcounteddb.rs b/util/journaldb/src/refcounteddb.rs index bf366faf753..944d81d3733 100644 --- a/util/journaldb/src/refcounteddb.rs +++ b/util/journaldb/src/refcounteddb.rs @@ -62,17 +62,18 @@ pub struct RefCountedDB { impl RefCountedDB { /// Create a new instance given a `backing` database. - pub fn new(backing: Arc, col: Option) -> RefCountedDB { - let latest_era = backing.get(col, &LATEST_ERA_KEY).expect("Low-level database error.") - .map(|val| decode::(&val)); + pub fn new(backing: Arc, column: Option) -> RefCountedDB { + let latest_era = backing.get(column, &LATEST_ERA_KEY) + .expect("Low-level database error.") + .map(|v| decode::(&v).expect("decoding db value failed")); RefCountedDB { - forward: OverlayDB::new(backing.clone(), col), - backing: backing, + forward: OverlayDB::new(backing.clone(), column), + backing, inserts: vec![], removes: vec![], - latest_era: latest_era, - column: col, + latest_era, + column, } } } diff --git a/util/rlp/src/lib.rs b/util/rlp/src/lib.rs index a6754e22de9..b416b1c25b0 100644 --- a/util/rlp/src/lib.rs +++ b/util/rlp/src/lib.rs @@ -63,13 +63,13 @@ pub const EMPTY_LIST_RLP: [u8; 1] = [0xC0; 1]; /// /// fn main () { /// let data = vec![0x83, b'c', b'a', b't']; -/// let animal: String = rlp::decode(&data); +/// let animal: String = rlp::decode(&data).expect("could not decode"); /// assert_eq!(animal, "cat".to_owned()); /// } /// ``` -pub fn decode(bytes: &[u8]) -> T where T: Decodable { +pub fn decode(bytes: &[u8]) -> Result where T: Decodable { let rlp = Rlp::new(bytes); - rlp.as_val().expect("trusted rlp should be valid") + rlp.as_val() } pub fn decode_list(bytes: &[u8]) -> Vec where T: Decodable { diff --git a/util/rlp/tests/tests.rs b/util/rlp/tests/tests.rs index 6ff426a7739..041c267667d 100644 --- a/util/rlp/tests/tests.rs +++ b/util/rlp/tests/tests.rs @@ -209,8 +209,10 @@ struct VDTestPair(Vec, Vec) where T: Decodable + fmt::Debug + cmp::Eq; fn run_decode_tests(tests: Vec>) where T: Decodable + fmt::Debug + cmp::Eq { for t in &tests { - let res: T = rlp::decode(&t.1); - assert_eq!(res, t.0); + let res : Result = rlp::decode(&t.1); + assert!(res.is_ok()); + let res = res.unwrap(); + assert_eq!(&res, &t.0); } } diff --git a/util/rlp_derive/tests/rlp.rs b/util/rlp_derive/tests/rlp.rs index c873805247d..ba51309146e 100644 --- a/util/rlp_derive/tests/rlp.rs +++ b/util/rlp_derive/tests/rlp.rs @@ -24,7 +24,7 @@ fn test_encode_foo() { let out = encode(&foo).into_vec(); assert_eq!(out, expected); - let decoded = decode(&expected); + let decoded = decode(&expected).expect("decode failure"); assert_eq!(foo, decoded); } @@ -38,7 +38,7 @@ fn test_encode_foo_wrapper() { let out = encode(&foo).into_vec(); assert_eq!(out, expected); - let decoded = decode(&expected); + let decoded = decode(&expected).expect("decode failure"); assert_eq!(foo, decoded); } diff --git a/whisper/src/message.rs b/whisper/src/message.rs index fbf2faf3fdf..d0de9af4b5a 100644 --- a/whisper/src/message.rs +++ b/whisper/src/message.rs @@ -446,7 +446,7 @@ mod tests { }; let encoded = ::rlp::encode(&envelope); - let decoded = ::rlp::decode(&encoded); + let decoded = ::rlp::decode(&encoded).expect("failure decoding Envelope"); assert_eq!(envelope, decoded) } @@ -462,7 +462,7 @@ mod tests { }; let encoded = ::rlp::encode(&envelope); - let decoded = ::rlp::decode(&encoded); + let decoded = ::rlp::decode(&encoded).expect("failure decoding Envelope"); assert_eq!(envelope, decoded) } From ac3de4c5fca0c0b469aa2198c42e92f04be18626 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Wed, 9 May 2018 08:47:21 +0200 Subject: [PATCH 41/95] Parity as a library (#8412) * Parity as a library * Fix concerns * Allow using a null on_client_restart_cb * Fix more concerns * Test the C library in test.sh * Reduce CMake version to 3.5 * Move the clib test before cargo test * Add println in test --- Cargo.lock | 8 +- Cargo.toml | 5 +- parity-clib-example/CMakeLists.txt | 19 ++ parity-clib-example/main.cpp | 28 +++ parity-clib/Cargo.toml | 17 ++ parity-clib/parity.h | 93 ++++++++++ parity-clib/src/lib.rs | 133 ++++++++++++++ parity/blockchain.rs | 7 - parity/cli/usage.rs | 1 + parity/configuration.rs | 41 +++-- parity/lib.rs | 249 ++++++++++++++++++++++++++ parity/main.rs | 275 +++++++---------------------- parity/run.rs | 138 +++++---------- parity/snapshot.rs | 3 - parity/url.rs | 3 +- test.sh | 16 +- 16 files changed, 702 insertions(+), 334 deletions(-) create mode 100644 parity-clib-example/CMakeLists.txt create mode 100644 parity-clib-example/main.cpp create mode 100644 parity-clib/Cargo.toml create mode 100644 parity-clib/parity.h create mode 100644 parity-clib/src/lib.rs create mode 100644 parity/lib.rs diff --git a/Cargo.lock b/Cargo.lock index ceb14ff277c..64e468e6703 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1954,7 +1954,6 @@ dependencies = [ "ethcore-private-tx 1.0.0", "ethcore-secretstore 1.0.0", "ethcore-service 0.1.0", - "ethcore-stratum 1.12.0", "ethcore-sync 1.12.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2008,6 +2007,13 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parity-clib" +version = "1.12.0" +dependencies = [ + "parity 1.12.0", +] + [[package]] name = "parity-dapps" version = "1.12.0" diff --git a/Cargo.toml b/Cargo.toml index a611458e653..de1a78bf4fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,6 @@ ethcore-miner = { path = "miner" } ethcore-network = { path = "util/network" } ethcore-private-tx = { path = "ethcore/private-tx" } ethcore-service = { path = "ethcore/service" } -ethcore-stratum = { path = "ethcore/stratum" } ethcore-sync = { path = "ethcore/sync" } ethcore-transaction = { path = "ethcore/transaction" } ethereum-types = "0.3" @@ -108,6 +107,9 @@ slow-blocks = ["ethcore/slow-blocks"] secretstore = ["ethcore-secretstore"] final = ["parity-version/final"] +[lib] +path = "parity/lib.rs" + [[bin]] path = "parity/main.rs" name = "parity" @@ -130,6 +132,7 @@ members = [ "ethstore/cli", "evmbin", "miner", + "parity-clib", "transaction-pool", "whisper", "whisper/cli", diff --git a/parity-clib-example/CMakeLists.txt b/parity-clib-example/CMakeLists.txt new file mode 100644 index 00000000000..143d014e322 --- /dev/null +++ b/parity-clib-example/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.5) +include(ExternalProject) + +include_directories("${CMAKE_SOURCE_DIR}/../parity-clib") + +add_executable(parity-example main.cpp) + +ExternalProject_Add( + libparity + DOWNLOAD_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + COMMAND cargo build -p parity-clib # Note: use --release in a real project + BINARY_DIR "${CMAKE_SOURCE_DIR}/../target" + INSTALL_COMMAND "" + LOG_BUILD ON) + +add_dependencies(parity-example libparity) +target_link_libraries(parity-example "${CMAKE_SOURCE_DIR}/../target/debug/libparity.so") diff --git a/parity-clib-example/main.cpp b/parity-clib-example/main.cpp new file mode 100644 index 00000000000..1fadf1b5b56 --- /dev/null +++ b/parity-clib-example/main.cpp @@ -0,0 +1,28 @@ +#include +#include +#include + +void on_restart(void*, const char*, size_t) {} + +int main() { + ParityParams cfg = { 0 }; + cfg.on_client_restart_cb = on_restart; + + const char* args[] = {"--light"}; + size_t str_lens[] = {7}; + if (parity_config_from_cli(args, str_lens, 1, &cfg.configuration) != 0) { + return 1; + } + + void* parity; + if (parity_start(&cfg, &parity) != 0) { + return 1; + } + + sleep(5); + if (parity != NULL) { + parity_destroy(parity); + } + + return 0; +} diff --git a/parity-clib/Cargo.toml b/parity-clib/Cargo.toml new file mode 100644 index 00000000000..001f954c211 --- /dev/null +++ b/parity-clib/Cargo.toml @@ -0,0 +1,17 @@ +[package] +description = "C bindings for the Parity Ethereum client" +name = "parity-clib" +version = "1.12.0" +license = "GPL-3.0" +authors = ["Parity Technologies "] + +[lib] +name = "parity" +crate-type = ["cdylib", "staticlib"] + +[dependencies] +parity = { path = "../", default-features = false } + +[features] +default = [] +final = ["parity/final"] diff --git a/parity-clib/parity.h b/parity-clib/parity.h new file mode 100644 index 00000000000..b61da8e458b --- /dev/null +++ b/parity-clib/parity.h @@ -0,0 +1,93 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +#ifndef _PARITY_H_INCLUDED_ +#define _PARITY_H_INCLUDED_ + +#include + +/// Parameters to pass to `parity_start`. +struct ParityParams { + /// Configuration object, as handled by the `parity_config_*` functions. + /// Note that calling `parity_start` will destroy the configuration object (even on failure). + void *configuration; + + /// Callback function to call when the client receives an RPC request to change its chain spec. + /// + /// Will only be called if you enable the `--can-restart` flag. + /// + /// The first parameter of the callback is the value of `on_client_restart_cb_custom`. + /// The second and third parameters of the callback are the string pointer and length. + void (*on_client_restart_cb)(void* custom, const char* new_chain, size_t new_chain_len); + + /// Custom parameter passed to the `on_client_restart_cb` callback as first parameter. + void *on_client_restart_cb_custom; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/// Builds a new configuration object by parsing a list of CLI arguments. +/// +/// The first two parameters are string pointers and string lengths. They must have a length equal +/// to `len`. The strings don't need to be zero-terminated. +/// +/// On success, the produced object will be written to the `void*` pointed by `out`. +/// +/// Returns 0 on success, and non-zero on error. +/// +/// # Example +/// +/// ```no_run +/// void* cfg; +/// const char *args[] = {"--light", "--can-restart"}; +/// size_t str_lens[] = {7, 13}; +/// if (parity_config_from_cli(args, str_lens, 2, &cfg) != 0) { +/// return 1; +/// } +/// ``` +/// +int parity_config_from_cli(char const* const* args, size_t const* arg_lens, size_t len, void** out); + +/// Destroys a configuration object created earlier. +/// +/// **Important**: You probably don't need to call this function. Calling `parity_start` destroys +/// the configuration object as well (even on failure). +void parity_config_destroy(void* cfg); + +/// Starts the parity client in background threads. Returns a pointer to a struct that represents +/// the running client. Can also return NULL if the execution completes instantly. +/// +/// **Important**: The configuration object passed inside `cfg` is destroyed when you +/// call `parity_start` (even on failure). +/// +/// On success, the produced object will be written to the `void*` pointed by `out`. +/// +/// Returns 0 on success, and non-zero on error. +int parity_start(const ParityParams* params, void** out); + +/// Destroys the parity client created with `parity_start`. +/// +/// **Warning**: `parity_start` can return NULL if execution finished instantly, in which case you +/// must not call this function. +void parity_destroy(void* parity); + +#ifdef __cplusplus +} +#endif + +#endif // include guard diff --git a/parity-clib/src/lib.rs b/parity-clib/src/lib.rs new file mode 100644 index 00000000000..b08d6487d1a --- /dev/null +++ b/parity-clib/src/lib.rs @@ -0,0 +1,133 @@ +// Copyright 2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Note that all the structs and functions here are documented in `parity.h`, to avoid +//! duplicating documentation. + +extern crate parity; + +use std::os::raw::{c_char, c_void, c_int}; +use std::panic; +use std::ptr; +use std::slice; + +#[repr(C)] +pub struct ParityParams { + pub configuration: *mut c_void, + pub on_client_restart_cb: Option, + pub on_client_restart_cb_custom: *mut c_void, +} + +#[no_mangle] +pub extern fn parity_config_from_cli(args: *const *const c_char, args_lens: *const usize, len: usize, output: *mut *mut c_void) -> c_int { + unsafe { + panic::catch_unwind(|| { + *output = ptr::null_mut(); + + let args = { + let arg_ptrs = slice::from_raw_parts(args, len); + let arg_lens = slice::from_raw_parts(args_lens, len); + + let mut args = Vec::with_capacity(len + 1); + args.push("parity".to_owned()); + + for (&arg, &len) in arg_ptrs.iter().zip(arg_lens.iter()) { + let string = slice::from_raw_parts(arg as *const u8, len); + match String::from_utf8(string.to_owned()) { + Ok(a) => args.push(a), + Err(_) => return 1, + }; + } + + args + }; + + match parity::Configuration::parse_cli(&args) { + Ok(mut cfg) => { + // Always disable the auto-updater when used as a library. + cfg.args.arg_auto_update = "none".to_owned(); + + let cfg = Box::into_raw(Box::new(cfg)); + *output = cfg as *mut _; + 0 + }, + Err(_) => { + 1 + }, + } + }).unwrap_or(1) + } +} + +#[no_mangle] +pub extern fn parity_config_destroy(cfg: *mut c_void) { + unsafe { + let _ = panic::catch_unwind(|| { + let _cfg = Box::from_raw(cfg as *mut parity::Configuration); + }); + } +} + +#[no_mangle] +pub extern fn parity_start(cfg: *const ParityParams, output: *mut *mut c_void) -> c_int { + unsafe { + panic::catch_unwind(|| { + *output = ptr::null_mut(); + let cfg: &ParityParams = &*cfg; + + let config = Box::from_raw(cfg.configuration as *mut parity::Configuration); + + let on_client_restart_cb = { + struct Cb(Option, *mut c_void); + unsafe impl Send for Cb {} + unsafe impl Sync for Cb {} + impl Cb { + fn call(&self, new_chain: String) { + if let Some(ref cb) = self.0 { + cb(self.1, new_chain.as_bytes().as_ptr() as *const _, new_chain.len()) + } + } + } + let cb = Cb(cfg.on_client_restart_cb, cfg.on_client_restart_cb_custom); + move |new_chain: String| { cb.call(new_chain); } + }; + + let action = match parity::start(*config, on_client_restart_cb, || {}) { + Ok(action) => action, + Err(_) => return 1, + }; + + match action { + parity::ExecutionAction::Instant(Some(s)) => { println!("{}", s); 0 }, + parity::ExecutionAction::Instant(None) => 0, + parity::ExecutionAction::Running(client) => { + *output = Box::into_raw(Box::::new(client)) as *mut c_void; + 0 + } + } + }).unwrap_or(1) + } +} + +#[no_mangle] +pub extern fn parity_destroy(client: *mut c_void) { + unsafe { + let _ = panic::catch_unwind(|| { + let client = Box::from_raw(client as *mut parity::RunningClient); + client.shutdown(); + }); + } +} diff --git a/parity/blockchain.rs b/parity/blockchain.rs index f9c2f8ba378..027814f2451 100644 --- a/parity/blockchain.rs +++ b/parity/blockchain.rs @@ -37,7 +37,6 @@ use params::{SpecType, Pruning, Switch, tracing_switch_to_bool, fatdb_switch_to_ use helpers::{to_client_config, execute_upgrades}; use dir::Directories; use user_defaults::UserDefaults; -use fdlimit; use ethcore_private_tx; use db; @@ -178,8 +177,6 @@ fn execute_import_light(cmd: ImportBlockchain) -> Result<(), String> { // load user defaults let user_defaults = UserDefaults::load(&user_defaults_path)?; - fdlimit::raise_fd_limit(); - // select pruning algorithm let algorithm = cmd.pruning.to_algorithm(&user_defaults); @@ -327,8 +324,6 @@ fn execute_import(cmd: ImportBlockchain) -> Result<(), String> { // load user defaults let mut user_defaults = UserDefaults::load(&user_defaults_path)?; - fdlimit::raise_fd_limit(); - // select pruning algorithm let algorithm = cmd.pruning.to_algorithm(&user_defaults); @@ -518,8 +513,6 @@ fn start_client( // load user defaults let user_defaults = UserDefaults::load(&user_defaults_path)?; - fdlimit::raise_fd_limit(); - // select pruning algorithm let algorithm = pruning.to_algorithm(&user_defaults); diff --git a/parity/cli/usage.rs b/parity/cli/usage.rs index 2bdeaaed1a5..ce138fdff3d 100644 --- a/parity/cli/usage.rs +++ b/parity/cli/usage.rs @@ -198,6 +198,7 @@ macro_rules! usage { } } + /// Parsed command line arguments. #[derive(Debug, PartialEq)] pub struct Args { $( diff --git a/parity/configuration.rs b/parity/configuration.rs index 93cc9a4dd6a..3151621801c 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -92,23 +92,30 @@ pub struct Execute { pub cmd: Cmd, } +/// Configuration for the Parity client. #[derive(Debug, PartialEq)] pub struct Configuration { + /// Arguments to be interpreted. pub args: Args, } impl Configuration { - pub fn parse>(command: &[S]) -> Result { - let args = Args::parse(command)?; - + /// Parses a configuration from a list of command line arguments. + /// + /// # Example + /// + /// ``` + /// let _cfg = parity::Configuration::parse_cli(&["--light", "--chain", "koven"]).unwrap(); + /// ``` + pub fn parse_cli>(command: &[S]) -> Result { let config = Configuration { - args: args, + args: Args::parse(command)?, }; Ok(config) } - pub fn into_command(self) -> Result { + pub(crate) fn into_command(self) -> Result { let dirs = self.directories(); let pruning = self.args.arg_pruning.parse()?; let pruning_history = self.args.arg_pruning_history; @@ -1843,7 +1850,7 @@ mod tests { let filename = tempdir.path().join("peers"); File::create(&filename).unwrap().write_all(b" \n\t\n").unwrap(); let args = vec!["parity", "--reserved-peers", filename.to_str().unwrap()]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); assert!(conf.init_reserved_nodes().is_ok()); } @@ -1853,7 +1860,7 @@ mod tests { let filename = tempdir.path().join("peers_comments"); File::create(&filename).unwrap().write_all(b"# Sample comment\nenode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@172.0.0.1:30303\n").unwrap(); let args = vec!["parity", "--reserved-peers", filename.to_str().unwrap()]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); let reserved_nodes = conf.init_reserved_nodes(); assert!(reserved_nodes.is_ok()); assert_eq!(reserved_nodes.unwrap().len(), 1); @@ -1862,7 +1869,7 @@ mod tests { #[test] fn test_dev_preset() { let args = vec!["parity", "--config", "dev"]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { assert_eq!(c.net_settings.chain, "dev"); @@ -1876,7 +1883,7 @@ mod tests { #[test] fn test_mining_preset() { let args = vec!["parity", "--config", "mining"]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { assert_eq!(c.net_conf.min_peers, 50); @@ -1898,7 +1905,7 @@ mod tests { #[test] fn test_non_standard_ports_preset() { let args = vec!["parity", "--config", "non-standard-ports"]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { assert_eq!(c.net_settings.network_port, 30305); @@ -1911,7 +1918,7 @@ mod tests { #[test] fn test_insecure_preset() { let args = vec!["parity", "--config", "insecure"]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { assert_eq!(c.update_policy.require_consensus, false); @@ -1931,7 +1938,7 @@ mod tests { #[test] fn test_dev_insecure_preset() { let args = vec!["parity", "--config", "dev-insecure"]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { assert_eq!(c.net_settings.chain, "dev"); @@ -1954,7 +1961,7 @@ mod tests { #[test] fn test_override_preset() { let args = vec!["parity", "--config", "mining", "--min-peers=99"]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { assert_eq!(c.net_conf.min_peers, 99); @@ -2077,7 +2084,7 @@ mod tests { #[test] fn should_respect_only_max_peers_and_default() { let args = vec!["parity", "--max-peers=50"]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { assert_eq!(c.net_conf.min_peers, 25); @@ -2090,7 +2097,7 @@ mod tests { #[test] fn should_respect_only_max_peers_less_than_default() { let args = vec!["parity", "--max-peers=5"]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { assert_eq!(c.net_conf.min_peers, 5); @@ -2103,7 +2110,7 @@ mod tests { #[test] fn should_respect_only_min_peers_and_default() { let args = vec!["parity", "--min-peers=5"]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { assert_eq!(c.net_conf.min_peers, 5); @@ -2116,7 +2123,7 @@ mod tests { #[test] fn should_respect_only_min_peers_and_greater_than_default() { let args = vec!["parity", "--min-peers=500"]; - let conf = Configuration::parse(&args).unwrap(); + let conf = Configuration::parse_cli(&args).unwrap(); match conf.into_command().unwrap().cmd { Cmd::Run(c) => { assert_eq!(c.net_conf.min_peers, 500); diff --git a/parity/lib.rs b/parity/lib.rs new file mode 100644 index 00000000000..4d9d1a2c95f --- /dev/null +++ b/parity/lib.rs @@ -0,0 +1,249 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Ethcore client application. + +#![warn(missing_docs)] + +extern crate ansi_term; +extern crate docopt; +#[macro_use] +extern crate clap; +extern crate dir; +extern crate env_logger; +extern crate futures; +extern crate futures_cpupool; +extern crate atty; +extern crate jsonrpc_core; +extern crate num_cpus; +extern crate number_prefix; +extern crate parking_lot; +extern crate regex; +extern crate rlp; +extern crate rpassword; +extern crate rustc_hex; +extern crate semver; +extern crate serde; +extern crate serde_json; +#[macro_use] +extern crate serde_derive; +extern crate toml; + +extern crate ethcore; +extern crate ethcore_bytes as bytes; +extern crate ethcore_io as io; +extern crate ethcore_light as light; +extern crate ethcore_logger; +extern crate ethcore_miner as miner; +extern crate ethcore_network as network; +extern crate ethcore_private_tx; +extern crate ethcore_service; +extern crate ethcore_sync as sync; +extern crate ethcore_transaction as transaction; +extern crate ethereum_types; +extern crate ethkey; +extern crate kvdb; +extern crate node_health; +extern crate panic_hook; +extern crate parity_hash_fetch as hash_fetch; +extern crate parity_ipfs_api; +extern crate parity_local_store as local_store; +extern crate parity_reactor; +extern crate parity_rpc; +extern crate parity_updater as updater; +extern crate parity_version; +extern crate parity_whisper; +extern crate path; +extern crate rpc_cli; +extern crate node_filter; +extern crate keccak_hash as hash; +extern crate journaldb; +extern crate registrar; + +#[macro_use] +extern crate log as rlog; + +#[cfg(feature="secretstore")] +extern crate ethcore_secretstore; + +#[cfg(feature = "dapps")] +extern crate parity_dapps; + +#[cfg(test)] +#[macro_use] +extern crate pretty_assertions; + +#[cfg(windows)] extern crate winapi; + +#[cfg(test)] +extern crate tempdir; + +mod account; +mod blockchain; +mod cache; +mod cli; +mod configuration; +mod dapps; +mod export_hardcoded_sync; +mod ipfs; +mod deprecated; +mod helpers; +mod informant; +mod light_helpers; +mod modules; +mod params; +mod presale; +mod rpc; +mod rpc_apis; +mod run; +mod secretstore; +mod signer; +mod snapshot; +mod upgrade; +mod url; +mod user_defaults; +mod whisper; +mod db; + +use std::net::{TcpListener}; +use std::io::BufReader; +use std::fs::File; +use ansi_term::Style; +use hash::keccak_buffer; +use cli::Args; +use configuration::{Cmd, Execute}; +use deprecated::find_deprecated; +use ethcore_logger::{Config as LogConfig, setup_log}; + +pub use self::configuration::Configuration; +pub use self::run::RunningClient; + +fn print_hash_of(maybe_file: Option) -> Result { + if let Some(file) = maybe_file { + let mut f = BufReader::new(File::open(&file).map_err(|_| "Unable to open file".to_owned())?); + let hash = keccak_buffer(&mut f).map_err(|_| "Unable to read from file".to_owned())?; + Ok(format!("{:x}", hash)) + } else { + Err("Streaming from standard input not yet supported. Specify a file.".to_owned()) + } +} + +/// Action that Parity performed when running `start`. +pub enum ExecutionAction { + /// The execution didn't require starting a node, and thus has finished. + /// Contains the string to print on stdout, if any. + Instant(Option), + + /// The client has started running and must be shut down manually by calling `shutdown`. + /// + /// If you don't call `shutdown()`, execution will continue in the background. + Running(RunningClient), +} + +fn execute(command: Execute, on_client_rq: Cr, on_updater_rq: Rr) -> Result + where Cr: Fn(String) + 'static + Send, + Rr: Fn() + 'static + Send +{ + // TODO: move this to `main()` and expose in the C API so that users can setup logging the way + // they want + let logger = setup_log(&command.logger).expect("Logger is initialized only once; qed"); + + match command.cmd { + Cmd::Run(run_cmd) => { + if run_cmd.ui_conf.enabled && !run_cmd.ui_conf.info_page_only { + warn!("{}", Style::new().bold().paint("Parity browser interface is deprecated. It's going to be removed in the next version, use standalone Parity UI instead.")); + warn!("{}", Style::new().bold().paint("Standalone Parity UI: https://github.com/Parity-JS/shell/releases")); + } + + if run_cmd.ui && run_cmd.dapps_conf.enabled { + // Check if Parity is already running + let addr = format!("{}:{}", run_cmd.ui_conf.interface, run_cmd.ui_conf.port); + if !TcpListener::bind(&addr as &str).is_ok() { + return open_ui(&run_cmd.ws_conf, &run_cmd.ui_conf, &run_cmd.logger_config).map(|_| ExecutionAction::Instant(None)); + } + } + + // start ui + if run_cmd.ui { + open_ui(&run_cmd.ws_conf, &run_cmd.ui_conf, &run_cmd.logger_config)?; + } + + if let Some(ref dapp) = run_cmd.dapp { + open_dapp(&run_cmd.dapps_conf, &run_cmd.http_conf, dapp)?; + } + + let outcome = run::execute(run_cmd, logger, on_client_rq, on_updater_rq)?; + Ok(ExecutionAction::Running(outcome)) + }, + Cmd::Version => Ok(ExecutionAction::Instant(Some(Args::print_version()))), + Cmd::Hash(maybe_file) => print_hash_of(maybe_file).map(|s| ExecutionAction::Instant(Some(s))), + Cmd::Account(account_cmd) => account::execute(account_cmd).map(|s| ExecutionAction::Instant(Some(s))), + Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd).map(|s| ExecutionAction::Instant(Some(s))), + Cmd::Blockchain(blockchain_cmd) => blockchain::execute(blockchain_cmd).map(|_| ExecutionAction::Instant(None)), + Cmd::SignerToken(ws_conf, ui_conf, logger_config) => signer::execute(ws_conf, ui_conf, logger_config).map(|s| ExecutionAction::Instant(Some(s))), + Cmd::SignerSign { id, pwfile, port, authfile } => rpc_cli::signer_sign(id, pwfile, port, authfile).map(|s| ExecutionAction::Instant(Some(s))), + Cmd::SignerList { port, authfile } => rpc_cli::signer_list(port, authfile).map(|s| ExecutionAction::Instant(Some(s))), + Cmd::SignerReject { id, port, authfile } => rpc_cli::signer_reject(id, port, authfile).map(|s| ExecutionAction::Instant(Some(s))), + Cmd::Snapshot(snapshot_cmd) => snapshot::execute(snapshot_cmd).map(|s| ExecutionAction::Instant(Some(s))), + Cmd::ExportHardcodedSync(export_hs_cmd) => export_hardcoded_sync::execute(export_hs_cmd).map(|s| ExecutionAction::Instant(Some(s))), + } +} + +/// Starts the parity client. +/// +/// `on_client_rq` is the action to perform when the client receives an RPC request to be restarted +/// with a different chain. +/// +/// `on_updater_rq` is the action to perform when the updater has a new binary to execute. +/// +/// The first parameter is the command line arguments that you would pass when running the parity +/// binary. +/// +/// On error, returns what to print on stderr. +pub fn start(conf: Configuration, on_client_rq: Cr, on_updater_rq: Rr) -> Result + where Cr: Fn(String) + 'static + Send, + Rr: Fn() + 'static + Send +{ + let deprecated = find_deprecated(&conf.args); + for d in deprecated { + println!("{}", d); + } + + execute(conf.into_command()?, on_client_rq, on_updater_rq) +} + +fn open_ui(ws_conf: &rpc::WsConfiguration, ui_conf: &rpc::UiConfiguration, logger_config: &LogConfig) -> Result<(), String> { + if !ui_conf.enabled { + return Err("Cannot use UI command with UI turned off.".into()) + } + + let token = signer::generate_token_and_url(ws_conf, ui_conf, logger_config)?; + // Open a browser + url::open(&token.url).map_err(|e| format!("{}", e))?; + // Print a message + println!("{}", token.message); + Ok(()) +} + +fn open_dapp(dapps_conf: &dapps::Configuration, rpc_conf: &rpc::HttpConfiguration, dapp: &str) -> Result<(), String> { + if !dapps_conf.enabled { + return Err("Cannot use DAPP command with Dapps turned off.".into()) + } + + let url = format!("http://{}:{}/{}/", rpc_conf.interface, rpc_conf.port, dapp); + url::open(&url).map_err(|e| format!("{}", e))?; + Ok(()) +} diff --git a/parity/main.rs b/parity/main.rs index 6774a83864c..e489ad865e4 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// Copyright 2015-2018 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify @@ -18,187 +18,28 @@ #![warn(missing_docs)] -extern crate ansi_term; +extern crate parity; + extern crate ctrlc; -extern crate docopt; -#[macro_use] -extern crate clap; extern crate dir; -extern crate env_logger; extern crate fdlimit; -extern crate futures; -extern crate futures_cpupool; -extern crate atty; -extern crate jsonrpc_core; -extern crate num_cpus; -extern crate number_prefix; -extern crate parking_lot; -extern crate regex; -extern crate rlp; -extern crate rpassword; -extern crate rustc_hex; -extern crate semver; -extern crate serde; -extern crate serde_json; #[macro_use] -extern crate serde_derive; -extern crate toml; - -extern crate ethcore; -extern crate ethcore_bytes as bytes; -extern crate ethcore_io as io; -extern crate ethcore_light as light; -extern crate ethcore_logger; -extern crate ethcore_miner as miner; -extern crate ethcore_network as network; -extern crate ethcore_private_tx; -extern crate ethcore_service; -extern crate ethcore_sync as sync; -extern crate ethcore_transaction as transaction; -extern crate ethereum_types; -extern crate ethkey; -extern crate kvdb; -extern crate node_health; +extern crate log; extern crate panic_hook; -extern crate parity_hash_fetch as hash_fetch; -extern crate parity_ipfs_api; -extern crate parity_local_store as local_store; -extern crate parity_reactor; -extern crate parity_rpc; -extern crate parity_updater as updater; -extern crate parity_version; -extern crate parity_whisper; -extern crate path; -extern crate rpc_cli; -extern crate node_filter; -extern crate keccak_hash as hash; -extern crate journaldb; -extern crate registrar; - -#[macro_use] -extern crate log as rlog; - -#[cfg(feature="stratum")] -extern crate ethcore_stratum; - -#[cfg(feature="secretstore")] -extern crate ethcore_secretstore; - -#[cfg(feature = "dapps")] -extern crate parity_dapps; - -#[cfg(test)] -#[macro_use] -extern crate pretty_assertions; +extern crate parking_lot; #[cfg(windows)] extern crate winapi; -#[cfg(test)] -extern crate tempdir; - -mod account; -mod blockchain; -mod cache; -mod cli; -mod configuration; -mod dapps; -mod export_hardcoded_sync; -mod ipfs; -mod deprecated; -mod helpers; -mod informant; -mod light_helpers; -mod modules; -mod params; -mod presale; -mod rpc; -mod rpc_apis; -mod run; -mod secretstore; -mod signer; -mod snapshot; -mod upgrade; -mod url; -mod user_defaults; -mod whisper; -mod db; - -#[cfg(feature="stratum")] -mod stratum; - use std::{process, env}; -use std::collections::HashMap; -use std::io::{self as stdio, BufReader, Read, Write}; +use std::io::{self as stdio, Read, Write}; use std::fs::{remove_file, metadata, File, create_dir_all}; use std::path::PathBuf; -use hash::keccak_buffer; -use cli::Args; -use configuration::{Cmd, Execute, Configuration}; -use deprecated::find_deprecated; -use ethcore_logger::setup_log; +use std::sync::Arc; +use ctrlc::CtrlC; use dir::default_hypervisor_path; - -fn print_hash_of(maybe_file: Option) -> Result { - if let Some(file) = maybe_file { - let mut f = BufReader::new(File::open(&file).map_err(|_| "Unable to open file".to_owned())?); - let hash = keccak_buffer(&mut f).map_err(|_| "Unable to read from file".to_owned())?; - Ok(format!("{:x}", hash)) - } else { - Err("Streaming from standard input not yet supported. Specify a file.".to_owned()) - } -} - -enum PostExecutionAction { - Print(String), - Restart(Option), - Quit, -} - -fn execute(command: Execute, can_restart: bool) -> Result { - let logger = setup_log(&command.logger).expect("Logger is initialized only once; qed"); - - match command.cmd { - Cmd::Run(run_cmd) => { - let (restart, spec_name) = run::execute(run_cmd, can_restart, logger)?; - Ok(if restart { PostExecutionAction::Restart(spec_name) } else { PostExecutionAction::Quit }) - }, - Cmd::Version => Ok(PostExecutionAction::Print(Args::print_version())), - Cmd::Hash(maybe_file) => print_hash_of(maybe_file).map(|s| PostExecutionAction::Print(s)), - Cmd::Account(account_cmd) => account::execute(account_cmd).map(|s| PostExecutionAction::Print(s)), - Cmd::ImportPresaleWallet(presale_cmd) => presale::execute(presale_cmd).map(|s| PostExecutionAction::Print(s)), - Cmd::Blockchain(blockchain_cmd) => blockchain::execute(blockchain_cmd).map(|_| PostExecutionAction::Quit), - Cmd::SignerToken(ws_conf, ui_conf, logger_config) => signer::execute(ws_conf, ui_conf, logger_config).map(|s| PostExecutionAction::Print(s)), - Cmd::SignerSign { id, pwfile, port, authfile } => rpc_cli::signer_sign(id, pwfile, port, authfile).map(|s| PostExecutionAction::Print(s)), - Cmd::SignerList { port, authfile } => rpc_cli::signer_list(port, authfile).map(|s| PostExecutionAction::Print(s)), - Cmd::SignerReject { id, port, authfile } => rpc_cli::signer_reject(id, port, authfile).map(|s| PostExecutionAction::Print(s)), - Cmd::Snapshot(snapshot_cmd) => snapshot::execute(snapshot_cmd).map(|s| PostExecutionAction::Print(s)), - Cmd::ExportHardcodedSync(export_hs_cmd) => export_hardcoded_sync::execute(export_hs_cmd).map(|s| PostExecutionAction::Print(s)), - } -} - -fn start(mut args: Vec) -> Result { - args.insert(0, "parity".to_owned()); - let conf = Configuration::parse(&args).unwrap_or_else(|e| e.exit()); - let can_restart = conf.args.flag_can_restart; - - let deprecated = find_deprecated(&conf.args); - for d in deprecated { - println!("{}", d); - } - - let cmd = conf.into_command()?; - execute(cmd, can_restart) -} - -#[cfg(not(feature="stratum"))] -fn stratum_main(_: &mut HashMap) {} - -#[cfg(feature="stratum")] -fn stratum_main(alt_mains: &mut HashMap) { - alt_mains.insert("stratum".to_owned(), stratum::main); -} - -fn sync_main(_: &mut HashMap) {} +use fdlimit::raise_fd_limit; +use parity::{start, ExecutionAction}; +use parking_lot::{Condvar, Mutex}; fn updates_path(name: &str) -> PathBuf { let mut dest = PathBuf::from(default_hypervisor_path()); @@ -275,48 +116,68 @@ const PLEASE_RESTART_EXIT_CODE: i32 = 69; // Returns the exit error code. fn main_direct(force_can_restart: bool) -> i32 { global_init(); - let mut alt_mains = HashMap::new(); - sync_main(&mut alt_mains); - stratum_main(&mut alt_mains); - let res = if let Some(f) = std::env::args().nth(1).and_then(|arg| alt_mains.get(&arg.to_string())) { - f(); - 0 + + let mut conf = { + let args = std::env::args().collect::>(); + parity::Configuration::parse_cli(&args).unwrap_or_else(|e| e.exit()) + }; + + if let Some(spec_override) = take_spec_name_override() { + conf.args.flag_testnet = false; + conf.args.arg_chain = spec_override; + } + + let can_restart = force_can_restart || conf.args.flag_can_restart; + + // increase max number of open files + raise_fd_limit(); + + let exit = Arc::new((Mutex::new((false, None)), Condvar::new())); + + let exec = if can_restart { + let e1 = exit.clone(); + let e2 = exit.clone(); + start(conf, + move |new_chain: String| { *e1.0.lock() = (true, Some(new_chain)); e1.1.notify_all(); }, + move || { *e2.0.lock() = (true, None); e2.1.notify_all(); }) } else { - let mut args = std::env::args().skip(1).collect::>(); - if force_can_restart && !args.iter().any(|arg| arg == "--can-restart") { - args.push("--can-restart".to_owned()); - } + trace!(target: "mode", "Not hypervised: not setting exit handlers."); + start(conf, move |_| {}, move || {}) + }; - if let Some(spec_override) = take_spec_name_override() { - args.retain(|f| f != "--testnet"); - args.retain(|f| !f.starts_with("--chain=")); - while let Some(pos) = args.iter().position(|a| a == "--chain") { - if args.len() > pos + 1 { - args.remove(pos + 1); + let res = match exec { + Ok(result) => match result { + ExecutionAction::Instant(Some(s)) => { println!("{}", s); 0 }, + ExecutionAction::Instant(None) => 0, + ExecutionAction::Running(client) => { + CtrlC::set_handler({ + let e = exit.clone(); + move || { e.1.notify_all(); } + }); + + // Wait for signal + let mut lock = exit.0.lock(); + let _ = exit.1.wait(&mut lock); + + client.shutdown(); + + match &*lock { + &(true, ref spec_name_override) => { + if let &Some(ref spec_name) = spec_name_override { + set_spec_name_override(spec_name.clone()); + } + PLEASE_RESTART_EXIT_CODE + }, + _ => 0, } - args.remove(pos); - } - args.push("--chain".to_owned()); - args.push(spec_override); - } - - match start(args) { - Ok(result) => match result { - PostExecutionAction::Print(s) => { println!("{}", s); 0 }, - PostExecutionAction::Restart(spec_name_override) => { - if let Some(spec_name) = spec_name_override { - set_spec_name_override(spec_name); - } - PLEASE_RESTART_EXIT_CODE - }, - PostExecutionAction::Quit => 0, - }, - Err(err) => { - writeln!(&mut stdio::stderr(), "{}", err).expect("StdErr available; qed"); - 1 }, - } + }, + Err(err) => { + writeln!(&mut stdio::stderr(), "{}", err).expect("StdErr available; qed"); + 1 + }, }; + global_cleanup(); res } diff --git a/parity/run.rs b/parity/run.rs index fdb32293b9c..73113055bbf 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -19,10 +19,8 @@ use std::fmt; use std::sync::{Arc, Weak}; use std::time::{Duration, Instant}; use std::thread; -use std::net::{TcpListener}; -use ansi_term::{Colour, Style}; -use ctrlc::CtrlC; +use ansi_term::Colour; use ethcore::account_provider::{AccountProvider, AccountProviderSettings}; use ethcore::client::{Client, Mode, DatabaseCompactionProfile, VMType, BlockChainClient, BlockInfo}; use ethcore::ethstore::ethkey; @@ -34,7 +32,6 @@ use ethcore_logger::{Config as LogConfig, RotatingLogger}; use ethcore_service::ClientService; use sync::{self, SyncConfig}; use miner::work_notify::WorkPoster; -use fdlimit::raise_fd_limit; use futures_cpupool::CpuPool; use hash_fetch::{self, fetch}; use informant::{Informant, LightNodeInformantData, FullNodeInformantData}; @@ -45,7 +42,6 @@ use node_filter::NodeFilter; use node_health; use parity_reactor::EventLoop; use parity_rpc::{NetworkSettings, informant, is_major_importing}; -use parking_lot::{Condvar, Mutex}; use updater::{UpdatePolicy, Updater}; use parity_version::version; use ethcore_private_tx::{ProviderConfig, EncryptorConfig, SecretStoreEncryptor}; @@ -65,7 +61,6 @@ use rpc; use rpc_apis; use secretstore; use signer; -use url; use db; // how often to take periodic snapshots. @@ -138,28 +133,6 @@ pub struct RunCmd { pub no_hardcoded_sync: bool, } -pub fn open_ui(ws_conf: &rpc::WsConfiguration, ui_conf: &rpc::UiConfiguration, logger_config: &LogConfig) -> Result<(), String> { - if !ui_conf.enabled { - return Err("Cannot use UI command with UI turned off.".into()) - } - - let token = signer::generate_token_and_url(ws_conf, ui_conf, logger_config)?; - // Open a browser - url::open(&token.url).map_err(|e| format!("{}", e))?; - // Print a message - println!("{}", token.message); - Ok(()) -} - -pub fn open_dapp(dapps_conf: &dapps::Configuration, rpc_conf: &rpc::HttpConfiguration, dapp: &str) -> Result<(), String> { - if !dapps_conf.enabled { - return Err("Cannot use DAPP command with Dapps turned off.".into()) - } - - let url = format!("http://{}:{}/{}/", rpc_conf.interface, rpc_conf.port, dapp); - url::open(&url).map_err(|e| format!("{}", e))?; - Ok(()) -} // node info fetcher for the local store. struct FullNodeInfo { miner: Option>, // TODO: only TXQ needed, just use that after decoupling. @@ -415,10 +388,12 @@ fn execute_light_impl(cmd: RunCmd, logger: Arc) -> Result(cmd: RunCmd, logger: Arc, on_client_rq: }, }; - // start ui - if cmd.ui { - open_ui(&cmd.ws_conf, &cmd.ui_conf, &cmd.logger_config)?; - } - - if let Some(dapp) = cmd.dapp { - open_dapp(&cmd.dapps_conf, &cmd.http_conf, &dapp)?; - } - client.set_exit_handler(on_client_rq); updater.set_exit_handler(on_updater_rq); - Ok(RunningClient::Full { - informant, - client, - keep_alive: Box::new((watcher, service, updater, ws_server, http_server, ipc_server, ui_server, secretstore_key_server, ipfs_server, event_loop)), + Ok(RunningClient { + inner: RunningClientInner::Full { + informant, + client, + keep_alive: Box::new((watcher, service, updater, ws_server, http_server, ipc_server, ui_server, secretstore_key_server, ipfs_server, event_loop)), + } }) } -enum RunningClient { +/// Parity client currently executing in background threads. +/// +/// Should be destroyed by calling `shutdown()`, otherwise execution will continue in the +/// background. +pub struct RunningClient { + inner: RunningClientInner +} + +enum RunningClientInner { Light { informant: Arc>, client: Arc, @@ -931,9 +907,10 @@ enum RunningClient { } impl RunningClient { - fn shutdown(self) { - match self { - RunningClient::Light { informant, client, keep_alive } => { + /// Shuts down the client. + pub fn shutdown(self) { + match self.inner { + RunningClientInner::Light { informant, client, keep_alive } => { // Create a weak reference to the client so that we can wait on shutdown // until it is dropped let weak_client = Arc::downgrade(&client); @@ -943,7 +920,7 @@ impl RunningClient { drop(client); wait_for_drop(weak_client); }, - RunningClient::Full { informant, client, keep_alive } => { + RunningClientInner::Full { informant, client, keep_alive } => { info!("Finishing work, please wait..."); // Create a weak reference to the client so that we can wait on shutdown // until it is dropped @@ -961,51 +938,24 @@ impl RunningClient { } } -pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc) -> Result<(bool, Option), String> { - if cmd.ui_conf.enabled && !cmd.ui_conf.info_page_only { - warn!("{}", Style::new().bold().paint("Parity browser interface is deprecated. It's going to be removed in the next version, use standalone Parity UI instead.")); - warn!("{}", Style::new().bold().paint("Standalone Parity UI: https://github.com/Parity-JS/shell/releases")); - } - - if cmd.ui && cmd.dapps_conf.enabled { - // Check if Parity is already running - let addr = format!("{}:{}", cmd.ui_conf.interface, cmd.ui_conf.port); - if !TcpListener::bind(&addr as &str).is_ok() { - return open_ui(&cmd.ws_conf, &cmd.ui_conf, &cmd.logger_config).map(|_| (false, None)); - } - } - - // increase max number of open files - raise_fd_limit(); - - let exit = Arc::new((Mutex::new((false, None)), Condvar::new())); - - let running_client = if cmd.light { - execute_light_impl(cmd, logger)? - } else if can_restart { - let e1 = exit.clone(); - let e2 = exit.clone(); - execute_impl(cmd, logger, - move |new_chain: String| { *e1.0.lock() = (true, Some(new_chain)); e1.1.notify_all(); }, - move || { *e2.0.lock() = (true, None); e2.1.notify_all(); })? +/// Executes the given run command. +/// +/// `on_client_rq` is the action to perform when the client receives an RPC request to be restarted +/// with a different chain. +/// +/// `on_updater_rq` is the action to perform when the updater has a new binary to execute. +/// +/// On error, returns what to print on stderr. +pub fn execute(cmd: RunCmd, logger: Arc, + on_client_rq: Cr, on_updater_rq: Rr) -> Result + where Cr: Fn(String) + 'static + Send, + Rr: Fn() + 'static + Send +{ + if cmd.light { + execute_light_impl(cmd, logger) } else { - trace!(target: "mode", "Not hypervised: not setting exit handlers."); - execute_impl(cmd, logger, move |_| {}, move || {})? - }; - - // Handle possible exits - CtrlC::set_handler({ - let e = exit.clone(); - move || { e.1.notify_all(); } - }); - - // Wait for signal - let mut l = exit.0.lock(); - let _ = exit.1.wait(&mut l); - - running_client.shutdown(); - - Ok(l.clone()) + execute_impl(cmd, logger, on_client_rq, on_updater_rq) + } } #[cfg(not(windows))] diff --git a/parity/snapshot.rs b/parity/snapshot.rs index ad93801c0b5..423864679a2 100644 --- a/parity/snapshot.rs +++ b/parity/snapshot.rs @@ -35,7 +35,6 @@ use params::{SpecType, Pruning, Switch, tracing_switch_to_bool, fatdb_switch_to_ use helpers::{to_client_config, execute_upgrades}; use dir::Directories; use user_defaults::UserDefaults; -use fdlimit; use ethcore_private_tx; use db; @@ -149,8 +148,6 @@ impl SnapshotCommand { // load user defaults let user_defaults = UserDefaults::load(&user_defaults_path)?; - fdlimit::raise_fd_limit(); - // select pruning algorithm let algorithm = self.pruning.to_algorithm(&user_defaults); diff --git a/parity/url.rs b/parity/url.rs index 41c4e545831..4f547c28f07 100644 --- a/parity/url.rs +++ b/parity/url.rs @@ -80,8 +80,9 @@ pub fn open(url: &str) -> Result<(), Error> { } #[cfg(target_os="android")] -pub fn open(_url: &str) { +pub fn open(_url: &str) -> Result<(), Error> { // TODO: While it is generally always bad to leave a function implemented, there is not much // more we can do here. This function will eventually be removed when we compile Parity // as a library and not as a full binary. + Ok(()) } diff --git a/test.sh b/test.sh index 84940a6aca4..6dcd258ea36 100755 --- a/test.sh +++ b/test.sh @@ -40,8 +40,18 @@ echo "________Validate chainspecs________" fi -# Running test's +# Running the C example +echo "________Running the C example________" +cd parity-clib-example && \ + mkdir -p build && \ + cd build && \ + cmake .. && \ + make && \ + ./parity-example && \ + cd .. && \ + rm -rf build && \ + cd .. + +# Running tests echo "________Running Parity Full Test Suite________" - cargo test -j 8 $OPTIONS --features "$FEATURES" --all $1 - From 7a00d97977f387e66793e6b31e0d739d3f5ff8c8 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 9 May 2018 14:48:55 +0800 Subject: [PATCH 42/95] Trace precompiled contracts when the transfer value is not zero (#8486) * Trace precompiled contracts when the transfer value is not zero * Add tests for precompiled CALL tracing * Use byzantium test machine for the new test * Add notes in comments on why we don't trace all precompileds * Use is_transferred instead of transferred --- ethcore/src/executive.rs | 86 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index cded6358e8f..e29da093c7d 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -428,8 +428,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { self.state.discard_checkpoint(); output.write(0, &builtin_out_buffer); - // trace only top level calls to builtins to avoid DDoS attacks - if self.depth == 0 { + // Trace only top level calls and calls with balance transfer to builtins. The reason why we don't + // trace all internal calls to builtin contracts is that memcpy (IDENTITY) is a heavily used + // function. + let is_transferred = match params.value { + ActionValue::Transfer(value) => value != U256::zero(), + ActionValue::Apparent(_) => false, + }; + if self.depth == 0 || is_transferred { let mut trace_output = tracer.prepare_trace_output(); if let Some(out) = trace_output.as_mut() { *out = output.to_owned(); @@ -722,6 +728,12 @@ mod tests { machine } + fn make_byzantium_machine(max_depth: usize) -> EthereumMachine { + let mut machine = ::ethereum::new_byzantium_test_machine(); + machine.set_schedule_creation_rules(Box::new(move |s, _| s.max_depth = max_depth)); + machine + } + #[test] fn test_contract_address() { let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); @@ -813,6 +825,76 @@ mod tests { assert_eq!(substate.contracts_created.len(), 0); } + #[test] + fn test_call_to_precompiled_tracing() { + // code: + // + // 60 00 - push 00 out size + // 60 00 - push 00 out offset + // 60 00 - push 00 in size + // 60 00 - push 00 in offset + // 60 01 - push 01 value + // 60 03 - push 03 to + // 61 ffff - push fff gas + // f1 - CALL + + let code = "60006000600060006001600361fffff1".from_hex().unwrap(); + let sender = Address::from_str("4444444444444444444444444444444444444444").unwrap(); + let address = Address::from_str("5555555555555555555555555555555555555555").unwrap(); + + let mut params = ActionParams::default(); + params.address = address.clone(); + params.code_address = address.clone(); + params.sender = sender.clone(); + params.origin = sender.clone(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.value = ActionValue::Transfer(U256::from(100)); + params.call_type = CallType::Call; + let mut state = get_temp_state(); + state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); + let info = EnvInfo::default(); + let machine = make_byzantium_machine(5); + let mut substate = Substate::new(); + let mut tracer = ExecutiveTracer::default(); + let mut vm_tracer = ExecutiveVMTracer::toplevel(); + + let mut ex = Executive::new(&mut state, &info, &machine); + let output = BytesRef::Fixed(&mut[0u8;0]); + ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap(); + + assert_eq!(tracer.drain(), vec![FlatTrace { + action: trace::Action::Call(trace::Call { + from: "4444444444444444444444444444444444444444".into(), + to: "5555555555555555555555555555555555555555".into(), + value: 100.into(), + gas: 100_000.into(), + input: vec![], + call_type: CallType::Call + }), + result: trace::Res::Call(trace::CallResult { + gas_used: 33021.into(), + output: vec![] + }), + subtraces: 1, + trace_address: Default::default() + }, FlatTrace { + action: trace::Action::Call(trace::Call { + from: "5555555555555555555555555555555555555555".into(), + to: "0000000000000000000000000000000000000003".into(), + value: 1.into(), + gas: 66560.into(), + input: vec![], + call_type: CallType::Call + }), result: trace::Res::Call(trace::CallResult { + gas_used: 600.into(), + output: vec![] + }), + subtraces: 0, + trace_address: vec![0].into_iter().collect(), + }]); + } + #[test] // Tracing is not suported in JIT fn test_call_to_create() { From 24838bbcd3aa3eccde8bb0c24909172c06fdf58b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 9 May 2018 08:49:34 +0200 Subject: [PATCH 43/95] Don't block sync when importing old blocks (#8530) * Alter IO queueing. * Don't require IoMessages to be Clone * Ancient blocks imported via IoChannel. * Get rid of private transactions io message. * Get rid of deadlock and fix disconnected handler. * Revert to old disconnect condition. * Fix tests. * Fix deadlock. --- Cargo.lock | 2 + ethcore/private-tx/src/lib.rs | 250 +++++++++--------- ethcore/private-tx/tests/private_contract.rs | 2 +- ethcore/service/Cargo.toml | 1 + ethcore/service/src/lib.rs | 3 + ethcore/service/src/service.rs | 32 +-- ethcore/src/client/ancient_import.rs | 50 +++- ethcore/src/client/client.rs | 254 +++++++++++-------- ethcore/src/client/io_message.rs | 30 ++- ethcore/src/client/mod.rs | 3 +- ethcore/src/client/test_client.rs | 32 +-- ethcore/src/client/traits.rs | 24 +- ethcore/src/views/block.rs | 5 +- ethcore/sync/Cargo.toml | 1 + ethcore/sync/src/api.rs | 4 + ethcore/sync/src/block_sync.rs | 2 +- ethcore/sync/src/chain.rs | 5 +- ethcore/sync/src/lib.rs | 2 + ethcore/sync/src/tests/helpers.rs | 6 +- ethcore/sync/src/tests/private.rs | 9 +- util/io/src/lib.rs | 4 +- util/io/src/service.rs | 50 ++-- util/io/src/worker.rs | 10 +- 23 files changed, 452 insertions(+), 329 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64e468e6703..b02fcbd24e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -818,6 +818,7 @@ dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "stop-guard 0.1.0", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "trace-time 0.1.0", ] [[package]] @@ -866,6 +867,7 @@ dependencies = [ "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "trace-time 0.1.0", "triehash 0.1.0", ] diff --git a/ethcore/private-tx/src/lib.rs b/ethcore/private-tx/src/lib.rs index 723d4918298..7aca4c85dc4 100644 --- a/ethcore/private-tx/src/lib.rs +++ b/ethcore/private-tx/src/lib.rs @@ -149,8 +149,8 @@ impl Provider where { encryptor: Box, config: ProviderConfig, channel: IoChannel, - ) -> Result { - Ok(Provider { + ) -> Self { + Provider { encryptor, validator_accounts: config.validator_accounts.into_iter().collect(), signer_account: config.signer_account, @@ -162,7 +162,7 @@ impl Provider where { miner, accounts, channel, - }) + } } // TODO [ToDr] Don't use `ChainNotify` here! @@ -243,50 +243,6 @@ impl Provider where { Ok(original_transaction) } - /// Process received private transaction - pub fn import_private_transaction(&self, rlp: &[u8]) -> Result<(), Error> { - trace!("Private transaction received"); - let private_tx: PrivateTransaction = Rlp::new(rlp).as_val()?; - let contract = private_tx.contract; - let contract_validators = self.get_validators(BlockId::Latest, &contract)?; - - let validation_account = contract_validators - .iter() - .find(|address| self.validator_accounts.contains(address)); - - match validation_account { - None => { - // TODO [ToDr] This still seems a bit invalid, imho we should still import the transaction to the pool. - // Importing to pool verifies correctness and nonce; here we are just blindly forwarding. - // - // Not for verification, broadcast further to peers - self.broadcast_private_transaction(rlp.into()); - return Ok(()); - }, - Some(&validation_account) => { - let hash = private_tx.hash(); - trace!("Private transaction taken for verification"); - let original_tx = self.extract_original_transaction(private_tx, &contract)?; - trace!("Validating transaction: {:?}", original_tx); - // Verify with the first account available - trace!("The following account will be used for verification: {:?}", validation_account); - let nonce_cache = Default::default(); - self.transactions_for_verification.lock().add_transaction( - original_tx, - contract, - validation_account, - hash, - self.pool_client(&nonce_cache), - )?; - // NOTE This will just fire `on_private_transaction_queued` but from a client thread. - // It seems that a lot of heavy work (verification) is done in this thread anyway - // it might actually make sense to decouple it from clientService and just use dedicated thread - // for both verification and execution. - self.channel.send(ClientIoMessage::NewPrivateTransaction).map_err(|_| ErrorKind::ClientIsMalformed.into()) - } - } - } - fn pool_client<'a>(&'a self, nonce_cache: &'a RwLock>) -> miner::pool_client::PoolClient<'a, Client> { let engine = self.client.engine(); let refuse_service_transactions = true; @@ -299,11 +255,6 @@ impl Provider where { ) } - /// Private transaction for validation added into queue - pub fn on_private_transaction_queued(&self) -> Result<(), Error> { - self.process_queue() - } - /// Retrieve and verify the first available private transaction for every sender /// /// TODO [ToDr] It seems that: @@ -347,73 +298,6 @@ impl Provider where { Ok(()) } - /// Add signed private transaction into the store - /// Creates corresponding public transaction if last required singature collected and sends it to the chain - pub fn import_signed_private_transaction(&self, rlp: &[u8]) -> Result<(), Error> { - let tx: SignedPrivateTransaction = Rlp::new(rlp).as_val()?; - trace!("Signature for private transaction received: {:?}", tx); - let private_hash = tx.private_transaction_hash(); - let desc = match self.transactions_for_signing.lock().get(&private_hash) { - None => { - // TODO [ToDr] Verification (we can't just blindly forward every transaction) - - // Not our transaction, broadcast further to peers - self.broadcast_signed_private_transaction(rlp.into()); - return Ok(()); - }, - Some(desc) => desc, - }; - - let last = self.last_required_signature(&desc, tx.signature())?; - - if last { - let mut signatures = desc.received_signatures.clone(); - signatures.push(tx.signature()); - let rsv: Vec = signatures.into_iter().map(|sign| sign.into_electrum().into()).collect(); - //Create public transaction - let public_tx = self.public_transaction( - desc.state.clone(), - &desc.original_transaction, - &rsv, - desc.original_transaction.nonce, - desc.original_transaction.gas_price - )?; - trace!("Last required signature received, public transaction created: {:?}", public_tx); - //Sign and add it to the queue - let chain_id = desc.original_transaction.chain_id(); - let hash = public_tx.hash(chain_id); - let signer_account = self.signer_account.ok_or_else(|| ErrorKind::SignerAccountNotSet)?; - let password = find_account_password(&self.passwords, &*self.accounts, &signer_account); - let signature = self.accounts.sign(signer_account, password, hash)?; - let signed = SignedTransaction::new(public_tx.with_signature(signature, chain_id))?; - match self.miner.import_own_transaction(&*self.client, signed.into()) { - Ok(_) => trace!("Public transaction added to queue"), - Err(err) => { - trace!("Failed to add transaction to queue, error: {:?}", err); - bail!(err); - } - } - //Remove from store for signing - match self.transactions_for_signing.lock().remove(&private_hash) { - Ok(_) => {} - Err(err) => { - trace!("Failed to remove transaction from signing store, error: {:?}", err); - bail!(err); - } - } - } else { - //Add signature to the store - match self.transactions_for_signing.lock().add_signature(&private_hash, tx.signature()) { - Ok(_) => trace!("Signature stored for private transaction"), - Err(err) => { - trace!("Failed to add signature to signing store, error: {:?}", err); - bail!(err); - } - } - } - Ok(()) - } - fn last_required_signature(&self, desc: &PrivateTransactionSigningDesc, sign: Signature) -> Result { if desc.received_signatures.contains(&sign) { return Ok(false); @@ -657,6 +541,134 @@ impl Provider where { } } +pub trait Importer { + /// Process received private transaction + fn import_private_transaction(&self, _rlp: &[u8]) -> Result<(), Error>; + + /// Add signed private transaction into the store + /// + /// Creates corresponding public transaction if last required signature collected and sends it to the chain + fn import_signed_private_transaction(&self, _rlp: &[u8]) -> Result<(), Error>; +} + +// TODO [ToDr] Offload more heavy stuff to the IoService thread. +// It seems that a lot of heavy work (verification) is done in this thread anyway +// it might actually make sense to decouple it from clientService and just use dedicated thread +// for both verification and execution. + +impl Importer for Arc { + fn import_private_transaction(&self, rlp: &[u8]) -> Result<(), Error> { + trace!("Private transaction received"); + let private_tx: PrivateTransaction = Rlp::new(rlp).as_val()?; + let contract = private_tx.contract; + let contract_validators = self.get_validators(BlockId::Latest, &contract)?; + + let validation_account = contract_validators + .iter() + .find(|address| self.validator_accounts.contains(address)); + + match validation_account { + None => { + // TODO [ToDr] This still seems a bit invalid, imho we should still import the transaction to the pool. + // Importing to pool verifies correctness and nonce; here we are just blindly forwarding. + // + // Not for verification, broadcast further to peers + self.broadcast_private_transaction(rlp.into()); + return Ok(()); + }, + Some(&validation_account) => { + let hash = private_tx.hash(); + trace!("Private transaction taken for verification"); + let original_tx = self.extract_original_transaction(private_tx, &contract)?; + trace!("Validating transaction: {:?}", original_tx); + // Verify with the first account available + trace!("The following account will be used for verification: {:?}", validation_account); + let nonce_cache = Default::default(); + self.transactions_for_verification.lock().add_transaction( + original_tx, + contract, + validation_account, + hash, + self.pool_client(&nonce_cache), + )?; + let provider = Arc::downgrade(self); + self.channel.send(ClientIoMessage::execute(move |_| { + if let Some(provider) = provider.upgrade() { + if let Err(e) = provider.process_queue() { + debug!("Unable to process the queue: {}", e); + } + } + })).map_err(|_| ErrorKind::ClientIsMalformed.into()) + } + } + } + + fn import_signed_private_transaction(&self, rlp: &[u8]) -> Result<(), Error> { + let tx: SignedPrivateTransaction = Rlp::new(rlp).as_val()?; + trace!("Signature for private transaction received: {:?}", tx); + let private_hash = tx.private_transaction_hash(); + let desc = match self.transactions_for_signing.lock().get(&private_hash) { + None => { + // TODO [ToDr] Verification (we can't just blindly forward every transaction) + + // Not our transaction, broadcast further to peers + self.broadcast_signed_private_transaction(rlp.into()); + return Ok(()); + }, + Some(desc) => desc, + }; + + let last = self.last_required_signature(&desc, tx.signature())?; + + if last { + let mut signatures = desc.received_signatures.clone(); + signatures.push(tx.signature()); + let rsv: Vec = signatures.into_iter().map(|sign| sign.into_electrum().into()).collect(); + //Create public transaction + let public_tx = self.public_transaction( + desc.state.clone(), + &desc.original_transaction, + &rsv, + desc.original_transaction.nonce, + desc.original_transaction.gas_price + )?; + trace!("Last required signature received, public transaction created: {:?}", public_tx); + //Sign and add it to the queue + let chain_id = desc.original_transaction.chain_id(); + let hash = public_tx.hash(chain_id); + let signer_account = self.signer_account.ok_or_else(|| ErrorKind::SignerAccountNotSet)?; + let password = find_account_password(&self.passwords, &*self.accounts, &signer_account); + let signature = self.accounts.sign(signer_account, password, hash)?; + let signed = SignedTransaction::new(public_tx.with_signature(signature, chain_id))?; + match self.miner.import_own_transaction(&*self.client, signed.into()) { + Ok(_) => trace!("Public transaction added to queue"), + Err(err) => { + trace!("Failed to add transaction to queue, error: {:?}", err); + bail!(err); + } + } + //Remove from store for signing + match self.transactions_for_signing.lock().remove(&private_hash) { + Ok(_) => {} + Err(err) => { + trace!("Failed to remove transaction from signing store, error: {:?}", err); + bail!(err); + } + } + } else { + //Add signature to the store + match self.transactions_for_signing.lock().add_signature(&private_hash, tx.signature()) { + Ok(_) => trace!("Signature stored for private transaction"), + Err(err) => { + trace!("Failed to add signature to signing store, error: {:?}", err); + bail!(err); + } + } + } + Ok(()) + } +} + /// Try to unlock account using stored password, return found password if any fn find_account_password(passwords: &Vec, account_provider: &AccountProvider, account: &Address) -> Option { for password in passwords { diff --git a/ethcore/private-tx/tests/private_contract.rs b/ethcore/private-tx/tests/private_contract.rs index e53ad5e5f68..e7e608c2b61 100644 --- a/ethcore/private-tx/tests/private_contract.rs +++ b/ethcore/private-tx/tests/private_contract.rs @@ -74,7 +74,7 @@ fn private_contract() { Box::new(NoopEncryptor::default()), config, io, - ).unwrap()); + )); let (address, _) = contract_address(CreateContractAddress::FromSenderAndNonce, &key1.address(), &0.into(), &[]); diff --git a/ethcore/service/Cargo.toml b/ethcore/service/Cargo.toml index b612baf5660..3a10849b61f 100644 --- a/ethcore/service/Cargo.toml +++ b/ethcore/service/Cargo.toml @@ -13,6 +13,7 @@ ethcore-sync = { path = "../sync" } kvdb = { path = "../../util/kvdb" } log = "0.3" stop-guard = { path = "../../util/stop-guard" } +trace-time = { path = "../../util/trace-time" } [dev-dependencies] tempdir = "0.3" diff --git a/ethcore/service/src/lib.rs b/ethcore/service/src/lib.rs index 1604e84b10a..d85a377cde2 100644 --- a/ethcore/service/src/lib.rs +++ b/ethcore/service/src/lib.rs @@ -28,6 +28,9 @@ extern crate error_chain; #[macro_use] extern crate log; +#[macro_use] +extern crate trace_time; + #[cfg(test)] extern crate tempdir; diff --git a/ethcore/service/src/service.rs b/ethcore/service/src/service.rs index b60d4194c90..5f46799796a 100644 --- a/ethcore/service/src/service.rs +++ b/ethcore/service/src/service.rs @@ -33,7 +33,7 @@ use ethcore::snapshot::{RestorationStatus}; use ethcore::spec::Spec; use ethcore::account_provider::AccountProvider; -use ethcore_private_tx; +use ethcore_private_tx::{self, Importer}; use Error; pub struct PrivateTxService { @@ -112,14 +112,13 @@ impl ClientService { account_provider, encryptor, private_tx_conf, - io_service.channel())?, - ); + io_service.channel(), + )); let private_tx = Arc::new(PrivateTxService::new(provider)); let client_io = Arc::new(ClientIoHandler { client: client.clone(), snapshot: snapshot.clone(), - private_tx: private_tx.clone(), }); io_service.register_handler(client_io)?; @@ -175,7 +174,6 @@ impl ClientService { struct ClientIoHandler { client: Arc, snapshot: Arc, - private_tx: Arc, } const CLIENT_TICK_TIMER: TimerToken = 0; @@ -191,6 +189,7 @@ impl IoHandler for ClientIoHandler { } fn timeout(&self, _io: &IoContext, timer: TimerToken) { + trace_time!("service::read"); match timer { CLIENT_TICK_TIMER => { use ethcore::snapshot::SnapshotService; @@ -203,20 +202,24 @@ impl IoHandler for ClientIoHandler { } fn message(&self, _io: &IoContext, net_message: &ClientIoMessage) { + trace_time!("service::message"); use std::thread; match *net_message { - ClientIoMessage::BlockVerified => { self.client.import_verified_blocks(); } - ClientIoMessage::NewTransactions(ref transactions, peer_id) => { - self.client.import_queued_transactions(transactions, peer_id); + ClientIoMessage::BlockVerified => { + self.client.import_verified_blocks(); } ClientIoMessage::BeginRestoration(ref manifest) => { if let Err(e) = self.snapshot.init_restore(manifest.clone(), true) { warn!("Failed to initialize snapshot restoration: {}", e); } } - ClientIoMessage::FeedStateChunk(ref hash, ref chunk) => self.snapshot.feed_state_chunk(*hash, chunk), - ClientIoMessage::FeedBlockChunk(ref hash, ref chunk) => self.snapshot.feed_block_chunk(*hash, chunk), + ClientIoMessage::FeedStateChunk(ref hash, ref chunk) => { + self.snapshot.feed_state_chunk(*hash, chunk) + } + ClientIoMessage::FeedBlockChunk(ref hash, ref chunk) => { + self.snapshot.feed_block_chunk(*hash, chunk) + } ClientIoMessage::TakeSnapshot(num) => { let client = self.client.clone(); let snapshot = self.snapshot.clone(); @@ -231,12 +234,9 @@ impl IoHandler for ClientIoHandler { debug!(target: "snapshot", "Failed to initialize periodic snapshot thread: {:?}", e); } }, - ClientIoMessage::NewMessage(ref message) => if let Err(e) = self.client.engine().handle_message(message) { - trace!(target: "poa", "Invalid message received: {}", e); - }, - ClientIoMessage::NewPrivateTransaction => if let Err(e) = self.private_tx.provider.on_private_transaction_queued() { - warn!("Failed to handle private transaction {:?}", e); - }, + ClientIoMessage::Execute(ref exec) => { + (*exec.0)(&self.client); + } _ => {} // ignore other messages } } diff --git a/ethcore/src/client/ancient_import.rs b/ethcore/src/client/ancient_import.rs index 13699ea5a0e..c2523a13a56 100644 --- a/ethcore/src/client/ancient_import.rs +++ b/ethcore/src/client/ancient_import.rs @@ -32,16 +32,16 @@ const HEAVY_VERIFY_RATE: f32 = 0.02; /// Ancient block verifier: import an ancient sequence of blocks in order from a starting /// epoch. pub struct AncientVerifier { - cur_verifier: RwLock>>, + cur_verifier: RwLock>>>, engine: Arc, } impl AncientVerifier { - /// Create a new ancient block verifier with the given engine and initial verifier. - pub fn new(engine: Arc, start_verifier: Box>) -> Self { + /// Create a new ancient block verifier with the given engine. + pub fn new(engine: Arc) -> Self { AncientVerifier { - cur_verifier: RwLock::new(start_verifier), - engine: engine, + cur_verifier: RwLock::new(None), + engine, } } @@ -53,17 +53,49 @@ impl AncientVerifier { header: &Header, chain: &BlockChain, ) -> Result<(), ::error::Error> { - match rng.gen::() <= HEAVY_VERIFY_RATE { - true => self.cur_verifier.read().verify_heavy(header)?, - false => self.cur_verifier.read().verify_light(header)?, + // perform verification + let verified = if let Some(ref cur_verifier) = *self.cur_verifier.read() { + match rng.gen::() <= HEAVY_VERIFY_RATE { + true => cur_verifier.verify_heavy(header)?, + false => cur_verifier.verify_light(header)?, + } + true + } else { + false + }; + + // when there is no verifier initialize it. + // We use a bool flag to avoid double locking in the happy case + if !verified { + { + let mut cur_verifier = self.cur_verifier.write(); + if cur_verifier.is_none() { + *cur_verifier = Some(self.initial_verifier(header, chain)?); + } + } + // Call again to verify. + return self.verify(rng, header, chain); } // ancient import will only use transitions obtained from the snapshot. if let Some(transition) = chain.epoch_transition(header.number(), header.hash()) { let v = self.engine.epoch_verifier(&header, &transition.proof).known_confirmed()?; - *self.cur_verifier.write() = v; + *self.cur_verifier.write() = Some(v); } Ok(()) } + + fn initial_verifier(&self, header: &Header, chain: &BlockChain) + -> Result>, ::error::Error> + { + trace!(target: "client", "Initializing ancient block restoration."); + let current_epoch_data = chain.epoch_transitions() + .take_while(|&(_, ref t)| t.block_number < header.number()) + .last() + .map(|(_, t)| t.proof) + .expect("At least one epoch entry (genesis) always stored; qed"); + + self.engine.epoch_verifier(&header, ¤t_epoch_data).known_confirmed() + } } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 8119ebd35f6..bffa4e38ba8 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -15,15 +15,16 @@ // along with Parity. If not, see . use std::collections::{HashSet, BTreeMap, BTreeSet, VecDeque}; +use std::fmt; use std::str::FromStr; -use std::sync::{Arc, Weak}; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; +use std::sync::{Arc, Weak}; use std::time::{Instant, Duration}; -use itertools::Itertools; // util use hash::keccak; use bytes::Bytes; +use itertools::Itertools; use journaldb; use trie::{TrieSpec, TrieFactory, Trie}; use kvdb::{DBValue, KeyValueDB, DBTransaction}; @@ -45,7 +46,8 @@ use client::{ use client::{ BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient, TraceFilter, CallAnalytics, BlockImportError, Mode, - ChainNotify, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType + ChainNotify, ChainRoute, PruningInfo, ProvingBlockChainClient, EngineInfo, ChainMessageType, + IoClient, }; use encoded; use engines::{EthEngine, EpochTransition}; @@ -55,7 +57,7 @@ use evm::Schedule; use executive::{Executive, Executed, TransactOptions, contract_address}; use factory::{Factories, VmFactory}; use header::{BlockNumber, Header}; -use io::IoChannel; +use io::{IoChannel, IoError}; use log_entry::LocalizedLogEntry; use miner::{Miner, MinerService}; use ethcore_miner::pool::VerifiedTransaction; @@ -85,6 +87,7 @@ pub use verification::queue::QueueInfo as BlockQueueInfo; use_contract!(registry, "Registry", "res/contracts/registrar.json"); const MAX_TX_QUEUE_SIZE: usize = 4096; +const MAX_ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096; const MAX_QUEUE_SIZE_TO_SLEEP_ON: usize = 2; const MIN_HISTORY_SIZE: u64 = 8; @@ -154,10 +157,7 @@ struct Importer { pub miner: Arc, /// Ancient block verifier: import an ancient sequence of blocks in order from a starting epoch - pub ancient_verifier: Mutex>, - - /// Random number generator used by `AncientVerifier` - pub rng: Mutex, + pub ancient_verifier: AncientVerifier, /// Ethereum engine to be used during import pub engine: Arc, @@ -204,8 +204,13 @@ pub struct Client { /// List of actors to be notified on certain chain events notify: RwLock>>, - /// Count of pending transactions in the queue - queue_transactions: AtomicUsize, + /// Queued transactions from IO + queue_transactions: IoChannelQueue, + /// Ancient blocks import queue + queue_ancient_blocks: IoChannelQueue, + /// Consensus messages import queue + queue_consensus_message: IoChannelQueue, + last_hashes: RwLock>, factories: Factories, @@ -239,8 +244,7 @@ impl Importer { verifier: verification::new(config.verifier_type.clone()), block_queue, miner, - ancient_verifier: Mutex::new(None), - rng: Mutex::new(OsRng::new()?), + ancient_verifier: AncientVerifier::new(engine.clone()), engine, }) } @@ -416,55 +420,25 @@ impl Importer { Ok(locked_block) } + /// Import a block with transaction receipts. /// /// The block is guaranteed to be the next best blocks in the /// first block sequence. Does no sealing or transaction validation. - fn import_old_block(&self, header: &Header, block_bytes: Bytes, receipts_bytes: Bytes, db: &KeyValueDB, chain: &BlockChain) -> Result { - let receipts = ::rlp::decode_list(&receipts_bytes); + fn import_old_block(&self, header: &Header, block_bytes: &[u8], receipts_bytes: &[u8], db: &KeyValueDB, chain: &BlockChain) -> Result { + let receipts = ::rlp::decode_list(receipts_bytes); let hash = header.hash(); let _import_lock = self.import_lock.lock(); { trace_time!("import_old_block"); - let mut ancient_verifier = self.ancient_verifier.lock(); - - { - // closure for verifying a block. - let verify_with = |verifier: &AncientVerifier| -> Result<(), ::error::Error> { - // verify the block, passing the chain for updating the epoch - // verifier. - let mut rng = OsRng::new().map_err(UtilError::from)?; - verifier.verify(&mut rng, &header, &chain) - }; - - // initialize the ancient block verifier if we don't have one already. - match &mut *ancient_verifier { - &mut Some(ref verifier) => { - verify_with(verifier)? - } - x @ &mut None => { - // load most recent epoch. - trace!(target: "client", "Initializing ancient block restoration."); - let current_epoch_data = chain.epoch_transitions() - .take_while(|&(_, ref t)| t.block_number < header.number()) - .last() - .map(|(_, t)| t.proof) - .expect("At least one epoch entry (genesis) always stored; qed"); - - let current_verifier = self.engine.epoch_verifier(&header, ¤t_epoch_data) - .known_confirmed()?; - let current_verifier = AncientVerifier::new(self.engine.clone(), current_verifier); - - verify_with(¤t_verifier)?; - *x = Some(current_verifier); - } - } - } + // verify the block, passing the chain for updating the epoch verifier. + let mut rng = OsRng::new().map_err(UtilError::from)?; + self.ancient_verifier.verify(&mut rng, &header, &chain)?; // Commit results let mut batch = DBTransaction::new(); - chain.insert_unordered_block(&mut batch, &block_bytes, receipts, None, false, true); + chain.insert_unordered_block(&mut batch, block_bytes, receipts, None, false, true); // Final commit to the DB db.write_buffered(batch); chain.commit(); @@ -734,7 +708,9 @@ impl Client { report: RwLock::new(Default::default()), io_channel: Mutex::new(message_channel), notify: RwLock::new(Vec::new()), - queue_transactions: AtomicUsize::new(0), + queue_transactions: IoChannelQueue::new(MAX_TX_QUEUE_SIZE), + queue_ancient_blocks: IoChannelQueue::new(MAX_ANCIENT_BLOCKS_QUEUE_SIZE), + queue_consensus_message: IoChannelQueue::new(usize::max_value()), last_hashes: RwLock::new(VecDeque::new()), factories: factories, history: history, @@ -820,7 +796,7 @@ impl Client { } fn notify(&self, f: F) where F: Fn(&ChainNotify) { - for np in self.notify.read().iter() { + for np in &*self.notify.read() { if let Some(n) = np.upgrade() { f(&*n); } @@ -954,24 +930,6 @@ impl Client { } } - /// Import transactions from the IO queue - pub fn import_queued_transactions(&self, transactions: &[Bytes], peer_id: usize) -> usize { - trace_time!("import_queued_transactions"); - self.queue_transactions.fetch_sub(transactions.len(), AtomicOrdering::SeqCst); - - let txs: Vec = transactions - .iter() - .filter_map(|bytes| self.engine().decode_transaction(bytes).ok()) - .collect(); - - self.notify(|notify| { - notify.transactions_received(&txs, peer_id); - }); - - let results = self.importer.miner.import_external_transactions(self, txs); - results.len() - } - /// Get shared miner reference. #[cfg(test)] pub fn miner(&self) -> Arc { @@ -1392,22 +1350,6 @@ impl ImportBlock for Client { } Ok(self.importer.block_queue.import(unverified)?) } - - fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result { - let header: Header = ::rlp::Rlp::new(&block_bytes).val_at(0)?; - { - // check block order - if self.chain.read().is_known(&header.hash()) { - bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain)); - } - let status = self.block_status(BlockId::Hash(*header.parent_hash())); - if status == BlockStatus::Unknown || status == BlockStatus::Pending { - bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(*header.parent_hash()))); - } - } - - self.importer.import_old_block(&header, block_bytes, receipts_bytes, &**self.db.read(), &*self.chain.read()).map_err(Into::into) - } } impl StateClient for Client { @@ -1958,35 +1900,10 @@ impl BlockChainClient for Client { (*self.build_last_hashes(&self.chain.read().best_block_hash())).clone() } - fn queue_transactions(&self, transactions: Vec, peer_id: usize) { - let queue_size = self.queue_transactions.load(AtomicOrdering::Relaxed); - trace!(target: "external_tx", "Queue size: {}", queue_size); - if queue_size > MAX_TX_QUEUE_SIZE { - debug!("Ignoring {} transactions: queue is full", transactions.len()); - } else { - let len = transactions.len(); - match self.io_channel.lock().send(ClientIoMessage::NewTransactions(transactions, peer_id)) { - Ok(_) => { - self.queue_transactions.fetch_add(len, AtomicOrdering::SeqCst); - } - Err(e) => { - debug!("Ignoring {} transactions: error queueing: {}", len, e); - } - } - } - } - fn ready_transactions(&self) -> Vec> { self.importer.miner.ready_transactions(self) } - fn queue_consensus_message(&self, message: Bytes) { - let channel = self.io_channel.lock().clone(); - if let Err(e) = channel.send(ClientIoMessage::NewMessage(message)) { - debug!("Ignoring the message, error queueing: {}", e); - } - } - fn signing_chain_id(&self) -> Option { self.engine.signing_chain_id(&self.latest_env_info()) } @@ -2034,6 +1951,72 @@ impl BlockChainClient for Client { } } +impl IoClient for Client { + fn queue_transactions(&self, transactions: Vec, peer_id: usize) { + let len = transactions.len(); + self.queue_transactions.queue(&mut self.io_channel.lock(), len, move |client| { + trace_time!("import_queued_transactions"); + + let txs: Vec = transactions + .iter() + .filter_map(|bytes| client.engine.decode_transaction(bytes).ok()) + .collect(); + + client.notify(|notify| { + notify.transactions_received(&txs, peer_id); + }); + + client.importer.miner.import_external_transactions(client, txs); + }).unwrap_or_else(|e| { + debug!(target: "client", "Ignoring {} transactions: {}", len, e); + }); + } + + fn queue_ancient_block(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result { + let header: Header = ::rlp::Rlp::new(&block_bytes).val_at(0)?; + let hash = header.hash(); + + { + // check block order + if self.chain.read().is_known(&header.hash()) { + bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain)); + } + let status = self.block_status(BlockId::Hash(*header.parent_hash())); + if status == BlockStatus::Unknown || status == BlockStatus::Pending { + bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(*header.parent_hash()))); + } + } + + match self.queue_ancient_blocks.queue(&mut self.io_channel.lock(), 1, move |client| { + client.importer.import_old_block( + &header, + &block_bytes, + &receipts_bytes, + &**client.db.read(), + &*client.chain.read() + ).map(|_| ()).unwrap_or_else(|e| { + error!(target: "client", "Error importing ancient block: {}", e); + }); + }) { + Ok(_) => Ok(hash), + Err(e) => bail!(BlockImportErrorKind::Other(format!("{}", e))), + } + } + + fn queue_consensus_message(&self, message: Bytes) { + match self.queue_consensus_message.queue(&mut self.io_channel.lock(), 1, move |client| { + if let Err(e) = client.engine().handle_message(&message) { + debug!(target: "poa", "Invalid message received: {}", e); + } + }) { + Ok(_) => (), + Err(e) => { + debug!(target: "poa", "Ignoring the message, error queueing: {}", e); + } + } + } +} + impl ReopenBlock for Client { fn reopen_block(&self, block: ClosedBlock) -> OpenBlock { let engine = &*self.engine; @@ -2409,3 +2392,54 @@ mod tests { }); } } + +#[derive(Debug)] +enum QueueError { + Channel(IoError), + Full(usize), +} + +impl fmt::Display for QueueError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + QueueError::Channel(ref c) => fmt::Display::fmt(c, fmt), + QueueError::Full(limit) => write!(fmt, "The queue is full ({})", limit), + } + } +} + +/// Queue some items to be processed by IO client. +struct IoChannelQueue { + currently_queued: Arc, + limit: usize, +} + +impl IoChannelQueue { + pub fn new(limit: usize) -> Self { + IoChannelQueue { + currently_queued: Default::default(), + limit, + } + } + + pub fn queue(&self, channel: &mut IoChannel, count: usize, fun: F) -> Result<(), QueueError> where + F: Fn(&Client) + Send + Sync + 'static, + { + let queue_size = self.currently_queued.load(AtomicOrdering::Relaxed); + ensure!(queue_size < self.limit, QueueError::Full(self.limit)); + + let currently_queued = self.currently_queued.clone(); + let result = channel.send(ClientIoMessage::execute(move |client| { + currently_queued.fetch_sub(count, AtomicOrdering::SeqCst); + fun(client); + })); + + match result { + Ok(_) => { + self.currently_queued.fetch_add(count, AtomicOrdering::SeqCst); + Ok(()) + }, + Err(e) => Err(QueueError::Channel(e)), + } + } +} diff --git a/ethcore/src/client/io_message.rs b/ethcore/src/client/io_message.rs index e19d3054fe0..817c7260205 100644 --- a/ethcore/src/client/io_message.rs +++ b/ethcore/src/client/io_message.rs @@ -14,19 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethereum_types::H256; +use std::fmt; use bytes::Bytes; +use client::Client; +use ethereum_types::H256; use snapshot::ManifestData; /// Message type for external and internal events -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Debug)] pub enum ClientIoMessage { /// Best Block Hash in chain has been changed NewChainHead, /// A block is ready BlockVerified, - /// New transaction RLPs are ready to be imported - NewTransactions(Vec, usize), /// Begin snapshot restoration BeginRestoration(ManifestData), /// Feed a state chunk to the snapshot service @@ -35,9 +35,23 @@ pub enum ClientIoMessage { FeedBlockChunk(H256, Bytes), /// Take a snapshot for the block with given number. TakeSnapshot(u64), - /// New consensus message received. - NewMessage(Bytes), - /// New private transaction arrived - NewPrivateTransaction, + /// Execute wrapped closure + Execute(Callback), +} + +impl ClientIoMessage { + /// Create new `ClientIoMessage` that executes given procedure. + pub fn execute(fun: F) -> Self { + ClientIoMessage::Execute(Callback(Box::new(fun))) + } +} + +/// A function to invoke in the client thread. +pub struct Callback(pub Box); + +impl fmt::Debug for Callback { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "") + } } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 05e2018258f..4c410d30117 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -36,9 +36,8 @@ pub use self::traits::{ Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, PrepareOpenBlock, CallContract, TransactionInfo, RegistryInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock, StateClient, Call, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter }; -//pub use self::private_notify::PrivateNotify; pub use state::StateInfo; -pub use self::traits::{BlockChainClient, EngineClient, ProvingBlockChainClient}; +pub use self::traits::{BlockChainClient, EngineClient, ProvingBlockChainClient, IoClient}; pub use types::ids::*; pub use types::trace_filter::Filter as TraceFilter; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index c2e06009b64..b229159667d 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -39,7 +39,7 @@ use client::{ PrepareOpenBlock, BlockChainClient, BlockChainInfo, BlockStatus, BlockId, TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics, BlockImportError, ProvingBlockChainClient, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock, - Call, StateClient, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter + Call, StateClient, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter, IoClient }; use db::{NUM_COLUMNS, COL_STATE}; use header::{Header as BlockHeader, BlockNumber}; @@ -556,10 +556,6 @@ impl ImportBlock for TestBlockChainClient { } Ok(h) } - - fn import_block_with_receipts(&self, b: Bytes, _r: Bytes) -> Result { - self.import_block(b) - } } impl Call for TestBlockChainClient { @@ -809,16 +805,6 @@ impl BlockChainClient for TestBlockChainClient { self.traces.read().clone() } - fn queue_transactions(&self, transactions: Vec, _peer_id: usize) { - // import right here - let txs = transactions.into_iter().filter_map(|bytes| Rlp::new(&bytes).as_val().ok()).collect(); - self.miner.import_external_transactions(self, txs); - } - - fn queue_consensus_message(&self, message: Bytes) { - self.spec.engine.handle_message(&message).unwrap(); - } - fn ready_transactions(&self) -> Vec> { self.miner.ready_transactions(self) } @@ -863,6 +849,22 @@ impl BlockChainClient for TestBlockChainClient { fn eip86_transition(&self) -> u64 { u64::max_value() } } +impl IoClient for TestBlockChainClient { + fn queue_transactions(&self, transactions: Vec, _peer_id: usize) { + // import right here + let txs = transactions.into_iter().filter_map(|bytes| Rlp::new(&bytes).as_val().ok()).collect(); + self.miner.import_external_transactions(self, txs); + } + + fn queue_ancient_block(&self, b: Bytes, _r: Bytes) -> Result { + self.import_block(b) + } + + fn queue_consensus_message(&self, message: Bytes) { + self.spec.engine.handle_message(&message).unwrap(); + } +} + impl ProvingBlockChainClient for TestBlockChainClient { fn prove_storage(&self, _: H256, _: H256, _: BlockId) -> Option<(Vec, H256)> { None diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 7d4d5846c69..358e24fa905 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -168,9 +168,6 @@ pub trait RegistryInfo { pub trait ImportBlock { /// Import a block into the blockchain. fn import_block(&self, bytes: Bytes) -> Result; - - /// Import a block with transaction receipts. Does no sealing and transaction validation. - fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result; } /// Provides `call_contract` method @@ -201,8 +198,21 @@ pub trait EngineInfo { fn engine(&self) -> &EthEngine; } +/// IO operations that should off-load heavy work to another thread. +pub trait IoClient: Sync + Send { + /// Queue transactions for importing. + fn queue_transactions(&self, transactions: Vec, peer_id: usize); + + /// Queue block import with transaction receipts. Does no sealing and transaction validation. + fn queue_ancient_block(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result; + + /// Queue conensus engine message. + fn queue_consensus_message(&self, message: Bytes); +} + /// Blockchain database client. Owns and manages a blockchain and a block queue. -pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContract + RegistryInfo + ImportBlock { +pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContract + RegistryInfo + ImportBlock ++ IoClient { /// Look up the block number for the given block ID. fn block_number(&self, id: BlockId) -> Option; @@ -310,12 +320,6 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra /// Get last hashes starting from best block. fn last_hashes(&self) -> LastHashes; - /// Queue transactions for importing. - fn queue_transactions(&self, transactions: Vec, peer_id: usize); - - /// Queue conensus engine message. - fn queue_consensus_message(&self, message: Bytes); - /// List all transactions that are allowed into the next block. fn ready_transactions(&self) -> Vec>; diff --git a/ethcore/src/views/block.rs b/ethcore/src/views/block.rs index f610504d85f..3bed1818f24 100644 --- a/ethcore/src/views/block.rs +++ b/ethcore/src/views/block.rs @@ -29,7 +29,6 @@ pub struct BlockView<'a> { rlp: ViewRlp<'a> } - impl<'a> BlockView<'a> { /// Creates new view onto block from rlp. /// Use the `view!` macro to create this view in order to capture debugging info. @@ -39,9 +38,9 @@ impl<'a> BlockView<'a> { /// ``` /// #[macro_use] /// extern crate ethcore; - /// + /// /// use ethcore::views::{BlockView}; - /// + /// /// fn main() { /// let bytes : &[u8] = &[]; /// let block_view = view!(BlockView, bytes); diff --git a/ethcore/sync/Cargo.toml b/ethcore/sync/Cargo.toml index d2d060e686f..ba03075d0e3 100644 --- a/ethcore/sync/Cargo.toml +++ b/ethcore/sync/Cargo.toml @@ -30,6 +30,7 @@ heapsize = "0.4" semver = "0.9" smallvec = { version = "0.4", features = ["heapsizeof"] } parking_lot = "0.5" +trace-time = { path = "../../util/trace-time" } ipnetwork = "0.12.6" [dev-dependencies] diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index 7690eeb864b..4fd0cbb54dd 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -379,10 +379,12 @@ impl NetworkProtocolHandler for SyncProtocolHandler { } fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) { + trace_time!("sync::read"); ChainSync::dispatch_packet(&self.sync, &mut NetSyncIo::new(io, &*self.chain, &*self.snapshot_service, &self.overlay), *peer, packet_id, data); } fn connected(&self, io: &NetworkContext, peer: &PeerId) { + trace_time!("sync::connected"); // If warp protocol is supported only allow warp handshake let warp_protocol = io.protocol_version(WARP_SYNC_PROTOCOL_ID, *peer).unwrap_or(0) != 0; let warp_context = io.subprotocol_name() == WARP_SYNC_PROTOCOL_ID; @@ -392,12 +394,14 @@ impl NetworkProtocolHandler for SyncProtocolHandler { } fn disconnected(&self, io: &NetworkContext, peer: &PeerId) { + trace_time!("sync::disconnected"); if io.subprotocol_name() != WARP_SYNC_PROTOCOL_ID { self.sync.write().on_peer_aborting(&mut NetSyncIo::new(io, &*self.chain, &*self.snapshot_service, &self.overlay), *peer); } } fn timeout(&self, io: &NetworkContext, _timer: TimerToken) { + trace_time!("sync::timeout"); let mut io = NetSyncIo::new(io, &*self.chain, &*self.snapshot_service, &self.overlay); self.sync.write().maintain_peers(&mut io); self.sync.write().maintain_sync(&mut io); diff --git a/ethcore/sync/src/block_sync.rs b/ethcore/sync/src/block_sync.rs index 4a5acae526b..7411fa30ccf 100644 --- a/ethcore/sync/src/block_sync.rs +++ b/ethcore/sync/src/block_sync.rs @@ -496,7 +496,7 @@ impl BlockDownloader { } let result = if let Some(receipts) = receipts { - io.chain().import_block_with_receipts(block, receipts) + io.chain().queue_ancient_block(block, receipts) } else { io.chain().import_block(block) }; diff --git a/ethcore/sync/src/chain.rs b/ethcore/sync/src/chain.rs index 25d9a09f6bc..1a6af101159 100644 --- a/ethcore/sync/src/chain.rs +++ b/ethcore/sync/src/chain.rs @@ -1789,10 +1789,13 @@ impl ChainSync { } pub fn on_packet(&mut self, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { + debug!(target: "sync", "{} -> Dispatching packet: {}", peer, packet_id); + if packet_id != STATUS_PACKET && !self.peers.contains_key(&peer) { debug!(target:"sync", "Unexpected packet {} from unregistered peer: {}:{}", packet_id, peer, io.peer_info(peer)); return; } + let rlp = Rlp::new(data); let result = match packet_id { STATUS_PACKET => self.on_peer_status(io, peer, &rlp), @@ -1831,7 +1834,7 @@ impl ChainSync { PeerAsking::SnapshotData => elapsed > SNAPSHOT_DATA_TIMEOUT, }; if timeout { - trace!(target:"sync", "Timeout {}", peer_id); + debug!(target:"sync", "Timeout {}", peer_id); io.disconnect_peer(*peer_id); aborting.push(*peer_id); } diff --git a/ethcore/sync/src/lib.rs b/ethcore/sync/src/lib.rs index a3e24bdb823..3eb2e8332b4 100644 --- a/ethcore/sync/src/lib.rs +++ b/ethcore/sync/src/lib.rs @@ -54,6 +54,8 @@ extern crate macros; extern crate log; #[macro_use] extern crate heapsize; +#[macro_use] +extern crate trace_time; mod chain; mod blocks; diff --git a/ethcore/sync/src/tests/helpers.rs b/ethcore/sync/src/tests/helpers.rs index dc52fdd8b85..3a4697cc093 100644 --- a/ethcore/sync/src/tests/helpers.rs +++ b/ethcore/sync/src/tests/helpers.rs @@ -520,11 +520,9 @@ impl TestIoHandler { impl IoHandler for TestIoHandler { fn message(&self, _io: &IoContext, net_message: &ClientIoMessage) { match *net_message { - ClientIoMessage::NewMessage(ref message) => if let Err(e) = self.client.engine().handle_message(message) { - panic!("Invalid message received: {}", e); - }, - ClientIoMessage::NewPrivateTransaction => { + ClientIoMessage::Execute(ref exec) => { *self.private_tx_queued.lock() += 1; + (*exec.0)(&self.client); }, _ => {} // ignore other messages } diff --git a/ethcore/sync/src/tests/private.rs b/ethcore/sync/src/tests/private.rs index a9e8718e5e7..b54240bfb87 100644 --- a/ethcore/sync/src/tests/private.rs +++ b/ethcore/sync/src/tests/private.rs @@ -24,7 +24,7 @@ use ethcore::CreateContractAddress; use transaction::{Transaction, Action}; use ethcore::executive::{contract_address}; use ethcore::test_helpers::{push_block_with_transactions}; -use ethcore_private_tx::{Provider, ProviderConfig, NoopEncryptor}; +use ethcore_private_tx::{Provider, ProviderConfig, NoopEncryptor, Importer}; use ethcore::account_provider::AccountProvider; use ethkey::{KeyPair}; use tests::helpers::{TestNet, TestIoHandler}; @@ -84,7 +84,7 @@ fn send_private_transaction() { Box::new(NoopEncryptor::default()), signer_config, IoChannel::to_handler(Arc::downgrade(&io_handler0)), - ).unwrap()); + )); pm0.add_notify(net.peers[0].clone()); let pm1 = Arc::new(Provider::new( @@ -94,7 +94,7 @@ fn send_private_transaction() { Box::new(NoopEncryptor::default()), validator_config, IoChannel::to_handler(Arc::downgrade(&io_handler1)), - ).unwrap()); + )); pm1.add_notify(net.peers[1].clone()); // Create and deploy contract @@ -133,7 +133,6 @@ fn send_private_transaction() { //process received private transaction message let private_transaction = received_private_transactions[0].clone(); assert!(pm1.import_private_transaction(&private_transaction).is_ok()); - assert!(pm1.on_private_transaction_queued().is_ok()); //send signed response net.sync(); @@ -147,4 +146,4 @@ fn send_private_transaction() { assert!(pm0.import_signed_private_transaction(&signed_private_transaction).is_ok()); let local_transactions = net.peer(0).miner.local_transactions(); assert_eq!(local_transactions.len(), 1); -} \ No newline at end of file +} diff --git a/util/io/src/lib.rs b/util/io/src/lib.rs index 20b908ac91d..9232b2a909a 100644 --- a/util/io/src/lib.rs +++ b/util/io/src/lib.rs @@ -106,7 +106,7 @@ impl From<::std::io::Error> for IoError { } } -impl From>> for IoError where Message: Send + Clone { +impl From>> for IoError where Message: Send { fn from(_err: NotifyError>) -> IoError { IoError::Mio(::std::io::Error::new(::std::io::ErrorKind::ConnectionAborted, "Network IO notification error")) } @@ -115,7 +115,7 @@ impl From>> for IoError where M /// Generic IO handler. /// All the handler function are called from within IO event loop. /// `Message` type is used as notification data -pub trait IoHandler: Send + Sync where Message: Send + Sync + Clone + 'static { +pub trait IoHandler: Send + Sync where Message: Send + Sync + 'static { /// Initialize the handler fn initialize(&self, _io: &IoContext) {} /// Timer function called after a timeout created with `HandlerIo::timeout`. diff --git a/util/io/src/service.rs b/util/io/src/service.rs index 19f2d4b3bb5..0de674ae121 100644 --- a/util/io/src/service.rs +++ b/util/io/src/service.rs @@ -41,7 +41,7 @@ const MAX_HANDLERS: usize = 8; /// Messages used to communicate with the event loop from other threads. #[derive(Clone)] -pub enum IoMessage where Message: Send + Clone + Sized { +pub enum IoMessage where Message: Send + Sized { /// Shutdown the event loop Shutdown, /// Register a new protocol handler. @@ -74,16 +74,16 @@ pub enum IoMessage where Message: Send + Clone + Sized { token: StreamToken, }, /// Broadcast a message across all protocol handlers. - UserMessage(Message) + UserMessage(Arc) } /// IO access point. This is passed to all IO handlers and provides an interface to the IO subsystem. -pub struct IoContext where Message: Send + Clone + Sync + 'static { +pub struct IoContext where Message: Send + Sync + 'static { channel: IoChannel, handler: HandlerId, } -impl IoContext where Message: Send + Clone + Sync + 'static { +impl IoContext where Message: Send + Sync + 'static { /// Create a new IO access point. Takes references to all the data that can be updated within the IO handler. pub fn new(channel: IoChannel, handler: HandlerId) -> IoContext { IoContext { @@ -187,7 +187,7 @@ pub struct IoManager where Message: Send + Sync { work_ready: Arc, } -impl IoManager where Message: Send + Sync + Clone + 'static { +impl IoManager where Message: Send + Sync + 'static { /// Creates a new instance and registers it with the event loop. pub fn start( event_loop: &mut EventLoop>, @@ -219,7 +219,7 @@ impl IoManager where Message: Send + Sync + Clone + 'static { } } -impl Handler for IoManager where Message: Send + Clone + Sync + 'static { +impl Handler for IoManager where Message: Send + Sync + 'static { type Timeout = Token; type Message = IoMessage; @@ -317,7 +317,12 @@ impl Handler for IoManager where Message: Send + Clone + Sync for id in 0 .. MAX_HANDLERS { if let Some(h) = self.handlers.read().get(id) { let handler = h.clone(); - self.worker_channel.push(Work { work_type: WorkType::Message(data.clone()), token: 0, handler: handler, handler_id: id }); + self.worker_channel.push(Work { + work_type: WorkType::Message(data.clone()), + token: 0, + handler: handler, + handler_id: id + }); } } self.work_ready.notify_all(); @@ -326,21 +331,30 @@ impl Handler for IoManager where Message: Send + Clone + Sync } } -#[derive(Clone)] -enum Handlers where Message: Send + Clone { +enum Handlers where Message: Send { SharedCollection(Weak>, HandlerId>>>), Single(Weak>), } +impl Clone for Handlers { + fn clone(&self) -> Self { + use self::Handlers::*; + + match *self { + SharedCollection(ref w) => SharedCollection(w.clone()), + Single(ref w) => Single(w.clone()), + } + } +} + /// Allows sending messages into the event loop. All the IO handlers will get the message /// in the `message` callback. -pub struct IoChannel where Message: Send + Clone{ +pub struct IoChannel where Message: Send { channel: Option>>, handlers: Handlers, - } -impl Clone for IoChannel where Message: Send + Clone + Sync + 'static { +impl Clone for IoChannel where Message: Send + Sync + 'static { fn clone(&self) -> IoChannel { IoChannel { channel: self.channel.clone(), @@ -349,11 +363,11 @@ impl Clone for IoChannel where Message: Send + Clone + Sync + } } -impl IoChannel where Message: Send + Clone + Sync + 'static { +impl IoChannel where Message: Send + Sync + 'static { /// Send a message through the channel pub fn send(&self, message: Message) -> Result<(), IoError> { match self.channel { - Some(ref channel) => channel.send(IoMessage::UserMessage(message))?, + Some(ref channel) => channel.send(IoMessage::UserMessage(Arc::new(message)))?, None => self.send_sync(message)? } Ok(()) @@ -413,13 +427,13 @@ impl IoChannel where Message: Send + Clone + Sync + 'static { /// General IO Service. Starts an event loop and dispatches IO requests. /// 'Message' is a notification message type -pub struct IoService where Message: Send + Sync + Clone + 'static { +pub struct IoService where Message: Send + Sync + 'static { thread: Mutex>>, host_channel: Mutex>>, handlers: Arc>, HandlerId>>>, } -impl IoService where Message: Send + Sync + Clone + 'static { +impl IoService where Message: Send + Sync + 'static { /// Starts IO event loop pub fn start() -> Result, IoError> { let mut config = EventLoopBuilder::new(); @@ -462,7 +476,7 @@ impl IoService where Message: Send + Sync + Clone + 'static { /// Send a message over the network. Normaly `HostIo::send` should be used. This can be used from non-io threads. pub fn send_message(&self, message: Message) -> Result<(), IoError> { - self.host_channel.lock().send(IoMessage::UserMessage(message))?; + self.host_channel.lock().send(IoMessage::UserMessage(Arc::new(message)))?; Ok(()) } @@ -472,7 +486,7 @@ impl IoService where Message: Send + Sync + Clone + 'static { } } -impl Drop for IoService where Message: Send + Sync + Clone { +impl Drop for IoService where Message: Send + Sync { fn drop(&mut self) { self.stop() } diff --git a/util/io/src/worker.rs b/util/io/src/worker.rs index 79570d3612a..0f0d448ecb4 100644 --- a/util/io/src/worker.rs +++ b/util/io/src/worker.rs @@ -38,7 +38,7 @@ pub enum WorkType { Writable, Hup, Timeout, - Message(Message) + Message(Arc) } pub struct Work { @@ -65,7 +65,7 @@ impl Worker { wait: Arc, wait_mutex: Arc>, ) -> Worker - where Message: Send + Sync + Clone + 'static { + where Message: Send + Sync + 'static { let deleting = Arc::new(AtomicBool::new(false)); let mut worker = Worker { thread: None, @@ -86,7 +86,7 @@ impl Worker { channel: IoChannel, wait: Arc, wait_mutex: Arc>, deleting: Arc) - where Message: Send + Sync + Clone + 'static { + where Message: Send + Sync + 'static { loop { { let lock = wait_mutex.lock().expect("Poisoned work_loop mutex"); @@ -105,7 +105,7 @@ impl Worker { } } - fn do_work(work: Work, channel: IoChannel) where Message: Send + Sync + Clone + 'static { + fn do_work(work: Work, channel: IoChannel) where Message: Send + Sync + 'static { match work.work_type { WorkType::Readable => { work.handler.stream_readable(&IoContext::new(channel, work.handler_id), work.token); @@ -120,7 +120,7 @@ impl Worker { work.handler.timeout(&IoContext::new(channel, work.handler_id), work.token); } WorkType::Message(message) => { - work.handler.message(&IoContext::new(channel, work.handler_id), &message); + work.handler.message(&IoContext::new(channel, work.handler_id), &*message); } } } From f20f9f376ef6a713400e2ba18353268bd35129fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 9 May 2018 08:54:37 +0200 Subject: [PATCH 44/95] Make trace-time publishable. (#8568) --- transaction-pool/Cargo.toml | 2 +- util/trace-time/Cargo.toml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/transaction-pool/Cargo.toml b/transaction-pool/Cargo.toml index 342c376f63c..8965c8cee01 100644 --- a/transaction-pool/Cargo.toml +++ b/transaction-pool/Cargo.toml @@ -9,7 +9,7 @@ authors = ["Parity Technologies "] error-chain = "0.11" log = "0.3" smallvec = "0.4" -trace-time = { path = "../util/trace-time" } +trace-time = { path = "../util/trace-time", version = "0.1" } [dev-dependencies] ethereum-types = "0.3" diff --git a/util/trace-time/Cargo.toml b/util/trace-time/Cargo.toml index 00597ebfc49..288a2c4e47c 100644 --- a/util/trace-time/Cargo.toml +++ b/util/trace-time/Cargo.toml @@ -1,7 +1,9 @@ [package] name = "trace-time" +description = "Easily trace time to execute a scope." version = "0.1.0" authors = ["Parity Technologies "] +license = "GPL-3.0" [dependencies] log = "0.3" From b84682168d46716f455c53ee35166ad7e8e6f7ce Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 9 May 2018 14:55:01 +0800 Subject: [PATCH 45/95] Remove State::replace_backend (#8569) --- ethcore/src/state/mod.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 20d564588c5..5b969bccb93 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -402,19 +402,6 @@ impl State { self.factories.vm.clone() } - /// Swap the current backend for another. - // TODO: [rob] find a less hacky way to avoid duplication of `Client::state_at`. - pub fn replace_backend(self, backend: T) -> State { - State { - db: backend, - root: self.root, - cache: self.cache, - checkpoints: self.checkpoints, - account_start_nonce: self.account_start_nonce, - factories: self.factories, - } - } - /// Create a recoverable checkpoint of this state. pub fn checkpoint(&mut self) { self.checkpoints.get_mut().push(HashMap::new()); From 8b0ba97cf2cec8c79b368e907d975484acaef504 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Wed, 9 May 2018 12:05:34 +0200 Subject: [PATCH 46/95] Refactoring `ethcore-sync` - Fixing warp-sync barrier (#8543) * Start dividing sync chain : first supplier method * WIP - updated chain sync supplier * Finish refactoring the Chain Sync Supplier * Create Chain Sync Requester * Add Propagator for Chain Sync * Add the Chain Sync Handler * Move tests from mod -> handler * Move tests to propagator * Refactor SyncRequester arguments * Refactoring peer fork header handler * Fix wrong highest block number in snapshot sync * Small refactor... * Address PR grumbles * Retry failed CI job * Fix tests * PR Grumbles --- ethcore/sync/src/chain.rs | 3112 -------------------------- ethcore/sync/src/chain/handler.rs | 828 +++++++ ethcore/sync/src/chain/mod.rs | 1379 ++++++++++++ ethcore/sync/src/chain/propagator.rs | 636 ++++++ ethcore/sync/src/chain/requester.rs | 154 ++ ethcore/sync/src/chain/supplier.rs | 446 ++++ ethcore/sync/src/tests/snapshot.rs | 12 +- 7 files changed, 3453 insertions(+), 3114 deletions(-) delete mode 100644 ethcore/sync/src/chain.rs create mode 100644 ethcore/sync/src/chain/handler.rs create mode 100644 ethcore/sync/src/chain/mod.rs create mode 100644 ethcore/sync/src/chain/propagator.rs create mode 100644 ethcore/sync/src/chain/requester.rs create mode 100644 ethcore/sync/src/chain/supplier.rs diff --git a/ethcore/sync/src/chain.rs b/ethcore/sync/src/chain.rs deleted file mode 100644 index 1a6af101159..00000000000 --- a/ethcore/sync/src/chain.rs +++ /dev/null @@ -1,3112 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -/// `BlockChain` synchronization strategy. -/// Syncs to peers and keeps up to date. -/// This implementation uses ethereum protocol v63 -/// -/// Syncing strategy summary. -/// Split the chain into ranges of N blocks each. Download ranges sequentially. Split each range into subchains of M blocks. Download subchains in parallel. -/// State. -/// Sync state consists of the following data: -/// - s: State enum which can be one of the following values: `ChainHead`, `Blocks`, `Idle` -/// - H: A set of downloaded block headers -/// - B: A set of downloaded block bodies -/// - S: Set of block subchain start block hashes to download. -/// - l: Last imported / common block hash -/// - P: A set of connected peers. For each peer we maintain its last known total difficulty and starting block hash being requested if any. -/// General behaviour. -/// We start with all sets empty, l is set to the best block in the block chain, s is set to `ChainHead`. -/// If at any moment a bad block is reported by the block queue, we set s to `ChainHead`, reset l to the best block in the block chain and clear H, B and S. -/// If at any moment P becomes empty, we set s to `ChainHead`, and clear H, B and S. -/// -/// Workflow for `ChainHead` state. -/// In this state we try to get subchain headers with a single `GetBlockHeaders` request. -/// On `NewPeer` / On `Restart`: -/// If peer's total difficulty is higher and there are less than 5 peers downloading, request N/M headers with interval M+1 starting from l -/// On `BlockHeaders(R)`: -/// If R is empty: -/// If l is equal to genesis block hash or l is more than 1000 blocks behind our best hash: -/// Remove current peer from P. set l to the best block in the block chain. Select peer with maximum total difficulty from P and restart. -/// Else -/// Set l to l’s parent and restart. -/// Else if we already have all the headers in the block chain or the block queue: -/// Set s to `Idle`, -/// Else -/// Set S to R, set s to `Blocks`. -/// -/// All other messages are ignored. -/// -/// Workflow for `Blocks` state. -/// In this state we download block headers and bodies from multiple peers. -/// On `NewPeer` / On `Restart`: -/// For all idle peers: -/// Find a set of 256 or less block hashes in H which are not in B and not being downloaded by other peers. If the set is not empty: -/// Request block bodies for the hashes in the set. -/// Else -/// Find an element in S which is not being downloaded by other peers. If found: Request M headers starting from the element. -/// -/// On `BlockHeaders(R)`: -/// If R is empty remove current peer from P and restart. -/// Validate received headers: -/// For each header find a parent in H or R or the blockchain. Restart if there is a block with unknown parent. -/// Find at least one header from the received list in S. Restart if there is none. -/// Go to `CollectBlocks`. -/// -/// On `BlockBodies(R)`: -/// If R is empty remove current peer from P and restart. -/// Add bodies with a matching header in H to B. -/// Go to `CollectBlocks`. -/// -/// `CollectBlocks`: -/// Find a chain of blocks C in H starting from h where h’s parent equals to l. The chain ends with the first block which does not have a body in B. -/// Add all blocks from the chain to the block queue. Remove them from H and B. Set l to the hash of the last block from C. -/// Update and merge subchain heads in S. For each h in S find a chain of blocks in B starting from h. Remove h from S. if the chain does not include an element from S add the end of the chain to S. -/// If H is empty and S contains a single element set s to `ChainHead`. -/// Restart. -/// -/// All other messages are ignored. -/// Workflow for Idle state. -/// On `NewBlock`: -/// Import the block. If the block is unknown set s to `ChainHead` and restart. -/// On `NewHashes`: -/// Set s to `ChainHead` and restart. -/// -/// All other messages are ignored. -/// - -use std::sync::Arc; -use std::collections::{HashSet, HashMap}; -use std::cmp; -use std::time::{Duration, Instant}; -use hash::keccak; -use heapsize::HeapSizeOf; -use ethereum_types::{H256, U256}; -use plain_hasher::H256FastMap; -use parking_lot::RwLock; -use bytes::Bytes; -use rlp::{Rlp, RlpStream, DecoderError, Encodable}; -use network::{self, PeerId, PacketId}; -use ethcore::header::{BlockNumber, Header as BlockHeader}; -use ethcore::client::{BlockChainClient, BlockStatus, BlockId, BlockChainInfo, BlockImportError, BlockImportErrorKind, BlockQueueInfo}; -use ethcore::error::*; -use ethcore::snapshot::{ManifestData, RestorationStatus}; -use transaction::SignedTransaction; -use sync_io::SyncIo; -use super::{WarpSync, SyncConfig}; -use block_sync::{BlockDownloader, BlockRequest, BlockDownloaderImportError as DownloaderImportError, DownloadAction}; -use rand::Rng; -use snapshot::{Snapshot, ChunkType}; -use api::{EthProtocolInfo as PeerInfoDigest, WARP_SYNC_PROTOCOL_ID}; -use private_tx::PrivateTxHandler; -use transactions_stats::{TransactionsStats, Stats as TransactionStats}; -use transaction::UnverifiedTransaction; - -known_heap_size!(0, PeerInfo); - -type PacketDecodeError = DecoderError; - -/// 63 version of Ethereum protocol. -pub const ETH_PROTOCOL_VERSION_63: u8 = 63; -/// 62 version of Ethereum protocol. -pub const ETH_PROTOCOL_VERSION_62: u8 = 62; -/// 1 version of Parity protocol. -pub const PAR_PROTOCOL_VERSION_1: u8 = 1; -/// 2 version of Parity protocol (consensus messages added). -pub const PAR_PROTOCOL_VERSION_2: u8 = 2; -/// 3 version of Parity protocol (private transactions messages added). -pub const PAR_PROTOCOL_VERSION_3: u8 = 3; - -const MAX_BODIES_TO_SEND: usize = 256; -const MAX_HEADERS_TO_SEND: usize = 512; -const MAX_NODE_DATA_TO_SEND: usize = 1024; -const MAX_RECEIPTS_TO_SEND: usize = 1024; -const MAX_RECEIPTS_HEADERS_TO_SEND: usize = 256; -const MIN_PEERS_PROPAGATION: usize = 4; -const MAX_PEERS_PROPAGATION: usize = 128; -const MAX_PEER_LAG_PROPAGATION: BlockNumber = 20; -const MAX_NEW_HASHES: usize = 64; -const MAX_NEW_BLOCK_AGE: BlockNumber = 20; -// maximal packet size with transactions (cannot be greater than 16MB - protocol limitation). -const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024; -// Maximal number of transactions in sent in single packet. -const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64; -// Min number of blocks to be behind for a snapshot sync -const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000; -const SNAPSHOT_MIN_PEERS: usize = 3; - -const STATUS_PACKET: u8 = 0x00; -const NEW_BLOCK_HASHES_PACKET: u8 = 0x01; -const TRANSACTIONS_PACKET: u8 = 0x02; -const GET_BLOCK_HEADERS_PACKET: u8 = 0x03; -const BLOCK_HEADERS_PACKET: u8 = 0x04; -const GET_BLOCK_BODIES_PACKET: u8 = 0x05; -const BLOCK_BODIES_PACKET: u8 = 0x06; -const NEW_BLOCK_PACKET: u8 = 0x07; - -const GET_NODE_DATA_PACKET: u8 = 0x0d; -const NODE_DATA_PACKET: u8 = 0x0e; -const GET_RECEIPTS_PACKET: u8 = 0x0f; -const RECEIPTS_PACKET: u8 = 0x10; - -pub const ETH_PACKET_COUNT: u8 = 0x11; - -const GET_SNAPSHOT_MANIFEST_PACKET: u8 = 0x11; -const SNAPSHOT_MANIFEST_PACKET: u8 = 0x12; -const GET_SNAPSHOT_DATA_PACKET: u8 = 0x13; -const SNAPSHOT_DATA_PACKET: u8 = 0x14; -const CONSENSUS_DATA_PACKET: u8 = 0x15; -const PRIVATE_TRANSACTION_PACKET: u8 = 0x16; -const SIGNED_PRIVATE_TRANSACTION_PACKET: u8 = 0x17; - -pub const SNAPSHOT_SYNC_PACKET_COUNT: u8 = 0x18; - -const MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD: usize = 3; - -const WAIT_PEERS_TIMEOUT: Duration = Duration::from_secs(5); -const STATUS_TIMEOUT: Duration = Duration::from_secs(5); -const HEADERS_TIMEOUT: Duration = Duration::from_secs(15); -const BODIES_TIMEOUT: Duration = Duration::from_secs(20); -const RECEIPTS_TIMEOUT: Duration = Duration::from_secs(10); -const FORK_HEADER_TIMEOUT: Duration = Duration::from_secs(3); -const SNAPSHOT_MANIFEST_TIMEOUT: Duration = Duration::from_secs(5); -const SNAPSHOT_DATA_TIMEOUT: Duration = Duration::from_secs(120); - -#[derive(Copy, Clone, Eq, PartialEq, Debug)] -/// Sync state -pub enum SyncState { - /// Collecting enough peers to start syncing. - WaitingPeers, - /// Waiting for snapshot manifest download - SnapshotManifest, - /// Downloading snapshot data - SnapshotData, - /// Waiting for snapshot restoration progress. - SnapshotWaiting, - /// Downloading new blocks - Blocks, - /// Initial chain sync complete. Waiting for new packets - Idle, - /// Block downloading paused. Waiting for block queue to process blocks and free some space - Waiting, - /// Downloading blocks learned from `NewHashes` packet - NewBlocks, -} - -/// Syncing status and statistics -#[derive(Clone, Copy)] -pub struct SyncStatus { - /// State - pub state: SyncState, - /// Syncing protocol version. That's the maximum protocol version we connect to. - pub protocol_version: u8, - /// The underlying p2p network version. - pub network_id: u64, - /// `BlockChain` height for the moment the sync started. - pub start_block_number: BlockNumber, - /// Last fully downloaded and imported block number (if any). - pub last_imported_block_number: Option, - /// Highest block number in the download queue (if any). - pub highest_block_number: Option, - /// Total number of blocks for the sync process. - pub blocks_total: BlockNumber, - /// Number of blocks downloaded so far. - pub blocks_received: BlockNumber, - /// Total number of connected peers - pub num_peers: usize, - /// Total number of active peers. - pub num_active_peers: usize, - /// Heap memory used in bytes. - pub mem_used: usize, - /// Snapshot chunks - pub num_snapshot_chunks: usize, - /// Snapshot chunks downloaded - pub snapshot_chunks_done: usize, - /// Last fully downloaded and imported ancient block number (if any). - pub last_imported_old_block_number: Option, -} - -impl SyncStatus { - /// Indicates if snapshot download is in progress - pub fn is_snapshot_syncing(&self) -> bool { - self.state == SyncState::SnapshotManifest - || self.state == SyncState::SnapshotData - || self.state == SyncState::SnapshotWaiting - } - - /// Returns max no of peers to display in informants - pub fn current_max_peers(&self, min_peers: u32, max_peers: u32) -> u32 { - if self.num_peers as u32 > min_peers { - max_peers - } else { - min_peers - } - } - - /// Is it doing a major sync? - pub fn is_syncing(&self, queue_info: BlockQueueInfo) -> bool { - let is_syncing_state = match self.state { SyncState::Idle | SyncState::NewBlocks => false, _ => true }; - let is_verifying = queue_info.unverified_queue_size + queue_info.verified_queue_size > 3; - is_verifying || is_syncing_state - } -} - -#[derive(PartialEq, Eq, Debug, Clone)] -/// Peer data type requested -enum PeerAsking { - Nothing, - ForkHeader, - BlockHeaders, - BlockBodies, - BlockReceipts, - SnapshotManifest, - SnapshotData, -} - -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -/// Block downloader channel. -enum BlockSet { - /// New blocks better than out best blocks - NewBlocks, - /// Missing old blocks - OldBlocks, -} -#[derive(Clone, Eq, PartialEq)] -enum ForkConfirmation { - /// Fork block confirmation pending. - Unconfirmed, - /// Peers chain is too short to confirm the fork. - TooShort, - /// Fork is confirmed. - Confirmed, -} - -#[derive(Clone)] -/// Syncing peer information -struct PeerInfo { - /// eth protocol version - protocol_version: u8, - /// Peer chain genesis hash - genesis: H256, - /// Peer network id - network_id: u64, - /// Peer best block hash - latest_hash: H256, - /// Peer total difficulty if known - difficulty: Option, - /// Type of data currenty being requested from peer. - asking: PeerAsking, - /// A set of block numbers being requested - asking_blocks: Vec, - /// Holds requested header hash if currently requesting block header by hash - asking_hash: Option, - /// Holds requested snapshot chunk hash if any. - asking_snapshot_data: Option, - /// Request timestamp - ask_time: Instant, - /// Holds a set of transactions recently sent to this peer to avoid spamming. - last_sent_transactions: HashSet, - /// Pending request is expired and result should be ignored - expired: bool, - /// Peer fork confirmation status - confirmation: ForkConfirmation, - /// Best snapshot hash - snapshot_hash: Option, - /// Best snapshot block number - snapshot_number: Option, - /// Block set requested - block_set: Option, -} - -impl PeerInfo { - fn can_sync(&self) -> bool { - self.confirmation == ForkConfirmation::Confirmed && !self.expired - } - - fn is_allowed(&self) -> bool { - self.confirmation != ForkConfirmation::Unconfirmed && !self.expired - } - - fn reset_asking(&mut self) { - self.asking_blocks.clear(); - self.asking_hash = None; - // mark any pending requests as expired - if self.asking != PeerAsking::Nothing && self.is_allowed() { - self.expired = true; - } - } -} - -#[cfg(not(test))] -mod random { - use rand; - pub fn new() -> rand::ThreadRng { rand::thread_rng() } -} -#[cfg(test)] -mod random { - use rand::{self, SeedableRng}; - pub fn new() -> rand::XorShiftRng { rand::XorShiftRng::from_seed([0, 1, 2, 3]) } -} - -/// Blockchain sync handler. -/// See module documentation for more details. -pub struct ChainSync { - /// Sync state - state: SyncState, - /// Last block number for the start of sync - starting_block: BlockNumber, - /// Highest block number seen - highest_block: Option, - /// All connected peers - peers: HashMap, - /// Peers active for current sync round - active_peers: HashSet, - /// Block download process for new blocks - new_blocks: BlockDownloader, - /// Block download process for ancient blocks - old_blocks: Option, - /// Last propagated block number - last_sent_block_number: BlockNumber, - /// Network ID - network_id: u64, - /// Optional fork block to check - fork_block: Option<(BlockNumber, H256)>, - /// Snapshot downloader. - snapshot: Snapshot, - /// Connected peers pending Status message. - /// Value is request timestamp. - handshaking_peers: HashMap, - /// Sync start timestamp. Measured when first peer is connected - sync_start_time: Option, - /// Transactions propagation statistics - transactions_stats: TransactionsStats, - /// Enable ancient block downloading - download_old_blocks: bool, - /// Shared private tx service. - private_tx_handler: Arc, - /// Enable warp sync. - warp_sync: WarpSync, -} - -type RlpResponseResult = Result, PacketDecodeError>; - -impl ChainSync { - /// Create a new instance of syncing strategy. - pub fn new(config: SyncConfig, chain: &BlockChainClient, private_tx_handler: Arc) -> ChainSync { - let chain_info = chain.chain_info(); - let best_block = chain.chain_info().best_block_number; - let state = match config.warp_sync { - WarpSync::Enabled => SyncState::WaitingPeers, - WarpSync::OnlyAndAfter(block) if block > best_block => SyncState::WaitingPeers, - _ => SyncState::Idle, - }; - - let mut sync = ChainSync { - state, - starting_block: best_block, - highest_block: None, - peers: HashMap::new(), - handshaking_peers: HashMap::new(), - active_peers: HashSet::new(), - new_blocks: BlockDownloader::new(false, &chain_info.best_block_hash, chain_info.best_block_number), - old_blocks: None, - last_sent_block_number: 0, - network_id: config.network_id, - fork_block: config.fork_block, - download_old_blocks: config.download_old_blocks, - snapshot: Snapshot::new(), - sync_start_time: None, - transactions_stats: TransactionsStats::default(), - private_tx_handler, - warp_sync: config.warp_sync, - }; - sync.update_targets(chain); - sync - } - - /// Returns synchonization status - pub fn status(&self) -> SyncStatus { - let last_imported_number = self.new_blocks.last_imported_block_number(); - SyncStatus { - state: self.state.clone(), - protocol_version: ETH_PROTOCOL_VERSION_63, - network_id: self.network_id, - start_block_number: self.starting_block, - last_imported_block_number: Some(last_imported_number), - last_imported_old_block_number: self.old_blocks.as_ref().map(|d| d.last_imported_block_number()), - highest_block_number: self.highest_block.map(|n| cmp::max(n, last_imported_number)), - blocks_received: if last_imported_number > self.starting_block { last_imported_number - self.starting_block } else { 0 }, - blocks_total: match self.highest_block { Some(x) if x > self.starting_block => x - self.starting_block, _ => 0 }, - num_peers: self.peers.values().filter(|p| p.is_allowed()).count(), - num_active_peers: self.peers.values().filter(|p| p.is_allowed() && p.asking != PeerAsking::Nothing).count(), - num_snapshot_chunks: self.snapshot.total_chunks(), - snapshot_chunks_done: self.snapshot.done_chunks(), - mem_used: - self.new_blocks.heap_size() - + self.old_blocks.as_ref().map_or(0, |d| d.heap_size()) - + self.peers.heap_size_of_children(), - } - } - - /// Returns information on peers connections - pub fn peer_info(&self, peer_id: &PeerId) -> Option { - self.peers.get(peer_id).map(|peer_data| { - PeerInfoDigest { - version: peer_data.protocol_version as u32, - difficulty: peer_data.difficulty, - head: peer_data.latest_hash, - } - }) - } - - /// Returns transactions propagation statistics - pub fn transactions_stats(&self) -> &H256FastMap { - self.transactions_stats.stats() - } - - /// Updates transactions were received by a peer - pub fn transactions_received(&mut self, txs: &[UnverifiedTransaction], peer_id: PeerId) { - if let Some(peer_info) = self.peers.get_mut(&peer_id) { - peer_info.last_sent_transactions.extend(txs.iter().map(|tx| tx.hash())); - } - } - - /// Abort all sync activity - pub fn abort(&mut self, io: &mut SyncIo) { - self.reset_and_continue(io); - self.peers.clear(); - } - - /// Reset sync. Clear all downloaded data but keep the queue - fn reset(&mut self, io: &mut SyncIo) { - self.new_blocks.reset(); - let chain_info = io.chain().chain_info(); - for (_, ref mut p) in &mut self.peers { - if p.block_set != Some(BlockSet::OldBlocks) { - p.reset_asking(); - if p.difficulty.is_none() { - // assume peer has up to date difficulty - p.difficulty = Some(chain_info.pending_total_difficulty); - } - } - } - self.state = SyncState::Idle; - // Reactivate peers only if some progress has been made - // since the last sync round of if starting fresh. - self.active_peers = self.peers.keys().cloned().collect(); - } - - /// Restart sync - pub fn reset_and_continue(&mut self, io: &mut SyncIo) { - trace!(target: "sync", "Restarting"); - if self.state == SyncState::SnapshotData { - debug!(target:"sync", "Aborting snapshot restore"); - io.snapshot_service().abort_restore(); - } - self.snapshot.clear(); - self.reset(io); - self.continue_sync(io); - } - - /// Remove peer from active peer set. Peer will be reactivated on the next sync - /// round. - fn deactivate_peer(&mut self, _io: &mut SyncIo, peer_id: PeerId) { - trace!(target: "sync", "Deactivating peer {}", peer_id); - self.active_peers.remove(&peer_id); - } - - fn maybe_start_snapshot_sync(&mut self, io: &mut SyncIo) { - if !self.warp_sync.is_enabled() || io.snapshot_service().supported_versions().is_none() { - trace!(target: "sync", "Skipping warp sync. Disabled or not supported."); - return; - } - if self.state != SyncState::WaitingPeers && self.state != SyncState::Blocks && self.state != SyncState::Waiting { - trace!(target: "sync", "Skipping warp sync. State: {:?}", self.state); - return; - } - // Make sure the snapshot block is not too far away from best block and network best block and - // that it is higher than fork detection block - let our_best_block = io.chain().chain_info().best_block_number; - let fork_block = self.fork_block.as_ref().map(|&(n, _)| n).unwrap_or(0); - - let (best_hash, max_peers, snapshot_peers) = { - let expected_warp_block = match self.warp_sync { - WarpSync::OnlyAndAfter(block) => block, - _ => 0, - }; - //collect snapshot infos from peers - let snapshots = self.peers.iter() - .filter(|&(_, p)| p.is_allowed() && p.snapshot_number.map_or(false, |sn| - our_best_block < sn && (sn - our_best_block) > SNAPSHOT_RESTORE_THRESHOLD && - sn > fork_block && - sn > expected_warp_block && - self.highest_block.map_or(true, |highest| highest >= sn && (highest - sn) <= SNAPSHOT_RESTORE_THRESHOLD) - )) - .filter_map(|(p, peer)| peer.snapshot_hash.map(|hash| (p, hash.clone()))) - .filter(|&(_, ref hash)| !self.snapshot.is_known_bad(hash)); - - let mut snapshot_peers = HashMap::new(); - let mut max_peers: usize = 0; - let mut best_hash = None; - for (p, hash) in snapshots { - let peers = snapshot_peers.entry(hash).or_insert_with(Vec::new); - peers.push(*p); - if peers.len() > max_peers { - max_peers = peers.len(); - best_hash = Some(hash); - } - } - (best_hash, max_peers, snapshot_peers) - }; - - let timeout = (self.state == SyncState::WaitingPeers) && self.sync_start_time.map_or(false, |t| t.elapsed() > WAIT_PEERS_TIMEOUT); - - if let (Some(hash), Some(peers)) = (best_hash, best_hash.map_or(None, |h| snapshot_peers.get(&h))) { - if max_peers >= SNAPSHOT_MIN_PEERS { - trace!(target: "sync", "Starting confirmed snapshot sync {:?} with {:?}", hash, peers); - self.start_snapshot_sync(io, peers); - } else if timeout { - trace!(target: "sync", "Starting unconfirmed snapshot sync {:?} with {:?}", hash, peers); - self.start_snapshot_sync(io, peers); - } - } else if timeout && !self.warp_sync.is_warp_only() { - trace!(target: "sync", "No snapshots found, starting full sync"); - self.state = SyncState::Idle; - self.continue_sync(io); - } - } - - fn start_snapshot_sync(&mut self, io: &mut SyncIo, peers: &[PeerId]) { - if !self.snapshot.have_manifest() { - for p in peers { - if self.peers.get(p).map_or(false, |p| p.asking == PeerAsking::Nothing) { - self.request_snapshot_manifest(io, *p); - } - } - self.state = SyncState::SnapshotManifest; - trace!(target: "sync", "New snapshot sync with {:?}", peers); - } else { - self.state = SyncState::SnapshotData; - trace!(target: "sync", "Resumed snapshot sync with {:?}", peers); - } - } - - /// Restart sync disregarding the block queue status. May end up re-downloading up to QUEUE_SIZE blocks - pub fn restart(&mut self, io: &mut SyncIo) { - self.update_targets(io.chain()); - self.reset_and_continue(io); - } - - /// Update sync after the blockchain has been changed externally. - pub fn update_targets(&mut self, chain: &BlockChainClient) { - // Do not assume that the block queue/chain still has our last_imported_block - let chain = chain.chain_info(); - self.new_blocks = BlockDownloader::new(false, &chain.best_block_hash, chain.best_block_number); - self.old_blocks = None; - if self.download_old_blocks { - if let (Some(ancient_block_hash), Some(ancient_block_number)) = (chain.ancient_block_hash, chain.ancient_block_number) { - - trace!(target: "sync", "Downloading old blocks from {:?} (#{}) till {:?} (#{:?})", ancient_block_hash, ancient_block_number, chain.first_block_hash, chain.first_block_number); - let mut downloader = BlockDownloader::with_unlimited_reorg(true, &ancient_block_hash, ancient_block_number); - if let Some(hash) = chain.first_block_hash { - trace!(target: "sync", "Downloader target set to {:?}", hash); - downloader.set_target(&hash); - } - self.old_blocks = Some(downloader); - } - } - } - - /// Called by peer to report status - fn on_peer_status(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - self.handshaking_peers.remove(&peer_id); - let protocol_version: u8 = r.val_at(0)?; - let warp_protocol = io.protocol_version(&WARP_SYNC_PROTOCOL_ID, peer_id) != 0; - let peer = PeerInfo { - protocol_version: protocol_version, - network_id: r.val_at(1)?, - difficulty: Some(r.val_at(2)?), - latest_hash: r.val_at(3)?, - genesis: r.val_at(4)?, - asking: PeerAsking::Nothing, - asking_blocks: Vec::new(), - asking_hash: None, - ask_time: Instant::now(), - last_sent_transactions: HashSet::new(), - expired: false, - confirmation: if self.fork_block.is_none() { ForkConfirmation::Confirmed } else { ForkConfirmation::Unconfirmed }, - asking_snapshot_data: None, - snapshot_hash: if warp_protocol { Some(r.val_at(5)?) } else { None }, - snapshot_number: if warp_protocol { Some(r.val_at(6)?) } else { None }, - block_set: None, - }; - - trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{}, snapshot:{:?})", - peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest_hash, peer.genesis, peer.snapshot_number); - if io.is_expired() { - trace!(target: "sync", "Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id)); - return Ok(()); - } - - if self.peers.contains_key(&peer_id) { - debug!(target: "sync", "Unexpected status packet from {}:{}", peer_id, io.peer_info(peer_id)); - return Ok(()); - } - let chain_info = io.chain().chain_info(); - if peer.genesis != chain_info.genesis_hash { - io.disable_peer(peer_id); - trace!(target: "sync", "Peer {} genesis hash mismatch (ours: {}, theirs: {})", peer_id, chain_info.genesis_hash, peer.genesis); - return Ok(()); - } - if peer.network_id != self.network_id { - io.disable_peer(peer_id); - trace!(target: "sync", "Peer {} network id mismatch (ours: {}, theirs: {})", peer_id, self.network_id, peer.network_id); - return Ok(()); - } - if (warp_protocol && peer.protocol_version != PAR_PROTOCOL_VERSION_1 && peer.protocol_version != PAR_PROTOCOL_VERSION_2 && peer.protocol_version != PAR_PROTOCOL_VERSION_3) - || (!warp_protocol && peer.protocol_version != ETH_PROTOCOL_VERSION_63 && peer.protocol_version != ETH_PROTOCOL_VERSION_62) { - io.disable_peer(peer_id); - trace!(target: "sync", "Peer {} unsupported eth protocol ({})", peer_id, peer.protocol_version); - return Ok(()); - } - - if self.sync_start_time.is_none() { - self.sync_start_time = Some(Instant::now()); - } - - self.peers.insert(peer_id.clone(), peer); - // Don't activate peer immediatelly when searching for common block. - // Let the current sync round complete first. - self.active_peers.insert(peer_id.clone()); - debug!(target: "sync", "Connected {}:{}", peer_id, io.peer_info(peer_id)); - if let Some((fork_block, _)) = self.fork_block { - self.request_fork_header_by_number(io, peer_id, fork_block); - } else { - self.sync_peer(io, peer_id, false); - } - Ok(()) - } - - /// Called by peer once it has new block headers during sync - fn on_peer_block_headers(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - let confirmed = match self.peers.get_mut(&peer_id) { - Some(ref mut peer) if peer.asking == PeerAsking::ForkHeader => { - peer.asking = PeerAsking::Nothing; - let item_count = r.item_count()?; - let (fork_number, fork_hash) = self.fork_block.expect("ForkHeader request is sent only fork block is Some; qed").clone(); - if item_count == 0 || item_count != 1 { - trace!(target: "sync", "{}: Chain is too short to confirm the block", peer_id); - peer.confirmation = ForkConfirmation::TooShort; - } else { - let header = r.at(0)?.as_raw(); - if keccak(&header) == fork_hash { - trace!(target: "sync", "{}: Confirmed peer", peer_id); - peer.confirmation = ForkConfirmation::Confirmed; - if !io.chain_overlay().read().contains_key(&fork_number) { - io.chain_overlay().write().insert(fork_number, header.to_vec()); - } - } else { - trace!(target: "sync", "{}: Fork mismatch", peer_id); - io.disable_peer(peer_id); - return Ok(()); - } - } - true - }, - _ => false, - }; - if confirmed { - self.sync_peer(io, peer_id, false); - return Ok(()); - } - - self.clear_peer_download(peer_id); - let expected_hash = self.peers.get(&peer_id).and_then(|p| p.asking_hash); - let allowed = self.peers.get(&peer_id).map(|p| p.is_allowed()).unwrap_or(false); - let block_set = self.peers.get(&peer_id).and_then(|p| p.block_set).unwrap_or(BlockSet::NewBlocks); - if !self.reset_peer_asking(peer_id, PeerAsking::BlockHeaders) || expected_hash.is_none() || !allowed { - trace!(target: "sync", "{}: Ignored unexpected headers, expected_hash = {:?}", peer_id, expected_hash); - self.continue_sync(io); - return Ok(()); - } - let item_count = r.item_count()?; - trace!(target: "sync", "{} -> BlockHeaders ({} entries), state = {:?}, set = {:?}", peer_id, item_count, self.state, block_set); - if (self.state == SyncState::Idle || self.state == SyncState::WaitingPeers) && self.old_blocks.is_none() { - trace!(target: "sync", "Ignored unexpected block headers"); - self.continue_sync(io); - return Ok(()); - } - if self.state == SyncState::Waiting { - trace!(target: "sync", "Ignored block headers while waiting"); - self.continue_sync(io); - return Ok(()); - } - - let result = { - let downloader = match block_set { - BlockSet::NewBlocks => &mut self.new_blocks, - BlockSet::OldBlocks => { - match self.old_blocks { - None => { - trace!(target: "sync", "Ignored block headers while block download is inactive"); - self.continue_sync(io); - return Ok(()); - }, - Some(ref mut blocks) => blocks, - } - } - }; - downloader.import_headers(io, r, expected_hash) - }; - - match result { - Err(DownloaderImportError::Useless) => { - self.deactivate_peer(io, peer_id); - }, - Err(DownloaderImportError::Invalid) => { - io.disable_peer(peer_id); - self.deactivate_peer(io, peer_id); - self.continue_sync(io); - return Ok(()); - }, - Ok(DownloadAction::Reset) => { - // mark all outstanding requests as expired - trace!("Resetting downloads for {:?}", block_set); - for (_, ref mut p) in self.peers.iter_mut().filter(|&(_, ref p)| p.block_set == Some(block_set)) { - p.reset_asking(); - } - - } - Ok(DownloadAction::None) => {}, - } - - self.collect_blocks(io, block_set); - // give a task to the same peer first if received valuable headers. - self.sync_peer(io, peer_id, false); - // give tasks to other peers - self.continue_sync(io); - Ok(()) - } - - /// Called by peer once it has new block bodies - fn on_peer_block_bodies(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - self.clear_peer_download(peer_id); - let block_set = self.peers.get(&peer_id).and_then(|p| p.block_set).unwrap_or(BlockSet::NewBlocks); - if !self.reset_peer_asking(peer_id, PeerAsking::BlockBodies) { - trace!(target: "sync", "{}: Ignored unexpected bodies", peer_id); - self.continue_sync(io); - return Ok(()); - } - let item_count = r.item_count()?; - trace!(target: "sync", "{} -> BlockBodies ({} entries), set = {:?}", peer_id, item_count, block_set); - if item_count == 0 { - self.deactivate_peer(io, peer_id); - } - else if self.state == SyncState::Waiting { - trace!(target: "sync", "Ignored block bodies while waiting"); - } - else - { - let result = { - let downloader = match block_set { - BlockSet::NewBlocks => &mut self.new_blocks, - BlockSet::OldBlocks => match self.old_blocks { - None => { - trace!(target: "sync", "Ignored block headers while block download is inactive"); - self.continue_sync(io); - return Ok(()); - }, - Some(ref mut blocks) => blocks, - } - }; - downloader.import_bodies(io, r) - }; - - match result { - Err(DownloaderImportError::Invalid) => { - io.disable_peer(peer_id); - self.deactivate_peer(io, peer_id); - self.continue_sync(io); - return Ok(()); - }, - Err(DownloaderImportError::Useless) => { - self.deactivate_peer(io, peer_id); - }, - Ok(()) => (), - } - - self.collect_blocks(io, block_set); - self.sync_peer(io, peer_id, false); - } - self.continue_sync(io); - Ok(()) - } - - /// Called by peer once it has new block receipts - fn on_peer_block_receipts(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - self.clear_peer_download(peer_id); - let block_set = self.peers.get(&peer_id).and_then(|p| p.block_set).unwrap_or(BlockSet::NewBlocks); - if !self.reset_peer_asking(peer_id, PeerAsking::BlockReceipts) { - trace!(target: "sync", "{}: Ignored unexpected receipts", peer_id); - self.continue_sync(io); - return Ok(()); - } - let item_count = r.item_count()?; - trace!(target: "sync", "{} -> BlockReceipts ({} entries)", peer_id, item_count); - if item_count == 0 { - self.deactivate_peer(io, peer_id); - } - else if self.state == SyncState::Waiting { - trace!(target: "sync", "Ignored block receipts while waiting"); - } - else - { - let result = { - let downloader = match block_set { - BlockSet::NewBlocks => &mut self.new_blocks, - BlockSet::OldBlocks => match self.old_blocks { - None => { - trace!(target: "sync", "Ignored block headers while block download is inactive"); - self.continue_sync(io); - return Ok(()); - }, - Some(ref mut blocks) => blocks, - } - }; - downloader.import_receipts(io, r) - }; - - match result { - Err(DownloaderImportError::Invalid) => { - io.disable_peer(peer_id); - self.deactivate_peer(io, peer_id); - self.continue_sync(io); - return Ok(()); - }, - Err(DownloaderImportError::Useless) => { - self.deactivate_peer(io, peer_id); - }, - Ok(()) => (), - } - - self.collect_blocks(io, block_set); - self.sync_peer(io, peer_id, false); - } - self.continue_sync(io); - Ok(()) - } - - /// Called by peer once it has new block bodies - fn on_peer_new_block(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - if !self.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { - trace!(target: "sync", "Ignoring new block from unconfirmed peer {}", peer_id); - return Ok(()); - } - let difficulty: U256 = r.val_at(1)?; - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - if peer.difficulty.map_or(true, |pd| difficulty > pd) { - peer.difficulty = Some(difficulty); - } - } - let block_rlp = r.at(0)?; - let header_rlp = block_rlp.at(0)?; - let h = keccak(&header_rlp.as_raw()); - trace!(target: "sync", "{} -> NewBlock ({})", peer_id, h); - let header: BlockHeader = header_rlp.as_val()?; - if header.number() > self.highest_block.unwrap_or(0) { - self.highest_block = Some(header.number()); - } - let mut unknown = false; - { - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - peer.latest_hash = header.hash(); - } - } - let last_imported_number = self.new_blocks.last_imported_block_number(); - if last_imported_number > header.number() && last_imported_number - header.number() > MAX_NEW_BLOCK_AGE { - trace!(target: "sync", "Ignored ancient new block {:?}", h); - io.disable_peer(peer_id); - return Ok(()); - } - match io.chain().import_block(block_rlp.as_raw().to_vec()) { - Err(BlockImportError(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain), _)) => { - trace!(target: "sync", "New block already in chain {:?}", h); - }, - Err(BlockImportError(BlockImportErrorKind::Import(ImportErrorKind::AlreadyQueued), _)) => { - trace!(target: "sync", "New block already queued {:?}", h); - }, - Ok(_) => { - // abort current download of the same block - self.complete_sync(io); - self.new_blocks.mark_as_known(&header.hash(), header.number()); - trace!(target: "sync", "New block queued {:?} ({})", h, header.number()); - }, - Err(BlockImportError(BlockImportErrorKind::Block(BlockError::UnknownParent(p)), _)) => { - unknown = true; - trace!(target: "sync", "New block with unknown parent ({:?}) {:?}", p, h); - }, - Err(e) => { - debug!(target: "sync", "Bad new block {:?} : {:?}", h, e); - io.disable_peer(peer_id); - } - }; - if unknown { - if self.state != SyncState::Idle { - trace!(target: "sync", "NewBlock ignored while seeking"); - } else { - trace!(target: "sync", "New unknown block {:?}", h); - //TODO: handle too many unknown blocks - self.sync_peer(io, peer_id, true); - } - } - self.continue_sync(io); - Ok(()) - } - - /// Handles `NewHashes` packet. Initiates headers download for any unknown hashes. - fn on_peer_new_hashes(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - if !self.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { - trace!(target: "sync", "Ignoring new hashes from unconfirmed peer {}", peer_id); - return Ok(()); - } - let hashes: Vec<_> = r.iter().take(MAX_NEW_HASHES).map(|item| (item.val_at::(0), item.val_at::(1))).collect(); - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - // Peer has new blocks with unknown difficulty - peer.difficulty = None; - if let Some(&(Ok(ref h), _)) = hashes.last() { - peer.latest_hash = h.clone(); - } - } - if self.state != SyncState::Idle { - trace!(target: "sync", "Ignoring new hashes since we're already downloading."); - let max = r.iter().take(MAX_NEW_HASHES).map(|item| item.val_at::(1).unwrap_or(0)).fold(0u64, cmp::max); - if max > self.highest_block.unwrap_or(0) { - self.highest_block = Some(max); - } - self.continue_sync(io); - return Ok(()); - } - trace!(target: "sync", "{} -> NewHashes ({} entries)", peer_id, r.item_count()?); - let mut max_height: BlockNumber = 0; - let mut new_hashes = Vec::new(); - let last_imported_number = self.new_blocks.last_imported_block_number(); - for (rh, rn) in hashes { - let hash = rh?; - let number = rn?; - if number > self.highest_block.unwrap_or(0) { - self.highest_block = Some(number); - } - if self.new_blocks.is_downloading(&hash) { - continue; - } - if last_imported_number > number && last_imported_number - number > MAX_NEW_BLOCK_AGE { - trace!(target: "sync", "Ignored ancient new block hash {:?}", hash); - io.disable_peer(peer_id); - continue; - } - match io.chain().block_status(BlockId::Hash(hash.clone())) { - BlockStatus::InChain => { - trace!(target: "sync", "New block hash already in chain {:?}", hash); - }, - BlockStatus::Queued => { - trace!(target: "sync", "New hash block already queued {:?}", hash); - }, - BlockStatus::Unknown | BlockStatus::Pending => { - new_hashes.push(hash.clone()); - if number > max_height { - trace!(target: "sync", "New unknown block hash {:?}", hash); - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - peer.latest_hash = hash.clone(); - } - max_height = number; - } - }, - BlockStatus::Bad => { - debug!(target: "sync", "Bad new block hash {:?}", hash); - io.disable_peer(peer_id); - return Ok(()); - } - } - }; - if max_height != 0 { - trace!(target: "sync", "Downloading blocks for new hashes"); - self.new_blocks.reset_to(new_hashes); - self.state = SyncState::NewBlocks; - self.sync_peer(io, peer_id, true); - } - self.continue_sync(io); - Ok(()) - } - - /// Called when snapshot manifest is downloaded from a peer. - fn on_snapshot_manifest(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - if !self.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { - trace!(target: "sync", "Ignoring snapshot manifest from unconfirmed peer {}", peer_id); - return Ok(()); - } - self.clear_peer_download(peer_id); - if !self.reset_peer_asking(peer_id, PeerAsking::SnapshotManifest) || self.state != SyncState::SnapshotManifest { - trace!(target: "sync", "{}: Ignored unexpected/expired manifest", peer_id); - self.continue_sync(io); - return Ok(()); - } - - let manifest_rlp = r.at(0)?; - let manifest = match ManifestData::from_rlp(manifest_rlp.as_raw()) { - Err(e) => { - trace!(target: "sync", "{}: Ignored bad manifest: {:?}", peer_id, e); - io.disable_peer(peer_id); - self.continue_sync(io); - return Ok(()); - } - Ok(manifest) => manifest, - }; - - let is_supported_version = io.snapshot_service().supported_versions() - .map_or(false, |(l, h)| manifest.version >= l && manifest.version <= h); - - if !is_supported_version { - trace!(target: "sync", "{}: Snapshot manifest version not supported: {}", peer_id, manifest.version); - io.disable_peer(peer_id); - self.continue_sync(io); - return Ok(()); - } - self.snapshot.reset_to(&manifest, &keccak(manifest_rlp.as_raw())); - io.snapshot_service().begin_restore(manifest); - self.state = SyncState::SnapshotData; - - // give a task to the same peer first. - self.sync_peer(io, peer_id, false); - // give tasks to other peers - self.continue_sync(io); - Ok(()) - } - - /// Called when snapshot data is downloaded from a peer. - fn on_snapshot_data(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - if !self.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { - trace!(target: "sync", "Ignoring snapshot data from unconfirmed peer {}", peer_id); - return Ok(()); - } - self.clear_peer_download(peer_id); - if !self.reset_peer_asking(peer_id, PeerAsking::SnapshotData) || (self.state != SyncState::SnapshotData && self.state != SyncState::SnapshotWaiting) { - trace!(target: "sync", "{}: Ignored unexpected snapshot data", peer_id); - self.continue_sync(io); - return Ok(()); - } - - // check service status - let status = io.snapshot_service().status(); - match status { - RestorationStatus::Inactive | RestorationStatus::Failed => { - trace!(target: "sync", "{}: Snapshot restoration aborted", peer_id); - self.state = SyncState::WaitingPeers; - - // only note bad if restoration failed. - if let (Some(hash), RestorationStatus::Failed) = (self.snapshot.snapshot_hash(), status) { - trace!(target: "sync", "Noting snapshot hash {} as bad", hash); - self.snapshot.note_bad(hash); - } - - self.snapshot.clear(); - self.continue_sync(io); - return Ok(()); - }, - RestorationStatus::Ongoing { .. } => { - trace!(target: "sync", "{}: Snapshot restoration is ongoing", peer_id); - }, - } - - let snapshot_data: Bytes = r.val_at(0)?; - match self.snapshot.validate_chunk(&snapshot_data) { - Ok(ChunkType::Block(hash)) => { - trace!(target: "sync", "{}: Processing block chunk", peer_id); - io.snapshot_service().restore_block_chunk(hash, snapshot_data); - } - Ok(ChunkType::State(hash)) => { - trace!(target: "sync", "{}: Processing state chunk", peer_id); - io.snapshot_service().restore_state_chunk(hash, snapshot_data); - } - Err(()) => { - trace!(target: "sync", "{}: Got bad snapshot chunk", peer_id); - io.disconnect_peer(peer_id); - self.continue_sync(io); - return Ok(()); - } - } - - if self.snapshot.is_complete() { - // wait for snapshot restoration process to complete - self.state = SyncState::SnapshotWaiting; - } - // give a task to the same peer first. - self.sync_peer(io, peer_id, false); - // give tasks to other peers - self.continue_sync(io); - Ok(()) - } - - /// Called by peer when it is disconnecting - pub fn on_peer_aborting(&mut self, io: &mut SyncIo, peer: PeerId) { - trace!(target: "sync", "== Disconnecting {}: {}", peer, io.peer_info(peer)); - self.handshaking_peers.remove(&peer); - if self.peers.contains_key(&peer) { - debug!(target: "sync", "Disconnected {}", peer); - self.clear_peer_download(peer); - self.peers.remove(&peer); - self.active_peers.remove(&peer); - self.continue_sync(io); - } - } - - /// Called when a new peer is connected - pub fn on_peer_connected(&mut self, io: &mut SyncIo, peer: PeerId) { - trace!(target: "sync", "== Connected {}: {}", peer, io.peer_info(peer)); - if let Err(e) = self.send_status(io, peer) { - debug!(target:"sync", "Error sending status request: {:?}", e); - io.disconnect_peer(peer); - } else { - self.handshaking_peers.insert(peer, Instant::now()); - } - } - - /// Resume downloading - fn continue_sync(&mut self, io: &mut SyncIo) { - let mut peers: Vec<(PeerId, U256, u8)> = self.peers.iter().filter_map(|(k, p)| - if p.can_sync() { Some((*k, p.difficulty.unwrap_or_else(U256::zero), p.protocol_version)) } else { None }).collect(); - random::new().shuffle(&mut peers); //TODO: sort by rating - // prefer peers with higher protocol version - peers.sort_by(|&(_, _, ref v1), &(_, _, ref v2)| v1.cmp(v2)); - trace!(target: "sync", "Syncing with peers: {} active, {} confirmed, {} total", self.active_peers.len(), peers.len(), self.peers.len()); - for (p, _, _) in peers { - if self.active_peers.contains(&p) { - self.sync_peer(io, p, false); - } - } - - if - self.state != SyncState::WaitingPeers && - self.state != SyncState::SnapshotWaiting && - self.state != SyncState::Waiting && - self.state != SyncState::Idle && - !self.peers.values().any(|p| p.asking != PeerAsking::Nothing && p.block_set != Some(BlockSet::OldBlocks) && p.can_sync()) - { - self.complete_sync(io); - } - } - - /// Called after all blocks have been downloaded - fn complete_sync(&mut self, io: &mut SyncIo) { - trace!(target: "sync", "Sync complete"); - self.reset(io); - self.state = SyncState::Idle; - } - - /// Enter waiting state - fn pause_sync(&mut self) { - trace!(target: "sync", "Block queue full, pausing sync"); - self.state = SyncState::Waiting; - } - - /// Find something to do for a peer. Called for a new peer or when a peer is done with its task. - fn sync_peer(&mut self, io: &mut SyncIo, peer_id: PeerId, force: bool) { - if !self.active_peers.contains(&peer_id) { - trace!(target: "sync", "Skipping deactivated peer {}", peer_id); - return; - } - let (peer_latest, peer_difficulty, peer_snapshot_number, peer_snapshot_hash) = { - if let Some(peer) = self.peers.get_mut(&peer_id) { - if peer.asking != PeerAsking::Nothing || !peer.can_sync() { - trace!(target: "sync", "Skipping busy peer {}", peer_id); - return; - } - if self.state == SyncState::Waiting { - trace!(target: "sync", "Waiting for the block queue"); - return; - } - if self.state == SyncState::SnapshotWaiting { - trace!(target: "sync", "Waiting for the snapshot restoration"); - return; - } - (peer.latest_hash.clone(), peer.difficulty.clone(), peer.snapshot_number.as_ref().cloned().unwrap_or(0), peer.snapshot_hash.as_ref().cloned()) - } else { - return; - } - }; - let chain_info = io.chain().chain_info(); - let syncing_difficulty = chain_info.pending_total_difficulty; - let num_active_peers = self.peers.values().filter(|p| p.asking != PeerAsking::Nothing).count(); - - let higher_difficulty = peer_difficulty.map_or(true, |pd| pd > syncing_difficulty); - if force || higher_difficulty || self.old_blocks.is_some() { - match self.state { - SyncState::WaitingPeers => { - trace!( - target: "sync", - "Checking snapshot sync: {} vs {} (peer: {})", - peer_snapshot_number, - chain_info.best_block_number, - peer_id - ); - self.maybe_start_snapshot_sync(io); - }, - SyncState::Idle | SyncState::Blocks | SyncState::NewBlocks => { - if io.chain().queue_info().is_full() { - self.pause_sync(); - return; - } - - let have_latest = io.chain().block_status(BlockId::Hash(peer_latest)) != BlockStatus::Unknown; - trace!(target: "sync", "Considering peer {}, force={}, td={:?}, our td={}, latest={}, have_latest={}, state={:?}", peer_id, force, peer_difficulty, syncing_difficulty, peer_latest, have_latest, self.state); - if !have_latest && (higher_difficulty || force || self.state == SyncState::NewBlocks) { - // check if got new blocks to download - trace!(target: "sync", "Syncing with peer {}, force={}, td={:?}, our td={}, state={:?}", peer_id, force, peer_difficulty, syncing_difficulty, self.state); - if let Some(request) = self.new_blocks.request_blocks(io, num_active_peers) { - self.request_blocks(io, peer_id, request, BlockSet::NewBlocks); - if self.state == SyncState::Idle { - self.state = SyncState::Blocks; - } - return; - } - } - - if let Some(request) = self.old_blocks.as_mut().and_then(|d| d.request_blocks(io, num_active_peers)) { - self.request_blocks(io, peer_id, request, BlockSet::OldBlocks); - return; - } - }, - SyncState::SnapshotData => { - if let RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } = io.snapshot_service().status() { - if self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize > MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { - trace!(target: "sync", "Snapshot queue full, pausing sync"); - self.state = SyncState::SnapshotWaiting; - return; - } - } - if peer_snapshot_hash.is_some() && peer_snapshot_hash == self.snapshot.snapshot_hash() { - self.request_snapshot_data(io, peer_id); - } - }, - SyncState::SnapshotManifest | //already downloading from other peer - SyncState::Waiting | SyncState::SnapshotWaiting => () - } - } else { - trace!(target: "sync", "Skipping peer {}, force={}, td={:?}, our td={}, state={:?}", peer_id, force, peer_difficulty, syncing_difficulty, self.state); - } - } - - /// Perofrm block download request` - fn request_blocks(&mut self, io: &mut SyncIo, peer_id: PeerId, request: BlockRequest, block_set: BlockSet) { - match request { - BlockRequest::Headers { start, count, skip } => { - self.request_headers_by_hash(io, peer_id, &start, count, skip, false, block_set); - }, - BlockRequest::Bodies { hashes } => { - self.request_bodies(io, peer_id, hashes, block_set); - }, - BlockRequest::Receipts { hashes } => { - self.request_receipts(io, peer_id, hashes, block_set); - }, - } - } - - /// Find some headers or blocks to download for a peer. - fn request_snapshot_data(&mut self, io: &mut SyncIo, peer_id: PeerId) { - self.clear_peer_download(peer_id); - // find chunk data to download - if let Some(hash) = self.snapshot.needed_chunk() { - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - peer.asking_snapshot_data = Some(hash.clone()); - } - self.request_snapshot_chunk(io, peer_id, &hash); - } - } - - /// Clear all blocks/headers marked as being downloaded by a peer. - fn clear_peer_download(&mut self, peer_id: PeerId) { - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - match peer.asking { - PeerAsking::BlockHeaders => { - if let Some(ref hash) = peer.asking_hash { - self.new_blocks.clear_header_download(hash); - if let Some(ref mut old) = self.old_blocks { - old.clear_header_download(hash); - } - } - }, - PeerAsking::BlockBodies => { - self.new_blocks.clear_body_download(&peer.asking_blocks); - if let Some(ref mut old) = self.old_blocks { - old.clear_body_download(&peer.asking_blocks); - } - }, - PeerAsking::BlockReceipts => { - self.new_blocks.clear_receipt_download(&peer.asking_blocks); - if let Some(ref mut old) = self.old_blocks { - old.clear_receipt_download(&peer.asking_blocks); - } - }, - PeerAsking::SnapshotData => { - if let Some(hash) = peer.asking_snapshot_data { - self.snapshot.clear_chunk_download(&hash); - } - }, - _ => (), - } - } - } - - /// Checks if there are blocks fully downloaded that can be imported into the blockchain and does the import. - fn collect_blocks(&mut self, io: &mut SyncIo, block_set: BlockSet) { - match block_set { - BlockSet::NewBlocks => { - if self.new_blocks.collect_blocks(io, self.state == SyncState::NewBlocks) == Err(DownloaderImportError::Invalid) { - self.restart(io); - } - }, - BlockSet::OldBlocks => { - if self.old_blocks.as_mut().map_or(false, |downloader| { downloader.collect_blocks(io, false) == Err(DownloaderImportError::Invalid) }) { - self.restart(io); - } else if self.old_blocks.as_ref().map_or(false, |downloader| { downloader.is_complete() }) { - trace!(target: "sync", "Background block download is complete"); - self.old_blocks = None; - } - } - } - } - - /// Request headers from a peer by block hash - fn request_headers_by_hash(&mut self, sync: &mut SyncIo, peer_id: PeerId, h: &H256, count: u64, skip: u64, reverse: bool, set: BlockSet) { - trace!(target: "sync", "{} <- GetBlockHeaders: {} entries starting from {}, set = {:?}", peer_id, count, h, set); - let mut rlp = RlpStream::new_list(4); - rlp.append(h); - rlp.append(&count); - rlp.append(&skip); - rlp.append(&if reverse {1u32} else {0u32}); - self.send_request(sync, peer_id, PeerAsking::BlockHeaders, GET_BLOCK_HEADERS_PACKET, rlp.out()); - let peer = self.peers.get_mut(&peer_id).expect("peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed"); - peer.asking_hash = Some(h.clone()); - peer.block_set = Some(set); - } - - /// Request headers from a peer by block number - fn request_fork_header_by_number(&mut self, sync: &mut SyncIo, peer_id: PeerId, n: BlockNumber) { - trace!(target: "sync", "{} <- GetForkHeader: at {}", peer_id, n); - let mut rlp = RlpStream::new_list(4); - rlp.append(&n); - rlp.append(&1u32); - rlp.append(&0u32); - rlp.append(&0u32); - self.send_request(sync, peer_id, PeerAsking::ForkHeader, GET_BLOCK_HEADERS_PACKET, rlp.out()); - } - - /// Request snapshot manifest from a peer. - fn request_snapshot_manifest(&mut self, sync: &mut SyncIo, peer_id: PeerId) { - trace!(target: "sync", "{} <- GetSnapshotManifest", peer_id); - let rlp = RlpStream::new_list(0); - self.send_request(sync, peer_id, PeerAsking::SnapshotManifest, GET_SNAPSHOT_MANIFEST_PACKET, rlp.out()); - } - - /// Request snapshot chunk from a peer. - fn request_snapshot_chunk(&mut self, sync: &mut SyncIo, peer_id: PeerId, chunk: &H256) { - trace!(target: "sync", "{} <- GetSnapshotData {:?}", peer_id, chunk); - let mut rlp = RlpStream::new_list(1); - rlp.append(chunk); - self.send_request(sync, peer_id, PeerAsking::SnapshotData, GET_SNAPSHOT_DATA_PACKET, rlp.out()); - } - - /// Request block bodies from a peer - fn request_bodies(&mut self, sync: &mut SyncIo, peer_id: PeerId, hashes: Vec, set: BlockSet) { - let mut rlp = RlpStream::new_list(hashes.len()); - trace!(target: "sync", "{} <- GetBlockBodies: {} entries starting from {:?}, set = {:?}", peer_id, hashes.len(), hashes.first(), set); - for h in &hashes { - rlp.append(&h.clone()); - } - self.send_request(sync, peer_id, PeerAsking::BlockBodies, GET_BLOCK_BODIES_PACKET, rlp.out()); - let peer = self.peers.get_mut(&peer_id).expect("peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed"); - peer.asking_blocks = hashes; - peer.block_set = Some(set); - } - - /// Request block receipts from a peer - fn request_receipts(&mut self, sync: &mut SyncIo, peer_id: PeerId, hashes: Vec, set: BlockSet) { - let mut rlp = RlpStream::new_list(hashes.len()); - trace!(target: "sync", "{} <- GetBlockReceipts: {} entries starting from {:?}, set = {:?}", peer_id, hashes.len(), hashes.first(), set); - for h in &hashes { - rlp.append(&h.clone()); - } - self.send_request(sync, peer_id, PeerAsking::BlockReceipts, GET_RECEIPTS_PACKET, rlp.out()); - let peer = self.peers.get_mut(&peer_id).expect("peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed"); - peer.asking_blocks = hashes; - peer.block_set = Some(set); - } - - /// Reset peer status after request is complete. - fn reset_peer_asking(&mut self, peer_id: PeerId, asking: PeerAsking) -> bool { - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - peer.expired = false; - peer.block_set = None; - if peer.asking != asking { - trace!(target:"sync", "Asking {:?} while expected {:?}", peer.asking, asking); - peer.asking = PeerAsking::Nothing; - return false; - } else { - peer.asking = PeerAsking::Nothing; - return true; - } - } - false - } - - /// Generic request sender - fn send_request(&mut self, sync: &mut SyncIo, peer_id: PeerId, asking: PeerAsking, packet_id: PacketId, packet: Bytes) { - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - if peer.asking != PeerAsking::Nothing { - warn!(target:"sync", "Asking {:?} while requesting {:?}", peer.asking, asking); - } - peer.asking = asking; - peer.ask_time = Instant::now(); - let result = if packet_id >= ETH_PACKET_COUNT { - sync.send_protocol(WARP_SYNC_PROTOCOL_ID, peer_id, packet_id, packet) - } else { - sync.send(peer_id, packet_id, packet) - }; - if let Err(e) = result { - debug!(target:"sync", "Error sending request: {:?}", e); - sync.disconnect_peer(peer_id); - } - } - } - - /// Generic packet sender - fn send_packet(&mut self, sync: &mut SyncIo, peer_id: PeerId, packet_id: PacketId, packet: Bytes) { - if let Err(e) = sync.send(peer_id, packet_id, packet) { - debug!(target:"sync", "Error sending packet: {:?}", e); - sync.disconnect_peer(peer_id); - } - } - - /// Called when peer sends us new transactions - fn on_peer_transactions(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - // Accept transactions only when fully synced - if !io.is_chain_queue_empty() || (self.state != SyncState::Idle && self.state != SyncState::NewBlocks) { - trace!(target: "sync", "{} Ignoring transactions while syncing", peer_id); - return Ok(()); - } - if !self.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { - trace!(target: "sync", "{} Ignoring transactions from unconfirmed/unknown peer", peer_id); - return Ok(()); - } - - let item_count = r.item_count()?; - trace!(target: "sync", "{:02} -> Transactions ({} entries)", peer_id, item_count); - let mut transactions = Vec::with_capacity(item_count); - for i in 0 .. item_count { - let rlp = r.at(i)?; - let tx = rlp.as_raw().to_vec(); - transactions.push(tx); - } - io.chain().queue_transactions(transactions, peer_id); - Ok(()) - } - - /// Send Status message - fn send_status(&mut self, io: &mut SyncIo, peer: PeerId) -> Result<(), network::Error> { - let warp_protocol_version = io.protocol_version(&WARP_SYNC_PROTOCOL_ID, peer); - let warp_protocol = warp_protocol_version != 0; - let protocol = if warp_protocol { warp_protocol_version } else { ETH_PROTOCOL_VERSION_63 }; - trace!(target: "sync", "Sending status to {}, protocol version {}", peer, protocol); - let mut packet = RlpStream::new_list(if warp_protocol { 7 } else { 5 }); - let chain = io.chain().chain_info(); - packet.append(&(protocol as u32)); - packet.append(&self.network_id); - packet.append(&chain.total_difficulty); - packet.append(&chain.best_block_hash); - packet.append(&chain.genesis_hash); - if warp_protocol { - let manifest = match self.old_blocks.is_some() { - true => None, - false => io.snapshot_service().manifest(), - }; - let block_number = manifest.as_ref().map_or(0, |m| m.block_number); - let manifest_hash = manifest.map_or(H256::new(), |m| keccak(m.into_rlp())); - packet.append(&manifest_hash); - packet.append(&block_number); - } - io.respond(STATUS_PACKET, packet.out()) - } - - /// Respond to GetBlockHeaders request - fn return_block_headers(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { - // Packet layout: - // [ block: { P , B_32 }, maxHeaders: P, skip: P, reverse: P in { 0 , 1 } ] - let max_headers: usize = r.val_at(1)?; - let skip: usize = r.val_at(2)?; - let reverse: bool = r.val_at(3)?; - let last = io.chain().chain_info().best_block_number; - let number = if r.at(0)?.size() == 32 { - // id is a hash - let hash: H256 = r.val_at(0)?; - trace!(target: "sync", "{} -> GetBlockHeaders (hash: {}, max: {}, skip: {}, reverse:{})", peer_id, hash, max_headers, skip, reverse); - match io.chain().block_header(BlockId::Hash(hash)) { - Some(hdr) => { - let number = hdr.number().into(); - debug_assert_eq!(hdr.hash(), hash); - - if max_headers == 1 || io.chain().block_hash(BlockId::Number(number)) != Some(hash) { - // Non canonical header or single header requested - // TODO: handle single-step reverse hashchains of non-canon hashes - trace!(target:"sync", "Returning single header: {:?}", hash); - let mut rlp = RlpStream::new_list(1); - rlp.append_raw(&hdr.into_inner(), 1); - return Ok(Some((BLOCK_HEADERS_PACKET, rlp))); - } - number - } - None => return Ok(Some((BLOCK_HEADERS_PACKET, RlpStream::new_list(0)))) //no such header, return nothing - } - } else { - trace!(target: "sync", "{} -> GetBlockHeaders (number: {}, max: {}, skip: {}, reverse:{})", peer_id, r.val_at::(0)?, max_headers, skip, reverse); - r.val_at(0)? - }; - - let mut number = if reverse { - cmp::min(last, number) - } else { - cmp::max(0, number) - }; - let max_count = cmp::min(MAX_HEADERS_TO_SEND, max_headers); - let mut count = 0; - let mut data = Bytes::new(); - let inc = (skip + 1) as BlockNumber; - let overlay = io.chain_overlay().read(); - - while number <= last && count < max_count { - if let Some(hdr) = overlay.get(&number) { - trace!(target: "sync", "{}: Returning cached fork header", peer_id); - data.extend_from_slice(hdr); - count += 1; - } else if let Some(hdr) = io.chain().block_header(BlockId::Number(number)) { - data.append(&mut hdr.into_inner()); - count += 1; - } else { - // No required block. - break; - } - if reverse { - if number <= inc || number == 0 { - break; - } - number -= inc; - } - else { - number += inc; - } - } - let mut rlp = RlpStream::new_list(count as usize); - rlp.append_raw(&data, count as usize); - trace!(target: "sync", "{} -> GetBlockHeaders: returned {} entries", peer_id, count); - Ok(Some((BLOCK_HEADERS_PACKET, rlp))) - } - - /// Respond to GetBlockBodies request - fn return_block_bodies(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { - let mut count = r.item_count().unwrap_or(0); - if count == 0 { - debug!(target: "sync", "Empty GetBlockBodies request, ignoring."); - return Ok(None); - } - count = cmp::min(count, MAX_BODIES_TO_SEND); - let mut added = 0usize; - let mut data = Bytes::new(); - for i in 0..count { - if let Some(body) = io.chain().block_body(BlockId::Hash(r.val_at::(i)?)) { - data.append(&mut body.into_inner()); - added += 1; - } - } - let mut rlp = RlpStream::new_list(added); - rlp.append_raw(&data, added); - trace!(target: "sync", "{} -> GetBlockBodies: returned {} entries", peer_id, added); - Ok(Some((BLOCK_BODIES_PACKET, rlp))) - } - - /// Respond to GetNodeData request - fn return_node_data(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { - let mut count = r.item_count().unwrap_or(0); - trace!(target: "sync", "{} -> GetNodeData: {} entries", peer_id, count); - if count == 0 { - debug!(target: "sync", "Empty GetNodeData request, ignoring."); - return Ok(None); - } - count = cmp::min(count, MAX_NODE_DATA_TO_SEND); - let mut added = 0usize; - let mut data = Vec::new(); - for i in 0..count { - if let Some(node) = io.chain().state_data(&r.val_at::(i)?) { - data.push(node); - added += 1; - } - } - trace!(target: "sync", "{} -> GetNodeData: return {} entries", peer_id, added); - let mut rlp = RlpStream::new_list(added); - for d in data { - rlp.append(&d); - } - Ok(Some((NODE_DATA_PACKET, rlp))) - } - - fn return_receipts(io: &SyncIo, rlp: &Rlp, peer_id: PeerId) -> RlpResponseResult { - let mut count = rlp.item_count().unwrap_or(0); - trace!(target: "sync", "{} -> GetReceipts: {} entries", peer_id, count); - if count == 0 { - debug!(target: "sync", "Empty GetReceipts request, ignoring."); - return Ok(None); - } - count = cmp::min(count, MAX_RECEIPTS_HEADERS_TO_SEND); - let mut added_headers = 0usize; - let mut added_receipts = 0usize; - let mut data = Bytes::new(); - for i in 0..count { - if let Some(mut receipts_bytes) = io.chain().block_receipts(&rlp.val_at::(i)?) { - data.append(&mut receipts_bytes); - added_receipts += receipts_bytes.len(); - added_headers += 1; - if added_receipts > MAX_RECEIPTS_TO_SEND { break; } - } - } - let mut rlp_result = RlpStream::new_list(added_headers); - rlp_result.append_raw(&data, added_headers); - Ok(Some((RECEIPTS_PACKET, rlp_result))) - } - - /// Respond to GetSnapshotManifest request - fn return_snapshot_manifest(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { - let count = r.item_count().unwrap_or(0); - trace!(target: "sync", "{} -> GetSnapshotManifest", peer_id); - if count != 0 { - debug!(target: "sync", "Invalid GetSnapshotManifest request, ignoring."); - return Ok(None); - } - let rlp = match io.snapshot_service().manifest() { - Some(manifest) => { - trace!(target: "sync", "{} <- SnapshotManifest", peer_id); - let mut rlp = RlpStream::new_list(1); - rlp.append_raw(&manifest.into_rlp(), 1); - rlp - }, - None => { - trace!(target: "sync", "{}: No manifest to return", peer_id); - RlpStream::new_list(0) - } - }; - Ok(Some((SNAPSHOT_MANIFEST_PACKET, rlp))) - } - - /// Respond to GetSnapshotData request - fn return_snapshot_data(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { - let hash: H256 = r.val_at(0)?; - trace!(target: "sync", "{} -> GetSnapshotData {:?}", peer_id, hash); - let rlp = match io.snapshot_service().chunk(hash) { - Some(data) => { - let mut rlp = RlpStream::new_list(1); - trace!(target: "sync", "{} <- SnapshotData", peer_id); - rlp.append(&data); - rlp - }, - None => { - RlpStream::new_list(0) - } - }; - Ok(Some((SNAPSHOT_DATA_PACKET, rlp))) - } - - fn return_rlp(io: &mut SyncIo, rlp: &Rlp, peer: PeerId, rlp_func: FRlp, error_func: FError) -> Result<(), PacketDecodeError> - where FRlp : Fn(&SyncIo, &Rlp, PeerId) -> RlpResponseResult, - FError : FnOnce(network::Error) -> String - { - let response = rlp_func(io, rlp, peer); - match response { - Err(e) => Err(e), - Ok(Some((packet_id, rlp_stream))) => { - io.respond(packet_id, rlp_stream.out()).unwrap_or_else( - |e| debug!(target: "sync", "{:?}", error_func(e))); - Ok(()) - } - _ => Ok(()) - } - } - - /// Dispatch incoming requests and responses - pub fn dispatch_packet(sync: &RwLock, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { - let rlp = Rlp::new(data); - let result = match packet_id { - GET_BLOCK_BODIES_PACKET => ChainSync::return_rlp(io, &rlp, peer, - ChainSync::return_block_bodies, - |e| format!("Error sending block bodies: {:?}", e)), - - GET_BLOCK_HEADERS_PACKET => ChainSync::return_rlp(io, &rlp, peer, - ChainSync::return_block_headers, - |e| format!("Error sending block headers: {:?}", e)), - - GET_RECEIPTS_PACKET => ChainSync::return_rlp(io, &rlp, peer, - ChainSync::return_receipts, - |e| format!("Error sending receipts: {:?}", e)), - - GET_NODE_DATA_PACKET => ChainSync::return_rlp(io, &rlp, peer, - ChainSync::return_node_data, - |e| format!("Error sending nodes: {:?}", e)), - - GET_SNAPSHOT_MANIFEST_PACKET => ChainSync::return_rlp(io, &rlp, peer, - ChainSync::return_snapshot_manifest, - |e| format!("Error sending snapshot manifest: {:?}", e)), - - GET_SNAPSHOT_DATA_PACKET => ChainSync::return_rlp(io, &rlp, peer, - ChainSync::return_snapshot_data, - |e| format!("Error sending snapshot data: {:?}", e)), - CONSENSUS_DATA_PACKET => ChainSync::on_consensus_packet(io, peer, &rlp), - _ => { - sync.write().on_packet(io, peer, packet_id, data); - Ok(()) - } - }; - result.unwrap_or_else(|e| { - debug!(target:"sync", "{} -> Malformed packet {} : {}", peer, packet_id, e); - }) - } - - pub fn on_packet(&mut self, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { - debug!(target: "sync", "{} -> Dispatching packet: {}", peer, packet_id); - - if packet_id != STATUS_PACKET && !self.peers.contains_key(&peer) { - debug!(target:"sync", "Unexpected packet {} from unregistered peer: {}:{}", packet_id, peer, io.peer_info(peer)); - return; - } - - let rlp = Rlp::new(data); - let result = match packet_id { - STATUS_PACKET => self.on_peer_status(io, peer, &rlp), - TRANSACTIONS_PACKET => self.on_peer_transactions(io, peer, &rlp), - BLOCK_HEADERS_PACKET => self.on_peer_block_headers(io, peer, &rlp), - BLOCK_BODIES_PACKET => self.on_peer_block_bodies(io, peer, &rlp), - RECEIPTS_PACKET => self.on_peer_block_receipts(io, peer, &rlp), - NEW_BLOCK_PACKET => self.on_peer_new_block(io, peer, &rlp), - NEW_BLOCK_HASHES_PACKET => self.on_peer_new_hashes(io, peer, &rlp), - SNAPSHOT_MANIFEST_PACKET => self.on_snapshot_manifest(io, peer, &rlp), - SNAPSHOT_DATA_PACKET => self.on_snapshot_data(io, peer, &rlp), - PRIVATE_TRANSACTION_PACKET => self.on_private_transaction(io, peer, &rlp), - SIGNED_PRIVATE_TRANSACTION_PACKET => self.on_signed_private_transaction(io, peer, &rlp), - _ => { - debug!(target: "sync", "{}: Unknown packet {}", peer, packet_id); - Ok(()) - } - }; - result.unwrap_or_else(|e| { - debug!(target:"sync", "{} -> Malformed packet {} : {}", peer, packet_id, e); - }) - } - - pub fn maintain_peers(&mut self, io: &mut SyncIo) { - let tick = Instant::now(); - let mut aborting = Vec::new(); - for (peer_id, peer) in &self.peers { - let elapsed = tick - peer.ask_time; - let timeout = match peer.asking { - PeerAsking::BlockHeaders => elapsed > HEADERS_TIMEOUT, - PeerAsking::BlockBodies => elapsed > BODIES_TIMEOUT, - PeerAsking::BlockReceipts => elapsed > RECEIPTS_TIMEOUT, - PeerAsking::Nothing => false, - PeerAsking::ForkHeader => elapsed > FORK_HEADER_TIMEOUT, - PeerAsking::SnapshotManifest => elapsed > SNAPSHOT_MANIFEST_TIMEOUT, - PeerAsking::SnapshotData => elapsed > SNAPSHOT_DATA_TIMEOUT, - }; - if timeout { - debug!(target:"sync", "Timeout {}", peer_id); - io.disconnect_peer(*peer_id); - aborting.push(*peer_id); - } - } - for p in aborting { - self.on_peer_aborting(io, p); - } - - // Check for handshake timeouts - for (peer, &ask_time) in &self.handshaking_peers { - let elapsed = (tick - ask_time) / 1_000_000_000; - if elapsed > STATUS_TIMEOUT { - trace!(target:"sync", "Status timeout {}", peer); - io.disconnect_peer(*peer); - } - } - } - - fn check_resume(&mut self, io: &mut SyncIo) { - if self.state == SyncState::Waiting && !io.chain().queue_info().is_full() && self.state == SyncState::Waiting { - self.state = SyncState::Blocks; - self.continue_sync(io); - } else if self.state == SyncState::SnapshotWaiting { - match io.snapshot_service().status() { - RestorationStatus::Inactive => { - trace!(target:"sync", "Snapshot restoration is complete"); - self.restart(io); - self.continue_sync(io); - }, - RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } => { - if !self.snapshot.is_complete() && self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize <= MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { - trace!(target:"sync", "Resuming snapshot sync"); - self.state = SyncState::SnapshotData; - self.continue_sync(io); - } - }, - RestorationStatus::Failed => { - trace!(target: "sync", "Snapshot restoration aborted"); - self.state = SyncState::WaitingPeers; - self.snapshot.clear(); - self.continue_sync(io); - }, - } - } - } - - /// creates rlp to send for the tree defined by 'from' and 'to' hashes - fn create_new_hashes_rlp(chain: &BlockChainClient, from: &H256, to: &H256) -> Option { - match chain.tree_route(from, to) { - Some(route) => { - let uncles = chain.find_uncles(from).unwrap_or_else(Vec::new); - match route.blocks.len() { - 0 => None, - _ => { - let mut blocks = route.blocks; - blocks.extend(uncles); - let mut rlp_stream = RlpStream::new_list(blocks.len()); - for block_hash in blocks { - let mut hash_rlp = RlpStream::new_list(2); - let number = chain.block_header(BlockId::Hash(block_hash.clone())) - .expect("chain.tree_route and chain.find_uncles only return hahses of blocks that are in the blockchain. qed.").number(); - hash_rlp.append(&block_hash); - hash_rlp.append(&number); - rlp_stream.append_raw(hash_rlp.as_raw(), 1); - } - Some(rlp_stream.out()) - } - } - }, - None => None - } - } - - /// creates rlp from block bytes and total difficulty - fn create_block_rlp(bytes: &Bytes, total_difficulty: U256) -> Bytes { - let mut rlp_stream = RlpStream::new_list(2); - rlp_stream.append_raw(bytes, 1); - rlp_stream.append(&total_difficulty); - rlp_stream.out() - } - - /// creates latest block rlp for the given client - fn create_latest_block_rlp(chain: &BlockChainClient) -> Bytes { - ChainSync::create_block_rlp( - &chain.block(BlockId::Hash(chain.chain_info().best_block_hash)) - .expect("Best block always exists").into_inner(), - chain.chain_info().total_difficulty - ) - } - - /// creates given hash block rlp for the given client - fn create_new_block_rlp(chain: &BlockChainClient, hash: &H256) -> Bytes { - ChainSync::create_block_rlp( - &chain.block(BlockId::Hash(hash.clone())).expect("Block has just been sealed; qed").into_inner(), - chain.block_total_difficulty(BlockId::Hash(hash.clone())).expect("Block has just been sealed; qed.") - ) - } - - /// returns peer ids that have different blocks than our chain - fn get_lagging_peers(&mut self, chain_info: &BlockChainInfo) -> Vec { - let latest_hash = chain_info.best_block_hash; - self - .peers - .iter_mut() - .filter_map(|(&id, ref mut peer_info)| { - trace!(target: "sync", "Checking peer our best {} their best {}", latest_hash, peer_info.latest_hash); - if peer_info.latest_hash != latest_hash { - Some(id) - } else { - None - } - }) - .collect::>() - } - - fn select_random_peers(peers: &[PeerId]) -> Vec { - // take sqrt(x) peers - let mut peers = peers.to_vec(); - let mut count = (peers.len() as f64).powf(0.5).round() as usize; - count = cmp::min(count, MAX_PEERS_PROPAGATION); - count = cmp::max(count, MIN_PEERS_PROPAGATION); - random::new().shuffle(&mut peers); - peers.truncate(count); - peers - } - - fn get_consensus_peers(&self) -> Vec { - self.peers.iter().filter_map(|(id, p)| if p.protocol_version >= PAR_PROTOCOL_VERSION_2 { Some(*id) } else { None }).collect() - } - - fn get_private_transaction_peers(&self) -> Vec { - self.peers.iter().filter_map(|(id, p)| if p.protocol_version >= PAR_PROTOCOL_VERSION_3 { Some(*id) } else { None }).collect() - } - - /// propagates latest block to a set of peers - fn propagate_blocks(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo, blocks: &[H256], peers: &[PeerId]) -> usize { - trace!(target: "sync", "Sending NewBlocks to {:?}", peers); - let mut sent = 0; - for peer_id in peers { - if blocks.is_empty() { - let rlp = ChainSync::create_latest_block_rlp(io.chain()); - self.send_packet(io, *peer_id, NEW_BLOCK_PACKET, rlp); - } else { - for h in blocks { - let rlp = ChainSync::create_new_block_rlp(io.chain(), h); - self.send_packet(io, *peer_id, NEW_BLOCK_PACKET, rlp); - } - } - if let Some(ref mut peer) = self.peers.get_mut(peer_id) { - peer.latest_hash = chain_info.best_block_hash.clone(); - } - sent += 1; - } - sent - } - - /// propagates new known hashes to all peers - fn propagate_new_hashes(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo, peers: &[PeerId]) -> usize { - trace!(target: "sync", "Sending NewHashes to {:?}", peers); - let mut sent = 0; - let last_parent = *io.chain().best_block_header().parent_hash(); - for peer_id in peers { - sent += match ChainSync::create_new_hashes_rlp(io.chain(), &last_parent, &chain_info.best_block_hash) { - Some(rlp) => { - { - if let Some(ref mut peer) = self.peers.get_mut(peer_id) { - peer.latest_hash = chain_info.best_block_hash.clone(); - } - } - self.send_packet(io, *peer_id, NEW_BLOCK_HASHES_PACKET, rlp); - 1 - }, - None => 0 - } - } - sent - } - - /// propagates new transactions to all peers - pub fn propagate_new_transactions(&mut self, io: &mut SyncIo) -> usize { - // Early out if nobody to send to. - if self.peers.is_empty() { - return 0; - } - - let transactions = io.chain().ready_transactions(); - if transactions.is_empty() { - return 0; - } - - let (transactions, service_transactions): (Vec<_>, Vec<_>) = transactions.iter() - .map(|tx| tx.signed()) - .partition(|tx| !tx.gas_price.is_zero()); - - // usual transactions could be propagated to all peers - let mut affected_peers = HashSet::new(); - if !transactions.is_empty() { - let peers = self.select_peers_for_transactions(|_| true); - affected_peers = self.propagate_transactions_to_peers(io, peers, transactions); - } - - // most of times service_transactions will be empty - // => there's no need to merge packets - if !service_transactions.is_empty() { - let service_transactions_peers = self.select_peers_for_transactions(|peer_id| accepts_service_transaction(&io.peer_info(*peer_id))); - let service_transactions_affected_peers = self.propagate_transactions_to_peers(io, service_transactions_peers, service_transactions); - affected_peers.extend(&service_transactions_affected_peers); - } - - affected_peers.len() - } - - fn select_peers_for_transactions(&self, filter: F) -> Vec - where F: Fn(&PeerId) -> bool { - // sqrt(x)/x scaled to max u32 - let fraction = ((self.peers.len() as f64).powf(-0.5) * (u32::max_value() as f64).round()) as u32; - let small = self.peers.len() < MIN_PEERS_PROPAGATION; - - let mut random = random::new(); - self.peers.keys() - .cloned() - .filter(filter) - .filter(|_| small || random.next_u32() < fraction) - .take(MAX_PEERS_PROPAGATION) - .collect() - } - - fn propagate_transactions_to_peers(&mut self, io: &mut SyncIo, peers: Vec, transactions: Vec<&SignedTransaction>) -> HashSet { - let all_transactions_hashes = transactions.iter() - .map(|tx| tx.hash()) - .collect::>(); - let all_transactions_rlp = { - let mut packet = RlpStream::new_list(transactions.len()); - for tx in &transactions { packet.append(&**tx); } - packet.out() - }; - - // Clear old transactions from stats - self.transactions_stats.retain(&all_transactions_hashes); - - // sqrt(x)/x scaled to max u32 - let block_number = io.chain().chain_info().best_block_number; - - let lucky_peers = { - peers.into_iter() - .filter_map(|peer_id| { - let stats = &mut self.transactions_stats; - let peer_info = self.peers.get_mut(&peer_id) - .expect("peer_id is form peers; peers is result of select_peers_for_transactions; select_peers_for_transactions selects peers from self.peers; qed"); - - // Send all transactions - if peer_info.last_sent_transactions.is_empty() { - // update stats - for hash in &all_transactions_hashes { - let id = io.peer_session_info(peer_id).and_then(|info| info.id); - stats.propagated(hash, id, block_number); - } - peer_info.last_sent_transactions = all_transactions_hashes.clone(); - return Some((peer_id, all_transactions_hashes.len(), all_transactions_rlp.clone())); - } - - // Get hashes of all transactions to send to this peer - let to_send = all_transactions_hashes.difference(&peer_info.last_sent_transactions) - .take(MAX_TRANSACTIONS_TO_PROPAGATE) - .cloned() - .collect::>(); - if to_send.is_empty() { - return None; - } - - // Construct RLP - let (packet, to_send) = { - let mut to_send = to_send; - let mut packet = RlpStream::new(); - packet.begin_unbounded_list(); - let mut pushed = 0; - for tx in &transactions { - let hash = tx.hash(); - if to_send.contains(&hash) { - let mut transaction = RlpStream::new(); - tx.rlp_append(&mut transaction); - let appended = packet.append_raw_checked(&transaction.drain(), 1, MAX_TRANSACTION_PACKET_SIZE); - if !appended { - // Maximal packet size reached just proceed with sending - debug!("Transaction packet size limit reached. Sending incomplete set of {}/{} transactions.", pushed, to_send.len()); - to_send = to_send.into_iter().take(pushed).collect(); - break; - } - pushed += 1; - } - } - packet.complete_unbounded_list(); - (packet, to_send) - }; - - // Update stats - let id = io.peer_session_info(peer_id).and_then(|info| info.id); - for hash in &to_send { - // update stats - stats.propagated(hash, id, block_number); - } - - peer_info.last_sent_transactions = all_transactions_hashes - .intersection(&peer_info.last_sent_transactions) - .chain(&to_send) - .cloned() - .collect(); - Some((peer_id, to_send.len(), packet.out())) - }) - .collect::>() - }; - - // Send RLPs - let mut peers = HashSet::new(); - if lucky_peers.len() > 0 { - let mut max_sent = 0; - let lucky_peers_len = lucky_peers.len(); - for (peer_id, sent, rlp) in lucky_peers { - peers.insert(peer_id); - self.send_packet(io, peer_id, TRANSACTIONS_PACKET, rlp); - trace!(target: "sync", "{:02} <- Transactions ({} entries)", peer_id, sent); - max_sent = cmp::max(max_sent, sent); - } - debug!(target: "sync", "Sent up to {} transactions to {} peers.", max_sent, lucky_peers_len); - } - - peers - } - - fn propagate_latest_blocks(&mut self, io: &mut SyncIo, sealed: &[H256]) { - let chain_info = io.chain().chain_info(); - if (((chain_info.best_block_number as i64) - (self.last_sent_block_number as i64)).abs() as BlockNumber) < MAX_PEER_LAG_PROPAGATION { - let mut peers = self.get_lagging_peers(&chain_info); - if sealed.is_empty() { - let hashes = self.propagate_new_hashes(&chain_info, io, &peers); - peers = ChainSync::select_random_peers(&peers); - let blocks = self.propagate_blocks(&chain_info, io, sealed, &peers); - if blocks != 0 || hashes != 0 { - trace!(target: "sync", "Sent latest {} blocks and {} hashes to peers.", blocks, hashes); - } - } else { - self.propagate_blocks(&chain_info, io, sealed, &peers); - self.propagate_new_hashes(&chain_info, io, &peers); - trace!(target: "sync", "Sent sealed block to all peers"); - }; - } - self.last_sent_block_number = chain_info.best_block_number; - } - - /// Distribute valid proposed blocks to subset of current peers. - fn propagate_proposed_blocks(&mut self, io: &mut SyncIo, proposed: &[Bytes]) { - let peers = self.get_consensus_peers(); - trace!(target: "sync", "Sending proposed blocks to {:?}", peers); - for block in proposed { - let rlp = ChainSync::create_block_rlp( - block, - io.chain().chain_info().total_difficulty - ); - for peer_id in &peers { - self.send_packet(io, *peer_id, NEW_BLOCK_PACKET, rlp.clone()); - } - } - } - - /// Maintain other peers. Send out any new blocks and transactions - pub fn maintain_sync(&mut self, io: &mut SyncIo) { - self.maybe_start_snapshot_sync(io); - self.check_resume(io); - } - - /// called when block is imported to chain - propagates the blocks and updates transactions sent to peers - pub fn chain_new_blocks(&mut self, io: &mut SyncIo, _imported: &[H256], invalid: &[H256], enacted: &[H256], _retracted: &[H256], sealed: &[H256], proposed: &[Bytes]) { - let queue_info = io.chain().queue_info(); - let is_syncing = self.status().is_syncing(queue_info); - - if !is_syncing || !sealed.is_empty() || !proposed.is_empty() { - trace!(target: "sync", "Propagating blocks, state={:?}", self.state); - self.propagate_latest_blocks(io, sealed); - self.propagate_proposed_blocks(io, proposed); - } - if !invalid.is_empty() { - trace!(target: "sync", "Bad blocks in the queue, restarting"); - self.restart(io); - } - - if !is_syncing && !enacted.is_empty() && !self.peers.is_empty() { - // Select random peer to re-broadcast transactions to. - let peer = random::new().gen_range(0, self.peers.len()); - trace!(target: "sync", "Re-broadcasting transactions to a random peer."); - self.peers.values_mut().nth(peer).map(|peer_info| - peer_info.last_sent_transactions.clear() - ); - } - } - - /// Called when peer sends us new consensus packet - fn on_consensus_packet(io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - trace!(target: "sync", "Received consensus packet from {:?}", peer_id); - io.chain().queue_consensus_message(r.as_raw().to_vec()); - Ok(()) - } - - /// Broadcast consensus message to peers. - pub fn propagate_consensus_packet(&mut self, io: &mut SyncIo, packet: Bytes) { - let lucky_peers = ChainSync::select_random_peers(&self.get_consensus_peers()); - trace!(target: "sync", "Sending consensus packet to {:?}", lucky_peers); - for peer_id in lucky_peers { - self.send_packet(io, peer_id, CONSENSUS_DATA_PACKET, packet.clone()); - } - } - - /// Called when peer sends us new private transaction packet - fn on_private_transaction(&self, _io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - if !self.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { - trace!(target: "sync", "{} Ignoring packet from unconfirmed/unknown peer", peer_id); - return Ok(()); - } - - trace!(target: "sync", "Received private transaction packet from {:?}", peer_id); - - if let Err(e) = self.private_tx_handler.import_private_transaction(r.as_raw()) { - trace!(target: "sync", "Ignoring the message, error queueing: {}", e); - } - Ok(()) - } - - /// Broadcast private transaction message to peers. - pub fn propagate_private_transaction(&mut self, io: &mut SyncIo, packet: Bytes) { - let lucky_peers = ChainSync::select_random_peers(&self.get_private_transaction_peers()); - trace!(target: "sync", "Sending private transaction packet to {:?}", lucky_peers); - for peer_id in lucky_peers { - self.send_packet(io, peer_id, PRIVATE_TRANSACTION_PACKET, packet.clone()); - } - } - - /// Called when peer sends us signed private transaction packet - fn on_signed_private_transaction(&self, _io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { - if !self.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { - trace!(target: "sync", "{} Ignoring packet from unconfirmed/unknown peer", peer_id); - return Ok(()); - } - - trace!(target: "sync", "Received signed private transaction packet from {:?}", peer_id); - if let Err(e) = self.private_tx_handler.import_signed_private_transaction(r.as_raw()) { - trace!(target: "sync", "Ignoring the message, error queueing: {}", e); - } - Ok(()) - } - - /// Broadcast signed private transaction message to peers. - pub fn propagate_signed_private_transaction(&mut self, io: &mut SyncIo, packet: Bytes) { - let lucky_peers = ChainSync::select_random_peers(&self.get_private_transaction_peers()); - trace!(target: "sync", "Sending signed private transaction packet to {:?}", lucky_peers); - for peer_id in lucky_peers { - self.send_packet(io, peer_id, SIGNED_PRIVATE_TRANSACTION_PACKET, packet.clone()); - } - } - -} - -/// Checks if peer is able to process service transactions -fn accepts_service_transaction(client_id: &str) -> bool { - // Parity versions starting from this will accept service-transactions - const SERVICE_TRANSACTIONS_VERSION: (u32, u32) = (1u32, 6u32); - // Parity client string prefix - const PARITY_CLIENT_ID_PREFIX: &'static str = "Parity/v"; - - if !client_id.starts_with(PARITY_CLIENT_ID_PREFIX) { - return false; - } - let ver: Vec = client_id[PARITY_CLIENT_ID_PREFIX.len()..].split('.') - .take(2) - .filter_map(|s| s.parse().ok()) - .collect(); - ver.len() == 2 && (ver[0] > SERVICE_TRANSACTIONS_VERSION.0 || (ver[0] == SERVICE_TRANSACTIONS_VERSION.0 && ver[1] >= SERVICE_TRANSACTIONS_VERSION.1)) -} - -#[cfg(test)] -mod tests { - use std::collections::{HashSet, VecDeque}; - use ethkey; - use network::PeerId; - use tests::helpers::{TestIo}; - use tests::snapshot::TestSnapshotService; - use ethereum_types::{H256, U256, Address}; - use parking_lot::RwLock; - use bytes::Bytes; - use rlp::{Rlp, RlpStream}; - use super::*; - use ::SyncConfig; - use super::{PeerInfo, PeerAsking}; - use ethcore::header::*; - use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient, ChainInfo, BlockInfo}; - use ethcore::miner::MinerService; - use private_tx::NoopPrivateTxHandler; - - fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { - let mut header = Header::new(); - header.set_gas_limit(0.into()); - header.set_difficulty((order * 100).into()); - header.set_timestamp((order * 10) as u64); - header.set_number(order as u64); - header.set_parent_hash(parent_hash); - header.set_state_root(H256::zero()); - - let mut rlp = RlpStream::new_list(3); - rlp.append(&header); - rlp.append_raw(&::rlp::EMPTY_LIST_RLP, 1); - rlp.append_raw(&::rlp::EMPTY_LIST_RLP, 1); - rlp.out() - } - - fn get_dummy_blocks(order: u32, parent_hash: H256) -> Bytes { - let mut rlp = RlpStream::new_list(1); - rlp.append_raw(&get_dummy_block(order, parent_hash), 1); - let difficulty: U256 = (100 * order).into(); - rlp.append(&difficulty); - rlp.out() - } - - fn get_dummy_hashes() -> Bytes { - let mut rlp = RlpStream::new_list(5); - for _ in 0..5 { - let mut hash_d_rlp = RlpStream::new_list(2); - let hash: H256 = H256::from(0u64); - let diff: U256 = U256::from(1u64); - hash_d_rlp.append(&hash); - hash_d_rlp.append(&diff); - - rlp.append_raw(&hash_d_rlp.out(), 1); - } - - rlp.out() - } - - fn queue_info(unverified: usize, verified: usize) -> BlockQueueInfo { - BlockQueueInfo { - unverified_queue_size: unverified, - verified_queue_size: verified, - verifying_queue_size: 0, - max_queue_size: 1000, - max_mem_use: 1000, - mem_used: 500 - } - } - - fn sync_status(state: SyncState) -> SyncStatus { - SyncStatus { - state: state, - protocol_version: 0, - network_id: 0, - start_block_number: 0, - last_imported_block_number: None, - highest_block_number: None, - blocks_total: 0, - blocks_received: 0, - num_peers: 0, - num_active_peers: 0, - mem_used: 0, - num_snapshot_chunks: 0, - snapshot_chunks_done: 0, - last_imported_old_block_number: None, - } - } - - #[test] - fn is_still_verifying() { - assert!(!sync_status(SyncState::Idle).is_syncing(queue_info(2, 1))); - assert!(sync_status(SyncState::Idle).is_syncing(queue_info(2, 2))); - } - - #[test] - fn is_synced_state() { - assert!(sync_status(SyncState::Blocks).is_syncing(queue_info(0, 0))); - assert!(!sync_status(SyncState::Idle).is_syncing(queue_info(0, 0))); - } - - #[test] - fn return_receipts_empty() { - let mut client = TestBlockChainClient::new(); - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let io = TestIo::new(&mut client, &ss, &queue, None); - - let result = ChainSync::return_receipts(&io, &Rlp::new(&[0xc0]), 0); - - assert!(result.is_ok()); - } - - #[test] - fn return_receipts() { - let mut client = TestBlockChainClient::new(); - let queue = RwLock::new(VecDeque::new()); - let sync = dummy_sync_with_peer(H256::new(), &client); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - let mut receipt_list = RlpStream::new_list(4); - receipt_list.append(&H256::from("0000000000000000000000000000000000000000000000005555555555555555")); - receipt_list.append(&H256::from("ff00000000000000000000000000000000000000000000000000000000000000")); - receipt_list.append(&H256::from("fff0000000000000000000000000000000000000000000000000000000000000")); - receipt_list.append(&H256::from("aff0000000000000000000000000000000000000000000000000000000000000")); - - let receipts_request = receipt_list.out(); - // it returns rlp ONLY for hashes started with "f" - let result = ChainSync::return_receipts(&io, &Rlp::new(&receipts_request.clone()), 0); - - assert!(result.is_ok()); - let rlp_result = result.unwrap(); - assert!(rlp_result.is_some()); - - // the length of two rlp-encoded receipts - assert_eq!(603, rlp_result.unwrap().1.out().len()); - - io.sender = Some(2usize); - ChainSync::dispatch_packet(&RwLock::new(sync), &mut io, 0usize, super::GET_RECEIPTS_PACKET, &receipts_request); - assert_eq!(1, io.packets.len()); - } - - #[test] - fn return_block_headers() { - use ethcore::views::HeaderView; - fn make_hash_req(h: &H256, count: usize, skip: usize, reverse: bool) -> Bytes { - let mut rlp = RlpStream::new_list(4); - rlp.append(h); - rlp.append(&count); - rlp.append(&skip); - rlp.append(&if reverse {1u32} else {0u32}); - rlp.out() - } - - fn make_num_req(n: usize, count: usize, skip: usize, reverse: bool) -> Bytes { - let mut rlp = RlpStream::new_list(4); - rlp.append(&n); - rlp.append(&count); - rlp.append(&skip); - rlp.append(&if reverse {1u32} else {0u32}); - rlp.out() - } - fn to_header_vec(rlp: ::chain::RlpResponseResult) -> Vec { - Rlp::new(&rlp.unwrap().unwrap().1.out()).iter().map(|r| r.as_raw().to_vec()).collect() - } - - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Nothing); - let blocks: Vec<_> = (0 .. 100) - .map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).map(|b| b.into_inner()).unwrap()).collect(); - let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).unwrap().as_raw().to_vec()).collect(); - let hashes: Vec<_> = headers.iter().map(|h| view!(HeaderView, h).hash()).collect(); - - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let io = TestIo::new(&mut client, &ss, &queue, None); - - let unknown: H256 = H256::new(); - let result = ChainSync::return_block_headers(&io, &Rlp::new(&make_hash_req(&unknown, 1, 0, false)), 0); - assert!(to_header_vec(result).is_empty()); - let result = ChainSync::return_block_headers(&io, &Rlp::new(&make_hash_req(&unknown, 1, 0, true)), 0); - assert!(to_header_vec(result).is_empty()); - - let result = ChainSync::return_block_headers(&io, &Rlp::new(&make_hash_req(&hashes[2], 1, 0, true)), 0); - assert_eq!(to_header_vec(result), vec![headers[2].clone()]); - - let result = ChainSync::return_block_headers(&io, &Rlp::new(&make_hash_req(&hashes[2], 1, 0, false)), 0); - assert_eq!(to_header_vec(result), vec![headers[2].clone()]); - - let result = ChainSync::return_block_headers(&io, &Rlp::new(&make_hash_req(&hashes[50], 3, 5, false)), 0); - assert_eq!(to_header_vec(result), vec![headers[50].clone(), headers[56].clone(), headers[62].clone()]); - - let result = ChainSync::return_block_headers(&io, &Rlp::new(&make_hash_req(&hashes[50], 3, 5, true)), 0); - assert_eq!(to_header_vec(result), vec![headers[50].clone(), headers[44].clone(), headers[38].clone()]); - - let result = ChainSync::return_block_headers(&io, &Rlp::new(&make_num_req(2, 1, 0, true)), 0); - assert_eq!(to_header_vec(result), vec![headers[2].clone()]); - - let result = ChainSync::return_block_headers(&io, &Rlp::new(&make_num_req(2, 1, 0, false)), 0); - assert_eq!(to_header_vec(result), vec![headers[2].clone()]); - - let result = ChainSync::return_block_headers(&io, &Rlp::new(&make_num_req(50, 3, 5, false)), 0); - assert_eq!(to_header_vec(result), vec![headers[50].clone(), headers[56].clone(), headers[62].clone()]); - - let result = ChainSync::return_block_headers(&io, &Rlp::new(&make_num_req(50, 3, 5, true)), 0); - assert_eq!(to_header_vec(result), vec![headers[50].clone(), headers[44].clone(), headers[38].clone()]); - } - - #[test] - fn return_nodes() { - let mut client = TestBlockChainClient::new(); - let queue = RwLock::new(VecDeque::new()); - let sync = dummy_sync_with_peer(H256::new(), &client); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - let mut node_list = RlpStream::new_list(3); - node_list.append(&H256::from("0000000000000000000000000000000000000000000000005555555555555555")); - node_list.append(&H256::from("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa")); - node_list.append(&H256::from("aff0000000000000000000000000000000000000000000000000000000000000")); - - let node_request = node_list.out(); - // it returns rlp ONLY for hashes started with "f" - let result = ChainSync::return_node_data(&io, &Rlp::new(&node_request.clone()), 0); - - assert!(result.is_ok()); - let rlp_result = result.unwrap(); - assert!(rlp_result.is_some()); - - // the length of one rlp-encoded hashe - let rlp = rlp_result.unwrap().1.out(); - let rlp = Rlp::new(&rlp); - assert_eq!(Ok(1), rlp.item_count()); - - io.sender = Some(2usize); - - ChainSync::dispatch_packet(&RwLock::new(sync), &mut io, 0usize, super::GET_NODE_DATA_PACKET, &node_request); - assert_eq!(1, io.packets.len()); - } - - fn dummy_sync_with_peer(peer_latest_hash: H256, client: &BlockChainClient) -> ChainSync { - let mut sync = ChainSync::new(SyncConfig::default(), client, Arc::new(NoopPrivateTxHandler)); - insert_dummy_peer(&mut sync, 0, peer_latest_hash); - sync - } - - fn insert_dummy_peer(sync: &mut ChainSync, peer_id: PeerId, peer_latest_hash: H256) { - sync.peers.insert(peer_id, - PeerInfo { - protocol_version: 0, - genesis: H256::zero(), - network_id: 0, - latest_hash: peer_latest_hash, - difficulty: None, - asking: PeerAsking::Nothing, - asking_blocks: Vec::new(), - asking_hash: None, - ask_time: Instant::now(), - last_sent_transactions: HashSet::new(), - expired: false, - confirmation: super::ForkConfirmation::Confirmed, - snapshot_number: None, - snapshot_hash: None, - asking_snapshot_data: None, - block_set: None, - }); - - } - - #[test] - fn finds_lagging_peers() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(10), &client); - let chain_info = client.chain_info(); - - let lagging_peers = sync.get_lagging_peers(&chain_info); - - assert_eq!(1, lagging_peers.len()); - } - - #[test] - fn calculates_tree_for_lagging_peer() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(15, EachBlockWith::Uncle); - - let start = client.block_hash_delta_minus(4); - let end = client.block_hash_delta_minus(2); - - // wrong way end -> start, should be None - let rlp = ChainSync::create_new_hashes_rlp(&client, &end, &start); - assert!(rlp.is_none()); - - let rlp = ChainSync::create_new_hashes_rlp(&client, &start, &end).unwrap(); - // size of three rlp encoded hash-difficulty - assert_eq!(107, rlp.len()); - } - - #[test] - fn sends_new_hashes_to_lagging_peer() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - let queue = RwLock::new(VecDeque::new()); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - let chain_info = client.chain_info(); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - let peers = sync.get_lagging_peers(&chain_info); - let peer_count = sync.propagate_new_hashes(&chain_info, &mut io, &peers); - - // 1 message should be send - assert_eq!(1, io.packets.len()); - // 1 peer should be updated - assert_eq!(1, peer_count); - // NEW_BLOCK_HASHES_PACKET - assert_eq!(0x01, io.packets[0].packet_id); - } - - #[test] - fn sends_latest_block_to_lagging_peer() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - let queue = RwLock::new(VecDeque::new()); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - let chain_info = client.chain_info(); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - let peers = sync.get_lagging_peers(&chain_info); - let peer_count = sync.propagate_blocks(&chain_info, &mut io, &[], &peers); - - // 1 message should be send - assert_eq!(1, io.packets.len()); - // 1 peer should be updated - assert_eq!(1, peer_count); - // NEW_BLOCK_PACKET - assert_eq!(0x07, io.packets[0].packet_id); - } - - #[test] - fn sends_sealed_block() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - let queue = RwLock::new(VecDeque::new()); - let hash = client.block_hash(BlockId::Number(99)).unwrap(); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - let chain_info = client.chain_info(); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - let peers = sync.get_lagging_peers(&chain_info); - let peer_count = sync.propagate_blocks(&chain_info, &mut io, &[hash.clone()], &peers); - - // 1 message should be send - assert_eq!(1, io.packets.len()); - // 1 peer should be updated - assert_eq!(1, peer_count); - // NEW_BLOCK_PACKET - assert_eq!(0x07, io.packets[0].packet_id); - } - - #[test] - fn sends_proposed_block() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(2, EachBlockWith::Uncle); - let queue = RwLock::new(VecDeque::new()); - let block = client.block(BlockId::Latest).unwrap().into_inner(); - let mut sync = ChainSync::new(SyncConfig::default(), &client, Arc::new(NoopPrivateTxHandler)); - sync.peers.insert(0, - PeerInfo { - // Messaging protocol - protocol_version: 2, - genesis: H256::zero(), - network_id: 0, - latest_hash: client.block_hash_delta_minus(1), - difficulty: None, - asking: PeerAsking::Nothing, - asking_blocks: Vec::new(), - asking_hash: None, - ask_time: Instant::now(), - last_sent_transactions: HashSet::new(), - expired: false, - confirmation: super::ForkConfirmation::Confirmed, - snapshot_number: None, - snapshot_hash: None, - asking_snapshot_data: None, - block_set: None, - }); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - sync.propagate_proposed_blocks(&mut io, &[block]); - - // 1 message should be sent - assert_eq!(1, io.packets.len()); - // NEW_BLOCK_PACKET - assert_eq!(0x07, io.packets[0].packet_id); - } - - #[test] - fn propagates_transactions() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - client.insert_transaction_to_queue(); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(1), &client); - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - let peer_count = sync.propagate_new_transactions(&mut io); - // Try to propagate same transactions for the second time - let peer_count2 = sync.propagate_new_transactions(&mut io); - // Even after new block transactions should not be propagated twice - sync.chain_new_blocks(&mut io, &[], &[], &[], &[], &[], &[]); - // Try to propagate same transactions for the third time - let peer_count3 = sync.propagate_new_transactions(&mut io); - - // 1 message should be send - assert_eq!(1, io.packets.len()); - // 1 peer should be updated but only once - assert_eq!(1, peer_count); - assert_eq!(0, peer_count2); - assert_eq!(0, peer_count3); - // TRANSACTIONS_PACKET - assert_eq!(0x02, io.packets[0].packet_id); - } - - #[test] - fn does_not_propagate_new_transactions_after_new_block() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - client.insert_transaction_to_queue(); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(1), &client); - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - let peer_count = sync.propagate_new_transactions(&mut io); - io.chain.insert_transaction_to_queue(); - // New block import should not trigger propagation. - // (we only propagate on timeout) - sync.chain_new_blocks(&mut io, &[], &[], &[], &[], &[], &[]); - - // 2 message should be send - assert_eq!(1, io.packets.len()); - // 1 peer should receive the message - assert_eq!(1, peer_count); - // TRANSACTIONS_PACKET - assert_eq!(0x02, io.packets[0].packet_id); - } - - #[test] - fn does_not_fail_for_no_peers() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - client.insert_transaction_to_queue(); - // Sync with no peers - let mut sync = ChainSync::new(SyncConfig::default(), &client, Arc::new(NoopPrivateTxHandler)); - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - let peer_count = sync.propagate_new_transactions(&mut io); - sync.chain_new_blocks(&mut io, &[], &[], &[], &[], &[], &[]); - // Try to propagate same transactions for the second time - let peer_count2 = sync.propagate_new_transactions(&mut io); - - assert_eq!(0, io.packets.len()); - assert_eq!(0, peer_count); - assert_eq!(0, peer_count2); - } - - #[test] - fn propagates_transactions_without_alternating() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - client.insert_transaction_to_queue(); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(1), &client); - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - // should sent some - { - let mut io = TestIo::new(&mut client, &ss, &queue, None); - let peer_count = sync.propagate_new_transactions(&mut io); - assert_eq!(1, io.packets.len()); - assert_eq!(1, peer_count); - } - // Insert some more - client.insert_transaction_to_queue(); - let (peer_count2, peer_count3) = { - let mut io = TestIo::new(&mut client, &ss, &queue, None); - // Propagate new transactions - let peer_count2 = sync.propagate_new_transactions(&mut io); - // And now the peer should have all transactions - let peer_count3 = sync.propagate_new_transactions(&mut io); - (peer_count2, peer_count3) - }; - - // 2 message should be send (in total) - assert_eq!(2, queue.read().len()); - // 1 peer should be updated but only once after inserting new transaction - assert_eq!(1, peer_count2); - assert_eq!(0, peer_count3); - // TRANSACTIONS_PACKET - assert_eq!(0x02, queue.read()[0].packet_id); - assert_eq!(0x02, queue.read()[1].packet_id); - } - - #[test] - fn should_maintain_transations_propagation_stats() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - client.insert_transaction_to_queue(); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(1), &client); - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - sync.propagate_new_transactions(&mut io); - - let stats = sync.transactions_stats(); - assert_eq!(stats.len(), 1, "Should maintain stats for single transaction.") - } - - #[test] - fn should_propagate_service_transaction_to_selected_peers_only() { - let mut client = TestBlockChainClient::new(); - client.insert_transaction_with_gas_price_to_queue(U256::zero()); - let block_hash = client.block_hash_delta_minus(1); - let mut sync = ChainSync::new(SyncConfig::default(), &client, Arc::new(NoopPrivateTxHandler)); - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - // when peer#1 is Geth - insert_dummy_peer(&mut sync, 1, block_hash); - io.peers_info.insert(1, "Geth".to_owned()); - // and peer#2 is Parity, accepting service transactions - insert_dummy_peer(&mut sync, 2, block_hash); - io.peers_info.insert(2, "Parity/v1.6".to_owned()); - // and peer#3 is Parity, discarding service transactions - insert_dummy_peer(&mut sync, 3, block_hash); - io.peers_info.insert(3, "Parity/v1.5".to_owned()); - // and peer#4 is Parity, accepting service transactions - insert_dummy_peer(&mut sync, 4, block_hash); - io.peers_info.insert(4, "Parity/v1.7.3-ABCDEFGH".to_owned()); - - // and new service transaction is propagated to peers - sync.propagate_new_transactions(&mut io); - - // peer#2 && peer#4 are receiving service transaction - assert!(io.packets.iter().any(|p| p.packet_id == 0x02 && p.recipient == 2)); // TRANSACTIONS_PACKET - assert!(io.packets.iter().any(|p| p.packet_id == 0x02 && p.recipient == 4)); // TRANSACTIONS_PACKET - assert_eq!(io.packets.len(), 2); - } - - #[test] - fn should_propagate_service_transaction_is_sent_as_separate_message() { - let mut client = TestBlockChainClient::new(); - let tx1_hash = client.insert_transaction_to_queue(); - let tx2_hash = client.insert_transaction_with_gas_price_to_queue(U256::zero()); - let block_hash = client.block_hash_delta_minus(1); - let mut sync = ChainSync::new(SyncConfig::default(), &client, Arc::new(NoopPrivateTxHandler)); - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - // when peer#1 is Parity, accepting service transactions - insert_dummy_peer(&mut sync, 1, block_hash); - io.peers_info.insert(1, "Parity/v1.6".to_owned()); - - // and service + non-service transactions are propagated to peers - sync.propagate_new_transactions(&mut io); - - // two separate packets for peer are queued: - // 1) with non-service-transaction - // 2) with service transaction - let sent_transactions: Vec = io.packets.iter() - .filter_map(|p| { - if p.packet_id != 0x02 || p.recipient != 1 { // TRANSACTIONS_PACKET - return None; - } - - let rlp = Rlp::new(&*p.data); - let item_count = rlp.item_count().unwrap_or(0); - if item_count != 1 { - return None; - } - - rlp.at(0).ok().and_then(|r| r.as_val().ok()) - }) - .collect(); - assert_eq!(sent_transactions.len(), 2); - assert!(sent_transactions.iter().any(|tx| tx.hash() == tx1_hash)); - assert!(sent_transactions.iter().any(|tx| tx.hash() == tx2_hash)); - } - - #[test] - fn handles_peer_new_block_malformed() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(10, EachBlockWith::Uncle); - - let block_data = get_dummy_block(11, client.chain_info().best_block_hash); - - let queue = RwLock::new(VecDeque::new()); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - //sync.have_common_block = true; - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - let block = Rlp::new(&block_data); - - let result = sync.on_peer_new_block(&mut io, 0, &block); - - assert!(result.is_err()); - } - - #[test] - fn handles_peer_new_block() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(10, EachBlockWith::Uncle); - - let block_data = get_dummy_blocks(11, client.chain_info().best_block_hash); - - let queue = RwLock::new(VecDeque::new()); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - let block = Rlp::new(&block_data); - - let result = sync.on_peer_new_block(&mut io, 0, &block); - - assert!(result.is_ok()); - } - - #[test] - fn handles_peer_new_block_empty() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(10, EachBlockWith::Uncle); - let queue = RwLock::new(VecDeque::new()); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - let empty_data = vec![]; - let block = Rlp::new(&empty_data); - - let result = sync.on_peer_new_block(&mut io, 0, &block); - - assert!(result.is_err()); - } - - #[test] - fn handles_peer_new_hashes() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(10, EachBlockWith::Uncle); - let queue = RwLock::new(VecDeque::new()); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - let hashes_data = get_dummy_hashes(); - let hashes_rlp = Rlp::new(&hashes_data); - - let result = sync.on_peer_new_hashes(&mut io, 0, &hashes_rlp); - - assert!(result.is_ok()); - } - - #[test] - fn handles_peer_new_hashes_empty() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(10, EachBlockWith::Uncle); - let queue = RwLock::new(VecDeque::new()); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - let empty_hashes_data = vec![]; - let hashes_rlp = Rlp::new(&empty_hashes_data); - - let result = sync.on_peer_new_hashes(&mut io, 0, &hashes_rlp); - - assert!(result.is_ok()); - } - - // idea is that what we produce when propagading latest hashes should be accepted in - // on_peer_new_hashes in our code as well - #[test] - fn hashes_rlp_mutually_acceptable() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - let queue = RwLock::new(VecDeque::new()); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - let chain_info = client.chain_info(); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - let peers = sync.get_lagging_peers(&chain_info); - sync.propagate_new_hashes(&chain_info, &mut io, &peers); - - let data = &io.packets[0].data.clone(); - let result = sync.on_peer_new_hashes(&mut io, 0, &Rlp::new(data)); - assert!(result.is_ok()); - } - - // idea is that what we produce when propagading latest block should be accepted in - // on_peer_new_block in our code as well - #[test] - fn block_rlp_mutually_acceptable() { - let mut client = TestBlockChainClient::new(); - client.add_blocks(100, EachBlockWith::Uncle); - let queue = RwLock::new(VecDeque::new()); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - let chain_info = client.chain_info(); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - let peers = sync.get_lagging_peers(&chain_info); - sync.propagate_blocks(&chain_info, &mut io, &[], &peers); - - let data = &io.packets[0].data.clone(); - let result = sync.on_peer_new_block(&mut io, 0, &Rlp::new(data)); - assert!(result.is_ok()); - } - - #[test] - fn should_add_transactions_to_queue() { - fn sender(tx: &UnverifiedTransaction) -> Address { - ethkey::public_to_address(&tx.recover_public().unwrap()) - } - - // given - let mut client = TestBlockChainClient::new(); - client.add_blocks(98, EachBlockWith::Uncle); - client.add_blocks(1, EachBlockWith::UncleAndTransaction); - client.add_blocks(1, EachBlockWith::Transaction); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - - let good_blocks = vec![client.block_hash_delta_minus(2)]; - let retracted_blocks = vec![client.block_hash_delta_minus(1)]; - - // Add some balance to clients and reset nonces - for h in &[good_blocks[0], retracted_blocks[0]] { - let block = client.block(BlockId::Hash(*h)).unwrap(); - let sender = sender(&block.transactions()[0]);; - client.set_balance(sender, U256::from(10_000_000_000_000_000_000u64)); - client.set_nonce(sender, U256::from(0)); - } - - - // when - { - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - io.chain.miner.chain_new_blocks(io.chain, &[], &[], &[], &good_blocks, false); - sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks, &[], &[]); - assert_eq!(io.chain.miner.ready_transactions(io.chain).len(), 1); - } - // We need to update nonce status (because we say that the block has been imported) - for h in &[good_blocks[0]] { - let block = client.block(BlockId::Hash(*h)).unwrap(); - client.set_nonce(sender(&block.transactions()[0]), U256::from(1)); - } - { - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&client, &ss, &queue, None); - io.chain.miner.chain_new_blocks(io.chain, &[], &[], &good_blocks, &retracted_blocks, false); - sync.chain_new_blocks(&mut io, &[], &[], &good_blocks, &retracted_blocks, &[], &[]); - } - - // then - assert_eq!(client.miner.ready_transactions(&client).len(), 1); - } - - #[test] - fn should_not_add_transactions_to_queue_if_not_synced() { - // given - let mut client = TestBlockChainClient::new(); - client.add_blocks(98, EachBlockWith::Uncle); - client.add_blocks(1, EachBlockWith::UncleAndTransaction); - client.add_blocks(1, EachBlockWith::Transaction); - let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); - - let good_blocks = vec![client.block_hash_delta_minus(2)]; - let retracted_blocks = vec![client.block_hash_delta_minus(1)]; - - let queue = RwLock::new(VecDeque::new()); - let ss = TestSnapshotService::new(); - let mut io = TestIo::new(&mut client, &ss, &queue, None); - - // when - sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks, &[], &[]); - assert_eq!(io.chain.miner.queue_status().status.transaction_count, 0); - sync.chain_new_blocks(&mut io, &[], &[], &good_blocks, &retracted_blocks, &[], &[]); - - // then - let status = io.chain.miner.queue_status(); - assert_eq!(status.status.transaction_count, 0); - } -} diff --git a/ethcore/sync/src/chain/handler.rs b/ethcore/sync/src/chain/handler.rs new file mode 100644 index 00000000000..966b7ce20ad --- /dev/null +++ b/ethcore/sync/src/chain/handler.rs @@ -0,0 +1,828 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use api::WARP_SYNC_PROTOCOL_ID; +use block_sync::{BlockDownloaderImportError as DownloaderImportError, DownloadAction}; +use bytes::Bytes; +use ethcore::client::{BlockStatus, BlockId, BlockImportError, BlockImportErrorKind}; +use ethcore::error::*; +use ethcore::header::{BlockNumber, Header as BlockHeader}; +use ethcore::snapshot::{ManifestData, RestorationStatus}; +use ethereum_types::{H256, U256}; +use hash::keccak; +use network::PeerId; +use rlp::Rlp; +use snapshot::ChunkType; +use std::cmp; +use std::collections::HashSet; +use std::time::Instant; +use sync_io::SyncIo; + +use super::{ + BlockSet, + ChainSync, + ForkConfirmation, + PacketDecodeError, + PeerAsking, + PeerInfo, + SyncRequester, + SyncState, + ETH_PROTOCOL_VERSION_62, + ETH_PROTOCOL_VERSION_63, + MAX_NEW_BLOCK_AGE, + MAX_NEW_HASHES, + PAR_PROTOCOL_VERSION_1, + PAR_PROTOCOL_VERSION_2, + PAR_PROTOCOL_VERSION_3, + BLOCK_BODIES_PACKET, + BLOCK_HEADERS_PACKET, + NEW_BLOCK_HASHES_PACKET, + NEW_BLOCK_PACKET, + PRIVATE_TRANSACTION_PACKET, + RECEIPTS_PACKET, + SIGNED_PRIVATE_TRANSACTION_PACKET, + SNAPSHOT_DATA_PACKET, + SNAPSHOT_MANIFEST_PACKET, + STATUS_PACKET, + TRANSACTIONS_PACKET, +}; + +/// The Chain Sync Handler: handles responses from peers +pub struct SyncHandler; + +impl SyncHandler { + /// Handle incoming packet from peer + pub fn on_packet(sync: &mut ChainSync, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { + if packet_id != STATUS_PACKET && !sync.peers.contains_key(&peer) { + debug!(target:"sync", "Unexpected packet {} from unregistered peer: {}:{}", packet_id, peer, io.peer_info(peer)); + return; + } + let rlp = Rlp::new(data); + let result = match packet_id { + STATUS_PACKET => SyncHandler::on_peer_status(sync, io, peer, &rlp), + TRANSACTIONS_PACKET => SyncHandler::on_peer_transactions(sync, io, peer, &rlp), + BLOCK_HEADERS_PACKET => SyncHandler::on_peer_block_headers(sync, io, peer, &rlp), + BLOCK_BODIES_PACKET => SyncHandler::on_peer_block_bodies(sync, io, peer, &rlp), + RECEIPTS_PACKET => SyncHandler::on_peer_block_receipts(sync, io, peer, &rlp), + NEW_BLOCK_PACKET => SyncHandler::on_peer_new_block(sync, io, peer, &rlp), + NEW_BLOCK_HASHES_PACKET => SyncHandler::on_peer_new_hashes(sync, io, peer, &rlp), + SNAPSHOT_MANIFEST_PACKET => SyncHandler::on_snapshot_manifest(sync, io, peer, &rlp), + SNAPSHOT_DATA_PACKET => SyncHandler::on_snapshot_data(sync, io, peer, &rlp), + PRIVATE_TRANSACTION_PACKET => SyncHandler::on_private_transaction(sync, io, peer, &rlp), + SIGNED_PRIVATE_TRANSACTION_PACKET => SyncHandler::on_signed_private_transaction(sync, io, peer, &rlp), + _ => { + debug!(target: "sync", "{}: Unknown packet {}", peer, packet_id); + Ok(()) + } + }; + result.unwrap_or_else(|e| { + debug!(target:"sync", "{} -> Malformed packet {} : {}", peer, packet_id, e); + }) + } + + /// Called when peer sends us new consensus packet + pub fn on_consensus_packet(io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + trace!(target: "sync", "Received consensus packet from {:?}", peer_id); + io.chain().queue_consensus_message(r.as_raw().to_vec()); + Ok(()) + } + + /// Called by peer when it is disconnecting + pub fn on_peer_aborting(sync: &mut ChainSync, io: &mut SyncIo, peer: PeerId) { + trace!(target: "sync", "== Disconnecting {}: {}", peer, io.peer_info(peer)); + sync.handshaking_peers.remove(&peer); + if sync.peers.contains_key(&peer) { + debug!(target: "sync", "Disconnected {}", peer); + sync.clear_peer_download(peer); + sync.peers.remove(&peer); + sync.active_peers.remove(&peer); + sync.continue_sync(io); + } + } + + /// Called when a new peer is connected + pub fn on_peer_connected(sync: &mut ChainSync, io: &mut SyncIo, peer: PeerId) { + trace!(target: "sync", "== Connected {}: {}", peer, io.peer_info(peer)); + if let Err(e) = sync.send_status(io, peer) { + debug!(target:"sync", "Error sending status request: {:?}", e); + io.disconnect_peer(peer); + } else { + sync.handshaking_peers.insert(peer, Instant::now()); + } + } + + /// Called by peer once it has new block bodies + pub fn on_peer_new_block(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + if !sync.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { + trace!(target: "sync", "Ignoring new block from unconfirmed peer {}", peer_id); + return Ok(()); + } + let difficulty: U256 = r.val_at(1)?; + if let Some(ref mut peer) = sync.peers.get_mut(&peer_id) { + if peer.difficulty.map_or(true, |pd| difficulty > pd) { + peer.difficulty = Some(difficulty); + } + } + let block_rlp = r.at(0)?; + let header_rlp = block_rlp.at(0)?; + let h = keccak(&header_rlp.as_raw()); + trace!(target: "sync", "{} -> NewBlock ({})", peer_id, h); + let header: BlockHeader = header_rlp.as_val()?; + if header.number() > sync.highest_block.unwrap_or(0) { + sync.highest_block = Some(header.number()); + } + let mut unknown = false; + { + if let Some(ref mut peer) = sync.peers.get_mut(&peer_id) { + peer.latest_hash = header.hash(); + } + } + let last_imported_number = sync.new_blocks.last_imported_block_number(); + if last_imported_number > header.number() && last_imported_number - header.number() > MAX_NEW_BLOCK_AGE { + trace!(target: "sync", "Ignored ancient new block {:?}", h); + io.disable_peer(peer_id); + return Ok(()); + } + match io.chain().import_block(block_rlp.as_raw().to_vec()) { + Err(BlockImportError(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain), _)) => { + trace!(target: "sync", "New block already in chain {:?}", h); + }, + Err(BlockImportError(BlockImportErrorKind::Import(ImportErrorKind::AlreadyQueued), _)) => { + trace!(target: "sync", "New block already queued {:?}", h); + }, + Ok(_) => { + // abort current download of the same block + sync.complete_sync(io); + sync.new_blocks.mark_as_known(&header.hash(), header.number()); + trace!(target: "sync", "New block queued {:?} ({})", h, header.number()); + }, + Err(BlockImportError(BlockImportErrorKind::Block(BlockError::UnknownParent(p)), _)) => { + unknown = true; + trace!(target: "sync", "New block with unknown parent ({:?}) {:?}", p, h); + }, + Err(e) => { + debug!(target: "sync", "Bad new block {:?} : {:?}", h, e); + io.disable_peer(peer_id); + } + }; + if unknown { + if sync.state != SyncState::Idle { + trace!(target: "sync", "NewBlock ignored while seeking"); + } else { + trace!(target: "sync", "New unknown block {:?}", h); + //TODO: handle too many unknown blocks + sync.sync_peer(io, peer_id, true); + } + } + sync.continue_sync(io); + Ok(()) + } + + /// Handles `NewHashes` packet. Initiates headers download for any unknown hashes. + pub fn on_peer_new_hashes(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + if !sync.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { + trace!(target: "sync", "Ignoring new hashes from unconfirmed peer {}", peer_id); + return Ok(()); + } + let hashes: Vec<_> = r.iter().take(MAX_NEW_HASHES).map(|item| (item.val_at::(0), item.val_at::(1))).collect(); + if let Some(ref mut peer) = sync.peers.get_mut(&peer_id) { + // Peer has new blocks with unknown difficulty + peer.difficulty = None; + if let Some(&(Ok(ref h), _)) = hashes.last() { + peer.latest_hash = h.clone(); + } + } + if sync.state != SyncState::Idle { + trace!(target: "sync", "Ignoring new hashes since we're already downloading."); + let max = r.iter().take(MAX_NEW_HASHES).map(|item| item.val_at::(1).unwrap_or(0)).fold(0u64, cmp::max); + if max > sync.highest_block.unwrap_or(0) { + sync.highest_block = Some(max); + } + sync.continue_sync(io); + return Ok(()); + } + trace!(target: "sync", "{} -> NewHashes ({} entries)", peer_id, r.item_count()?); + let mut max_height: BlockNumber = 0; + let mut new_hashes = Vec::new(); + let last_imported_number = sync.new_blocks.last_imported_block_number(); + for (rh, rn) in hashes { + let hash = rh?; + let number = rn?; + if number > sync.highest_block.unwrap_or(0) { + sync.highest_block = Some(number); + } + if sync.new_blocks.is_downloading(&hash) { + continue; + } + if last_imported_number > number && last_imported_number - number > MAX_NEW_BLOCK_AGE { + trace!(target: "sync", "Ignored ancient new block hash {:?}", hash); + io.disable_peer(peer_id); + continue; + } + match io.chain().block_status(BlockId::Hash(hash.clone())) { + BlockStatus::InChain => { + trace!(target: "sync", "New block hash already in chain {:?}", hash); + }, + BlockStatus::Queued => { + trace!(target: "sync", "New hash block already queued {:?}", hash); + }, + BlockStatus::Unknown | BlockStatus::Pending => { + new_hashes.push(hash.clone()); + if number > max_height { + trace!(target: "sync", "New unknown block hash {:?}", hash); + if let Some(ref mut peer) = sync.peers.get_mut(&peer_id) { + peer.latest_hash = hash.clone(); + } + max_height = number; + } + }, + BlockStatus::Bad => { + debug!(target: "sync", "Bad new block hash {:?}", hash); + io.disable_peer(peer_id); + return Ok(()); + } + } + }; + if max_height != 0 { + trace!(target: "sync", "Downloading blocks for new hashes"); + sync.new_blocks.reset_to(new_hashes); + sync.state = SyncState::NewBlocks; + sync.sync_peer(io, peer_id, true); + } + sync.continue_sync(io); + Ok(()) + } + + /// Called by peer once it has new block bodies + fn on_peer_block_bodies(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + sync.clear_peer_download(peer_id); + let block_set = sync.peers.get(&peer_id).and_then(|p| p.block_set).unwrap_or(BlockSet::NewBlocks); + if !sync.reset_peer_asking(peer_id, PeerAsking::BlockBodies) { + trace!(target: "sync", "{}: Ignored unexpected bodies", peer_id); + sync.continue_sync(io); + return Ok(()); + } + let item_count = r.item_count()?; + trace!(target: "sync", "{} -> BlockBodies ({} entries), set = {:?}", peer_id, item_count, block_set); + if item_count == 0 { + sync.deactivate_peer(io, peer_id); + } + else if sync.state == SyncState::Waiting { + trace!(target: "sync", "Ignored block bodies while waiting"); + } + else + { + let result = { + let downloader = match block_set { + BlockSet::NewBlocks => &mut sync.new_blocks, + BlockSet::OldBlocks => match sync.old_blocks { + None => { + trace!(target: "sync", "Ignored block headers while block download is inactive"); + sync.continue_sync(io); + return Ok(()); + }, + Some(ref mut blocks) => blocks, + } + }; + downloader.import_bodies(io, r) + }; + + match result { + Err(DownloaderImportError::Invalid) => { + io.disable_peer(peer_id); + sync.deactivate_peer(io, peer_id); + sync.continue_sync(io); + return Ok(()); + }, + Err(DownloaderImportError::Useless) => { + sync.deactivate_peer(io, peer_id); + }, + Ok(()) => (), + } + + sync.collect_blocks(io, block_set); + sync.sync_peer(io, peer_id, false); + } + sync.continue_sync(io); + Ok(()) + } + + fn on_peer_confirmed(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId) { + sync.sync_peer(io, peer_id, false); + } + + fn on_peer_fork_header(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + { + let peer = sync.peers.get_mut(&peer_id).expect("Is only called when peer is present in peers"); + peer.asking = PeerAsking::Nothing; + let item_count = r.item_count()?; + let (fork_number, fork_hash) = sync.fork_block.expect("ForkHeader request is sent only fork block is Some; qed").clone(); + + if item_count == 0 || item_count != 1 { + trace!(target: "sync", "{}: Chain is too short to confirm the block", peer_id); + io.disable_peer(peer_id); + return Ok(()); + } + + let header = r.at(0)?.as_raw(); + if keccak(&header) != fork_hash { + trace!(target: "sync", "{}: Fork mismatch", peer_id); + io.disable_peer(peer_id); + return Ok(()); + } + + trace!(target: "sync", "{}: Confirmed peer", peer_id); + peer.confirmation = ForkConfirmation::Confirmed; + if !io.chain_overlay().read().contains_key(&fork_number) { + io.chain_overlay().write().insert(fork_number, header.to_vec()); + } + } + SyncHandler::on_peer_confirmed(sync, io, peer_id); + return Ok(()); + } + + /// Called by peer once it has new block headers during sync + fn on_peer_block_headers(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + let is_fork_header_request = match sync.peers.get(&peer_id) { + Some(peer) if peer.asking == PeerAsking::ForkHeader => true, + _ => false, + }; + + if is_fork_header_request { + return SyncHandler::on_peer_fork_header(sync, io, peer_id, r); + } + + sync.clear_peer_download(peer_id); + let expected_hash = sync.peers.get(&peer_id).and_then(|p| p.asking_hash); + let allowed = sync.peers.get(&peer_id).map(|p| p.is_allowed()).unwrap_or(false); + let block_set = sync.peers.get(&peer_id).and_then(|p| p.block_set).unwrap_or(BlockSet::NewBlocks); + if !sync.reset_peer_asking(peer_id, PeerAsking::BlockHeaders) || expected_hash.is_none() || !allowed { + trace!(target: "sync", "{}: Ignored unexpected headers, expected_hash = {:?}", peer_id, expected_hash); + sync.continue_sync(io); + return Ok(()); + } + let item_count = r.item_count()?; + trace!(target: "sync", "{} -> BlockHeaders ({} entries), state = {:?}, set = {:?}", peer_id, item_count, sync.state, block_set); + if (sync.state == SyncState::Idle || sync.state == SyncState::WaitingPeers) && sync.old_blocks.is_none() { + trace!(target: "sync", "Ignored unexpected block headers"); + sync.continue_sync(io); + return Ok(()); + } + if sync.state == SyncState::Waiting { + trace!(target: "sync", "Ignored block headers while waiting"); + sync.continue_sync(io); + return Ok(()); + } + + let result = { + let downloader = match block_set { + BlockSet::NewBlocks => &mut sync.new_blocks, + BlockSet::OldBlocks => { + match sync.old_blocks { + None => { + trace!(target: "sync", "Ignored block headers while block download is inactive"); + sync.continue_sync(io); + return Ok(()); + }, + Some(ref mut blocks) => blocks, + } + } + }; + downloader.import_headers(io, r, expected_hash) + }; + + match result { + Err(DownloaderImportError::Useless) => { + sync.deactivate_peer(io, peer_id); + }, + Err(DownloaderImportError::Invalid) => { + io.disable_peer(peer_id); + sync.deactivate_peer(io, peer_id); + sync.continue_sync(io); + return Ok(()); + }, + Ok(DownloadAction::Reset) => { + // mark all outstanding requests as expired + trace!("Resetting downloads for {:?}", block_set); + for (_, ref mut p) in sync.peers.iter_mut().filter(|&(_, ref p)| p.block_set == Some(block_set)) { + p.reset_asking(); + } + + } + Ok(DownloadAction::None) => {}, + } + + sync.collect_blocks(io, block_set); + // give a task to the same peer first if received valuable headers. + sync.sync_peer(io, peer_id, false); + // give tasks to other peers + sync.continue_sync(io); + Ok(()) + } + + /// Called by peer once it has new block receipts + fn on_peer_block_receipts(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + sync.clear_peer_download(peer_id); + let block_set = sync.peers.get(&peer_id).and_then(|p| p.block_set).unwrap_or(BlockSet::NewBlocks); + if !sync.reset_peer_asking(peer_id, PeerAsking::BlockReceipts) { + trace!(target: "sync", "{}: Ignored unexpected receipts", peer_id); + sync.continue_sync(io); + return Ok(()); + } + let item_count = r.item_count()?; + trace!(target: "sync", "{} -> BlockReceipts ({} entries)", peer_id, item_count); + if item_count == 0 { + sync.deactivate_peer(io, peer_id); + } + else if sync.state == SyncState::Waiting { + trace!(target: "sync", "Ignored block receipts while waiting"); + } + else + { + let result = { + let downloader = match block_set { + BlockSet::NewBlocks => &mut sync.new_blocks, + BlockSet::OldBlocks => match sync.old_blocks { + None => { + trace!(target: "sync", "Ignored block headers while block download is inactive"); + sync.continue_sync(io); + return Ok(()); + }, + Some(ref mut blocks) => blocks, + } + }; + downloader.import_receipts(io, r) + }; + + match result { + Err(DownloaderImportError::Invalid) => { + io.disable_peer(peer_id); + sync.deactivate_peer(io, peer_id); + sync.continue_sync(io); + return Ok(()); + }, + Err(DownloaderImportError::Useless) => { + sync.deactivate_peer(io, peer_id); + }, + Ok(()) => (), + } + + sync.collect_blocks(io, block_set); + sync.sync_peer(io, peer_id, false); + } + sync.continue_sync(io); + Ok(()) + } + + /// Called when snapshot manifest is downloaded from a peer. + fn on_snapshot_manifest(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + if !sync.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { + trace!(target: "sync", "Ignoring snapshot manifest from unconfirmed peer {}", peer_id); + return Ok(()); + } + sync.clear_peer_download(peer_id); + if !sync.reset_peer_asking(peer_id, PeerAsking::SnapshotManifest) || sync.state != SyncState::SnapshotManifest { + trace!(target: "sync", "{}: Ignored unexpected/expired manifest", peer_id); + sync.continue_sync(io); + return Ok(()); + } + + let manifest_rlp = r.at(0)?; + let manifest = match ManifestData::from_rlp(manifest_rlp.as_raw()) { + Err(e) => { + trace!(target: "sync", "{}: Ignored bad manifest: {:?}", peer_id, e); + io.disable_peer(peer_id); + sync.continue_sync(io); + return Ok(()); + } + Ok(manifest) => manifest, + }; + + let is_supported_version = io.snapshot_service().supported_versions() + .map_or(false, |(l, h)| manifest.version >= l && manifest.version <= h); + + if !is_supported_version { + trace!(target: "sync", "{}: Snapshot manifest version not supported: {}", peer_id, manifest.version); + io.disable_peer(peer_id); + sync.continue_sync(io); + return Ok(()); + } + sync.snapshot.reset_to(&manifest, &keccak(manifest_rlp.as_raw())); + io.snapshot_service().begin_restore(manifest); + sync.state = SyncState::SnapshotData; + + // give a task to the same peer first. + sync.sync_peer(io, peer_id, false); + // give tasks to other peers + sync.continue_sync(io); + Ok(()) + } + + /// Called when snapshot data is downloaded from a peer. + fn on_snapshot_data(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + if !sync.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { + trace!(target: "sync", "Ignoring snapshot data from unconfirmed peer {}", peer_id); + return Ok(()); + } + sync.clear_peer_download(peer_id); + if !sync.reset_peer_asking(peer_id, PeerAsking::SnapshotData) || (sync.state != SyncState::SnapshotData && sync.state != SyncState::SnapshotWaiting) { + trace!(target: "sync", "{}: Ignored unexpected snapshot data", peer_id); + sync.continue_sync(io); + return Ok(()); + } + + // check service status + let status = io.snapshot_service().status(); + match status { + RestorationStatus::Inactive | RestorationStatus::Failed => { + trace!(target: "sync", "{}: Snapshot restoration aborted", peer_id); + sync.state = SyncState::WaitingPeers; + + // only note bad if restoration failed. + if let (Some(hash), RestorationStatus::Failed) = (sync.snapshot.snapshot_hash(), status) { + trace!(target: "sync", "Noting snapshot hash {} as bad", hash); + sync.snapshot.note_bad(hash); + } + + sync.snapshot.clear(); + sync.continue_sync(io); + return Ok(()); + }, + RestorationStatus::Ongoing { .. } => { + trace!(target: "sync", "{}: Snapshot restoration is ongoing", peer_id); + }, + } + + let snapshot_data: Bytes = r.val_at(0)?; + match sync.snapshot.validate_chunk(&snapshot_data) { + Ok(ChunkType::Block(hash)) => { + trace!(target: "sync", "{}: Processing block chunk", peer_id); + io.snapshot_service().restore_block_chunk(hash, snapshot_data); + } + Ok(ChunkType::State(hash)) => { + trace!(target: "sync", "{}: Processing state chunk", peer_id); + io.snapshot_service().restore_state_chunk(hash, snapshot_data); + } + Err(()) => { + trace!(target: "sync", "{}: Got bad snapshot chunk", peer_id); + io.disconnect_peer(peer_id); + sync.continue_sync(io); + return Ok(()); + } + } + + if sync.snapshot.is_complete() { + // wait for snapshot restoration process to complete + sync.state = SyncState::SnapshotWaiting; + } + // give a task to the same peer first. + sync.sync_peer(io, peer_id, false); + // give tasks to other peers + sync.continue_sync(io); + Ok(()) + } + + /// Called by peer to report status + fn on_peer_status(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + sync.handshaking_peers.remove(&peer_id); + let protocol_version: u8 = r.val_at(0)?; + let warp_protocol = io.protocol_version(&WARP_SYNC_PROTOCOL_ID, peer_id) != 0; + let peer = PeerInfo { + protocol_version: protocol_version, + network_id: r.val_at(1)?, + difficulty: Some(r.val_at(2)?), + latest_hash: r.val_at(3)?, + genesis: r.val_at(4)?, + asking: PeerAsking::Nothing, + asking_blocks: Vec::new(), + asking_hash: None, + ask_time: Instant::now(), + last_sent_transactions: HashSet::new(), + expired: false, + confirmation: if sync.fork_block.is_none() { ForkConfirmation::Confirmed } else { ForkConfirmation::Unconfirmed }, + asking_snapshot_data: None, + snapshot_hash: if warp_protocol { Some(r.val_at(5)?) } else { None }, + snapshot_number: if warp_protocol { Some(r.val_at(6)?) } else { None }, + block_set: None, + }; + + trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{}, snapshot:{:?})", + peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest_hash, peer.genesis, peer.snapshot_number); + if io.is_expired() { + trace!(target: "sync", "Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id)); + return Ok(()); + } + + if sync.peers.contains_key(&peer_id) { + debug!(target: "sync", "Unexpected status packet from {}:{}", peer_id, io.peer_info(peer_id)); + return Ok(()); + } + let chain_info = io.chain().chain_info(); + if peer.genesis != chain_info.genesis_hash { + io.disable_peer(peer_id); + trace!(target: "sync", "Peer {} genesis hash mismatch (ours: {}, theirs: {})", peer_id, chain_info.genesis_hash, peer.genesis); + return Ok(()); + } + if peer.network_id != sync.network_id { + io.disable_peer(peer_id); + trace!(target: "sync", "Peer {} network id mismatch (ours: {}, theirs: {})", peer_id, sync.network_id, peer.network_id); + return Ok(()); + } + if (warp_protocol && peer.protocol_version != PAR_PROTOCOL_VERSION_1 && peer.protocol_version != PAR_PROTOCOL_VERSION_2 && peer.protocol_version != PAR_PROTOCOL_VERSION_3) + || (!warp_protocol && peer.protocol_version != ETH_PROTOCOL_VERSION_63 && peer.protocol_version != ETH_PROTOCOL_VERSION_62) { + io.disable_peer(peer_id); + trace!(target: "sync", "Peer {} unsupported eth protocol ({})", peer_id, peer.protocol_version); + return Ok(()); + } + + if sync.sync_start_time.is_none() { + sync.sync_start_time = Some(Instant::now()); + } + + sync.peers.insert(peer_id.clone(), peer); + // Don't activate peer immediatelly when searching for common block. + // Let the current sync round complete first. + sync.active_peers.insert(peer_id.clone()); + debug!(target: "sync", "Connected {}:{}", peer_id, io.peer_info(peer_id)); + if let Some((fork_block, _)) = sync.fork_block { + SyncRequester::request_fork_header(sync, io, peer_id, fork_block); + } else { + SyncHandler::on_peer_confirmed(sync, io, peer_id); + } + Ok(()) + } + + /// Called when peer sends us new transactions + fn on_peer_transactions(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + // Accept transactions only when fully synced + if !io.is_chain_queue_empty() || (sync.state != SyncState::Idle && sync.state != SyncState::NewBlocks) { + trace!(target: "sync", "{} Ignoring transactions while syncing", peer_id); + return Ok(()); + } + if !sync.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { + trace!(target: "sync", "{} Ignoring transactions from unconfirmed/unknown peer", peer_id); + return Ok(()); + } + + let item_count = r.item_count()?; + trace!(target: "sync", "{:02} -> Transactions ({} entries)", peer_id, item_count); + let mut transactions = Vec::with_capacity(item_count); + for i in 0 .. item_count { + let rlp = r.at(i)?; + let tx = rlp.as_raw().to_vec(); + transactions.push(tx); + } + io.chain().queue_transactions(transactions, peer_id); + Ok(()) + } + + /// Called when peer sends us signed private transaction packet + fn on_signed_private_transaction(sync: &ChainSync, _io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + if !sync.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { + trace!(target: "sync", "{} Ignoring packet from unconfirmed/unknown peer", peer_id); + return Ok(()); + } + + trace!(target: "sync", "Received signed private transaction packet from {:?}", peer_id); + if let Err(e) = sync.private_tx_handler.import_signed_private_transaction(r.as_raw()) { + trace!(target: "sync", "Ignoring the message, error queueing: {}", e); + } + Ok(()) + } + + /// Called when peer sends us new private transaction packet + fn on_private_transaction(sync: &ChainSync, _io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + if !sync.peers.get(&peer_id).map_or(false, |p| p.can_sync()) { + trace!(target: "sync", "{} Ignoring packet from unconfirmed/unknown peer", peer_id); + return Ok(()); + } + + trace!(target: "sync", "Received private transaction packet from {:?}", peer_id); + + if let Err(e) = sync.private_tx_handler.import_private_transaction(r.as_raw()) { + trace!(target: "sync", "Ignoring the message, error queueing: {}", e); + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use ethcore::client::{ChainInfo, EachBlockWith, TestBlockChainClient}; + use parking_lot::RwLock; + use rlp::{Rlp}; + use std::collections::{VecDeque}; + use tests::helpers::{TestIo}; + use tests::snapshot::TestSnapshotService; + + use super::*; + use super::super::tests::{ + dummy_sync_with_peer, + get_dummy_block, + get_dummy_blocks, + get_dummy_hashes, + }; + + #[test] + fn handles_peer_new_hashes() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(10, EachBlockWith::Uncle); + let queue = RwLock::new(VecDeque::new()); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + let hashes_data = get_dummy_hashes(); + let hashes_rlp = Rlp::new(&hashes_data); + + let result = SyncHandler::on_peer_new_hashes(&mut sync, &mut io, 0, &hashes_rlp); + + assert!(result.is_ok()); + } + + #[test] + fn handles_peer_new_block_malformed() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(10, EachBlockWith::Uncle); + + let block_data = get_dummy_block(11, client.chain_info().best_block_hash); + + let queue = RwLock::new(VecDeque::new()); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + //sync.have_common_block = true; + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + let block = Rlp::new(&block_data); + + let result = SyncHandler::on_peer_new_block(&mut sync, &mut io, 0, &block); + + assert!(result.is_err()); + } + + #[test] + fn handles_peer_new_block() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(10, EachBlockWith::Uncle); + + let block_data = get_dummy_blocks(11, client.chain_info().best_block_hash); + + let queue = RwLock::new(VecDeque::new()); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + let block = Rlp::new(&block_data); + + let result = SyncHandler::on_peer_new_block(&mut sync, &mut io, 0, &block); + + assert!(result.is_ok()); + } + + #[test] + fn handles_peer_new_block_empty() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(10, EachBlockWith::Uncle); + let queue = RwLock::new(VecDeque::new()); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + let empty_data = vec![]; + let block = Rlp::new(&empty_data); + + let result = SyncHandler::on_peer_new_block(&mut sync, &mut io, 0, &block); + + assert!(result.is_err()); + } + + #[test] + fn handles_peer_new_hashes_empty() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(10, EachBlockWith::Uncle); + let queue = RwLock::new(VecDeque::new()); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + let empty_hashes_data = vec![]; + let hashes_rlp = Rlp::new(&empty_hashes_data); + + let result = SyncHandler::on_peer_new_hashes(&mut sync, &mut io, 0, &hashes_rlp); + + assert!(result.is_ok()); + } +} diff --git a/ethcore/sync/src/chain/mod.rs b/ethcore/sync/src/chain/mod.rs new file mode 100644 index 00000000000..abab1da9413 --- /dev/null +++ b/ethcore/sync/src/chain/mod.rs @@ -0,0 +1,1379 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! `BlockChain` synchronization strategy. +//! Syncs to peers and keeps up to date. +//! This implementation uses ethereum protocol v63 +//! +//! Syncing strategy summary. +//! Split the chain into ranges of N blocks each. Download ranges sequentially. Split each range into subchains of M blocks. Download subchains in parallel. +//! State. +//! Sync state consists of the following data: +//! - s: State enum which can be one of the following values: `ChainHead`, `Blocks`, `Idle` +//! - H: A set of downloaded block headers +//! - B: A set of downloaded block bodies +//! - S: Set of block subchain start block hashes to download. +//! - l: Last imported / common block hash +//! - P: A set of connected peers. For each peer we maintain its last known total difficulty and starting block hash being requested if any. +//! General behaviour. +//! We start with all sets empty, l is set to the best block in the block chain, s is set to `ChainHead`. +//! If at any moment a bad block is reported by the block queue, we set s to `ChainHead`, reset l to the best block in the block chain and clear H, B and S. +//! If at any moment P becomes empty, we set s to `ChainHead`, and clear H, B and S. +//! +//! Workflow for `ChainHead` state. +//! In this state we try to get subchain headers with a single `GetBlockHeaders` request. +//! On `NewPeer` / On `Restart`: +//! If peer's total difficulty is higher and there are less than 5 peers downloading, request N/M headers with interval M+1 starting from l +//! On `BlockHeaders(R)`: +//! If R is empty: +//! If l is equal to genesis block hash or l is more than 1000 blocks behind our best hash: +//! Remove current peer from P. set l to the best block in the block chain. Select peer with maximum total difficulty from P and restart. +//! Else +//! Set l to l’s parent and restart. +//! Else if we already have all the headers in the block chain or the block queue: +//! Set s to `Idle`, +//! Else +//! Set S to R, set s to `Blocks`. +//! +//! All other messages are ignored. +//! +//! Workflow for `Blocks` state. +//! In this state we download block headers and bodies from multiple peers. +//! On `NewPeer` / On `Restart`: +//! For all idle peers: +//! Find a set of 256 or less block hashes in H which are not in B and not being downloaded by other peers. If the set is not empty: +//! Request block bodies for the hashes in the set. +//! Else +//! Find an element in S which is not being downloaded by other peers. If found: Request M headers starting from the element. +//! +//! On `BlockHeaders(R)`: +//! If R is empty remove current peer from P and restart. +//! Validate received headers: +//! For each header find a parent in H or R or the blockchain. Restart if there is a block with unknown parent. +//! Find at least one header from the received list in S. Restart if there is none. +//! Go to `CollectBlocks`. +//! +//! On `BlockBodies(R)`: +//! If R is empty remove current peer from P and restart. +//! Add bodies with a matching header in H to B. +//! Go to `CollectBlocks`. +//! +//! `CollectBlocks`: +//! Find a chain of blocks C in H starting from h where h’s parent equals to l. The chain ends with the first block which does not have a body in B. +//! Add all blocks from the chain to the block queue. Remove them from H and B. Set l to the hash of the last block from C. +//! Update and merge subchain heads in S. For each h in S find a chain of blocks in B starting from h. Remove h from S. if the chain does not include an element from S add the end of the chain to S. +//! If H is empty and S contains a single element set s to `ChainHead`. +//! Restart. +//! +//! All other messages are ignored. +//! Workflow for Idle state. +//! On `NewBlock`: +//! Import the block. If the block is unknown set s to `ChainHead` and restart. +//! On `NewHashes`: +//! Set s to `ChainHead` and restart. +//! +//! All other messages are ignored. + +mod handler; +mod propagator; +mod requester; +mod supplier; + +use std::sync::Arc; +use std::collections::{HashSet, HashMap}; +use std::cmp; +use std::time::{Duration, Instant}; +use hash::keccak; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, U256}; +use plain_hasher::H256FastMap; +use parking_lot::RwLock; +use bytes::Bytes; +use rlp::{Rlp, RlpStream, DecoderError}; +use network::{self, PeerId, PacketId}; +use ethcore::header::{BlockNumber}; +use ethcore::client::{BlockChainClient, BlockStatus, BlockId, BlockChainInfo, BlockQueueInfo}; +use ethcore::snapshot::{RestorationStatus}; +use sync_io::SyncIo; +use super::{WarpSync, SyncConfig}; +use block_sync::{BlockDownloader, BlockDownloaderImportError as DownloaderImportError}; +use rand::Rng; +use snapshot::{Snapshot}; +use api::{EthProtocolInfo as PeerInfoDigest, WARP_SYNC_PROTOCOL_ID}; +use private_tx::PrivateTxHandler; +use transactions_stats::{TransactionsStats, Stats as TransactionStats}; +use transaction::UnverifiedTransaction; + +use self::handler::SyncHandler; +use self::propagator::SyncPropagator; +use self::requester::SyncRequester; +use self::supplier::SyncSupplier; + +known_heap_size!(0, PeerInfo); + +pub type PacketDecodeError = DecoderError; + +/// 63 version of Ethereum protocol. +pub const ETH_PROTOCOL_VERSION_63: u8 = 63; +/// 62 version of Ethereum protocol. +pub const ETH_PROTOCOL_VERSION_62: u8 = 62; +/// 1 version of Parity protocol. +pub const PAR_PROTOCOL_VERSION_1: u8 = 1; +/// 2 version of Parity protocol (consensus messages added). +pub const PAR_PROTOCOL_VERSION_2: u8 = 2; +/// 3 version of Parity protocol (private transactions messages added). +pub const PAR_PROTOCOL_VERSION_3: u8 = 3; + +pub const MAX_BODIES_TO_SEND: usize = 256; +pub const MAX_HEADERS_TO_SEND: usize = 512; +pub const MAX_NODE_DATA_TO_SEND: usize = 1024; +pub const MAX_RECEIPTS_TO_SEND: usize = 1024; +pub const MAX_RECEIPTS_HEADERS_TO_SEND: usize = 256; +const MIN_PEERS_PROPAGATION: usize = 4; +const MAX_PEERS_PROPAGATION: usize = 128; +const MAX_PEER_LAG_PROPAGATION: BlockNumber = 20; +const MAX_NEW_HASHES: usize = 64; +const MAX_NEW_BLOCK_AGE: BlockNumber = 20; +// maximal packet size with transactions (cannot be greater than 16MB - protocol limitation). +const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024; +// Maximal number of transactions in sent in single packet. +const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64; +// Min number of blocks to be behind for a snapshot sync +const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000; +const SNAPSHOT_MIN_PEERS: usize = 3; + +const STATUS_PACKET: u8 = 0x00; +const NEW_BLOCK_HASHES_PACKET: u8 = 0x01; +const TRANSACTIONS_PACKET: u8 = 0x02; +pub const GET_BLOCK_HEADERS_PACKET: u8 = 0x03; +pub const BLOCK_HEADERS_PACKET: u8 = 0x04; +pub const GET_BLOCK_BODIES_PACKET: u8 = 0x05; +const BLOCK_BODIES_PACKET: u8 = 0x06; +const NEW_BLOCK_PACKET: u8 = 0x07; + +pub const GET_NODE_DATA_PACKET: u8 = 0x0d; +pub const NODE_DATA_PACKET: u8 = 0x0e; +pub const GET_RECEIPTS_PACKET: u8 = 0x0f; +pub const RECEIPTS_PACKET: u8 = 0x10; + +pub const ETH_PACKET_COUNT: u8 = 0x11; + +pub const GET_SNAPSHOT_MANIFEST_PACKET: u8 = 0x11; +pub const SNAPSHOT_MANIFEST_PACKET: u8 = 0x12; +pub const GET_SNAPSHOT_DATA_PACKET: u8 = 0x13; +pub const SNAPSHOT_DATA_PACKET: u8 = 0x14; +pub const CONSENSUS_DATA_PACKET: u8 = 0x15; +const PRIVATE_TRANSACTION_PACKET: u8 = 0x16; +const SIGNED_PRIVATE_TRANSACTION_PACKET: u8 = 0x17; + +pub const SNAPSHOT_SYNC_PACKET_COUNT: u8 = 0x18; + +const MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD: usize = 3; + +const WAIT_PEERS_TIMEOUT: Duration = Duration::from_secs(5); +const STATUS_TIMEOUT: Duration = Duration::from_secs(5); +const HEADERS_TIMEOUT: Duration = Duration::from_secs(15); +const BODIES_TIMEOUT: Duration = Duration::from_secs(20); +const RECEIPTS_TIMEOUT: Duration = Duration::from_secs(10); +const FORK_HEADER_TIMEOUT: Duration = Duration::from_secs(3); +const SNAPSHOT_MANIFEST_TIMEOUT: Duration = Duration::from_secs(5); +const SNAPSHOT_DATA_TIMEOUT: Duration = Duration::from_secs(120); + +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +/// Sync state +pub enum SyncState { + /// Collecting enough peers to start syncing. + WaitingPeers, + /// Waiting for snapshot manifest download + SnapshotManifest, + /// Downloading snapshot data + SnapshotData, + /// Waiting for snapshot restoration progress. + SnapshotWaiting, + /// Downloading new blocks + Blocks, + /// Initial chain sync complete. Waiting for new packets + Idle, + /// Block downloading paused. Waiting for block queue to process blocks and free some space + Waiting, + /// Downloading blocks learned from `NewHashes` packet + NewBlocks, +} + +/// Syncing status and statistics +#[derive(Clone, Copy)] +pub struct SyncStatus { + /// State + pub state: SyncState, + /// Syncing protocol version. That's the maximum protocol version we connect to. + pub protocol_version: u8, + /// The underlying p2p network version. + pub network_id: u64, + /// `BlockChain` height for the moment the sync started. + pub start_block_number: BlockNumber, + /// Last fully downloaded and imported block number (if any). + pub last_imported_block_number: Option, + /// Highest block number in the download queue (if any). + pub highest_block_number: Option, + /// Total number of blocks for the sync process. + pub blocks_total: BlockNumber, + /// Number of blocks downloaded so far. + pub blocks_received: BlockNumber, + /// Total number of connected peers + pub num_peers: usize, + /// Total number of active peers. + pub num_active_peers: usize, + /// Heap memory used in bytes. + pub mem_used: usize, + /// Snapshot chunks + pub num_snapshot_chunks: usize, + /// Snapshot chunks downloaded + pub snapshot_chunks_done: usize, + /// Last fully downloaded and imported ancient block number (if any). + pub last_imported_old_block_number: Option, +} + +impl SyncStatus { + /// Indicates if snapshot download is in progress + pub fn is_snapshot_syncing(&self) -> bool { + self.state == SyncState::SnapshotManifest + || self.state == SyncState::SnapshotData + || self.state == SyncState::SnapshotWaiting + } + + /// Returns max no of peers to display in informants + pub fn current_max_peers(&self, min_peers: u32, max_peers: u32) -> u32 { + if self.num_peers as u32 > min_peers { + max_peers + } else { + min_peers + } + } + + /// Is it doing a major sync? + pub fn is_syncing(&self, queue_info: BlockQueueInfo) -> bool { + let is_syncing_state = match self.state { SyncState::Idle | SyncState::NewBlocks => false, _ => true }; + let is_verifying = queue_info.unverified_queue_size + queue_info.verified_queue_size > 3; + is_verifying || is_syncing_state + } +} + +#[derive(PartialEq, Eq, Debug, Clone)] +/// Peer data type requested +pub enum PeerAsking { + Nothing, + ForkHeader, + BlockHeaders, + BlockBodies, + BlockReceipts, + SnapshotManifest, + SnapshotData, +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +/// Block downloader channel. +pub enum BlockSet { + /// New blocks better than out best blocks + NewBlocks, + /// Missing old blocks + OldBlocks, +} +#[derive(Clone, Eq, PartialEq)] +pub enum ForkConfirmation { + /// Fork block confirmation pending. + Unconfirmed, + /// Fork is confirmed. + Confirmed, +} + +#[derive(Clone)] +/// Syncing peer information +pub struct PeerInfo { + /// eth protocol version + protocol_version: u8, + /// Peer chain genesis hash + genesis: H256, + /// Peer network id + network_id: u64, + /// Peer best block hash + latest_hash: H256, + /// Peer total difficulty if known + difficulty: Option, + /// Type of data currenty being requested from peer. + asking: PeerAsking, + /// A set of block numbers being requested + asking_blocks: Vec, + /// Holds requested header hash if currently requesting block header by hash + asking_hash: Option, + /// Holds requested snapshot chunk hash if any. + asking_snapshot_data: Option, + /// Request timestamp + ask_time: Instant, + /// Holds a set of transactions recently sent to this peer to avoid spamming. + last_sent_transactions: HashSet, + /// Pending request is expired and result should be ignored + expired: bool, + /// Peer fork confirmation status + confirmation: ForkConfirmation, + /// Best snapshot hash + snapshot_hash: Option, + /// Best snapshot block number + snapshot_number: Option, + /// Block set requested + block_set: Option, +} + +impl PeerInfo { + fn can_sync(&self) -> bool { + self.confirmation == ForkConfirmation::Confirmed && !self.expired + } + + fn is_allowed(&self) -> bool { + self.confirmation != ForkConfirmation::Unconfirmed && !self.expired + } + + fn reset_asking(&mut self) { + self.asking_blocks.clear(); + self.asking_hash = None; + // mark any pending requests as expired + if self.asking != PeerAsking::Nothing && self.is_allowed() { + self.expired = true; + } + } +} + +#[cfg(not(test))] +pub mod random { + use rand; + pub fn new() -> rand::ThreadRng { rand::thread_rng() } +} +#[cfg(test)] +pub mod random { + use rand::{self, SeedableRng}; + pub fn new() -> rand::XorShiftRng { rand::XorShiftRng::from_seed([0, 1, 2, 3]) } +} + +pub type RlpResponseResult = Result, PacketDecodeError>; +pub type Peers = HashMap; + +/// Blockchain sync handler. +/// See module documentation for more details. +pub struct ChainSync { + /// Sync state + state: SyncState, + /// Last block number for the start of sync + starting_block: BlockNumber, + /// Highest block number seen + highest_block: Option, + /// All connected peers + peers: Peers, + /// Peers active for current sync round + active_peers: HashSet, + /// Block download process for new blocks + new_blocks: BlockDownloader, + /// Block download process for ancient blocks + old_blocks: Option, + /// Last propagated block number + last_sent_block_number: BlockNumber, + /// Network ID + network_id: u64, + /// Optional fork block to check + fork_block: Option<(BlockNumber, H256)>, + /// Snapshot downloader. + snapshot: Snapshot, + /// Connected peers pending Status message. + /// Value is request timestamp. + handshaking_peers: HashMap, + /// Sync start timestamp. Measured when first peer is connected + sync_start_time: Option, + /// Transactions propagation statistics + transactions_stats: TransactionsStats, + /// Enable ancient block downloading + download_old_blocks: bool, + /// Shared private tx service. + private_tx_handler: Arc, + /// Enable warp sync. + warp_sync: WarpSync, +} + +impl ChainSync { + /// Create a new instance of syncing strategy. + pub fn new(config: SyncConfig, chain: &BlockChainClient, private_tx_handler: Arc) -> ChainSync { + let chain_info = chain.chain_info(); + let best_block = chain.chain_info().best_block_number; + let state = ChainSync::get_init_state(config.warp_sync, chain); + + let mut sync = ChainSync { + state, + starting_block: best_block, + highest_block: None, + peers: HashMap::new(), + handshaking_peers: HashMap::new(), + active_peers: HashSet::new(), + new_blocks: BlockDownloader::new(false, &chain_info.best_block_hash, chain_info.best_block_number), + old_blocks: None, + last_sent_block_number: 0, + network_id: config.network_id, + fork_block: config.fork_block, + download_old_blocks: config.download_old_blocks, + snapshot: Snapshot::new(), + sync_start_time: None, + transactions_stats: TransactionsStats::default(), + private_tx_handler, + warp_sync: config.warp_sync, + }; + sync.update_targets(chain); + sync + } + + fn get_init_state(warp_sync: WarpSync, chain: &BlockChainClient) -> SyncState { + let best_block = chain.chain_info().best_block_number; + match warp_sync { + WarpSync::Enabled => SyncState::WaitingPeers, + WarpSync::OnlyAndAfter(block) if block > best_block => SyncState::WaitingPeers, + _ => SyncState::Idle, + } + } + + /// Returns synchonization status + pub fn status(&self) -> SyncStatus { + let last_imported_number = self.new_blocks.last_imported_block_number(); + SyncStatus { + state: self.state.clone(), + protocol_version: ETH_PROTOCOL_VERSION_63, + network_id: self.network_id, + start_block_number: self.starting_block, + last_imported_block_number: Some(last_imported_number), + last_imported_old_block_number: self.old_blocks.as_ref().map(|d| d.last_imported_block_number()), + highest_block_number: self.highest_block.map(|n| cmp::max(n, last_imported_number)), + blocks_received: if last_imported_number > self.starting_block { last_imported_number - self.starting_block } else { 0 }, + blocks_total: match self.highest_block { Some(x) if x > self.starting_block => x - self.starting_block, _ => 0 }, + num_peers: self.peers.values().filter(|p| p.is_allowed()).count(), + num_active_peers: self.peers.values().filter(|p| p.is_allowed() && p.asking != PeerAsking::Nothing).count(), + num_snapshot_chunks: self.snapshot.total_chunks(), + snapshot_chunks_done: self.snapshot.done_chunks(), + mem_used: + self.new_blocks.heap_size() + + self.old_blocks.as_ref().map_or(0, |d| d.heap_size()) + + self.peers.heap_size_of_children(), + } + } + + /// Returns information on peers connections + pub fn peer_info(&self, peer_id: &PeerId) -> Option { + self.peers.get(peer_id).map(|peer_data| { + PeerInfoDigest { + version: peer_data.protocol_version as u32, + difficulty: peer_data.difficulty, + head: peer_data.latest_hash, + } + }) + } + + /// Returns transactions propagation statistics + pub fn transactions_stats(&self) -> &H256FastMap { + self.transactions_stats.stats() + } + + /// Updates transactions were received by a peer + pub fn transactions_received(&mut self, txs: &[UnverifiedTransaction], peer_id: PeerId) { + if let Some(peer_info) = self.peers.get_mut(&peer_id) { + peer_info.last_sent_transactions.extend(txs.iter().map(|tx| tx.hash())); + } + } + + /// Abort all sync activity + pub fn abort(&mut self, io: &mut SyncIo) { + self.reset_and_continue(io); + self.peers.clear(); + } + + /// Reset sync. Clear all downloaded data but keep the queue + fn reset(&mut self, io: &mut SyncIo) { + self.new_blocks.reset(); + let chain_info = io.chain().chain_info(); + for (_, ref mut p) in &mut self.peers { + if p.block_set != Some(BlockSet::OldBlocks) { + p.reset_asking(); + if p.difficulty.is_none() { + // assume peer has up to date difficulty + p.difficulty = Some(chain_info.pending_total_difficulty); + } + } + } + self.state = ChainSync::get_init_state(self.warp_sync, io.chain()); + // Reactivate peers only if some progress has been made + // since the last sync round of if starting fresh. + self.active_peers = self.peers.keys().cloned().collect(); + } + + /// Restart sync + pub fn reset_and_continue(&mut self, io: &mut SyncIo) { + trace!(target: "sync", "Restarting"); + if self.state == SyncState::SnapshotData { + debug!(target:"sync", "Aborting snapshot restore"); + io.snapshot_service().abort_restore(); + } + self.snapshot.clear(); + self.reset(io); + self.continue_sync(io); + } + + /// Remove peer from active peer set. Peer will be reactivated on the next sync + /// round. + fn deactivate_peer(&mut self, _io: &mut SyncIo, peer_id: PeerId) { + trace!(target: "sync", "Deactivating peer {}", peer_id); + self.active_peers.remove(&peer_id); + } + + fn maybe_start_snapshot_sync(&mut self, io: &mut SyncIo) { + if !self.warp_sync.is_enabled() || io.snapshot_service().supported_versions().is_none() { + trace!(target: "sync", "Skipping warp sync. Disabled or not supported."); + return; + } + if self.state != SyncState::WaitingPeers && self.state != SyncState::Blocks && self.state != SyncState::Waiting { + trace!(target: "sync", "Skipping warp sync. State: {:?}", self.state); + return; + } + // Make sure the snapshot block is not too far away from best block and network best block and + // that it is higher than fork detection block + let our_best_block = io.chain().chain_info().best_block_number; + let fork_block = self.fork_block.map_or(0, |(n, _)| n); + + let (best_hash, max_peers, snapshot_peers) = { + let expected_warp_block = match self.warp_sync { + WarpSync::OnlyAndAfter(block) => block, + _ => 0, + }; + //collect snapshot infos from peers + let snapshots = self.peers.iter() + .filter(|&(_, p)| p.is_allowed() && p.snapshot_number.map_or(false, |sn| + // Snapshot must be old enough that it's usefull to sync with it + our_best_block < sn && (sn - our_best_block) > SNAPSHOT_RESTORE_THRESHOLD && + // Snapshot must have been taken after the Fork + sn > fork_block && + // Snapshot must be greater than the warp barrier if any + sn > expected_warp_block && + // If we know a highest block, snapshot must be recent enough + self.highest_block.map_or(true, |highest| { + highest < sn || (highest - sn) <= SNAPSHOT_RESTORE_THRESHOLD + }) + )) + .filter_map(|(p, peer)| peer.snapshot_hash.map(|hash| (p, hash.clone()))) + .filter(|&(_, ref hash)| !self.snapshot.is_known_bad(hash)); + + let mut snapshot_peers = HashMap::new(); + let mut max_peers: usize = 0; + let mut best_hash = None; + for (p, hash) in snapshots { + let peers = snapshot_peers.entry(hash).or_insert_with(Vec::new); + peers.push(*p); + if peers.len() > max_peers { + max_peers = peers.len(); + best_hash = Some(hash); + } + } + (best_hash, max_peers, snapshot_peers) + }; + + let timeout = (self.state == SyncState::WaitingPeers) && self.sync_start_time.map_or(false, |t| t.elapsed() > WAIT_PEERS_TIMEOUT); + + if let (Some(hash), Some(peers)) = (best_hash, best_hash.map_or(None, |h| snapshot_peers.get(&h))) { + if max_peers >= SNAPSHOT_MIN_PEERS { + trace!(target: "sync", "Starting confirmed snapshot sync {:?} with {:?}", hash, peers); + self.start_snapshot_sync(io, peers); + } else if timeout { + trace!(target: "sync", "Starting unconfirmed snapshot sync {:?} with {:?}", hash, peers); + self.start_snapshot_sync(io, peers); + } + } else if timeout && !self.warp_sync.is_warp_only() { + trace!(target: "sync", "No snapshots found, starting full sync"); + self.state = SyncState::Idle; + self.continue_sync(io); + } + } + + fn start_snapshot_sync(&mut self, io: &mut SyncIo, peers: &[PeerId]) { + if !self.snapshot.have_manifest() { + for p in peers { + if self.peers.get(p).map_or(false, |p| p.asking == PeerAsking::Nothing) { + SyncRequester::request_snapshot_manifest(self, io, *p); + } + } + self.state = SyncState::SnapshotManifest; + trace!(target: "sync", "New snapshot sync with {:?}", peers); + } else { + self.state = SyncState::SnapshotData; + trace!(target: "sync", "Resumed snapshot sync with {:?}", peers); + } + } + + /// Restart sync disregarding the block queue status. May end up re-downloading up to QUEUE_SIZE blocks + pub fn restart(&mut self, io: &mut SyncIo) { + self.update_targets(io.chain()); + self.reset_and_continue(io); + } + + /// Update sync after the blockchain has been changed externally. + pub fn update_targets(&mut self, chain: &BlockChainClient) { + // Do not assume that the block queue/chain still has our last_imported_block + let chain = chain.chain_info(); + self.new_blocks = BlockDownloader::new(false, &chain.best_block_hash, chain.best_block_number); + self.old_blocks = None; + if self.download_old_blocks { + if let (Some(ancient_block_hash), Some(ancient_block_number)) = (chain.ancient_block_hash, chain.ancient_block_number) { + + trace!(target: "sync", "Downloading old blocks from {:?} (#{}) till {:?} (#{:?})", ancient_block_hash, ancient_block_number, chain.first_block_hash, chain.first_block_number); + let mut downloader = BlockDownloader::with_unlimited_reorg(true, &ancient_block_hash, ancient_block_number); + if let Some(hash) = chain.first_block_hash { + trace!(target: "sync", "Downloader target set to {:?}", hash); + downloader.set_target(&hash); + } + self.old_blocks = Some(downloader); + } + } + } + + /// Resume downloading + fn continue_sync(&mut self, io: &mut SyncIo) { + // Collect active peers that can sync + let confirmed_peers: Vec<(PeerId, u8)> = self.peers.iter().filter_map(|(peer_id, peer)| + if peer.can_sync() { + Some((*peer_id, peer.protocol_version)) + } else { + None + } + ).collect(); + let mut peers: Vec<(PeerId, u8)> = confirmed_peers.iter().filter(|&&(peer_id, _)| + self.active_peers.contains(&peer_id) + ).map(|v| *v).collect(); + + random::new().shuffle(&mut peers); //TODO: sort by rating + // prefer peers with higher protocol version + peers.sort_by(|&(_, ref v1), &(_, ref v2)| v1.cmp(v2)); + trace!( + target: "sync", + "Syncing with peers: {} active, {} confirmed, {} total", + self.active_peers.len(), confirmed_peers.len(), self.peers.len() + ); + for (peer_id, _) in peers { + self.sync_peer(io, peer_id, false); + } + + if + (self.state == SyncState::Blocks || self.state == SyncState::NewBlocks) && + !self.peers.values().any(|p| p.asking != PeerAsking::Nothing && p.block_set != Some(BlockSet::OldBlocks) && p.can_sync()) + { + self.complete_sync(io); + } + } + + /// Called after all blocks have been downloaded + fn complete_sync(&mut self, io: &mut SyncIo) { + trace!(target: "sync", "Sync complete"); + self.reset(io); + } + + /// Enter waiting state + fn pause_sync(&mut self) { + trace!(target: "sync", "Block queue full, pausing sync"); + self.state = SyncState::Waiting; + } + + /// Find something to do for a peer. Called for a new peer or when a peer is done with its task. + fn sync_peer(&mut self, io: &mut SyncIo, peer_id: PeerId, force: bool) { + if !self.active_peers.contains(&peer_id) { + trace!(target: "sync", "Skipping deactivated peer {}", peer_id); + return; + } + let (peer_latest, peer_difficulty, peer_snapshot_number, peer_snapshot_hash) = { + if let Some(peer) = self.peers.get_mut(&peer_id) { + if peer.asking != PeerAsking::Nothing || !peer.can_sync() { + trace!(target: "sync", "Skipping busy peer {}", peer_id); + return; + } + if self.state == SyncState::Waiting { + trace!(target: "sync", "Waiting for the block queue"); + return; + } + if self.state == SyncState::SnapshotWaiting { + trace!(target: "sync", "Waiting for the snapshot restoration"); + return; + } + (peer.latest_hash.clone(), peer.difficulty.clone(), peer.snapshot_number.as_ref().cloned().unwrap_or(0), peer.snapshot_hash.as_ref().cloned()) + } else { + return; + } + }; + let chain_info = io.chain().chain_info(); + let syncing_difficulty = chain_info.pending_total_difficulty; + let num_active_peers = self.peers.values().filter(|p| p.asking != PeerAsking::Nothing).count(); + + let higher_difficulty = peer_difficulty.map_or(true, |pd| pd > syncing_difficulty); + if force || higher_difficulty || self.old_blocks.is_some() { + match self.state { + SyncState::WaitingPeers => { + trace!( + target: "sync", + "Checking snapshot sync: {} vs {} (peer: {})", + peer_snapshot_number, + chain_info.best_block_number, + peer_id + ); + self.maybe_start_snapshot_sync(io); + }, + SyncState::Idle | SyncState::Blocks | SyncState::NewBlocks => { + if io.chain().queue_info().is_full() { + self.pause_sync(); + return; + } + + let have_latest = io.chain().block_status(BlockId::Hash(peer_latest)) != BlockStatus::Unknown; + trace!(target: "sync", "Considering peer {}, force={}, td={:?}, our td={}, latest={}, have_latest={}, state={:?}", peer_id, force, peer_difficulty, syncing_difficulty, peer_latest, have_latest, self.state); + if !have_latest && (higher_difficulty || force || self.state == SyncState::NewBlocks) { + // check if got new blocks to download + trace!(target: "sync", "Syncing with peer {}, force={}, td={:?}, our td={}, state={:?}", peer_id, force, peer_difficulty, syncing_difficulty, self.state); + if let Some(request) = self.new_blocks.request_blocks(io, num_active_peers) { + SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::NewBlocks); + if self.state == SyncState::Idle { + self.state = SyncState::Blocks; + } + return; + } + } + + if let Some(request) = self.old_blocks.as_mut().and_then(|d| d.request_blocks(io, num_active_peers)) { + SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks); + return; + } + }, + SyncState::SnapshotData => { + if let RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } = io.snapshot_service().status() { + if self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize > MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { + trace!(target: "sync", "Snapshot queue full, pausing sync"); + self.state = SyncState::SnapshotWaiting; + return; + } + } + if peer_snapshot_hash.is_some() && peer_snapshot_hash == self.snapshot.snapshot_hash() { + self.clear_peer_download(peer_id); + SyncRequester::request_snapshot_data(self, io, peer_id); + } + }, + SyncState::SnapshotManifest | //already downloading from other peer + SyncState::Waiting | SyncState::SnapshotWaiting => () + } + } else { + trace!(target: "sync", "Skipping peer {}, force={}, td={:?}, our td={}, state={:?}", peer_id, force, peer_difficulty, syncing_difficulty, self.state); + } + } + + /// Clear all blocks/headers marked as being downloaded by a peer. + fn clear_peer_download(&mut self, peer_id: PeerId) { + if let Some(ref peer) = self.peers.get(&peer_id) { + match peer.asking { + PeerAsking::BlockHeaders => { + if let Some(ref hash) = peer.asking_hash { + self.new_blocks.clear_header_download(hash); + if let Some(ref mut old) = self.old_blocks { + old.clear_header_download(hash); + } + } + }, + PeerAsking::BlockBodies => { + self.new_blocks.clear_body_download(&peer.asking_blocks); + if let Some(ref mut old) = self.old_blocks { + old.clear_body_download(&peer.asking_blocks); + } + }, + PeerAsking::BlockReceipts => { + self.new_blocks.clear_receipt_download(&peer.asking_blocks); + if let Some(ref mut old) = self.old_blocks { + old.clear_receipt_download(&peer.asking_blocks); + } + }, + PeerAsking::SnapshotData => { + if let Some(hash) = peer.asking_snapshot_data { + self.snapshot.clear_chunk_download(&hash); + } + }, + _ => (), + } + } + } + + /// Checks if there are blocks fully downloaded that can be imported into the blockchain and does the import. + fn collect_blocks(&mut self, io: &mut SyncIo, block_set: BlockSet) { + match block_set { + BlockSet::NewBlocks => { + if self.new_blocks.collect_blocks(io, self.state == SyncState::NewBlocks) == Err(DownloaderImportError::Invalid) { + self.restart(io); + } + }, + BlockSet::OldBlocks => { + if self.old_blocks.as_mut().map_or(false, |downloader| { downloader.collect_blocks(io, false) == Err(DownloaderImportError::Invalid) }) { + self.restart(io); + } else if self.old_blocks.as_ref().map_or(false, |downloader| { downloader.is_complete() }) { + trace!(target: "sync", "Background block download is complete"); + self.old_blocks = None; + } + } + } + } + + /// Reset peer status after request is complete. + fn reset_peer_asking(&mut self, peer_id: PeerId, asking: PeerAsking) -> bool { + if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { + peer.expired = false; + peer.block_set = None; + if peer.asking != asking { + trace!(target:"sync", "Asking {:?} while expected {:?}", peer.asking, asking); + peer.asking = PeerAsking::Nothing; + return false; + } else { + peer.asking = PeerAsking::Nothing; + return true; + } + } + false + } + + /// Send Status message + fn send_status(&mut self, io: &mut SyncIo, peer: PeerId) -> Result<(), network::Error> { + let warp_protocol_version = io.protocol_version(&WARP_SYNC_PROTOCOL_ID, peer); + let warp_protocol = warp_protocol_version != 0; + let protocol = if warp_protocol { warp_protocol_version } else { ETH_PROTOCOL_VERSION_63 }; + trace!(target: "sync", "Sending status to {}, protocol version {}", peer, protocol); + let mut packet = RlpStream::new_list(if warp_protocol { 7 } else { 5 }); + let chain = io.chain().chain_info(); + packet.append(&(protocol as u32)); + packet.append(&self.network_id); + packet.append(&chain.total_difficulty); + packet.append(&chain.best_block_hash); + packet.append(&chain.genesis_hash); + if warp_protocol { + let manifest = match self.old_blocks.is_some() { + true => None, + false => io.snapshot_service().manifest(), + }; + let block_number = manifest.as_ref().map_or(0, |m| m.block_number); + let manifest_hash = manifest.map_or(H256::new(), |m| keccak(m.into_rlp())); + packet.append(&manifest_hash); + packet.append(&block_number); + } + io.respond(STATUS_PACKET, packet.out()) + } + + pub fn maintain_peers(&mut self, io: &mut SyncIo) { + let tick = Instant::now(); + let mut aborting = Vec::new(); + for (peer_id, peer) in &self.peers { + let elapsed = tick - peer.ask_time; + let timeout = match peer.asking { + PeerAsking::BlockHeaders => elapsed > HEADERS_TIMEOUT, + PeerAsking::BlockBodies => elapsed > BODIES_TIMEOUT, + PeerAsking::BlockReceipts => elapsed > RECEIPTS_TIMEOUT, + PeerAsking::Nothing => false, + PeerAsking::ForkHeader => elapsed > FORK_HEADER_TIMEOUT, + PeerAsking::SnapshotManifest => elapsed > SNAPSHOT_MANIFEST_TIMEOUT, + PeerAsking::SnapshotData => elapsed > SNAPSHOT_DATA_TIMEOUT, + }; + if timeout { + debug!(target:"sync", "Timeout {}", peer_id); + io.disconnect_peer(*peer_id); + aborting.push(*peer_id); + } + } + for p in aborting { + SyncHandler::on_peer_aborting(self, io, p); + } + + // Check for handshake timeouts + for (peer, &ask_time) in &self.handshaking_peers { + let elapsed = (tick - ask_time) / 1_000_000_000; + if elapsed > STATUS_TIMEOUT { + trace!(target:"sync", "Status timeout {}", peer); + io.disconnect_peer(*peer); + } + } + } + + fn check_resume(&mut self, io: &mut SyncIo) { + if self.state == SyncState::Waiting && !io.chain().queue_info().is_full() { + self.state = SyncState::Blocks; + self.continue_sync(io); + } else if self.state == SyncState::SnapshotWaiting { + match io.snapshot_service().status() { + RestorationStatus::Inactive => { + trace!(target:"sync", "Snapshot restoration is complete"); + self.restart(io); + }, + RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } => { + if !self.snapshot.is_complete() && self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize <= MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { + trace!(target:"sync", "Resuming snapshot sync"); + self.state = SyncState::SnapshotData; + self.continue_sync(io); + } + }, + RestorationStatus::Failed => { + trace!(target: "sync", "Snapshot restoration aborted"); + self.state = SyncState::WaitingPeers; + self.snapshot.clear(); + self.continue_sync(io); + }, + } + } + } + + /// creates rlp to send for the tree defined by 'from' and 'to' hashes + fn create_new_hashes_rlp(chain: &BlockChainClient, from: &H256, to: &H256) -> Option { + match chain.tree_route(from, to) { + Some(route) => { + let uncles = chain.find_uncles(from).unwrap_or_else(Vec::new); + match route.blocks.len() { + 0 => None, + _ => { + let mut blocks = route.blocks; + blocks.extend(uncles); + let mut rlp_stream = RlpStream::new_list(blocks.len()); + for block_hash in blocks { + let mut hash_rlp = RlpStream::new_list(2); + let number = chain.block_header(BlockId::Hash(block_hash.clone())) + .expect("chain.tree_route and chain.find_uncles only return hahses of blocks that are in the blockchain. qed.").number(); + hash_rlp.append(&block_hash); + hash_rlp.append(&number); + rlp_stream.append_raw(hash_rlp.as_raw(), 1); + } + Some(rlp_stream.out()) + } + } + }, + None => None + } + } + + /// creates rlp from block bytes and total difficulty + fn create_block_rlp(bytes: &Bytes, total_difficulty: U256) -> Bytes { + let mut rlp_stream = RlpStream::new_list(2); + rlp_stream.append_raw(bytes, 1); + rlp_stream.append(&total_difficulty); + rlp_stream.out() + } + + /// creates latest block rlp for the given client + fn create_latest_block_rlp(chain: &BlockChainClient) -> Bytes { + ChainSync::create_block_rlp( + &chain.block(BlockId::Hash(chain.chain_info().best_block_hash)) + .expect("Best block always exists").into_inner(), + chain.chain_info().total_difficulty + ) + } + + /// creates given hash block rlp for the given client + fn create_new_block_rlp(chain: &BlockChainClient, hash: &H256) -> Bytes { + ChainSync::create_block_rlp( + &chain.block(BlockId::Hash(hash.clone())).expect("Block has just been sealed; qed").into_inner(), + chain.block_total_difficulty(BlockId::Hash(hash.clone())).expect("Block has just been sealed; qed.") + ) + } + + /// returns peer ids that have different blocks than our chain + fn get_lagging_peers(&mut self, chain_info: &BlockChainInfo) -> Vec { + let latest_hash = chain_info.best_block_hash; + self + .peers + .iter_mut() + .filter_map(|(&id, ref mut peer_info)| { + trace!(target: "sync", "Checking peer our best {} their best {}", latest_hash, peer_info.latest_hash); + if peer_info.latest_hash != latest_hash { + Some(id) + } else { + None + } + }) + .collect::>() + } + + fn select_random_peers(peers: &[PeerId]) -> Vec { + // take sqrt(x) peers + let mut peers = peers.to_vec(); + let mut count = (peers.len() as f64).powf(0.5).round() as usize; + count = cmp::min(count, MAX_PEERS_PROPAGATION); + count = cmp::max(count, MIN_PEERS_PROPAGATION); + random::new().shuffle(&mut peers); + peers.truncate(count); + peers + } + + fn get_consensus_peers(&self) -> Vec { + self.peers.iter().filter_map(|(id, p)| if p.protocol_version >= PAR_PROTOCOL_VERSION_2 { Some(*id) } else { None }).collect() + } + + fn get_private_transaction_peers(&self) -> Vec { + self.peers.iter().filter_map(|(id, p)| if p.protocol_version >= PAR_PROTOCOL_VERSION_3 { Some(*id) } else { None }).collect() + } + + /// Maintain other peers. Send out any new blocks and transactions + pub fn maintain_sync(&mut self, io: &mut SyncIo) { + self.maybe_start_snapshot_sync(io); + self.check_resume(io); + } + + /// called when block is imported to chain - propagates the blocks and updates transactions sent to peers + pub fn chain_new_blocks(&mut self, io: &mut SyncIo, _imported: &[H256], invalid: &[H256], enacted: &[H256], _retracted: &[H256], sealed: &[H256], proposed: &[Bytes]) { + let queue_info = io.chain().queue_info(); + let is_syncing = self.status().is_syncing(queue_info); + + if !is_syncing || !sealed.is_empty() || !proposed.is_empty() { + trace!(target: "sync", "Propagating blocks, state={:?}", self.state); + SyncPropagator::propagate_latest_blocks(self, io, sealed); + SyncPropagator::propagate_proposed_blocks(self, io, proposed); + } + if !invalid.is_empty() { + trace!(target: "sync", "Bad blocks in the queue, restarting"); + self.restart(io); + } + + if !is_syncing && !enacted.is_empty() && !self.peers.is_empty() { + // Select random peer to re-broadcast transactions to. + let peer = random::new().gen_range(0, self.peers.len()); + trace!(target: "sync", "Re-broadcasting transactions to a random peer."); + self.peers.values_mut().nth(peer).map(|peer_info| + peer_info.last_sent_transactions.clear() + ); + } + } + + /// Dispatch incoming requests and responses + pub fn dispatch_packet(sync: &RwLock, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { + SyncSupplier::dispatch_packet(sync, io, peer, packet_id, data) + } + + pub fn on_packet(&mut self, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { + debug!(target: "sync", "{} -> Dispatching packet: {}", peer, packet_id); + SyncHandler::on_packet(self, io, peer, packet_id, data); + } + + /// Called when peer sends us new consensus packet + pub fn on_consensus_packet(io: &mut SyncIo, peer_id: PeerId, r: &Rlp) -> Result<(), PacketDecodeError> { + SyncHandler::on_consensus_packet(io, peer_id, r) + } + + /// Called by peer when it is disconnecting + pub fn on_peer_aborting(&mut self, io: &mut SyncIo, peer: PeerId) { + SyncHandler::on_peer_aborting(self, io, peer); + } + + /// Called when a new peer is connected + pub fn on_peer_connected(&mut self, io: &mut SyncIo, peer: PeerId) { + SyncHandler::on_peer_connected(self, io, peer); + } + + /// propagates new transactions to all peers + pub fn propagate_new_transactions(&mut self, io: &mut SyncIo) -> usize { + SyncPropagator::propagate_new_transactions(self, io) + } + + /// Broadcast consensus message to peers. + pub fn propagate_consensus_packet(&mut self, io: &mut SyncIo, packet: Bytes) { + SyncPropagator::propagate_consensus_packet(self, io, packet); + } + + /// Broadcast private transaction message to peers. + pub fn propagate_private_transaction(&mut self, io: &mut SyncIo, packet: Bytes) { + SyncPropagator::propagate_private_transaction(self, io, packet); + } + + /// Broadcast signed private transaction message to peers. + pub fn propagate_signed_private_transaction(&mut self, io: &mut SyncIo, packet: Bytes) { + SyncPropagator::propagate_signed_private_transaction(self, io, packet); + } +} + +#[cfg(test)] +pub mod tests { + use std::collections::{HashSet, VecDeque}; + use ethkey; + use network::PeerId; + use tests::helpers::{TestIo}; + use tests::snapshot::TestSnapshotService; + use ethereum_types::{H256, U256, Address}; + use parking_lot::RwLock; + use bytes::Bytes; + use rlp::{Rlp, RlpStream}; + use super::*; + use ::SyncConfig; + use super::{PeerInfo, PeerAsking}; + use ethcore::header::*; + use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient, ChainInfo, BlockInfo}; + use ethcore::miner::MinerService; + use private_tx::NoopPrivateTxHandler; + + pub fn get_dummy_block(order: u32, parent_hash: H256) -> Bytes { + let mut header = Header::new(); + header.set_gas_limit(0.into()); + header.set_difficulty((order * 100).into()); + header.set_timestamp((order * 10) as u64); + header.set_number(order as u64); + header.set_parent_hash(parent_hash); + header.set_state_root(H256::zero()); + + let mut rlp = RlpStream::new_list(3); + rlp.append(&header); + rlp.append_raw(&::rlp::EMPTY_LIST_RLP, 1); + rlp.append_raw(&::rlp::EMPTY_LIST_RLP, 1); + rlp.out() + } + + pub fn get_dummy_blocks(order: u32, parent_hash: H256) -> Bytes { + let mut rlp = RlpStream::new_list(1); + rlp.append_raw(&get_dummy_block(order, parent_hash), 1); + let difficulty: U256 = (100 * order).into(); + rlp.append(&difficulty); + rlp.out() + } + + pub fn get_dummy_hashes() -> Bytes { + let mut rlp = RlpStream::new_list(5); + for _ in 0..5 { + let mut hash_d_rlp = RlpStream::new_list(2); + let hash: H256 = H256::from(0u64); + let diff: U256 = U256::from(1u64); + hash_d_rlp.append(&hash); + hash_d_rlp.append(&diff); + + rlp.append_raw(&hash_d_rlp.out(), 1); + } + + rlp.out() + } + + fn queue_info(unverified: usize, verified: usize) -> BlockQueueInfo { + BlockQueueInfo { + unverified_queue_size: unverified, + verified_queue_size: verified, + verifying_queue_size: 0, + max_queue_size: 1000, + max_mem_use: 1000, + mem_used: 500 + } + } + + fn sync_status(state: SyncState) -> SyncStatus { + SyncStatus { + state: state, + protocol_version: 0, + network_id: 0, + start_block_number: 0, + last_imported_block_number: None, + highest_block_number: None, + blocks_total: 0, + blocks_received: 0, + num_peers: 0, + num_active_peers: 0, + mem_used: 0, + num_snapshot_chunks: 0, + snapshot_chunks_done: 0, + last_imported_old_block_number: None, + } + } + + #[test] + fn is_still_verifying() { + assert!(!sync_status(SyncState::Idle).is_syncing(queue_info(2, 1))); + assert!(sync_status(SyncState::Idle).is_syncing(queue_info(2, 2))); + } + + #[test] + fn is_synced_state() { + assert!(sync_status(SyncState::Blocks).is_syncing(queue_info(0, 0))); + assert!(!sync_status(SyncState::Idle).is_syncing(queue_info(0, 0))); + } + + pub fn dummy_sync_with_peer(peer_latest_hash: H256, client: &BlockChainClient) -> ChainSync { + let mut sync = ChainSync::new(SyncConfig::default(), client, Arc::new(NoopPrivateTxHandler)); + insert_dummy_peer(&mut sync, 0, peer_latest_hash); + sync + } + + pub fn insert_dummy_peer(sync: &mut ChainSync, peer_id: PeerId, peer_latest_hash: H256) { + sync.peers.insert(peer_id, + PeerInfo { + protocol_version: 0, + genesis: H256::zero(), + network_id: 0, + latest_hash: peer_latest_hash, + difficulty: None, + asking: PeerAsking::Nothing, + asking_blocks: Vec::new(), + asking_hash: None, + ask_time: Instant::now(), + last_sent_transactions: HashSet::new(), + expired: false, + confirmation: super::ForkConfirmation::Confirmed, + snapshot_number: None, + snapshot_hash: None, + asking_snapshot_data: None, + block_set: None, + }); + + } + + #[test] + fn finds_lagging_peers() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(10), &client); + let chain_info = client.chain_info(); + + let lagging_peers = sync.get_lagging_peers(&chain_info); + + assert_eq!(1, lagging_peers.len()); + } + + #[test] + fn calculates_tree_for_lagging_peer() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(15, EachBlockWith::Uncle); + + let start = client.block_hash_delta_minus(4); + let end = client.block_hash_delta_minus(2); + + // wrong way end -> start, should be None + let rlp = ChainSync::create_new_hashes_rlp(&client, &end, &start); + assert!(rlp.is_none()); + + let rlp = ChainSync::create_new_hashes_rlp(&client, &start, &end).unwrap(); + // size of three rlp encoded hash-difficulty + assert_eq!(107, rlp.len()); + } + // idea is that what we produce when propagading latest hashes should be accepted in + // on_peer_new_hashes in our code as well + #[test] + fn hashes_rlp_mutually_acceptable() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + let queue = RwLock::new(VecDeque::new()); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + let chain_info = client.chain_info(); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + let peers = sync.get_lagging_peers(&chain_info); + SyncPropagator::propagate_new_hashes(&mut sync, &chain_info, &mut io, &peers); + + let data = &io.packets[0].data.clone(); + let result = SyncHandler::on_peer_new_hashes(&mut sync, &mut io, 0, &Rlp::new(data)); + assert!(result.is_ok()); + } + + // idea is that what we produce when propagading latest block should be accepted in + // on_peer_new_block in our code as well + #[test] + fn block_rlp_mutually_acceptable() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + let queue = RwLock::new(VecDeque::new()); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + let chain_info = client.chain_info(); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + let peers = sync.get_lagging_peers(&chain_info); + SyncPropagator::propagate_blocks(&mut sync, &chain_info, &mut io, &[], &peers); + + let data = &io.packets[0].data.clone(); + let result = SyncHandler::on_peer_new_block(&mut sync, &mut io, 0, &Rlp::new(data)); + assert!(result.is_ok()); + } + + #[test] + fn should_add_transactions_to_queue() { + fn sender(tx: &UnverifiedTransaction) -> Address { + ethkey::public_to_address(&tx.recover_public().unwrap()) + } + + // given + let mut client = TestBlockChainClient::new(); + client.add_blocks(98, EachBlockWith::Uncle); + client.add_blocks(1, EachBlockWith::UncleAndTransaction); + client.add_blocks(1, EachBlockWith::Transaction); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + + let good_blocks = vec![client.block_hash_delta_minus(2)]; + let retracted_blocks = vec![client.block_hash_delta_minus(1)]; + + // Add some balance to clients and reset nonces + for h in &[good_blocks[0], retracted_blocks[0]] { + let block = client.block(BlockId::Hash(*h)).unwrap(); + let sender = sender(&block.transactions()[0]);; + client.set_balance(sender, U256::from(10_000_000_000_000_000_000u64)); + client.set_nonce(sender, U256::from(0)); + } + + + // when + { + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + io.chain.miner.chain_new_blocks(io.chain, &[], &[], &[], &good_blocks, false); + sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks, &[], &[]); + assert_eq!(io.chain.miner.ready_transactions(io.chain).len(), 1); + } + // We need to update nonce status (because we say that the block has been imported) + for h in &[good_blocks[0]] { + let block = client.block(BlockId::Hash(*h)).unwrap(); + client.set_nonce(sender(&block.transactions()[0]), U256::from(1)); + } + { + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&client, &ss, &queue, None); + io.chain.miner.chain_new_blocks(io.chain, &[], &[], &good_blocks, &retracted_blocks, false); + sync.chain_new_blocks(&mut io, &[], &[], &good_blocks, &retracted_blocks, &[], &[]); + } + + // then + assert_eq!(client.miner.ready_transactions(&client).len(), 1); + } + + #[test] + fn should_not_add_transactions_to_queue_if_not_synced() { + // given + let mut client = TestBlockChainClient::new(); + client.add_blocks(98, EachBlockWith::Uncle); + client.add_blocks(1, EachBlockWith::UncleAndTransaction); + client.add_blocks(1, EachBlockWith::Transaction); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + + let good_blocks = vec![client.block_hash_delta_minus(2)]; + let retracted_blocks = vec![client.block_hash_delta_minus(1)]; + + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + // when + sync.chain_new_blocks(&mut io, &[], &[], &[], &good_blocks, &[], &[]); + assert_eq!(io.chain.miner.queue_status().status.transaction_count, 0); + sync.chain_new_blocks(&mut io, &[], &[], &good_blocks, &retracted_blocks, &[], &[]); + + // then + let status = io.chain.miner.queue_status(); + assert_eq!(status.status.transaction_count, 0); + } +} diff --git a/ethcore/sync/src/chain/propagator.rs b/ethcore/sync/src/chain/propagator.rs new file mode 100644 index 00000000000..4ae0518a537 --- /dev/null +++ b/ethcore/sync/src/chain/propagator.rs @@ -0,0 +1,636 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use bytes::Bytes; +use ethereum_types::H256; +use ethcore::client::BlockChainInfo; +use ethcore::header::BlockNumber; +use network::{PeerId, PacketId}; +use rand::Rng; +use rlp::{Encodable, RlpStream}; +use sync_io::SyncIo; +use std::cmp; +use std::collections::HashSet; +use transaction::SignedTransaction; + +use super::{ + random, + ChainSync, + MAX_PEER_LAG_PROPAGATION, + MAX_PEERS_PROPAGATION, + MAX_TRANSACTION_PACKET_SIZE, + MAX_TRANSACTIONS_TO_PROPAGATE, + MIN_PEERS_PROPAGATION, + CONSENSUS_DATA_PACKET, + NEW_BLOCK_HASHES_PACKET, + NEW_BLOCK_PACKET, + PRIVATE_TRANSACTION_PACKET, + SIGNED_PRIVATE_TRANSACTION_PACKET, + TRANSACTIONS_PACKET, +}; + +/// Checks if peer is able to process service transactions +fn accepts_service_transaction(client_id: &str) -> bool { + // Parity versions starting from this will accept service-transactions + const SERVICE_TRANSACTIONS_VERSION: (u32, u32) = (1u32, 6u32); + // Parity client string prefix + const PARITY_CLIENT_ID_PREFIX: &'static str = "Parity/v"; + + if !client_id.starts_with(PARITY_CLIENT_ID_PREFIX) { + return false; + } + let ver: Vec = client_id[PARITY_CLIENT_ID_PREFIX.len()..].split('.') + .take(2) + .filter_map(|s| s.parse().ok()) + .collect(); + ver.len() == 2 && (ver[0] > SERVICE_TRANSACTIONS_VERSION.0 || (ver[0] == SERVICE_TRANSACTIONS_VERSION.0 && ver[1] >= SERVICE_TRANSACTIONS_VERSION.1)) +} + +/// The Chain Sync Propagator: propagates data to peers +pub struct SyncPropagator; + +impl SyncPropagator { + /// propagates latest block to a set of peers + pub fn propagate_blocks(sync: &mut ChainSync, chain_info: &BlockChainInfo, io: &mut SyncIo, blocks: &[H256], peers: &[PeerId]) -> usize { + trace!(target: "sync", "Sending NewBlocks to {:?}", peers); + let mut sent = 0; + for peer_id in peers { + if blocks.is_empty() { + let rlp = ChainSync::create_latest_block_rlp(io.chain()); + SyncPropagator::send_packet(io, *peer_id, NEW_BLOCK_PACKET, rlp); + } else { + for h in blocks { + let rlp = ChainSync::create_new_block_rlp(io.chain(), h); + SyncPropagator::send_packet(io, *peer_id, NEW_BLOCK_PACKET, rlp); + } + } + if let Some(ref mut peer) = sync.peers.get_mut(peer_id) { + peer.latest_hash = chain_info.best_block_hash.clone(); + } + sent += 1; + } + sent + } + + /// propagates new known hashes to all peers + pub fn propagate_new_hashes(sync: &mut ChainSync, chain_info: &BlockChainInfo, io: &mut SyncIo, peers: &[PeerId]) -> usize { + trace!(target: "sync", "Sending NewHashes to {:?}", peers); + let mut sent = 0; + let last_parent = *io.chain().best_block_header().parent_hash(); + for peer_id in peers { + sent += match ChainSync::create_new_hashes_rlp(io.chain(), &last_parent, &chain_info.best_block_hash) { + Some(rlp) => { + { + if let Some(ref mut peer) = sync.peers.get_mut(peer_id) { + peer.latest_hash = chain_info.best_block_hash.clone(); + } + } + SyncPropagator::send_packet(io, *peer_id, NEW_BLOCK_HASHES_PACKET, rlp); + 1 + }, + None => 0 + } + } + sent + } + + /// propagates new transactions to all peers + pub fn propagate_new_transactions(sync: &mut ChainSync, io: &mut SyncIo) -> usize { + // Early out if nobody to send to. + if sync.peers.is_empty() { + return 0; + } + + let transactions = io.chain().ready_transactions(); + if transactions.is_empty() { + return 0; + } + + let (transactions, service_transactions): (Vec<_>, Vec<_>) = transactions.iter() + .map(|tx| tx.signed()) + .partition(|tx| !tx.gas_price.is_zero()); + + // usual transactions could be propagated to all peers + let mut affected_peers = HashSet::new(); + if !transactions.is_empty() { + let peers = SyncPropagator::select_peers_for_transactions(sync, |_| true); + affected_peers = SyncPropagator::propagate_transactions_to_peers(sync, io, peers, transactions); + } + + // most of times service_transactions will be empty + // => there's no need to merge packets + if !service_transactions.is_empty() { + let service_transactions_peers = SyncPropagator::select_peers_for_transactions(sync, |peer_id| accepts_service_transaction(&io.peer_info(*peer_id))); + let service_transactions_affected_peers = SyncPropagator::propagate_transactions_to_peers(sync, io, service_transactions_peers, service_transactions); + affected_peers.extend(&service_transactions_affected_peers); + } + + affected_peers.len() + } + + fn propagate_transactions_to_peers(sync: &mut ChainSync, io: &mut SyncIo, peers: Vec, transactions: Vec<&SignedTransaction>) -> HashSet { + let all_transactions_hashes = transactions.iter() + .map(|tx| tx.hash()) + .collect::>(); + let all_transactions_rlp = { + let mut packet = RlpStream::new_list(transactions.len()); + for tx in &transactions { packet.append(&**tx); } + packet.out() + }; + + // Clear old transactions from stats + sync.transactions_stats.retain(&all_transactions_hashes); + + // sqrt(x)/x scaled to max u32 + let block_number = io.chain().chain_info().best_block_number; + + let lucky_peers = { + peers.into_iter() + .filter_map(|peer_id| { + let stats = &mut sync.transactions_stats; + let peer_info = sync.peers.get_mut(&peer_id) + .expect("peer_id is form peers; peers is result of select_peers_for_transactions; select_peers_for_transactions selects peers from self.peers; qed"); + + // Send all transactions + if peer_info.last_sent_transactions.is_empty() { + // update stats + for hash in &all_transactions_hashes { + let id = io.peer_session_info(peer_id).and_then(|info| info.id); + stats.propagated(hash, id, block_number); + } + peer_info.last_sent_transactions = all_transactions_hashes.clone(); + return Some((peer_id, all_transactions_hashes.len(), all_transactions_rlp.clone())); + } + + // Get hashes of all transactions to send to this peer + let to_send = all_transactions_hashes.difference(&peer_info.last_sent_transactions) + .take(MAX_TRANSACTIONS_TO_PROPAGATE) + .cloned() + .collect::>(); + if to_send.is_empty() { + return None; + } + + // Construct RLP + let (packet, to_send) = { + let mut to_send = to_send; + let mut packet = RlpStream::new(); + packet.begin_unbounded_list(); + let mut pushed = 0; + for tx in &transactions { + let hash = tx.hash(); + if to_send.contains(&hash) { + let mut transaction = RlpStream::new(); + tx.rlp_append(&mut transaction); + let appended = packet.append_raw_checked(&transaction.drain(), 1, MAX_TRANSACTION_PACKET_SIZE); + if !appended { + // Maximal packet size reached just proceed with sending + debug!("Transaction packet size limit reached. Sending incomplete set of {}/{} transactions.", pushed, to_send.len()); + to_send = to_send.into_iter().take(pushed).collect(); + break; + } + pushed += 1; + } + } + packet.complete_unbounded_list(); + (packet, to_send) + }; + + // Update stats + let id = io.peer_session_info(peer_id).and_then(|info| info.id); + for hash in &to_send { + // update stats + stats.propagated(hash, id, block_number); + } + + peer_info.last_sent_transactions = all_transactions_hashes + .intersection(&peer_info.last_sent_transactions) + .chain(&to_send) + .cloned() + .collect(); + Some((peer_id, to_send.len(), packet.out())) + }) + .collect::>() + }; + + // Send RLPs + let mut peers = HashSet::new(); + if lucky_peers.len() > 0 { + let mut max_sent = 0; + let lucky_peers_len = lucky_peers.len(); + for (peer_id, sent, rlp) in lucky_peers { + peers.insert(peer_id); + SyncPropagator::send_packet(io, peer_id, TRANSACTIONS_PACKET, rlp); + trace!(target: "sync", "{:02} <- Transactions ({} entries)", peer_id, sent); + max_sent = cmp::max(max_sent, sent); + } + debug!(target: "sync", "Sent up to {} transactions to {} peers.", max_sent, lucky_peers_len); + } + + peers + } + + pub fn propagate_latest_blocks(sync: &mut ChainSync, io: &mut SyncIo, sealed: &[H256]) { + let chain_info = io.chain().chain_info(); + if (((chain_info.best_block_number as i64) - (sync.last_sent_block_number as i64)).abs() as BlockNumber) < MAX_PEER_LAG_PROPAGATION { + let mut peers = sync.get_lagging_peers(&chain_info); + if sealed.is_empty() { + let hashes = SyncPropagator::propagate_new_hashes(sync, &chain_info, io, &peers); + peers = ChainSync::select_random_peers(&peers); + let blocks = SyncPropagator::propagate_blocks(sync, &chain_info, io, sealed, &peers); + if blocks != 0 || hashes != 0 { + trace!(target: "sync", "Sent latest {} blocks and {} hashes to peers.", blocks, hashes); + } + } else { + SyncPropagator::propagate_blocks(sync, &chain_info, io, sealed, &peers); + SyncPropagator::propagate_new_hashes(sync, &chain_info, io, &peers); + trace!(target: "sync", "Sent sealed block to all peers"); + }; + } + sync.last_sent_block_number = chain_info.best_block_number; + } + + /// Distribute valid proposed blocks to subset of current peers. + pub fn propagate_proposed_blocks(sync: &mut ChainSync, io: &mut SyncIo, proposed: &[Bytes]) { + let peers = sync.get_consensus_peers(); + trace!(target: "sync", "Sending proposed blocks to {:?}", peers); + for block in proposed { + let rlp = ChainSync::create_block_rlp( + block, + io.chain().chain_info().total_difficulty + ); + for peer_id in &peers { + SyncPropagator::send_packet(io, *peer_id, NEW_BLOCK_PACKET, rlp.clone()); + } + } + } + + /// Broadcast consensus message to peers. + pub fn propagate_consensus_packet(sync: &mut ChainSync, io: &mut SyncIo, packet: Bytes) { + let lucky_peers = ChainSync::select_random_peers(&sync.get_consensus_peers()); + trace!(target: "sync", "Sending consensus packet to {:?}", lucky_peers); + for peer_id in lucky_peers { + SyncPropagator::send_packet(io, peer_id, CONSENSUS_DATA_PACKET, packet.clone()); + } + } + + /// Broadcast private transaction message to peers. + pub fn propagate_private_transaction(sync: &mut ChainSync, io: &mut SyncIo, packet: Bytes) { + let lucky_peers = ChainSync::select_random_peers(&sync.get_private_transaction_peers()); + trace!(target: "sync", "Sending private transaction packet to {:?}", lucky_peers); + for peer_id in lucky_peers { + SyncPropagator::send_packet(io, peer_id, PRIVATE_TRANSACTION_PACKET, packet.clone()); + } + } + + /// Broadcast signed private transaction message to peers. + pub fn propagate_signed_private_transaction(sync: &mut ChainSync, io: &mut SyncIo, packet: Bytes) { + let lucky_peers = ChainSync::select_random_peers(&sync.get_private_transaction_peers()); + trace!(target: "sync", "Sending signed private transaction packet to {:?}", lucky_peers); + for peer_id in lucky_peers { + SyncPropagator::send_packet(io, peer_id, SIGNED_PRIVATE_TRANSACTION_PACKET, packet.clone()); + } + } + + fn select_peers_for_transactions(sync: &ChainSync, filter: F) -> Vec + where F: Fn(&PeerId) -> bool { + // sqrt(x)/x scaled to max u32 + let fraction = ((sync.peers.len() as f64).powf(-0.5) * (u32::max_value() as f64).round()) as u32; + let small = sync.peers.len() < MIN_PEERS_PROPAGATION; + + let mut random = random::new(); + sync.peers.keys() + .cloned() + .filter(filter) + .filter(|_| small || random.next_u32() < fraction) + .take(MAX_PEERS_PROPAGATION) + .collect() + } + + /// Generic packet sender + fn send_packet(sync: &mut SyncIo, peer_id: PeerId, packet_id: PacketId, packet: Bytes) { + if let Err(e) = sync.send(peer_id, packet_id, packet) { + debug!(target:"sync", "Error sending packet: {:?}", e); + sync.disconnect_peer(peer_id); + } + } +} + +#[cfg(test)] +mod tests { + use ethcore::client::{BlockInfo, ChainInfo, EachBlockWith, TestBlockChainClient}; + use parking_lot::RwLock; + use private_tx::NoopPrivateTxHandler; + use rlp::{Rlp}; + use std::collections::{VecDeque}; + use tests::helpers::{TestIo}; + use tests::snapshot::TestSnapshotService; + + use super::{*, super::{*, tests::*}}; + + #[test] + fn sends_new_hashes_to_lagging_peer() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + let queue = RwLock::new(VecDeque::new()); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + let chain_info = client.chain_info(); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + let peers = sync.get_lagging_peers(&chain_info); + let peer_count = SyncPropagator::propagate_new_hashes(&mut sync, &chain_info, &mut io, &peers); + + // 1 message should be send + assert_eq!(1, io.packets.len()); + // 1 peer should be updated + assert_eq!(1, peer_count); + // NEW_BLOCK_HASHES_PACKET + assert_eq!(0x01, io.packets[0].packet_id); + } + + #[test] + fn sends_latest_block_to_lagging_peer() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + let queue = RwLock::new(VecDeque::new()); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + let chain_info = client.chain_info(); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + let peers = sync.get_lagging_peers(&chain_info); + let peer_count = SyncPropagator::propagate_blocks(&mut sync, &chain_info, &mut io, &[], &peers); + + // 1 message should be send + assert_eq!(1, io.packets.len()); + // 1 peer should be updated + assert_eq!(1, peer_count); + // NEW_BLOCK_PACKET + assert_eq!(0x07, io.packets[0].packet_id); + } + + #[test] + fn sends_sealed_block() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + let queue = RwLock::new(VecDeque::new()); + let hash = client.block_hash(BlockId::Number(99)).unwrap(); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(5), &client); + let chain_info = client.chain_info(); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + let peers = sync.get_lagging_peers(&chain_info); + let peer_count = SyncPropagator::propagate_blocks(&mut sync ,&chain_info, &mut io, &[hash.clone()], &peers); + + // 1 message should be send + assert_eq!(1, io.packets.len()); + // 1 peer should be updated + assert_eq!(1, peer_count); + // NEW_BLOCK_PACKET + assert_eq!(0x07, io.packets[0].packet_id); + } + + #[test] + fn sends_proposed_block() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(2, EachBlockWith::Uncle); + let queue = RwLock::new(VecDeque::new()); + let block = client.block(BlockId::Latest).unwrap().into_inner(); + let mut sync = ChainSync::new(SyncConfig::default(), &client, Arc::new(NoopPrivateTxHandler)); + sync.peers.insert(0, + PeerInfo { + // Messaging protocol + protocol_version: 2, + genesis: H256::zero(), + network_id: 0, + latest_hash: client.block_hash_delta_minus(1), + difficulty: None, + asking: PeerAsking::Nothing, + asking_blocks: Vec::new(), + asking_hash: None, + ask_time: Instant::now(), + last_sent_transactions: HashSet::new(), + expired: false, + confirmation: ForkConfirmation::Confirmed, + snapshot_number: None, + snapshot_hash: None, + asking_snapshot_data: None, + block_set: None, + }); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + SyncPropagator::propagate_proposed_blocks(&mut sync, &mut io, &[block]); + + // 1 message should be sent + assert_eq!(1, io.packets.len()); + // NEW_BLOCK_PACKET + assert_eq!(0x07, io.packets[0].packet_id); + } + + #[test] + fn propagates_transactions() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + client.insert_transaction_to_queue(); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(1), &client); + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + let peer_count = SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + // Try to propagate same transactions for the second time + let peer_count2 = SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + // Even after new block transactions should not be propagated twice + sync.chain_new_blocks(&mut io, &[], &[], &[], &[], &[], &[]); + // Try to propagate same transactions for the third time + let peer_count3 = SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + + // 1 message should be send + assert_eq!(1, io.packets.len()); + // 1 peer should be updated but only once + assert_eq!(1, peer_count); + assert_eq!(0, peer_count2); + assert_eq!(0, peer_count3); + // TRANSACTIONS_PACKET + assert_eq!(0x02, io.packets[0].packet_id); + } + + #[test] + fn does_not_propagate_new_transactions_after_new_block() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + client.insert_transaction_to_queue(); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(1), &client); + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + let peer_count = SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + io.chain.insert_transaction_to_queue(); + // New block import should not trigger propagation. + // (we only propagate on timeout) + sync.chain_new_blocks(&mut io, &[], &[], &[], &[], &[], &[]); + + // 2 message should be send + assert_eq!(1, io.packets.len()); + // 1 peer should receive the message + assert_eq!(1, peer_count); + // TRANSACTIONS_PACKET + assert_eq!(0x02, io.packets[0].packet_id); + } + + #[test] + fn does_not_fail_for_no_peers() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + client.insert_transaction_to_queue(); + // Sync with no peers + let mut sync = ChainSync::new(SyncConfig::default(), &client, Arc::new(NoopPrivateTxHandler)); + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + let peer_count = SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + sync.chain_new_blocks(&mut io, &[], &[], &[], &[], &[], &[]); + // Try to propagate same transactions for the second time + let peer_count2 = SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + + assert_eq!(0, io.packets.len()); + assert_eq!(0, peer_count); + assert_eq!(0, peer_count2); + } + + #[test] + fn propagates_transactions_without_alternating() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + client.insert_transaction_to_queue(); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(1), &client); + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + // should sent some + { + let mut io = TestIo::new(&mut client, &ss, &queue, None); + let peer_count = SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + assert_eq!(1, io.packets.len()); + assert_eq!(1, peer_count); + } + // Insert some more + client.insert_transaction_to_queue(); + let (peer_count2, peer_count3) = { + let mut io = TestIo::new(&mut client, &ss, &queue, None); + // Propagate new transactions + let peer_count2 = SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + // And now the peer should have all transactions + let peer_count3 = SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + (peer_count2, peer_count3) + }; + + // 2 message should be send (in total) + assert_eq!(2, queue.read().len()); + // 1 peer should be updated but only once after inserting new transaction + assert_eq!(1, peer_count2); + assert_eq!(0, peer_count3); + // TRANSACTIONS_PACKET + assert_eq!(0x02, queue.read()[0].packet_id); + assert_eq!(0x02, queue.read()[1].packet_id); + } + + #[test] + fn should_maintain_transations_propagation_stats() { + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Uncle); + client.insert_transaction_to_queue(); + let mut sync = dummy_sync_with_peer(client.block_hash_delta_minus(1), &client); + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + + let stats = sync.transactions_stats(); + assert_eq!(stats.len(), 1, "Should maintain stats for single transaction.") + } + + #[test] + fn should_propagate_service_transaction_to_selected_peers_only() { + let mut client = TestBlockChainClient::new(); + client.insert_transaction_with_gas_price_to_queue(U256::zero()); + let block_hash = client.block_hash_delta_minus(1); + let mut sync = ChainSync::new(SyncConfig::default(), &client, Arc::new(NoopPrivateTxHandler)); + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + // when peer#1 is Geth + insert_dummy_peer(&mut sync, 1, block_hash); + io.peers_info.insert(1, "Geth".to_owned()); + // and peer#2 is Parity, accepting service transactions + insert_dummy_peer(&mut sync, 2, block_hash); + io.peers_info.insert(2, "Parity/v1.6".to_owned()); + // and peer#3 is Parity, discarding service transactions + insert_dummy_peer(&mut sync, 3, block_hash); + io.peers_info.insert(3, "Parity/v1.5".to_owned()); + // and peer#4 is Parity, accepting service transactions + insert_dummy_peer(&mut sync, 4, block_hash); + io.peers_info.insert(4, "Parity/v1.7.3-ABCDEFGH".to_owned()); + + // and new service transaction is propagated to peers + SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + + // peer#2 && peer#4 are receiving service transaction + assert!(io.packets.iter().any(|p| p.packet_id == 0x02 && p.recipient == 2)); // TRANSACTIONS_PACKET + assert!(io.packets.iter().any(|p| p.packet_id == 0x02 && p.recipient == 4)); // TRANSACTIONS_PACKET + assert_eq!(io.packets.len(), 2); + } + + #[test] + fn should_propagate_service_transaction_is_sent_as_separate_message() { + let mut client = TestBlockChainClient::new(); + let tx1_hash = client.insert_transaction_to_queue(); + let tx2_hash = client.insert_transaction_with_gas_price_to_queue(U256::zero()); + let block_hash = client.block_hash_delta_minus(1); + let mut sync = ChainSync::new(SyncConfig::default(), &client, Arc::new(NoopPrivateTxHandler)); + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + // when peer#1 is Parity, accepting service transactions + insert_dummy_peer(&mut sync, 1, block_hash); + io.peers_info.insert(1, "Parity/v1.6".to_owned()); + + // and service + non-service transactions are propagated to peers + SyncPropagator::propagate_new_transactions(&mut sync, &mut io); + + // two separate packets for peer are queued: + // 1) with non-service-transaction + // 2) with service transaction + let sent_transactions: Vec = io.packets.iter() + .filter_map(|p| { + if p.packet_id != 0x02 || p.recipient != 1 { // TRANSACTIONS_PACKET + return None; + } + + let rlp = Rlp::new(&*p.data); + let item_count = rlp.item_count().unwrap_or(0); + if item_count != 1 { + return None; + } + + rlp.at(0).ok().and_then(|r| r.as_val().ok()) + }) + .collect(); + assert_eq!(sent_transactions.len(), 2); + assert!(sent_transactions.iter().any(|tx| tx.hash() == tx1_hash)); + assert!(sent_transactions.iter().any(|tx| tx.hash() == tx2_hash)); + } +} diff --git a/ethcore/sync/src/chain/requester.rs b/ethcore/sync/src/chain/requester.rs new file mode 100644 index 00000000000..e6acf6bc53a --- /dev/null +++ b/ethcore/sync/src/chain/requester.rs @@ -0,0 +1,154 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use api::WARP_SYNC_PROTOCOL_ID; +use block_sync::BlockRequest; +use bytes::Bytes; +use ethcore::header::BlockNumber; +use ethereum_types::H256; +use network::{PeerId, PacketId}; +use rlp::RlpStream; +use std::time::Instant; +use sync_io::SyncIo; + +use super::{ + BlockSet, + ChainSync, + PeerAsking, + ETH_PACKET_COUNT, + GET_BLOCK_BODIES_PACKET, + GET_BLOCK_HEADERS_PACKET, + GET_RECEIPTS_PACKET, + GET_SNAPSHOT_DATA_PACKET, + GET_SNAPSHOT_MANIFEST_PACKET, +}; + +/// The Chain Sync Requester: requesting data to other peers +pub struct SyncRequester; + +impl SyncRequester { + /// Perform block download request` + pub fn request_blocks(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, request: BlockRequest, block_set: BlockSet) { + match request { + BlockRequest::Headers { start, count, skip } => { + SyncRequester::request_headers_by_hash(sync, io, peer_id, &start, count, skip, false, block_set); + }, + BlockRequest::Bodies { hashes } => { + SyncRequester::request_bodies(sync, io, peer_id, hashes, block_set); + }, + BlockRequest::Receipts { hashes } => { + SyncRequester::request_receipts(sync, io, peer_id, hashes, block_set); + }, + } + } + + /// Request block bodies from a peer + fn request_bodies(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, hashes: Vec, set: BlockSet) { + let mut rlp = RlpStream::new_list(hashes.len()); + trace!(target: "sync", "{} <- GetBlockBodies: {} entries starting from {:?}, set = {:?}", peer_id, hashes.len(), hashes.first(), set); + for h in &hashes { + rlp.append(&h.clone()); + } + SyncRequester::send_request(sync, io, peer_id, PeerAsking::BlockBodies, GET_BLOCK_BODIES_PACKET, rlp.out()); + let peer = sync.peers.get_mut(&peer_id).expect("peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed"); + peer.asking_blocks = hashes; + peer.block_set = Some(set); + } + + /// Request headers from a peer by block number + pub fn request_fork_header(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, n: BlockNumber) { + trace!(target: "sync", "{} <- GetForkHeader: at {}", peer_id, n); + let mut rlp = RlpStream::new_list(4); + rlp.append(&n); + rlp.append(&1u32); + rlp.append(&0u32); + rlp.append(&0u32); + SyncRequester::send_request(sync, io, peer_id, PeerAsking::ForkHeader, GET_BLOCK_HEADERS_PACKET, rlp.out()); + } + + /// Find some headers or blocks to download for a peer. + pub fn request_snapshot_data(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId) { + // find chunk data to download + if let Some(hash) = sync.snapshot.needed_chunk() { + if let Some(ref mut peer) = sync.peers.get_mut(&peer_id) { + peer.asking_snapshot_data = Some(hash.clone()); + } + SyncRequester::request_snapshot_chunk(sync, io, peer_id, &hash); + } + } + + /// Request snapshot manifest from a peer. + pub fn request_snapshot_manifest(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId) { + trace!(target: "sync", "{} <- GetSnapshotManifest", peer_id); + let rlp = RlpStream::new_list(0); + SyncRequester::send_request(sync, io, peer_id, PeerAsking::SnapshotManifest, GET_SNAPSHOT_MANIFEST_PACKET, rlp.out()); + } + + /// Request headers from a peer by block hash + fn request_headers_by_hash(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, h: &H256, count: u64, skip: u64, reverse: bool, set: BlockSet) { + trace!(target: "sync", "{} <- GetBlockHeaders: {} entries starting from {}, set = {:?}", peer_id, count, h, set); + let mut rlp = RlpStream::new_list(4); + rlp.append(h); + rlp.append(&count); + rlp.append(&skip); + rlp.append(&if reverse {1u32} else {0u32}); + SyncRequester::send_request(sync, io, peer_id, PeerAsking::BlockHeaders, GET_BLOCK_HEADERS_PACKET, rlp.out()); + let peer = sync.peers.get_mut(&peer_id).expect("peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed"); + peer.asking_hash = Some(h.clone()); + peer.block_set = Some(set); + } + + /// Request block receipts from a peer + fn request_receipts(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, hashes: Vec, set: BlockSet) { + let mut rlp = RlpStream::new_list(hashes.len()); + trace!(target: "sync", "{} <- GetBlockReceipts: {} entries starting from {:?}, set = {:?}", peer_id, hashes.len(), hashes.first(), set); + for h in &hashes { + rlp.append(&h.clone()); + } + SyncRequester::send_request(sync, io, peer_id, PeerAsking::BlockReceipts, GET_RECEIPTS_PACKET, rlp.out()); + let peer = sync.peers.get_mut(&peer_id).expect("peer_id may originate either from on_packet, where it is already validated or from enumerating self.peers. qed"); + peer.asking_blocks = hashes; + peer.block_set = Some(set); + } + + /// Request snapshot chunk from a peer. + fn request_snapshot_chunk(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, chunk: &H256) { + trace!(target: "sync", "{} <- GetSnapshotData {:?}", peer_id, chunk); + let mut rlp = RlpStream::new_list(1); + rlp.append(chunk); + SyncRequester::send_request(sync, io, peer_id, PeerAsking::SnapshotData, GET_SNAPSHOT_DATA_PACKET, rlp.out()); + } + + /// Generic request sender + fn send_request(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId, asking: PeerAsking, packet_id: PacketId, packet: Bytes) { + if let Some(ref mut peer) = sync.peers.get_mut(&peer_id) { + if peer.asking != PeerAsking::Nothing { + warn!(target:"sync", "Asking {:?} while requesting {:?}", peer.asking, asking); + } + peer.asking = asking; + peer.ask_time = Instant::now(); + let result = if packet_id >= ETH_PACKET_COUNT { + io.send_protocol(WARP_SYNC_PROTOCOL_ID, peer_id, packet_id, packet) + } else { + io.send(peer_id, packet_id, packet) + }; + if let Err(e) = result { + debug!(target:"sync", "Error sending request: {:?}", e); + io.disconnect_peer(peer_id); + } + } + } +} diff --git a/ethcore/sync/src/chain/supplier.rs b/ethcore/sync/src/chain/supplier.rs new file mode 100644 index 00000000000..0bfb8569823 --- /dev/null +++ b/ethcore/sync/src/chain/supplier.rs @@ -0,0 +1,446 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use bytes::Bytes; +use ethcore::client::BlockId; +use ethcore::header::BlockNumber; +use ethereum_types::H256; +use network::{self, PeerId}; +use parking_lot::RwLock; +use rlp::{Rlp, RlpStream}; +use std::cmp; +use sync_io::SyncIo; + +use super::{ + ChainSync, + RlpResponseResult, + PacketDecodeError, + BLOCK_BODIES_PACKET, + BLOCK_HEADERS_PACKET, + CONSENSUS_DATA_PACKET, + GET_BLOCK_BODIES_PACKET, + GET_BLOCK_HEADERS_PACKET, + GET_NODE_DATA_PACKET, + GET_RECEIPTS_PACKET, + GET_SNAPSHOT_DATA_PACKET, + GET_SNAPSHOT_MANIFEST_PACKET, + MAX_BODIES_TO_SEND, + MAX_HEADERS_TO_SEND, + MAX_NODE_DATA_TO_SEND, + MAX_RECEIPTS_HEADERS_TO_SEND, + MAX_RECEIPTS_TO_SEND, + NODE_DATA_PACKET, + RECEIPTS_PACKET, + SNAPSHOT_DATA_PACKET, + SNAPSHOT_MANIFEST_PACKET, +}; + +/// The Chain Sync Supplier: answers requests from peers with available data +pub struct SyncSupplier; + +impl SyncSupplier { + /// Dispatch incoming requests and responses + pub fn dispatch_packet(sync: &RwLock, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { + let rlp = Rlp::new(data); + let result = match packet_id { + GET_BLOCK_BODIES_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, + SyncSupplier::return_block_bodies, + |e| format!("Error sending block bodies: {:?}", e)), + + GET_BLOCK_HEADERS_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, + SyncSupplier::return_block_headers, + |e| format!("Error sending block headers: {:?}", e)), + + GET_RECEIPTS_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, + SyncSupplier::return_receipts, + |e| format!("Error sending receipts: {:?}", e)), + + GET_NODE_DATA_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, + SyncSupplier::return_node_data, + |e| format!("Error sending nodes: {:?}", e)), + + GET_SNAPSHOT_MANIFEST_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, + SyncSupplier::return_snapshot_manifest, + |e| format!("Error sending snapshot manifest: {:?}", e)), + + GET_SNAPSHOT_DATA_PACKET => SyncSupplier::return_rlp(io, &rlp, peer, + SyncSupplier::return_snapshot_data, + |e| format!("Error sending snapshot data: {:?}", e)), + CONSENSUS_DATA_PACKET => ChainSync::on_consensus_packet(io, peer, &rlp), + _ => { + sync.write().on_packet(io, peer, packet_id, data); + Ok(()) + } + }; + result.unwrap_or_else(|e| { + debug!(target:"sync", "{} -> Malformed packet {} : {}", peer, packet_id, e); + }) + } + + /// Respond to GetBlockHeaders request + fn return_block_headers(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { + // Packet layout: + // [ block: { P , B_32 }, maxHeaders: P, skip: P, reverse: P in { 0 , 1 } ] + let max_headers: usize = r.val_at(1)?; + let skip: usize = r.val_at(2)?; + let reverse: bool = r.val_at(3)?; + let last = io.chain().chain_info().best_block_number; + let number = if r.at(0)?.size() == 32 { + // id is a hash + let hash: H256 = r.val_at(0)?; + trace!(target: "sync", "{} -> GetBlockHeaders (hash: {}, max: {}, skip: {}, reverse:{})", peer_id, hash, max_headers, skip, reverse); + match io.chain().block_header(BlockId::Hash(hash)) { + Some(hdr) => { + let number = hdr.number().into(); + debug_assert_eq!(hdr.hash(), hash); + + if max_headers == 1 || io.chain().block_hash(BlockId::Number(number)) != Some(hash) { + // Non canonical header or single header requested + // TODO: handle single-step reverse hashchains of non-canon hashes + trace!(target:"sync", "Returning single header: {:?}", hash); + let mut rlp = RlpStream::new_list(1); + rlp.append_raw(&hdr.into_inner(), 1); + return Ok(Some((BLOCK_HEADERS_PACKET, rlp))); + } + number + } + None => return Ok(Some((BLOCK_HEADERS_PACKET, RlpStream::new_list(0)))) //no such header, return nothing + } + } else { + trace!(target: "sync", "{} -> GetBlockHeaders (number: {}, max: {}, skip: {}, reverse:{})", peer_id, r.val_at::(0)?, max_headers, skip, reverse); + r.val_at(0)? + }; + + let mut number = if reverse { + cmp::min(last, number) + } else { + cmp::max(0, number) + }; + let max_count = cmp::min(MAX_HEADERS_TO_SEND, max_headers); + let mut count = 0; + let mut data = Bytes::new(); + let inc = (skip + 1) as BlockNumber; + let overlay = io.chain_overlay().read(); + + while number <= last && count < max_count { + if let Some(hdr) = overlay.get(&number) { + trace!(target: "sync", "{}: Returning cached fork header", peer_id); + data.extend_from_slice(hdr); + count += 1; + } else if let Some(hdr) = io.chain().block_header(BlockId::Number(number)) { + data.append(&mut hdr.into_inner()); + count += 1; + } else { + // No required block. + break; + } + if reverse { + if number <= inc || number == 0 { + break; + } + number -= inc; + } + else { + number += inc; + } + } + let mut rlp = RlpStream::new_list(count as usize); + rlp.append_raw(&data, count as usize); + trace!(target: "sync", "{} -> GetBlockHeaders: returned {} entries", peer_id, count); + Ok(Some((BLOCK_HEADERS_PACKET, rlp))) + } + + /// Respond to GetBlockBodies request + fn return_block_bodies(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { + let mut count = r.item_count().unwrap_or(0); + if count == 0 { + debug!(target: "sync", "Empty GetBlockBodies request, ignoring."); + return Ok(None); + } + count = cmp::min(count, MAX_BODIES_TO_SEND); + let mut added = 0usize; + let mut data = Bytes::new(); + for i in 0..count { + if let Some(body) = io.chain().block_body(BlockId::Hash(r.val_at::(i)?)) { + data.append(&mut body.into_inner()); + added += 1; + } + } + let mut rlp = RlpStream::new_list(added); + rlp.append_raw(&data, added); + trace!(target: "sync", "{} -> GetBlockBodies: returned {} entries", peer_id, added); + Ok(Some((BLOCK_BODIES_PACKET, rlp))) + } + + /// Respond to GetNodeData request + fn return_node_data(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { + let mut count = r.item_count().unwrap_or(0); + trace!(target: "sync", "{} -> GetNodeData: {} entries", peer_id, count); + if count == 0 { + debug!(target: "sync", "Empty GetNodeData request, ignoring."); + return Ok(None); + } + count = cmp::min(count, MAX_NODE_DATA_TO_SEND); + let mut added = 0usize; + let mut data = Vec::new(); + for i in 0..count { + if let Some(node) = io.chain().state_data(&r.val_at::(i)?) { + data.push(node); + added += 1; + } + } + trace!(target: "sync", "{} -> GetNodeData: return {} entries", peer_id, added); + let mut rlp = RlpStream::new_list(added); + for d in data { + rlp.append(&d); + } + Ok(Some((NODE_DATA_PACKET, rlp))) + } + + fn return_receipts(io: &SyncIo, rlp: &Rlp, peer_id: PeerId) -> RlpResponseResult { + let mut count = rlp.item_count().unwrap_or(0); + trace!(target: "sync", "{} -> GetReceipts: {} entries", peer_id, count); + if count == 0 { + debug!(target: "sync", "Empty GetReceipts request, ignoring."); + return Ok(None); + } + count = cmp::min(count, MAX_RECEIPTS_HEADERS_TO_SEND); + let mut added_headers = 0usize; + let mut added_receipts = 0usize; + let mut data = Bytes::new(); + for i in 0..count { + if let Some(mut receipts_bytes) = io.chain().block_receipts(&rlp.val_at::(i)?) { + data.append(&mut receipts_bytes); + added_receipts += receipts_bytes.len(); + added_headers += 1; + if added_receipts > MAX_RECEIPTS_TO_SEND { break; } + } + } + let mut rlp_result = RlpStream::new_list(added_headers); + rlp_result.append_raw(&data, added_headers); + Ok(Some((RECEIPTS_PACKET, rlp_result))) + } + + /// Respond to GetSnapshotManifest request + fn return_snapshot_manifest(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { + let count = r.item_count().unwrap_or(0); + trace!(target: "sync", "{} -> GetSnapshotManifest", peer_id); + if count != 0 { + debug!(target: "sync", "Invalid GetSnapshotManifest request, ignoring."); + return Ok(None); + } + let rlp = match io.snapshot_service().manifest() { + Some(manifest) => { + trace!(target: "sync", "{} <- SnapshotManifest", peer_id); + let mut rlp = RlpStream::new_list(1); + rlp.append_raw(&manifest.into_rlp(), 1); + rlp + }, + None => { + trace!(target: "sync", "{}: No manifest to return", peer_id); + RlpStream::new_list(0) + } + }; + Ok(Some((SNAPSHOT_MANIFEST_PACKET, rlp))) + } + + /// Respond to GetSnapshotData request + fn return_snapshot_data(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { + let hash: H256 = r.val_at(0)?; + trace!(target: "sync", "{} -> GetSnapshotData {:?}", peer_id, hash); + let rlp = match io.snapshot_service().chunk(hash) { + Some(data) => { + let mut rlp = RlpStream::new_list(1); + trace!(target: "sync", "{} <- SnapshotData", peer_id); + rlp.append(&data); + rlp + }, + None => { + RlpStream::new_list(0) + } + }; + Ok(Some((SNAPSHOT_DATA_PACKET, rlp))) + } + + fn return_rlp(io: &mut SyncIo, rlp: &Rlp, peer: PeerId, rlp_func: FRlp, error_func: FError) -> Result<(), PacketDecodeError> + where FRlp : Fn(&SyncIo, &Rlp, PeerId) -> RlpResponseResult, + FError : FnOnce(network::Error) -> String + { + let response = rlp_func(io, rlp, peer); + match response { + Err(e) => Err(e), + Ok(Some((packet_id, rlp_stream))) => { + io.respond(packet_id, rlp_stream.out()).unwrap_or_else( + |e| debug!(target: "sync", "{:?}", error_func(e))); + Ok(()) + } + _ => Ok(()) + } + } +} + +#[cfg(test)] +mod test { + use std::collections::{VecDeque}; + use tests::helpers::{TestIo}; + use tests::snapshot::TestSnapshotService; + use ethereum_types::{H256}; + use parking_lot::RwLock; + use bytes::Bytes; + use rlp::{Rlp, RlpStream}; + use super::{*, super::tests::*}; + use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient}; + + #[test] + fn return_block_headers() { + use ethcore::views::HeaderView; + fn make_hash_req(h: &H256, count: usize, skip: usize, reverse: bool) -> Bytes { + let mut rlp = RlpStream::new_list(4); + rlp.append(h); + rlp.append(&count); + rlp.append(&skip); + rlp.append(&if reverse {1u32} else {0u32}); + rlp.out() + } + + fn make_num_req(n: usize, count: usize, skip: usize, reverse: bool) -> Bytes { + let mut rlp = RlpStream::new_list(4); + rlp.append(&n); + rlp.append(&count); + rlp.append(&skip); + rlp.append(&if reverse {1u32} else {0u32}); + rlp.out() + } + fn to_header_vec(rlp: ::chain::RlpResponseResult) -> Vec { + Rlp::new(&rlp.unwrap().unwrap().1.out()).iter().map(|r| r.as_raw().to_vec()).collect() + } + + let mut client = TestBlockChainClient::new(); + client.add_blocks(100, EachBlockWith::Nothing); + let blocks: Vec<_> = (0 .. 100) + .map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).map(|b| b.into_inner()).unwrap()).collect(); + let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).unwrap().as_raw().to_vec()).collect(); + let hashes: Vec<_> = headers.iter().map(|h| view!(HeaderView, h).hash()).collect(); + + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let io = TestIo::new(&mut client, &ss, &queue, None); + + let unknown: H256 = H256::new(); + let result = SyncSupplier::return_block_headers(&io, &Rlp::new(&make_hash_req(&unknown, 1, 0, false)), 0); + assert!(to_header_vec(result).is_empty()); + let result = SyncSupplier::return_block_headers(&io, &Rlp::new(&make_hash_req(&unknown, 1, 0, true)), 0); + assert!(to_header_vec(result).is_empty()); + + let result = SyncSupplier::return_block_headers(&io, &Rlp::new(&make_hash_req(&hashes[2], 1, 0, true)), 0); + assert_eq!(to_header_vec(result), vec![headers[2].clone()]); + + let result = SyncSupplier::return_block_headers(&io, &Rlp::new(&make_hash_req(&hashes[2], 1, 0, false)), 0); + assert_eq!(to_header_vec(result), vec![headers[2].clone()]); + + let result = SyncSupplier::return_block_headers(&io, &Rlp::new(&make_hash_req(&hashes[50], 3, 5, false)), 0); + assert_eq!(to_header_vec(result), vec![headers[50].clone(), headers[56].clone(), headers[62].clone()]); + + let result = SyncSupplier::return_block_headers(&io, &Rlp::new(&make_hash_req(&hashes[50], 3, 5, true)), 0); + assert_eq!(to_header_vec(result), vec![headers[50].clone(), headers[44].clone(), headers[38].clone()]); + + let result = SyncSupplier::return_block_headers(&io, &Rlp::new(&make_num_req(2, 1, 0, true)), 0); + assert_eq!(to_header_vec(result), vec![headers[2].clone()]); + + let result = SyncSupplier::return_block_headers(&io, &Rlp::new(&make_num_req(2, 1, 0, false)), 0); + assert_eq!(to_header_vec(result), vec![headers[2].clone()]); + + let result = SyncSupplier::return_block_headers(&io, &Rlp::new(&make_num_req(50, 3, 5, false)), 0); + assert_eq!(to_header_vec(result), vec![headers[50].clone(), headers[56].clone(), headers[62].clone()]); + + let result = SyncSupplier::return_block_headers(&io, &Rlp::new(&make_num_req(50, 3, 5, true)), 0); + assert_eq!(to_header_vec(result), vec![headers[50].clone(), headers[44].clone(), headers[38].clone()]); + } + + #[test] + fn return_nodes() { + let mut client = TestBlockChainClient::new(); + let queue = RwLock::new(VecDeque::new()); + let sync = dummy_sync_with_peer(H256::new(), &client); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + let mut node_list = RlpStream::new_list(3); + node_list.append(&H256::from("0000000000000000000000000000000000000000000000005555555555555555")); + node_list.append(&H256::from("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa")); + node_list.append(&H256::from("aff0000000000000000000000000000000000000000000000000000000000000")); + + let node_request = node_list.out(); + // it returns rlp ONLY for hashes started with "f" + let result = SyncSupplier::return_node_data(&io, &Rlp::new(&node_request.clone()), 0); + + assert!(result.is_ok()); + let rlp_result = result.unwrap(); + assert!(rlp_result.is_some()); + + // the length of one rlp-encoded hashe + let rlp = rlp_result.unwrap().1.out(); + let rlp = Rlp::new(&rlp); + assert_eq!(Ok(1), rlp.item_count()); + + io.sender = Some(2usize); + + ChainSync::dispatch_packet(&RwLock::new(sync), &mut io, 0usize, GET_NODE_DATA_PACKET, &node_request); + assert_eq!(1, io.packets.len()); + } + + #[test] + fn return_receipts_empty() { + let mut client = TestBlockChainClient::new(); + let queue = RwLock::new(VecDeque::new()); + let ss = TestSnapshotService::new(); + let io = TestIo::new(&mut client, &ss, &queue, None); + + let result = SyncSupplier::return_receipts(&io, &Rlp::new(&[0xc0]), 0); + + assert!(result.is_ok()); + } + + #[test] + fn return_receipts() { + let mut client = TestBlockChainClient::new(); + let queue = RwLock::new(VecDeque::new()); + let sync = dummy_sync_with_peer(H256::new(), &client); + let ss = TestSnapshotService::new(); + let mut io = TestIo::new(&mut client, &ss, &queue, None); + + let mut receipt_list = RlpStream::new_list(4); + receipt_list.append(&H256::from("0000000000000000000000000000000000000000000000005555555555555555")); + receipt_list.append(&H256::from("ff00000000000000000000000000000000000000000000000000000000000000")); + receipt_list.append(&H256::from("fff0000000000000000000000000000000000000000000000000000000000000")); + receipt_list.append(&H256::from("aff0000000000000000000000000000000000000000000000000000000000000")); + + let receipts_request = receipt_list.out(); + // it returns rlp ONLY for hashes started with "f" + let result = SyncSupplier::return_receipts(&io, &Rlp::new(&receipts_request.clone()), 0); + + assert!(result.is_ok()); + let rlp_result = result.unwrap(); + assert!(rlp_result.is_some()); + + // the length of two rlp-encoded receipts + assert_eq!(603, rlp_result.unwrap().1.out().len()); + + io.sender = Some(2usize); + ChainSync::dispatch_packet(&RwLock::new(sync), &mut io, 0usize, GET_RECEIPTS_PACKET, &receipts_request); + assert_eq!(1, io.packets.len()); + } +} diff --git a/ethcore/sync/src/tests/snapshot.rs b/ethcore/sync/src/tests/snapshot.rs index 2f6441f4f28..804ebe9c535 100644 --- a/ethcore/sync/src/tests/snapshot.rs +++ b/ethcore/sync/src/tests/snapshot.rs @@ -22,7 +22,7 @@ use parking_lot::Mutex; use bytes::Bytes; use ethcore::snapshot::{SnapshotService, ManifestData, RestorationStatus}; use ethcore::header::BlockNumber; -use ethcore::client::{EachBlockWith}; +use ethcore::client::EachBlockWith; use super::helpers::*; use {SyncConfig, WarpSync}; @@ -99,7 +99,15 @@ impl SnapshotService for TestSnapshotService { } fn begin_restore(&self, manifest: ManifestData) { - *self.restoration_manifest.lock() = Some(manifest); + let mut restoration_manifest = self.restoration_manifest.lock(); + + if let Some(ref c_manifest) = *restoration_manifest { + if c_manifest.state_root == manifest.state_root { + return; + } + } + + *restoration_manifest = Some(manifest); self.state_restoration_chunks.lock().clear(); self.block_restoration_chunks.lock().clear(); } From 842b75c0e63f76e1b77d75529c7f6c3f4969d8d7 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 9 May 2018 12:05:56 +0200 Subject: [PATCH 47/95] Decoding headers can fail (#8570) * rlp::decode returns Result * Fix journaldb to handle rlp::decode Result * Fix ethcore to work with rlp::decode returning Result * Light client handles rlp::decode returning Result * Fix tests in rlp_derive * Fix tests * Cleanup * cleanup * Allow panic rather than breaking out of iterator * Let decoding failures when reading from disk blow up * syntax * Fix the trivial grumbles * Fix failing tests * Make Account::from_rlp return Result * Syntx, sigh * Temp-fix for decoding failures * Header::decode returns Result Handle new return type throughout the code base. * Do not continue reading from the DB when a value could not be read * Fix tests * Handle header decoding in light_sync * Handling header decoding errors * Let the DecodeError bubble up unchanged * Remove redundant error conversion --- ethcore/light/src/client/header_chain.rs | 10 ++++--- ethcore/light/src/client/mod.rs | 12 ++++++-- ethcore/src/client/client.rs | 14 ++++++---- ethcore/src/client/test_client.rs | 5 ++-- ethcore/src/encoded.rs | 6 ++-- ethcore/src/engines/authority_round/mod.rs | 2 +- ethcore/src/error.rs | 10 +++++-- ethcore/src/miner/miner.rs | 11 ++++++-- ethcore/src/snapshot/mod.rs | 2 +- ethcore/src/verification/verification.rs | 5 ++-- ethcore/sync/src/light_sync/response.rs | 32 ++++++++++++---------- ethcore/sync/src/light_sync/tests/mod.rs | 2 +- rpc/src/v1/helpers/errors.rs | 13 +++++++++ rpc/src/v1/impls/eth.rs | 13 +++++---- rpc/src/v1/impls/light/eth.rs | 2 +- rpc/src/v1/impls/light/parity.rs | 2 +- rpc/src/v1/impls/parity.rs | 4 +-- rpc/src/v1/impls/traces.rs | 6 ++-- 18 files changed, 98 insertions(+), 53 deletions(-) diff --git a/ethcore/light/src/client/header_chain.rs b/ethcore/light/src/client/header_chain.rs index 02a18a60dfe..b85091e53bf 100644 --- a/ethcore/light/src/client/header_chain.rs +++ b/ethcore/light/src/client/header_chain.rs @@ -305,7 +305,7 @@ impl HeaderChain { batch.put(col, cht_key(cht_num as u64).as_bytes(), &::rlp::encode(cht_root)); } - let decoded_header = hardcoded_sync.header.decode(); + let decoded_header = hardcoded_sync.header.decode()?; let decoded_header_num = decoded_header.number(); // write the block in the DB. @@ -585,7 +585,7 @@ impl HeaderChain { bail!(ErrorKind::Database(msg.into())); }; - let decoded = header.decode(); + let decoded = header.decode().expect("decoding db value failed"); let entry: Entry = { let bytes = self.db.get(self.col, era_key(h_num).as_bytes())? @@ -815,7 +815,9 @@ impl HeaderChain { for hdr in self.ancestry_iter(BlockId::Hash(parent_hash)) { if let Some(transition) = live_proofs.get(&hdr.hash()).cloned() { - return Some((hdr.decode(), transition.proof)) + return hdr.decode().map(|decoded_hdr| { + (decoded_hdr, transition.proof) + }).ok(); } } @@ -1224,7 +1226,7 @@ mod tests { let hardcoded_sync = chain.read_hardcoded_sync().expect("failed reading hardcoded sync").expect("failed unwrapping hardcoded sync"); assert_eq!(hardcoded_sync.chts.len(), 3); assert_eq!(hardcoded_sync.total_difficulty, total_difficulty); - let decoded: Header = hardcoded_sync.header.decode(); + let decoded: Header = hardcoded_sync.header.decode().expect("decoding failed"); assert_eq!(decoded.number(), h_num); } } diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index cf603d853f0..82b424cc833 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -318,7 +318,7 @@ impl Client { let epoch_proof = self.engine.is_epoch_end( &verified_header, - &|h| self.chain.block_header(BlockId::Hash(h)).map(|hdr| hdr.decode()), + &|h| self.chain.block_header(BlockId::Hash(h)).and_then(|hdr| hdr.decode().ok()), &|h| self.chain.pending_transition(h), ); @@ -426,7 +426,15 @@ impl Client { }; // Verify Block Family - let verify_family_result = self.engine.verify_block_family(&verified_header, &parent_header.decode()); + + let verify_family_result = { + parent_header.decode() + .map_err(|dec_err| dec_err.into()) + .and_then(|decoded| { + self.engine.verify_block_family(&verified_header, &decoded) + }) + + }; if let Err(e) = verify_family_result { warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", verified_header.number(), verified_header.hash(), e); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index bffa4e38ba8..76d78e3df63 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1219,8 +1219,7 @@ impl Client { => Some(self.chain.read().best_block_header()), BlockId::Number(number) if number == self.chain.read().best_block_number() => Some(self.chain.read().best_block_header()), - _ - => self.block_header(id).map(|h| h.decode()), + _ => self.block_header(id).and_then(|h| h.decode().ok()) } } } @@ -1915,7 +1914,11 @@ impl BlockChainClient for Client { fn uncle_extra_info(&self, id: UncleId) -> Option> { self.uncle(id) - .map(|header| self.engine.extra_info(&header.decode())) + .and_then(|h| { + h.decode().map(|dh| { + self.engine.extra_info(&dh) + }).ok() + }) } fn pruning_info(&self) -> PruningInfo { @@ -2033,7 +2036,8 @@ impl ReopenBlock for Client { for h in uncles { if !block.uncles().iter().any(|header| header.hash() == h) { let uncle = chain.block_header_data(&h).expect("find_uncle_hashes only returns hashes for existing headers; qed"); - block.push_uncle(uncle.decode()).expect("pushing up to maximum_uncle_count; + let uncle = uncle.decode().expect("decoding failure"); + block.push_uncle(uncle).expect("pushing up to maximum_uncle_count; push_uncle is not ok only if more than maximum_uncle_count is pushed; so all push_uncle are Ok; qed"); @@ -2074,7 +2078,7 @@ impl PrepareOpenBlock for Client { .into_iter() .take(engine.maximum_uncle_count(open_block.header().number())) .foreach(|h| { - open_block.push_uncle(h.decode()).expect("pushing maximum_uncle_count; + open_block.push_uncle(h.decode().expect("decoding failure")).expect("pushing maximum_uncle_count; open_block was just created; push_uncle is not ok only if more than maximum_uncle_count is pushed; so all push_uncle are Ok; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index b229159667d..6a3166f7c04 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -289,7 +289,7 @@ impl TestBlockChainClient { /// Make a bad block by setting invalid extra data. pub fn corrupt_block(&self, n: BlockNumber) { let hash = self.block_hash(BlockId::Number(n)).unwrap(); - let mut header: BlockHeader = self.block_header(BlockId::Number(n)).unwrap().decode(); + let mut header: BlockHeader = self.block_header(BlockId::Number(n)).unwrap().decode().expect("decoding failed"); header.set_extra_data(b"This extra data is way too long to be considered valid".to_vec()); let mut rlp = RlpStream::new_list(3); rlp.append(&header); @@ -301,7 +301,7 @@ impl TestBlockChainClient { /// Make a bad block by setting invalid parent hash. pub fn corrupt_block_parent(&self, n: BlockNumber) { let hash = self.block_hash(BlockId::Number(n)).unwrap(); - let mut header: BlockHeader = self.block_header(BlockId::Number(n)).unwrap().decode(); + let mut header: BlockHeader = self.block_header(BlockId::Number(n)).unwrap().decode().expect("decoding failed"); header.set_parent_hash(H256::from(42)); let mut rlp = RlpStream::new_list(3); rlp.append(&header); @@ -479,6 +479,7 @@ impl BlockInfo for TestBlockChainClient { self.block_header(BlockId::Hash(self.chain_info().best_block_hash)) .expect("Best block always has header.") .decode() + .expect("decoding failed") } fn block(&self, id: BlockId) -> Option { diff --git a/ethcore/src/encoded.rs b/ethcore/src/encoded.rs index 01df386cc2e..c436607f8c3 100644 --- a/ethcore/src/encoded.rs +++ b/ethcore/src/encoded.rs @@ -28,7 +28,7 @@ use ethereum_types::{H256, Bloom, U256, Address}; use hash::keccak; use header::{BlockNumber, Header as FullHeader}; use heapsize::HeapSizeOf; -use rlp::{Rlp, RlpStream}; +use rlp::{self, Rlp, RlpStream}; use transaction::UnverifiedTransaction; use views::{self, BlockView, HeaderView, BodyView}; @@ -47,7 +47,9 @@ impl Header { pub fn new(encoded: Vec) -> Self { Header(encoded) } /// Upgrade this encoded view to a fully owned `Header` object. - pub fn decode(&self) -> FullHeader { ::rlp::decode(&self.0).expect("decoding failure") } + pub fn decode(&self) -> Result { + rlp::decode(&self.0) + } /// Get a borrowed header view onto the data. #[inline] diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index c2aee7c6efc..ed9a9a4f251 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -996,7 +996,7 @@ impl Engine for AuthorityRound { let parent = client.block_header(::client::BlockId::Hash(*block.header().parent_hash())) .expect("hash is from parent; parent header must exist; qed") - .decode(); + .decode()?; let parent_step = header_step(&parent, self.empty_steps_transition)?; let current_step = self.step.load(); diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 561701e7620..bec749297cb 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -290,6 +290,12 @@ error_chain! { description("Unknown engine name") display("Unknown engine name ({})", name) } + + #[doc = "RLP decoding errors"] + Decoder(err: ::rlp::DecoderError) { + description("decoding value failed") + display("decoding value failed with error: {}", err) + } } } @@ -310,11 +316,11 @@ impl From for Error { fn from(err: AccountsError) -> Error { ErrorKind::AccountProvider(err).into() } -} +} impl From<::rlp::DecoderError> for Error { fn from(err: ::rlp::DecoderError) -> Error { - UtilError::from(err).into() + ErrorKind::Decoder(err).into() } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 76a011343fb..3168ff1a846 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -528,8 +528,8 @@ impl Miner { } /// Attempts to perform internal sealing (one that does not require work) and handles the result depending on the type of Seal. - fn seal_and_import_block_internally(&self, chain: &C, block: ClosedBlock) -> bool where - C: BlockChain + SealedBlockImporter, + fn seal_and_import_block_internally(&self, chain: &C, block: ClosedBlock) -> bool + where C: BlockChain + SealedBlockImporter, { { let sealing = self.sealing.lock(); @@ -544,7 +544,12 @@ impl Miner { trace!(target: "miner", "seal_block_internally: attempting internal seal."); let parent_header = match chain.block_header(BlockId::Hash(*block.header().parent_hash())) { - Some(hdr) => hdr.decode(), + Some(h) => { + match h.decode() { + Ok(decoded_hdr) => decoded_hdr, + Err(_) => return false + } + } None => return false, }; diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index 94236e9e95d..8871ced26fa 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -487,7 +487,7 @@ pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &EthEngine, ch if always || rng.gen::() <= POW_VERIFY_RATE { engine.verify_block_unordered(header)?; match chain.block_header_data(header.parent_hash()) { - Some(parent) => engine.verify_block_family(header, &parent.decode()), + Some(parent) => engine.verify_block_family(header, &parent.decode()?), None => Ok(()), } } else { diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 92f3e77f902..03a6d6f8d41 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -224,7 +224,7 @@ fn verify_uncles(header: &Header, bytes: &[u8], bc: &BlockProvider, engine: &Eth return Err(From::from(BlockError::UncleParentNotInChain(uncle_parent.hash()))); } - let uncle_parent = uncle_parent.decode(); + let uncle_parent = uncle_parent.decode()?; verify_parent(&uncle, &uncle_parent, engine)?; engine.verify_block_family(&uncle, &uncle_parent)?; verified.insert(uncle.hash()); @@ -500,10 +500,9 @@ mod tests { // no existing tests need access to test, so having this not function // is fine. let client = ::client::TestBlockChainClient::default(); - let parent = bc.block_header_data(header.parent_hash()) .ok_or(BlockError::UnknownParent(header.parent_hash().clone()))? - .decode(); + .decode()?; let full_params = FullFamilyParams { block_bytes: bytes, diff --git a/ethcore/sync/src/light_sync/response.rs b/ethcore/sync/src/light_sync/response.rs index 4dfb383d466..74665118b7f 100644 --- a/ethcore/sync/src/light_sync/response.rs +++ b/ethcore/sync/src/light_sync/response.rs @@ -16,13 +16,11 @@ //! Helpers for decoding and verifying responses for headers. -use std::fmt; - -use ethcore::encoded; -use ethcore::header::Header; +use ethcore::{self, encoded, header::Header}; +use ethereum_types::H256; use light::request::{HashOrNumber, CompleteHeadersRequest as HeadersRequest}; use rlp::DecoderError; -use ethereum_types::H256; +use std::fmt; /// Errors found when decoding headers and verifying with basic constraints. #[derive(Debug, PartialEq)] @@ -74,19 +72,23 @@ pub trait Constraint { /// Do basic verification of provided headers against a request. pub fn verify(headers: &[encoded::Header], request: &HeadersRequest) -> Result, BasicError> { - let headers: Vec<_> = headers.iter().map(|h| h.decode()).collect(); + let headers: Result, _> = headers.iter().map(|h| h.decode() ).collect(); + match headers { + Ok(headers) => { + let reverse = request.reverse; + + Max(request.max as usize).verify(&headers, reverse)?; + match request.start { + HashOrNumber::Number(ref num) => StartsAtNumber(*num).verify(&headers, reverse)?, + HashOrNumber::Hash(ref hash) => StartsAtHash(*hash).verify(&headers, reverse)?, + } - let reverse = request.reverse; + SkipsBetween(request.skip).verify(&headers, reverse)?; - Max(request.max as usize).verify(&headers, reverse)?; - match request.start { - HashOrNumber::Number(ref num) => StartsAtNumber(*num).verify(&headers, reverse)?, - HashOrNumber::Hash(ref hash) => StartsAtHash(*hash).verify(&headers, reverse)?, + Ok(headers) + }, + Err(e) => Err(e.into()) } - - SkipsBetween(request.skip).verify(&headers, reverse)?; - - Ok(headers) } struct StartsAtNumber(u64); diff --git a/ethcore/sync/src/light_sync/tests/mod.rs b/ethcore/sync/src/light_sync/tests/mod.rs index 9fd270838bf..3fee1c71707 100644 --- a/ethcore/sync/src/light_sync/tests/mod.rs +++ b/ethcore/sync/src/light_sync/tests/mod.rs @@ -45,7 +45,7 @@ fn fork_post_cht() { for id in (0..CHAIN_LENGTH).map(|x| x + 1).map(BlockId::Number) { let (light_peer, full_peer) = (net.peer(0), net.peer(1)); let light_chain = light_peer.light_chain(); - let header = full_peer.chain().block_header(id).unwrap().decode(); + let header = full_peer.chain().block_header(id).unwrap().decode().expect("decoding failure"); let _ = light_chain.import_header(header); light_chain.flush_queue(); light_chain.import_verified(); diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 4f3289a116b..c85beef7d5a 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -360,6 +360,19 @@ pub fn transaction>(error: T) -> Error { } } +pub fn decode>(error: T) -> Error { + let error = error.into(); + match *error.kind() { + ErrorKind::Decoder(ref dec_err) => rlp(dec_err.clone()), + _ => Error { + code: ErrorCode::InternalError, + message: "decoding error".into(), + data: None, + } + + } +} + pub fn rlp(error: DecoderError) -> Error { Error { code: ErrorCode::InvalidParams, diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index a7ff4916dee..389805c1765 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -343,7 +343,10 @@ impl EthClient hdr.decode(), + Some(hdr) => match hdr.decode() { + Ok(h) => h, + Err(e) => return Err(errors::decode(e)) + }, None => { return Ok(None); } }; @@ -851,9 +854,9 @@ impl Eth for EthClient< }; let state = try_bf!(self.client.state_at(id).ok_or(errors::state_pruned())); - let header = try_bf!(self.client.block_header(id).ok_or(errors::state_pruned())); + let header = try_bf!(self.client.block_header(id).ok_or(errors::state_pruned()).and_then(|h| h.decode().map_err(errors::decode))); - (state, header.decode()) + (state, header) }; let result = self.client.call(&signed, Default::default(), &mut state, &header); @@ -890,9 +893,9 @@ impl Eth for EthClient< }; let state = try_bf!(self.client.state_at(id).ok_or(errors::state_pruned())); - let header = try_bf!(self.client.block_header(id).ok_or(errors::state_pruned())); + let header = try_bf!(self.client.block_header(id).ok_or(errors::state_pruned()).and_then(|h| h.decode().map_err(errors::decode))); - (state, header.decode()) + (state, header) }; Box::new(future::done(self.client.estimate_gas(&signed, &state, &header) diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index eeef12da6e6..35f7792b52c 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -371,7 +371,7 @@ impl Eth for EthClient { } fn send_raw_transaction(&self, raw: Bytes) -> Result { - let best_header = self.client.best_block_header().decode(); + let best_header = self.client.best_block_header().decode().map_err(errors::decode)?; Rlp::new(&raw.into_vec()).as_val() .map_err(errors::rlp) diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 3d31d9e6765..982c7ff3633 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -395,7 +395,7 @@ impl Parity for ParityClient { let engine = self.light_dispatch.client.engine().clone(); let from_encoded = move |encoded: encoded::Header| { - let header = encoded.decode(); + let header = encoded.decode().expect("decoding error"); // REVIEW: not sure what to do here; what is a decent return value for the error case here? let extra_info = engine.extra_info(&header); RichHeader { inner: Header { diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index db66bddc7e9..08d5147202c 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -487,9 +487,9 @@ impl Parity for ParityClient where }; let state = self.client.state_at(id).ok_or(errors::state_pruned())?; - let header = self.client.block_header(id).ok_or(errors::state_pruned())?; + let header = self.client.block_header(id).ok_or(errors::state_pruned())?.decode().map_err(errors::decode)?; - (state, header.decode()) + (state, header) }; self.client.call_many(&requests, &mut state, &header) diff --git a/rpc/src/v1/impls/traces.rs b/rpc/src/v1/impls/traces.rs index bf4dc83beb1..0130b3b9c13 100644 --- a/rpc/src/v1/impls/traces.rs +++ b/rpc/src/v1/impls/traces.rs @@ -104,7 +104,7 @@ impl Traces for TracesClient where let mut state = self.client.state_at(id).ok_or(errors::state_pruned())?; let header = self.client.block_header(id).ok_or(errors::state_pruned())?; - self.client.call(&signed, to_call_analytics(flags), &mut state, &header.decode()) + self.client.call(&signed, to_call_analytics(flags), &mut state, &header.decode().map_err(errors::decode)?) .map(TraceResults::from) .map_err(errors::call) } @@ -131,7 +131,7 @@ impl Traces for TracesClient where let mut state = self.client.state_at(id).ok_or(errors::state_pruned())?; let header = self.client.block_header(id).ok_or(errors::state_pruned())?; - self.client.call_many(&requests, &mut state, &header.decode()) + self.client.call_many(&requests, &mut state, &header.decode().map_err(errors::decode)?) .map(|results| results.into_iter().map(TraceResults::from).collect()) .map_err(errors::call) } @@ -153,7 +153,7 @@ impl Traces for TracesClient where let mut state = self.client.state_at(id).ok_or(errors::state_pruned())?; let header = self.client.block_header(id).ok_or(errors::state_pruned())?; - self.client.call(&signed, to_call_analytics(flags), &mut state, &header.decode()) + self.client.call(&signed, to_call_analytics(flags), &mut state, &header.decode().map_err(errors::decode)?) .map(TraceResults::from) .map_err(errors::call) } From 25536c5ffb42136291a371efe0998c1b21354b47 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Wed, 9 May 2018 14:11:36 +0200 Subject: [PATCH 48/95] Update CHANGELOG for 1.9, 1.10, and 1.11 (#8556) * Move changelog for 1.10.x * Mark 1.9 EOL * Prepare changelog for 1.10.3 stable * Prepare changelog for 1.11.0 stable * Update changelogs * Update CHANGELOG for 1.10.3 beta * Update CHANGELOG for 1.11.0 beta * Update CHANGELOG for 1.11.0 beta * Update CHANGELOG for 1.11.0 beta * Format changelog --- CHANGELOG.md | 530 +++++++++++++++++++++-------------------- docs/CHANGELOG-1.10.md | 325 +++++++++++++++++++++++++ docs/CHANGELOG-1.9.md | 2 + 3 files changed, 594 insertions(+), 263 deletions(-) create mode 100644 docs/CHANGELOG-1.10.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 6272c32a7e8..0c7dcf878be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,272 +1,276 @@ -## Parity [v1.10.2](https://github.com/paritytech/parity/releases/tag/v1.10.2) (2018-04-24) - -Parity 1.10.2 is a bug-fix release to improve performance and stability. - -The full list of included changes: - -- Update Parity beta to 1.10.2 + Backports ([#8455](https://github.com/paritytech/parity/pull/8455)) - - Update Parity beta to 1.10.2 - - Allow 32-bit pipelines to fail ([#8454](https://github.com/paritytech/parity/pull/8454)) - - Disable 32-bit targets for Gitlab - - Rename Linux pipelines - - Update wasmi ([#8452](https://github.com/paritytech/parity/pull/8452)) - - Fix Cargo.lock -- Backports ([#8450](https://github.com/paritytech/parity/pull/8450)) - - Use forked app_dirs crate for reverted Windows dir behavior ([#8438](https://github.com/paritytech/parity/pull/8438)) - - Remove unused app_dirs dependency in CLI - - Use forked app_dirs crate for reverted Windows dir behavior - - Remove Tendermint extra_info due to seal inconsistencies ([#8367](https://github.com/paritytech/parity/pull/8367)) - - Handle queue import errors a bit more gracefully ([#8385](https://github.com/paritytech/parity/pull/8385)) - - Improve VM executor stack size estimation rules ([#8439](https://github.com/paritytech/parity/pull/8439)) - - Improve VM executor stack size estimation rules - - Typo: docs add "(Debug build)" comment - - Fix an off by one typo and set minimal stack size - - Use saturating_sub to avoid potential overflow - -## Parity [v1.10.1](https://github.com/paritytech/parity/releases/tag/v1.10.1) (2018-04-17) - -Parity 1.10.1 is a bug-fix release to improve performance and stability. Among other changes, you can now use `--warp-barrier [BLOCK]` to specify a minimum block number to `--warp` to. This is useful in cases where clients restore to outdated snapshots far behind the latest chain head. - -The full list of included changes: - -- Bump beta to 1.10.1 ([#8350](https://github.com/paritytech/parity/pull/8350)) - - Bump beta to 1.10.1 - - Unflag critical release -- Backports ([#8346](https://github.com/paritytech/parity/pull/8346)) - - Warp-only sync with warp-barrier [blocknumber] flag. ([#8228](https://github.com/paritytech/parity/pull/8228)) - - Warp-only sync with warp-after [blocknumber] flag. - - Fix tests. - - Fix configuration tests. - - Rename to warp barrier. - - Allow unsafe js eval on Parity Wallet. ([#8204](https://github.com/paritytech/parity/pull/8204)) - - Update musicoin spec in line with gmc v2.6.2 ([#8242](https://github.com/paritytech/parity/pull/8242)) - - Supress TemporaryInvalid verification failures. ([#8256](https://github.com/paritytech/parity/pull/8256)) - - Include suicided accounts in state diff ([#8297](https://github.com/paritytech/parity/pull/8297)) - - Include suicided accounts in state diff - - Shorten form match -> if let - - Test suicide trace diff in State - - Replace_home for password_files, reserved_peers and log_file ([#8324](https://github.com/paritytech/parity/pull/8324)) - - Replace_home for password_files, reserved_peers and log_file - - Typo: arg_log_file is Option - - Enable UI by default, but only display info page. - - Fix test. - - Fix naming and remove old todo. - - Change "wallet" with "browser UI" -- Change name Wallet -> UI ([#8164](https://github.com/paritytech/parity/pull/8164)) ([#8205](https://github.com/paritytech/parity/pull/8205)) - - Change name Wallet -> UI - - Make warning bold -- Backport [#8099](https://github.com/paritytech/parity/pull/8099) ([#8132](https://github.com/paritytech/parity/pull/8132)) -- WASM libs ([#8220](https://github.com/paritytech/parity/pull/8220)) - - Bump wasm libs ([#8171](https://github.com/paritytech/parity/pull/8171)) - - Bump wasmi version ([#8209](https://github.com/paritytech/parity/pull/8209)) -- Update hyper to 0.11.24 ([#8203](https://github.com/paritytech/parity/pull/8203)) -- Updated jsonrpc to include latest backports (beta) ([#8181](https://github.com/paritytech/parity/pull/8181)) - - Updated jsonrpc to include latest backports - - Update dependencies. - -## Parity [v1.10.0](https://github.com/paritytech/parity/releases/tag/v1.10.0) (2018-03-22) - -This is the Parity 1.10.0-beta release! Cool! - -### Disabling the Parity Wallet - -The **Parity Wallet (a.k.a. "UI") is now disabled by default**. We are preparing to split the wallet from the core client. - -To reactivate the parity wallet, you have to run Parity either with `parity --force-ui` (not recommended) or `parity ui` (deprecated) from the command line. Or, if you feel super fancy and want to test our pre-releases of the stand-alone electron wallet, head over to the [Parity-JS repositories and check the releases](https://github.com/Parity-JS/shell/releases). - -Further reading: - -- [Docs: Parity Wallet](https://wiki.parity.io/Parity-Wallet) -- [Docs: How to customize Parity UI?](https://wiki.parity.io/FAQ-Customize-Parity-UI.html) -- [Github: Parity-JS](https://github.com/parity-js) - -### Introducing the Wasm VM - -We are excited to announce support for **Wasm Smart Contracts on Kovan network**. The hard-fork to activate the Wasm-VM will take place on block `6_600_000`. - -To enable Wasm contracts on your custom network, just schedule a `wasmActivationTransition` at your favorite block number (e.g., `42`, `666`, or `0xbada55`). To hack your first Wasm smart contracts in Rust, have a look at the [Parity Wasm Tutorials](https://github.com/paritytech/pwasm-tutorial). - -Further reading: - -- [Docs: WebAssembly (wasm)](https://wiki.parity.io/WebAssembly-Home) -- [Docs: Wasm VM Design](https://wiki.parity.io/WebAssembly-Design) -- [Docs: Wasm tutorials and examples](https://wiki.parity.io/WebAssembly-Links) - -### Empty step messages in PoA - -To **reduce blockchain bloat, proof-of-authority networks can now enable _empty step messages_ which replace empty blocks**. Each step message will be signed and broadcasted by the issuing authorities, and included and rewarded in the next non-empty block. - -To enable empty step messages, set the `emptyStepsTransition` to your favorite block number. You can also specify a maximum number of empty steps with `maximumEmptySteps` in your chain spec. - -### Other noteworthy changes - -We removed the old database migrations from 2016. In case you upgrade Parity from a really, really old version, you will have to reset your database manually first with `parity db kill`. - -We fixed DELEGATECALL `from` and `to` fields, see [#7166](https://github.com/paritytech/parity/issues/7166). - -We reduced the default USD per transaction value to 0.0001. Thanks, @MysticRyuujin! - -The Musicoin chain is now enabled with Byzantium features starting at block `2_222_222`. - -### Overview of all changes included +## Parity [v1.11.0](https://github.com/paritytech/parity/releases/tag/v1.10.0) (2018-05-09) + +This is the Parity 1.11.0-beta release! Hurray! + +Notable changes in reversed alphabetical order: + +- TOOLING: **Whisper CLI** [#8201](https://github.com/paritytech/parity/pull/8201) + - `whisper-cli` is a standalone tool to communicate with the Whisper protocol. + - It provides functionality to specify `whisper-pool-size`, `port` and `address` to use. + - All whisper RPC APIs are enabled and can be directly acessed. +I'm not used to writing these changelogs but I guess that would explain it +- JSON-RPC API: **Return error in case eth_call returns VM errors** [#8448](https://github.com/paritytech/parity/pull/8448) + - This changes the behaviors of `eth_call` to respect VM errors if any. + - In case of `REVERT`, it will also return the reverted return data in hex format. +- ENGINES: **Block reward contract** [#8419](https://github.com/paritytech/parity/pull/8419) + - The _AuRa_ PoA engine has now support for having a contract to calculate the block rewards. + - The engine passes a list of benefactors and reward types to the contract which then returns a list of addresses and respective rewards. +- CORE: **Private transactions integration pr** [#6422](https://github.com/paritytech/parity/pull/6422) + - Parity now provides a private transactions system. + - Please, check out our wiki to get and [overview and setup instructions](https://wiki.parity.io/Private-Transactions.html). +- CORE: **New Transaction Queue implementation** [#8074](https://github.com/paritytech/parity/pull/8074) + - Verification is now done in parallel. + - Previous queue had `O(1)` time to get pending set, but `O(n^2)` insertion time. And obviously insertion/removal happens much more often than retrieving the pending set (only for propagation and pending block building) Currently we have `O(n * log(senders))` pending set time (with cache) and `O(tx_per_sender)` (usually within `log(tx_per_sender)`) insertion time. + - `Scoring` and `Readiness` are separated from the pool, so it's easier to customize them or introduce different definitions (for instance for [EIP-859](https://github.com/ethereum/EIPs/issues/859) or private transactions, etc). + - Banning removed, soft-penalization introduced instead: if transaction exceeds the limit other transactions from that sender get lower priority. + - There is no explicit distinction between current and future transactions in the pool - `Readiness` determines that. Because of this we additionally remove `future` transactions that occupy the pool for long time. +- CONFIGURATION: **Warp-only sync with --warp-barrier [block-number] flag.** [#8228](https://github.com/paritytech/parity/pull/8228) + - Enables warp-only sync in case `--warp-barrier [block-number]` is provided. + - This avoids clients to warp to outdated snapshots that are too far away from the best block. + - This avoids clients to fall back to normal sync if there are no recent snapshots available currently. +- CONFIGURATION: **Disable UI by default.** [#8105](https://github.com/paritytech/parity/pull/8105) + - The user interface is now disabled by default. It still can be activated with the `--force-ui` flag. + - To get the stand-alone Parity UI, please check the dedicated [releases page](https://github.com/parity-js/shell/releases). +- CONFIGURATION: **Auto-updater improvements** [#8078](https://github.com/paritytech/parity/pull/8078) + - Added `--auto-update-delay` to randomly delay updates by `n` blocks. This takes into account the number of the block of the update release (old updates aren't delayed). + - Added `--auto-update-check-frequency` to define the periodicity of auto-update checks in number of blocks. + - This is an important improvement to ensure the network does not update all clients at the same time. +- CHAIN SPECS: **Enable WebAssembly and Byzantium for Ellaism** [#8520](https://github.com/paritytech/parity/pull/8520) + - This activates the Ellaism Byzantium hardfork ([2018-0004-byzantium](https://github.com/ellaism/specs/blob/master/specs/2018-0004-byzantium.md)) at block `2_000_000`. + - This enables the Wasm VM on Ellaism ([2018-0003-wasm-hardfork](https://github.com/ellaism/specs/blob/master/specs/2018-0003-wasm-hardfork.md)) at block `2_000_000`. + - Please, upgrade your clients if you run an Ellaism configuration. +- CHAIN SPECS: **Dev chain - increase gasLimit to 8_000_000** [#8362](https://github.com/paritytech/parity/pull/8362) + - This increases the default block gas limit on development chains to `8_000_000`. + - Please note, this makes previous dev chain configurations incompatible. +- CHAIN SPECS: **Add MCIP-6 Byzyantium transition to Musicoin spec** [#7841](https://github.com/paritytech/parity/pull/7841) + - This activates the Musicoin Byzantium hardfork ([MCIP-6](https://github.com/Musicoin/MCIPs/blob/master/MCIPS/mcip-6.md)) at block `2_222_222`. + - Please, upgrade your clients if you run a Musicoin configuration. The full list of included changes: -- Re-enable signer, even with no UI. ([#8167](https://github.com/paritytech/parity/pull/8167)) ([#8168](https://github.com/paritytech/parity/pull/8168)) - - Re-enable signer, even with no UI. - - Fix message. -- Beta Backports ([#8136](https://github.com/paritytech/parity/pull/8136)) - - Support parity protocol. ([#8035](https://github.com/paritytech/parity/pull/8035)) - - updater: apply exponential backoff after download failure ([#8059](https://github.com/paritytech/parity/pull/8059)) - - updater: apply exponential backoff after download failure - - updater: reset backoff on new release - - Max code size on Kovan ([#8067](https://github.com/paritytech/parity/pull/8067)) - - Enable code size limit on kovan - - Fix formatting. - - Limit incoming connections. ([#8060](https://github.com/paritytech/parity/pull/8060)) - - Limit ingress connections - - Optimized handshakes logging - - WASM libraries bump ([#7970](https://github.com/paritytech/parity/pull/7970)) - - update wasmi, parity-wasm, wasm-utils to latest version - - Update to new wasmi & error handling - - also utilize new stack limiter - - fix typo - - replace dependency url - - Cargo.lock update - - add some dos protection ([#8084](https://github.com/paritytech/parity/pull/8084)) - - revert removing blooms ([#8066](https://github.com/paritytech/parity/pull/8066)) - - Revert "fix traces, removed bloomchain crate, closes [#7228](https://github.com/paritytech/parity/issues/7228), closes [#7167](https://github.com/paritytech/parity/issues/7167)" - - Revert "fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934))" - - fixed broken logs - - bring back old lock order - - remove migration v13 - - revert CURRENT_VERSION to 12 in migration.rs - - more dos protection ([#8104](https://github.com/paritytech/parity/pull/8104)) - - Const time comparison ([#8113](https://github.com/paritytech/parity/pull/8113)) - - Use `subtle::slices_equal` for constant time comparison. - - Also update the existing version of subtle in `ethcrypto` from 0.1 to 0.5 - - Test specifically for InvalidPassword error. - - fix trace filter returning returning unrelated reward calls, closes #8070 ([#8098](https://github.com/paritytech/parity/pull/8098)) - - network: init discovery using healthy nodes ([#8061](https://github.com/paritytech/parity/pull/8061)) - - network: init discovery using healthy nodes - - network: fix style grumble - - network: fix typo - - Postpone Kovan hard fork ([#8137](https://github.com/paritytech/parity/pull/8137)) - - ethcore: postpone Kovan hard fork - - util: update version fork metadata - - Disable UI by default. ([#8105](https://github.com/paritytech/parity/pull/8105)) - - dapps: update parity-ui dependencies ([#8160](https://github.com/paritytech/parity/pull/8160)) -- Probe changes one step deeper ([#8134](https://github.com/paritytech/parity/pull/8134)) ([#8135](https://github.com/paritytech/parity/pull/8135)) -- Beta backports ([#8053](https://github.com/paritytech/parity/pull/8053)) - - CI: Fix cargo cache ([#7968](https://github.com/paritytech/parity/pull/7968)) - - Fix cache - - Only clean locked cargo cache on windows - - fixed ethstore sign ([#8026](https://github.com/paritytech/parity/pull/8026)) - - fixed parsing ethash seals and verify_block_undordered ([#8031](https://github.com/paritytech/parity/pull/8031)) - - fix for verify_block_basic crashing on invalid transaction rlp ([#8032](https://github.com/paritytech/parity/pull/8032)) - - fix cache & snapcraft CI build ([#8052](https://github.com/paritytech/parity/pull/8052)) - - Add MCIP-6 Byzyantium transition to Musicoin spec ([#7841](https://github.com/paritytech/parity/pull/7841)) - - Add test chain spec for musicoin byzantium testnet - - Add MCIP-6 Byzyantium transition to Musicoin spec - - Update mcip6_byz.json - - ethcore: update musicoin byzantium block number - - ethcore: update musicoin bootnodes - - Update musicoin.json - - More bootnodes. -- Make 1.10 beta ([#8022](https://github.com/paritytech/parity/pull/8022)) - - Make 1.10 beta - - Fix gitlab builds -- SecretStore: secretstore_generateDocumentKey RPC ([#7864](https://github.com/paritytech/parity/pull/7864)) -- SecretStore: ECDSA session for cases when 2*t < N ([#7739](https://github.com/paritytech/parity/pull/7739)) -- bump tiny-keccak ([#8019](https://github.com/paritytech/parity/pull/8019)) -- Remove un-necessary comment ([#8014](https://github.com/paritytech/parity/pull/8014)) -- clean up account fmt::Debug ([#7983](https://github.com/paritytech/parity/pull/7983)) -- improve quality of vote_collector module ([#7984](https://github.com/paritytech/parity/pull/7984)) -- ExecutedBlock cleanup ([#7991](https://github.com/paritytech/parity/pull/7991)) -- Hardware-wallet/usb-subscribe-refactor ([#7860](https://github.com/paritytech/parity/pull/7860)) -- remove wildcard imports from views, make tests more idiomatic ([#7986](https://github.com/paritytech/parity/pull/7986)) -- moved PerfTimer to a separate crate - "trace-time" ([#7985](https://github.com/paritytech/parity/pull/7985)) -- clean up ethcore::spec module imports ([#7990](https://github.com/paritytech/parity/pull/7990)) -- rpc: don't include current block in new_block_filter ([#7982](https://github.com/paritytech/parity/pull/7982)) -- fix traces, removed bloomchain crate ([#7979](https://github.com/paritytech/parity/pull/7979)) -- simplify compression and move it out of rlp crate ([#7957](https://github.com/paritytech/parity/pull/7957)) -- removed old migrations ([#7974](https://github.com/paritytech/parity/pull/7974)) -- Reject too large packets in snapshot sync. ([#7977](https://github.com/paritytech/parity/pull/7977)) -- fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934)) -- Increase max download limit to 128MB ([#7965](https://github.com/paritytech/parity/pull/7965)) -- Calculate proper keccak256/sha3 using parity. ([#7953](https://github.com/paritytech/parity/pull/7953)) -- Add changelog for 1.8.10 stable and 1.9.3 beta ([#7947](https://github.com/paritytech/parity/pull/7947)) -- kvdb-rocksdb: remove buffered operations when committing transaction ([#7950](https://github.com/paritytech/parity/pull/7950)) -- Bump WebSockets ([#7952](https://github.com/paritytech/parity/pull/7952)) -- removed redundant Bloom conversions ([#7932](https://github.com/paritytech/parity/pull/7932)) -- simplify RefInfo fmt ([#7929](https://github.com/paritytech/parity/pull/7929)) -- Kovan WASM fork code ([#7849](https://github.com/paritytech/parity/pull/7849)) -- bring back trie and triehash benches ([#7926](https://github.com/paritytech/parity/pull/7926)) -- removed redundant PodAccount::new method ([#7928](https://github.com/paritytech/parity/pull/7928)) -- removed dummy wrapper structure - LogGroupPosition ([#7922](https://github.com/paritytech/parity/pull/7922)) -- spec: Validate required divisor fields are not 0 ([#7933](https://github.com/paritytech/parity/pull/7933)) -- simplify Client::filter_traces method ([#7936](https://github.com/paritytech/parity/pull/7936)) -- gitlab cache ([#7921](https://github.com/paritytech/parity/pull/7921)) -- Fix a division by zero in light client RPC handler ([#7917](https://github.com/paritytech/parity/pull/7917)) -- triehash optimisations ([#7920](https://github.com/paritytech/parity/pull/7920)) -- removed redundant Blockchain::db method ([#7919](https://github.com/paritytech/parity/pull/7919)) -- removed redundant Blockchain::rewind method ([#7918](https://github.com/paritytech/parity/pull/7918)) -- Pending transactions subscription ([#7906](https://github.com/paritytech/parity/pull/7906)) -- removed redundant otry! macro from ethcore ([#7916](https://github.com/paritytech/parity/pull/7916)) -- Make block generator easier to use ([#7888](https://github.com/paritytech/parity/pull/7888)) -- ECIP 1041 - Remove Difficulty Bomb ([#7905](https://github.com/paritytech/parity/pull/7905)) -- Fix CSP for dapps that require eval. ([#7867](https://github.com/paritytech/parity/pull/7867)) -- Fix gitlab ([#7901](https://github.com/paritytech/parity/pull/7901)) -- Gitlb snap master patch ([#7900](https://github.com/paritytech/parity/pull/7900)) -- fix snap build master ([#7896](https://github.com/paritytech/parity/pull/7896)) -- Fix wallet import ([#7873](https://github.com/paritytech/parity/pull/7873)) -- Fix snapcraft nightly ([#7884](https://github.com/paritytech/parity/pull/7884)) -- Add a timeout for light client sync requests ([#7848](https://github.com/paritytech/parity/pull/7848)) -- SecretStore: fixed test ([#7878](https://github.com/paritytech/parity/pull/7878)) -- Fix checksums and auto-update push ([#7846](https://github.com/paritytech/parity/pull/7846)) -- Forward-port snap fixes ([#7831](https://github.com/paritytech/parity/pull/7831)) -- Update gitlab-test.sh ([#7883](https://github.com/paritytech/parity/pull/7883)) -- Fix installer binary names for macos and windows ([#7881](https://github.com/paritytech/parity/pull/7881)) -- Fix string typo: "develoopment" -> "development" ([#7874](https://github.com/paritytech/parity/pull/7874)) -- Update the instructions to install the stable snap ([#7876](https://github.com/paritytech/parity/pull/7876)) -- SecretStore: 'broadcast' decryption session ([#7843](https://github.com/paritytech/parity/pull/7843)) -- Flush keyfiles. Resolves #7632 ([#7868](https://github.com/paritytech/parity/pull/7868)) -- Read registry_address from given block ([#7866](https://github.com/paritytech/parity/pull/7866)) -- Clean up docs formatting for Wasm runtime ([#7869](https://github.com/paritytech/parity/pull/7869)) -- WASM: Disable internal memory ([#7842](https://github.com/paritytech/parity/pull/7842)) -- Update gitlab-build.sh ([#7855](https://github.com/paritytech/parity/pull/7855)) -- ethabi version 5 ([#7723](https://github.com/paritytech/parity/pull/7723)) -- Light client: randomize the peer we dispatch requests to ([#7844](https://github.com/paritytech/parity/pull/7844)) -- Store updater metadata in a single place ([#7832](https://github.com/paritytech/parity/pull/7832)) -- Add new EF ropstens nodes. ([#7824](https://github.com/paritytech/parity/pull/7824)) -- refactor stratum to remove retain cycle ([#7827](https://github.com/paritytech/parity/pull/7827)) -- Bump jsonrpc. ([#7828](https://github.com/paritytech/parity/pull/7828)) -- Add binary identifiers and sha256sum to builds ([#7830](https://github.com/paritytech/parity/pull/7830)) -- Update references to UI shell & wallet ([#7808](https://github.com/paritytech/parity/pull/7808)) -- Adjust storage update evm-style ([#7812](https://github.com/paritytech/parity/pull/7812)) -- Updated WASM Runtime & new interpreter (wasmi) ([#7796](https://github.com/paritytech/parity/pull/7796)) -- SecretStore: ignore removed authorities when running auto-migration ([#7674](https://github.com/paritytech/parity/pull/7674)) -- Fix build ([#7807](https://github.com/paritytech/parity/pull/7807)) -- Move js & js-old code to github.com/parity-js ([#7685](https://github.com/paritytech/parity/pull/7685)) -- More changelogs :) ([#7782](https://github.com/paritytech/parity/pull/7782)) -- Actualized API set in help ([#7790](https://github.com/paritytech/parity/pull/7790)) -- Removed obsolete file ([#7788](https://github.com/paritytech/parity/pull/7788)) -- Update ropsten bootnodes ([#7776](https://github.com/paritytech/parity/pull/7776)) -- CHANGELOG for 1.9.1 and 1.8.8 ([#7775](https://github.com/paritytech/parity/pull/7775)) -- Enable byzantium features on non-ethash chains ([#7753](https://github.com/paritytech/parity/pull/7753)) -- Fix client not being dropped on shutdown ([#7695](https://github.com/paritytech/parity/pull/7695)) -- Filter-out nodes.json ([#7716](https://github.com/paritytech/parity/pull/7716)) -- Removes redundant parentheses ([#7721](https://github.com/paritytech/parity/pull/7721)) -- Transaction-pool fixes ([#7741](https://github.com/paritytech/parity/pull/7741)) -- More visible download link in README.md ([#7707](https://github.com/paritytech/parity/pull/7707)) -- Changelog for 1.9.0 ([#7664](https://github.com/paritytech/parity/pull/7664)) -- Add scroll when too many accounts ([#7677](https://github.com/paritytech/parity/pull/7677)) -- SecretStore: return HTTP 403 (access denied) if consensus is unreachable ([#7656](https://github.com/paritytech/parity/pull/7656)) -- Moved StopGaurd to it's own crate ([#7635](https://github.com/paritytech/parity/pull/7635)) +- Backports ([#8558](https://github.com/paritytech/parity/pull/8558)) + - Fetching logs by hash in blockchain database ([#8463](https://github.com/paritytech/parity/pull/8463)) + - Fetch logs by hash in blockchain database + - Fix tests + - Add unit test for branch block logs fetching + - Add docs that blocks must already be sorted + - Handle branch block cases properly + - typo: empty -> is_empty + - Remove return_empty_if_none by using a closure + - Use BTreeSet to avoid sorting again + - Move is_canon to BlockChain + - typo: pass value by reference + - Use loop and wrap inside blocks to simplify the code + - typo: missed a comment + - Pass on storage keys tracing to handle the case when it is not modified ([#8491](https://github.com/paritytech/parity/pull/8491)) + - Pass on storage keys even if it is not modified + - typo: account and storage query + - Fix tests + - Use state query directly because of suicided accounts + - Fix a RefCell borrow issue + - Add tests for unmodified storage trace + - Address grumbles + - typo: remove unwanted empty line + - ensure_cached compiles with the original signature + - Update wasmi and pwasm-utils ([#8493](https://github.com/paritytech/parity/pull/8493)) + - Update wasmi to 0.2 + - Update pwasm-utils to 0.1.5 + - Show imported messages for light client ([#8517](https://github.com/paritytech/parity/pull/8517)) + - Enable WebAssembly and Byzantium for Ellaism ([#8520](https://github.com/paritytech/parity/pull/8520)) + - Enable WebAssembly and Byzantium for Ellaism + - Fix indentation + - Remove empty lines + - Don't panic in import_block if invalid rlp ([#8522](https://github.com/paritytech/parity/pull/8522)) + - Don't panic in import_block if invalid rlp + - Remove redundant type annotation + - Replace RLP header view usage with safe decoding + - Node table sorting according to last contact data ([#8541](https://github.com/paritytech/parity/pull/8541)) + - network-devp2p: sort nodes in node table using last contact data + - network-devp2p: rename node contact types in node table json output + - network-devp2p: fix node table tests + - network-devp2p: note node failure when failed to establish connection + - network-devp2p: handle UselessPeer error + - network-devp2p: note failure when marking node as useless +- Betalize 1.11 :) ([#8475](https://github.com/paritytech/parity/pull/8475)) + - Betalize 1.11 :) + - Update Gitlab scripts + - Use master as gitlab latest + - Fix snap builds ([#8483](https://github.com/paritytech/parity/pull/8483)) + - Update hardcodedSync for Ethereum, Kovan, and Ropsten ([#8489](https://github.com/paritytech/parity/pull/8489)) +- Fix typos in vm description comment ([#8446](https://github.com/paritytech/parity/pull/8446)) +- Add changelog for 1.9.7 and 1.10.2 ([#8460](https://github.com/paritytech/parity/pull/8460)) +- Fix docker build ([#8462](https://github.com/paritytech/parity/pull/8462)) +- Parityshell::open `Return result` ([#8377](https://github.com/paritytech/parity/pull/8377)) +- Return error in case eth_call returns VM errors ([#8448](https://github.com/paritytech/parity/pull/8448)) +- Update wasmi ([#8452](https://github.com/paritytech/parity/pull/8452)) +- Allow 32 bit pipelines to fail ([#8454](https://github.com/paritytech/parity/pull/8454)) +- Update Cargo hidapi-rs dependency ([#8447](https://github.com/paritytech/parity/pull/8447)) +- Private transactions processing error handling ([#8431](https://github.com/paritytech/parity/pull/8431)) +- Improve VM executor stack size estimation rules ([#8439](https://github.com/paritytech/parity/pull/8439)) +- Block reward contract ([#8419](https://github.com/paritytech/parity/pull/8419)) +- Permission fix ([#8441](https://github.com/paritytech/parity/pull/8441)) +- Use forked app_dirs crate for reverted Windows dir behavior ([#8438](https://github.com/paritytech/parity/pull/8438)) +- Remove From::from. ([#8390](https://github.com/paritytech/parity/pull/8390)) +- Move ethcore::Error to error_chain ([#8386](https://github.com/paritytech/parity/pull/8386)) +- Changelogs for 1.9.6 and 1.10.1 ([#8411](https://github.com/paritytech/parity/pull/8411)) +- Fix receipts stripping. ([#8414](https://github.com/paritytech/parity/pull/8414)) +- Typo, docs parity_chainId: empty string -> None ([#8434](https://github.com/paritytech/parity/pull/8434)) +- Update zip to 0.3 ([#8381](https://github.com/paritytech/parity/pull/8381)) +- Fix TODO comments ([#8413](https://github.com/paritytech/parity/pull/8413)) +- Replace legacy Rlp with UntrustedRlp and use in ethcore rlp views ([#8316](https://github.com/paritytech/parity/pull/8316)) +- Tokio-core v0.1.16 -> v0.1.17 ([#8408](https://github.com/paritytech/parity/pull/8408)) +- More code refactoring to integrate Duration ([#8322](https://github.com/paritytech/parity/pull/8322)) +- Remove Tendermint extra_info due to seal inconsistencies ([#8367](https://github.com/paritytech/parity/pull/8367)) +- Use tokio::spawn in secret_store listener and fix Uri ([#8373](https://github.com/paritytech/parity/pull/8373)) +- Unify and limit rocksdb dependency places ([#8371](https://github.com/paritytech/parity/pull/8371)) +- Clarify that windows need perl and yasm ([#8402](https://github.com/paritytech/parity/pull/8402)) +- New Transaction Queue implementation ([#8074](https://github.com/paritytech/parity/pull/8074)) +- Some tweaks to main.rs for parity as a library ([#8370](https://github.com/paritytech/parity/pull/8370)) +- Handle queue import errors a bit more gracefully ([#8385](https://github.com/paritytech/parity/pull/8385)) +- Ci: fix change detection in master builds ([#8382](https://github.com/paritytech/parity/pull/8382)) +- Fix config test by adding no-hardcodec-sync ([#8380](https://github.com/paritytech/parity/pull/8380)) +- Fixed unsafe shell call on windows ([#8372](https://github.com/paritytech/parity/pull/8372)) +- Parity uses winapi 0.3.4 ([#8366](https://github.com/paritytech/parity/pull/8366)) +- No hardcoded client name ([#8368](https://github.com/paritytech/parity/pull/8368)) +- Add `util/mem` to zero out memory on drop. ([#8356](https://github.com/paritytech/parity/pull/8356)) +- Use atty instead of isatty ([#8365](https://github.com/paritytech/parity/pull/8365)) +- Increase gasLimit to 8'000'000 ([#8362](https://github.com/paritytech/parity/pull/8362)) +- Util `fake-fetch` ([#8363](https://github.com/paritytech/parity/pull/8363)) +- Bump snappy and ring, use single rayon version, closes [#8296](https://github.com/paritytech/parity/issues/8296) ([#8364](https://github.com/paritytech/parity/pull/8364)) +- Use async hyper server in secret_store and upgrade igd ([#8359](https://github.com/paritytech/parity/pull/8359)) +- Enable UI by default, but only display deprecation notice ([#8262](https://github.com/paritytech/parity/pull/8262)) +- Ethcrypto renamed to ethcore-crypto and moved to ethcore dir ([#8340](https://github.com/paritytech/parity/pull/8340)) +- Use hyper 0.11 in ethcore-miner and improvements in parity-reactor ([#8335](https://github.com/paritytech/parity/pull/8335)) +- Ethcore-sync ([#8347](https://github.com/paritytech/parity/pull/8347)) +- Rpc, eth_filter: return error if the filter id does not exist ([#8341](https://github.com/paritytech/parity/pull/8341)) +- Ethcore-stratum crate moved to ethcore directory ([#8338](https://github.com/paritytech/parity/pull/8338)) +- Secretstore: get rid of engine.signer dependency ([#8173](https://github.com/paritytech/parity/pull/8173)) +- Whisper cli ([#8201](https://github.com/paritytech/parity/pull/8201)) +- Replace_home for password_files, reserved_peers and log_file ([#8324](https://github.com/paritytech/parity/pull/8324)) +- Add Ethereum Social support ([#8325](https://github.com/paritytech/parity/pull/8325)) +- Private transactions integration pr ([#6422](https://github.com/paritytech/parity/pull/6422)) +- Decouple rocksdb dependency from ethcore ([#8320](https://github.com/paritytech/parity/pull/8320)) +- Remove the clone operation of code_cache ([#8334](https://github.com/paritytech/parity/pull/8334)) +- Fix the JSONRPC API not running with the light client ([#8326](https://github.com/paritytech/parity/pull/8326)) +- Read registry_address from block with REQUEST_CONFIRMATIONS_REQUIRED ([#8309](https://github.com/paritytech/parity/pull/8309)) +- Tweaks and add a Dockerfile for Android ([#8036](https://github.com/paritytech/parity/pull/8036)) +- Use associated type M::Error instead of Error ([#8308](https://github.com/paritytech/parity/pull/8308)) +- Remove InvalidParentHash in favor of assert! ([#8300](https://github.com/paritytech/parity/pull/8300)) +- Bump proc macro deps ([#8310](https://github.com/paritytech/parity/pull/8310)) +- Decouple timestamp open-block-assignment/verification to Engine ([#8305](https://github.com/paritytech/parity/pull/8305)) +- Validate if gas limit is not zero ([#8307](https://github.com/paritytech/parity/pull/8307)) +- Implement Easthub chain spec ([#8295](https://github.com/paritytech/parity/pull/8295)) +- Update some dependencies ([#8285](https://github.com/paritytech/parity/pull/8285)) +- Ethcore now uses Rayon 1.0 as a dependency ([#8296](https://github.com/paritytech/parity/pull/8296)) ([#8304](https://github.com/paritytech/parity/pull/8304)) +- Upgrader `remove raw unwrap` and bump semver ([#8251](https://github.com/paritytech/parity/pull/8251)) +- Cleaner binary shutdown system ([#8284](https://github.com/paritytech/parity/pull/8284)) +- Ethcore now uses rayon to 0.9 as a dependency ([#8296](https://github.com/paritytech/parity/pull/8296)) ([#8302](https://github.com/paritytech/parity/pull/8302)) +- Include suicided accounts in state diff ([#8297](https://github.com/paritytech/parity/pull/8297)) +- Remove evmjit ([#8229](https://github.com/paritytech/parity/pull/8229)) +- Build: fix updater rand dependency in Cargo.lock ([#8298](https://github.com/paritytech/parity/pull/8298)) +- Honor --max-peers if --min-peers is not specified ([#8087](https://github.com/paritytech/parity/pull/8087)) +- Auto-updater improvements ([#8078](https://github.com/paritytech/parity/pull/8078)) +- Dapps-fetcher: calculate keccak in-flight while reading the response ([#8294](https://github.com/paritytech/parity/pull/8294)) +- Cleanup Ellaism bootnodes ([#8276](https://github.com/paritytech/parity/pull/8276)) +- Allow unsafe js eval on Parity Wallet. ([#8204](https://github.com/paritytech/parity/pull/8204)) +- Remove RefCell from Header ([#8227](https://github.com/paritytech/parity/pull/8227)) +- Typo fix: todo with no content ([#8292](https://github.com/paritytech/parity/pull/8292)) +- Revert "ci: disable link-dead-code in coverage build ([#8118](https://github.com/paritytech/parity/pull/8118))" ([#8287](https://github.com/paritytech/parity/pull/8287)) +- Bump ethabi & ethereum-types. ([#8258](https://github.com/paritytech/parity/pull/8258)) +- Allow customization of max WS connections. ([#8257](https://github.com/paritytech/parity/pull/8257)) +- Supress TemporaryInvalid verification failures. ([#8256](https://github.com/paritytech/parity/pull/8256)) +- Return null number for pending block in eth_getBlockByNumber ([#8281](https://github.com/paritytech/parity/pull/8281)) +- Use constant durations ([#8278](https://github.com/paritytech/parity/pull/8278)) +- Typo fix: Mode doc - RLP should be client ([#8283](https://github.com/paritytech/parity/pull/8283)) +- Eth_uninstallfilter should return false for non-existent filter ([#8280](https://github.com/paritytech/parity/pull/8280)) +- Update `app_dirs` to 1.2.1 ([#8268](https://github.com/paritytech/parity/pull/8268)) +- Add missing license header for runtime.rs ([#8252](https://github.com/paritytech/parity/pull/8252)) +- Warp-only sync with warp-barrier [blocknumber] flag. ([#8228](https://github.com/paritytech/parity/pull/8228)) +- Replace all Rlp usages with UntrustedRlp except for ethcore views ([#8233](https://github.com/paritytech/parity/pull/8233)) +- Add test for ethstore-cli, fixes [#8027](https://github.com/paritytech/parity/issues/8027) ([#8187](https://github.com/paritytech/parity/pull/8187)) +- Update musicoin spec in line with gmc v2.6.2 ([#8242](https://github.com/paritytech/parity/pull/8242)) +- Fixed ethcore tx_filter ([#8200](https://github.com/paritytech/parity/pull/8200)) +- Update CLI help for jsonrpc-apis, ws-apis and ipc-apis ([#8234](https://github.com/paritytech/parity/pull/8234)) +- Remove network stats ([#8225](https://github.com/paritytech/parity/pull/8225)) +- Node-filter does not use ChainNotify ([#8231](https://github.com/paritytech/parity/pull/8231)) +- Implement hardcoded sync in the light client ([#8075](https://github.com/paritytech/parity/pull/8075)) +- Update some of the dependencies for WASM ([#8223](https://github.com/paritytech/parity/pull/8223)) +- Bump wasmi version ([#8209](https://github.com/paritytech/parity/pull/8209)) +- Updated jsonrpc to point to the 1.11 branch ([#8180](https://github.com/paritytech/parity/pull/8180)) +- Change name Wallet -> UI ([#8164](https://github.com/paritytech/parity/pull/8164)) +- Introduce Parity UI ([#8202](https://github.com/paritytech/parity/pull/8202)) +- Update Changelogs ([#8175](https://github.com/paritytech/parity/pull/8175)) +- Returns number of topcis to take fr.. ([#8199](https://github.com/paritytech/parity/pull/8199)) +- Make docopt usage non-const ([#8189](https://github.com/paritytech/parity/pull/8189)) +- Avoid allocations when computing triehash. ([#8176](https://github.com/paritytech/parity/pull/8176)) +- Handle rlp decoding Result in patricia trie ([#8166](https://github.com/paritytech/parity/pull/8166)) +- Bump wasm libs ([#8171](https://github.com/paritytech/parity/pull/8171)) +- Re-enable signer, even with no UI. ([#8167](https://github.com/paritytech/parity/pull/8167)) +- Update daemonize ([#8165](https://github.com/paritytech/parity/pull/8165)) +- Some tiny modifications. ([#8163](https://github.com/paritytech/parity/pull/8163)) +- Secretstore: store key author address in db ([#7887](https://github.com/paritytech/parity/pull/7887)) +- Rename DatabaseValueView::new to from_rlp ([#8159](https://github.com/paritytech/parity/pull/8159)) +- Dapps: update parity-ui dependencies ([#8160](https://github.com/paritytech/parity/pull/8160)) +- Disable UI by default. ([#8105](https://github.com/paritytech/parity/pull/8105)) +- Fix wasmi x32 builds ([#8155](https://github.com/paritytech/parity/pull/8155)) +- Postpone Kovan hard fork ([#8137](https://github.com/paritytech/parity/pull/8137)) +- Secretstore: ability to identify requester via Public/Address ([#7886](https://github.com/paritytech/parity/pull/7886)) +- Optional dependency on secp256k1 for ethcrypto ([#8109](https://github.com/paritytech/parity/pull/8109)) +- Network: init discovery using healthy nodes ([#8061](https://github.com/paritytech/parity/pull/8061)) +- Check one step deeper if we're on release track branches ([#8134](https://github.com/paritytech/parity/pull/8134)) +- Explicitly mention pruning_history uses RAM ([#8130](https://github.com/paritytech/parity/pull/8130)) +- Remove `ethcrypto::{en,de}crypt_single_message`. ([#8126](https://github.com/paritytech/parity/pull/8126)) +- Fix typo ([#8124](https://github.com/paritytech/parity/pull/8124)) +- Secret_store: use `ecies::encrypt`/`ecies::decrypt`. ([#8125](https://github.com/paritytech/parity/pull/8125)) +- Fix comment for fn gas() in wasm/runtime ([#8122](https://github.com/paritytech/parity/pull/8122)) +- Structured rlp encoding in journaldb ([#8047](https://github.com/paritytech/parity/pull/8047)) +- Ci: disable link-dead-code in coverage build ([#8118](https://github.com/paritytech/parity/pull/8118)) +- Fix trace filter returning returning unrelated reward calls, closes [#8070](https://github.com/paritytech/parity/issues/8070) ([#8098](https://github.com/paritytech/parity/pull/8098)) +- Const time comparison ([#8113](https://github.com/paritytech/parity/pull/8113)) +- Replace reqwest with hyper ([#8099](https://github.com/paritytech/parity/pull/8099)) +- More dos protection ([#8104](https://github.com/paritytech/parity/pull/8104)) +- Remove the time dependency where possible ([#8100](https://github.com/paritytech/parity/pull/8100)) +- Fix comment for gas extern in Wasm runtime ([#8101](https://github.com/paritytech/parity/pull/8101)) +- Replace std::env::temp_dir with tempdir in tests ([#8103](https://github.com/paritytech/parity/pull/8103)) +- Fix Cargo.lock not parsable ([#8102](https://github.com/paritytech/parity/pull/8102)) +- Additional data in EVMTestClient ([#7964](https://github.com/paritytech/parity/pull/7964)) +- Update serde, serde-derive, ethabi-derive, syn, quote and rlp_derive ([#8085](https://github.com/paritytech/parity/pull/8085)) +- Ethcore-service ([#8089](https://github.com/paritytech/parity/pull/8089)) +- [contract-client] refactor ([#7978](https://github.com/paritytech/parity/pull/7978)) +- Revert removing blooms ([#8066](https://github.com/paritytech/parity/pull/8066)) +- Ethcore test::helpers cleanup ([#8086](https://github.com/paritytech/parity/pull/8086)) +- Add some dos protection ([#8084](https://github.com/paritytech/parity/pull/8084)) +- Wasm libraries bump ([#7970](https://github.com/paritytech/parity/pull/7970)) +- Echo back the message hash of a ping in the pong request ([#8042](https://github.com/paritytech/parity/pull/8042)) +- Add Kovan WASM activation blocknumber ([#8057](https://github.com/paritytech/parity/pull/8057)) +- [ethkey] Unify debug/display for Address/Public/Secret ([#8076](https://github.com/paritytech/parity/pull/8076)) +- Limit incoming connections. ([#8060](https://github.com/paritytech/parity/pull/8060)) +- Max code size on Kovan ([#8067](https://github.com/paritytech/parity/pull/8067)) +- Updater: apply exponential backoff after download failure ([#8059](https://github.com/paritytech/parity/pull/8059)) +- Make blockchain functions more idiomatic, avoid needless writes to cache_man ([#8054](https://github.com/paritytech/parity/pull/8054)) +- Make patricia-trie more idiomatic and remove redundant code ([#8056](https://github.com/paritytech/parity/pull/8056)) +- Abstract devp2p ([#8048](https://github.com/paritytech/parity/pull/8048)) +- Update refs to shell ([#8051](https://github.com/paritytech/parity/pull/8051)) +- Fix cache & snapcraft CI build ([#8052](https://github.com/paritytech/parity/pull/8052)) +- Prelude to the block module cleanup ([#8025](https://github.com/paritytech/parity/pull/8025)) +- Add MCIP-6 Byzyantium transition to Musicoin spec ([#7841](https://github.com/paritytech/parity/pull/7841)) +- Bump master to 1.11.0 ([#8021](https://github.com/paritytech/parity/pull/8021)) +- `client` refactoring ([#7038](https://github.com/paritytech/parity/pull/7038)) +- [hardware wallet] sleeping -> pollling ([#8018](https://github.com/paritytech/parity/pull/8018)) +- Fixed broken link in README ([#8012](https://github.com/paritytech/parity/pull/8012)) +- Support parity protocol. ([#8035](https://github.com/paritytech/parity/pull/8035)) +- Add changelog for 1.8.11 stable and 1.9.4 beta ([#8017](https://github.com/paritytech/parity/pull/8017)) +- Fix for verify_block_basic crashing on invalid transaction rlp ([#8032](https://github.com/paritytech/parity/pull/8032)) +- Extract the hard dependency on rocksdb from the light client ([#8034](https://github.com/paritytech/parity/pull/8034)) +- Fixed parsing ethash seals and verify_block_undordered ([#8031](https://github.com/paritytech/parity/pull/8031)) +- Fixed ethstore sign ([#8026](https://github.com/paritytech/parity/pull/8026)) +- Ci: Fix cargo cache ([#7968](https://github.com/paritytech/parity/pull/7968)) +- Update ref to new shell ([#8024](https://github.com/paritytech/parity/pull/8024)) ## Previous releases -- [CHANGELOG-1.9](docs/CHANGELOG-1.9.md) (_stable_) +- [CHANGELOG-1.10](docs/CHANGELOG-1.10.md) (_stable_) +- [CHANGELOG-1.9](docs/CHANGELOG-1.9.md) (EOL: 2018-05-09) - [CHANGELOG-1.8](docs/CHANGELOG-1.8.md) (EOL: 2018-03-22) - [CHANGELOG-1.7](docs/CHANGELOG-1.7.md) (EOL: 2018-01-25) - [CHANGELOG-1.6](docs/CHANGELOG-1.6.md) (EOL: 2017-10-15) diff --git a/docs/CHANGELOG-1.10.md b/docs/CHANGELOG-1.10.md new file mode 100644 index 00000000000..4db8f32bb67 --- /dev/null +++ b/docs/CHANGELOG-1.10.md @@ -0,0 +1,325 @@ +## Parity [v1.10.3](https://github.com/paritytech/parity/releases/tag/v1.10.3) (2018-05-08) + +Parity 1.10.3 marks the first stable release on the 1.10 track. Among others, it improves performance and stability. + +The full list of included changes: + +- Backports ([#8557](https://github.com/paritytech/parity/pull/8557)) + - Update wasmi and pwasm-utils ([#8493](https://github.com/paritytech/parity/pull/8493)) + - Update wasmi to 0.2 + - Update pwasm-utils to 0.1.5 + - Fetching logs by hash in blockchain database ([#8463](https://github.com/paritytech/parity/pull/8463)) + - Fetch logs by hash in blockchain database + - Fix tests + - Add unit test for branch block logs fetching + - Add docs that blocks must already be sorted + - Handle branch block cases properly + - typo: empty -> is_empty + - Remove return_empty_if_none by using a closure + - Use BTreeSet to avoid sorting again + - Move is_canon to BlockChain + - typo: pass value by reference + - Use loop and wrap inside blocks to simplify the code + - typo: missed a comment + - Pass on storage keys tracing to handle the case when it is not modified ([#8491](https://github.com/paritytech/parity/pull/8491)) + - Pass on storage keys even if it is not modified + - typo: account and storage query `to_pod_diff` builds both `touched_addresses` merge and storage keys merge. + - Fix tests + - Use state query directly because of suicided accounts + - Fix a RefCell borrow issue + - Add tests for unmodified storage trace + - Address grumbles + - typo: remove unwanted empty line + - ensure_cached compiles with the original signature + - Enable WebAssembly and Byzantium for Ellaism ([#8520](https://github.com/paritytech/parity/pull/8520)) + - Enable WebAssembly and Byzantium for Ellaism + - Fix indentation + - Remove empty lines + - Fix compilation. +- Stabilize 1.10.3 ([#8474](https://github.com/paritytech/parity/pull/8474)) + - Stabelize 1.10 + - Bump stable to 1.10.3 + - Update Gitlab scripts + - Fix snap builds ([#8483](https://github.com/paritytech/parity/pull/8483)) + - Fix docker build ([#8462](https://github.com/paritytech/parity/pull/8462)) + - Use `master` as Docker's `latest` (`beta-release` is not used anymore) + +## Parity [v1.10.2](https://github.com/paritytech/parity/releases/tag/v1.10.2) (2018-04-24) + +Parity 1.10.2 is a bug-fix release to improve performance and stability. + +The full list of included changes: + +- Update Parity beta to 1.10.2 + Backports ([#8455](https://github.com/paritytech/parity/pull/8455)) + - Update Parity beta to 1.10.2 + - Allow 32-bit pipelines to fail ([#8454](https://github.com/paritytech/parity/pull/8454)) + - Disable 32-bit targets for Gitlab + - Rename Linux pipelines + - Update wasmi ([#8452](https://github.com/paritytech/parity/pull/8452)) + - Fix Cargo.lock +- Backports ([#8450](https://github.com/paritytech/parity/pull/8450)) + - Use forked app_dirs crate for reverted Windows dir behavior ([#8438](https://github.com/paritytech/parity/pull/8438)) + - Remove unused app_dirs dependency in CLI + - Use forked app_dirs crate for reverted Windows dir behavior + - Remove Tendermint extra_info due to seal inconsistencies ([#8367](https://github.com/paritytech/parity/pull/8367)) + - Handle queue import errors a bit more gracefully ([#8385](https://github.com/paritytech/parity/pull/8385)) + - Improve VM executor stack size estimation rules ([#8439](https://github.com/paritytech/parity/pull/8439)) + - Improve VM executor stack size estimation rules + - Typo: docs add "(Debug build)" comment + - Fix an off by one typo and set minimal stack size + - Use saturating_sub to avoid potential overflow + +## Parity [v1.10.1](https://github.com/paritytech/parity/releases/tag/v1.10.1) (2018-04-17) + +Parity 1.10.1 is a bug-fix release to improve performance and stability. Among other changes, you can now use `--warp-barrier [BLOCK]` to specify a minimum block number to `--warp` to. This is useful in cases where clients restore to outdated snapshots far behind the latest chain head. + +The full list of included changes: + +- Bump beta to 1.10.1 ([#8350](https://github.com/paritytech/parity/pull/8350)) + - Bump beta to 1.10.1 + - Unflag critical release +- Backports ([#8346](https://github.com/paritytech/parity/pull/8346)) + - Warp-only sync with warp-barrier [blocknumber] flag. ([#8228](https://github.com/paritytech/parity/pull/8228)) + - Warp-only sync with warp-after [blocknumber] flag. + - Fix tests. + - Fix configuration tests. + - Rename to warp barrier. + - Allow unsafe js eval on Parity Wallet. ([#8204](https://github.com/paritytech/parity/pull/8204)) + - Update musicoin spec in line with gmc v2.6.2 ([#8242](https://github.com/paritytech/parity/pull/8242)) + - Supress TemporaryInvalid verification failures. ([#8256](https://github.com/paritytech/parity/pull/8256)) + - Include suicided accounts in state diff ([#8297](https://github.com/paritytech/parity/pull/8297)) + - Include suicided accounts in state diff + - Shorten form match -> if let + - Test suicide trace diff in State + - Replace_home for password_files, reserved_peers and log_file ([#8324](https://github.com/paritytech/parity/pull/8324)) + - Replace_home for password_files, reserved_peers and log_file + - Typo: arg_log_file is Option + - Enable UI by default, but only display info page. + - Fix test. + - Fix naming and remove old todo. + - Change "wallet" with "browser UI" +- Change name Wallet -> UI ([#8164](https://github.com/paritytech/parity/pull/8164)) ([#8205](https://github.com/paritytech/parity/pull/8205)) + - Change name Wallet -> UI + - Make warning bold +- Backport [#8099](https://github.com/paritytech/parity/pull/8099) ([#8132](https://github.com/paritytech/parity/pull/8132)) +- WASM libs ([#8220](https://github.com/paritytech/parity/pull/8220)) + - Bump wasm libs ([#8171](https://github.com/paritytech/parity/pull/8171)) + - Bump wasmi version ([#8209](https://github.com/paritytech/parity/pull/8209)) +- Update hyper to 0.11.24 ([#8203](https://github.com/paritytech/parity/pull/8203)) +- Updated jsonrpc to include latest backports (beta) ([#8181](https://github.com/paritytech/parity/pull/8181)) + - Updated jsonrpc to include latest backports + - Update dependencies. + +## Parity [v1.10.0](https://github.com/paritytech/parity/releases/tag/v1.10.0) (2018-03-22) + +This is the Parity 1.10.0-beta release! Cool! + +### Disabling the Parity Wallet + +The **Parity Wallet (a.k.a. "UI") is now disabled by default**. We are preparing to split the wallet from the core client. + +To reactivate the parity wallet, you have to run Parity either with `parity --force-ui` (not recommended) or `parity ui` (deprecated) from the command line. Or, if you feel super fancy and want to test our pre-releases of the stand-alone electron wallet, head over to the [Parity-JS repositories and check the releases](https://github.com/Parity-JS/shell/releases). + +Further reading: + +- [Docs: Parity Wallet](https://wiki.parity.io/Parity-Wallet) +- [Docs: How to customize Parity UI?](https://wiki.parity.io/FAQ-Customize-Parity-UI.html) +- [Github: Parity-JS](https://github.com/parity-js) + +### Introducing the Wasm VM + +We are excited to announce support for **Wasm Smart Contracts on Kovan network**. The hard-fork to activate the Wasm-VM will take place on block `6_600_000`. + +To enable Wasm contracts on your custom network, just schedule a `wasmActivationTransition` at your favorite block number (e.g., `42`, `666`, or `0xbada55`). To hack your first Wasm smart contracts in Rust, have a look at the [Parity Wasm Tutorials](https://github.com/paritytech/pwasm-tutorial). + +Further reading: + +- [Docs: WebAssembly (wasm)](https://wiki.parity.io/WebAssembly-Home) +- [Docs: Wasm VM Design](https://wiki.parity.io/WebAssembly-Design) +- [Docs: Wasm tutorials and examples](https://wiki.parity.io/WebAssembly-Links) + +### Empty step messages in PoA + +To **reduce blockchain bloat, proof-of-authority networks can now enable _empty step messages_ which replace empty blocks**. Each step message will be signed and broadcasted by the issuing authorities, and included and rewarded in the next non-empty block. + +To enable empty step messages, set the `emptyStepsTransition` to your favorite block number. You can also specify a maximum number of empty steps with `maximumEmptySteps` in your chain spec. + +### Other noteworthy changes + +We removed the old database migrations from 2016. In case you upgrade Parity from a really, really old version, you will have to reset your database manually first with `parity db kill`. + +We fixed DELEGATECALL `from` and `to` fields, see [#7166](https://github.com/paritytech/parity/issues/7166). + +We reduced the default USD per transaction value to 0.0001. Thanks, @MysticRyuujin! + +The Musicoin chain is now enabled with Byzantium features starting at block `2_222_222`. + +### Overview of all changes included + +The full list of included changes: + +- Re-enable signer, even with no UI. ([#8167](https://github.com/paritytech/parity/pull/8167)) ([#8168](https://github.com/paritytech/parity/pull/8168)) + - Re-enable signer, even with no UI. + - Fix message. +- Beta Backports ([#8136](https://github.com/paritytech/parity/pull/8136)) + - Support parity protocol. ([#8035](https://github.com/paritytech/parity/pull/8035)) + - updater: apply exponential backoff after download failure ([#8059](https://github.com/paritytech/parity/pull/8059)) + - updater: apply exponential backoff after download failure + - updater: reset backoff on new release + - Max code size on Kovan ([#8067](https://github.com/paritytech/parity/pull/8067)) + - Enable code size limit on kovan + - Fix formatting. + - Limit incoming connections. ([#8060](https://github.com/paritytech/parity/pull/8060)) + - Limit ingress connections + - Optimized handshakes logging + - WASM libraries bump ([#7970](https://github.com/paritytech/parity/pull/7970)) + - update wasmi, parity-wasm, wasm-utils to latest version + - Update to new wasmi & error handling + - also utilize new stack limiter + - fix typo + - replace dependency url + - Cargo.lock update + - add some dos protection ([#8084](https://github.com/paritytech/parity/pull/8084)) + - revert removing blooms ([#8066](https://github.com/paritytech/parity/pull/8066)) + - Revert "fix traces, removed bloomchain crate, closes [#7228](https://github.com/paritytech/parity/issues/7228), closes [#7167](https://github.com/paritytech/parity/issues/7167)" + - Revert "fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934))" + - fixed broken logs + - bring back old lock order + - remove migration v13 + - revert CURRENT_VERSION to 12 in migration.rs + - more dos protection ([#8104](https://github.com/paritytech/parity/pull/8104)) + - Const time comparison ([#8113](https://github.com/paritytech/parity/pull/8113)) + - Use `subtle::slices_equal` for constant time comparison. + - Also update the existing version of subtle in `ethcrypto` from 0.1 to 0.5 + - Test specifically for InvalidPassword error. + - fix trace filter returning returning unrelated reward calls, closes #8070 ([#8098](https://github.com/paritytech/parity/pull/8098)) + - network: init discovery using healthy nodes ([#8061](https://github.com/paritytech/parity/pull/8061)) + - network: init discovery using healthy nodes + - network: fix style grumble + - network: fix typo + - Postpone Kovan hard fork ([#8137](https://github.com/paritytech/parity/pull/8137)) + - ethcore: postpone Kovan hard fork + - util: update version fork metadata + - Disable UI by default. ([#8105](https://github.com/paritytech/parity/pull/8105)) + - dapps: update parity-ui dependencies ([#8160](https://github.com/paritytech/parity/pull/8160)) +- Probe changes one step deeper ([#8134](https://github.com/paritytech/parity/pull/8134)) ([#8135](https://github.com/paritytech/parity/pull/8135)) +- Beta backports ([#8053](https://github.com/paritytech/parity/pull/8053)) + - CI: Fix cargo cache ([#7968](https://github.com/paritytech/parity/pull/7968)) + - Fix cache + - Only clean locked cargo cache on windows + - fixed ethstore sign ([#8026](https://github.com/paritytech/parity/pull/8026)) + - fixed parsing ethash seals and verify_block_undordered ([#8031](https://github.com/paritytech/parity/pull/8031)) + - fix for verify_block_basic crashing on invalid transaction rlp ([#8032](https://github.com/paritytech/parity/pull/8032)) + - fix cache & snapcraft CI build ([#8052](https://github.com/paritytech/parity/pull/8052)) + - Add MCIP-6 Byzyantium transition to Musicoin spec ([#7841](https://github.com/paritytech/parity/pull/7841)) + - Add test chain spec for musicoin byzantium testnet + - Add MCIP-6 Byzyantium transition to Musicoin spec + - Update mcip6_byz.json + - ethcore: update musicoin byzantium block number + - ethcore: update musicoin bootnodes + - Update musicoin.json + - More bootnodes. +- Make 1.10 beta ([#8022](https://github.com/paritytech/parity/pull/8022)) + - Make 1.10 beta + - Fix gitlab builds +- SecretStore: secretstore_generateDocumentKey RPC ([#7864](https://github.com/paritytech/parity/pull/7864)) +- SecretStore: ECDSA session for cases when 2*t < N ([#7739](https://github.com/paritytech/parity/pull/7739)) +- bump tiny-keccak ([#8019](https://github.com/paritytech/parity/pull/8019)) +- Remove un-necessary comment ([#8014](https://github.com/paritytech/parity/pull/8014)) +- clean up account fmt::Debug ([#7983](https://github.com/paritytech/parity/pull/7983)) +- improve quality of vote_collector module ([#7984](https://github.com/paritytech/parity/pull/7984)) +- ExecutedBlock cleanup ([#7991](https://github.com/paritytech/parity/pull/7991)) +- Hardware-wallet/usb-subscribe-refactor ([#7860](https://github.com/paritytech/parity/pull/7860)) +- remove wildcard imports from views, make tests more idiomatic ([#7986](https://github.com/paritytech/parity/pull/7986)) +- moved PerfTimer to a separate crate - "trace-time" ([#7985](https://github.com/paritytech/parity/pull/7985)) +- clean up ethcore::spec module imports ([#7990](https://github.com/paritytech/parity/pull/7990)) +- rpc: don't include current block in new_block_filter ([#7982](https://github.com/paritytech/parity/pull/7982)) +- fix traces, removed bloomchain crate ([#7979](https://github.com/paritytech/parity/pull/7979)) +- simplify compression and move it out of rlp crate ([#7957](https://github.com/paritytech/parity/pull/7957)) +- removed old migrations ([#7974](https://github.com/paritytech/parity/pull/7974)) +- Reject too large packets in snapshot sync. ([#7977](https://github.com/paritytech/parity/pull/7977)) +- fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934)) +- Increase max download limit to 128MB ([#7965](https://github.com/paritytech/parity/pull/7965)) +- Calculate proper keccak256/sha3 using parity. ([#7953](https://github.com/paritytech/parity/pull/7953)) +- Add changelog for 1.8.10 stable and 1.9.3 beta ([#7947](https://github.com/paritytech/parity/pull/7947)) +- kvdb-rocksdb: remove buffered operations when committing transaction ([#7950](https://github.com/paritytech/parity/pull/7950)) +- Bump WebSockets ([#7952](https://github.com/paritytech/parity/pull/7952)) +- removed redundant Bloom conversions ([#7932](https://github.com/paritytech/parity/pull/7932)) +- simplify RefInfo fmt ([#7929](https://github.com/paritytech/parity/pull/7929)) +- Kovan WASM fork code ([#7849](https://github.com/paritytech/parity/pull/7849)) +- bring back trie and triehash benches ([#7926](https://github.com/paritytech/parity/pull/7926)) +- removed redundant PodAccount::new method ([#7928](https://github.com/paritytech/parity/pull/7928)) +- removed dummy wrapper structure - LogGroupPosition ([#7922](https://github.com/paritytech/parity/pull/7922)) +- spec: Validate required divisor fields are not 0 ([#7933](https://github.com/paritytech/parity/pull/7933)) +- simplify Client::filter_traces method ([#7936](https://github.com/paritytech/parity/pull/7936)) +- gitlab cache ([#7921](https://github.com/paritytech/parity/pull/7921)) +- Fix a division by zero in light client RPC handler ([#7917](https://github.com/paritytech/parity/pull/7917)) +- triehash optimisations ([#7920](https://github.com/paritytech/parity/pull/7920)) +- removed redundant Blockchain::db method ([#7919](https://github.com/paritytech/parity/pull/7919)) +- removed redundant Blockchain::rewind method ([#7918](https://github.com/paritytech/parity/pull/7918)) +- Pending transactions subscription ([#7906](https://github.com/paritytech/parity/pull/7906)) +- removed redundant otry! macro from ethcore ([#7916](https://github.com/paritytech/parity/pull/7916)) +- Make block generator easier to use ([#7888](https://github.com/paritytech/parity/pull/7888)) +- ECIP 1041 - Remove Difficulty Bomb ([#7905](https://github.com/paritytech/parity/pull/7905)) +- Fix CSP for dapps that require eval. ([#7867](https://github.com/paritytech/parity/pull/7867)) +- Fix gitlab ([#7901](https://github.com/paritytech/parity/pull/7901)) +- Gitlb snap master patch ([#7900](https://github.com/paritytech/parity/pull/7900)) +- fix snap build master ([#7896](https://github.com/paritytech/parity/pull/7896)) +- Fix wallet import ([#7873](https://github.com/paritytech/parity/pull/7873)) +- Fix snapcraft nightly ([#7884](https://github.com/paritytech/parity/pull/7884)) +- Add a timeout for light client sync requests ([#7848](https://github.com/paritytech/parity/pull/7848)) +- SecretStore: fixed test ([#7878](https://github.com/paritytech/parity/pull/7878)) +- Fix checksums and auto-update push ([#7846](https://github.com/paritytech/parity/pull/7846)) +- Forward-port snap fixes ([#7831](https://github.com/paritytech/parity/pull/7831)) +- Update gitlab-test.sh ([#7883](https://github.com/paritytech/parity/pull/7883)) +- Fix installer binary names for macos and windows ([#7881](https://github.com/paritytech/parity/pull/7881)) +- Fix string typo: "develoopment" -> "development" ([#7874](https://github.com/paritytech/parity/pull/7874)) +- Update the instructions to install the stable snap ([#7876](https://github.com/paritytech/parity/pull/7876)) +- SecretStore: 'broadcast' decryption session ([#7843](https://github.com/paritytech/parity/pull/7843)) +- Flush keyfiles. Resolves #7632 ([#7868](https://github.com/paritytech/parity/pull/7868)) +- Read registry_address from given block ([#7866](https://github.com/paritytech/parity/pull/7866)) +- Clean up docs formatting for Wasm runtime ([#7869](https://github.com/paritytech/parity/pull/7869)) +- WASM: Disable internal memory ([#7842](https://github.com/paritytech/parity/pull/7842)) +- Update gitlab-build.sh ([#7855](https://github.com/paritytech/parity/pull/7855)) +- ethabi version 5 ([#7723](https://github.com/paritytech/parity/pull/7723)) +- Light client: randomize the peer we dispatch requests to ([#7844](https://github.com/paritytech/parity/pull/7844)) +- Store updater metadata in a single place ([#7832](https://github.com/paritytech/parity/pull/7832)) +- Add new EF ropstens nodes. ([#7824](https://github.com/paritytech/parity/pull/7824)) +- refactor stratum to remove retain cycle ([#7827](https://github.com/paritytech/parity/pull/7827)) +- Bump jsonrpc. ([#7828](https://github.com/paritytech/parity/pull/7828)) +- Add binary identifiers and sha256sum to builds ([#7830](https://github.com/paritytech/parity/pull/7830)) +- Update references to UI shell & wallet ([#7808](https://github.com/paritytech/parity/pull/7808)) +- Adjust storage update evm-style ([#7812](https://github.com/paritytech/parity/pull/7812)) +- Updated WASM Runtime & new interpreter (wasmi) ([#7796](https://github.com/paritytech/parity/pull/7796)) +- SecretStore: ignore removed authorities when running auto-migration ([#7674](https://github.com/paritytech/parity/pull/7674)) +- Fix build ([#7807](https://github.com/paritytech/parity/pull/7807)) +- Move js & js-old code to github.com/parity-js ([#7685](https://github.com/paritytech/parity/pull/7685)) +- More changelogs :) ([#7782](https://github.com/paritytech/parity/pull/7782)) +- Actualized API set in help ([#7790](https://github.com/paritytech/parity/pull/7790)) +- Removed obsolete file ([#7788](https://github.com/paritytech/parity/pull/7788)) +- Update ropsten bootnodes ([#7776](https://github.com/paritytech/parity/pull/7776)) +- CHANGELOG for 1.9.1 and 1.8.8 ([#7775](https://github.com/paritytech/parity/pull/7775)) +- Enable byzantium features on non-ethash chains ([#7753](https://github.com/paritytech/parity/pull/7753)) +- Fix client not being dropped on shutdown ([#7695](https://github.com/paritytech/parity/pull/7695)) +- Filter-out nodes.json ([#7716](https://github.com/paritytech/parity/pull/7716)) +- Removes redundant parentheses ([#7721](https://github.com/paritytech/parity/pull/7721)) +- Transaction-pool fixes ([#7741](https://github.com/paritytech/parity/pull/7741)) +- More visible download link in README.md ([#7707](https://github.com/paritytech/parity/pull/7707)) +- Changelog for 1.9.0 ([#7664](https://github.com/paritytech/parity/pull/7664)) +- Add scroll when too many accounts ([#7677](https://github.com/paritytech/parity/pull/7677)) +- SecretStore: return HTTP 403 (access denied) if consensus is unreachable ([#7656](https://github.com/paritytech/parity/pull/7656)) +- Moved StopGaurd to it's own crate ([#7635](https://github.com/paritytech/parity/pull/7635)) + +## Previous releases + +- [CHANGELOG-1.9](docs/CHANGELOG-1.9.md) (_stable_) +- [CHANGELOG-1.8](docs/CHANGELOG-1.8.md) (EOL: 2018-03-22) +- [CHANGELOG-1.7](docs/CHANGELOG-1.7.md) (EOL: 2018-01-25) +- [CHANGELOG-1.6](docs/CHANGELOG-1.6.md) (EOL: 2017-10-15) +- [CHANGELOG-1.5](docs/CHANGELOG-1.5.md) (EOL: 2017-07-28) +- [CHANGELOG-1.4](docs/CHANGELOG-1.4.md) (EOL: 2017-03-13) +- [CHANGELOG-1.3](docs/CHANGELOG-1.3.md) (EOL: 2017-01-19) +- [CHANGELOG-1.2](docs/CHANGELOG-1.2.md) (EOL: 2016-11-07) +- [CHANGELOG-1.1](docs/CHANGELOG-1.1.md) (EOL: 2016-08-12) +- [CHANGELOG-1.0](docs/CHANGELOG-1.0.md) (EOL: 2016-06-24) +- [CHANGELOG-0.9](docs/CHANGELOG-0.9.md) (EOL: 2016-05-02) diff --git a/docs/CHANGELOG-1.9.md b/docs/CHANGELOG-1.9.md index 133c93c4770..2be3fcf27b2 100644 --- a/docs/CHANGELOG-1.9.md +++ b/docs/CHANGELOG-1.9.md @@ -1,3 +1,5 @@ +Note: Parity 1.9 reached End-of-Life on 2018-05-09 (EOL). + ## Parity [v1.9.7](https://github.com/paritytech/parity/releases/tag/v1.9.7) (2018-04-23) Parity 1.9.7 is a bug-fix release to improve performance and stability. From cb7ad2366dc2b62ac95e844287e516ebf6024772 Mon Sep 17 00:00:00 2001 From: David Date: Wed, 9 May 2018 15:58:02 +0200 Subject: [PATCH 49/95] Handle socket address parsing errors (#8545) Unpack errors and check for io::ErrorKind::InvalidInput and return our own AddressParse error. Remove the foreign link to std::net::AddrParseError and add an `impl From` for that error. Test parsing properly. --- Cargo.lock | 7 ++++ util/network-devp2p/Cargo.toml | 1 + util/network-devp2p/src/lib.rs | 2 ++ util/network-devp2p/src/node_table.rs | 52 ++++++++++++++++++++++----- util/network/src/error.rs | 11 +++++- 5 files changed, 63 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b02fcbd24e5..edd76f9f4de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,6 +35,11 @@ dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "assert_matches" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "aster" version = "0.41.0" @@ -699,6 +704,7 @@ name = "ethcore-network-devp2p" version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0", @@ -3767,6 +3773,7 @@ dependencies = [ "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum app_dirs 1.2.1 (git+https://github.com/paritytech/app-dirs-rs)" = "" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" +"checksum assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "664470abf00fae0f31c0eb6e1ca12d82961b2a2541ef898bc9dd51a9254d218b" "checksum aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfdf7355d9db158df68f976ed030ab0f6578af811f5a7bb6dcf221ec24e0e0" "checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" "checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" diff --git a/util/network-devp2p/Cargo.toml b/util/network-devp2p/Cargo.toml index a8207ca615b..3ec96843931 100644 --- a/util/network-devp2p/Cargo.toml +++ b/util/network-devp2p/Cargo.toml @@ -38,6 +38,7 @@ error-chain = { version = "0.11", default-features = false } [dev-dependencies] tempdir = "0.3" +assert_matches = "1.2" [features] default = [] diff --git a/util/network-devp2p/src/lib.rs b/util/network-devp2p/src/lib.rs index 8faf21e465c..239763cbe18 100644 --- a/util/network-devp2p/src/lib.rs +++ b/util/network-devp2p/src/lib.rs @@ -95,6 +95,8 @@ extern crate serde_derive; #[cfg(test)] extern crate tempdir; +#[cfg(test)] #[macro_use] +extern crate assert_matches; mod host; mod connection; diff --git a/util/network-devp2p/src/node_table.rs b/util/network-devp2p/src/node_table.rs index 5079455866c..8640901cd09 100644 --- a/util/network-devp2p/src/node_table.rs +++ b/util/network-devp2p/src/node_table.rs @@ -14,6 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use discovery::{TableUpdates, NodeEntry}; +use ethereum_types::H512; +use ip_utils::*; +use network::{Error, ErrorKind, AllowIP, IpFilter}; +use rlp::{Rlp, RlpStream, DecoderError}; +use serde_json; use std::collections::{HashMap, HashSet}; use std::fmt::{self, Display, Formatter}; use std::hash::{Hash, Hasher}; @@ -23,12 +29,6 @@ use std::str::FromStr; use std::{fs, mem, slice}; use std::time::{self, Duration, SystemTime}; use rand::{self, Rng}; -use ethereum_types::H512; -use rlp::{Rlp, RlpStream, DecoderError}; -use network::{Error, ErrorKind, AllowIP, IpFilter}; -use discovery::{TableUpdates, NodeEntry}; -use ip_utils::*; -use serde_json; /// Node public key pub type NodeId = H512; @@ -124,8 +124,8 @@ impl FromStr for NodeEndpoint { address: a, udp_port: a.port() }), - Ok(_) => Err(ErrorKind::AddressResolve(None).into()), - Err(e) => Err(ErrorKind::AddressResolve(Some(e)).into()) + Ok(None) => bail!(ErrorKind::AddressResolve(None)), + Err(_) => Err(ErrorKind::AddressParse.into()) // always an io::Error of InvalidInput kind } } } @@ -534,11 +534,34 @@ mod tests { assert!(endpoint.is_ok()); let v4 = match endpoint.unwrap().address { SocketAddr::V4(v4address) => v4address, - _ => panic!("should ve v4 address") + _ => panic!("should be v4 address") }; assert_eq!(SocketAddrV4::new(Ipv4Addr::new(123, 99, 55, 44), 7770), v4); } + #[test] + fn endpoint_parse_empty_ip_string_returns_error() { + let endpoint = NodeEndpoint::from_str(""); + assert!(endpoint.is_err()); + assert_matches!(endpoint.unwrap_err().kind(), &ErrorKind::AddressParse); + } + + #[test] + fn endpoint_parse_invalid_ip_string_returns_error() { + let endpoint = NodeEndpoint::from_str("beef"); + assert!(endpoint.is_err()); + assert_matches!(endpoint.unwrap_err().kind(), &ErrorKind::AddressParse); + } + + #[test] + fn endpoint_parse_valid_ip_without_port_returns_error() { + let endpoint = NodeEndpoint::from_str("123.123.123.123"); + assert!(endpoint.is_err()); + assert_matches!(endpoint.unwrap_err().kind(), &ErrorKind::AddressParse); + let endpoint = NodeEndpoint::from_str("123.123.123.123:123"); + assert!(endpoint.is_ok()) + } + #[test] fn node_parse() { assert!(validate_node_url("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").is_none()); @@ -555,6 +578,17 @@ mod tests { node.id); } + #[test] + fn node_parse_fails_for_invalid_urls() { + let node = Node::from_str("foo"); + assert!(node.is_err()); + assert_matches!(node.unwrap_err().kind(), &ErrorKind::AddressParse); + + let node = Node::from_str("enode://foo@bar"); + assert!(node.is_err()); + assert_matches!(node.unwrap_err().kind(), &ErrorKind::AddressParse); + } + #[test] fn table_last_contact_order() { let node1 = Node::from_str("enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@22.99.55.44:7770").unwrap(); diff --git a/util/network/src/error.rs b/util/network/src/error.rs index 6342bfe4ad6..61044866966 100644 --- a/util/network/src/error.rs +++ b/util/network/src/error.rs @@ -84,11 +84,16 @@ error_chain! { foreign_links { SocketIo(IoError) #[doc = "Socket IO error."]; Io(io::Error) #[doc = "Error concerning the Rust standard library's IO subsystem."]; - AddressParse(net::AddrParseError) #[doc = "Error concerning the network address parsing subsystem."]; Decompression(snappy::InvalidInput) #[doc = "Decompression error."]; } errors { + #[doc = "Error concerning the network address parsing subsystem."] + AddressParse { + description("Failed to parse network address"), + display("Failed to parse network address"), + } + #[doc = "Error concerning the network address resolution subsystem."] AddressResolve(err: Option) { description("Failed to resolve network address"), @@ -163,6 +168,10 @@ impl From for Error { } } +impl From for Error { + fn from(_err: net::AddrParseError) -> Self { ErrorKind::AddressParse.into() } +} + #[test] fn test_errors() { assert_eq!(DisconnectReason::ClientQuit, DisconnectReason::from_u8(8)); From cddc33bb24edf5e8b5d9052338965247829c5f4b Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Thu, 10 May 2018 00:41:56 +0800 Subject: [PATCH 50/95] Remove unnecessary cloning in overwrite_with (#8580) * Remove unnecessary cloning in overwrite_with * Remove into_iter --- ethcore/src/state/account.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/state/account.rs b/ethcore/src/state/account.rs index ff7d70bd3aa..5c1dd403969 100644 --- a/ethcore/src/state/account.rs +++ b/ethcore/src/state/account.rs @@ -460,7 +460,7 @@ impl Account { self.address_hash = other.address_hash; let mut cache = self.storage_cache.borrow_mut(); for (k, v) in other.storage_cache.into_inner() { - cache.insert(k.clone() , v.clone()); //TODO: cloning should not be required here + cache.insert(k, v); } self.storage_changes = other.storage_changes; } From 1d42b7f0d1f44a3495f973704be494fd52644285 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Wed, 9 May 2018 23:21:16 +0200 Subject: [PATCH 51/95] changelog nit (#8585) --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c7dcf878be..f839802e7cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,6 @@ Notable changes in reversed alphabetical order: - `whisper-cli` is a standalone tool to communicate with the Whisper protocol. - It provides functionality to specify `whisper-pool-size`, `port` and `address` to use. - All whisper RPC APIs are enabled and can be directly acessed. -I'm not used to writing these changelogs but I guess that would explain it - JSON-RPC API: **Return error in case eth_call returns VM errors** [#8448](https://github.com/paritytech/parity/pull/8448) - This changes the behaviors of `eth_call` to respect VM errors if any. - In case of `REVERT`, it will also return the reverted return data in hex format. From 21dad1d41ec3d1336a9a6a7c7e8eb4c9194dc2bd Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Wed, 9 May 2018 23:25:58 +0200 Subject: [PATCH 52/95] Rename `whisper-cli binary` to `whisper` (#8579) * rename whisper-cli binary to whisper * fix tests --- whisper/cli/Cargo.toml | 4 +++- whisper/cli/src/main.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/whisper/cli/Cargo.toml b/whisper/cli/Cargo.toml index 363471a1a34..9aea1a8776e 100644 --- a/whisper/cli/Cargo.toml +++ b/whisper/cli/Cargo.toml @@ -1,7 +1,9 @@ [package] name = "whisper-cli" +description = "Whisper command line interface" version = "0.1.0" authors = ["Parity Technologies "] +license = "GPL-3.0" [dependencies] ethcore-network-devp2p = { path = "../../util/network-devp2p" } @@ -18,5 +20,5 @@ jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branc log = "0.3" [[bin]] -name = "whisper-cli" +name = "whisper" path = "src/main.rs" diff --git a/whisper/cli/src/main.rs b/whisper/cli/src/main.rs index d0866cd66a8..f9211b993b4 100644 --- a/whisper/cli/src/main.rs +++ b/whisper/cli/src/main.rs @@ -46,7 +46,7 @@ use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation}; const POOL_UNIT: usize = 1024 * 1024; const USAGE: &'static str = r#" Whisper CLI. - Copyright 2017 Parity Technologies (UK) Ltd + Copyright 2018 Parity Technologies (UK) Ltd Usage: whisper [options] @@ -56,7 +56,7 @@ Options: --whisper-pool-size SIZE Specify Whisper pool size [default: 10]. -p, --port PORT Specify which RPC port to use [default: 8545]. -a, --address ADDRESS Specify which address to use [default: 127.0.0.1]. - -l, --log LEVEL Specify the logging level. Must conform to the same format as RUST_LOG [default: Error]. + -l, --log LEVEL Specify the logging level. Must conform to the same format as RUST_LOG [default: Error]. -h, --help Display this message and exit. "#; @@ -259,7 +259,7 @@ mod tests { #[test] fn invalid_argument() { - let command = vec!["whisper-cli", "--foo=12"] + let command = vec!["whisper", "--foo=12"] .into_iter() .map(Into::into) .collect::>(); @@ -270,7 +270,7 @@ mod tests { #[test] #[ignore] fn privileged_port() { - let command = vec!["whisper-cli", "--port=3"] + let command = vec!["whisper", "--port=3"] .into_iter() .map(Into::into) .collect::>(); @@ -280,7 +280,7 @@ mod tests { #[test] fn invalid_ip_address() { - let command = vec!["whisper-cli", "--address=x.x.x.x"] + let command = vec!["whisper", "--address=x.x.x.x"] .into_iter() .map(Into::into) .collect::>(); @@ -290,7 +290,7 @@ mod tests { #[test] fn invalid_whisper_pool_size() { - let command = vec!["whisper-cli", "--whisper-pool-size=-100000000000000000000000000000000000000"] + let command = vec!["whisper", "--whisper-pool-size=-100000000000000000000000000000000000000"] .into_iter() .map(Into::into) .collect::>(); From b2cc1c54f891c35364627757280ee33e836987ef Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Wed, 9 May 2018 23:26:30 +0200 Subject: [PATCH 53/95] Add whisper CLI to the pipelines (#8578) * Add whisper CLI to the pipelines * Address todo, ref #8579 --- scripts/gitlab-build.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/scripts/gitlab-build.sh b/scripts/gitlab-build.sh index 89fa2a08541..2f1b7b8d086 100755 --- a/scripts/gitlab-build.sh +++ b/scripts/gitlab-build.sh @@ -62,13 +62,16 @@ build () { cargo build --target $PLATFORM --release -p ethstore-cli echo "Build ethkey-cli:" cargo build --target $PLATFORM --release -p ethkey-cli + echo "Build whisper-cli:" + cargo build --target $PLATFORM --release -p whisper-cli } strip_binaries () { echo "Strip binaries:" $STRIP_BIN -v target/$PLATFORM/release/parity $STRIP_BIN -v target/$PLATFORM/release/parity-evm $STRIP_BIN -v target/$PLATFORM/release/ethstore - $STRIP_BIN -v target/$PLATFORM/release/ethkey; + $STRIP_BIN -v target/$PLATFORM/release/ethkey + $STRIP_BIN -v target/$PLATFORM/release/whisper; } calculate_checksums () { echo "Checksum calculation:" @@ -89,6 +92,8 @@ calculate_checksums () { $SHA256_BIN target/$PLATFORM/release/ethstore$S3WIN > ethstore$S3WIN.sha256 $MD5_BIN target/$PLATFORM/release/ethkey$S3WIN > ethkey$S3WIN.md5 $SHA256_BIN target/$PLATFORM/release/ethkey$S3WIN > ethkey$S3WIN.sha256 + $MD5_BIN target/$PLATFORM/release/whisper$S3WIN > whisper$S3WIN.md5 + $SHA256_BIN target/$PLATFORM/release/whisper$S3WIN > whisper$S3WIN.sha256 } make_deb () { rm -rf deb @@ -122,6 +127,7 @@ make_deb () { cp target/$PLATFORM/release/parity-evm deb/usr/bin/parity-evm cp target/$PLATFORM/release/ethstore deb/usr/bin/ethstore cp target/$PLATFORM/release/ethkey deb/usr/bin/ethkey + cp target/$PLATFORM/release/whisper deb/usr/bin/whisper dpkg-deb -b deb "parity_"$VER"_"$IDENT"_"$ARC".deb" $MD5_BIN "parity_"$VER"_"$IDENT"_"$ARC".deb" > "parity_"$VER"_"$IDENT"_"$ARC".deb.md5" $SHA256_BIN "parity_"$VER"_"$IDENT"_"$ARC".deb" > "parity_"$VER"_"$IDENT"_"$ARC".deb.sha256" @@ -133,6 +139,7 @@ make_rpm () { cp target/$PLATFORM/release/parity-evm /install/usr/bin/parity-evm cp target/$PLATFORM/release/ethstore /install/usr/bin/ethstore cp target/$PLATFORM/release/ethkey /install/usr/bin/ethkey + cp target/$PLATFORM/release/whisper /install/usr/bin/whisper rm -rf "parity-"$VER"-1."$ARC".rpm" || true fpm -s dir -t rpm -n parity -v $VER --epoch 1 --license GPLv3 -d openssl --provides parity --url https://parity.io --vendor "Parity Technologies" -a x86_64 -m "" --description "Ethereum network client by Parity Technologies" -C /install/ @@ -146,6 +153,7 @@ make_pkg () { cp target/$PLATFORM/release/parity-evm target/release/parity-evm cp target/$PLATFORM/release/ethstore target/release/ethstore cp target/$PLATFORM/release/ethkey target/release/ethkey + cp target/$PLATFORM/release/whisper target/release/whisper cd mac xcodebuild -configuration Release cd .. @@ -194,6 +202,9 @@ push_binaries () { aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$BUILD_PLATFORM/ethkey$S3WIN --body target/$PLATFORM/release/ethkey$S3WIN aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$BUILD_PLATFORM/ethkey$S3WIN.md5 --body ethkey$S3WIN.md5 aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$BUILD_PLATFORM/ethkey$S3WIN.sha256 --body ethkey$S3WIN.sha256 + aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$BUILD_PLATFORM/whisper$S3WIN --body target/$PLATFORM/release/whisper$S3WIN + aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$BUILD_PLATFORM/whisper$S3WIN.md5 --body whisper$S3WIN.md5 + aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$BUILD_PLATFORM/whisper$S3WIN.sha256 --body whisper$S3WIN.sha256 aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$BUILD_PLATFORM/"parity_"$VER"_"$IDENT"_"$ARC"."$EXT --body "parity_"$VER"_"$IDENT"_"$ARC"."$EXT aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$BUILD_PLATFORM/"parity_"$VER"_"$IDENT"_"$ARC"."$EXT".md5" --body "parity_"$VER"_"$IDENT"_"$ARC"."$EXT".md5" aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$BUILD_PLATFORM/"parity_"$VER"_"$IDENT"_"$ARC"."$EXT".sha256" --body "parity_"$VER"_"$IDENT"_"$ARC"."$EXT".sha256" @@ -201,7 +212,7 @@ push_binaries () { make_archive () { echo "add artifacts to archive" rm -rf parity.zip - zip -r parity.zip target/$PLATFORM/release/parity$S3WIN target/$PLATFORM/release/parity-evm$S3WIN target/$PLATFORM/release/ethstore$S3WIN target/$PLATFORM/release/ethkey$S3WIN parity$S3WIN.md5 parity-evm$S3WIN.md5 ethstore$S3WIN.md5 ethkey$S3WIN.md5 parity$S3WIN.sha256 parity-evm$S3WIN.sha256 ethstore$S3WIN.sha256 ethkey$S3WIN.sha256 + zip -r parity.zip target/$PLATFORM/release/parity$S3WIN target/$PLATFORM/release/parity-evm$S3WIN target/$PLATFORM/release/ethstore$S3WIN target/$PLATFORM/release/ethkey$S3WIN target/$PLATFORM/release/whisper$S3WIN parity$S3WIN.md5 parity-evm$S3WIN.md5 ethstore$S3WIN.md5 ethkey$S3WIN.md5 whisper$S3WIN.md5 parity$S3WIN.sha256 parity-evm$S3WIN.sha256 ethstore$S3WIN.sha256 ethkey$S3WIN.sha256 whisper$S3WIN.sha256 } updater_push_release () { From a57c45bb1c79799a5ec68dd30eedb755545809bc Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 9 May 2018 23:28:16 +0200 Subject: [PATCH 54/95] Added Dockerfile for alpine linux by @andresilva, closes #3565 (#8587) --- docker/alpine/Dockerfile | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 docker/alpine/Dockerfile diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile new file mode 100644 index 00000000000..ad8879ecf73 --- /dev/null +++ b/docker/alpine/Dockerfile @@ -0,0 +1,29 @@ +FROM alpine:3.7 + +WORKDIR /build + +# install tools and dependencies +RUN apk add --no-cache gcc musl-dev openssl-dev pkgconfig g++ make curl \ + eudev-dev rust cargo git file binutils libusb-dev \ + linux-headers + +# show backtraces +ENV RUST_BACKTRACE 1 + +# show tools +RUN rustc -vV && \ +cargo -V && \ +gcc -v &&\ +g++ -v + +# build parity +ADD . /build/parity +RUN cd parity && \ + cargo build --release --verbose && \ + ls /build/parity/target/release/parity && \ + strip /build/parity/target/release/parity + +RUN file /build/parity/target/release/parity + +EXPOSE 8080 8545 8180 +ENTRYPOINT ["/build/parity/target/release/parity"] From fb0e6cf0d0759bf0f0657f9995b666e1d9ec3e7b Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Thu, 10 May 2018 12:33:40 +0200 Subject: [PATCH 55/95] Changelog and Readme (#8591) * Move changelog for 1.10.x * Mark 1.9 EOL * Prepare changelog for 1.10.3 stable * Prepare changelog for 1.11.0 stable * Update changelogs * Update CHANGELOG for 1.10.3 beta * Update CHANGELOG for 1.11.0 beta * Update CHANGELOG for 1.11.0 beta * Update CHANGELOG for 1.11.0 beta * Format changelog * Update README for 1.11 * Fix typo --- README.md | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index bfa7bde7bf6..36e855fe420 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,7 @@ Get in touch with us on Gitter: Or join our community on Matrix: [![Riot: +Parity](https://img.shields.io/badge/riot-%2Bparity%3Amatrix.parity.io-orange.svg)](https://riot.im/app/#/group/+parity:matrix.parity.io) -Official website: https://parity.io - -Be sure to check out [our wiki](https://wiki.parity.io) for more information. +Official website: https://parity.io | Be sure to check out [our wiki](https://wiki.parity.io) for more information. ---- @@ -29,28 +27,19 @@ Be sure to check out [our wiki](https://wiki.parity.io) for more information. Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs. -Parity comes with a built-in wallet, to install it please follow [these instructions](https://wiki.parity.io/Parity-Wallet). It includes various functionality allowing you to: - -- create and manage your Ethereum accounts; -- manage your Ether and any Ethereum tokens; -- create and register your own tokens; -- and much more. - -From Parity Ethereum client version >=1.10, the User Interface (UI) is accessible in a separate application called Parity UI. To keep using the UI in the browser (deprecated), [follow these steps](https://wiki.parity.io/FAQ-Basic-Operations,-Configuration,-and-Synchronization.md#the-parity-ui-application-isnt-working-the-way-i-want). +From Parity Ethereum client version 1.10.0, the User Interface (UI) is accessible in a separate application called Parity UI. To keep using the UI in the browser (deprecated), [follow these steps](https://wiki.parity.io/FAQ-Basic-Operations,-Configuration,-and-Synchronization.md#the-parity-ui-application-isnt-working-the-way-i-want). By default, Parity will also run a JSONRPC server on `127.0.0.1:8545` and a websockets server on `127.0.0.1:8546`. This is fully configurable and supports a number of APIs. -If you run into an issue while using Parity, feel free to file one in this repository or hop on our [Gitter](https://gitter.im/paritytech/parity) or [Riot](https://riot.im/app/#/group/+parity:matrix.parity.io) chat room to ask a question. We are glad to help! - -**For security-critical issues**, please refer to the security policy outlined in [SECURITY.MD](SECURITY.md). +If you run into an issue while using Parity, feel free to file one in this repository or hop on our [Gitter](https://gitter.im/paritytech/parity) or [Riot](https://riot.im/app/#/group/+parity:matrix.parity.io) chat room to ask a question. We are glad to help! **For security-critical issues**, please refer to the security policy outlined in [SECURITY.MD](SECURITY.md). -Parity's current release is 1.9. You can download it at https://github.com/paritytech/parity/releases or follow the instructions below to build from source. +Parity's current beta-release is 1.11. You can download it at https://github.com/paritytech/parity/releases or follow the instructions below to build from source. ---- ## Build dependencies -**Parity requires Rust version 1.23.0 to build** +**Parity requires Rust version 1.26.0 to build** We recommend installing Rust through [rustup](https://www.rustup.rs/). If you don't already have rustup, you can install it like this: @@ -124,13 +113,7 @@ Note: if cargo fails to parse manifest try: $ ~/.cargo/bin/cargo build --release ``` -Note: When compiling a crate and you receive the following error: - -``` -error: the crate is compiled with the panic strategy `abort` which is incompatible with this crate's strategy of `unwind` -``` - -Cleaning the repository will most likely solve the issue, try: +Note, when compiling a crate and you receive errors, it's in most cases your outdated version of Rust, or some of your crates have to be recompiled. Cleaning the repository will most likely solve the issue if you are on the latest stable version of Rust, try: ```bash $ cargo clean From 6e2e08628a91ae248729030e3ece3b8e926c805f Mon Sep 17 00:00:00 2001 From: David Date: Thu, 10 May 2018 12:33:56 +0200 Subject: [PATCH 56/95] Attempt to fix intermittent test failures (#8584) Occasionally should_return_correct_nonces_when_dropped_because_of_limit fails, possibly because of multiple threads competing to finish. See CI logs here for an example: https://gitlab.parity.io/parity/parity/-/jobs/86738 --- miner/src/pool/tests/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/miner/src/pool/tests/mod.rs b/miner/src/pool/tests/mod.rs index 0d8e38a6e11..5d80c2d5bf6 100644 --- a/miner/src/pool/tests/mod.rs +++ b/miner/src/pool/tests/mod.rs @@ -63,8 +63,10 @@ fn should_return_correct_nonces_when_dropped_because_of_limit() { let nonce = tx1.nonce; // when - let result = txq.import(TestClient::new(), vec![tx1, tx2].local()); - assert_eq!(result, vec![Ok(()), Err(transaction::Error::LimitReached)]); + let r1= txq.import(TestClient::new(), vec![tx1].local()); + let r2= txq.import(TestClient::new(), vec![tx2].local()); + assert_eq!(r1, vec![Ok(())]); + assert_eq!(r2, vec![Err(transaction::Error::LimitReached)]); assert_eq!(txq.status().status.transaction_count, 1); // then From 1b8f299df2e6a29738a090c47911cc218db49b8d Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 10 May 2018 12:34:36 +0200 Subject: [PATCH 57/95] Make mio optional in ethcore-io (#8537) * Make mio optional in ethcore-io * Add some annotations, plus a check for features * Increase timer for test --- Cargo.lock | 46 ++- ethcore/sync/Cargo.toml | 1 + test.sh | 2 + util/io/Cargo.toml | 9 +- util/io/src/lib.rs | 145 +++++++-- util/io/src/{service.rs => service_mio.rs} | 16 +- util/io/src/service_non_mio.rs | 334 +++++++++++++++++++++ util/io/src/worker.rs | 11 +- util/network-devp2p/Cargo.toml | 2 +- 9 files changed, 508 insertions(+), 58 deletions(-) rename util/io/src/{service.rs => service_mio.rs} (97%) create mode 100644 util/io/src/service_non_mio.rs diff --git a/Cargo.lock b/Cargo.lock index edd76f9f4de..b4d6bd315f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -209,6 +209,16 @@ dependencies = [ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "chrono" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cid" version = "0.2.3" @@ -542,7 +552,7 @@ dependencies = [ "memory-cache 0.1.0", "memorydb 0.1.1", "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-machine 0.1.0", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie 0.1.0", @@ -597,10 +607,14 @@ name = "ethcore-io" version = "1.12.0" dependencies = [ "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "timer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -991,7 +1005,7 @@ dependencies = [ "dir 0.1.0", "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethstore 0.2.0", - "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1117,7 +1131,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1483,7 +1497,7 @@ dependencies = [ "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)", @@ -1888,7 +1902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1981,7 +1995,7 @@ dependencies = [ "migration-rocksdb 0.1.0", "node-filter 1.12.0", "node-health 0.1.0", - "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", "parity-dapps 1.12.0", @@ -2680,7 +2694,7 @@ dependencies = [ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3183,7 +3197,7 @@ name = "threadpool" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3197,6 +3211,14 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "timer" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tiny-keccak" version = "1.4.1" @@ -3350,7 +3372,7 @@ dependencies = [ "crossbeam-deque 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3795,6 +3817,7 @@ dependencies = [ "checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9" "checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" "checksum cid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d85ee025368e69063c420cbb2ed9f852cb03a5e69b73be021e65726ce03585b6" "checksum clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8f4a2b3bb7ef3c672d7c13d15613211d5a6976b6892c598b0fcb5d40765f19c2" "checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299" @@ -3903,7 +3926,7 @@ dependencies = [ "checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" -"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d" +"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "59a14be9c211cb9c602bad35ac99f41e9a84b44d71b8cbd3040e3bd02a214902" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" "checksum order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "efa535d5117d3661134dbf1719b6f0ffe06f2375843b13935db186cd094105eb" @@ -4001,6 +4024,7 @@ dependencies = [ "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" +"checksum timer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b" "checksum tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "58911ed5eb275a8fd2f1f0418ed360a42f59329864b64e1e95377a9024498c01" "checksum tokio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be15ef40f675c9fe66e354d74c73f3ed012ca1aa14d65846a33ee48f1ae8d922" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" diff --git a/ethcore/sync/Cargo.toml b/ethcore/sync/Cargo.toml index ba03075d0e3..cf163cc7bd5 100644 --- a/ethcore/sync/Cargo.toml +++ b/ethcore/sync/Cargo.toml @@ -34,6 +34,7 @@ trace-time = { path = "../../util/trace-time" } ipnetwork = "0.12.6" [dev-dependencies] +ethcore-io = { path = "../../util/io", features = ["mio"] } ethkey = { path = "../../ethkey" } kvdb-memorydb = { path = "../../util/kvdb-memorydb" } ethcore-private-tx = { path = "../private-tx" } diff --git a/test.sh b/test.sh index 6dcd258ea36..9bb527b7083 100755 --- a/test.sh +++ b/test.sh @@ -33,6 +33,8 @@ if [ "$VALIDATE" -eq "1" ]; then # Validate --no-default-features build echo "________Validate build________" cargo check --no-default-features +cargo check --manifest-path util/io/Cargo.toml --no-default-features +cargo check --manifest-path util/io/Cargo.toml --features "mio" # Validate chainspecs echo "________Validate chainspecs________" diff --git a/util/io/Cargo.toml b/util/io/Cargo.toml index 8538863d03e..71688661605 100644 --- a/util/io/Cargo.toml +++ b/util/io/Cargo.toml @@ -7,9 +7,12 @@ version = "1.12.0" authors = ["Parity Technologies "] [dependencies] -mio = "0.6.8" +fnv = "1.0" +mio = { version = "0.6.8", optional = true } crossbeam = "0.3" parking_lot = "0.5" log = "0.3" -slab = "0.2" - +slab = "0.4" +num_cpus = "1.8" +timer = "0.2" +time = "0.1" diff --git a/util/io/src/lib.rs b/util/io/src/lib.rs index 9232b2a909a..ef8c3adc7ec 100644 --- a/util/io/src/lib.rs +++ b/util/io/src/lib.rs @@ -54,30 +54,59 @@ //! // Drop the service //! } //! ``` +//! +//! # Mio vs non-mio +//! +//! This library has two modes: mio and not mio. The `mio` feature can be activated or deactivated +//! when compiling or depending on the library. +//! +//! Without mio, only timers and message-passing are available. With mio, you can also use +//! low-level sockets provided by mio. +//! +//! The non-mio mode exists because the `mio` library doesn't compile on platforms such as +//! emscripten. //TODO: use Poll from mio #![allow(deprecated)] +#[cfg(feature = "mio")] extern crate mio; #[macro_use] extern crate log as rlog; extern crate slab; extern crate crossbeam; extern crate parking_lot; +extern crate num_cpus; +extern crate timer; +extern crate fnv; +extern crate time; -mod service; +#[cfg(feature = "mio")] +mod service_mio; +#[cfg(not(feature = "mio"))] +mod service_non_mio; +#[cfg(feature = "mio")] mod worker; +use std::cell::Cell; use std::{fmt, error}; +#[cfg(feature = "mio")] use mio::deprecated::{EventLoop, NotifyError}; +#[cfg(feature = "mio")] use mio::Token; -pub use worker::LOCAL_STACK_SIZE; +thread_local! { + /// Stack size + /// Should be modified if it is changed in Rust since it is no way + /// to know or get it + pub static LOCAL_STACK_SIZE: Cell = Cell::new(::std::env::var("RUST_MIN_STACK").ok().and_then(|s| s.parse().ok()).unwrap_or(2 * 1024 * 1024)); +} #[derive(Debug)] /// IO Error pub enum IoError { /// Low level error from mio crate + #[cfg(feature = "mio")] Mio(::std::io::Error), /// Error concerning the Rust standard library's IO subsystem. StdIo(::std::io::Error), @@ -88,6 +117,7 @@ impl fmt::Display for IoError { // just defer to the std implementation for now. // we can refine the formatting when more variants are added. match *self { + #[cfg(feature = "mio")] IoError::Mio(ref std_err) => std_err.fmt(f), IoError::StdIo(ref std_err) => std_err.fmt(f), } @@ -106,8 +136,9 @@ impl From<::std::io::Error> for IoError { } } -impl From>> for IoError where Message: Send { - fn from(_err: NotifyError>) -> IoError { +#[cfg(feature = "mio")] +impl From>> for IoError where Message: Send { + fn from(_err: NotifyError>) -> IoError { IoError::Mio(::std::io::Error::new(::std::io::ErrorKind::ConnectionAborted, "Network IO notification error")) } } @@ -123,58 +154,120 @@ pub trait IoHandler: Send + Sync where Message: Send + Sync + 'static { /// Called when a broadcasted message is received. The message can only be sent from a different IO handler. fn message(&self, _io: &IoContext, _message: &Message) {} /// Called when an IO stream gets closed + #[cfg(feature = "mio")] fn stream_hup(&self, _io: &IoContext, _stream: StreamToken) {} /// Called when an IO stream can be read from + #[cfg(feature = "mio")] fn stream_readable(&self, _io: &IoContext, _stream: StreamToken) {} /// Called when an IO stream can be written to + #[cfg(feature = "mio")] fn stream_writable(&self, _io: &IoContext, _stream: StreamToken) {} /// Register a new stream with the event loop + #[cfg(feature = "mio")] fn register_stream(&self, _stream: StreamToken, _reg: Token, _event_loop: &mut EventLoop>) {} /// Re-register a stream with the event loop + #[cfg(feature = "mio")] fn update_stream(&self, _stream: StreamToken, _reg: Token, _event_loop: &mut EventLoop>) {} /// Deregister a stream. Called whenstream is removed from event loop + #[cfg(feature = "mio")] fn deregister_stream(&self, _stream: StreamToken, _event_loop: &mut EventLoop>) {} } -pub use service::TimerToken; -pub use service::StreamToken; -pub use service::IoContext; -pub use service::IoService; -pub use service::IoChannel; -pub use service::IoManager; -pub use service::TOKENS_PER_HANDLER; +#[cfg(feature = "mio")] +pub use service_mio::{TimerToken, StreamToken, IoContext, IoService, IoChannel, IoManager, TOKENS_PER_HANDLER}; +#[cfg(not(feature = "mio"))] +pub use service_non_mio::{TimerToken, IoContext, IoService, IoChannel, TOKENS_PER_HANDLER}; #[cfg(test)] mod tests { - use std::sync::Arc; + use std::sync::atomic; + use std::thread; use std::time::Duration; use super::*; - struct MyHandler; + #[test] + fn send_message_to_handler() { + struct MyHandler(atomic::AtomicBool); - #[derive(Clone)] - struct MyMessage { - data: u32 - } + #[derive(Clone)] + struct MyMessage { + data: u32 + } - impl IoHandler for MyHandler { - fn initialize(&self, io: &IoContext) { - io.register_timer(0, Duration::from_secs(1)).unwrap(); + impl IoHandler for MyHandler { + fn message(&self, _io: &IoContext, message: &MyMessage) { + assert_eq!(message.data, 5); + self.0.store(true, atomic::Ordering::SeqCst); + } } - fn timeout(&self, _io: &IoContext, timer: TimerToken) { - println!("Timeout {}", timer); + let handler = Arc::new(MyHandler(atomic::AtomicBool::new(false))); + + let service = IoService::::start().expect("Error creating network service"); + service.register_handler(handler.clone()).unwrap(); + + service.send_message(MyMessage { data: 5 }).unwrap(); + + thread::sleep(Duration::from_secs(5)); + assert!(handler.0.load(atomic::Ordering::SeqCst)); + } + + #[test] + fn timeout_working() { + struct MyHandler(atomic::AtomicBool); + + #[derive(Clone)] + struct MyMessage { + data: u32 } - fn message(&self, _io: &IoContext, message: &MyMessage) { - println!("Message {}", message.data); + impl IoHandler for MyHandler { + fn initialize(&self, io: &IoContext) { + io.register_timer_once(1234, Duration::from_millis(500)).unwrap(); + } + + fn timeout(&self, _io: &IoContext, timer: TimerToken) { + assert_eq!(timer, 1234); + assert!(!self.0.swap(true, atomic::Ordering::SeqCst)); + } } + + let handler = Arc::new(MyHandler(atomic::AtomicBool::new(false))); + + let service = IoService::::start().expect("Error creating network service"); + service.register_handler(handler.clone()).unwrap(); + + thread::sleep(Duration::from_secs(2)); + assert!(handler.0.load(atomic::Ordering::SeqCst)); } #[test] - fn test_service_register_handler () { + fn multi_timeout_working() { + struct MyHandler(atomic::AtomicUsize); + + #[derive(Clone)] + struct MyMessage { + data: u32 + } + + impl IoHandler for MyHandler { + fn initialize(&self, io: &IoContext) { + io.register_timer(1234, Duration::from_millis(500)).unwrap(); + } + + fn timeout(&self, _io: &IoContext, timer: TimerToken) { + assert_eq!(timer, 1234); + self.0.fetch_add(1, atomic::Ordering::SeqCst); + } + } + + let handler = Arc::new(MyHandler(atomic::AtomicUsize::new(0))); + let service = IoService::::start().expect("Error creating network service"); - service.register_handler(Arc::new(MyHandler)).unwrap(); + service.register_handler(handler.clone()).unwrap(); + + thread::sleep(Duration::from_secs(2)); + assert!(handler.0.load(atomic::Ordering::SeqCst) >= 2); } } diff --git a/util/io/src/service.rs b/util/io/src/service_mio.rs similarity index 97% rename from util/io/src/service.rs rename to util/io/src/service_mio.rs index 0de674ae121..f7c9f1976cf 100644 --- a/util/io/src/service.rs +++ b/util/io/src/service_mio.rs @@ -181,7 +181,7 @@ struct UserTimer { /// Root IO handler. Manages user handlers, messages and IO timers. pub struct IoManager where Message: Send + Sync { timers: Arc>>, - handlers: Arc>, HandlerId>>>, + handlers: Arc>>>>, workers: Vec, worker_channel: chase_lev::Worker>, work_ready: Arc, @@ -191,7 +191,7 @@ impl IoManager where Message: Send + Sync + 'static { /// Creates a new instance and registers it with the event loop. pub fn start( event_loop: &mut EventLoop>, - handlers: Arc>, HandlerId>>> + handlers: Arc>>>> ) -> Result<(), IoError> { let (worker, stealer) = chase_lev::deque(); let num_workers = 4; @@ -267,7 +267,8 @@ impl Handler for IoManager where Message: Send + Sync + 'stati event_loop.shutdown(); }, IoMessage::AddHandler { handler } => { - let handler_id = self.handlers.write().insert(handler.clone()).unwrap_or_else(|_| panic!("Too many handlers registered")); + let handler_id = self.handlers.write().insert(handler.clone()); + assert!(handler_id <= MAX_HANDLERS, "Too many handlers registered"); handler.initialize(&IoContext::new(IoChannel::new(event_loop.channel(), Arc::downgrade(&self.handlers)), handler_id)); }, IoMessage::RemoveHandler { handler_id } => { @@ -332,7 +333,7 @@ impl Handler for IoManager where Message: Send + Sync + 'stati } enum Handlers where Message: Send { - SharedCollection(Weak>, HandlerId>>>), + SharedCollection(Weak>>>>), Single(Weak>), } @@ -417,7 +418,7 @@ impl IoChannel where Message: Send + Sync + 'static { handlers: Handlers::Single(handler), } } - fn new(channel: Sender>, handlers: Weak>, HandlerId>>>) -> IoChannel { + fn new(channel: Sender>, handlers: Weak>>>>) -> IoChannel { IoChannel { channel: Some(channel), handlers: Handlers::SharedCollection(handlers), @@ -430,7 +431,7 @@ impl IoChannel where Message: Send + Sync + 'static { pub struct IoService where Message: Send + Sync + 'static { thread: Mutex>>, host_channel: Mutex>>, - handlers: Arc>, HandlerId>>>, + handlers: Arc>>>>, } impl IoService where Message: Send + Sync + 'static { @@ -440,7 +441,7 @@ impl IoService where Message: Send + Sync + 'static { config.messages_per_tick(1024); let mut event_loop = config.build().expect("Error creating event loop"); let channel = event_loop.channel(); - let handlers = Arc::new(RwLock::new(Slab::new(MAX_HANDLERS))); + let handlers = Arc::new(RwLock::new(Slab::with_capacity(MAX_HANDLERS))); let h = handlers.clone(); let thread = thread::spawn(move || { IoManager::::start(&mut event_loop, h).expect("Error starting IO service"); @@ -491,4 +492,3 @@ impl Drop for IoService where Message: Send + Sync { self.stop() } } - diff --git a/util/io/src/service_non_mio.rs b/util/io/src/service_non_mio.rs new file mode 100644 index 00000000000..22a795e4e8d --- /dev/null +++ b/util/io/src/service_non_mio.rs @@ -0,0 +1,334 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use std::sync::{Arc, Weak}; +use std::thread; +use crossbeam::sync::chase_lev; +use slab::Slab; +use fnv::FnvHashMap; +use {IoError, IoHandler}; +use parking_lot::{RwLock, Mutex}; +use num_cpus; +use std::time::Duration; +use timer::{Timer, Guard as TimerGuard}; +use time::Duration as TimeDuration; + +/// Timer ID +pub type TimerToken = usize; +/// IO Handler ID +pub type HandlerId = usize; + +/// Maximum number of tokens a handler can use +pub const TOKENS_PER_HANDLER: usize = 16384; +const MAX_HANDLERS: usize = 8; + +/// IO access point. This is passed to all IO handlers and provides an interface to the IO subsystem. +pub struct IoContext where Message: Send + Sync + 'static { + handler: HandlerId, + shared: Arc>, +} + +impl IoContext where Message: Send + Sync + 'static { + /// Register a new recurring IO timer. 'IoHandler::timeout' will be called with the token. + pub fn register_timer(&self, token: TimerToken, delay: Duration) -> Result<(), IoError> { + let channel = self.channel(); + + let msg = WorkTask::TimerTrigger { + handler_id: self.handler, + token: token, + }; + + let delay = TimeDuration::from_std(delay) + .map_err(|e| ::std::io::Error::new(::std::io::ErrorKind::Other, e))?; + let guard = self.shared.timer.lock().schedule_repeating(delay, move || { + channel.send_raw(msg.clone()); + }); + + self.shared.timers.lock().insert(token, guard); + + Ok(()) + } + + /// Register a new IO timer once. 'IoHandler::timeout' will be called with the token. + pub fn register_timer_once(&self, token: TimerToken, delay: Duration) -> Result<(), IoError> { + let channel = self.channel(); + + let msg = WorkTask::TimerTrigger { + handler_id: self.handler, + token: token, + }; + + let delay = TimeDuration::from_std(delay) + .map_err(|e| ::std::io::Error::new(::std::io::ErrorKind::Other, e))?; + let guard = self.shared.timer.lock().schedule_with_delay(delay, move || { + channel.send_raw(msg.clone()); + }); + + self.shared.timers.lock().insert(token, guard); + + Ok(()) + } + + /// Delete a timer. + pub fn clear_timer(&self, token: TimerToken) -> Result<(), IoError> { + self.shared.timers.lock().remove(&token); + Ok(()) + } + + /// Broadcast a message to other IO clients + pub fn message(&self, message: Message) -> Result<(), IoError> { + if let Some(ref channel) = *self.shared.channel.lock() { + channel.push(WorkTask::UserMessage(Arc::new(message))); + } + for thread in self.shared.threads.read().iter() { + thread.unpark(); + } + + Ok(()) + } + + /// Get message channel + pub fn channel(&self) -> IoChannel { + IoChannel { shared: Arc::downgrade(&self.shared) } + } + + /// Unregister current IO handler. + pub fn unregister_handler(&self) -> Result<(), IoError> { + self.shared.handlers.write().remove(self.handler); + Ok(()) + } +} + +/// Allows sending messages into the event loop. All the IO handlers will get the message +/// in the `message` callback. +pub struct IoChannel where Message: Send + Sync + 'static { + shared: Weak>, +} + +impl Clone for IoChannel where Message: Send + Sync + 'static { + fn clone(&self) -> IoChannel { + IoChannel { + shared: self.shared.clone(), + } + } +} + +impl IoChannel where Message: Send + Sync + 'static { + /// Send a message through the channel + pub fn send(&self, message: Message) -> Result<(), IoError> { + if let Some(shared) = self.shared.upgrade() { + match *shared.channel.lock() { + Some(ref channel) => channel.push(WorkTask::UserMessage(Arc::new(message))), + None => self.send_sync(message)? + }; + + for thread in shared.threads.read().iter() { + thread.unpark(); + } + } + + Ok(()) + } + + /// Send a message through the channel and handle it synchronously + pub fn send_sync(&self, message: Message) -> Result<(), IoError> { + if let Some(shared) = self.shared.upgrade() { + for id in 0 .. MAX_HANDLERS { + if let Some(h) = shared.handlers.read().get(id) { + let handler = h.clone(); + let ctxt = IoContext { handler: id, shared: shared.clone() }; + handler.message(&ctxt, &message); + } + } + } + + Ok(()) + } + + // Send low level io message + fn send_raw(&self, message: WorkTask) { + if let Some(shared) = self.shared.upgrade() { + if let Some(ref channel) = *shared.channel.lock() { + channel.push(message); + } + + for thread in shared.threads.read().iter() { + thread.unpark(); + } + } + } + + /// Create a new channel disconnected from an event loop. + pub fn disconnected() -> IoChannel { + IoChannel { + shared: Weak::default(), + } + } +} + +/// General IO Service. Starts an event loop and dispatches IO requests. +/// 'Message' is a notification message type +pub struct IoService where Message: Send + Sync + 'static { + thread_joins: Mutex>>, + shared: Arc>, +} + +// Struct shared throughout the whole implementation. +struct Shared where Message: Send + Sync + 'static { + // All the I/O handlers that have been registered. + handlers: RwLock>>>, + // All the background threads, so that we can unpark them. + threads: RwLock>, + // Used to create timeouts. + timer: Mutex, + // List of created timers. We need to keep them in a data struct so that we can cancel them if + // necessary. + timers: Mutex>, + // Channel used to send work to the worker threads. + channel: Mutex>>>, +} + +// Messages used to communicate with the event loop from other threads. +enum WorkTask where Message: Send + Sized { + Shutdown, + TimerTrigger { + handler_id: HandlerId, + token: TimerToken, + }, + UserMessage(Arc) +} + +impl Clone for WorkTask where Message: Send + Sized { + fn clone(&self) -> WorkTask { + match *self { + WorkTask::Shutdown => WorkTask::Shutdown, + WorkTask::TimerTrigger { handler_id, token } => WorkTask::TimerTrigger { handler_id, token }, + WorkTask::UserMessage(ref msg) => WorkTask::UserMessage(msg.clone()), + } + } +} + +impl IoService where Message: Send + Sync + 'static { + /// Starts IO event loop + pub fn start() -> Result, IoError> { + let (tx, rx) = chase_lev::deque(); + + let shared = Arc::new(Shared { + handlers: RwLock::new(Slab::with_capacity(MAX_HANDLERS)), + threads: RwLock::new(Vec::new()), + timer: Mutex::new(Timer::new()), + timers: Mutex::new(FnvHashMap::default()), + channel: Mutex::new(Some(tx)), + }); + + let thread_joins = (0 .. num_cpus::get()).map(|_| { + let rx = rx.clone(); + let shared = shared.clone(); + thread::spawn(move || { + do_work(&shared, rx) + }) + }).collect::>(); + + *shared.threads.write() = thread_joins.iter().map(|t| t.thread().clone()).collect(); + + Ok(IoService { + thread_joins: Mutex::new(thread_joins), + shared, + }) + } + + /// Stops the IO service. + pub fn stop(&self) { + trace!(target: "shutdown", "[IoService] Closing..."); + // Clear handlers so that shared pointers are not stuck on stack + // in Channel::send_sync + self.shared.handlers.write().clear(); + let channel = self.shared.channel.lock().take(); + let mut thread_joins = self.thread_joins.lock(); + if let Some(channel) = channel { + for _ in 0 .. thread_joins.len() { + channel.push(WorkTask::Shutdown); + } + } + for thread in thread_joins.drain(..) { + thread.thread().unpark(); + thread.join().unwrap_or_else(|e| { + debug!(target: "shutdown", "Error joining IO service worker thread: {:?}", e); + }); + } + trace!(target: "shutdown", "[IoService] Closed."); + } + + /// Register an IO handler with the event loop. + pub fn register_handler(&self, handler: Arc+Send>) -> Result<(), IoError> { + let id = self.shared.handlers.write().insert(handler.clone()); + assert!(id <= MAX_HANDLERS, "Too many handlers registered"); + let ctxt = IoContext { handler: id, shared: self.shared.clone() }; + handler.initialize(&ctxt); + Ok(()) + } + + /// Send a message over the network. Normaly `HostIo::send` should be used. This can be used from non-io threads. + pub fn send_message(&self, message: Message) -> Result<(), IoError> { + if let Some(ref channel) = *self.shared.channel.lock() { + channel.push(WorkTask::UserMessage(Arc::new(message))); + } + for thread in self.shared.threads.read().iter() { + thread.unpark(); + } + Ok(()) + } + + /// Create a new message channel + #[inline] + pub fn channel(&self) -> IoChannel { + IoChannel { + shared: Arc::downgrade(&self.shared) + } + } +} + +impl Drop for IoService where Message: Send + Sync { + fn drop(&mut self) { + self.stop() + } +} + +fn do_work(shared: &Arc>, rx: chase_lev::Stealer>) + where Message: Send + Sync + 'static +{ + loop { + match rx.steal() { + chase_lev::Steal::Abort => continue, + chase_lev::Steal::Empty => thread::park(), + chase_lev::Steal::Data(WorkTask::Shutdown) => break, + chase_lev::Steal::Data(WorkTask::UserMessage(message)) => { + for id in 0 .. MAX_HANDLERS { + if let Some(handler) = shared.handlers.read().get(id) { + let ctxt = IoContext { handler: id, shared: shared.clone() }; + handler.message(&ctxt, &message); + } + } + }, + chase_lev::Steal::Data(WorkTask::TimerTrigger { handler_id, token }) => { + if let Some(handler) = shared.handlers.read().get(handler_id) { + let ctxt = IoContext { handler: handler_id, shared: shared.clone() }; + handler.timeout(&ctxt, token); + } + }, + } + } +} diff --git a/util/io/src/worker.rs b/util/io/src/worker.rs index 0f0d448ecb4..89657810dcf 100644 --- a/util/io/src/worker.rs +++ b/util/io/src/worker.rs @@ -18,21 +18,14 @@ use std::sync::Arc; use std::thread::{JoinHandle, self}; use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; use crossbeam::sync::chase_lev; -use service::{HandlerId, IoChannel, IoContext}; +use service_mio::{HandlerId, IoChannel, IoContext}; use IoHandler; -use std::cell::Cell; +use LOCAL_STACK_SIZE; use std::sync::{Condvar as SCondvar, Mutex as SMutex}; const STACK_SIZE: usize = 16*1024*1024; -thread_local! { - /// Stack size - /// Should be modified if it is changed in Rust since it is no way - /// to know or get it - pub static LOCAL_STACK_SIZE: Cell = Cell::new(::std::env::var("RUST_MIN_STACK").ok().and_then(|s| s.parse().ok()).unwrap_or(2 * 1024 * 1024)); -} - pub enum WorkType { Readable, Writable, diff --git a/util/network-devp2p/Cargo.toml b/util/network-devp2p/Cargo.toml index 3ec96843931..f4889fe26d4 100644 --- a/util/network-devp2p/Cargo.toml +++ b/util/network-devp2p/Cargo.toml @@ -19,7 +19,7 @@ libc = "0.2.7" parking_lot = "0.5" ansi_term = "0.10" rustc-hex = "1.0" -ethcore-io = { path = "../io" } +ethcore-io = { path = "../io", features = ["mio"] } ethcore-bytes = { path = "../bytes" } ethcore-crypto = { path = "../../ethcore/crypto" } ethcore-logger = { path ="../../logger" } From aea26dcc640696a712befd5339ab3186bcc3426b Mon Sep 17 00:00:00 2001 From: Thibaut S <33178835+Tbaut@users.noreply.github.com> Date: Fri, 11 May 2018 08:04:04 +0100 Subject: [PATCH 58/95] Fix Parity UI link (#8600) Fix link https://github.com/paritytech/parity/issues/8599 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 36e855fe420..9255d014b6c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Official website: https://parity.io | Be sure to check out [our wiki](https://wi Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs. -From Parity Ethereum client version 1.10.0, the User Interface (UI) is accessible in a separate application called Parity UI. To keep using the UI in the browser (deprecated), [follow these steps](https://wiki.parity.io/FAQ-Basic-Operations,-Configuration,-and-Synchronization.md#the-parity-ui-application-isnt-working-the-way-i-want). +From Parity Ethereum client version 1.10.0, the User Interface (UI) is accessible in a separate application called Parity UI. To keep using the UI in the browser (deprecated), [follow these steps](https://wiki.parity.io/FAQ-Basic-Operations,-Configuration,-and-Synchronization#the-parity-ui-application-isnt-working-the-way-i-want). By default, Parity will also run a JSONRPC server on `127.0.0.1:8545` and a websockets server on `127.0.0.1:8546`. This is fully configurable and supports a number of APIs. From ecd7caa93d803d1f07b4f6888e5f13de6d189fb8 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Fri, 11 May 2018 11:23:19 +0200 Subject: [PATCH 59/95] fix compiler warning (#8590) --- ethcore/sync/src/light_sync/response.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/sync/src/light_sync/response.rs b/ethcore/sync/src/light_sync/response.rs index 74665118b7f..3629613224d 100644 --- a/ethcore/sync/src/light_sync/response.rs +++ b/ethcore/sync/src/light_sync/response.rs @@ -16,7 +16,7 @@ //! Helpers for decoding and verifying responses for headers. -use ethcore::{self, encoded, header::Header}; +use ethcore::{encoded, header::Header}; use ethereum_types::H256; use light::request::{HashOrNumber, CompleteHeadersRequest as HeadersRequest}; use rlp::DecoderError; From 61ec02248aa4acb21ff35999dd2c8945478eeb32 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 11 May 2018 11:33:13 +0200 Subject: [PATCH 60/95] Block::decode() returns Result (#8586) --- ethcore/src/encoded.rs | 2 +- ethcore/src/snapshot/consensus/authority.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/src/encoded.rs b/ethcore/src/encoded.rs index c436607f8c3..5a2d376a2a3 100644 --- a/ethcore/src/encoded.rs +++ b/ethcore/src/encoded.rs @@ -206,7 +206,7 @@ impl Block { pub fn header_view(&self) -> HeaderView { self.view().header_view() } /// Decode to a full block. - pub fn decode(&self) -> FullBlock { ::rlp::decode(&self.0).expect("decoding failure") } + pub fn decode(&self) -> Result { rlp::decode(&self.0) } /// Decode the header. pub fn decode_header(&self) -> FullHeader { self.view().rlp().val_at(0) } diff --git a/ethcore/src/snapshot/consensus/authority.rs b/ethcore/src/snapshot/consensus/authority.rs index 474f5d350c1..38d2c184ca1 100644 --- a/ethcore/src/snapshot/consensus/authority.rs +++ b/ethcore/src/snapshot/consensus/authority.rs @@ -100,7 +100,7 @@ impl SnapshotComponents for PoaSnapshot { let (block, receipts) = chain.block(&block_at) .and_then(|b| chain.block_receipts(&block_at).map(|r| (b, r))) .ok_or(Error::BlockNotFound(block_at))?; - let block = block.decode(); + let block = block.decode()?; let parent_td = chain.block_details(block.header.parent_hash()) .map(|d| d.total_difficulty) From 25dc1c2155c8e84f2263e46b830f24f51a6e5195 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 11 May 2018 11:34:07 +0200 Subject: [PATCH 61/95] block_header can fail so return Result (#8581) * block_header can fail so return Result * Restore previous return type based on feedback * Fix failing doc tests running on non-code --- rpc/src/v1/impls/light/parity.rs | 9 ++++----- util/journaldb/src/earlymergedb.rs | 6 +++--- util/journaldb/src/refcounteddb.rs | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 982c7ff3633..025538fc427 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -395,9 +395,9 @@ impl Parity for ParityClient { let engine = self.light_dispatch.client.engine().clone(); let from_encoded = move |encoded: encoded::Header| { - let header = encoded.decode().expect("decoding error"); // REVIEW: not sure what to do here; what is a decent return value for the error case here? + let header = encoded.decode().map_err(errors::decode)?; let extra_info = engine.extra_info(&header); - RichHeader { + Ok(RichHeader { inner: Header { hash: Some(header.hash().into()), size: Some(encoded.rlp().as_raw().len().into()), @@ -418,9 +418,8 @@ impl Parity for ParityClient { extra_data: Bytes::new(header.extra_data().clone()), }, extra_info: extra_info, - } + }) }; - // Note: Here we treat `Pending` as `Latest`. // Since light clients don't produce pending blocks // (they don't have state) we can safely fallback to `Latest`. @@ -430,7 +429,7 @@ impl Parity for ParityClient { BlockNumber::Latest | BlockNumber::Pending => BlockId::Latest, }; - Box::new(self.fetcher().header(id).map(from_encoded)) + Box::new(self.fetcher().header(id).and_then(from_encoded)) } fn ipfs_cid(&self, content: Bytes) -> Result { diff --git a/util/journaldb/src/earlymergedb.rs b/util/journaldb/src/earlymergedb.rs index e76cdcd313a..c26a67e0ad2 100644 --- a/util/journaldb/src/earlymergedb.rs +++ b/util/journaldb/src/earlymergedb.rs @@ -57,7 +57,7 @@ enum RemoveFrom { /// the removals actually take effect. /// /// journal format: -/// ``` +/// ```text /// [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ] /// [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ] /// [era, n] => [ ... ] @@ -76,7 +76,7 @@ enum RemoveFrom { /// which includes an original key, if any. /// /// The semantics of the `counter` are: -/// ``` +/// ```text /// insert key k: /// counter already contains k: count += 1 /// counter doesn't contain k: @@ -92,7 +92,7 @@ enum RemoveFrom { /// /// Practically, this means that for each commit block turning from recent to ancient we do the /// following: -/// ``` +/// ```text /// is_canonical: /// inserts: Ignored (left alone in the backing database). /// deletes: Enacted; however, recent history queue is checked for ongoing references. This is diff --git a/util/journaldb/src/refcounteddb.rs b/util/journaldb/src/refcounteddb.rs index 944d81d3733..d182d5cf803 100644 --- a/util/journaldb/src/refcounteddb.rs +++ b/util/journaldb/src/refcounteddb.rs @@ -40,7 +40,7 @@ use util::{DatabaseKey, DatabaseValueView, DatabaseValueRef}; /// the removals actually take effect. /// /// journal format: -/// ``` +/// ```text /// [era, 0] => [ id, [insert_0, ...], [remove_0, ...] ] /// [era, 1] => [ id, [insert_0, ...], [remove_0, ...] ] /// [era, n] => [ ... ] From 1fa95ac236ab280afc9eccb4d6ea51b494f11422 Mon Sep 17 00:00:00 2001 From: Axel Chalon Date: Fri, 11 May 2018 12:09:42 +0200 Subject: [PATCH 62/95] Remove inject.js server-side injection for dapps (#8539) * Remove inject.js server-side injection for dapps * Remove dapps test `should_inject_js` Parity doesn't inject a "#, - apps::UTILS_PATH, - ); - - content.as_bytes().to_vec() - } else { - Vec::new() - }; - - let (reader, body) = Reader::pair(file.into_reader(), initial_content); + let (reader, body) = Reader::pair(file.into_reader(), Vec::new()); res.set_body(body); (Some(reader), res) } diff --git a/dapps/src/tests/home.rs b/dapps/src/tests/home.rs index 0ee06536482..fa5c5b4c465 100644 --- a/dapps/src/tests/home.rs +++ b/dapps/src/tests/home.rs @@ -60,32 +60,3 @@ fn should_serve_home() { response.assert_header("Content-Type", "text/html"); assert_security_headers(&response.headers); } - - -#[test] -fn should_inject_js() { - // given - let server = serve_ui(); - - // when - let response = request(server, - "\ - GET / HTTP/1.1\r\n\ - Host: 127.0.0.1:8080\r\n\ - Connection: close\r\n\ - \r\n\ - {} - " - ); - - // then - response.assert_status("HTTP/1.1 200 OK"); - response.assert_header("Content-Type", "text/html"); - assert_eq!( - response.body.contains(r#"/inject.js">"#), - true, - "Expected inject script tag in: {}", - response.body - ); - assert_security_headers(&response.headers); -} From 57d1f2b4d35d79a69aabe4d4460463a8e2569ad3 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 11 May 2018 13:45:07 +0200 Subject: [PATCH 63/95] Fix the mio test again (#8602) --- util/io/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/util/io/src/lib.rs b/util/io/src/lib.rs index ef8c3adc7ec..cd635121fff 100644 --- a/util/io/src/lib.rs +++ b/util/io/src/lib.rs @@ -186,7 +186,12 @@ mod tests { use std::time::Duration; use super::*; + // Mio's behaviour is too unstable for this test. Sometimes we have to wait a few milliseconds, + // sometimes more than 5 seconds for the message to arrive. + // Therefore we ignore this test in order to not have spurious failure when running continuous + // integration. #[test] + #[cfg_attr(feature = "mio", ignore)] fn send_message_to_handler() { struct MyHandler(atomic::AtomicBool); @@ -209,7 +214,7 @@ mod tests { service.send_message(MyMessage { data: 5 }).unwrap(); - thread::sleep(Duration::from_secs(5)); + thread::sleep(Duration::from_secs(1)); assert!(handler.0.load(atomic::Ordering::SeqCst)); } From 979af3d3143a4219f8d7428f969d7c1b221d0133 Mon Sep 17 00:00:00 2001 From: lihuafeng <31607114+EighteenZi@users.noreply.github.com> Date: Sun, 13 May 2018 04:46:08 +0800 Subject: [PATCH 64/95] 2 tiny modification on snapshot (#8601) * Some tiny modifications. 1. fix some typo in the comment. 2. sort the order of methods in 'impl state::Backend for StateDB` * Remove the clone of code_cache, as it has been done in clone_basic. * remove From::from. It seems not necessary. * change mode: remove rust files' executable mode. * 2 tiny modifications on snapshot. --- ethcore/src/snapshot/consensus/work.rs | 2 +- ethcore/src/snapshot/service.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/src/snapshot/consensus/work.rs b/ethcore/src/snapshot/consensus/work.rs index 5414ed59634..b71f7b9d1da 100644 --- a/ethcore/src/snapshot/consensus/work.rs +++ b/ethcore/src/snapshot/consensus/work.rs @@ -229,7 +229,7 @@ impl Rebuilder for PowRebuilder { let item_count = rlp.item_count()?; let num_blocks = (item_count - 3) as u64; - trace!(target: "snapshot", "restoring block chunk with {} blocks.", item_count - 3); + trace!(target: "snapshot", "restoring block chunk with {} blocks.", num_blocks); if self.fed_blocks + num_blocks > self.snapshot_blocks { return Err(Error::TooManyBlocks(self.snapshot_blocks, self.fed_blocks + num_blocks).into()) diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index 9cfb2eb63f4..c5b9123e10f 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -176,7 +176,7 @@ impl Restoration { // verify final state root. let root = self.state.state_root(); if root != self.final_state_root { - warn!("Final restored state has wrong state root: expected {:?}, got {:?}", root, self.final_state_root); + warn!("Final restored state has wrong state root: expected {:?}, got {:?}", self.final_state_root, root); return Err(TrieError::InvalidStateRoot(root).into()); } From 981554cf74980c9470abf23039ad39e75246eef8 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 14 May 2018 15:22:59 +0800 Subject: [PATCH 65/95] Use full qualified syntax for itertools::Itertools::flatten (#8606) --- ethstore/src/accounts_dir/memory.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethstore/src/accounts_dir/memory.rs b/ethstore/src/accounts_dir/memory.rs index bd162b5ef0c..5cfdba0e5c7 100644 --- a/ethstore/src/accounts_dir/memory.rs +++ b/ethstore/src/accounts_dir/memory.rs @@ -16,7 +16,7 @@ use std::collections::HashMap; use parking_lot::RwLock; -use itertools::Itertools; +use itertools; use ethkey::Address; use {SafeAccount, Error}; @@ -30,7 +30,7 @@ pub struct MemoryDirectory { impl KeyDirectory for MemoryDirectory { fn load(&self) -> Result, Error> { - Ok(self.accounts.read().values().cloned().flatten().collect()) + Ok(itertools::Itertools::flatten(self.accounts.read().values().cloned()).collect()) } fn update(&self, account: SafeAccount) -> Result { From 08abf67a5118ad7846eb0a438cca5b0d54fb9666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 14 May 2018 10:09:05 +0200 Subject: [PATCH 66/95] Fix packet count when talking with PAR2 peers (#8555) * Support diferent packet counts in different protocol versions. * Fix light timeouts and eclipse protection. * Fix devp2p tests. * Fix whisper-cli compilation. * Fix compilation. * Fix ethcore-sync tests. * Revert "Fix light timeouts and eclipse protection." This reverts commit 06285ea8c1d9d184d809f64b5507aece633da6cc. * Increase timeouts. --- ethcore/light/src/net/mod.rs | 17 ++++++++++------- ethcore/sync/src/api.rs | 17 +++++++---------- ethcore/sync/src/chain/handler.rs | 8 +++++--- ethcore/sync/src/chain/mod.rs | 24 ++++++++++-------------- ethcore/sync/src/chain/requester.rs | 5 +++-- ethcore/sync/src/tests/helpers.rs | 4 ++-- parity/whisper.rs | 2 -- util/network-devp2p/src/host.rs | 13 +++++++++---- util/network-devp2p/src/lib.rs | 2 +- util/network-devp2p/src/service.rs | 13 +++++++++---- util/network-devp2p/tests/tests.rs | 4 ++-- util/network/src/lib.rs | 6 ++---- whisper/cli/src/main.rs | 4 ++-- whisper/src/net/mod.rs | 10 ++++++---- 14 files changed, 68 insertions(+), 61 deletions(-) diff --git a/ethcore/light/src/net/mod.rs b/ethcore/light/src/net/mod.rs index d58d90fac45..27d5c12a5fa 100644 --- a/ethcore/light/src/net/mod.rs +++ b/ethcore/light/src/net/mod.rs @@ -75,14 +75,17 @@ const RECALCULATE_COSTS_INTERVAL: Duration = Duration::from_secs(60 * 60); // minimum interval between updates. const UPDATE_INTERVAL: Duration = Duration::from_millis(5000); +/// Packet count for PIP. +const PACKET_COUNT_V1: u8 = 9; + /// Supported protocol versions. -pub const PROTOCOL_VERSIONS: &'static [u8] = &[1]; +pub const PROTOCOL_VERSIONS: &'static [(u8, u8)] = &[ + (1, PACKET_COUNT_V1), +]; /// Max protocol version. pub const MAX_PROTOCOL_VERSION: u8 = 1; -/// Packet count for PIP. -pub const PACKET_COUNT: u8 = 9; // packet ID definitions. mod packet { @@ -111,9 +114,9 @@ mod packet { mod timeout { use std::time::Duration; - pub const HANDSHAKE: Duration = Duration::from_millis(2500); - pub const ACKNOWLEDGE_UPDATE: Duration = Duration::from_millis(5000); - pub const BASE: u64 = 1500; // base timeout for packet. + pub const HANDSHAKE: Duration = Duration::from_millis(4_000); + pub const ACKNOWLEDGE_UPDATE: Duration = Duration::from_millis(5_000); + pub const BASE: u64 = 2_500; // base timeout for packet. // timeouts per request within packet. pub const HEADERS: u64 = 250; // per header? @@ -688,7 +691,7 @@ impl LightProtocol { Err(e) => { punish(*peer, io, e); return } }; - if PROTOCOL_VERSIONS.iter().find(|x| **x == proto_version).is_none() { + if PROTOCOL_VERSIONS.iter().find(|x| x.0 == proto_version).is_none() { punish(*peer, io, Error::UnsupportedProtocolVersion(proto_version)); return; } diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index 4fd0cbb54dd..e901528e411 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -33,7 +33,7 @@ use chain::{ChainSync, SyncStatus as EthSyncStatus}; use std::net::{SocketAddr, AddrParseError}; use std::str::FromStr; use parking_lot::RwLock; -use chain::{ETH_PACKET_COUNT, SNAPSHOT_SYNC_PACKET_COUNT, ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_62, +use chain::{ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_62, PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, PAR_PROTOCOL_VERSION_3}; use light::client::AsLightClient; use light::Provider; @@ -202,10 +202,8 @@ pub struct AttachedProtocol { pub handler: Arc, /// 3-character ID for the protocol. pub protocol_id: ProtocolId, - /// Packet count. - pub packet_count: u8, - /// Supported versions. - pub versions: &'static [u8], + /// Supported versions and their packet counts. + pub versions: &'static [(u8, u8)], } impl AttachedProtocol { @@ -213,7 +211,6 @@ impl AttachedProtocol { let res = network.register_protocol( self.handler.clone(), self.protocol_id, - self.packet_count, self.versions ); @@ -459,15 +456,15 @@ impl ChainNotify for EthSync { Err(err) => warn!("Error starting network: {}", err), _ => {}, } - self.network.register_protocol(self.eth_handler.clone(), self.subprotocol_name, ETH_PACKET_COUNT, &[ETH_PROTOCOL_VERSION_62, ETH_PROTOCOL_VERSION_63]) + self.network.register_protocol(self.eth_handler.clone(), self.subprotocol_name, &[ETH_PROTOCOL_VERSION_62, ETH_PROTOCOL_VERSION_63]) .unwrap_or_else(|e| warn!("Error registering ethereum protocol: {:?}", e)); // register the warp sync subprotocol - self.network.register_protocol(self.eth_handler.clone(), WARP_SYNC_PROTOCOL_ID, SNAPSHOT_SYNC_PACKET_COUNT, &[PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, PAR_PROTOCOL_VERSION_3]) + self.network.register_protocol(self.eth_handler.clone(), WARP_SYNC_PROTOCOL_ID, &[PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, PAR_PROTOCOL_VERSION_3]) .unwrap_or_else(|e| warn!("Error registering snapshot sync protocol: {:?}", e)); // register the light protocol. if let Some(light_proto) = self.light_proto.as_ref().map(|x| x.clone()) { - self.network.register_protocol(light_proto, self.light_subprotocol_name, ::light::net::PACKET_COUNT, ::light::net::PROTOCOL_VERSIONS) + self.network.register_protocol(light_proto, self.light_subprotocol_name, ::light::net::PROTOCOL_VERSIONS) .unwrap_or_else(|e| warn!("Error registering light client protocol: {:?}", e)); } @@ -827,7 +824,7 @@ impl ManageNetwork for LightSync { let light_proto = self.proto.clone(); - self.network.register_protocol(light_proto, self.subprotocol_name, ::light::net::PACKET_COUNT, ::light::net::PROTOCOL_VERSIONS) + self.network.register_protocol(light_proto, self.subprotocol_name, ::light::net::PROTOCOL_VERSIONS) .unwrap_or_else(|e| warn!("Error registering light client protocol: {:?}", e)); for proto in &self.attached_protos { proto.register(&self.network) } diff --git a/ethcore/sync/src/chain/handler.rs b/ethcore/sync/src/chain/handler.rs index 966b7ce20ad..a55c0319b37 100644 --- a/ethcore/sync/src/chain/handler.rs +++ b/ethcore/sync/src/chain/handler.rs @@ -45,7 +45,6 @@ use super::{ MAX_NEW_BLOCK_AGE, MAX_NEW_HASHES, PAR_PROTOCOL_VERSION_1, - PAR_PROTOCOL_VERSION_2, PAR_PROTOCOL_VERSION_3, BLOCK_BODIES_PACKET, BLOCK_HEADERS_PACKET, @@ -641,8 +640,11 @@ impl SyncHandler { trace!(target: "sync", "Peer {} network id mismatch (ours: {}, theirs: {})", peer_id, sync.network_id, peer.network_id); return Ok(()); } - if (warp_protocol && peer.protocol_version != PAR_PROTOCOL_VERSION_1 && peer.protocol_version != PAR_PROTOCOL_VERSION_2 && peer.protocol_version != PAR_PROTOCOL_VERSION_3) - || (!warp_protocol && peer.protocol_version != ETH_PROTOCOL_VERSION_63 && peer.protocol_version != ETH_PROTOCOL_VERSION_62) { + + if false + || (warp_protocol && (peer.protocol_version < PAR_PROTOCOL_VERSION_1.0 || peer.protocol_version > PAR_PROTOCOL_VERSION_3.0)) + || (!warp_protocol && (peer.protocol_version < ETH_PROTOCOL_VERSION_62.0 || peer.protocol_version > ETH_PROTOCOL_VERSION_63.0)) + { io.disable_peer(peer_id); trace!(target: "sync", "Peer {} unsupported eth protocol ({})", peer_id, peer.protocol_version); return Ok(()); diff --git a/ethcore/sync/src/chain/mod.rs b/ethcore/sync/src/chain/mod.rs index abab1da9413..381936949bd 100644 --- a/ethcore/sync/src/chain/mod.rs +++ b/ethcore/sync/src/chain/mod.rs @@ -127,15 +127,15 @@ known_heap_size!(0, PeerInfo); pub type PacketDecodeError = DecoderError; /// 63 version of Ethereum protocol. -pub const ETH_PROTOCOL_VERSION_63: u8 = 63; +pub const ETH_PROTOCOL_VERSION_63: (u8, u8) = (63, 0x11); /// 62 version of Ethereum protocol. -pub const ETH_PROTOCOL_VERSION_62: u8 = 62; -/// 1 version of Parity protocol. -pub const PAR_PROTOCOL_VERSION_1: u8 = 1; +pub const ETH_PROTOCOL_VERSION_62: (u8, u8) = (62, 0x11); +/// 1 version of Parity protocol and the packet count. +pub const PAR_PROTOCOL_VERSION_1: (u8, u8) = (1, 0x15); /// 2 version of Parity protocol (consensus messages added). -pub const PAR_PROTOCOL_VERSION_2: u8 = 2; +pub const PAR_PROTOCOL_VERSION_2: (u8, u8) = (2, 0x16); /// 3 version of Parity protocol (private transactions messages added). -pub const PAR_PROTOCOL_VERSION_3: u8 = 3; +pub const PAR_PROTOCOL_VERSION_3: (u8, u8) = (3, 0x18); pub const MAX_BODIES_TO_SEND: usize = 256; pub const MAX_HEADERS_TO_SEND: usize = 512; @@ -169,8 +169,6 @@ pub const NODE_DATA_PACKET: u8 = 0x0e; pub const GET_RECEIPTS_PACKET: u8 = 0x0f; pub const RECEIPTS_PACKET: u8 = 0x10; -pub const ETH_PACKET_COUNT: u8 = 0x11; - pub const GET_SNAPSHOT_MANIFEST_PACKET: u8 = 0x11; pub const SNAPSHOT_MANIFEST_PACKET: u8 = 0x12; pub const GET_SNAPSHOT_DATA_PACKET: u8 = 0x13; @@ -179,8 +177,6 @@ pub const CONSENSUS_DATA_PACKET: u8 = 0x15; const PRIVATE_TRANSACTION_PACKET: u8 = 0x16; const SIGNED_PRIVATE_TRANSACTION_PACKET: u8 = 0x17; -pub const SNAPSHOT_SYNC_PACKET_COUNT: u8 = 0x18; - const MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD: usize = 3; const WAIT_PEERS_TIMEOUT: Duration = Duration::from_secs(5); @@ -453,7 +449,7 @@ impl ChainSync { let last_imported_number = self.new_blocks.last_imported_block_number(); SyncStatus { state: self.state.clone(), - protocol_version: ETH_PROTOCOL_VERSION_63, + protocol_version: ETH_PROTOCOL_VERSION_63.0, network_id: self.network_id, start_block_number: self.starting_block, last_imported_block_number: Some(last_imported_number), @@ -855,7 +851,7 @@ impl ChainSync { fn send_status(&mut self, io: &mut SyncIo, peer: PeerId) -> Result<(), network::Error> { let warp_protocol_version = io.protocol_version(&WARP_SYNC_PROTOCOL_ID, peer); let warp_protocol = warp_protocol_version != 0; - let protocol = if warp_protocol { warp_protocol_version } else { ETH_PROTOCOL_VERSION_63 }; + let protocol = if warp_protocol { warp_protocol_version } else { ETH_PROTOCOL_VERSION_63.0 }; trace!(target: "sync", "Sending status to {}, protocol version {}", peer, protocol); let mut packet = RlpStream::new_list(if warp_protocol { 7 } else { 5 }); let chain = io.chain().chain_info(); @@ -1019,11 +1015,11 @@ impl ChainSync { } fn get_consensus_peers(&self) -> Vec { - self.peers.iter().filter_map(|(id, p)| if p.protocol_version >= PAR_PROTOCOL_VERSION_2 { Some(*id) } else { None }).collect() + self.peers.iter().filter_map(|(id, p)| if p.protocol_version >= PAR_PROTOCOL_VERSION_2.0 { Some(*id) } else { None }).collect() } fn get_private_transaction_peers(&self) -> Vec { - self.peers.iter().filter_map(|(id, p)| if p.protocol_version >= PAR_PROTOCOL_VERSION_3 { Some(*id) } else { None }).collect() + self.peers.iter().filter_map(|(id, p)| if p.protocol_version >= PAR_PROTOCOL_VERSION_3.0 { Some(*id) } else { None }).collect() } /// Maintain other peers. Send out any new blocks and transactions diff --git a/ethcore/sync/src/chain/requester.rs b/ethcore/sync/src/chain/requester.rs index e6acf6bc53a..a85874d2927 100644 --- a/ethcore/sync/src/chain/requester.rs +++ b/ethcore/sync/src/chain/requester.rs @@ -28,7 +28,7 @@ use super::{ BlockSet, ChainSync, PeerAsking, - ETH_PACKET_COUNT, + ETH_PROTOCOL_VERSION_63, GET_BLOCK_BODIES_PACKET, GET_BLOCK_HEADERS_PACKET, GET_RECEIPTS_PACKET, @@ -140,7 +140,8 @@ impl SyncRequester { } peer.asking = asking; peer.ask_time = Instant::now(); - let result = if packet_id >= ETH_PACKET_COUNT { + // TODO [ToDr] This seems quite fragile. Be careful when protocol is updated. + let result = if packet_id >= ETH_PROTOCOL_VERSION_63.1 { io.send_protocol(WARP_SYNC_PROTOCOL_ID, peer_id, packet_id, packet) } else { io.send(peer_id, packet_id, packet) diff --git a/ethcore/sync/src/tests/helpers.rs b/ethcore/sync/src/tests/helpers.rs index 3a4697cc093..407f699e0e6 100644 --- a/ethcore/sync/src/tests/helpers.rs +++ b/ethcore/sync/src/tests/helpers.rs @@ -134,11 +134,11 @@ impl<'p, C> SyncIo for TestIo<'p, C> where C: FlushingBlockChainClient, C: 'p { } fn eth_protocol_version(&self, _peer: PeerId) -> u8 { - ETH_PROTOCOL_VERSION_63 + ETH_PROTOCOL_VERSION_63.0 } fn protocol_version(&self, protocol: &ProtocolId, peer_id: PeerId) -> u8 { - if protocol == &WARP_SYNC_PROTOCOL_ID { PAR_PROTOCOL_VERSION_3 } else { self.eth_protocol_version(peer_id) } + if protocol == &WARP_SYNC_PROTOCOL_ID { PAR_PROTOCOL_VERSION_3.0 } else { self.eth_protocol_version(peer_id) } } fn chain_overlay(&self) -> &RwLock> { diff --git a/parity/whisper.rs b/parity/whisper.rs index c7acd8f9d6f..bb9aebf0b9b 100644 --- a/parity/whisper.rs +++ b/parity/whisper.rs @@ -89,7 +89,6 @@ pub fn setup(target_pool_size: usize, protos: &mut Vec) protos.push(AttachedProtocol { handler: net.clone() as Arc<_>, - packet_count: whisper_net::PACKET_COUNT, versions: whisper_net::SUPPORTED_VERSIONS, protocol_id: whisper_net::PROTOCOL_ID, }); @@ -97,7 +96,6 @@ pub fn setup(target_pool_size: usize, protos: &mut Vec) // parity-only extensions to whisper. protos.push(AttachedProtocol { handler: Arc::new(whisper_net::ParityExtensions), - packet_count: whisper_net::PACKET_COUNT, versions: whisper_net::SUPPORTED_VERSIONS, protocol_id: whisper_net::PARITY_PROTOCOL_ID, }); diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index 2de9a1884c8..3c8643fe62d 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -79,7 +79,9 @@ const NODE_TABLE_TIMEOUT: Duration = Duration::from_secs(300); #[derive(Debug, PartialEq, Eq)] /// Protocol info pub struct CapabilityInfo { + /// Protocol ID pub protocol: ProtocolId, + /// Protocol version pub version: u8, /// Total number of packet IDs this protocol support. pub packet_count: u8, @@ -687,7 +689,7 @@ impl Host { Err(e) => { let s = session.lock(); trace!(target: "network", "Session read error: {}:{:?} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); - if let ErrorKind::Disconnect(DisconnectReason::UselessPeer) = *e.kind() { + if let ErrorKind::Disconnect(DisconnectReason::IncompatibleProtocol) = *e.kind() { if let Some(id) = s.id() { if !self.reserved_nodes.read().contains(id) { let mut nodes = self.nodes.write(); @@ -990,7 +992,6 @@ impl IoHandler for Host { ref handler, ref protocol, ref versions, - ref packet_count, } => { let h = handler.clone(); let reserved = self.reserved_nodes.read(); @@ -1000,8 +1001,12 @@ impl IoHandler for Host { ); self.handlers.write().insert(*protocol, h); let mut info = self.info.write(); - for v in versions { - info.capabilities.push(CapabilityInfo { protocol: *protocol, version: *v, packet_count: *packet_count }); + for &(version, packet_count) in versions { + info.capabilities.push(CapabilityInfo { + protocol: *protocol, + version, + packet_count, + }); } }, NetworkIoMessage::AddTimer { diff --git a/util/network-devp2p/src/lib.rs b/util/network-devp2p/src/lib.rs index 239763cbe18..e5bb95f2207 100644 --- a/util/network-devp2p/src/lib.rs +++ b/util/network-devp2p/src/lib.rs @@ -49,7 +49,7 @@ //! fn main () { //! let mut service = NetworkService::new(NetworkConfiguration::new_local(), None).expect("Error creating network service"); //! service.start().expect("Error starting service"); -//! service.register_protocol(Arc::new(MyHandler), *b"myp", 1, &[1u8]); +//! service.register_protocol(Arc::new(MyHandler), *b"myp", &[(1u8, 1u8)]); //! //! // Wait for quit condition //! // ... diff --git a/util/network-devp2p/src/service.rs b/util/network-devp2p/src/service.rs index 711ee95cf3b..10a1e9abc85 100644 --- a/util/network-devp2p/src/service.rs +++ b/util/network-devp2p/src/service.rs @@ -67,12 +67,17 @@ impl NetworkService { } /// Regiter a new protocol handler with the event loop. - pub fn register_protocol(&self, handler: Arc, protocol: ProtocolId, packet_count: u8, versions: &[u8]) -> Result<(), Error> { + pub fn register_protocol( + &self, + handler: Arc, + protocol: ProtocolId, + // version id + packet count + versions: &[(u8, u8)] + ) -> Result<(), Error> { self.io_service.send_message(NetworkIoMessage::AddHandler { - handler: handler, - protocol: protocol, + handler, + protocol, versions: versions.to_vec(), - packet_count: packet_count, })?; Ok(()) } diff --git a/util/network-devp2p/tests/tests.rs b/util/network-devp2p/tests/tests.rs index 4788e0d442a..e8c8eddde4b 100644 --- a/util/network-devp2p/tests/tests.rs +++ b/util/network-devp2p/tests/tests.rs @@ -52,7 +52,7 @@ impl TestProtocol { /// Creates and register protocol with the network service pub fn register(service: &mut NetworkService, drop_session: bool) -> Arc { let handler = Arc::new(TestProtocol::new(drop_session)); - service.register_protocol(handler.clone(), *b"tst", 1, &[42u8, 43u8]).expect("Error registering test protocol handler"); + service.register_protocol(handler.clone(), *b"tst", &[(42u8, 1u8), (43u8, 1u8)]).expect("Error registering test protocol handler"); handler } @@ -104,7 +104,7 @@ impl NetworkProtocolHandler for TestProtocol { fn net_service() { let service = NetworkService::new(NetworkConfiguration::new_local(), None).expect("Error creating network service"); service.start().unwrap(); - service.register_protocol(Arc::new(TestProtocol::new(false)), *b"myp", 1, &[1u8]).unwrap(); + service.register_protocol(Arc::new(TestProtocol::new(false)), *b"myp", &[(1u8, 1u8)]).unwrap(); } #[test] diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index 5077a953d48..673e4dab357 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -64,10 +64,8 @@ pub enum NetworkIoMessage { handler: Arc, /// Protocol Id. protocol: ProtocolId, - /// Supported protocol versions. - versions: Vec, - /// Number of packet IDs reserved by the protocol. - packet_count: u8, + /// Supported protocol versions and number of packet IDs reserved by the protocol (packet count). + versions: Vec<(u8, u8)>, }, /// Register a new protocol timer AddTimer { diff --git a/whisper/cli/src/main.rs b/whisper/cli/src/main.rs index f9211b993b4..c3a4dc8c3a2 100644 --- a/whisper/cli/src/main.rs +++ b/whisper/cli/src/main.rs @@ -218,10 +218,10 @@ fn execute(command: I) -> Result<(), Error> where I: IntoIterator, network.start()?; // Attach whisper protocol to the network service - network.register_protocol(whisper_network_handler.clone(), whisper::net::PROTOCOL_ID, whisper::net::PACKET_COUNT, + network.register_protocol(whisper_network_handler.clone(), whisper::net::PROTOCOL_ID, whisper::net::SUPPORTED_VERSIONS)?; network.register_protocol(Arc::new(whisper::net::ParityExtensions), whisper::net::PARITY_PROTOCOL_ID, - whisper::net::PACKET_COUNT, whisper::net::SUPPORTED_VERSIONS)?; + whisper::net::SUPPORTED_VERSIONS)?; // Request handler let mut io = MetaIoHandler::default(); diff --git a/whisper/src/net/mod.rs b/whisper/src/net/mod.rs index fc6138cf1dd..c462baa9d72 100644 --- a/whisper/src/net/mod.rs +++ b/whisper/src/net/mod.rs @@ -41,15 +41,17 @@ const RALLY_TIMEOUT: Duration = Duration::from_millis(2500); /// Current protocol version. pub const PROTOCOL_VERSION: usize = 6; +/// Number of packets. A bunch are reserved. +const PACKET_COUNT: u8 = 128; + /// Supported protocol versions. -pub const SUPPORTED_VERSIONS: &'static [u8] = &[PROTOCOL_VERSION as u8]; +pub const SUPPORTED_VERSIONS: &'static [(u8, u8)] = &[ + (PROTOCOL_VERSION as u8, PACKET_COUNT) +]; // maximum tolerated delay between messages packets. const MAX_TOLERATED_DELAY: Duration = Duration::from_millis(5000); -/// Number of packets. A bunch are reserved. -pub const PACKET_COUNT: u8 = 128; - /// Whisper protocol ID pub const PROTOCOL_ID: ::network::ProtocolId = *b"shh"; From cfd50538bb5daa2a1ca2e097f08a6c6ce73af65e Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 14 May 2018 16:10:11 +0800 Subject: [PATCH 67/95] typo: wrong indentation in kovan config (#8610) --- ethcore/res/ethereum/kovan.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index 1cd74d973c7..02d22bb4196 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -4,8 +4,8 @@ "engine": { "authorityRound": { "params": { - "stepDuration": "4", - "blockReward": "0x4563918244F40000", + "stepDuration": "4", + "blockReward": "0x4563918244F40000", "validators" : { "list": [ "0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED", From 272ebc1ef7ff2f6fab76d0e1999eebd899e23485 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 14 May 2018 16:10:28 +0800 Subject: [PATCH 68/95] Fix account list double 0x display (#8596) * Remove unused self import * Fix account list double 0x display --- parity/account.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parity/account.rs b/parity/account.rs index 3db1844a1b4..676cf93e735 100644 --- a/parity/account.rs +++ b/parity/account.rs @@ -94,7 +94,7 @@ fn new(n: NewAccount) -> Result { let secret_store = Box::new(secret_store(dir, Some(n.iterations))?); let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default()); let new_account = acc_provider.new_account(&password).map_err(|e| format!("Could not create new account: {}", e))?; - Ok(format!("0x{:?}", new_account)) + Ok(format!("0x{:x}", new_account)) } fn list(list_cmd: ListAccounts) -> Result { @@ -103,7 +103,7 @@ fn list(list_cmd: ListAccounts) -> Result { let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default()); let accounts = acc_provider.accounts().map_err(|e| format!("{}", e))?; let result = accounts.into_iter() - .map(|a| format!("0x{:?}", a)) + .map(|a| format!("0x{:x}", a)) .collect::>() .join("\n"); From 1b95af18ff4f5898786fcd044d3c42fe6f5fcd4a Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Mon, 14 May 2018 10:11:10 +0200 Subject: [PATCH 69/95] Remove manually added text to the errors (#8595) These messages were confusing for the users especially the help message. --- whisper/cli/src/main.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/whisper/cli/src/main.rs b/whisper/cli/src/main.rs index c3a4dc8c3a2..f245e99e482 100644 --- a/whisper/cli/src/main.rs +++ b/whisper/cli/src/main.rs @@ -170,12 +170,12 @@ impl From for Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { - Error::SockAddr(ref e) => write!(f, "SockAddrError: {}", e), - Error::Docopt(ref e) => write!(f, "DocoptError: {}", e), - Error::Io(ref e) => write!(f, "IoError: {}", e), - Error::JsonRpc(ref e) => write!(f, "JsonRpcError: {:?}", e), - Error::Network(ref e) => write!(f, "NetworkError: {}", e), - Error::Logger(ref e) => write!(f, "LoggerError: {}", e), + Error::SockAddr(ref e) => write!(f, "{}", e), + Error::Docopt(ref e) => write!(f, "{}", e), + Error::Io(ref e) => write!(f, "{}", e), + Error::JsonRpc(ref e) => write!(f, "{:?}", e), + Error::Network(ref e) => write!(f, "{}", e), + Error::Logger(ref e) => write!(f, "{}", e), } } } @@ -252,7 +252,6 @@ fn initialize_logger(log_level: String) -> Result<(), String> { Ok(()) } - #[cfg(test)] mod tests { use super::execute; From 938c3707fc63c5d37bb7a16a9f0c39742d841ad5 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Mon, 14 May 2018 11:28:41 +0200 Subject: [PATCH 70/95] Gitlab test script fixes (#8573) * Exclude /docs from modified files. * Ensure all references in the working tree are available * Remove duplicated line from test script --- scripts/gitlab-test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/gitlab-test.sh b/scripts/gitlab-test.sh index a617f68e227..57cf7c6b6c5 100755 --- a/scripts/gitlab-test.sh +++ b/scripts/gitlab-test.sh @@ -7,8 +7,8 @@ if [[ "$CI_COMMIT_REF_NAME" = "master" || "$CI_COMMIT_REF_NAME" = "beta" || "$CI else export GIT_COMPARE=master; fi -export RUST_FILES_MODIFIED="$(git --no-pager diff --name-only $GIT_COMPARE...$CI_COMMIT_SHA | grep -v -e ^\\. -e ^LICENSE -e ^README.md -e ^test.sh -e ^windows/ -e ^scripts/ -e ^mac/ -e ^nsis/ | wc -l)" -echo "RUST_FILES_MODIFIED: $RUST_FILES_MODIFIED" +git fetch -a +export RUST_FILES_MODIFIED="$(git --no-pager diff --name-only $GIT_COMPARE...$CI_COMMIT_SHA | grep -v -e ^\\. -e ^LICENSE -e ^README.md -e ^test.sh -e ^windows/ -e ^scripts/ -e ^mac/ -e ^nsis/ -e ^docs/ | wc -l)" echo "RUST_FILES_MODIFIED: $RUST_FILES_MODIFIED" TEST_SWITCH=$1 rust_test () { From af90fbfb3344fdc2447d97d4c48dcdfd69899a4f Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Mon, 14 May 2018 22:26:18 +0800 Subject: [PATCH 71/95] Fix BlockReward contract "arithmetic operation overflow" (#8611) * Fix BlockReward contract "arithmetic operation overflow" * Add docs on how execute_as_system works * Fix typo --- ethcore/src/machine.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index 4aa72b50d92..d0d434b1de0 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -122,7 +122,13 @@ impl EthereumMachine { } impl EthereumMachine { - /// Execute a call as the system address. + /// Execute a call as the system address. Block environment information passed to the + /// VM is modified to have its gas limit bounded at the upper limit of possible used + /// gases including this system call, capped at the maximum value able to be + /// represented by U256. This system call modifies the block state, but discards other + /// information. If suicides, logs or refunds happen within the system call, they + /// will not be executed or recorded. Gas used by this system call will not be counted + /// on the block. pub fn execute_as_system( &self, block: &mut ExecutedBlock, @@ -132,7 +138,7 @@ impl EthereumMachine { ) -> Result, Error> { let env_info = { let mut env_info = block.env_info(); - env_info.gas_limit = env_info.gas_used + gas; + env_info.gas_limit = env_info.gas_used.saturating_add(gas); env_info }; From 8f56606cac19d7a55735e214c8c96fc7cebb49f1 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Tue, 15 May 2018 07:46:37 +0200 Subject: [PATCH 72/95] =?UTF-8?q?=C2=B4main.rs=C2=B4=20typo=20(#8629)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Typo * Update main.rs --- parity/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/main.rs b/parity/main.rs index e489ad865e4..03b04a8c82f 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -71,7 +71,7 @@ fn take_spec_name_override() -> Option { #[cfg(windows)] fn global_cleanup() { - // We need to cleanup all sockets before spawning another Parity process. This makes shure everything is cleaned up. + // We need to cleanup all sockets before spawning another Parity process. This makes sure everything is cleaned up. // The loop is required because of internal reference counter for winsock dll. We don't know how many crates we use do // initialize it. There's at least 2 now. for _ in 0.. 10 { From e4614e49ae532bbef239f9eb3cf1741a2bdc7093 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 15 May 2018 12:57:32 +0200 Subject: [PATCH 73/95] Store morden db and keys in "path/to/parity/data/Morden" (ropsten uses "test", like before) (#8621) * Store morden db and keys in "path/to/parity/data/morden" (ropsten uses "test", like before) --- .gitignore | 2 +- ethcore/res/ethereum/morden.json | 2 +- util/dir/src/lib.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 0675bc41ebf..3bc041c9081 100644 --- a/.gitignore +++ b/.gitignore @@ -40,5 +40,5 @@ node_modules out/ .vscode - +rls/ /parity.* diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index 04c5a124441..bca9919903e 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -1,6 +1,6 @@ { "name": "Morden", - "dataDir": "test", + "dataDir": "morden", "engine": { "Ethash": { "params": { diff --git a/util/dir/src/lib.rs b/util/dir/src/lib.rs index b2ffed329c1..bb36a46a834 100644 --- a/util/dir/src/lib.rs +++ b/util/dir/src/lib.rs @@ -104,9 +104,9 @@ impl Directories { DatabaseDirectories { path: self.db.clone(), legacy_path: self.base.clone(), - genesis_hash: genesis_hash, - fork_name: fork_name, - spec_name: spec_name, + genesis_hash, + fork_name, + spec_name, } } From 0c4d2fbc703608c05b17b0bc5b97a38ea76e7525 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 15 May 2018 15:35:52 +0200 Subject: [PATCH 74/95] Fix light sync with initial validator-set contract (#8528) * Fix #8468 * Use U256::max_value() instead * Fix again * Also change initial transaction gas --- ethcore/src/spec/spec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index ef69f4847bc..1ee8cf70323 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -783,7 +783,7 @@ impl Spec { author: *genesis.author(), timestamp: genesis.timestamp(), difficulty: *genesis.difficulty(), - gas_limit: *genesis.gas_limit(), + gas_limit: U256::max_value(), last_hashes: Arc::new(Vec::new()), gas_used: 0.into(), }; @@ -792,7 +792,7 @@ impl Spec { let tx = Transaction { nonce: self.engine.account_start_nonce(0), action: Action::Call(a), - gas: U256::from(50_000_000), // TODO: share with client. + gas: U256::max_value(), gas_price: U256::default(), value: U256::default(), data: d, From 8e078b1d83bf708ef29bbbb166ab5c6edfdaa7b3 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 15 May 2018 17:03:09 +0200 Subject: [PATCH 75/95] Remove NetworkContext::io_channel() (#8625) * Remove io_channel() * Fix warning --- util/network-devp2p/src/host.rs | 4 ---- util/network/src/lib.rs | 8 -------- 2 files changed, 12 deletions(-) diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index 3c8643fe62d..4cca2e6e5a7 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -153,10 +153,6 @@ impl<'s> NetworkContextTrait for NetworkContext<'s> { self.session_id.map_or_else(|| Err(ErrorKind::Expired.into()), |id| self.send(id, packet_id, data)) } - fn io_channel(&self) -> IoChannel { - self.io.channel() - } - fn disable_peer(&self, peer: PeerId) { self.io.message(NetworkIoMessage::DisablePeer(peer)) .unwrap_or_else(|e| warn!("Error sending network IO message: {:?}", e)); diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index 673e4dab357..1327a9ad59f 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -39,7 +39,6 @@ use std::str::{self, FromStr}; use std::sync::Arc; use std::time::Duration; use ipnetwork::{IpNetwork, IpNetworkError}; -use io::IoChannel; use ethkey::Secret; use ethereum_types::{H256, H512}; use rlp::{Decodable, DecoderError, Rlp}; @@ -257,9 +256,6 @@ pub trait NetworkContext { /// Respond to a current network message. Panics if no there is no packet in the context. If the session is expired returns nothing. fn respond(&self, packet_id: PacketId, data: Vec) -> Result<(), Error>; - /// Get an IoChannel. - fn io_channel(&self) -> IoChannel; - /// Disconnect a peer and prevent it from connecting again. fn disable_peer(&self, peer: PeerId); @@ -298,10 +294,6 @@ impl<'a, T> NetworkContext for &'a T where T: ?Sized + NetworkContext { (**self).respond(packet_id, data) } - fn io_channel(&self) -> IoChannel { - (**self).io_channel() - } - fn disable_peer(&self, peer: PeerId) { (**self).disable_peer(peer) } From 3bb5ad7204dcdabf841910799814bccc5019729e Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 15 May 2018 23:11:14 +0200 Subject: [PATCH 76/95] Check that the Android build doesn't dep on c++_shared (#8538) --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 347b5a57ba4..95a7ebcb5e4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -190,7 +190,7 @@ android-armv7: - triggers script: - cargo build --target=armv7-linux-androideabi - # TODO: check that `arm-linux-androideabi-objdump -x ./target/armv7-linux-androideabi/release/parity | grep c++_shared` is empty + - if [ $(arm-linux-androideabi-objdump -x ./target/armv7-linux-androideabi/debug/parity | grep -i 'c++_shared' | wc -l) -ne 0]; then echo "FAIL!!" fi tags: - rust-arm artifacts: From 0ecbb3ec02a5b36c95f09a20d5958a374c32511f Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Wed, 16 May 2018 14:58:01 +0800 Subject: [PATCH 77/95] Fork choice and metadata framework for Engine (#8401) * Add light client TODO item * Move existing total-difficulty-based fork choice check to Engine * Abstract total difficulty and block provider as Machine::BlockMetadata and Machine::BlockProvider * Decouple "generate_metadata" logic to Engine * Use fixed BlockMetadata and BlockProvider type for null and instantseal In this way they can use total difficulty fork choice check * Extend blockdetails with metadatas and finalized info * Extra data update: mark_finalized and update_metadatas * Check finalized block in Blockchain * Fix a test constructor in verification mod * Add total difficulty trait * Fix type import * Db migration to V13 with metadata column * Address grumbles * metadatas -> metadata * Use generic type for update_metadata to avoid passing HashMap all around * Remove metadata in blockdetails * [WIP] Implement a generic metadata architecture * [WIP] Metadata insertion logic in BlockChain * typo: Value -> Self::Value * [WIP] Temporarily remove Engine::is_new_best interface So that we don't have too many type errors. * [WIP] Fix more type errors * [WIP] ExtendedHeader::PartialEq * [WIP] Change metadata type Option> to Vec * [WIP] Remove Metadata Error * [WIP] Clean up error conversion * [WIP] finalized -> is_finalized * [WIP] Mark all fields in ExtrasInsert as pub * [WIP] Remove unused import * [WIP] Keep only local metadata info * Mark metadata as optional * [WIP] Revert metadata db change in BlockChain * [WIP] Put finalization in unclosed state * Use metadata interface in BlockDetail * [WIP] Fix current build failures * [WIP] Remove unused blockmetadata struct * Remove DB migration info * [WIP] Typo * Use ExtendedHeader to implement fork choice check * Implement is_new_best using Ancestry iterator * Use expect instead of panic * [WIP] Add ancestry Engine support via on_new_block * Fix tests * Emission of ancestry actions * use_short_version should take account of metadata * Engine::is_new_best -> Engine::fork_choice * Use proper expect format as defined in #1026 * panic -> expect * ancestry_header -> ancestry_with_metadata * Boxed iterator -> &mut iterator * Fix tests * is_new_best -> primitive_fork_choice * Document how fork_choice works * Engine::fork_choice -> Engine::primitive_fork_choice * comment: clarify types of finalization where Engine::primitive_fork_choice works * Expose FinalizationInfo to Engine * Fix tests due to merging * Remove TotalDifficulty trait * Do not pass FinalizationInfo to Engine If there's finalized blocks in from route, choose the old branch without calling `Engine::fork_choice`. * Fix compile * Fix unused import * Remove is_to_route_finalized When no block reorg passes a finalized block, this variable is always false. * Address format grumbles * Fix docs: mark_finalized returns None if block hash is not found `blockchain` mod does not yet have an Error type, so we still temporarily use None here. * Fix inaccurate tree_route None expect description --- ethcore/light/src/client/header_chain.rs | 1 + ethcore/src/block.rs | 51 +++- ethcore/src/blockchain/blockchain.rs | 258 ++++++++++++++------ ethcore/src/blockchain/extras.rs | 54 +++- ethcore/src/blockchain/mod.rs | 1 + ethcore/src/blockchain/update.rs | 10 + ethcore/src/client/client.rs | 67 ++++- ethcore/src/client/test_client.rs | 4 +- ethcore/src/engines/authority_round/mod.rs | 33 ++- ethcore/src/engines/basic_authority.rs | 8 +- ethcore/src/engines/instant_seal.rs | 12 +- ethcore/src/engines/mod.rs | 31 ++- ethcore/src/engines/null_engine.rs | 11 +- ethcore/src/engines/tendermint/mod.rs | 10 +- ethcore/src/ethereum/ethash.rs | 20 +- ethcore/src/header.rs | 48 +++- ethcore/src/machine.rs | 4 +- ethcore/src/snapshot/tests/proof_of_work.rs | 8 +- ethcore/src/test_helpers.rs | 17 +- ethcore/src/tests/trace.rs | 5 +- ethcore/src/verification/verification.rs | 2 + ethcore/types/src/ancestry_action.rs | 27 ++ ethcore/types/src/lib.rs | 1 + ethcore/types/src/tree_route.rs | 2 + machine/src/lib.rs | 48 +++- 25 files changed, 592 insertions(+), 141 deletions(-) create mode 100644 ethcore/types/src/ancestry_action.rs diff --git a/ethcore/light/src/client/header_chain.rs b/ethcore/light/src/client/header_chain.rs index b85091e53bf..60c7d288a76 100644 --- a/ethcore/light/src/client/header_chain.rs +++ b/ethcore/light/src/client/header_chain.rs @@ -445,6 +445,7 @@ impl HeaderChain { let raw = header.encoded().into_inner(); transaction.put_vec(self.col, &hash[..], raw); + // TODO: For engines when required, use cryptoeconomic guarantees. let (best_num, is_new_best) = { let cur_best = self.best_block.read(); if cur_best.total_difficulty < total_difficulty { diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index d9f3d27afb0..4c470896773 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -31,7 +31,7 @@ use vm::{EnvInfo, LastHashes}; use engines::EthEngine; use error::{Error, BlockError}; use factory::Factories; -use header::Header; +use header::{Header, ExtendedHeader}; use receipt::{Receipt, TransactionOutcome}; use state::State; use state_db::StateDB; @@ -94,6 +94,8 @@ pub struct ExecutedBlock { state: State, traces: Tracing, last_hashes: Arc, + is_finalized: bool, + metadata: Option>, } impl ExecutedBlock { @@ -112,6 +114,8 @@ impl ExecutedBlock { Tracing::Disabled }, last_hashes: last_hashes, + is_finalized: false, + metadata: None, } } @@ -206,6 +210,26 @@ impl ::parity_machine::Transactions for ExecutedBlock { } } +impl ::parity_machine::Finalizable for ExecutedBlock { + fn is_finalized(&self) -> bool { + self.is_finalized + } + + fn mark_finalized(&mut self) { + self.is_finalized = true; + } +} + +impl ::parity_machine::WithMetadata for ExecutedBlock { + fn metadata(&self) -> Option<&[u8]> { + self.metadata.as_ref().map(|v| v.as_ref()) + } + + fn set_metadata(&mut self, value: Option>) { + self.metadata = value; + } +} + /// Block that is ready for transactions to be added. /// /// It's a bit like a Vec, except that whenever a transaction is pushed, we execute it and @@ -224,6 +248,8 @@ pub struct ClosedBlock { block: ExecutedBlock, uncle_bytes: Bytes, unclosed_state: State, + unclosed_finalization_state: bool, + unclosed_metadata: Option>, } /// Just like `ClosedBlock` except that we can't reopen it and it's faster. @@ -245,7 +271,7 @@ pub struct SealedBlock { impl<'x> OpenBlock<'x> { /// Create a new `OpenBlock` ready for transaction pushing. - pub fn new( + pub fn new<'a>( engine: &'x EthEngine, factories: Factories, tracing: bool, @@ -256,6 +282,7 @@ impl<'x> OpenBlock<'x> { gas_range_target: (U256, U256), extra_data: Bytes, is_epoch_begin: bool, + ancestry: &mut Iterator, ) -> Result { let number = parent.number() + 1; let state = State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce(number), factories)?; @@ -277,7 +304,7 @@ impl<'x> OpenBlock<'x> { engine.populate_from_parent(&mut r.block.header, parent); engine.machine().on_new_block(&mut r.block)?; - engine.on_new_block(&mut r.block, is_epoch_begin)?; + engine.on_new_block(&mut r.block, is_epoch_begin, ancestry)?; Ok(r) } @@ -387,6 +414,8 @@ impl<'x> OpenBlock<'x> { let mut s = self; let unclosed_state = s.block.state.clone(); + let unclosed_metadata = s.block.metadata.clone(); + let unclosed_finalization_state = s.block.is_finalized; if let Err(e) = s.engine.on_close_block(&mut s.block) { warn!("Encountered error on closing the block: {}", e); @@ -410,6 +439,8 @@ impl<'x> OpenBlock<'x> { block: s.block, uncle_bytes, unclosed_state, + unclosed_metadata, + unclosed_finalization_state, } } @@ -483,6 +514,8 @@ impl ClosedBlock { // revert rewards (i.e. set state back at last transaction's state). let mut block = self.block; block.state = self.unclosed_state; + block.metadata = self.unclosed_metadata; + block.is_finalized = self.unclosed_finalization_state; OpenBlock { block: block, engine: engine, @@ -588,6 +621,7 @@ fn enact( last_hashes: Arc, factories: Factories, is_epoch_begin: bool, + ancestry: &mut Iterator, ) -> Result { { if ::log::max_log_level() >= ::log::LogLevel::Trace { @@ -608,6 +642,7 @@ fn enact( (3141562.into(), 31415620.into()), vec![], is_epoch_begin, + ancestry, )?; b.populate_from(&header); @@ -630,6 +665,7 @@ pub fn enact_verified( last_hashes: Arc, factories: Factories, is_epoch_begin: bool, + ancestry: &mut Iterator, ) -> Result { let view = view!(BlockView, &block.bytes); @@ -644,6 +680,7 @@ pub fn enact_verified( last_hashes, factories, is_epoch_begin, + ancestry, ) } @@ -701,6 +738,7 @@ mod tests { (3141562.into(), 31415620.into()), vec![], false, + &mut Vec::new().into_iter(), )?; b.populate_from(&header); @@ -734,7 +772,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b = b.close_and_lock(); let _ = b.seal(&*spec.engine, vec![]); } @@ -748,7 +786,7 @@ mod tests { let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap() + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap() .close_and_lock().seal(engine, vec![]).unwrap(); let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); @@ -772,7 +810,7 @@ mod tests { let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let mut uncle1_header = Header::new(); uncle1_header.set_extra_data(b"uncle1".to_vec()); let mut uncle2_header = Header::new(); @@ -797,4 +835,3 @@ mod tests { assert!(orig_db.journal_db().keys().iter().filter(|k| orig_db.journal_db().get(k.0) != db.journal_db().get(k.0)).next() == None); } } - diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 0e18c5f889c..f2621d00e1b 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -38,11 +38,12 @@ use blockchain::block_info::{BlockInfo, BlockLocation, BranchBecomingCanonChainD use blockchain::extras::{BlockReceipts, BlockDetails, TransactionAddress, EPOCH_KEY_PREFIX, EpochTransitions}; use types::blockchain_info::BlockChainInfo; use types::tree_route::TreeRoute; -use blockchain::update::ExtrasUpdate; +use blockchain::update::{ExtrasUpdate, ExtrasInsert}; use blockchain::{CacheSize, ImportRoute, Config}; use db::{self, Writable, Readable, CacheUpdatePolicy}; use cache_manager::CacheManager; use encoded; +use engines::ForkChoice; use engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition}; use rayon::prelude::*; use ansi_term::Colour; @@ -417,6 +418,42 @@ impl<'a> Iterator for AncestryIter<'a> { } } +/// An iterator which walks the blockchain towards the genesis, with metadata information. +pub struct AncestryWithMetadataIter<'a> { + current: H256, + chain: &'a BlockChain, +} + +impl<'a> Iterator for AncestryWithMetadataIter<'a> { + type Item = ExtendedHeader; + fn next(&mut self) -> Option { + if self.current.is_zero() { + None + } else { + let details = self.chain.block_details(&self.current); + let header = self.chain.block_header_data(&self.current) + .map(|h| h.decode().expect("Stored block header data is valid RLP; qed")); + + match (details, header) { + (Some(details), Some(header)) => { + self.current = details.parent; + Some(ExtendedHeader { + parent_total_difficulty: details.total_difficulty - *header.difficulty(), + is_finalized: details.is_finalized, + metadata: details.metadata, + + header: header, + }) + }, + _ => { + self.current = H256::default(); + None + }, + } + } + } +} + /// An iterator which walks all epoch transitions. /// Returns epoch transitions. pub struct EpochTransitionIter<'a> { @@ -510,6 +547,8 @@ impl BlockChain { total_difficulty: header.difficulty(), parent: header.parent_hash(), children: vec![], + is_finalized: false, + metadata: None, }; let mut batch = DBTransaction::new(); @@ -649,6 +688,7 @@ impl BlockChain { /// `None` is returned. pub fn tree_route(&self, from: H256, to: H256) -> Option { let mut from_branch = vec![]; + let mut is_from_route_finalized = false; let mut to_branch = vec![]; let mut from_details = self.block_details(&from)?; @@ -661,6 +701,7 @@ impl BlockChain { from_branch.push(current_from); current_from = from_details.parent.clone(); from_details = self.block_details(&from_details.parent)?; + is_from_route_finalized = is_from_route_finalized || from_details.is_finalized; } while to_details.number > from_details.number { @@ -676,6 +717,7 @@ impl BlockChain { from_branch.push(current_from); current_from = from_details.parent.clone(); from_details = self.block_details(&from_details.parent)?; + is_from_route_finalized = is_from_route_finalized || from_details.is_finalized; to_branch.push(current_to); current_to = to_details.parent.clone(); @@ -689,7 +731,8 @@ impl BlockChain { Some(TreeRoute { blocks: from_branch, ancestor: current_from, - index: index + index: index, + is_from_route_finalized: is_from_route_finalized, }) } @@ -733,7 +776,7 @@ impl BlockChain { self.prepare_update(batch, ExtrasUpdate { block_hashes: self.prepare_block_hashes_update(bytes, &info), - block_details: self.prepare_block_details_update(bytes, &info), + block_details: self.prepare_block_details_update(bytes, &info, false, None), block_receipts: self.prepare_block_receipts_update(receipts, &info), blocks_blooms: self.prepare_block_blooms_update(bytes, &info), transactions_addresses: self.prepare_transaction_addresses_update(bytes, &info), @@ -769,11 +812,14 @@ impl BlockChain { location: BlockLocation::CanonChain, }; + // TODO [sorpaas] support warp sync insertion of finalization and metadata. let block_details = BlockDetails { number: header.number(), total_difficulty: info.total_difficulty, parent: header.parent_hash(), children: Vec::new(), + is_finalized: false, + metadata: None, }; let mut update = HashMap::new(); @@ -898,7 +944,22 @@ impl BlockChain { /// Inserts the block into backing cache database. /// Expects the block to be valid and already verified. /// If the block is already known, does nothing. - pub fn insert_block(&self, batch: &mut DBTransaction, bytes: &[u8], receipts: Vec) -> ImportRoute { + pub fn insert_block(&self, batch: &mut DBTransaction, bytes: &[u8], receipts: Vec, extras: ExtrasInsert) -> ImportRoute { + let block = view!(BlockView, bytes); + let header = block.header_view(); + + let parent_hash = header.parent_hash(); + let best_hash = self.best_block_hash(); + + let route = self.tree_route(best_hash, parent_hash).expect("forks are only kept when it has common ancestors; tree route from best to prospective's parent always exists; qed"); + + self.insert_block_with_route(batch, bytes, receipts, route, extras) + } + + /// Inserts the block into backing cache database with already generated route information. + /// Expects the block to be valid and already verified and route is tree route information from current best block to new block's parent. + /// If the block is already known, does nothing. + pub fn insert_block_with_route(&self, batch: &mut DBTransaction, bytes: &[u8], receipts: Vec, route: TreeRoute, extras: ExtrasInsert) -> ImportRoute { // create views onto rlp let block = view!(BlockView, bytes); let header = block.header_view(); @@ -917,7 +978,7 @@ impl BlockChain { batch.put(db::COL_HEADERS, &hash, &compressed_header); batch.put(db::COL_BODIES, &hash, &compressed_body); - let info = self.block_info(&header); + let info = self.block_info(&header, route, &extras); if let BlockLocation::BranchBecomingCanonChain(ref d) = info.location { info!(target: "reorg", "Reorg to {} ({} {} {})", @@ -930,7 +991,7 @@ impl BlockChain { self.prepare_update(batch, ExtrasUpdate { block_hashes: self.prepare_block_hashes_update(bytes, &info), - block_details: self.prepare_block_details_update(bytes, &info), + block_details: self.prepare_block_details_update(bytes, &info, extras.is_finalized, extras.metadata), block_receipts: self.prepare_block_receipts_update(receipts, &info), blocks_blooms: self.prepare_block_blooms_update(bytes, &info), transactions_addresses: self.prepare_transaction_addresses_update(bytes, &info), @@ -942,45 +1003,59 @@ impl BlockChain { } /// Get inserted block info which is critical to prepare extras updates. - fn block_info(&self, header: &HeaderView) -> BlockInfo { + fn block_info(&self, header: &HeaderView, route: TreeRoute, extras: &ExtrasInsert) -> BlockInfo { let hash = header.hash(); let number = header.number(); let parent_hash = header.parent_hash(); let parent_details = self.block_details(&parent_hash).unwrap_or_else(|| panic!("Invalid parent hash: {:?}", parent_hash)); - let is_new_best = parent_details.total_difficulty + header.difficulty() > self.best_block_total_difficulty(); BlockInfo { hash: hash, number: number, total_difficulty: parent_details.total_difficulty + header.difficulty(), - location: if is_new_best { - // on new best block we need to make sure that all ancestors - // are moved to "canon chain" - // find the route between old best block and the new one - let best_hash = self.best_block_hash(); - let route = self.tree_route(best_hash, parent_hash) - .expect("blocks being imported always within recent history; qed"); - - assert_eq!(number, parent_details.number + 1); - - match route.blocks.len() { - 0 => BlockLocation::CanonChain, - _ => { - let retracted = route.blocks.iter().take(route.index).cloned().collect::>().into_iter().collect::>(); - let enacted = route.blocks.into_iter().skip(route.index).collect::>(); - BlockLocation::BranchBecomingCanonChain(BranchBecomingCanonChainData { - ancestor: route.ancestor, - enacted: enacted, - retracted: retracted, - }) + location: match extras.fork_choice { + ForkChoice::New => { + // On new best block we need to make sure that all ancestors + // are moved to "canon chain" + // find the route between old best block and the new one + match route.blocks.len() { + 0 => BlockLocation::CanonChain, + _ => { + let retracted = route.blocks.iter().take(route.index).cloned().collect::>().into_iter().collect::>(); + let enacted = route.blocks.into_iter().skip(route.index).collect::>(); + BlockLocation::BranchBecomingCanonChain(BranchBecomingCanonChainData { + ancestor: route.ancestor, + enacted: enacted, + retracted: retracted, + }) + } } - } - } else { - BlockLocation::Branch - } + }, + ForkChoice::Old => BlockLocation::Branch, + }, } } + /// Mark a block to be considered finalized. Returns `Some(())` if the operation succeeds, and `None` if the block + /// hash is not found. + pub fn mark_finalized(&self, batch: &mut DBTransaction, block_hash: H256) -> Option<()> { + let mut block_details = self.block_details(&block_hash)?; + block_details.is_finalized = true; + + self.update_block_details(batch, block_hash, block_details); + Some(()) + } + + /// Prepares extras block detail update. + fn update_block_details(&self, batch: &mut DBTransaction, block_hash: H256, block_details: BlockDetails) { + let mut details_map = HashMap::new(); + details_map.insert(block_hash, block_details); + + // We're only updating one existing value. So it shouldn't suffer from cache decoherence problem. + let mut write_details = self.pending_block_details.write(); + batch.extend_with_cache(db::COL_EXTRA, &mut *write_details, details_map, CacheUpdatePolicy::Overwrite); + } + /// Prepares extras update. fn prepare_update(&self, batch: &mut DBTransaction, update: ExtrasUpdate, is_best: bool) { @@ -1101,6 +1176,18 @@ impl BlockChain { } } + /// Iterator that lists `first` and then all of `first`'s ancestors, by extended header. + pub fn ancestry_with_metadata_iter<'a>(&'a self, first: H256) -> AncestryWithMetadataIter { + AncestryWithMetadataIter { + current: if self.is_known(&first) { + first + } else { + H256::default() // zero hash + }, + chain: self + } + } + /// Given a block's `parent`, find every block header which represents a valid possible uncle. pub fn find_uncle_headers(&self, parent: &H256, uncle_generations: usize) -> Option> { self.find_uncle_hashes(parent, uncle_generations) @@ -1166,7 +1253,7 @@ impl BlockChain { /// This function returns modified block details. /// Uses the given parent details or attempts to load them from the database. - fn prepare_block_details_update(&self, block_bytes: &[u8], info: &BlockInfo) -> HashMap { + fn prepare_block_details_update(&self, block_bytes: &[u8], info: &BlockInfo, is_finalized: bool, metadata: Option>) -> HashMap { let block = view!(BlockView, block_bytes); let header = block.header_view(); let parent_hash = header.parent_hash(); @@ -1181,6 +1268,8 @@ impl BlockChain { total_difficulty: info.total_difficulty, parent: parent_hash, children: vec![], + is_finalized: is_finalized, + metadata: metadata, }; // write to batch @@ -1418,7 +1507,7 @@ mod tests { use std::sync::Arc; use rustc_hex::FromHex; use hash::keccak; - use kvdb::KeyValueDB; + use kvdb::{KeyValueDB, DBTransaction}; use kvdb_memorydb; use ethereum_types::*; use receipt::{Receipt, TransactionOutcome}; @@ -1441,6 +1530,42 @@ mod tests { BlockChain::new(Config::default(), genesis, db) } + fn insert_block(db: &Arc, bc: &BlockChain, bytes: &[u8], receipts: Vec) -> ImportRoute { + insert_block_commit(db, bc, bytes, receipts, true) + } + + fn insert_block_commit(db: &Arc, bc: &BlockChain, bytes: &[u8], receipts: Vec, commit: bool) -> ImportRoute { + let mut batch = db.transaction(); + let res = insert_block_batch(&mut batch, bc, bytes, receipts); + db.write(batch).unwrap(); + if commit { + bc.commit(); + } + res + } + + fn insert_block_batch(batch: &mut DBTransaction, bc: &BlockChain, bytes: &[u8], receipts: Vec) -> ImportRoute { + use views::BlockView; + use blockchain::ExtrasInsert; + + let block = view!(BlockView, bytes); + let header = block.header_view(); + let parent_hash = header.parent_hash(); + let parent_details = bc.block_details(&parent_hash).unwrap_or_else(|| panic!("Invalid parent hash: {:?}", parent_hash)); + let block_total_difficulty = parent_details.total_difficulty + header.difficulty(); + let fork_choice = if block_total_difficulty > bc.best_block_total_difficulty() { + ::engines::ForkChoice::New + } else { + ::engines::ForkChoice::Old + }; + + bc.insert_block(batch, bytes, receipts, ExtrasInsert { + fork_choice: fork_choice, + is_finalized: false, + metadata: None + }) + } + #[test] fn should_cache_best_block() { // given @@ -1452,8 +1577,7 @@ mod tests { assert_eq!(bc.best_block_number(), 0); // when - let mut batch = db.transaction(); - bc.insert_block(&mut batch, &first.last().encoded(), vec![]); + insert_block_commit(&db, &bc, &first.last().encoded(), vec![], false); assert_eq!(bc.best_block_number(), 0); bc.commit(); // NOTE no db.write here (we want to check if best block is cached) @@ -1483,7 +1607,7 @@ mod tests { assert_eq!(bc.block_details(&genesis_hash).unwrap().children, vec![]); let mut batch = db.transaction(); - bc.insert_block(&mut batch, &first.encoded(), vec![]); + insert_block_batch(&mut batch, &bc, &first.encoded(), vec![]); db.write(batch).unwrap(); bc.commit(); @@ -1509,7 +1633,7 @@ mod tests { let mut batch = db.transaction(); for block in generator { block_hashes.push(block.hash()); - bc.insert_block(&mut batch, &block.encoded(), vec![]); + insert_block_batch(&mut batch, &bc, &block.encoded(), vec![]); bc.commit(); } db.write(batch).unwrap(); @@ -1549,14 +1673,10 @@ mod tests { let db = new_db(); let bc = new_chain(&genesis.last().encoded(), db.clone()); - let mut batch = db.transaction(); for b in generator { - bc.insert_block(&mut batch, &b.encoded(), vec![]); - bc.commit(); + insert_block(&db, &bc, &b.encoded(), vec![]); } - db.write(batch).unwrap(); - assert_eq!(uncle_headers, bc.find_uncle_headers(&b4a_hash, 3).unwrap()); // TODO: insert block that already includes one of them as an uncle to check it's not allowed. } @@ -1590,9 +1710,9 @@ mod tests { let bc = new_chain(&genesis.last().encoded(), db.clone()); let mut batch = db.transaction(); - let _ = bc.insert_block(&mut batch, &b1a.last().encoded(), vec![]); + let _ = insert_block_batch(&mut batch, &bc, &b1a.last().encoded(), vec![]); bc.commit(); - let _ = bc.insert_block(&mut batch, &b1b.last().encoded(), vec![]); + let _ = insert_block_batch(&mut batch, &bc, &b1b.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); @@ -1604,7 +1724,7 @@ mod tests { // now let's make forked chain the canon chain let mut batch = db.transaction(); - let _ = bc.insert_block(&mut batch, &b2.last().encoded(), vec![]); + let _ = insert_block_batch(&mut batch, &bc, &b2.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); @@ -1665,9 +1785,9 @@ mod tests { let bc = new_chain(&genesis.last().encoded(), db.clone()); let mut batch = db.transaction(); - let _ = bc.insert_block(&mut batch, &b1a.last().encoded(), vec![]); + let _ = insert_block_batch(&mut batch, &bc, &b1a.last().encoded(), vec![]); bc.commit(); - let _ = bc.insert_block(&mut batch, &b1b.last().encoded(), vec![]); + let _ = insert_block_batch(&mut batch, &bc, &b1b.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); @@ -1683,7 +1803,7 @@ mod tests { // now let's make forked chain the canon chain let mut batch = db.transaction(); - let _ = bc.insert_block(&mut batch, &b2.last().encoded(), vec![]); + let _ = insert_block_batch(&mut batch, &bc, &b2.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); @@ -1723,16 +1843,16 @@ mod tests { let bc = new_chain(&genesis.last().encoded(), db.clone()); let mut batch = db.transaction(); - let ir1 = bc.insert_block(&mut batch, &b1.last().encoded(), vec![]); + let ir1 = insert_block_batch(&mut batch, &bc, &b1.last().encoded(), vec![]); bc.commit(); - let ir2 = bc.insert_block(&mut batch, &b2.last().encoded(), vec![]); + let ir2 = insert_block_batch(&mut batch, &bc, &b2.last().encoded(), vec![]); bc.commit(); - let ir3b = bc.insert_block(&mut batch, &b3b.last().encoded(), vec![]); + let ir3b = insert_block_batch(&mut batch, &bc, &b3b.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); assert_eq!(bc.block_hash(3).unwrap(), b3b_hash); let mut batch = db.transaction(); - let ir3a = bc.insert_block(&mut batch, &b3a.last().encoded(), vec![]); + let ir3a = insert_block_batch(&mut batch, &bc, &b3a.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); @@ -1837,7 +1957,7 @@ mod tests { let bc = new_chain(&genesis.last().encoded(), db.clone()); assert_eq!(bc.best_block_hash(), genesis_hash); let mut batch = db.transaction(); - bc.insert_block(&mut batch, &first.last().encoded(), vec![]); + insert_block_batch(&mut batch, &bc, &first.last().encoded(), vec![]); db.write(batch).unwrap(); bc.commit(); assert_eq!(bc.best_block_hash(), first_hash); @@ -1896,7 +2016,7 @@ mod tests { let db = new_db(); let bc = new_chain(&genesis, db.clone()); let mut batch =db.transaction(); - bc.insert_block(&mut batch, &b1, vec![]); + insert_block_batch(&mut batch, &bc, &b1, vec![]); db.write(batch).unwrap(); bc.commit(); @@ -1907,14 +2027,6 @@ mod tests { } } - fn insert_block(db: &Arc, bc: &BlockChain, bytes: &[u8], receipts: Vec) -> ImportRoute { - let mut batch = db.transaction(); - let res = bc.insert_block(&mut batch, bytes, receipts); - db.write(batch).unwrap(); - bc.commit(); - res - } - #[test] fn test_logs() { let t1 = Transaction { @@ -2198,12 +2310,12 @@ mod tests { let mut batch = db.transaction(); // create a longer fork for block in generator { - bc.insert_block(&mut batch, &block.encoded(), vec![]); + insert_block_batch(&mut batch, &bc, &block.encoded(), vec![]); bc.commit(); } assert_eq!(bc.best_block_number(), 5); - bc.insert_block(&mut batch, &uncle.last().encoded(), vec![]); + insert_block_batch(&mut batch, &bc, &uncle.last().encoded(), vec![]); db.write(batch).unwrap(); bc.commit(); } @@ -2230,7 +2342,7 @@ mod tests { // create a longer fork for (i, block) in generator.into_iter().enumerate() { - bc.insert_block(&mut batch, &block.encoded(), vec![]); + insert_block_batch(&mut batch, &bc, &block.encoded(), vec![]); bc.insert_epoch_transition(&mut batch, i as u64, EpochTransition { block_hash: block.hash(), block_number: i as u64 + 1, @@ -2241,7 +2353,7 @@ mod tests { assert_eq!(bc.best_block_number(), 5); - bc.insert_block(&mut batch, &uncle.last().encoded(), vec![]); + insert_block_batch(&mut batch, &bc, &uncle.last().encoded(), vec![]); bc.insert_epoch_transition(&mut batch, 999, EpochTransition { block_hash: uncle.last().hash(), block_number: 1, @@ -2291,11 +2403,7 @@ mod tests { // and a non-canonical fork of 8 from genesis. let fork_hash = { for block in fork_generator { - let mut batch = db.transaction(); - - bc.insert_block(&mut batch, &block.encoded(), vec![]); - bc.commit(); - db.write(batch).unwrap(); + insert_block(&db, &bc, &block.encoded(), vec![]); } assert_eq!(bc.best_block_number(), 7); @@ -2303,11 +2411,7 @@ mod tests { }; for block in next_generator { - let mut batch = db.transaction(); - bc.insert_block(&mut batch, &block.encoded(), vec![]); - bc.commit(); - - db.write(batch).unwrap(); + insert_block(&db, &bc, &block.encoded(), vec![]); } assert_eq!(bc.best_block_number(), 10); diff --git a/ethcore/src/blockchain/extras.rs b/ethcore/src/blockchain/extras.rs index 97583a693a6..3fb25e7b1b1 100644 --- a/ethcore/src/blockchain/extras.rs +++ b/ethcore/src/blockchain/extras.rs @@ -23,6 +23,7 @@ use db::Key; use engines::epoch::{Transition as EpochTransition}; use header::BlockNumber; use receipt::Receipt; +use rlp; use heapsize::HeapSizeOf; use ethereum_types::{H256, H264, U256}; @@ -167,7 +168,7 @@ impl Key for u64 { } /// Familial details concerning a block -#[derive(Debug, Clone, RlpEncodable, RlpDecodable)] +#[derive(Debug, Clone)] pub struct BlockDetails { /// Block number pub number: BlockNumber, @@ -177,6 +178,57 @@ pub struct BlockDetails { pub parent: H256, /// List of children block hashes pub children: Vec, + /// Whether the block is considered finalized + pub is_finalized: bool, + /// Additional block metadata + pub metadata: Option>, +} + +impl rlp::Encodable for BlockDetails { + fn rlp_append(&self, stream: &mut rlp::RlpStream) { + let use_short_version = self.metadata.is_none() && !self.is_finalized; + + match use_short_version { + true => { stream.begin_list(4); }, + false => { stream.begin_list(6); }, + } + + stream.append(&self.number); + stream.append(&self.total_difficulty); + stream.append(&self.parent); + stream.append_list(&self.children); + if !use_short_version { + stream.append(&self.is_finalized); + stream.append(&self.metadata); + } + } +} + +impl rlp::Decodable for BlockDetails { + fn decode(rlp: &rlp::Rlp) -> Result { + let use_short_version = match rlp.item_count()? { + 4 => true, + 6 => false, + _ => return Err(rlp::DecoderError::RlpIncorrectListLen), + }; + + Ok(BlockDetails { + number: rlp.val_at(0)?, + total_difficulty: rlp.val_at(1)?, + parent: rlp.val_at(2)?, + children: rlp.list_at(3)?, + is_finalized: if use_short_version { + false + } else { + rlp.val_at(4)? + }, + metadata: if use_short_version { + None + } else { + rlp.val_at(5)? + }, + }) + } } impl HeapSizeOf for BlockDetails { diff --git a/ethcore/src/blockchain/mod.rs b/ethcore/src/blockchain/mod.rs index 062068c704d..f991692dedf 100644 --- a/ethcore/src/blockchain/mod.rs +++ b/ethcore/src/blockchain/mod.rs @@ -33,4 +33,5 @@ pub use self::cache::CacheSize; pub use self::config::Config; pub use self::extras::{BlockReceipts, BlockDetails, TransactionAddress}; pub use self::import_route::ImportRoute; +pub use self::update::ExtrasInsert; pub use types::tree_route::TreeRoute; diff --git a/ethcore/src/blockchain/update.rs b/ethcore/src/blockchain/update.rs index a5251c1ed8e..b695b9236b0 100644 --- a/ethcore/src/blockchain/update.rs +++ b/ethcore/src/blockchain/update.rs @@ -22,3 +22,13 @@ pub struct ExtrasUpdate<'a> { /// Modified transaction addresses (None signifies removed transactions). pub transactions_addresses: HashMap>, } + +/// Extra information in block insertion. +pub struct ExtrasInsert { + /// The primitive fork choice before applying finalization rules. + pub fork_choice: ::engines::ForkChoice, + /// Is the inserted block considered finalized. + pub is_finalized: bool, + /// New block local metadata. + pub metadata: Option>, +} diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 76d78e3df63..993ecdda216 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -33,7 +33,7 @@ use util_error::UtilError; // other use ethereum_types::{H256, Address, U256}; use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock}; -use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute, TransactionAddress}; +use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert}; use client::ancient_import::AncientVerifier; use client::Error as ClientError; use client::{ @@ -50,13 +50,13 @@ use client::{ IoClient, }; use encoded; -use engines::{EthEngine, EpochTransition}; +use engines::{EthEngine, EpochTransition, ForkChoice}; use error::{ImportErrorKind, BlockImportErrorKind, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError}; use vm::{EnvInfo, LastHashes}; use evm::Schedule; use executive::{Executive, Executed, TransactOptions, contract_address}; use factory::{Factories, VmFactory}; -use header::{BlockNumber, Header}; +use header::{BlockNumber, Header, ExtendedHeader}; use io::{IoChannel, IoError}; use log_entry::LocalizedLogEntry; use miner::{Miner, MinerService}; @@ -73,10 +73,12 @@ use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Databa use transaction::{self, LocalizedTransaction, UnverifiedTransaction, SignedTransaction, Transaction, Action}; use types::filter::Filter; use types::mode::Mode as IpcMode; +use types::ancestry_action::AncestryAction; use verification; use verification::{PreverifiedBlock, Verifier}; use verification::queue::BlockQueue; use views::BlockView; +use parity_machine::{Finalizable, WithMetadata}; // re-export pub use types::blockchain_info::BlockChainInfo; @@ -396,6 +398,7 @@ impl Importer { last_hashes, client.factories.clone(), is_epoch_begin, + &mut chain.ancestry_with_metadata_iter(*header.parent_hash()), ); let mut locked_block = enact_result.map_err(|e| { @@ -467,6 +470,44 @@ impl Importer { let mut batch = DBTransaction::new(); + let ancestry_actions = self.engine.ancestry_actions(block.block(), &mut chain.ancestry_with_metadata_iter(*parent)); + + let best_hash = chain.best_block_hash(); + let metadata = block.block().metadata().map(Into::into); + let is_finalized = block.block().is_finalized(); + + let new = ExtendedHeader { + header: header.clone(), + is_finalized: is_finalized, + metadata: metadata, + parent_total_difficulty: chain.block_details(&parent).expect("Parent block is in the database; qed").total_difficulty + }; + + let best = { + let hash = best_hash; + let header = chain.block_header_data(&hash) + .expect("Best block is in the database; qed") + .decode() + .expect("Stored block header is valid RLP; qed"); + let details = chain.block_details(&hash) + .expect("Best block is in the database; qed"); + + ExtendedHeader { + parent_total_difficulty: details.total_difficulty - *header.difficulty(), + is_finalized: details.is_finalized, + metadata: details.metadata, + + header: header, + } + }; + + let route = chain.tree_route(best_hash, *parent).expect("forks are only kept when it has common ancestors; tree route from best to prospective's parent always exists; qed"); + let fork_choice = if route.is_from_route_finalized { + ForkChoice::Old + } else { + self.engine.fork_choice(&new, &best) + }; + // CHECK! I *think* this is fine, even if the state_root is equal to another // already-imported block of the same number. // TODO: Prove it with a test. @@ -485,7 +526,17 @@ impl Importer { ); state.journal_under(&mut batch, number, hash).expect("DB commit failed"); - let route = chain.insert_block(&mut batch, block_data, receipts.clone()); + + for ancestry_action in ancestry_actions { + let AncestryAction::MarkFinalized(ancestry) = ancestry_action; + chain.mark_finalized(&mut batch, ancestry).expect("Engine's ancestry action must be known blocks; qed"); + } + + let route = chain.insert_block(&mut batch, block_data, receipts.clone(), ExtrasInsert { + fork_choice: fork_choice, + is_finalized: is_finalized, + metadata: new.metadata, + }); client.tracedb.read().import(&mut batch, TraceImportRequest { traces: traces.into(), @@ -2069,6 +2120,7 @@ impl PrepareOpenBlock for Client { gas_range_target, extra_data, is_epoch_begin, + &mut chain.ancestry_with_metadata_iter(best_header.hash()), ).expect("OpenBlock::new only fails if parent state root invalid; state root of best block's header is never invalid; qed"); // Add uncles @@ -2284,6 +2336,7 @@ mod tests { use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use kvdb::DBTransaction; + use blockchain::ExtrasInsert; let client = generate_dummy_client(0); let genesis = client.chain_info().best_block_hash; @@ -2296,7 +2349,11 @@ mod tests { let another_client = client.clone(); thread::spawn(move || { let mut batch = DBTransaction::new(); - another_client.chain.read().insert_block(&mut batch, &new_block, Vec::new()); + another_client.chain.read().insert_block(&mut batch, &new_block, Vec::new(), ExtrasInsert { + fork_choice: ::engines::ForkChoice::New, + is_finalized: false, + metadata: None, + }); go_thread.store(true, Ordering::SeqCst); }); go diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 6a3166f7c04..fab32346572 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -392,6 +392,7 @@ impl PrepareOpenBlock for TestBlockChainClient { gas_range_target, extra_data, false, + &mut Vec::new().into_iter(), ).expect("Opening block for tests will not fail."); // TODO [todr] Override timestamp for predictability open_block.set_timestamp(*self.latest_block_timestamp.read()); @@ -739,7 +740,8 @@ impl BlockChainClient for TestBlockChainClient { } } if adding { Vec::new() } else { blocks } - } + }, + is_from_route_finalized: false, }) } diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index ed9a9a4f251..02bb88c51f2 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -33,7 +33,7 @@ use error::{Error, BlockError}; use ethjson; use machine::{AuxiliaryData, Call, EthereumMachine}; use hash::keccak; -use header::{Header, BlockNumber}; +use header::{Header, BlockNumber, ExtendedHeader}; use super::signer::EngineSigner; use super::validator_set::{ValidatorSet, SimpleList, new_validator_set}; @@ -957,6 +957,7 @@ impl Engine for AuthorityRound { &self, block: &mut ExecutedBlock, epoch_begin: bool, + _ancestry: &mut Iterator, ) -> Result<(), Error> { // with immediate transitions, we don't use the epoch mechanism anyway. // the genesis is always considered an epoch, but we ignore it intentionally. @@ -1348,6 +1349,10 @@ impl Engine for AuthorityRound { Some(Box::new(::snapshot::PoaSnapshot)) } } + + fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> super::ForkChoice { + super::total_difficulty_fork_choice(new, current) + } } #[cfg(test)] @@ -1407,9 +1412,9 @@ mod tests { let db1 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b1 = b1.close_and_lock(); - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b2 = b2.close_and_lock(); engine.set_signer(tap.clone(), addr1, "1".into()); @@ -1441,9 +1446,9 @@ mod tests { let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b1 = b1.close_and_lock(); - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b2 = b2.close_and_lock(); engine.set_signer(tap.clone(), addr1, "1".into()); @@ -1696,7 +1701,7 @@ mod tests { let db1 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b1 = b1.close_and_lock(); let client = generate_dummy_client(0); @@ -1731,7 +1736,7 @@ mod tests { let last_hashes = Arc::new(vec![genesis_header.hash()]); // step 2 - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b1 = b1.close_and_lock(); // since the block is empty it isn't sealed and we generate empty steps @@ -1740,7 +1745,7 @@ mod tests { engine.step(); // step 3 - let mut b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let mut b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); b2.push_transaction(Transaction { action: Action::Create, nonce: U256::from(0), @@ -1779,7 +1784,7 @@ mod tests { let last_hashes = Arc::new(vec![genesis_header.hash()]); // step 2 - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b1 = b1.close_and_lock(); // since the block is empty it isn't sealed and we generate empty steps @@ -1788,7 +1793,7 @@ mod tests { engine.step(); // step 3 - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b2 = b2.close_and_lock(); engine.set_signer(tap.clone(), addr2, "0".into()); assert_eq!(engine.generate_seal(b2.block(), &genesis_header), Seal::None); @@ -1796,7 +1801,7 @@ mod tests { // step 4 // the spec sets the maximum_empty_steps to 2 so we will now seal an empty block and include the empty step messages - let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b3 = b3.close_and_lock(); engine.set_signer(tap.clone(), addr1, "1".into()); @@ -1829,7 +1834,7 @@ mod tests { engine.register_client(Arc::downgrade(&client) as _); // step 2 - let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b1 = b1.close_and_lock(); // since the block is empty it isn't sealed and we generate empty steps @@ -1839,7 +1844,7 @@ mod tests { // step 3 // the signer of the accumulated empty step message should be rewarded - let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let addr1_balance = b2.block().state().balance(&addr1).unwrap(); // after closing the block `addr1` should be reward twice, one for the included empty step message and another for block creation @@ -1962,6 +1967,7 @@ mod tests { (3141562.into(), 31415620.into()), vec![], false, + &mut Vec::new().into_iter(), ).unwrap(); let b1 = b1.close_and_lock(); @@ -1983,6 +1989,7 @@ mod tests { (3141562.into(), 31415620.into()), vec![], false, + &mut Vec::new().into_iter(), ).unwrap(); let addr1_balance = b2.block().state().balance(&addr1).unwrap(); diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index bbefddccb74..e99fd88dcbc 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -25,7 +25,7 @@ use block::*; use engines::{Engine, Seal, ConstructedVerifier, EngineError}; use error::{BlockError, Error}; use ethjson; -use header::Header; +use header::{Header, ExtendedHeader}; use client::EngineClient; use machine::{AuxiliaryData, Call, EthereumMachine}; use super::signer::EngineSigner; @@ -191,6 +191,10 @@ impl Engine for BasicAuthority { fn snapshot_components(&self) -> Option> { None } + + fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> super::ForkChoice { + super::total_difficulty_fork_choice(new, current) + } } #[cfg(test)] @@ -247,7 +251,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b = b.close_and_lock(); if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) { assert!(b.try_seal(engine, seal).is_ok()); diff --git a/ethcore/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs index 40a96e2b713..c16203f1053 100644 --- a/ethcore/src/engines/instant_seal.rs +++ b/ethcore/src/engines/instant_seal.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use engines::{Engine, Seal}; -use parity_machine::{Machine, Transactions}; +use parity_machine::{Machine, Transactions, TotalScoredHeader}; /// An engine which does not provide any consensus mechanism, just seals blocks internally. /// Only seals blocks which have transactions. @@ -33,7 +33,9 @@ impl InstantSeal { } impl Engine for InstantSeal - where M::LiveBlock: Transactions + where M::LiveBlock: Transactions, + M::ExtendedHeader: TotalScoredHeader, + ::Value: Ord { fn name(&self) -> &str { "InstantSeal" @@ -61,6 +63,10 @@ impl Engine for InstantSeal fn is_timestamp_valid(&self, header_timestamp: u64, parent_timestamp: u64) -> bool { header_timestamp >= parent_timestamp } + + fn fork_choice(&self, new: &M::ExtendedHeader, current: &M::ExtendedHeader) -> super::ForkChoice { + super::total_difficulty_fork_choice(new, current) + } } #[cfg(test)] @@ -80,7 +86,7 @@ mod tests { let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let genesis_header = spec.genesis_header(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b = b.close_and_lock(); if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) { assert!(b.try_seal(engine, seal).is_ok()); diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index e019636f53a..0878b4595f1 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -52,15 +52,25 @@ use spec::CommonParams; use transaction::{self, UnverifiedTransaction, SignedTransaction}; use ethkey::Signature; -use parity_machine::{Machine, LocalizedMachine as Localized}; +use parity_machine::{Machine, LocalizedMachine as Localized, TotalScoredHeader}; use ethereum_types::{H256, U256, Address}; use unexpected::{Mismatch, OutOfBounds}; use bytes::Bytes; +use types::ancestry_action::AncestryAction; /// Default EIP-210 contract code. /// As defined in https://github.com/ethereum/EIPs/pull/210 pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73fffffffffffffffffffffffffffffffffffffffe33141561006a5760014303600035610100820755610100810715156100455760003561010061010083050761010001555b6201000081071515610064576000356101006201000083050761020001555b5061013e565b4360003512151561008457600060405260206040f361013d565b61010060003543031315156100a857610100600035075460605260206060f361013c565b6101006000350715156100c55762010000600035430313156100c8565b60005b156100ea576101006101006000350507610100015460805260206080f361013b565b620100006000350715156101095763010000006000354303131561010c565b60005b1561012f57610100620100006000350507610200015460a052602060a0f361013a565b600060c052602060c0f35b5b5b5b5b"; +/// Fork choice. +#[derive(Debug, PartialEq, Eq)] +pub enum ForkChoice { + /// Choose the new block. + New, + /// Choose the current best block. + Old, +} + /// Voting errors. #[derive(Debug)] pub enum EngineError { @@ -208,6 +218,7 @@ pub trait Engine: Sync + Send { &self, _block: &mut M::LiveBlock, _epoch_begin: bool, + _ancestry: &mut Iterator, ) -> Result<(), M::Error> { Ok(()) } @@ -348,6 +359,24 @@ pub trait Engine: Sync + Send { fn is_timestamp_valid(&self, header_timestamp: u64, parent_timestamp: u64) -> bool { header_timestamp > parent_timestamp } + + /// Gather all ancestry actions. Called at the last stage when a block is committed. The Engine must guarantee that + /// the ancestry exists. + fn ancestry_actions(&self, _block: &M::LiveBlock, _ancestry: &mut Iterator) -> Vec { + Vec::new() + } + + /// Check whether the given new block is the best block, after finalization check. + fn fork_choice(&self, new: &M::ExtendedHeader, best: &M::ExtendedHeader) -> ForkChoice; +} + +/// Check whether a given block is the best block based on the default total difficulty rule. +pub fn total_difficulty_fork_choice(new: &T, best: &T) -> ForkChoice where ::Value: Ord { + if new.total_score() > best.total_score() { + ForkChoice::New + } else { + ForkChoice::Old + } } /// Common type alias for an engine coupled with an Ethereum-like state machine. diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 278eb037c06..c6025e62471 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -19,7 +19,7 @@ use engines::Engine; use engines::block_reward::{self, RewardKind}; use header::BlockNumber; use machine::WithRewards; -use parity_machine::{Header, LiveBlock, WithBalances}; +use parity_machine::{Header, LiveBlock, WithBalances, TotalScoredHeader}; /// Params for a null engine. #[derive(Clone, Default)] @@ -58,7 +58,10 @@ impl Default for NullEngine { } } -impl Engine for NullEngine { +impl Engine for NullEngine + where M::ExtendedHeader: TotalScoredHeader, + ::Value: Ord +{ fn name(&self) -> &str { "NullEngine" } @@ -101,4 +104,8 @@ impl Engine for NullEngine { fn snapshot_components(&self) -> Option> { Some(Box::new(::snapshot::PowSnapshot::new(10000, 10000))) } + + fn fork_choice(&self, new: &M::ExtendedHeader, current: &M::ExtendedHeader) -> super::ForkChoice { + super::total_difficulty_fork_choice(new, current) + } } diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 93fc347e942..52bf5ff67b8 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -35,7 +35,7 @@ use unexpected::{OutOfBounds, Mismatch}; use client::EngineClient; use bytes::Bytes; use error::{Error, BlockError}; -use header::{Header, BlockNumber}; +use header::{Header, BlockNumber, ExtendedHeader}; use rlp::Rlp; use ethkey::{self, Message, Signature}; use account_provider::AccountProvider; @@ -530,7 +530,7 @@ impl Engine for Tendermint { Ok(()) } - fn on_new_block(&self, block: &mut ExecutedBlock, epoch_begin: bool) -> Result<(), Error> { + fn on_new_block(&self, block: &mut ExecutedBlock, epoch_begin: bool, _ancestry: &mut Iterator) -> Result<(), Error> { if !epoch_begin { return Ok(()) } // genesis is never a new block, but might as well check. @@ -765,6 +765,10 @@ impl Engine for Tendermint { *self.client.write() = Some(client.clone()); self.validators.register_client(client); } + + fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> super::ForkChoice { + super::total_difficulty_fork_choice(new, current) + } } #[cfg(test)] @@ -800,7 +804,7 @@ mod tests { let db = spec.ensure_db_good(db, &Default::default()).unwrap(); let genesis_header = spec.genesis_header(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(spec.engine.as_ref(), Default::default(), false, db.boxed_clone(), &genesis_header, last_hashes, proposer, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b = OpenBlock::new(spec.engine.as_ref(), Default::default(), false, db.boxed_clone(), &genesis_header, last_hashes, proposer, (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b = b.close(); if let Seal::Proposal(seal) = spec.engine.generate_seal(b.block(), &genesis_header) { (b, seal) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 09151415c87..9b3945e38b1 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -25,7 +25,7 @@ use ethereum_types::{H256, H64, U256, Address}; use unexpected::{OutOfBounds, Mismatch}; use block::*; use error::{BlockError, Error}; -use header::{Header, BlockNumber}; +use header::{Header, BlockNumber, ExtendedHeader}; use engines::{self, Engine}; use ethjson; use rlp::Rlp; @@ -222,14 +222,6 @@ impl Engine for Arc { header.set_difficulty(difficulty); } - fn on_new_block( - &self, - _block: &mut ExecutedBlock, - _begins_epoch: bool, - ) -> Result<(), Error> { - Ok(()) - } - /// Apply the block reward on finalisation of the block. /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { @@ -364,6 +356,10 @@ impl Engine for Arc { fn snapshot_components(&self) -> Option> { Some(Box::new(::snapshot::PowSnapshot::new(SNAPSHOT_BLOCKS, MAX_SNAPSHOT_BLOCKS))) } + + fn fork_choice(&self, new: &ExtendedHeader, current: &ExtendedHeader) -> engines::ForkChoice { + engines::total_difficulty_fork_choice(new, current) + } } impl Ethash { @@ -538,7 +534,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b = b.close(); assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap()); } @@ -587,7 +583,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let mut uncle = Header::new(); let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); uncle.set_author(uncle_author); @@ -605,7 +601,7 @@ mod tests { let genesis_header = spec.genesis_header(); let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); - let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false, &mut Vec::new().into_iter()).unwrap(); let b = b.close(); let ubi_contract: Address = "00efdd5883ec628983e9063c7d969fe268bbf310".into(); diff --git a/ethcore/src/header.rs b/ethcore/src/header.rs index ba71eb30497..3e9675aa35b 100644 --- a/ethcore/src/header.rs +++ b/ethcore/src/header.rs @@ -34,6 +34,19 @@ enum Seal { Without, } +/// Extended block header, wrapping `Header` with finalized and total difficulty information. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ExtendedHeader { + /// The actual header. + pub header: Header, + /// Whether the block underlying this header is considered finalized. + pub is_finalized: bool, + /// The parent block difficulty. + pub parent_total_difficulty: U256, + /// The block metadata information. + pub metadata: Option>, +} + /// A block header. /// /// Reflects the specific RLP fields of a block in the chain with additional room for the seal @@ -368,21 +381,48 @@ impl HeapSizeOf for Header { impl ::parity_machine::Header for Header { fn bare_hash(&self) -> H256 { Header::bare_hash(self) } - fn hash(&self) -> H256 { Header::hash(self) } - fn seal(&self) -> &[Vec] { Header::seal(self) } - fn author(&self) -> &Address { Header::author(self) } - fn number(&self) -> BlockNumber { Header::number(self) } } impl ::parity_machine::ScoredHeader for Header { + type Value = U256; + fn score(&self) -> &U256 { self.difficulty() } fn set_score(&mut self, score: U256) { self.set_difficulty(score) } } +impl ::parity_machine::Header for ExtendedHeader { + fn bare_hash(&self) -> H256 { self.header.bare_hash() } + fn hash(&self) -> H256 { self.header.hash() } + fn seal(&self) -> &[Vec] { self.header.seal() } + fn author(&self) -> &Address { self.header.author() } + fn number(&self) -> BlockNumber { self.header.number() } +} + +impl ::parity_machine::ScoredHeader for ExtendedHeader { + type Value = U256; + + fn score(&self) -> &U256 { self.header.difficulty() } + fn set_score(&mut self, score: U256) { self.header.set_difficulty(score) } +} + +impl ::parity_machine::TotalScoredHeader for ExtendedHeader { + type Value = U256; + + fn total_score(&self) -> U256 { self.parent_total_difficulty + *self.header.difficulty() } +} + +impl ::parity_machine::FinalizableHeader for ExtendedHeader { + fn is_finalized(&self) -> bool { self.is_finalized } +} + +impl ::parity_machine::WithMetadataHeader for ExtendedHeader { + fn metadata(&self) -> Option<&[u8]> { self.metadata.as_ref().map(|v| v.as_ref()) } +} + #[cfg(test)] mod tests { use rustc_hex::FromHex; diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index d0d434b1de0..1bd3805ef3b 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -25,7 +25,7 @@ use builtin::Builtin; use client::{BlockInfo, CallContract}; use error::Error; use executive::Executive; -use header::{BlockNumber, Header}; +use header::{BlockNumber, Header, ExtendedHeader}; use spec::CommonParams; use state::{CleanupMode, Substate}; use trace::{NoopTracer, NoopVMTracer, Tracer, ExecutiveTracer, RewardType, Tracing}; @@ -422,10 +422,12 @@ pub enum AuxiliaryRequest { impl ::parity_machine::Machine for EthereumMachine { type Header = Header; + type ExtendedHeader = ExtendedHeader; type LiveBlock = ExecutedBlock; type EngineClient = ::client::EngineClient; type AuxiliaryRequest = AuxiliaryRequest; + type AncestryAction = ::types::ancestry_action::AncestryAction; type Error = Error; } diff --git a/ethcore/src/snapshot/tests/proof_of_work.rs b/ethcore/src/snapshot/tests/proof_of_work.rs index ae1805e85bd..3c3b47ce9c5 100644 --- a/ethcore/src/snapshot/tests/proof_of_work.rs +++ b/ethcore/src/snapshot/tests/proof_of_work.rs @@ -22,7 +22,7 @@ use tempdir::TempDir; use error::{Error, ErrorKind}; use blockchain::generator::{BlockGenerator, BlockBuilder}; -use blockchain::BlockChain; +use blockchain::{BlockChain, ExtrasInsert}; use snapshot::{chunk_secondary, Error as SnapshotError, Progress, SnapshotComponents}; use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter}; @@ -49,7 +49,11 @@ fn chunk_and_restore(amount: u64) { // build the blockchain. let mut batch = DBTransaction::new(); for block in generator { - bc.insert_block(&mut batch, &block.encoded(), vec![]); + bc.insert_block(&mut batch, &block.encoded(), vec![], ExtrasInsert { + fork_choice: ::engines::ForkChoice::New, + is_finalized: false, + metadata: None, + }); bc.commit(); } diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index 32b8beab830..e57d16a6549 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -19,7 +19,7 @@ use account_provider::AccountProvider; use ethereum_types::{H256, U256, Address}; use block::{OpenBlock, Drain}; -use blockchain::{BlockChain, Config as BlockChainConfig}; +use blockchain::{BlockChain, Config as BlockChainConfig, ExtrasInsert}; use bytes::Bytes; use client::{Client, ClientConfig, ChainInfo, ImportBlock, ChainNotify, ChainMessageType, PrepareOpenBlock}; use ethkey::KeyPair; @@ -148,6 +148,7 @@ pub fn generate_dummy_client_with_spec_accounts_and_data(test_spec: F, accoun (3141562.into(), 31415620.into()), vec![], false, + &mut Vec::new().into_iter(), ).unwrap(); rolling_timestamp += 10; b.set_timestamp(rolling_timestamp); @@ -265,7 +266,12 @@ pub fn generate_dummy_blockchain(block_number: u32) -> BlockChain { let mut batch = db.transaction(); for block_order in 1..block_number { - bc.insert_block(&mut batch, &create_unverifiable_block(block_order, bc.best_block_hash()), vec![]); + // Total difficulty is always 0 here. + bc.insert_block(&mut batch, &create_unverifiable_block(block_order, bc.best_block_hash()), vec![], ExtrasInsert { + fork_choice: ::engines::ForkChoice::New, + is_finalized: false, + metadata: None, + }); bc.commit(); } db.write(batch).unwrap(); @@ -280,7 +286,12 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> BlockChain { let mut batch = db.transaction(); for block_order in 1..block_number { - bc.insert_block(&mut batch, &create_unverifiable_block_with_extra(block_order, bc.best_block_hash(), None), vec![]); + // Total difficulty is always 0 here. + bc.insert_block(&mut batch, &create_unverifiable_block_with_extra(block_order, bc.best_block_hash(), None), vec![], ExtrasInsert { + fork_choice: ::engines::ForkChoice::New, + is_finalized: false, + metadata: None, + }); bc.commit(); } db.write(batch).unwrap(); diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index 72d0d473716..a98667b1423 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -87,6 +87,7 @@ fn can_trace_block_and_uncle_reward() { (3141562.into(), 31415620.into()), vec![], false, + &mut Vec::new().into_iter(), ).unwrap(); rolling_timestamp += 10; root_block.set_timestamp(rolling_timestamp); @@ -115,6 +116,7 @@ fn can_trace_block_and_uncle_reward() { (3141562.into(), 31415620.into()), vec![], false, + &mut Vec::new().into_iter(), ).unwrap(); rolling_timestamp += 10; parent_block.set_timestamp(rolling_timestamp); @@ -141,7 +143,8 @@ fn can_trace_block_and_uncle_reward() { author.clone(), (3141562.into(), 31415620.into()), vec![], - false + false, + &mut Vec::new().into_iter(), ).unwrap(); rolling_timestamp += 10; block.set_timestamp(rolling_timestamp); diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 03a6d6f8d41..de2f6c7195d 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -455,6 +455,8 @@ mod tests { total_difficulty: header.difficulty().clone(), parent: header.parent_hash().clone(), children: Vec::new(), + is_finalized: false, + metadata: None, } }) } diff --git a/ethcore/types/src/ancestry_action.rs b/ethcore/types/src/ancestry_action.rs new file mode 100644 index 00000000000..d9915cfee42 --- /dev/null +++ b/ethcore/types/src/ancestry_action.rs @@ -0,0 +1,27 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Actions on ancestry blocks when working on a new block. + +use ethereum_types::H256; + +#[derive(Debug, PartialEq, Eq, Clone)] +/// Actions on a live block's parent block. Only committed when the live block is committed. Those actions here must +/// respect the normal blockchain reorganization rules. +pub enum AncestryAction { + /// Mark an ancestry block as finalized. + MarkFinalized(H256), +} diff --git a/ethcore/types/src/lib.rs b/ethcore/types/src/lib.rs index 83a1cc65579..18e0dde86ad 100644 --- a/ethcore/types/src/lib.rs +++ b/ethcore/types/src/lib.rs @@ -46,6 +46,7 @@ pub mod state_diff; pub mod trace_filter; pub mod tree_route; pub mod verification_queue_info; +pub mod ancestry_action; /// Type for block number. pub type BlockNumber = u64; diff --git a/ethcore/types/src/tree_route.rs b/ethcore/types/src/tree_route.rs index b3fe431ab99..5d1bddd87b3 100644 --- a/ethcore/types/src/tree_route.rs +++ b/ethcore/types/src/tree_route.rs @@ -27,4 +27,6 @@ pub struct TreeRoute { pub ancestor: H256, /// An index where best common ancestor would be. pub index: usize, + /// Whether it has finalized blocks from `from` (inclusive) to `ancestor` (exclusive). + pub is_from_route_finalized: bool, } diff --git a/machine/src/lib.rs b/machine/src/lib.rs index 54ee403d954..075a42d7319 100644 --- a/machine/src/lib.rs +++ b/machine/src/lib.rs @@ -40,13 +40,35 @@ pub trait Header { fn number(&self) -> u64; } -/// a header with an associated score (difficulty in PoW terms) +/// A header with an associated score (difficulty in PoW terms) pub trait ScoredHeader: Header { + type Value; + /// Get the score of this header. - fn score(&self) -> &U256; + fn score(&self) -> &Self::Value; /// Set the score of this header. - fn set_score(&mut self, score: U256); + fn set_score(&mut self, score: Self::Value); +} + +/// A header with associated total score. +pub trait TotalScoredHeader: Header { + type Value; + + /// Get the total score of this header. + fn total_score(&self) -> Self::Value; +} + +/// A header with finalized information. +pub trait FinalizableHeader: Header { + /// Get whether this header is considered finalized, so that it will never be replaced in reorganization. + fn is_finalized(&self) -> bool; +} + +/// A header with metadata information. +pub trait WithMetadataHeader: Header { + /// Get the current header metadata. + fn metadata(&self) -> Option<&[u8]>; } /// A "live" block is one which is in the process of the transition. @@ -73,16 +95,36 @@ pub trait Transactions: LiveBlock { fn transactions(&self) -> &[Self::Transaction]; } +/// Trait for blocks which have finalized information. +pub trait Finalizable: LiveBlock { + /// Get whether the block is finalized. + fn is_finalized(&self) -> bool; + /// Mark the block as finalized. + fn mark_finalized(&mut self); +} + +/// A state machine with block metadata. +pub trait WithMetadata: LiveBlock { + /// Get the current live block metadata. + fn metadata(&self) -> Option<&[u8]>; + /// Set the current live block metadata. + fn set_metadata(&mut self, value: Option>); +} + /// Generalization of types surrounding blockchain-suitable state machines. pub trait Machine: for<'a> LocalizedMachine<'a> { /// The block header type. type Header: Header; /// The live block type. type LiveBlock: LiveBlock; + /// Block header with metadata information. + type ExtendedHeader: Header; /// A handle to a blockchain client for this machine. type EngineClient: ?Sized; /// A description of needed auxiliary data. type AuxiliaryRequest; + /// Actions taken on ancestry blocks when commiting a new block. + type AncestryAction; /// Errors which can occur when querying or interacting with the machine. type Error; From f9e64e0965febd95de513b1508f75fffc76169bf Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Wed, 16 May 2018 20:09:59 +0200 Subject: [PATCH 78/95] typo (#8640) --- parity/main.rs | 6 +++--- secret_store/src/acl_storage.rs | 2 +- secret_store/src/key_server_set.rs | 10 +++++----- secret_store/src/key_storage.rs | 2 +- secret_store/src/serialization.rs | 2 +- secret_store/src/traits.rs | 2 +- secret_store/src/types/all.rs | 2 +- secret_store/src/types/error.rs | 8 ++++---- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 03b04a8c82f..06671cbfebf 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -54,15 +54,15 @@ fn latest_exe_path() -> Option { fn set_spec_name_override(spec_name: String) { if let Err(e) = create_dir_all(default_hypervisor_path()) - .and_then(|_| File::create(updates_path("spec_name_overide")) + .and_then(|_| File::create(updates_path("spec_name_override")) .and_then(|mut f| f.write_all(spec_name.as_bytes()))) { - warn!("Couldn't override chain spec: {} at {:?}", e, updates_path("spec_name_overide")); + warn!("Couldn't override chain spec: {} at {:?}", e, updates_path("spec_name_override")); } } fn take_spec_name_override() -> Option { - let p = updates_path("spec_name_overide"); + let p = updates_path("spec_name_override"); let r = File::open(p.clone()).ok() .and_then(|mut f| { let mut spec_name = String::new(); f.read_to_string(&mut spec_name).ok().map(|_| spec_name) }); let _ = remove_file(p); diff --git a/secret_store/src/acl_storage.rs b/secret_store/src/acl_storage.rs index b3427fa1b20..bc75cfec44c 100644 --- a/secret_store/src/acl_storage.rs +++ b/secret_store/src/acl_storage.rs @@ -106,7 +106,7 @@ impl CachedContract { pub fn check(&mut self, requester: Address, document: &ServerKeyId) -> Result { if let Some(client) = self.client.get() { - // call contract to check accesss + // call contract to check access match self.contract_addr { Some(contract_address) => { let do_call = |data| client.call_contract(BlockId::Latest, contract_address, data); diff --git a/secret_store/src/key_server_set.rs b/secret_store/src/key_server_set.rs index d13017261c4..8a0d786af98 100644 --- a/secret_store/src/key_server_set.rs +++ b/secret_store/src/key_server_set.rs @@ -271,7 +271,7 @@ impl CachedContract { pub fn update(&mut self, enacted: Vec, retracted: Vec) { if let Some(client) = self.client.get() { - // read new snapshot from reqistry (if something has chnaged) + // read new snapshot from registry (if something has changed) self.read_from_registry_if_required(&*client, enacted, retracted); // update number of confirmations (if there's future new set) @@ -371,7 +371,7 @@ impl CachedContract { None => { // no contract installed => empty snapshot // WARNING: after restart current_set will be reset to the set from configuration file - // even though we have reset to empty set here. We are not considerning this as an issue + // even though we have reset to empty set here. We are not considering this as an issue // because it is actually the issue of administrator. self.snapshot = Default::default(); self.future_new_set = None; @@ -540,7 +540,7 @@ fn update_number_of_confirmations H256, F2: Fn(H256) -> Option> // not enough confirmations => do nothing Some(_) => return, // if number of confirmations is None, then reorg has happened && we need to reset block - // (some more intelligent startegy is possible, but let's stick to simplest one) + // (some more intelligent strategy is possible, but let's stick to simplest one) None => { future_new_set.block = latest_block(); return; @@ -556,9 +556,9 @@ fn update_number_of_confirmations H256, F2: Fn(H256) -> Option> fn update_last_transaction_block(client: &Client, migration_id: &H256, previous_transaction: &mut Option) -> bool { let last_block = client.block_number(BlockId::Latest).unwrap_or_default(); match previous_transaction.as_ref() { - // no previous transaction => send immideately + // no previous transaction => send immediately None => (), - // previous transaction has been sent for other migration process => send immideately + // previous transaction has been sent for other migration process => send immediately Some(tx) if tx.migration_id != *migration_id => (), // if we have sent the same type of transaction recently => do nothing (hope it will be mined eventually) // if we have sent the same transaction some time ago => diff --git a/secret_store/src/key_storage.rs b/secret_store/src/key_storage.rs index 4f78bc338c2..848e6bf2a52 100644 --- a/secret_store/src/key_storage.rs +++ b/secret_store/src/key_storage.rs @@ -108,7 +108,7 @@ pub struct SerializableDocumentKeyShareV0 { /// V1 of encrypted key share, as it is stored by key storage on the single key server. #[derive(Serialize, Deserialize)] struct SerializableDocumentKeyShareV1 { - /// Authore of the entry. + /// Author of the entry. pub author: SerializablePublic, /// Decryption threshold (at least threshold + 1 nodes are required to decrypt data). pub threshold: usize, diff --git a/secret_store/src/serialization.rs b/secret_store/src/serialization.rs index 42209e0de4a..f3e9aa1d76d 100644 --- a/secret_store/src/serialization.rs +++ b/secret_store/src/serialization.rs @@ -117,7 +117,7 @@ impl_bytes!(SerializableSignature, Signature, false, ()); /// Serializable shadow decryption result. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SerializableEncryptedDocumentKeyShadow { - /// Decrypted secret point. It is partially decrypted if shadow decrpytion was requested. + /// Decrypted secret point. It is partially decrypted if shadow decryption was requested. pub decrypted_secret: SerializablePublic, /// Shared common point. pub common_point: SerializablePublic, diff --git a/secret_store/src/traits.rs b/secret_store/src/traits.rs index 04f2fa1294e..704be1c2545 100644 --- a/secret_store/src/traits.rs +++ b/secret_store/src/traits.rs @@ -94,7 +94,7 @@ pub trait MessageSigner: ServerKeyGenerator { /// Administrative sessions server. pub trait AdminSessionsServer { /// Change servers set so that nodes in new_servers_set became owners of shares for all keys. - /// And old nodes (i.e. cluste nodes except new_servers_set) have clear databases. + /// And old nodes (i.e. cluster nodes except new_servers_set) have clear databases. /// WARNING: newly generated keys will be distributed among all cluster nodes. So this session /// must be followed with cluster nodes change (either via contract, or config files). fn change_servers_set(&self, old_set_signature: RequestSignature, new_set_signature: RequestSignature, new_servers_set: BTreeSet) -> Result<(), Error>; diff --git a/secret_store/src/types/all.rs b/secret_store/src/types/all.rs index bfc58779a6b..ab0aea1b133 100644 --- a/secret_store/src/types/all.rs +++ b/secret_store/src/types/all.rs @@ -94,7 +94,7 @@ pub struct ClusterConfiguration { /// Shadow decryption result. #[derive(Clone, Debug, PartialEq)] pub struct EncryptedDocumentKeyShadow { - /// Decrypted secret point. It is partially decrypted if shadow decrpytion was requested. + /// Decrypted secret point. It is partially decrypted if shadow decryption was requested. pub decrypted_secret: ethkey::Public, /// Shared common point. pub common_point: Option, diff --git a/secret_store/src/types/error.rs b/secret_store/src/types/error.rs index 1fceb120e82..eae914ec866 100644 --- a/secret_store/src/types/error.rs +++ b/secret_store/src/types/error.rs @@ -60,7 +60,7 @@ pub enum Error { /// Document key with this ID is not yet stored. DocumentKeyIsNotFound, /// Consensus is temporary unreachable. Means that something is currently blocking us from either forming - /// consensus group (like disconnecting from too many nodes, which are AGREE to partticipate in consensus) + /// consensus group (like disconnecting from too many nodes, which are AGREE to participate in consensus) /// or from rejecting request (disconnecting from AccessDenied-nodes). ConsensusTemporaryUnreachable, /// Consensus is unreachable. It doesn't mean that it will ALWAYS remain unreachable, but right NOW we have @@ -78,9 +78,9 @@ pub enum Error { InsufficientRequesterData(String), /// Cryptographic error. EthKey(String), - /// I/O error has occured. + /// I/O error has occurred. Io(String), - /// Deserialization error has occured. + /// Deserialization error has occurred. Serde(String), /// Hyper error. Hyper(String), @@ -148,7 +148,7 @@ impl fmt::Display for Error { Error::DocumentKeyIsNotFound => write!(f, "Document key with this ID is not found"), Error::ConsensusUnreachable => write!(f, "Consensus unreachable"), Error::ConsensusTemporaryUnreachable => write!(f, "Consensus temporary unreachable"), - Error::AccessDenied => write!(f, "Access dened"), + Error::AccessDenied => write!(f, "Access denied"), Error::ExclusiveSessionActive => write!(f, "Exclusive session active"), Error::HasActiveSessions => write!(f, "Unable to start exclusive session"), Error::InsufficientRequesterData(ref e) => write!(f, "Insufficient requester data: {}", e), From 30ecd045fa2a1b7f001ca387965d5a296af61d7d Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Wed, 16 May 2018 22:00:33 +0200 Subject: [PATCH 79/95] Changelog for 1.10.4-stable and 1.11.1-beta (#8637) * Add changelog for 1.10.4 * Add changelog for 1.11.1 * Fix Typos --- CHANGELOG.md | 119 ++++++++++++++++++++++++++++++++++++++--- docs/CHANGELOG-1.10.md | 23 ++++++++ 2 files changed, 136 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f839802e7cd..ee66149ed00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,22 +1,22 @@ -## Parity [v1.11.0](https://github.com/paritytech/parity/releases/tag/v1.10.0) (2018-05-09) +## Parity [v1.11.1](https://github.com/paritytech/parity/releases/tag/v1.11.1) (2018-05-15) -This is the Parity 1.11.0-beta release! Hurray! +This is the Parity 1.11.1-beta release! Hurray! Notable changes in reversed alphabetical order: - TOOLING: **Whisper CLI** [#8201](https://github.com/paritytech/parity/pull/8201) - `whisper-cli` is a standalone tool to communicate with the Whisper protocol. - It provides functionality to specify `whisper-pool-size`, `port` and `address` to use. - - All whisper RPC APIs are enabled and can be directly acessed. + - All whisper RPC APIs are enabled and can be directly accessed. - JSON-RPC API: **Return error in case eth_call returns VM errors** [#8448](https://github.com/paritytech/parity/pull/8448) - This changes the behaviors of `eth_call` to respect VM errors if any. - In case of `REVERT`, it will also return the reverted return data in hex format. -- ENGINES: **Block reward contract** [#8419](https://github.com/paritytech/parity/pull/8419) +- ENGINES: **Block Reward Contract** [#8419](https://github.com/paritytech/parity/pull/8419) - The _AuRa_ PoA engine has now support for having a contract to calculate the block rewards. - The engine passes a list of benefactors and reward types to the contract which then returns a list of addresses and respective rewards. -- CORE: **Private transactions integration pr** [#6422](https://github.com/paritytech/parity/pull/6422) +- CORE: **Private Transactions** [#6422](https://github.com/paritytech/parity/pull/6422) - Parity now provides a private transactions system. - - Please, check out our wiki to get and [overview and setup instructions](https://wiki.parity.io/Private-Transactions.html). + - Please, check out our wiki to get an [overview and setup instructions](https://wiki.parity.io/Private-Transactions.html). - CORE: **New Transaction Queue implementation** [#8074](https://github.com/paritytech/parity/pull/8074) - Verification is now done in parallel. - Previous queue had `O(1)` time to get pending set, but `O(n^2)` insertion time. And obviously insertion/removal happens much more often than retrieving the pending set (only for propagation and pending block building) Currently we have `O(n * log(senders))` pending set time (with cache) and `O(tx_per_sender)` (usually within `log(tx_per_sender)`) insertion time. @@ -47,6 +47,113 @@ Notable changes in reversed alphabetical order: The full list of included changes: +- Backports ([#8624](https://github.com/paritytech/parity/pull/8624)) + - Trace precompiled contracts when the transfer value is not zero ([#8486](https://github.com/paritytech/parity/pull/8486)) + - Trace precompiled contracts when the transfer value is not zero + - Add tests for precompiled CALL tracing + - Use byzantium test machine for the new test + - Add notes in comments on why we don't trace all precompiles + - Use is_transferred instead of transferred + - Return error if RLP size of transaction exceeds the limit ([#8473](https://github.com/paritytech/parity/pull/8473)) + - Return error if RLP size of transaction exceeds the limit + - Review comments fixed + - RLP check moved to verifier, corresponding pool test added + - Don't block sync when importing old blocks ([#8530](https://github.com/paritytech/parity/pull/8530)) + - Alter IO queueing. + - Don't require IoMessages to be Clone + - Ancient blocks imported via IoChannel. + - Get rid of private transactions io message. + - Get rid of deadlock and fix disconnected handler. + - Revert to old disconnect condition. + - Fix tests. + - Fix deadlock. + - Refactoring `ethcore-sync` - Fixing warp-sync barrier ([#8543](https://github.com/paritytech/parity/pull/8543)) + - Start dividing sync chain : first supplier method + - WIP - updated chain sync supplier + - Finish refactoring the Chain Sync Supplier + - Create Chain Sync Requester + - Add Propagator for Chain Sync + - Add the Chain Sync Handler + - Move tests from mod -> handler + - Move tests to propagator + - Refactor SyncRequester arguments + - Refactoring peer fork header handler + - Fix wrong highest block number in snapshot sync + - Small refactor... + - Address PR grumbles + - Retry failed CI job + - Fix tests + - PR Grumbles + - Handle socket address parsing errors ([#8545](https://github.com/paritytech/parity/pull/8545)) + - Fix packet count when talking with PAR2 peers ([#8555](https://github.com/paritytech/parity/pull/8555)) + - Support diferent packet counts in different protocol versions. + - Fix light timeouts and eclipse protection. + - Fix devp2p tests. + - Fix whisper-cli compilation. + - Fix compilation. + - Fix ethcore-sync tests. + - Revert "Fix light timeouts and eclipse protection." + - Increase timeouts. + - Add whisper CLI to the pipelines ([#8578](https://github.com/paritytech/parity/pull/8578)) + - Add whisper CLI to the pipelines + - Address todo, ref [#8579](https://github.com/paritytech/parity/pull/8579) + - Rename `whisper-cli binary` to `whisper` ([#8579](https://github.com/paritytech/parity/pull/8579)) + - Rename whisper-cli binary to whisper + - Fix tests + - Remove manually added text to the errors ([#8595](https://github.com/paritytech/parity/pull/8595)) + - Fix account list double 0x display ([#8596](https://github.com/paritytech/parity/pull/8596)) + - Remove unused self import + - Fix account list double 0x display + - Fix BlockReward contract "arithmetic operation overflow" ([#8611](https://github.com/paritytech/parity/pull/8611)) + - Fix BlockReward contract "arithmetic operation overflow" + - Add docs on how execute_as_system works + - Fix typo + - Rlp decode returns Result ([#8527](https://github.com/paritytech/parity/pull/8527)) + - Remove expect ([#8536](https://github.com/paritytech/parity/pull/8536)) + - Remove expect and propagate rlp::DecoderErrors as TrieErrors + - Decoding headers can fail ([#8570](https://github.com/paritytech/parity/pull/8570)) + - Rlp::decode returns Result + - Fix journaldb to handle rlp::decode Result + - Fix ethcore to work with rlp::decode returning Result + - Light client handles rlp::decode returning Result + - Fix tests in rlp_derive + - Fix tests + - Cleanup + - Cleanup + - Allow panic rather than breaking out of iterator + - Let decoding failures when reading from disk blow up + - Syntax + - Fix the trivial grumbles + - Fix failing tests + - Make Account::from_rlp return Result + - Syntx, sigh + - Temp-fix for decoding failures + - Header::decode returns Result + - Do not continue reading from the DB when a value could not be read + - Fix tests + - Handle header decoding in light_sync + - Handling header decoding errors + - Let the DecodeError bubble up unchanged + - Remove redundant error conversion + - Fix compiler warning ([#8590](https://github.com/paritytech/parity/pull/8590)) + - Attempt to fix intermittent test failures ([#8584](https://github.com/paritytech/parity/pull/8584)) + - Block_header can fail so return Result ([#8581](https://github.com/paritytech/parity/pull/8581)) + - Block_header can fail so return Result + - Restore previous return type based on feedback + - Fix failing doc tests running on non-code + - Block::decode() returns Result ([#8586](https://github.com/paritytech/parity/pull/8586)) + - Gitlab test script fixes ([#8573](https://github.com/paritytech/parity/pull/8573)) + - Exclude /docs from modified files. + - Ensure all references in the working tree are available + - Remove duplicated line from test script +- Bump beta to 1.11.1 ([#8627](https://github.com/paritytech/parity/pull/8627)) + +## Parity [v1.11.0](https://github.com/paritytech/parity/releases/tag/v1.11.0) (2018-05-09) + +This is the Parity 1.11.0-beta release! ~~Hurray!~~ This release has been pulled due to peering issues, please use 1.11.1-beta. + +The full list of included changes: + - Backports ([#8558](https://github.com/paritytech/parity/pull/8558)) - Fetching logs by hash in blockchain database ([#8463](https://github.com/paritytech/parity/pull/8463)) - Fetch logs by hash in blockchain database diff --git a/docs/CHANGELOG-1.10.md b/docs/CHANGELOG-1.10.md index 4db8f32bb67..a8c7ad20a75 100644 --- a/docs/CHANGELOG-1.10.md +++ b/docs/CHANGELOG-1.10.md @@ -1,3 +1,26 @@ +## Parity [v1.10.4](https://github.com/paritytech/parity/releases/tag/v1.10.4) (2018-05-15) + +Parity 1.10.4 is a bug-fix release to improve performance and stability. + +The full list of included changes: + +- Backports ([#8623](https://github.com/paritytech/parity/pull/8623)) + - Fix account list double 0x display ([#8596](https://github.com/paritytech/parity/pull/8596)) + - Remove unused self import + - Fix account list double 0x display + - Trace precompiled contracts when the transfer value is not zero ([#8486](https://github.com/paritytech/parity/pull/8486)) + - Trace precompiled contracts when the transfer value is not zero + - Add tests for precompiled CALL tracing + - Use byzantium test machine for the new test + - Add notes in comments on why we don't trace all precompileds + - Use is_transferred instead of transferred + - Gitlab test script fixes ([#8573](https://github.com/paritytech/parity/pull/8573)) + - Exclude /docs from modified files. + - Ensure all references in the working tree are available + - Remove duplicated line from test script +- Bump stable to 1.10.4 ([#8626](https://github.com/paritytech/parity/pull/8626)) +- Allow stable snaps to be stable. ([#8582](https://github.com/paritytech/parity/pull/8582)) + ## Parity [v1.10.3](https://github.com/paritytech/parity/releases/tag/v1.10.3) (2018-05-08) Parity 1.10.3 marks the first stable release on the 1.10 track. Among others, it improves performance and stability. From 6ecc855c3433403e5d54910cdc6c44700d7b4ab7 Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Wed, 16 May 2018 22:01:11 +0200 Subject: [PATCH 80/95] Don't open Browser post-install on Mac (#8641) Since we start parity with the UI disabled per default now, opening the browser post installation will show an annoying error message, confusing the user. This patch removes opening the browser to prevent that annoyance. fixes #8194 --- mac/post-install.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/mac/post-install.sh b/mac/post-install.sh index a364878d889..fc71ee1de6d 100755 --- a/mac/post-install.sh +++ b/mac/post-install.sh @@ -3,6 +3,4 @@ test -f /usr/local/libexec/uninstall-parity.sh && /usr/local/libexec/uninstall-parity.sh || true killall -9 parity && sleep 5 su $USER -c "open /Applications/Parity\ Ethereum.app" -sleep 5 -su $USER -c "open http://127.0.0.1:8180/" exit 0 From cdbcfaa7de55731f4e1eb2613f72c980fba1e0f7 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Wed, 16 May 2018 22:01:55 +0200 Subject: [PATCH 81/95] Resumable warp-sync / Seed downloaded snapshots (#8544) * Start dividing sync chain : first supplier method * WIP - updated chain sync supplier * Finish refactoring the Chain Sync Supplier * Create Chain Sync Requester * Add Propagator for Chain Sync * Add the Chain Sync Handler * Move tests from mod -> handler * Move tests to propagator * Refactor SyncRequester arguments * Refactoring peer fork header handler * Fix wrong highest block number in snapshot sync * Small refactor... * Resume warp-sync downloaded chunks * Add comments * Refactoring the previous chunks import * Fix tests * Address PR grumbles * Fix not seeding current snapshot * Address PR Grumbles * Address PR grumble * Retry failed CI job * Update SnapshotService readiness check Fix restoration locking issue for previous chunks restoration * Fix tests * Fix tests * Fix test * Early abort importing previous chunks * PR Grumbles * Update Gitlab CI config * SyncState back to Waiting when Manifest peers disconnect * Move fix * Better fix * Revert GitLab CI changes * Fix Warning * Refactor resuming snapshots * Fix string construction * Revert "Refactor resuming snapshots" This reverts commit 75fd4b553a38e4a49dc5d6a878c70e830ff382eb. * Update informant log * Fix string construction * Refactor resuming snapshots * Fix informant * PR Grumbles * Update informant message : show chunks done * PR Grumbles * Fix * Fix Warning * PR Grumbles --- ethcore/src/snapshot/service.rs | 165 ++++++++++++++++--- ethcore/src/snapshot/tests/service.rs | 8 +- ethcore/src/snapshot/traits.rs | 3 + ethcore/sync/src/chain/handler.rs | 52 ++++-- ethcore/sync/src/chain/mod.rs | 104 +++++++----- ethcore/sync/src/chain/supplier.rs | 26 +-- ethcore/sync/src/snapshot.rs | 71 ++++++-- ethcore/sync/src/tests/snapshot.rs | 4 + ethcore/types/src/restoration_status.rs | 5 + parity/informant.rs | 23 ++- parity/snapshot.rs | 1 + rpc/src/v1/tests/helpers/snapshot_service.rs | 1 + 12 files changed, 361 insertions(+), 102 deletions(-) diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index c5b9123e10f..17c362e0440 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -17,8 +17,8 @@ //! Snapshot network service implementation. use std::collections::HashSet; -use std::io::ErrorKind; -use std::fs; +use std::io::{self, Read, ErrorKind}; +use std::fs::{self, File}; use std::path::PathBuf; use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; @@ -30,6 +30,7 @@ use blockchain::BlockChain; use client::{Client, ChainInfo, ClientIoMessage}; use engines::EthEngine; use error::Error; +use hash::keccak; use ids::BlockId; use io::IoChannel; @@ -270,8 +271,8 @@ impl Service { } } - // delete the temporary restoration dir if it does exist. - if let Err(e) = fs::remove_dir_all(service.restoration_dir()) { + // delete the temporary restoration DB dir if it does exist. + if let Err(e) = fs::remove_dir_all(service.restoration_db()) { if e.kind() != ErrorKind::NotFound { return Err(e.into()) } @@ -325,6 +326,13 @@ impl Service { dir } + // previous snapshot chunks path. + fn prev_chunks_dir(&self) -> PathBuf { + let mut dir = self.snapshot_root.clone(); + dir.push("prev_chunks"); + dir + } + // replace one the client's database with our own. fn replace_client_db(&self) -> Result<(), Error> { let our_db = self.restoration_db(); @@ -406,9 +414,26 @@ impl Service { /// Initialize the restoration synchronously. /// The recover flag indicates whether to recover the restored snapshot. pub fn init_restore(&self, manifest: ManifestData, recover: bool) -> Result<(), Error> { + let mut res = self.restoration.lock(); + let rest_dir = self.restoration_dir(); + let rest_db = self.restoration_db(); + let recovery_temp = self.temp_recovery_dir(); + let prev_chunks = self.prev_chunks_dir(); - let mut res = self.restoration.lock(); + // delete and restore the restoration dir. + if let Err(e) = fs::remove_dir_all(&prev_chunks) { + match e.kind() { + ErrorKind::NotFound => {}, + _ => return Err(e.into()), + } + } + + // Move the previous recovery temp directory + // to `prev_chunks` to be able to restart restoring + // with previously downloaded blocks + // This step is optional, so don't fail on error + fs::rename(&recovery_temp, &prev_chunks).ok(); self.state_chunks.store(0, Ordering::SeqCst); self.block_chunks.store(0, Ordering::SeqCst); @@ -424,29 +449,38 @@ impl Service { } } + *self.status.lock() = RestorationStatus::Initializing { + chunks_done: 0, + }; + fs::create_dir_all(&rest_dir)?; // make new restoration. let writer = match recover { - true => Some(LooseWriter::new(self.temp_recovery_dir())?), + true => Some(LooseWriter::new(recovery_temp)?), false => None }; let params = RestorationParams { - manifest: manifest, + manifest: manifest.clone(), pruning: self.pruning, - db: self.restoration_db_handler.open(&self.restoration_db())?, + db: self.restoration_db_handler.open(&rest_db)?, writer: writer, genesis: &self.genesis_block, - guard: Guard::new(rest_dir), + guard: Guard::new(rest_db), engine: &*self.engine, }; - let state_chunks = params.manifest.state_hashes.len(); - let block_chunks = params.manifest.block_hashes.len(); + let state_chunks = manifest.state_hashes.len(); + let block_chunks = manifest.block_hashes.len(); *res = Some(Restoration::new(params)?); + self.restoring_snapshot.store(true, Ordering::SeqCst); + + // Import previous chunks, continue if it fails + self.import_prev_chunks(&mut res, manifest).ok(); + *self.status.lock() = RestorationStatus::Ongoing { state_chunks: state_chunks as u32, block_chunks: block_chunks as u32, @@ -454,10 +488,65 @@ impl Service { block_chunks_done: self.block_chunks.load(Ordering::SeqCst) as u32, }; - self.restoring_snapshot.store(true, Ordering::SeqCst); Ok(()) } + /// Import the previous chunks into the current restoration + fn import_prev_chunks(&self, restoration: &mut Option, manifest: ManifestData) -> Result<(), Error> { + let prev_chunks = self.prev_chunks_dir(); + + // Restore previous snapshot chunks + let files = fs::read_dir(prev_chunks.as_path())?; + let mut num_temp_chunks = 0; + + for prev_chunk_file in files { + // Don't go over all the files if the restoration has been aborted + if !self.restoring_snapshot.load(Ordering::SeqCst) { + trace!(target:"snapshot", "Aborting importing previous chunks"); + return Ok(()); + } + // Import the chunk, don't fail and continue if one fails + match self.import_prev_chunk(restoration, &manifest, prev_chunk_file) { + Ok(true) => num_temp_chunks += 1, + Err(e) => trace!(target: "snapshot", "Error importing chunk: {:?}", e), + _ => (), + } + } + + trace!(target:"snapshot", "Imported {} previous chunks", num_temp_chunks); + + // Remove the prev temp directory + fs::remove_dir_all(&prev_chunks)?; + + Ok(()) + } + + /// Import a previous chunk at the given path. Returns whether the block was imported or not + fn import_prev_chunk(&self, restoration: &mut Option, manifest: &ManifestData, file: io::Result) -> Result { + let file = file?; + let path = file.path(); + + let mut file = File::open(path.clone())?; + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer)?; + + let hash = keccak(&buffer); + + let is_state = if manifest.block_hashes.contains(&hash) { + false + } else if manifest.state_hashes.contains(&hash) { + true + } else { + return Ok(false); + }; + + self.feed_chunk_with_restoration(restoration, hash, &buffer, is_state)?; + + trace!(target: "snapshot", "Fed chunk {:?}", hash); + + Ok(true) + } + // finalize the restoration. this accepts an already-locked // restoration as an argument -- so acquiring it again _will_ // lead to deadlock. @@ -499,12 +588,19 @@ impl Service { /// Feed a chunk of either kind. no-op if no restoration or status is wrong. fn feed_chunk(&self, hash: H256, chunk: &[u8], is_state: bool) -> Result<(), Error> { // TODO: be able to process block chunks and state chunks at same time? - let (result, db) = { - let mut restoration = self.restoration.lock(); + let mut restoration = self.restoration.lock(); + self.feed_chunk_with_restoration(&mut restoration, hash, chunk, is_state) + } + /// Feed a chunk with the Restoration + fn feed_chunk_with_restoration(&self, restoration: &mut Option, hash: H256, chunk: &[u8], is_state: bool) -> Result<(), Error> { + let (result, db) = { match self.status() { - RestorationStatus::Inactive | RestorationStatus::Failed => return Ok(()), - RestorationStatus::Ongoing { .. } => { + RestorationStatus::Inactive | RestorationStatus::Failed => { + trace!(target: "snapshot", "Tried to restore chunk {:x} while inactive or failed", hash); + return Ok(()); + }, + RestorationStatus::Ongoing { .. } | RestorationStatus::Initializing { .. } => { let (res, db) = { let rest = match *restoration { Some(ref mut r) => r, @@ -583,11 +679,41 @@ impl SnapshotService for Service { self.reader.read().as_ref().and_then(|r| r.chunk(hash).ok()) } + fn completed_chunks(&self) -> Option> { + let restoration = self.restoration.lock(); + + match *restoration { + Some(ref restoration) => { + let completed_chunks = restoration.manifest.block_hashes + .iter() + .filter(|h| !restoration.block_chunks_left.contains(h)) + .chain( + restoration.manifest.state_hashes + .iter() + .filter(|h| !restoration.state_chunks_left.contains(h)) + ) + .map(|h| *h) + .collect(); + + Some(completed_chunks) + }, + None => None, + } + } + fn status(&self) -> RestorationStatus { let mut cur_status = self.status.lock(); - if let RestorationStatus::Ongoing { ref mut state_chunks_done, ref mut block_chunks_done, .. } = *cur_status { - *state_chunks_done = self.state_chunks.load(Ordering::SeqCst) as u32; - *block_chunks_done = self.block_chunks.load(Ordering::SeqCst) as u32; + + match *cur_status { + RestorationStatus::Initializing { ref mut chunks_done } => { + *chunks_done = self.state_chunks.load(Ordering::SeqCst) as u32 + + self.block_chunks.load(Ordering::SeqCst) as u32; + } + RestorationStatus::Ongoing { ref mut state_chunks_done, ref mut block_chunks_done, .. } => { + *state_chunks_done = self.state_chunks.load(Ordering::SeqCst) as u32; + *block_chunks_done = self.block_chunks.load(Ordering::SeqCst) as u32; + }, + _ => (), } cur_status.clone() @@ -600,6 +726,7 @@ impl SnapshotService for Service { } fn abort_restore(&self) { + trace!(target: "snapshot", "Aborting restore"); self.restoring_snapshot.store(false, Ordering::SeqCst); *self.restoration.lock() = None; *self.status.lock() = RestorationStatus::Inactive; diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 3e3087f2bf7..3fcb0addfab 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -130,12 +130,16 @@ fn guards_delete_folders() { service.init_restore(manifest.clone(), true).unwrap(); assert!(path.exists()); + // The `db` folder should have been deleted, + // while the `temp` one kept service.abort_restore(); - assert!(!path.exists()); + assert!(!path.join("db").exists()); + assert!(path.join("temp").exists()); service.init_restore(manifest.clone(), true).unwrap(); assert!(path.exists()); drop(service); - assert!(!path.exists()); + assert!(!path.join("db").exists()); + assert!(path.join("temp").exists()); } diff --git a/ethcore/src/snapshot/traits.rs b/ethcore/src/snapshot/traits.rs index a81c14f08d5..2b6ee9df9f4 100644 --- a/ethcore/src/snapshot/traits.rs +++ b/ethcore/src/snapshot/traits.rs @@ -30,6 +30,9 @@ pub trait SnapshotService : Sync + Send { /// `None` indicates warp sync isn't supported by the consensus engine. fn supported_versions(&self) -> Option<(u64, u64)>; + /// Returns a list of the completed chunks + fn completed_chunks(&self) -> Option>; + /// Get raw chunk for a given hash. fn chunk(&self, hash: H256) -> Option; diff --git a/ethcore/sync/src/chain/handler.rs b/ethcore/sync/src/chain/handler.rs index a55c0319b37..7668a645945 100644 --- a/ethcore/sync/src/chain/handler.rs +++ b/ethcore/sync/src/chain/handler.rs @@ -100,14 +100,27 @@ impl SyncHandler { } /// Called by peer when it is disconnecting - pub fn on_peer_aborting(sync: &mut ChainSync, io: &mut SyncIo, peer: PeerId) { - trace!(target: "sync", "== Disconnecting {}: {}", peer, io.peer_info(peer)); - sync.handshaking_peers.remove(&peer); - if sync.peers.contains_key(&peer) { - debug!(target: "sync", "Disconnected {}", peer); - sync.clear_peer_download(peer); - sync.peers.remove(&peer); - sync.active_peers.remove(&peer); + pub fn on_peer_aborting(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId) { + trace!(target: "sync", "== Disconnecting {}: {}", peer_id, io.peer_info(peer_id)); + sync.handshaking_peers.remove(&peer_id); + if sync.peers.contains_key(&peer_id) { + debug!(target: "sync", "Disconnected {}", peer_id); + sync.clear_peer_download(peer_id); + sync.peers.remove(&peer_id); + sync.active_peers.remove(&peer_id); + + if sync.state == SyncState::SnapshotManifest { + // Check if we are asking other peers for + // the snapshot manifest as well. + // If not, return to initial state + let still_asking_manifest = sync.peers.iter() + .filter(|&(id, p)| sync.active_peers.contains(id) && p.asking == PeerAsking::SnapshotManifest) + .next().is_none(); + + if still_asking_manifest { + sync.state = ChainSync::get_init_state(sync.warp_sync, io.chain()); + } + } sync.continue_sync(io); } } @@ -320,6 +333,10 @@ impl SyncHandler { } fn on_peer_confirmed(sync: &mut ChainSync, io: &mut SyncIo, peer_id: PeerId) { + { + let peer = sync.peers.get_mut(&peer_id).expect("Is only called when peer is present in peers"); + peer.confirmation = ForkConfirmation::Confirmed; + } sync.sync_peer(io, peer_id, false); } @@ -344,8 +361,8 @@ impl SyncHandler { } trace!(target: "sync", "{}: Confirmed peer", peer_id); - peer.confirmation = ForkConfirmation::Confirmed; if !io.chain_overlay().read().contains_key(&fork_number) { + trace!(target: "sync", "Inserting (fork) block {} header", fork_number); io.chain_overlay().write().insert(fork_number, header.to_vec()); } } @@ -560,6 +577,10 @@ impl SyncHandler { sync.continue_sync(io); return Ok(()); }, + RestorationStatus::Initializing { .. } => { + trace!(target: "warp", "{}: Snapshot restoration is initializing", peer_id); + return Ok(()); + } RestorationStatus::Ongoing { .. } => { trace!(target: "sync", "{}: Snapshot restoration is ongoing", peer_id); }, @@ -659,11 +680,16 @@ impl SyncHandler { // Let the current sync round complete first. sync.active_peers.insert(peer_id.clone()); debug!(target: "sync", "Connected {}:{}", peer_id, io.peer_info(peer_id)); - if let Some((fork_block, _)) = sync.fork_block { - SyncRequester::request_fork_header(sync, io, peer_id, fork_block); - } else { - SyncHandler::on_peer_confirmed(sync, io, peer_id); + + match sync.fork_block { + Some((fork_block, _)) => { + SyncRequester::request_fork_header(sync, io, peer_id, fork_block); + }, + _ => { + SyncHandler::on_peer_confirmed(sync, io, peer_id); + } } + Ok(()) } diff --git a/ethcore/sync/src/chain/mod.rs b/ethcore/sync/src/chain/mod.rs index 381936949bd..5af28925493 100644 --- a/ethcore/sync/src/chain/mod.rs +++ b/ethcore/sync/src/chain/mod.rs @@ -245,9 +245,12 @@ pub struct SyncStatus { impl SyncStatus { /// Indicates if snapshot download is in progress pub fn is_snapshot_syncing(&self) -> bool { - self.state == SyncState::SnapshotManifest - || self.state == SyncState::SnapshotData - || self.state == SyncState::SnapshotWaiting + match self.state { + SyncState::SnapshotManifest | + SyncState::SnapshotData | + SyncState::SnapshotWaiting => true, + _ => false, + } } /// Returns max no of peers to display in informants @@ -643,7 +646,7 @@ impl ChainSync { } } - /// Resume downloading + /// Resume downloading fn continue_sync(&mut self, io: &mut SyncIo) { // Collect active peers that can sync let confirmed_peers: Vec<(PeerId, u8)> = self.peers.iter().filter_map(|(peer_id, peer)| @@ -751,26 +754,45 @@ impl ChainSync { } } - if let Some(request) = self.old_blocks.as_mut().and_then(|d| d.request_blocks(io, num_active_peers)) { - SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks); - return; + // Only ask for old blocks if the peer has a higher difficulty + if force || higher_difficulty { + if let Some(request) = self.old_blocks.as_mut().and_then(|d| d.request_blocks(io, num_active_peers)) { + SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks); + return; + } + } else { + trace!(target: "sync", "peer {} is not suitable for asking old blocks", peer_id); + self.deactivate_peer(io, peer_id); } }, SyncState::SnapshotData => { - if let RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } = io.snapshot_service().status() { - if self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize > MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { - trace!(target: "sync", "Snapshot queue full, pausing sync"); - self.state = SyncState::SnapshotWaiting; + match io.snapshot_service().status() { + RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } => { + // Initialize the snapshot if not already done + self.snapshot.initialize(io.snapshot_service()); + if self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize > MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { + trace!(target: "sync", "Snapshot queue full, pausing sync"); + self.state = SyncState::SnapshotWaiting; + return; + } + }, + RestorationStatus::Initializing { .. } => { + trace!(target: "warp", "Snapshot is stil initializing."); return; - } + }, + _ => { + return; + }, } + if peer_snapshot_hash.is_some() && peer_snapshot_hash == self.snapshot.snapshot_hash() { self.clear_peer_download(peer_id); SyncRequester::request_snapshot_data(self, io, peer_id); } }, SyncState::SnapshotManifest | //already downloading from other peer - SyncState::Waiting | SyncState::SnapshotWaiting => () + SyncState::Waiting | + SyncState::SnapshotWaiting => () } } else { trace!(target: "sync", "Skipping peer {}, force={}, td={:?}, our td={}, state={:?}", peer_id, force, peer_difficulty, syncing_difficulty, self.state); @@ -861,10 +883,7 @@ impl ChainSync { packet.append(&chain.best_block_hash); packet.append(&chain.genesis_hash); if warp_protocol { - let manifest = match self.old_blocks.is_some() { - true => None, - false => io.snapshot_service().manifest(), - }; + let manifest = io.snapshot_service().manifest(); let block_number = manifest.as_ref().map_or(0, |m| m.block_number); let manifest_hash = manifest.map_or(H256::new(), |m| keccak(m.into_rlp())); packet.append(&manifest_hash); @@ -908,29 +927,36 @@ impl ChainSync { } fn check_resume(&mut self, io: &mut SyncIo) { - if self.state == SyncState::Waiting && !io.chain().queue_info().is_full() { - self.state = SyncState::Blocks; - self.continue_sync(io); - } else if self.state == SyncState::SnapshotWaiting { - match io.snapshot_service().status() { - RestorationStatus::Inactive => { - trace!(target:"sync", "Snapshot restoration is complete"); - self.restart(io); - }, - RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } => { - if !self.snapshot.is_complete() && self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize <= MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { - trace!(target:"sync", "Resuming snapshot sync"); - self.state = SyncState::SnapshotData; + match self.state { + SyncState::Waiting if !io.chain().queue_info().is_full() => { + self.state = SyncState::Blocks; + self.continue_sync(io); + }, + SyncState::SnapshotWaiting => { + match io.snapshot_service().status() { + RestorationStatus::Inactive => { + trace!(target:"sync", "Snapshot restoration is complete"); + self.restart(io); + }, + RestorationStatus::Initializing { .. } => { + trace!(target:"sync", "Snapshot restoration is initializing"); + }, + RestorationStatus::Ongoing { state_chunks_done, block_chunks_done, .. } => { + if !self.snapshot.is_complete() && self.snapshot.done_chunks() - (state_chunks_done + block_chunks_done) as usize <= MAX_SNAPSHOT_CHUNKS_DOWNLOAD_AHEAD { + trace!(target:"sync", "Resuming snapshot sync"); + self.state = SyncState::SnapshotData; + self.continue_sync(io); + } + }, + RestorationStatus::Failed => { + trace!(target: "sync", "Snapshot restoration aborted"); + self.state = SyncState::WaitingPeers; + self.snapshot.clear(); self.continue_sync(io); - } - }, - RestorationStatus::Failed => { - trace!(target: "sync", "Snapshot restoration aborted"); - self.state = SyncState::WaitingPeers; - self.snapshot.clear(); - self.continue_sync(io); - }, - } + }, + } + }, + _ => (), } } diff --git a/ethcore/sync/src/chain/supplier.rs b/ethcore/sync/src/chain/supplier.rs index 0bfb8569823..e0245fdbcd9 100644 --- a/ethcore/sync/src/chain/supplier.rs +++ b/ethcore/sync/src/chain/supplier.rs @@ -120,8 +120,9 @@ impl SyncSupplier { None => return Ok(Some((BLOCK_HEADERS_PACKET, RlpStream::new_list(0)))) //no such header, return nothing } } else { - trace!(target: "sync", "{} -> GetBlockHeaders (number: {}, max: {}, skip: {}, reverse:{})", peer_id, r.val_at::(0)?, max_headers, skip, reverse); - r.val_at(0)? + let number = r.val_at::(0)?; + trace!(target: "sync", "{} -> GetBlockHeaders (number: {}, max: {}, skip: {}, reverse:{})", peer_id, number, max_headers, skip, reverse); + number }; let mut number = if reverse { @@ -135,7 +136,10 @@ impl SyncSupplier { let inc = (skip + 1) as BlockNumber; let overlay = io.chain_overlay().read(); - while number <= last && count < max_count { + // We are checking the `overlay` as well since it's where the ForkBlock + // header is cached : so peers can confirm we are on the right fork, + // even if we are not synced until the fork block + while (number <= last || overlay.contains_key(&number)) && count < max_count { if let Some(hdr) = overlay.get(&number) { trace!(target: "sync", "{}: Returning cached fork header", peer_id); data.extend_from_slice(hdr); @@ -152,8 +156,7 @@ impl SyncSupplier { break; } number -= inc; - } - else { + } else { number += inc; } } @@ -237,20 +240,20 @@ impl SyncSupplier { /// Respond to GetSnapshotManifest request fn return_snapshot_manifest(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { let count = r.item_count().unwrap_or(0); - trace!(target: "sync", "{} -> GetSnapshotManifest", peer_id); + trace!(target: "warp", "{} -> GetSnapshotManifest", peer_id); if count != 0 { - debug!(target: "sync", "Invalid GetSnapshotManifest request, ignoring."); + debug!(target: "warp", "Invalid GetSnapshotManifest request, ignoring."); return Ok(None); } let rlp = match io.snapshot_service().manifest() { Some(manifest) => { - trace!(target: "sync", "{} <- SnapshotManifest", peer_id); + trace!(target: "warp", "{} <- SnapshotManifest", peer_id); let mut rlp = RlpStream::new_list(1); rlp.append_raw(&manifest.into_rlp(), 1); rlp }, None => { - trace!(target: "sync", "{}: No manifest to return", peer_id); + trace!(target: "warp", "{}: No snapshot manifest to return", peer_id); RlpStream::new_list(0) } }; @@ -260,15 +263,16 @@ impl SyncSupplier { /// Respond to GetSnapshotData request fn return_snapshot_data(io: &SyncIo, r: &Rlp, peer_id: PeerId) -> RlpResponseResult { let hash: H256 = r.val_at(0)?; - trace!(target: "sync", "{} -> GetSnapshotData {:?}", peer_id, hash); + trace!(target: "warp", "{} -> GetSnapshotData {:?}", peer_id, hash); let rlp = match io.snapshot_service().chunk(hash) { Some(data) => { let mut rlp = RlpStream::new_list(1); - trace!(target: "sync", "{} <- SnapshotData", peer_id); + trace!(target: "warp", "{} <- SnapshotData", peer_id); rlp.append(&data); rlp }, None => { + trace!(target: "warp", "{}: No snapshot data to return", peer_id); RlpStream::new_list(0) } }; diff --git a/ethcore/sync/src/snapshot.rs b/ethcore/sync/src/snapshot.rs index 917e84c8846..b603a2a007a 100644 --- a/ethcore/sync/src/snapshot.rs +++ b/ethcore/sync/src/snapshot.rs @@ -14,10 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use hash::keccak; +use ethcore::snapshot::{ManifestData, SnapshotService}; use ethereum_types::H256; +use hash::keccak; +use rand::{thread_rng, Rng}; + use std::collections::HashSet; -use ethcore::snapshot::ManifestData; +use std::iter::FromIterator; #[derive(PartialEq, Eq, Debug)] pub enum ChunkType { @@ -32,6 +35,7 @@ pub struct Snapshot { completed_chunks: HashSet, snapshot_hash: Option, bad_hashes: HashSet, + initialized: bool, } impl Snapshot { @@ -44,7 +48,27 @@ impl Snapshot { completed_chunks: HashSet::new(), snapshot_hash: None, bad_hashes: HashSet::new(), + initialized: false, + } + } + + /// Sync the Snapshot completed chunks with the Snapshot Service + pub fn initialize(&mut self, snapshot_service: &SnapshotService) { + if self.initialized { + return; + } + + if let Some(completed_chunks) = snapshot_service.completed_chunks() { + self.completed_chunks = HashSet::from_iter(completed_chunks); } + + trace!( + target: "snapshot", + "Snapshot is now initialized with {} completed chunks.", + self.completed_chunks.len(), + ); + + self.initialized = true; } /// Clear everything. @@ -54,6 +78,7 @@ impl Snapshot { self.downloading_chunks.clear(); self.completed_chunks.clear(); self.snapshot_hash = None; + self.initialized = false; } /// Check if currently downloading a snapshot. @@ -89,18 +114,35 @@ impl Snapshot { Err(()) } - /// Find a chunk to download + /// Find a random chunk to download pub fn needed_chunk(&mut self) -> Option { - // check state chunks first - let chunk = self.pending_state_chunks.iter() - .chain(self.pending_block_chunks.iter()) - .find(|&h| !self.downloading_chunks.contains(h) && !self.completed_chunks.contains(h)) - .cloned(); + // Find all random chunks: first blocks, then state + let needed_chunks = { + let chunk_filter = |h| !self.downloading_chunks.contains(h) && !self.completed_chunks.contains(h); + + let needed_block_chunks = self.pending_block_chunks.iter() + .filter(|&h| chunk_filter(h)) + .map(|h| *h) + .collect::>(); + + // If no block chunks to download, get the state chunks + if needed_block_chunks.len() == 0 { + self.pending_state_chunks.iter() + .filter(|&h| chunk_filter(h)) + .map(|h| *h) + .collect::>() + } else { + needed_block_chunks + } + }; + + // Get a random chunk + let chunk = thread_rng().choose(&needed_chunks); if let Some(hash) = chunk { self.downloading_chunks.insert(hash.clone()); } - chunk + chunk.map(|h| *h) } pub fn clear_chunk_download(&mut self, hash: &H256) { @@ -185,8 +227,15 @@ mod test { let requested: Vec = (0..40).map(|_| snapshot.needed_chunk().unwrap()).collect(); assert!(snapshot.needed_chunk().is_none()); - assert_eq!(&requested[0..20], &manifest.state_hashes[..]); - assert_eq!(&requested[20..40], &manifest.block_hashes[..]); + + let requested_all_block_chunks = manifest.block_hashes.iter() + .all(|h| requested.iter().any(|rh| rh == h)); + assert!(requested_all_block_chunks); + + let requested_all_state_chunks = manifest.state_hashes.iter() + .all(|h| requested.iter().any(|rh| rh == h)); + assert!(requested_all_state_chunks); + assert_eq!(snapshot.downloading_chunks.len(), 40); assert_eq!(snapshot.validate_chunk(&state_chunks[4]), Ok(ChunkType::State(manifest.state_hashes[4].clone()))); diff --git a/ethcore/sync/src/tests/snapshot.rs b/ethcore/sync/src/tests/snapshot.rs index 804ebe9c535..864f3d4dc6e 100644 --- a/ethcore/sync/src/tests/snapshot.rs +++ b/ethcore/sync/src/tests/snapshot.rs @@ -80,6 +80,10 @@ impl SnapshotService for TestSnapshotService { Some((1, 2)) } + fn completed_chunks(&self) -> Option> { + Some(vec![]) + } + fn chunk(&self, hash: H256) -> Option { self.chunks.get(&hash).cloned() } diff --git a/ethcore/types/src/restoration_status.rs b/ethcore/types/src/restoration_status.rs index 0cc7fccc08e..51f5b8aa0a3 100644 --- a/ethcore/types/src/restoration_status.rs +++ b/ethcore/types/src/restoration_status.rs @@ -21,6 +21,11 @@ pub enum RestorationStatus { /// No restoration. Inactive, + /// Restoration is initalizing + Initializing { + /// Number of chunks done/imported + chunks_done: u32, + }, /// Ongoing restoration. Ongoing { /// Total number of state chunks. diff --git a/parity/informant.rs b/parity/informant.rs index beeb258b522..a4d2727c359 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -278,15 +278,12 @@ impl Informant { } = full_report; let rpc_stats = self.rpc_stats.as_ref(); - - let (snapshot_sync, snapshot_current, snapshot_total) = self.snapshot.as_ref().map_or((false, 0, 0), |s| + let snapshot_sync = sync_info.as_ref().map_or(false, |s| s.snapshot_sync) && self.snapshot.as_ref().map_or(false, |s| match s.status() { - RestorationStatus::Ongoing { state_chunks, block_chunks, state_chunks_done, block_chunks_done } => - (true, state_chunks_done + block_chunks_done, state_chunks + block_chunks), - _ => (false, 0, 0), + RestorationStatus::Ongoing { .. } | RestorationStatus::Initializing { .. } => true, + _ => false, } ); - let snapshot_sync = snapshot_sync && sync_info.as_ref().map_or(false, |s| s.snapshot_sync); if !importing && !snapshot_sync && elapsed < Duration::from_secs(30) { return; } @@ -318,7 +315,19 @@ impl Informant { paint(Green.bold(), format!("{:5}", queue_info.unverified_queue_size)), paint(Green.bold(), format!("{:5}", queue_info.verified_queue_size)) ), - true => format!("Syncing snapshot {}/{}", snapshot_current, snapshot_total), + true => { + self.snapshot.as_ref().map_or(String::new(), |s| + match s.status() { + RestorationStatus::Ongoing { state_chunks, block_chunks, state_chunks_done, block_chunks_done } => { + format!("Syncing snapshot {}/{}", state_chunks_done + block_chunks_done, state_chunks + block_chunks) + }, + RestorationStatus::Initializing { chunks_done } => { + format!("Snapshot initializing ({} chunks restored)", chunks_done) + }, + _ => String::new(), + } + ) + }, }, false => String::new(), }, diff --git a/parity/snapshot.rs b/parity/snapshot.rs index 423864679a2..3c0dadedaa3 100644 --- a/parity/snapshot.rs +++ b/parity/snapshot.rs @@ -122,6 +122,7 @@ fn restore_using(snapshot: Arc, reader: &R, match snapshot.status() { RestorationStatus::Ongoing { .. } => Err("Snapshot file is incomplete and missing chunks.".into()), + RestorationStatus::Initializing { .. } => Err("Snapshot restoration is still initializing.".into()), RestorationStatus::Failed => Err("Snapshot restoration failed.".into()), RestorationStatus::Inactive => { info!("Restoration complete."); diff --git a/rpc/src/v1/tests/helpers/snapshot_service.rs b/rpc/src/v1/tests/helpers/snapshot_service.rs index 25abab578e9..099773ab522 100644 --- a/rpc/src/v1/tests/helpers/snapshot_service.rs +++ b/rpc/src/v1/tests/helpers/snapshot_service.rs @@ -43,6 +43,7 @@ impl TestSnapshotService { impl SnapshotService for TestSnapshotService { fn manifest(&self) -> Option { None } fn supported_versions(&self) -> Option<(u64, u64)> { None } + fn completed_chunks(&self) -> Option> { Some(vec![]) } fn chunk(&self, _hash: H256) -> Option { None } fn status(&self) -> RestorationStatus { self.status.lock().clone() } fn begin_restore(&self, _manifest: ManifestData) { } From d1934363e7c2c953f17cd451bea8476f46f52b82 Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Thu, 17 May 2018 10:58:35 +0200 Subject: [PATCH 82/95] Fix not downloading old blocks (#8642) --- ethcore/src/client/client.rs | 62 +++++++++++++++++++++++------------- ethcore/sync/src/blocks.rs | 2 +- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 993ecdda216..5cfe8fce82c 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -17,7 +17,7 @@ use std::collections::{HashSet, BTreeMap, BTreeSet, VecDeque}; use std::fmt; use std::str::FromStr; -use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; +use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; use std::sync::{Arc, Weak}; use std::time::{Instant, Duration}; @@ -210,6 +210,8 @@ pub struct Client { queue_transactions: IoChannelQueue, /// Ancient blocks import queue queue_ancient_blocks: IoChannelQueue, + /// Hashes of pending ancient block wainting to be included + pending_ancient_blocks: RwLock>, /// Consensus messages import queue queue_consensus_message: IoChannelQueue, @@ -433,6 +435,7 @@ impl Importer { let hash = header.hash(); let _import_lock = self.import_lock.lock(); + trace!(target: "client", "Trying to import old block #{}", header.number()); { trace_time!("import_old_block"); // verify the block, passing the chain for updating the epoch verifier. @@ -761,6 +764,7 @@ impl Client { notify: RwLock::new(Vec::new()), queue_transactions: IoChannelQueue::new(MAX_TX_QUEUE_SIZE), queue_ancient_blocks: IoChannelQueue::new(MAX_ANCIENT_BLOCKS_QUEUE_SIZE), + pending_ancient_blocks: RwLock::new(HashSet::new()), queue_consensus_message: IoChannelQueue::new(usize::max_value()), last_hashes: RwLock::new(VecDeque::new()), factories: factories, @@ -2008,7 +2012,7 @@ impl BlockChainClient for Client { impl IoClient for Client { fn queue_transactions(&self, transactions: Vec, peer_id: usize) { let len = transactions.len(); - self.queue_transactions.queue(&mut self.io_channel.lock(), len, move |client| { + self.queue_transactions.queue(&mut self.io_channel.lock(), move |client| { trace_time!("import_queued_transactions"); let txs: Vec = transactions @@ -2032,23 +2036,32 @@ impl IoClient for Client { { // check block order - if self.chain.read().is_known(&header.hash()) { + if self.chain.read().is_known(&hash) { bail!(BlockImportErrorKind::Import(ImportErrorKind::AlreadyInChain)); } - let status = self.block_status(BlockId::Hash(*header.parent_hash())); - if status == BlockStatus::Unknown || status == BlockStatus::Pending { - bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(*header.parent_hash()))); + + let parent_hash = *header.parent_hash(); + let parent_pending = self.pending_ancient_blocks.read().contains(&parent_hash); + let status = self.block_status(BlockId::Hash(parent_hash)); + if !parent_pending && (status == BlockStatus::Unknown || status == BlockStatus::Pending) { + bail!(BlockImportErrorKind::Block(BlockError::UnknownParent(parent_hash))); } } - match self.queue_ancient_blocks.queue(&mut self.io_channel.lock(), 1, move |client| { - client.importer.import_old_block( + self.pending_ancient_blocks.write().insert(hash); + + trace!(target: "client", "Queuing old block #{}", header.number()); + match self.queue_ancient_blocks.queue(&mut self.io_channel.lock(), move |client| { + let result = client.importer.import_old_block( &header, &block_bytes, &receipts_bytes, &**client.db.read(), &*client.chain.read() - ).map(|_| ()).unwrap_or_else(|e| { + ); + + client.pending_ancient_blocks.write().remove(&hash); + result.map(|_| ()).unwrap_or_else(|e| { error!(target: "client", "Error importing ancient block: {}", e); }); }) { @@ -2058,7 +2071,7 @@ impl IoClient for Client { } fn queue_consensus_message(&self, message: Bytes) { - match self.queue_consensus_message.queue(&mut self.io_channel.lock(), 1, move |client| { + match self.queue_consensus_message.queue(&mut self.io_channel.lock(), move |client| { if let Err(e) = client.engine().handle_message(&message) { debug!(target: "poa", "Invalid message received: {}", e); } @@ -2471,35 +2484,38 @@ impl fmt::Display for QueueError { /// Queue some items to be processed by IO client. struct IoChannelQueue { - currently_queued: Arc, + queue: Arc>>>, limit: usize, } impl IoChannelQueue { pub fn new(limit: usize) -> Self { IoChannelQueue { - currently_queued: Default::default(), + queue: Default::default(), limit, } } - pub fn queue(&self, channel: &mut IoChannel, count: usize, fun: F) -> Result<(), QueueError> where - F: Fn(&Client) + Send + Sync + 'static, + pub fn queue(&self, channel: &mut IoChannel, fun: F) -> Result<(), QueueError> + where F: Fn(&Client) + Send + Sync + 'static { - let queue_size = self.currently_queued.load(AtomicOrdering::Relaxed); - ensure!(queue_size < self.limit, QueueError::Full(self.limit)); + { + let mut queue = self.queue.lock(); + let queue_size = queue.len(); + ensure!(queue_size < self.limit, QueueError::Full(self.limit)); - let currently_queued = self.currently_queued.clone(); + queue.push_back(Box::new(fun)); + } + + let queue = self.queue.clone(); let result = channel.send(ClientIoMessage::execute(move |client| { - currently_queued.fetch_sub(count, AtomicOrdering::SeqCst); - fun(client); + while let Some(fun) = queue.lock().pop_front() { + fun(client); + } })); match result { - Ok(_) => { - self.currently_queued.fetch_add(count, AtomicOrdering::SeqCst); - Ok(()) - }, + Ok(_) => Ok(()), Err(e) => Err(QueueError::Channel(e)), } } diff --git a/ethcore/sync/src/blocks.rs b/ethcore/sync/src/blocks.rs index 321c783b4db..283f4ed610d 100644 --- a/ethcore/sync/src/blocks.rs +++ b/ethcore/sync/src/blocks.rs @@ -266,7 +266,7 @@ impl BlockCollection { } } - /// Get a valid chain of blocks ordered in descending order and ready for importing into blockchain. + /// Get a valid chain of blocks ordered in ascending order and ready for importing into blockchain. pub fn drain(&mut self) -> Vec { if self.blocks.is_empty() || self.head.is_none() { return Vec::new(); From 6552256981589a3a80a1c6c253fb8418f9ded0e8 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 18 May 2018 08:04:25 +0200 Subject: [PATCH 83/95] Remove HostInfo::next_nonce (#8644) --- util/network-devp2p/src/host.rs | 12 +++++++----- util/network/src/lib.rs | 2 -- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index 4cca2e6e5a7..f3446845fb1 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -210,6 +210,13 @@ pub struct HostInfo { pub public_endpoint: Option, } +impl HostInfo { + fn next_nonce(&mut self) -> H256 { + self.nonce = keccak(&self.nonce); + self.nonce + } +} + impl HostInfoTrait for HostInfo { fn id(&self) -> &NodeId { self.keys.public() @@ -219,11 +226,6 @@ impl HostInfoTrait for HostInfo { self.keys.secret() } - fn next_nonce(&mut self) -> H256 { - self.nonce = keccak(&self.nonce); - self.nonce - } - fn client_version(&self) -> &str { &self.config.client_version } diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index 1327a9ad59f..0137543fdd5 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -332,8 +332,6 @@ pub trait HostInfo { fn id(&self) -> &NodeId; /// Returns secret key fn secret(&self) -> &Secret; - /// Increments and returns connection nonce. - fn next_nonce(&mut self) -> H256; /// Returns the client version. fn client_version(&self) -> &str; } From 9e719f088f37ec9af7a24403cbd7e8cbfd9a134e Mon Sep 17 00:00:00 2001 From: David Date: Sun, 20 May 2018 06:27:59 +0200 Subject: [PATCH 84/95] Remove the Keccak C library and use the pure Rust impl (#8657) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add license and readme * Use pure rust implementation * Bump version to 0.1.1 * Don't use C, prefer the pure Rust implementation * Add test for `write_keccak` * Bump version * Add benchmarks * Add benchmarks * Add keccak_256, keccak_512, keccak_256_unchecked and keccak_512_unchecked – mostly for compatibility with ethash * Remove failed git merge attempt from external git repo Cargo.lock updates * whitespace * Mark unsafe function unsafe * Unsafe calls in unsafe block * Document unsafety invariants * Revert unintended changes to Cargo.lock --- Cargo.lock | 53 +++++----- ethash/src/keccak.rs | 20 ++-- util/hash/Cargo.toml | 11 +- util/hash/benches/keccak_256.rs | 36 +++++++ util/hash/build.rs | 26 ----- util/hash/src/lib.rs | 55 +++++++--- util/hash/src/tinykeccak.c | 177 -------------------------------- 7 files changed, 119 insertions(+), 259 deletions(-) create mode 100644 util/hash/benches/keccak_256.rs delete mode 100644 util/hash/build.rs delete mode 100644 util/hash/src/tinykeccak.c diff --git a/Cargo.lock b/Cargo.lock index b4d6bd315f2..e4c80310c1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -251,7 +251,7 @@ dependencies = [ "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "rlp 0.2.1", "rlp_derive 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -487,7 +487,7 @@ version = "1.12.0" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -541,7 +541,7 @@ dependencies = [ "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "journaldb 0.1.0", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "kvdb 0.1.0", "kvdb-memorydb 0.1.0", "kvdb-rocksdb 0.1.0", @@ -633,7 +633,7 @@ dependencies = [ "hashdb 0.1.1", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "kvdb 0.1.0", "kvdb-memorydb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -685,7 +685,7 @@ dependencies = [ "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parity-reactor 0.1.0", @@ -730,7 +730,7 @@ dependencies = [ "ethkey 0.3.0", "igd 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -769,7 +769,7 @@ dependencies = [ "ethkey 0.3.0", "fetch 0.1.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie 0.1.0", @@ -803,7 +803,7 @@ dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "kvdb 0.1.0", "kvdb-rocksdb 0.1.0", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -851,7 +851,7 @@ dependencies = [ "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -875,7 +875,7 @@ dependencies = [ "ethkey 0.3.0", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "kvdb 0.1.0", "kvdb-memorydb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -900,7 +900,7 @@ dependencies = [ "ethkey 0.3.0", "evm 0.1.0", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "rlp 0.2.1", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "unexpected 0.1.0", @@ -1021,7 +1021,7 @@ dependencies = [ "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "memory-cache 0.1.0", @@ -1345,7 +1345,7 @@ dependencies = [ "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "kvdb 0.1.0", "kvdb-memorydb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1454,9 +1454,8 @@ dependencies = [ [[package]] name = "keccak-hash" -version = "0.1.0" +version = "0.1.2" dependencies = [ - "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1648,7 +1647,7 @@ dependencies = [ "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "plain_hasher 0.1.0", "rlp 0.2.1", ] @@ -1987,7 +1986,7 @@ dependencies = [ "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", "journaldb 0.1.0", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "kvdb 0.1.0", "kvdb-rocksdb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2051,7 +2050,7 @@ dependencies = [ "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2115,7 +2114,7 @@ dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2208,7 +2207,7 @@ dependencies = [ "jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "kvdb-memorydb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "macros 0.1.0", @@ -2244,7 +2243,7 @@ dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-rpc 1.12.0", @@ -2332,7 +2331,7 @@ dependencies = [ "ethcore-bytes 0.1.0", "ethcore-sync 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2440,7 +2439,7 @@ dependencies = [ "ethcore-logger 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "memorydb 0.1.1", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2736,7 +2735,7 @@ dependencies = [ "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", ] [[package]] @@ -3472,7 +3471,7 @@ version = "0.1.0" dependencies = [ "ethcore-bytes 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "rlp 0.2.1", ] @@ -3482,7 +3481,7 @@ version = "0.1.0" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "rlp 0.2.1", "trie-standardmap 0.1.0", ] @@ -3630,7 +3629,7 @@ dependencies = [ "ethcore-bytes 0.1.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", - "keccak-hash 0.1.0", + "keccak-hash 0.1.2", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "patricia-trie 0.1.0", "rlp 0.2.1", diff --git a/ethash/src/keccak.rs b/ethash/src/keccak.rs index 8ca4f543844..36fb1735470 100644 --- a/ethash/src/keccak.rs +++ b/ethash/src/keccak.rs @@ -21,32 +21,36 @@ pub type H256 = [u8; 32]; pub mod keccak_512 { use super::hash; - pub use self::hash::keccak_512 as unchecked; + pub use self::hash::keccak_512_unchecked as unchecked; pub fn write(input: &[u8], output: &mut [u8]) { - unsafe { hash::keccak_512(output.as_mut_ptr(), output.len(), input.as_ptr(), input.len()) }; + hash::keccak_512(input, output); } pub fn inplace(input: &mut [u8]) { - // This is safe since `sha3_*` uses an internal buffer and copies the result to the output. This + // This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This // means that we can reuse the input buffer for both input and output. - unsafe { hash::keccak_512(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len()) }; + unsafe { + hash::keccak_512_unchecked(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len()); + } } } pub mod keccak_256 { use super::hash; - pub use self::hash::keccak_256 as unchecked; + pub use self::hash::keccak_256_unchecked as unchecked; #[allow(dead_code)] pub fn write(input: &[u8], output: &mut [u8]) { - unsafe { hash::keccak_256(output.as_mut_ptr(), output.len(), input.as_ptr(), input.len()) }; + hash::keccak_256(input, output); } pub fn inplace(input: &mut [u8]) { - // This is safe since `sha3_*` uses an internal buffer and copies the result to the output. This + // This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This // means that we can reuse the input buffer for both input and output. - unsafe { hash::keccak_256(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len()) }; + unsafe { + hash::keccak_256_unchecked(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len()); + } } } diff --git a/util/hash/Cargo.toml b/util/hash/Cargo.toml index da91cd733cb..e136ada305a 100644 --- a/util/hash/Cargo.toml +++ b/util/hash/Cargo.toml @@ -1,18 +1,15 @@ [package] description = "Rust bindings for tinykeccak C library" -homepage = "http://parity.io" +homepage = "https://github.com/paritytech/keccak-hash" +readme = "README.md" license = "GPL-3.0" name = "keccak-hash" -version = "0.1.0" +version = "0.1.2" authors = ["Parity Technologies "] -build = "build.rs" [dependencies] ethereum-types = "0.3" -tiny-keccak = "1.3" - -[build-dependencies] -cc = "1.0" +tiny-keccak = "1.4.1" [dev-dependencies] tempdir = "0.3" diff --git a/util/hash/benches/keccak_256.rs b/util/hash/benches/keccak_256.rs new file mode 100644 index 00000000000..8b398417d8b --- /dev/null +++ b/util/hash/benches/keccak_256.rs @@ -0,0 +1,36 @@ +#![feature(test)] + +extern crate test; +extern crate ethereum_types; +extern crate keccak_hash; + +use keccak_hash::{keccak, write_keccak}; +use test::Bencher; + +#[bench] +fn bench_keccak_256_with_empty_input(b: &mut Bencher) { + let empty = [0u8;0]; + b.bytes = empty.len() as u64; + b.iter(|| { + let _out = keccak(empty); + }) +} + +#[bench] +fn bench_keccak_256_with_typical_input(b: &mut Bencher) { + let data: Vec = From::from("some medum length string with important information"); + b.bytes = data.len() as u64; + b.iter(|| { + let _out = keccak(&data); + }) +} + +#[bench] +fn bench_keccak_256_with_large_input(b: &mut Bencher) { + // 4096 chars + let data: Vec = From::from("IGxcKBr1Qp7tuqtpSVhAbvt7UgWLEi7mCA6Wa185seLSIJLFS8K1aAFO9AwtO9b3n9SM3Qg136JMmy9Mj9gZ84IaUm8XioPtloabFDU5ZR1wvauJT6jNTkvBVBpUigIsyU7C1u3s99vKP64LpXqvo1hwItZKtISxmUAgzzjv5q14V4G9bkKAnmc4M5xixgLsDGZmnj6HcOMY3XRkWtxN3RscSKwPA0bfpgtz27ZVHplbXwloYRgRLpjRhZJc7sqO8RFnTHKasVkxVRcUoDBvWNJK27TbLvQQcfxETI2Q1H6c2cBAchi8unSiuxqy5rIvVxcl9rsmmRY4IXLEG9qKntUGbiIRLjEffIP9ODoWog0GbWLmMtfvtf24hWVwXz6Ap5oUAR0kLgb7HYIYrOwKjvfV25iEF7GW8cjhl8yowXx1zcgW4t6NJNqJlGzRKx8MvRWQXvHz8h8JxcHl7S64i6PAkxI9eCLXLvs8cpbEQQHt05Zu6GKm6IInjc9mSh52WFuGhgjbno69XzfkBufJs6c9tZuBf6ErVPj4UxmT82ajCruDusk79Tlvb8oQMLjoplQc1alQaLQwSsMac9iVp9MiE3PeYnTTepJ1V10tp79fciDAnNPJgPcRfDYv0REcSFgR9Q7yWhbpPpyBjO7HwOykDQVGtV0ZbDFrFRygLAXagAIkOPc9HDfcBNID1Q2MGk8ijVWMyvmGz1wzbpNfFcQaSOm8olhwoLyHUGvkyXegh44iNsPBUvSicNxTTDowtMqO5azleuWEjzxCobYbASDopvl6JeJjRtEBBO5YCQJiHsYjlXh9QR5Q543GsqhzRLgcHNRSZYLMZqDmIABXZi8VRNJMZyWXDRKHOGDmcHWe55uZomW6FnyU0uSRKxxz66K0JWfxuFzzxAR0vR4ZZCTemgDRQuDwL1loC3KUMjDpU13jUgoPc4UJUVfwQ4f4BUY3X51Cfw9FLw4oX39KoFoiCP2Z6z27gZUY1IlE59WoXGLj4KjTp4C16ZihG080gfDIWlXnDEk3VwBuBFyKWARB63sGLrGnn27b1gHWMaop6sPvkQgWxkEKIqsxDIvXLZJg2s23V8Gqtt0FeA7R3RCvBysF4jNjQ7NiQTIQWQZ8G9gO4mEsftolSZv6FlSpNeBKIIwYWSO2R6vkgeiz06euE9bwwnenOjwPNGTGk8WHIOZBJ1hIP0ejVU2i2ca9ON0phSAnewqjo5W3PtZf2Q7mDvp9imuVWoy4t8XcZq8I2Un9jVjes9Xi0FLN2t71vLFWLWZmGDzwXxpqEgkARS1WjtJoYXCBmRnXEPj6jQfwMZWKPYSIrmOogxMVoWvA8wrof6utfJna9JezyTnrBJSCuGTSNmwwAXRLoFYxF1RITyN8mI2KmHSfvLXBrbE6kmAkjsm4XJb6kria7oUQQ1gzJuCyB7oNHjZTBFNhNa7VeQ1s1xLOwZXLOAjZ4MDTYKnF7giGJGyswb5KQxkOV9orbuAu6pJsjtql6h1UD3BcNUkG3oz8kJNepbuCN3vNCJcZOX1VrQi0PWkDwyvECrQ2E1CgbU6GpWatpg2sCTpo9W62pCcWBK2FKUFWqU3qo2T7T1Mk2ZtM6hE9I8op0M7xlGE91Mn7ea6aq93MWp7nvFlBvbaMIoeU4MpDx0BeOSkROY03ZBJ0x7K8nJrNUhAtvxp17c9oFk0VxLiuRbAAcwDUormOmpVXZNIcqnap4twEVYaSIowfcNojyUSrFL5nPc8ZG93WgNNl9rpUPZhssVml3DvXghI80A9SW3QauzohTQAX2bkWelFBHnuG2LKrsJ8en51N6CkjcS5b87y1DVMZELcZ1n5s8PCAA1wyn7OSZlgw00GRzch1YwMoHzBBgIUtMO9HrMyuhgqIPJP7KcKbQkKhtvBXKplX8SCfSlOwUkLwHNKm3HYVE0uVfJ91NAsUrGoCOjYiXYpoRT8bjAPWTm6fDlTq2sbPOyTMoc4xRasmiOJ7B0PT6UxPzCPImM4100sPFxp7Kofv4okKZWTPKTefeYiPefI3jRgfDtEIP9E6a35LZD75lBNMXYlAqL3qlnheUQD1WQimFTHiDsW6bmURptNvtkMjEXzXzpWbnyxBskUGTvP2YQjtSAhWliDXkv6t1x71cYav7TQbqvbIzMRQQsguSGYMbs8YIC4DC9ep5reWAfanlTxcxksbEhQ7FGzXOvcufeGnDl2C85gWfryVzwN7kOZiSEktFMOQ1ngRC23y1fCOiHQVQJ2nLnaW7GILb9wkN1mBTRuHsOefRJST0TnRxcn4bBq4MIibIitVyjPRy7G5XvPEcL4pFaW1HCPGm6pUOEEwTer32JObNGCyTFB1BI2cRLJu5BHPjgG3mmb0gGkGlIfh8D2b2amogpivqEn2r9Y1KOKQ8ufJvG2mYfkevco9DuEZ9Nmzkm6XkCTZaFMNHqbfQaKqsEYK7i2N1KfkBct1leW2H9MQ9QO7AHCqXHK47b1kWVIm6pSJA1yV4funzCqXnIJCEURQgHiKf38YpN7ylLhe1J4UvSG3KeesZNeFFIZOEP9HZUSFMpnN1MOrwejojK0D4qzwucYWtXrTQ8I7UP5QhlijIsCKckUa9C1Osjrq8cgSclYNGt19wpy0onUbX1rOQBUlAAUJs4CyXNU0wmVUjw7tG1LUC8my4s9KZDUj4R5UcPz3VaZRrx1RqYu6YxjroJW70I1LyG4WEiQbOkCoLmaiWo9WzbUS2cErlOo2RPymlkWHxbNnZawX2Bc872ivRHSWqNpRHyuR5QewXmcyghH3EhESBAxTel5E2xuQXfLCEVK0kEk0Mj22KPsckKKyH7sVYC1F4YItQh5hj9Titb7KflQb9vnXQ44UHxY3zBhTQT5PSYv1Kv8HxXCsnpmhZCiBru16iX9oEB33icBVB2KKcZZEEKnCGPVxJlM9RTlyNyQmjHf7z4GeTDuMAUrsMO31WvgZBnWcAOtn6ulBTUCAaqxJiWqzlMx2FSANAlyAjAxqzmQjzPLvQRjskUnBFN3woKB1m2bSo2c5thwA1fKiPvN5LW8tl1rnfNy3rJ0GJpK8nZjkzHMztYrKYAe56pX4SvplpTyibTIiRXLyEVsmuByTHCZhO3fvGoFsav3ZuRhe9eAAWeqAh13eKDTcA0ufME3ZnmJheXEZ3OwrxnFjSf3U0clkWYVont3neh77ODKHhYnX0bOmnJJlr4RqFoLBitskY0kcGMKcZlaej21SENjDcFgaka3CfHbAH5vIFqnoX1JZrZPkQ65PZqQWImP79U3gXWKvz96lElyJZAFqn0Mbltllqw4MhlI766AvHraOmMsJoNvjv1QR7pCSnC0iX6nbqW1eVPaUSZDuZRtRIxfLA8HC9VbxufT2KZV3qG0l7wrZna5Di2MNcBE9uthuVLZcqp8vCmEhINDhRRlipR7tC2iRBHecS5WtxBCpbEm1y1kgNG5o60UKgAswxxuJ3RQ9Y49mPIApBMmp4LFpuKRfcrZb4UJnCfR3pNbQ70nnZ6Be2M7tuJUCoFfHrhqHXNz5A0uWMgxUS50c60zLl6QAELxHaCGba4WCMOHIo5nSKcUuYtDyDoDlrezALW5mZR4PRPRxnjrXxbJI14qrpymRReC3QgFDJp6sT5TLwvSHaavPlEbt2Eu0Kh5SXklGHXP9YuF3glGuJzSob3NakW1RXF5786U1MHhtJby64LyGWvNn4QXie3VjeL3QQu4C9crEAxSSiOJOfnL3DYIVOY4ipUkKFlF7Rp2q6gZazDvcUCp1cbcr7T7B4s22rXzjN7mHYWOyWuZGwlImeorY3aVKi7BaXbhgOFw6BUmIc1HeGFELHIEnPE9MwOjZam3LOm0rhBHlvJJZkXvJKmDUJrGlyqC5GtC5lDWLfXewyDWDqq7PY0atVQily5GWqib6wub6u6LZ3HZDNP8gK64Nf4kC259AE4V2hCohDnSsXAIoOkehwXyp6CkDT42NJb6sXHUv2N6cm292MiKA22PKWrwUGsan599KI2V67YRDfcfiB4ZHRDiSe62MBE0fGLIgXLIWw1xTWYbPQ9YAj3xovBvmewbJ1De4k6uS"); + b.bytes = data.len() as u64; + b.iter(|| { + let _out = keccak(&data); + }) +} \ No newline at end of file diff --git a/util/hash/build.rs b/util/hash/build.rs deleted file mode 100644 index eecb804f90d..00000000000 --- a/util/hash/build.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - - // build.rs - -// Bring in a dependency on an externally maintained `cc` package which manages -// invoking the C compiler. -extern crate cc; - -fn main() { - cc::Build::new().file("src/tinykeccak.c").compile("libtinykeccak.a"); -} - diff --git a/util/hash/src/lib.rs b/util/hash/src/lib.rs index 526d22aeda7..b75e095a681 100644 --- a/util/hash/src/lib.rs +++ b/util/hash/src/lib.rs @@ -18,7 +18,9 @@ extern crate ethereum_types; extern crate tiny_keccak; use std::io; +use std::slice; use tiny_keccak::Keccak; + pub use ethereum_types::H256; /// Get the KECCAK (i.e. Keccak) hash of the empty bytes string. @@ -30,12 +32,6 @@ pub const KECCAK_NULL_RLP: H256 = H256( [0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x5 /// The KECCAK of the RLP encoding of empty list. pub const KECCAK_EMPTY_LIST_RLP: H256 = H256( [0x1d, 0xcc, 0x4d, 0xe8, 0xde, 0xc7, 0x5d, 0x7a, 0xab, 0x85, 0xb5, 0x67, 0xb6, 0xcc, 0xd4, 0x1a, 0xd3, 0x12, 0x45, 0x1b, 0x94, 0x8a, 0x74, 0x13, 0xf0, 0xa1, 0x42, 0xfd, 0x40, 0xd4, 0x93, 0x47] ); -extern { - /// Hashes input. Returns -1 if either out or input does not exist. Otherwise returns 0. - pub fn keccak_256(out: *mut u8, outlen: usize, input: *const u8, inputlen: usize) -> i32; - /// Hashes input. Returns -1 if either out or input does not exist. Otherwise returns 0. - pub fn keccak_512(out: *mut u8, outlen: usize, input: *const u8, inputlen: usize) -> i32; -} pub fn keccak>(s: T) -> H256 { let mut result = [0u8; 32]; @@ -43,15 +39,30 @@ pub fn keccak>(s: T) -> H256 { H256(result) } -pub fn write_keccak>(s: T, dest: &mut [u8]) { - let input = s.as_ref(); - unsafe { - // we can safely ignore keccak_256 output, cause we know that both input - // and dest are properly allocated - keccak_256(dest.as_mut_ptr(), dest.len(), input.as_ptr(), input.len()); - } +pub unsafe fn keccak_256_unchecked(out: *mut u8, outlen: usize, input: *const u8, inputlen: usize) { + // This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This + // means that we can reuse the input buffer for both input and output. + Keccak::keccak256( + slice::from_raw_parts(input, inputlen), + slice::from_raw_parts_mut(out, outlen) + ); } +pub unsafe fn keccak_512_unchecked(out: *mut u8, outlen: usize, input: *const u8, inputlen: usize) { + // This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This + // means that we can reuse the input buffer for both input and output. + Keccak::keccak512( + slice::from_raw_parts(input, inputlen), + slice::from_raw_parts_mut(out, outlen) + ); +} + +pub fn keccak_256(input: &[u8], mut output: &mut [u8]) { Keccak::keccak256(input, &mut output); } + +pub fn keccak_512(input: &[u8], mut output: &mut [u8]) { Keccak::keccak512(input, &mut output); } + +pub fn write_keccak>(s: T, dest: &mut [u8]) { Keccak::keccak256(s.as_ref(), dest); } + pub fn keccak_pipe(r: &mut io::BufRead, w: &mut io::Write) -> Result { let mut output = [0u8; 32]; let mut input = [0u8; 1024]; @@ -82,17 +93,33 @@ mod tests { use std::fs; use std::io::{Write, BufReader}; use self::tempdir::TempDir; - use super::{keccak, keccak_buffer, KECCAK_EMPTY}; + use super::{keccak, write_keccak, keccak_buffer, KECCAK_EMPTY}; #[test] fn keccak_empty() { assert_eq!(keccak([0u8; 0]), KECCAK_EMPTY); } + #[test] fn keccak_as() { assert_eq!(keccak([0x41u8; 32]), From::from("59cad5948673622c1d64e2322488bf01619f7ff45789741b15a9f782ce9290a8")); } + #[test] + fn write_keccak_with_content() { + let data: Vec = From::from("hello world"); + let expected = vec![ + 0x47, 0x17, 0x32, 0x85, 0xa8, 0xd7, 0x34, 0x1e, + 0x5e, 0x97, 0x2f, 0xc6, 0x77, 0x28, 0x63, 0x84, + 0xf8, 0x02, 0xf8, 0xef, 0x42, 0xa5, 0xec, 0x5f, + 0x03, 0xbb, 0xfa, 0x25, 0x4c, 0xb0, 0x1f, 0xad + ]; + let mut dest = [0u8;32]; + write_keccak(data, &mut dest); + + assert_eq!(dest, expected.as_ref()); + } + #[test] fn should_keccak_a_file() { // given diff --git a/util/hash/src/tinykeccak.c b/util/hash/src/tinykeccak.c deleted file mode 100644 index bfe172e5f6d..00000000000 --- a/util/hash/src/tinykeccak.c +++ /dev/null @@ -1,177 +0,0 @@ -#include -#include - -/** libkeccak-tiny - * - * A single-file implementation of SHA-3 and SHAKE. - * - * Implementor: David Leon Gil - * License: CC0, attribution kindly requested. Blame taken too, - * but not liability. - */ - -#define decshake(bits) \ - int shake##bits(uint8_t*, size_t, const uint8_t*, size_t); - -#define deckeccak(bits) \ - int keccak_##bits(uint8_t*, size_t, const uint8_t*, size_t); - -decshake(128) -decshake(256) -deckeccak(224) -deckeccak(256) -deckeccak(384) -deckeccak(512) - -/******** The Keccak-f[1600] permutation ********/ - -/*** Constants. ***/ -static const uint8_t rho[24] = \ - { 1, 3, 6, 10, 15, 21, - 28, 36, 45, 55, 2, 14, - 27, 41, 56, 8, 25, 43, - 62, 18, 39, 61, 20, 44}; -static const uint8_t pi[24] = \ - {10, 7, 11, 17, 18, 3, - 5, 16, 8, 21, 24, 4, - 15, 23, 19, 13, 12, 2, - 20, 14, 22, 9, 6, 1}; -static const uint64_t RC[24] = \ - {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, - 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, - 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, - 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, - 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, - 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; - -/*** Helper macros to unroll the permutation. ***/ -#define rol(x, s) (((x) << s) | ((x) >> (64 - s))) -#define REPEAT6(e) e e e e e e -#define REPEAT24(e) REPEAT6(e e e e) -#define REPEAT5(e) e e e e e -#define FOR5(v, s, e) \ - v = 0; \ - REPEAT5(e; v += s;) - -/*** Keccak-f[1600] ***/ -static inline void keccakf(void* state) { - uint64_t* a = (uint64_t*)state; - uint64_t b[5] = {0}; - uint64_t t = 0; - uint8_t x, y; - int i; - - for (i = 0; i < 24; i++) { - // Theta - FOR5(x, 1, - b[x] = 0; - FOR5(y, 5, - b[x] ^= a[x + y]; )) - FOR5(x, 1, - FOR5(y, 5, - a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) - // Rho and pi - t = a[1]; - x = 0; - REPEAT24(b[0] = a[pi[x]]; - a[pi[x]] = rol(t, rho[x]); - t = b[0]; - x++; ) - // Chi - FOR5(y, - 5, - FOR5(x, 1, - b[x] = a[y + x];) - FOR5(x, 1, - a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) - // Iota - a[0] ^= RC[i]; - } -} - -/******** The FIPS202-defined functions. ********/ - -/*** Some helper macros. ***/ - -#define _(S) do { S } while (0) -#define FOR(i, ST, L, S) \ - _({size_t i; for (i = 0; i < L; i += ST) { S; }}) -#define mkapply_ds(NAME, S) \ - static inline void NAME(uint8_t* dst, \ - const uint8_t* src, \ - size_t len) { \ - FOR(i, 1, len, S); \ - } -#define mkapply_sd(NAME, S) \ - static inline void NAME(const uint8_t* src, \ - uint8_t* dst, \ - size_t len) { \ - FOR(i, 1, len, S); \ - } - -mkapply_ds(xorin, dst[i] ^= src[i]) // xorin -mkapply_sd(setout, dst[i] = src[i]) // setout - -#define P keccakf -#define Plen 200 - -// Fold P*F over the full blocks of an input. -#define foldP(I, L, F) \ - while (L >= rate) { \ - F(a, I, rate); \ - P(a); \ - I += rate; \ - L -= rate; \ - } - -/** The sponge-based hash construction. **/ -static inline int hash(uint8_t* out, size_t outlen, - const uint8_t* in, size_t inlen, - size_t rate, uint8_t delim) { - if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) { - return -1; - } - uint8_t a[Plen] = {0}; - // Absorb input. - foldP(in, inlen, xorin); - // Xor in the DS and pad frame. - a[inlen] ^= delim; - a[rate - 1] ^= 0x80; - // Xor in the last block. - xorin(a, in, inlen); - // Apply P - P(a); - // Squeeze output. - foldP(out, outlen, setout); - setout(a, out, outlen); - memset(a, 0, 200); - return 0; -} - -/*** Helper macros to define SHA3 and SHAKE instances. ***/ -#define defshake(bits) \ - int shake##bits(uint8_t* out, size_t outlen, \ - const uint8_t* in, size_t inlen) { \ - return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f); \ - } -#define defkeccak(bits) \ - int keccak_##bits(uint8_t* out, size_t outlen, \ - const uint8_t* in, size_t inlen) { \ - if (outlen > (bits/8)) { \ - return -1; \ - } \ - return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \ - } - -/*** FIPS202 SHAKE VOFs ***/ -defshake(128) -defshake(256) - -/*** FIPS202 SHA3 FOFs ***/ -defkeccak(224) -defkeccak(256) -defkeccak(384) -defkeccak(512) - - - From 52f10242e2419cc31096904578e6c92e0e54e503 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 21 May 2018 15:33:47 +0800 Subject: [PATCH 85/95] updated tiny-keccak to 1.4.2 (#8669) --- Cargo.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4c80310c1c..e2fa0a9db8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -462,7 +462,7 @@ dependencies = [ "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -504,7 +504,7 @@ dependencies = [ "ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -595,7 +595,7 @@ dependencies = [ "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.12.1 (git+https://github.com/paritytech/ring)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -746,7 +746,7 @@ dependencies = [ "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -780,7 +780,7 @@ dependencies = [ "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -814,7 +814,7 @@ dependencies = [ "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -955,7 +955,7 @@ dependencies = [ "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -995,7 +995,7 @@ dependencies = [ "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1458,7 +1458,7 @@ version = "0.1.2" dependencies = [ "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1776,7 +1776,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ring 0.12.1 (git+https://github.com/paritytech/ring)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2229,7 +2229,7 @@ dependencies = [ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "stats 0.1.0", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "transaction-pool 1.12.0", "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2392,7 +2392,7 @@ dependencies = [ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3220,7 +3220,7 @@ dependencies = [ [[package]] name = "tiny-keccak" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4024,7 +4024,7 @@ dependencies = [ "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" "checksum timer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31d42176308937165701f50638db1c31586f183f1aab416268216577aec7306b" -"checksum tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "58911ed5eb275a8fd2f1f0418ed360a42f59329864b64e1e95377a9024498c01" +"checksum tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9175261fbdb60781fcd388a4d6cc7e14764a2b629a7ad94abb439aed223a44f" "checksum tokio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be15ef40f675c9fe66e354d74c73f3ed012ca1aa14d65846a33ee48f1ae8d922" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" "checksum tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cac2a7883ff3567e9d66bb09100d09b33d90311feca0206c7ca034bc0c55113" From 3c2f13f88b5fee3d485e91130d6b1a8bf1f66f52 Mon Sep 17 00:00:00 2001 From: Afri Schoedon <5chdn@users.noreply.github.com> Date: Tue, 22 May 2018 04:19:00 +0200 Subject: [PATCH 86/95] parity: improve cli help and logging (#8665) * parity: indicate disabling ancient blocks is not recommended * parity: display decimals for stats in informant --- parity/cli/mod.rs | 6 +++--- parity/informant.rs | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index c7c484e2bda..34e3bf03a11 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// Copyright 2015-2018 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify @@ -424,7 +424,7 @@ usage! { FLAG flag_no_ancient_blocks: (bool) = false, or |_| None, "--no-ancient-blocks", - "Disable downloading old blocks after snapshot restoration or warp sync.", + "Disable downloading old blocks after snapshot restoration or warp sync. Not recommended.", FLAG flag_no_serve_light: (bool) = false, or |c: &Config| c.network.as_ref()?.no_serve_light.clone(), "--no-serve-light", @@ -894,7 +894,7 @@ usage! { ["Legacy options"] FLAG flag_warp: (bool) = false, or |_| None, "--warp", - "Does nothing; warp sync is enabled by default.", + "Does nothing; warp sync is enabled by default. Use --no-warp to disable.", FLAG flag_dapps_apis_all: (bool) = false, or |_| None, "--dapps-apis-all", diff --git a/parity/informant.rs b/parity/informant.rs index a4d2727c359..e2f3960b679 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// Copyright 2015-2018 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify @@ -303,13 +303,13 @@ impl Informant { paint(White.bold(), format!("{}", chain_info.best_block_hash)), if self.target.executes_transactions() { format!("{} blk/s {} tx/s {} Mgas/s", - paint(Yellow.bold(), format!("{:4}", (client_report.blocks_imported * 1000) as u64 / elapsed.as_milliseconds())), - paint(Yellow.bold(), format!("{:4}", (client_report.transactions_applied * 1000) as u64 / elapsed.as_milliseconds())), - paint(Yellow.bold(), format!("{:3}", (client_report.gas_processed / From::from(elapsed.as_milliseconds() * 1000)).low_u64())) + paint(Yellow.bold(), format!("{:5.2}", (client_report.blocks_imported * 1000) as f64 / elapsed.as_milliseconds() as f64)), + paint(Yellow.bold(), format!("{:6.1}", (client_report.transactions_applied * 1000) as f64 / elapsed.as_milliseconds() as f64)), + paint(Yellow.bold(), format!("{:4}", (client_report.gas_processed / From::from(elapsed.as_milliseconds() * 1000)).low_u64())) ) } else { format!("{} hdr/s", - paint(Yellow.bold(), format!("{:4}", (client_report.blocks_imported * 1000) as u64 / elapsed.as_milliseconds())) + paint(Yellow.bold(), format!("{:6.1}", (client_report.blocks_imported * 1000) as f64 / elapsed.as_milliseconds() as f64)) ) }, paint(Green.bold(), format!("{:5}", queue_info.unverified_queue_size)), @@ -350,8 +350,8 @@ impl Informant { Some(ref rpc_stats) => format!( "RPC: {} conn, {} req/s, {} µs", paint(Blue.bold(), format!("{:2}", rpc_stats.sessions())), - paint(Blue.bold(), format!("{:2}", rpc_stats.requests_rate())), - paint(Blue.bold(), format!("{:3}", rpc_stats.approximated_roundtrip())), + paint(Blue.bold(), format!("{:4}", rpc_stats.requests_rate())), + paint(Blue.bold(), format!("{:4}", rpc_stats.approximated_roundtrip())), ), _ => String::new(), }, From 3fde07b2e18f20453970ed2ab9c6f2df6cc717b1 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Tue, 22 May 2018 12:24:09 +0800 Subject: [PATCH 87/95] Refactor EIP150, EIP160 and EIP161 forks to be specified in CommonParams (#8614) * Allow post-homestead forks to be specified in CommonParams * Fix all json configs * Fix test in json crate * Fix test in ethcore * Fix all chain configs to use tabs Given we use tabs in .editorconfig and the majority of chain configs. This change is done in Emacs using `mark-whole-buffer` and `indent-region`. --- ...authority_round_block_reward_contract.json | 112 +- ethcore/res/ethereum/byzantium_test.json | 8 +- ethcore/res/ethereum/classic.json | 8 +- ethcore/res/ethereum/constantinople_test.json | 8 +- ethcore/res/ethereum/easthub.json | 174 +- ethcore/res/ethereum/eip150_test.json | 10 +- ethcore/res/ethereum/eip161_test.json | 10 +- ethcore/res/ethereum/ellaism.json | 144 +- ethcore/res/ethereum/expanse.json | 8 +- ethcore/res/ethereum/foundation.json | 8 +- ethcore/res/ethereum/frontier_like_test.json | 10 +- ethcore/res/ethereum/frontier_test.json | 10 +- ethcore/res/ethereum/homestead_test.json | 12 +- ethcore/res/ethereum/mcip3_test.json | 332 +- ethcore/res/ethereum/mcip6_byz.json | 318 +- ethcore/res/ethereum/morden.json | 8 +- ethcore/res/ethereum/musicoin.json | 324 +- ethcore/res/ethereum/olympic.json | 10 +- ethcore/res/ethereum/ropsten.json | 8 +- ethcore/res/ethereum/social.json | 17710 ++++++++-------- ethcore/res/ethereum/transition_test.json | 8 +- ethcore/src/machine.rs | 29 +- ethcore/src/spec/spec.rs | 29 +- json/src/spec/ethash.rs | 29 +- json/src/spec/params.rs | 15 + 25 files changed, 9663 insertions(+), 9679 deletions(-) diff --git a/ethcore/res/authority_round_block_reward_contract.json b/ethcore/res/authority_round_block_reward_contract.json index e008de117f7..31957731232 100644 --- a/ethcore/res/authority_round_block_reward_contract.json +++ b/ethcore/res/authority_round_block_reward_contract.json @@ -1,61 +1,61 @@ { - "name": "TestAuthorityRoundBlockRewardContract", - "engine": { - "authorityRound": { - "params": { - "stepDuration": 1, - "startStep": 2, - "validators": { - "list": [ - "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e", - "0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1" - ] + "name": "TestAuthorityRoundBlockRewardContract", + "engine": { + "authorityRound": { + "params": { + "stepDuration": 1, + "startStep": 2, + "validators": { + "list": [ + "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e", + "0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1" + ] + }, + "immediateTransitions": true, + "emptyStepsTransition": "1", + "maximumEmptySteps": "2", + "blockRewardContractAddress": "0x0000000000000000000000000000000000000042" + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x69", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0" + }, + "genesis": { + "seal": { + "authorityRound": { + "step": "0x0", + "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } }, - "immediateTransitions": true, - "emptyStepsTransition": "1", - "maximumEmptySteps": "2", - "blockRewardContractAddress": "0x0000000000000000000000000000000000000042" - } - } - }, - "params": { - "gasLimitBoundDivisor": "0x0400", - "accountStartNonce": "0x0", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID" : "0x69", - "eip140Transition": "0x0", - "eip211Transition": "0x0", - "eip214Transition": "0x0", - "eip658Transition": "0x0" - }, - "genesis": { - "seal": { - "authorityRound": { - "step": "0x0", - "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - } + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x222222" }, - "difficulty": "0x20000", - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x", - "gasLimit": "0x222222" - }, - "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, - "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" }, - "0000000000000000000000000000000000000042": { - "balance": "1", - "constructor": "6060604052341561000f57600080fd5b6102b88061001e6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063f91c289814610046575b600080fd5b341561005157600080fd5b610086600480803590602001908201803590602001919091929080359060200190820180359060200191909192905050610125565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100cd5780820151818401526020810190506100b2565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561010f5780820151818401526020810190506100f4565b5050505090500194505050505060405180910390f35b61012d610264565b610135610278565b61013d610278565b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561018d57600080fd5b85859050888890501415156101a157600080fd5b878790506040518059106101b25750595b90808252806020026020018201604052509150600090505b815181101561021d5785858281811015156101e157fe5b9050602002013561ffff166103e80161ffff16828281518110151561020257fe5b906020019060200201818152505080806001019150506101ca565b878783828280806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050915090915093509350505094509492505050565b602060405190810160405280600081525090565b6020604051908101604052806000815250905600a165627a7a723058201da0f164e75517fb8baf51f030b904032cb748334938e7386f63025bfb23f3de0029" + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" }, + "0000000000000000000000000000000000000042": { + "balance": "1", + "constructor": "6060604052341561000f57600080fd5b6102b88061001e6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063f91c289814610046575b600080fd5b341561005157600080fd5b610086600480803590602001908201803590602001919091929080359060200190820180359060200191909192905050610125565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100cd5780820151818401526020810190506100b2565b50505050905001838103825284818151815260200191508051906020019060200280838360005b8381101561010f5780820151818401526020810190506100f4565b5050505090500194505050505060405180910390f35b61012d610264565b610135610278565b61013d610278565b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561018d57600080fd5b85859050888890501415156101a157600080fd5b878790506040518059106101b25750595b90808252806020026020018201604052509150600090505b815181101561021d5785858281811015156101e157fe5b9050602002013561ffff166103e80161ffff16828281518110151561020257fe5b906020019060200201818152505080806001019150506101ca565b878783828280806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050915090915093509350505094509492505050565b602060405190810160405280600081525090565b6020604051908101604052806000815250905600a165627a7a723058201da0f164e75517fb8baf51f030b904032cb748334938e7386f63025bfb23f3de0029" + } } - } } diff --git a/ethcore/res/ethereum/byzantium_test.json b/ethcore/res/ethereum/byzantium_test.json index 40c7e465991..90c92bbff55 100644 --- a/ethcore/res/ethereum/byzantium_test.json +++ b/ethcore/res/ethereum/byzantium_test.json @@ -8,10 +8,6 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "homesteadTransition": "0x0", - "eip150Transition": "0x0", - "eip160Transition": "0x0", - "eip161abcTransition": "0x0", - "eip161dTransition": "0x0", "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": "0x0", "eip649Transition": "0x0" @@ -27,6 +23,10 @@ "networkID" : "0x1", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x0", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", "eip98Transition": "0xffffffffffffffff", "eip140Transition": "0x0", "eip211Transition": "0x0", diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index a4c6fe9f227..928c056d660 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -9,13 +9,9 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "homesteadTransition": 1150000, - "eip150Transition": 2500000, - "eip160Transition": 3000000, "ecip1010PauseTransition": 3000000, "ecip1010ContinueTransition": 5000000, "ecip1017EraRounds": 5000000, - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff", "bombDefuseTransition": 5900000 } } @@ -30,6 +26,10 @@ "chainID": "0x3d", "forkBlock": "0x1d4c00", "forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f", + "eip150Transition": 2500000, + "eip160Transition": 3000000, + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff", "eip155Transition": 3000000, "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff" diff --git a/ethcore/res/ethereum/constantinople_test.json b/ethcore/res/ethereum/constantinople_test.json index 7b137e86fa0..155b06507d0 100644 --- a/ethcore/res/ethereum/constantinople_test.json +++ b/ethcore/res/ethereum/constantinople_test.json @@ -8,10 +8,6 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "homesteadTransition": "0x0", - "eip150Transition": "0x0", - "eip160Transition": "0x0", - "eip161abcTransition": "0x0", - "eip161dTransition": "0x0", "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": "0x0", "eip649Transition": "0x0" @@ -28,6 +24,10 @@ "maxCodeSize": 24576, "maxCodeSizeTransition": "0x0", "eip98Transition": "0xffffffffffffffff", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", "eip140Transition": "0x0", "eip210Transition": "0x0", "eip211Transition": "0x0", diff --git a/ethcore/res/ethereum/easthub.json b/ethcore/res/ethereum/easthub.json index ddc170d8a67..e7e1a6e708e 100644 --- a/ethcore/res/ethereum/easthub.json +++ b/ethcore/res/ethereum/easthub.json @@ -1,89 +1,89 @@ { - "name": "Easthub", - "dataDir": "easthub", - "engine": { - "Ethash": { - "params": { - "minimumDifficulty": "0x020000", - "difficultyBoundDivisor": "0x0800", - "durationLimit": "0x0d", - "blockReward": "0x2B5E3AF16B1880000", - "homesteadTransition": "0x0", - "bombDefuseTransition": "0x0", - "eip150Transition": "0x0", - "eip160Transition": "0x0", - "ecip1017EraRounds": 5000000, - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" - } - } - }, - "params": { - "gasLimitBoundDivisor": "0x0400", - "registrar": "0x0000000000000000000000000000000000000000", - "accountStartNonce": "0x00", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID": "0x7", - "chainID": "0x7", - "eip155Transition": "0x0", - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" - }, - "genesis": { - "seal": { - "ethereum": { - "nonce": "0x0000000000000042", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "difficulty": "0x0400000000", - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x323031382045617374636f696e2050726f6a656374", - "gasLimit": "0x1388" - }, - "nodes": [ - "enode://ca57e40edb95a08a81b85a91e91099a0aaab777ad329ea7f3f772bc0fd511a276a5d84944725d181ff80f8c7dc1034814bff25b9723b03363d48617fed4b15f0@13.125.109.174:30303", - "enode://57254e23a7e5fe1e081ee5d1b236e37735a120660daeb4bf1fec6943a82c915c5b6fad23eeb1a43a27c23f236e084e8051aaa28f7d4139149f844747facb62bb@18.217.39.51:30303", - "enode://ef248f327c73c0318f4d51a62270b0612f3c4a4fd04b77d04854dc355980e137708d1e48811bc91387b0d7eb85cf447d8bbc095404f39bb7064e76751bda9cd4@52.221.160.236:30303", - "enode://bf6f0e37dd733cf04f2b079c753d2dea7cc7c59d8637eff9a8e63e17d08e2bfc91229fbb2dff08fe6ee12e51c1b6f8ed969d7042b89d77029e7ea02b05e17be3@18.197.47.177:30303" - ], - "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "20c1252a8cb33a7a9a257b2a4cfeed8daf87c847": { - "balance": "100000000000000000000000000" - }, - "9dcd37c8e5aea3a0d37c5d0a2db683362d81febd": { - "balance": "100000000000000000000000000" - }, - "9eff080302333f44a60bfd8c33bd63015c6d921b": { - "balance": "100000000000000000000000000" - }, - "c1df2e5de98d5c41fec0642dc302971f5d3500bd": { - "balance": "100000000000000000000000000" - }, - "2e0fb67cd1d029cbaea4b74c361efcc06b3105fd": { - "balance": "100000000000000000000000000" - }, - "2b6425cc3cd90654f077889ef7262ac2f5846460": { - "balance": "100000000000000000000000000" - }, - "28562041230c6d575e233e4ed1b35c514884d964": { - "balance": "100000000000000000000000000" - }, - "16eb6896a5a83d39ac762d79d21f825f5f980d12": { - "balance": "100000000000000000000000000" - }, - "f09e3f1de27dd03a1ac0a021b2d9e45bde1b360c": { - "balance": "100000000000000000000000000" - }, - "2d87547819c6433f208ee3096161cdb2835a2333": { - "balance": "100000000000000000000000000" - } - } + "name": "Easthub", + "dataDir": "easthub", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x2B5E3AF16B1880000", + "homesteadTransition": "0x0", + "bombDefuseTransition": "0x0", + "ecip1017EraRounds": 5000000 + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "registrar": "0x0000000000000000000000000000000000000000", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID": "0x7", + "chainID": "0x7", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip155Transition": "0x0", + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff", + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x0400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x323031382045617374636f696e2050726f6a656374", + "gasLimit": "0x1388" + }, + "nodes": [ + "enode://ca57e40edb95a08a81b85a91e91099a0aaab777ad329ea7f3f772bc0fd511a276a5d84944725d181ff80f8c7dc1034814bff25b9723b03363d48617fed4b15f0@13.125.109.174:30303", + "enode://57254e23a7e5fe1e081ee5d1b236e37735a120660daeb4bf1fec6943a82c915c5b6fad23eeb1a43a27c23f236e084e8051aaa28f7d4139149f844747facb62bb@18.217.39.51:30303", + "enode://ef248f327c73c0318f4d51a62270b0612f3c4a4fd04b77d04854dc355980e137708d1e48811bc91387b0d7eb85cf447d8bbc095404f39bb7064e76751bda9cd4@52.221.160.236:30303", + "enode://bf6f0e37dd733cf04f2b079c753d2dea7cc7c59d8637eff9a8e63e17d08e2bfc91229fbb2dff08fe6ee12e51c1b6f8ed969d7042b89d77029e7ea02b05e17be3@18.197.47.177:30303" + ], + "accounts": { + "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "20c1252a8cb33a7a9a257b2a4cfeed8daf87c847": { + "balance": "100000000000000000000000000" + }, + "9dcd37c8e5aea3a0d37c5d0a2db683362d81febd": { + "balance": "100000000000000000000000000" + }, + "9eff080302333f44a60bfd8c33bd63015c6d921b": { + "balance": "100000000000000000000000000" + }, + "c1df2e5de98d5c41fec0642dc302971f5d3500bd": { + "balance": "100000000000000000000000000" + }, + "2e0fb67cd1d029cbaea4b74c361efcc06b3105fd": { + "balance": "100000000000000000000000000" + }, + "2b6425cc3cd90654f077889ef7262ac2f5846460": { + "balance": "100000000000000000000000000" + }, + "28562041230c6d575e233e4ed1b35c514884d964": { + "balance": "100000000000000000000000000" + }, + "16eb6896a5a83d39ac762d79d21f825f5f980d12": { + "balance": "100000000000000000000000000" + }, + "f09e3f1de27dd03a1ac0a021b2d9e45bde1b360c": { + "balance": "100000000000000000000000000" + }, + "2d87547819c6433f208ee3096161cdb2835a2333": { + "balance": "100000000000000000000000000" + } + } } diff --git a/ethcore/res/ethereum/eip150_test.json b/ethcore/res/ethereum/eip150_test.json index 60157c57168..baf9c1b7bfc 100644 --- a/ethcore/res/ethereum/eip150_test.json +++ b/ethcore/res/ethereum/eip150_test.json @@ -7,11 +7,7 @@ "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", - "homesteadTransition": "0x0", - "eip150Transition": "0x0", - "eip160Transition": "0x7fffffffffffffff", - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "homesteadTransition": "0x0" } } }, @@ -22,6 +18,10 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", + "eip150Transition": "0x0", + "eip160Transition": "0x7fffffffffffffff", + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffffff", "eip86Transition": "0x7fffffffffffffff", "eip155Transition": "0x7fffffffffffffff", diff --git a/ethcore/res/ethereum/eip161_test.json b/ethcore/res/ethereum/eip161_test.json index ac1c0a5d1e3..079ce7d55a2 100644 --- a/ethcore/res/ethereum/eip161_test.json +++ b/ethcore/res/ethereum/eip161_test.json @@ -7,11 +7,7 @@ "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", - "homesteadTransition": "0x0", - "eip150Transition": "0x0", - "eip160Transition": "0x0", - "eip161abcTransition": "0x0", - "eip161dTransition": "0x0" + "homesteadTransition": "0x0" } } }, @@ -22,6 +18,10 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", "eip98Transition": "0x7fffffffffffffff", "eip86Transition": "0x7fffffffffffffff", "eip155Transition": "0x7fffffffffffffff", diff --git a/ethcore/res/ethereum/ellaism.json b/ethcore/res/ethereum/ellaism.json index 96c2016e55a..c3107bbe469 100644 --- a/ethcore/res/ethereum/ellaism.json +++ b/ethcore/res/ethereum/ellaism.json @@ -1,74 +1,74 @@ { - "name": "Ellaism", - "dataDir": "ellaism", - "engine": { - "Ethash": { - "params": { - "minimumDifficulty": "0x020000", - "difficultyBoundDivisor": "0x0800", - "durationLimit": "0x0d", - "blockReward": "0x4563918244F40000", - "homesteadTransition": "0x0", - "bombDefuseTransition": "0x0", - "eip150Transition": "0x0", - "eip160Transition": "0x0", - "ecip1017EraRounds": 10000000, - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff", - "eip100bTransition": 2000000 - } - } - }, - "params": { - "gasLimitBoundDivisor": "0x0400", - "registrar": "0x3bb2bb5c6c9c9b7f4EF430b47Dc7e026310042ea", - "accountStartNonce": "0x00", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID": "0x40", - "chainID": "0x40", - "eip155Transition": "0x0", - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", - "wasmActivationTransition": 2000000, - "eip140Transition": 2000000, - "eip211Transition": 2000000, - "eip214Transition": 2000000, - "eip658Transition": 2000000 - }, - "genesis": { - "seal": { - "ethereum": { - "nonce": "0x0000000000000040", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "difficulty": "0x40000000", - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", - "gasLimit": "0x1388" - }, - "nodes": [ - "enode://0d88e242aa0b01ee306ca43e956174677c96ec8eba4197f4d8be6fd7d4f2e57731e95d533b88229b66eb1a44399d870e99b7a4fe6547c8c80cdf00407a986e14@94.130.237.158:30303", - "enode://4be9e419d3efb0214faf3ef1794a0c33ebbd7633ece734a0a956faa166fefc496b2692a2a485adc66af805e461ba3e12f8d3941ec207e56bb9f3d3626787a705@94.130.237.158:60606", - "enode://834246cc2a7584df29ccdcf3b5366f118a0e291264980376769e809665a02c4caf0d68c43eecf8390dbeaf861823b05583807af0a62542a1f3f717046b958a76@45.77.106.33:30303", - "enode://d8059dcb137cb52b8960ca82613eeba1d121105572decd8f1d3ea22b09070645eeab548d2a3cd2914f206e1331c7870bd2bd5a231ebac6b3d4886ec3b8e627e5@173.212.216.105:30303", - "enode://9215ad77bd081e35013cb42a8ceadff9d8e94a78fcc680dff1752a54e7484badff0904e331c4b40a68be593782e55acfd800f076d22f9d2832e8483733ade149@213.14.82.125:30303", - "enode://5dd35866da95aea15211fb1f98684f6e8c4e355e6aa3cc17585680ed53fa164477b8c52cb6ca4b24ec4d80f3d48ff9212b53feb131d825c7945a3abaaf02d24d@178.79.189.58:60606", - "enode://6c585c18024eb902ca093278af73b04863ac904caabc39ac2920c23532307c572ad92afd828a990c980d272b1f26307f2409cc97aec3ff9fe866732cae49a8c2@144.217.163.224:31337", - "enode://edd90c4cc64528802ad52fd127d80b641ff80fd43fa5292fb111c8bd2914482dffee288fd1b0d26440c6b2c669b10a53cbcd37c895ba0d6194110e100a965b2d@188.166.179.159:30303", - "enode://9d960373335c1cc38ca696dea8f2893e2a071c8f21524f21e8aae22be032acc3b67797b1d21e866f9d832943ae7d9555b8466c6ab34f473d21e547114952df37@213.32.53.183:30303" - ], - "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 2000000, "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 2000000, "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 2000000, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 2000000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } - } + "name": "Ellaism", + "dataDir": "ellaism", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "homesteadTransition": "0x0", + "bombDefuseTransition": "0x0", + "ecip1017EraRounds": 10000000, + "eip100bTransition": 2000000 + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "registrar": "0x3bb2bb5c6c9c9b7f4EF430b47Dc7e026310042ea", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID": "0x40", + "chainID": "0x40", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff", + "eip155Transition": "0x0", + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff", + "wasmActivationTransition": 2000000, + "eip140Transition": 2000000, + "eip211Transition": 2000000, + "eip214Transition": 2000000, + "eip658Transition": 2000000 + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000040", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x40000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1388" + }, + "nodes": [ + "enode://0d88e242aa0b01ee306ca43e956174677c96ec8eba4197f4d8be6fd7d4f2e57731e95d533b88229b66eb1a44399d870e99b7a4fe6547c8c80cdf00407a986e14@94.130.237.158:30303", + "enode://4be9e419d3efb0214faf3ef1794a0c33ebbd7633ece734a0a956faa166fefc496b2692a2a485adc66af805e461ba3e12f8d3941ec207e56bb9f3d3626787a705@94.130.237.158:60606", + "enode://834246cc2a7584df29ccdcf3b5366f118a0e291264980376769e809665a02c4caf0d68c43eecf8390dbeaf861823b05583807af0a62542a1f3f717046b958a76@45.77.106.33:30303", + "enode://d8059dcb137cb52b8960ca82613eeba1d121105572decd8f1d3ea22b09070645eeab548d2a3cd2914f206e1331c7870bd2bd5a231ebac6b3d4886ec3b8e627e5@173.212.216.105:30303", + "enode://9215ad77bd081e35013cb42a8ceadff9d8e94a78fcc680dff1752a54e7484badff0904e331c4b40a68be593782e55acfd800f076d22f9d2832e8483733ade149@213.14.82.125:30303", + "enode://5dd35866da95aea15211fb1f98684f6e8c4e355e6aa3cc17585680ed53fa164477b8c52cb6ca4b24ec4d80f3d48ff9212b53feb131d825c7945a3abaaf02d24d@178.79.189.58:60606", + "enode://6c585c18024eb902ca093278af73b04863ac904caabc39ac2920c23532307c572ad92afd828a990c980d272b1f26307f2409cc97aec3ff9fe866732cae49a8c2@144.217.163.224:31337", + "enode://edd90c4cc64528802ad52fd127d80b641ff80fd43fa5292fb111c8bd2914482dffee288fd1b0d26440c6b2c669b10a53cbcd37c895ba0d6194110e100a965b2d@188.166.179.159:30303", + "enode://9d960373335c1cc38ca696dea8f2893e2a071c8f21524f21e8aae22be032acc3b67797b1d21e866f9d832943ae7d9555b8466c6ab34f473d21e547114952df37@213.32.53.183:30303" + ], + "accounts": { + "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 2000000, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 2000000, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 2000000, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 2000000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + } } diff --git a/ethcore/res/ethereum/expanse.json b/ethcore/res/ethereum/expanse.json index b9b734e313d..2061231c60d 100644 --- a/ethcore/res/ethereum/expanse.json +++ b/ethcore/res/ethereum/expanse.json @@ -13,10 +13,6 @@ "difficultyHardforkTransition": "0x59d9", "difficultyHardforkBoundDivisor": "0x0200", "bombDefuseTransition": "0x30d40", - "eip150Transition": "0x927C0", - "eip160Transition": "0x927C0", - "eip161abcTransition": "0x927C0", - "eip161dTransition": "0x927C0", "eip100bTransition": "0xC3500", "metropolisDifficultyIncrementDivisor": "0x1E", "eip649Transition": "0xC3500", @@ -37,6 +33,10 @@ "forkBlock": "0xDBBA0", "forkCanonHash": "0x8e7bed51e24f5174090408664ac476b90b5e1199a947af7442f1ac88263fc8c7", "subprotocolName": "exp", + "eip150Transition": "0x927C0", + "eip160Transition": "0x927C0", + "eip161abcTransition": "0x927C0", + "eip161dTransition": "0x927C0", "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x927C0", diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 6658b5e5227..b725c9f7c02 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -129,10 +129,6 @@ "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", "0x807640a13483f8ac783c557fcdf27be11ea4ac7a" ], - "eip150Transition": "0x259518", - "eip160Transition": 2675000, - "eip161abcTransition": 2675000, - "eip161dTransition": 2675000, "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": 4370000, "eip649Transition": 4370000 @@ -148,6 +144,10 @@ "networkID" : "0x1", "forkBlock": "0x1d4c00", "forkCanonHash": "0x4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb", + "eip150Transition": "0x259518", + "eip160Transition": 2675000, + "eip161abcTransition": 2675000, + "eip161dTransition": 2675000, "eip155Transition": 2675000, "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff", diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index 6d2ea3693df..7eac5acbd0a 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -127,11 +127,7 @@ "0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97", "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", "0x807640a13483f8ac783c557fcdf27be11ea4ac7a" - ], - "eip150Transition": "0x7fffffffffffffff", - "eip160Transition": "0x7fffffffffffffff", - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + ] } } }, @@ -142,6 +138,10 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", + "eip150Transition": "0x7fffffffffffffff", + "eip160Transition": "0x7fffffffffffffff", + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff" diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json index aae59cb071e..7e52f6ecf97 100644 --- a/ethcore/res/ethereum/frontier_test.json +++ b/ethcore/res/ethereum/frontier_test.json @@ -7,11 +7,7 @@ "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", - "homesteadTransition": "0x7fffffffffffffff", - "eip150Transition": "0x7fffffffffffffff", - "eip160Transition": "0x7fffffffffffffff", - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "homesteadTransition": "0x7fffffffffffffff" } } }, @@ -22,6 +18,10 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", + "eip150Transition": "0x7fffffffffffffff", + "eip160Transition": "0x7fffffffffffffff", + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff" diff --git a/ethcore/res/ethereum/homestead_test.json b/ethcore/res/ethereum/homestead_test.json index c6d49b54556..817bf5ff57f 100644 --- a/ethcore/res/ethereum/homestead_test.json +++ b/ethcore/res/ethereum/homestead_test.json @@ -7,11 +7,7 @@ "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", - "homesteadTransition": "0x0", - "eip150Transition": "0x7fffffffffffffff", - "eip160Transition": "0x7fffffffffffffff", - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "homesteadTransition": "0x0" } } }, @@ -24,7 +20,11 @@ "networkID" : "0x1", "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff", - "eip155Transition": "0x7fffffffffffffff" + "eip155Transition": "0x7fffffffffffffff", + "eip150Transition": "0x7fffffffffffffff", + "eip160Transition": "0x7fffffffffffffff", + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/mcip3_test.json b/ethcore/res/ethereum/mcip3_test.json index d2e5ec8b6bc..391a625730a 100644 --- a/ethcore/res/ethereum/mcip3_test.json +++ b/ethcore/res/ethereum/mcip3_test.json @@ -1,168 +1,168 @@ { - "name":"MCIP3 Test", - "dataDir":"mcip3test", - "engine":{ - "Ethash":{ - "params":{ - "minimumDifficulty":"0x020000", - "difficultyBoundDivisor":"0x0800", - "durationLimit":"0x0d", - "homesteadTransition":"0x118c30", - "eip100bTransition":"0x7fffffffffffff", - "eip150Transition":"0x7fffffffffffff", - "eip160Transition":"0x7fffffffffffff", - "eip161abcTransition":"0x7fffffffffffff", - "eip161dTransition":"0x7fffffffffffff", - "eip649Transition":"0x7fffffffffffff", - "blockReward":"0x1105a0185b50a80000", - "mcip3Transition":"0x00", - "mcip3MinerReward":"0xd8d726b7177a80000", - "mcip3UbiReward":"0x2b5e3af16b1880000", - "mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310", - "mcip3DevReward":"0xc249fdd327780000", - "mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536" - } - } - }, - "params":{ - "gasLimitBoundDivisor":"0x0400", - "registrar":"0x5C271c4C9A67E7D73b7b3669d47504741354f21D", - "accountStartNonce":"0x00", - "maximumExtraDataSize":"0x20", - "minGasLimit":"0x1388", - "networkID":"0x76740b", - "forkBlock":"0x5b6", - "forkCanonHash":"0xa5e88ad9e34d113e264e307bc27e8471452c8fc13780324bb3abb96fd0558343", - "eip86Transition":"0x7fffffffffffff", - "eip98Transition":"0x7fffffffffffff", - "eip140Transition":"0x7fffffffffffff", - "eip155Transition":"0x7fffffffffffff", - "eip211Transition":"0x7fffffffffffff", - "eip214Transition":"0x7fffffffffffff", - "eip658Transition":"0x7fffffffffffff", - "maxCodeSize":"0x6000", - "maxCodeSizeTransition": "0x7fffffffffffff" - }, - "genesis":{ - "seal":{ - "ethereum":{ - "nonce":"0x000000000000002a", - "mixHash":"0x00000000000000000000000000000000000000647572616c65787365646c6578" - } - }, - "difficulty":"0x3d0900", - "author":"0x0000000000000000000000000000000000000000", - "timestamp":"0x00", - "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData":"", - "gasLimit":"0x7a1200" - }, - "nodes":[ - "enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303", - "enode://3f1d12044546b76342d59d4a05532c14b85aa669704bfe1f864fe079415aa2c02d743e03218e57a33fb94523adb54032871a6c51b2cc5514cb7c7e35b3ed0a99@13.93.211.84:30303", - "enode://78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d@191.235.84.50:30303", - "enode://158f8aab45f6d19c6cbf4a089c2670541a8da11978a2f90dbf6a502a4a3bab80d288afdbeb7ec0ef6d92de563767f3b1ea9e8e334ca711e9f8e2df5a0385e8e6@13.75.154.138:30303", - "enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303", - "enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303", - "enode://d302f52c8789ad87ee528f1431a67f1aa646c9bec17babb4665dfb3d61de5b9119a70aa77b2147a5f28854092ba09769323c1c552a6ac6f6a34cbcf767e2d2fe@158.69.248.48:30303", - "enode://c72564bce8331ae298fb8ece113a456e3927d7e5989c2be3e445678b3600579f722410ef9bbfe339335d676af77343cb21b5b1703b7bebc32be85fce937a2220@191.252.185.71:30303", - "enode://e3ae4d25ee64791ff98bf17c37acf90933359f2505c00f65c84f6863231a32a94153cadb0a462e428f18f35ded6bd91cd91033d26576a28558c22678be9cfaee@5.63.158.137:35555" - ], - "accounts":{ - "0000000000000000000000000000000000000001":{ - "balance":"1", - "builtin":{ - "name":"ecrecover", - "pricing":{ - "linear":{ - "base":3000, - "word":0 - } - } - } - }, - "0000000000000000000000000000000000000002":{ - "balance":"1", - "builtin":{ - "name":"sha256", - "pricing":{ - "linear":{ - "base":60, - "word":12 - } - } - } - }, - "0000000000000000000000000000000000000003":{ - "balance":"1", - "builtin":{ - "name":"ripemd160", - "pricing":{ - "linear":{ - "base":600, - "word":120 - } - } - } - }, - "0000000000000000000000000000000000000004":{ - "balance":"1", - "builtin":{ - "name":"identity", - "pricing":{ - "linear":{ - "base":15, - "word":3 - } - } - } - }, - "0000000000000000000000000000000000000005":{ - "builtin":{ - "name":"modexp", - "activate_at":"0x7fffffffffffff", - "pricing":{ - "modexp":{ - "divisor":20 - } - } - } - }, - "0000000000000000000000000000000000000006":{ - "builtin":{ - "name":"alt_bn128_add", - "activate_at":"0x7fffffffffffff", - "pricing":{ - "linear":{ - "base":500, - "word":0 - } - } - } - }, - "0000000000000000000000000000000000000007":{ - "builtin":{ - "name":"alt_bn128_mul", - "activate_at":"0x7fffffffffffff", - "pricing":{ - "linear":{ - "base":40000, - "word":0 - } - } - } - }, - "0000000000000000000000000000000000000008":{ - "builtin":{ - "name":"alt_bn128_pairing", - "activate_at":"0x7fffffffffffff", - "pricing":{ - "alt_bn128_pairing":{ - "base":100000, - "pair":80000 - } - } - } - } - } + "name":"MCIP3 Test", + "dataDir":"mcip3test", + "engine":{ + "Ethash":{ + "params":{ + "minimumDifficulty":"0x020000", + "difficultyBoundDivisor":"0x0800", + "durationLimit":"0x0d", + "homesteadTransition":"0x118c30", + "eip100bTransition":"0x7fffffffffffff", + "eip649Transition":"0x7fffffffffffff", + "blockReward":"0x1105a0185b50a80000", + "mcip3Transition":"0x00", + "mcip3MinerReward":"0xd8d726b7177a80000", + "mcip3UbiReward":"0x2b5e3af16b1880000", + "mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310", + "mcip3DevReward":"0xc249fdd327780000", + "mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536" + } + } + }, + "params":{ + "gasLimitBoundDivisor":"0x0400", + "registrar":"0x5C271c4C9A67E7D73b7b3669d47504741354f21D", + "accountStartNonce":"0x00", + "maximumExtraDataSize":"0x20", + "minGasLimit":"0x1388", + "networkID":"0x76740b", + "forkBlock":"0x5b6", + "forkCanonHash":"0xa5e88ad9e34d113e264e307bc27e8471452c8fc13780324bb3abb96fd0558343", + "eip150Transition":"0x7fffffffffffff", + "eip160Transition":"0x7fffffffffffff", + "eip161abcTransition":"0x7fffffffffffff", + "eip161dTransition":"0x7fffffffffffff", + "eip86Transition":"0x7fffffffffffff", + "eip98Transition":"0x7fffffffffffff", + "eip140Transition":"0x7fffffffffffff", + "eip155Transition":"0x7fffffffffffff", + "eip211Transition":"0x7fffffffffffff", + "eip214Transition":"0x7fffffffffffff", + "eip658Transition":"0x7fffffffffffff", + "maxCodeSize":"0x6000", + "maxCodeSizeTransition": "0x7fffffffffffff" + }, + "genesis":{ + "seal":{ + "ethereum":{ + "nonce":"0x000000000000002a", + "mixHash":"0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty":"0x3d0900", + "author":"0x0000000000000000000000000000000000000000", + "timestamp":"0x00", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData":"", + "gasLimit":"0x7a1200" + }, + "nodes":[ + "enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303", + "enode://3f1d12044546b76342d59d4a05532c14b85aa669704bfe1f864fe079415aa2c02d743e03218e57a33fb94523adb54032871a6c51b2cc5514cb7c7e35b3ed0a99@13.93.211.84:30303", + "enode://78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d@191.235.84.50:30303", + "enode://158f8aab45f6d19c6cbf4a089c2670541a8da11978a2f90dbf6a502a4a3bab80d288afdbeb7ec0ef6d92de563767f3b1ea9e8e334ca711e9f8e2df5a0385e8e6@13.75.154.138:30303", + "enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303", + "enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303", + "enode://d302f52c8789ad87ee528f1431a67f1aa646c9bec17babb4665dfb3d61de5b9119a70aa77b2147a5f28854092ba09769323c1c552a6ac6f6a34cbcf767e2d2fe@158.69.248.48:30303", + "enode://c72564bce8331ae298fb8ece113a456e3927d7e5989c2be3e445678b3600579f722410ef9bbfe339335d676af77343cb21b5b1703b7bebc32be85fce937a2220@191.252.185.71:30303", + "enode://e3ae4d25ee64791ff98bf17c37acf90933359f2505c00f65c84f6863231a32a94153cadb0a462e428f18f35ded6bd91cd91033d26576a28558c22678be9cfaee@5.63.158.137:35555" + ], + "accounts":{ + "0000000000000000000000000000000000000001":{ + "balance":"1", + "builtin":{ + "name":"ecrecover", + "pricing":{ + "linear":{ + "base":3000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000002":{ + "balance":"1", + "builtin":{ + "name":"sha256", + "pricing":{ + "linear":{ + "base":60, + "word":12 + } + } + } + }, + "0000000000000000000000000000000000000003":{ + "balance":"1", + "builtin":{ + "name":"ripemd160", + "pricing":{ + "linear":{ + "base":600, + "word":120 + } + } + } + }, + "0000000000000000000000000000000000000004":{ + "balance":"1", + "builtin":{ + "name":"identity", + "pricing":{ + "linear":{ + "base":15, + "word":3 + } + } + } + }, + "0000000000000000000000000000000000000005":{ + "builtin":{ + "name":"modexp", + "activate_at":"0x7fffffffffffff", + "pricing":{ + "modexp":{ + "divisor":20 + } + } + } + }, + "0000000000000000000000000000000000000006":{ + "builtin":{ + "name":"alt_bn128_add", + "activate_at":"0x7fffffffffffff", + "pricing":{ + "linear":{ + "base":500, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000007":{ + "builtin":{ + "name":"alt_bn128_mul", + "activate_at":"0x7fffffffffffff", + "pricing":{ + "linear":{ + "base":40000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000008":{ + "builtin":{ + "name":"alt_bn128_pairing", + "activate_at":"0x7fffffffffffff", + "pricing":{ + "alt_bn128_pairing":{ + "base":100000, + "pair":80000 + } + } + } + } + } } diff --git a/ethcore/res/ethereum/mcip6_byz.json b/ethcore/res/ethereum/mcip6_byz.json index 8028e6b1bbb..a12df7c7115 100644 --- a/ethcore/res/ethereum/mcip6_byz.json +++ b/ethcore/res/ethereum/mcip6_byz.json @@ -1,161 +1,161 @@ { - "name":"Musicoin Byzantium Test", - "dataDir":"mcip6test", - "engine":{ - "Ethash":{ - "params":{ - "minimumDifficulty":"0x020000", - "difficultyBoundDivisor":"0x0800", - "durationLimit":"0x0d", - "homesteadTransition":"0x17", - "eip100bTransition":"0x2a", - "eip150Transition":"0x2a", - "eip160Transition":"0x7fffffffffffff", - "eip161abcTransition":"0x7fffffffffffff", - "eip161dTransition":"0x7fffffffffffff", - "eip649Transition":"0x2a", - "blockReward":"0x1105a0185b50a80000", - "mcip3Transition":"0x17", - "mcip3MinerReward":"0xd8d726b7177a80000", - "mcip3UbiReward":"0x2b5e3af16b1880000", - "mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310", - "mcip3DevReward":"0xc249fdd327780000", - "mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536" - } - } - }, - "params":{ - "gasLimitBoundDivisor":"0x0400", - "registrar":"0x5C271c4C9A67E7D73b7b3669d47504741354f21D", - "accountStartNonce":"0x00", - "maximumExtraDataSize":"0x20", - "minGasLimit":"0x1388", - "networkID":"0x76740c", - "forkBlock":"0x2b", - "forkCanonHash":"0x23c3171e864a5d513a3ef85e4cf86dac4cc36b89e5b8e63bf0ebcca68b9e43c9", - "eip86Transition":"0x7fffffffffffff", - "eip98Transition":"0x7fffffffffffff", - "eip140Transition":"0x2a", - "eip155Transition":"0x2a", - "eip211Transition":"0x2a", - "eip214Transition":"0x2a", - "eip658Transition":"0x2a", - "maxCodeSize":"0x6000", - "maxCodeSizeTransition": "0x7fffffffffffff" - }, - "genesis":{ - "seal":{ - "ethereum":{ - "nonce":"0x000000000000002a", - "mixHash":"0x00000000000000000000000000000000000000647572616c65787365646c6578" - } - }, - "difficulty":"0x3d0900", - "author":"0x0000000000000000000000000000000000000000", - "timestamp":"0x00", - "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData":"", - "gasLimit":"0x7a1200" - }, - "nodes":[ - "enode://5ddc110733f6d34101973cdef3f9b43484159acf6f816d3b1ee92bc3c98ea453e857bb1207edf0ec0242008ab3a0f9f05eeaee99d47bd414c08a5bdf4847de13@176.9.3.148:30303", - "enode://38f074f4db8e64dfbaf87984bf290eef67772a901a7113d1b62f36216be152b8450c393d6fc562a5e38f04f99bc8f439a99010a230b1d92dc1df43bf0bd00615@176.9.3.148:30403" - ], - "accounts":{ - "0000000000000000000000000000000000000001":{ - "balance":"1", - "builtin":{ - "name":"ecrecover", - "pricing":{ - "linear":{ - "base":3000, - "word":0 - } - } - } - }, - "0000000000000000000000000000000000000002":{ - "balance":"1", - "builtin":{ - "name":"sha256", - "pricing":{ - "linear":{ - "base":60, - "word":12 - } - } - } - }, - "0000000000000000000000000000000000000003":{ - "balance":"1", - "builtin":{ - "name":"ripemd160", - "pricing":{ - "linear":{ - "base":600, - "word":120 - } - } - } - }, - "0000000000000000000000000000000000000004":{ - "balance":"1", - "builtin":{ - "name":"identity", - "pricing":{ - "linear":{ - "base":15, - "word":3 - } - } - } - }, - "0000000000000000000000000000000000000005":{ - "builtin":{ - "name":"modexp", - "activate_at":"0x2a", - "pricing":{ - "modexp":{ - "divisor":20 - } - } - } - }, - "0000000000000000000000000000000000000006":{ - "builtin":{ - "name":"alt_bn128_add", - "activate_at":"0x2a", - "pricing":{ - "linear":{ - "base":500, - "word":0 - } - } - } - }, - "0000000000000000000000000000000000000007":{ - "builtin":{ - "name":"alt_bn128_mul", - "activate_at":"0x2a", - "pricing":{ - "linear":{ - "base":40000, - "word":0 - } - } - } - }, - "0000000000000000000000000000000000000008":{ - "builtin":{ - "name":"alt_bn128_pairing", - "activate_at":"0x2a", - "pricing":{ - "alt_bn128_pairing":{ - "base":100000, - "pair":80000 - } - } - } - } - } + "name":"Musicoin Byzantium Test", + "dataDir":"mcip6test", + "engine":{ + "Ethash":{ + "params":{ + "minimumDifficulty":"0x020000", + "difficultyBoundDivisor":"0x0800", + "durationLimit":"0x0d", + "homesteadTransition":"0x17", + "eip100bTransition":"0x2a", + "eip649Transition":"0x2a", + "blockReward":"0x1105a0185b50a80000", + "mcip3Transition":"0x17", + "mcip3MinerReward":"0xd8d726b7177a80000", + "mcip3UbiReward":"0x2b5e3af16b1880000", + "mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310", + "mcip3DevReward":"0xc249fdd327780000", + "mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536" + } + } + }, + "params":{ + "gasLimitBoundDivisor":"0x0400", + "registrar":"0x5C271c4C9A67E7D73b7b3669d47504741354f21D", + "accountStartNonce":"0x00", + "maximumExtraDataSize":"0x20", + "minGasLimit":"0x1388", + "networkID":"0x76740c", + "forkBlock":"0x2b", + "forkCanonHash":"0x23c3171e864a5d513a3ef85e4cf86dac4cc36b89e5b8e63bf0ebcca68b9e43c9", + "eip150Transition":"0x2a", + "eip160Transition":"0x7fffffffffffff", + "eip161abcTransition":"0x7fffffffffffff", + "eip161dTransition":"0x7fffffffffffff", + "eip86Transition":"0x7fffffffffffff", + "eip98Transition":"0x7fffffffffffff", + "eip140Transition":"0x2a", + "eip155Transition":"0x2a", + "eip211Transition":"0x2a", + "eip214Transition":"0x2a", + "eip658Transition":"0x2a", + "maxCodeSize":"0x6000", + "maxCodeSizeTransition": "0x7fffffffffffff" + }, + "genesis":{ + "seal":{ + "ethereum":{ + "nonce":"0x000000000000002a", + "mixHash":"0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty":"0x3d0900", + "author":"0x0000000000000000000000000000000000000000", + "timestamp":"0x00", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData":"", + "gasLimit":"0x7a1200" + }, + "nodes":[ + "enode://5ddc110733f6d34101973cdef3f9b43484159acf6f816d3b1ee92bc3c98ea453e857bb1207edf0ec0242008ab3a0f9f05eeaee99d47bd414c08a5bdf4847de13@176.9.3.148:30303", + "enode://38f074f4db8e64dfbaf87984bf290eef67772a901a7113d1b62f36216be152b8450c393d6fc562a5e38f04f99bc8f439a99010a230b1d92dc1df43bf0bd00615@176.9.3.148:30403" + ], + "accounts":{ + "0000000000000000000000000000000000000001":{ + "balance":"1", + "builtin":{ + "name":"ecrecover", + "pricing":{ + "linear":{ + "base":3000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000002":{ + "balance":"1", + "builtin":{ + "name":"sha256", + "pricing":{ + "linear":{ + "base":60, + "word":12 + } + } + } + }, + "0000000000000000000000000000000000000003":{ + "balance":"1", + "builtin":{ + "name":"ripemd160", + "pricing":{ + "linear":{ + "base":600, + "word":120 + } + } + } + }, + "0000000000000000000000000000000000000004":{ + "balance":"1", + "builtin":{ + "name":"identity", + "pricing":{ + "linear":{ + "base":15, + "word":3 + } + } + } + }, + "0000000000000000000000000000000000000005":{ + "builtin":{ + "name":"modexp", + "activate_at":"0x2a", + "pricing":{ + "modexp":{ + "divisor":20 + } + } + } + }, + "0000000000000000000000000000000000000006":{ + "builtin":{ + "name":"alt_bn128_add", + "activate_at":"0x2a", + "pricing":{ + "linear":{ + "base":500, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000007":{ + "builtin":{ + "name":"alt_bn128_mul", + "activate_at":"0x2a", + "pricing":{ + "linear":{ + "base":40000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000008":{ + "builtin":{ + "name":"alt_bn128_pairing", + "activate_at":"0x2a", + "pricing":{ + "alt_bn128_pairing":{ + "base":100000, + "pair":80000 + } + } + } + } + } } diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index bca9919903e..b61799c0c9d 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -9,13 +9,9 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "homesteadTransition": 494000, - "eip150Transition": 1783000, - "eip160Transition": 1915000, "ecip1010PauseTransition": 1915000, "ecip1010ContinueTransition": 3415000, "ecip1017EraRounds": 2000000, - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff", "bombDefuseTransition": 2300000 } } @@ -30,6 +26,10 @@ "chainID": "0x3e", "forkBlock": "0x1b34d8", "forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145", + "eip150Transition": 1783000, + "eip160Transition": 1915000, + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff", "eip155Transition": 1915000, "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff" diff --git a/ethcore/res/ethereum/musicoin.json b/ethcore/res/ethereum/musicoin.json index 6d5f6835bd9..724f11478bf 100644 --- a/ethcore/res/ethereum/musicoin.json +++ b/ethcore/res/ethereum/musicoin.json @@ -1,164 +1,164 @@ { - "name":"Musicoin", - "dataDir":"musicoin", - "engine":{ - "Ethash":{ - "params":{ - "minimumDifficulty":"0x020000", - "difficultyBoundDivisor":"0x0800", - "durationLimit":"0x0d", - "homesteadTransition":"0x118c30", - "eip100bTransition":"0x21e88e", - "eip150Transition":"0x21e88e", - "eip160Transition":"0x21e88e", - "eip161abcTransition":"0x21e88e", - "eip161dTransition":"0x21e88e", - "eip649Transition":"0x21e88e", - "blockReward":"0x1105a0185b50a80000", - "mcip3Transition":"0x124f81", - "mcip3MinerReward":"0xd8d726b7177a80000", - "mcip3UbiReward":"0x2b5e3af16b1880000", - "mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310", - "mcip3DevReward":"0xc249fdd327780000", - "mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536" - } - } - }, - "params":{ - "gasLimitBoundDivisor":"0x0400", - "registrar":"0x5C271c4C9A67E7D73b7b3669d47504741354f21D", - "accountStartNonce":"0x00", - "maximumExtraDataSize":"0x20", - "minGasLimit":"0x1388", - "networkID":"0x76740f", - "forkBlock":"0x1d8015", - "forkCanonHash":"0x380602acf82b629a0be6b5adb2b4a801e960a07dc8261bf196d21befdbb8f2f9", - "eip86Transition":"0x7fffffffffffff", - "eip98Transition":"0x7fffffffffffff", - "eip140Transition":"0x21e88e", - "eip155Transition":"0x21e88e", - "eip211Transition":"0x21e88e", - "eip214Transition":"0x21e88e", - "eip658Transition":"0x21e88e", - "maxCodeSize":"0x6000" - }, - "genesis":{ - "seal":{ - "ethereum":{ - "nonce":"0x000000000000002a", - "mixHash":"0x00000000000000000000000000000000000000647572616c65787365646c6578" - } - }, - "difficulty":"0x3d0900", - "author":"0x0000000000000000000000000000000000000000", - "timestamp":"0x00", - "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData":"", - "gasLimit":"0x7a1200" - }, - "nodes":[ - "enode://09fcd36d553044c8b499b9b9e13a228ffd99572c513f77073d41f009717c464cd4399c0e665d6aff1590324254ee4e698b2b2533b1998dd04d896b9d6aff7895@35.185.67.35:30303", - "enode://89e51a34770a0badf8ea18c4c4d2c361cde707abd60031d99b1ab3010363e1898230a516ddb37d974af8d8db1b322779d7fe0caae0617bed4924d1b4968cf92b@35.231.48.142:30303", - "enode://b58c0c71f08864c0cf7fa9dea2c4cbefae5ae7a36cc30d286603b24982d25f3ccc056b589119324c51768fc2054b8c529ecf682e06e1e9980170b93ff194ed7a@132.148.132.9:30303", - "enode://d302f52c8789ad87ee528f1431a67f1aa646c9bec17babb4665dfb3d61de5b9119a70aa77b2147a5f28854092ba09769323c1c552a6ac6f6a34cbcf767e2d2fe@158.69.248.48:30303", - "enode://c72564bce8331ae298fb8ece113a456e3927d7e5989c2be3e445678b3600579f722410ef9bbfe339335d676af77343cb21b5b1703b7bebc32be85fce937a2220@191.252.185.71:30303", - "enode://e3ae4d25ee64791ff98bf17c37acf90933359f2505c00f65c84f6863231a32a94153cadb0a462e428f18f35ded6bd91cd91033d26576a28558c22678be9cfaee@5.63.158.137:35555" - ], - "accounts":{ - "0000000000000000000000000000000000000001":{ - "balance":"1", - "builtin":{ - "name":"ecrecover", - "pricing":{ - "linear":{ - "base":3000, - "word":0 - } - } - } - }, - "0000000000000000000000000000000000000002":{ - "balance":"1", - "builtin":{ - "name":"sha256", - "pricing":{ - "linear":{ - "base":60, - "word":12 - } - } - } - }, - "0000000000000000000000000000000000000003":{ - "balance":"1", - "builtin":{ - "name":"ripemd160", - "pricing":{ - "linear":{ - "base":600, - "word":120 - } - } - } - }, - "0000000000000000000000000000000000000004":{ - "balance":"1", - "builtin":{ - "name":"identity", - "pricing":{ - "linear":{ - "base":15, - "word":3 - } - } - } - }, - "0000000000000000000000000000000000000005":{ - "builtin":{ - "name":"modexp", - "activate_at":"0x21e88e", - "pricing":{ - "modexp":{ - "divisor":20 - } - } - } - }, - "0000000000000000000000000000000000000006":{ - "builtin":{ - "name":"alt_bn128_add", - "activate_at":"0x21e88e", - "pricing":{ - "linear":{ - "base":500, - "word":0 - } - } - } - }, - "0000000000000000000000000000000000000007":{ - "builtin":{ - "name":"alt_bn128_mul", - "activate_at":"0x21e88e", - "pricing":{ - "linear":{ - "base":40000, - "word":0 - } - } - } - }, - "0000000000000000000000000000000000000008":{ - "builtin":{ - "name":"alt_bn128_pairing", - "activate_at":"0x21e88e", - "pricing":{ - "alt_bn128_pairing":{ - "base":100000, - "pair":80000 - } - } - } - } - } + "name":"Musicoin", + "dataDir":"musicoin", + "engine":{ + "Ethash":{ + "params":{ + "minimumDifficulty":"0x020000", + "difficultyBoundDivisor":"0x0800", + "durationLimit":"0x0d", + "homesteadTransition":"0x118c30", + "eip100bTransition":"0x21e88e", + "eip649Transition":"0x21e88e", + "blockReward":"0x1105a0185b50a80000", + "mcip3Transition":"0x124f81", + "mcip3MinerReward":"0xd8d726b7177a80000", + "mcip3UbiReward":"0x2b5e3af16b1880000", + "mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310", + "mcip3DevReward":"0xc249fdd327780000", + "mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536" + } + } + }, + "params":{ + "gasLimitBoundDivisor":"0x0400", + "registrar":"0x5C271c4C9A67E7D73b7b3669d47504741354f21D", + "accountStartNonce":"0x00", + "maximumExtraDataSize":"0x20", + "minGasLimit":"0x1388", + "networkID":"0x76740f", + "forkBlock":"0x1d8015", + "forkCanonHash":"0x380602acf82b629a0be6b5adb2b4a801e960a07dc8261bf196d21befdbb8f2f9", + "eip150Transition":"0x21e88e", + "eip160Transition":"0x21e88e", + "eip161abcTransition":"0x21e88e", + "eip161dTransition":"0x21e88e", + "eip86Transition":"0x7fffffffffffff", + "eip98Transition":"0x7fffffffffffff", + "eip140Transition":"0x21e88e", + "eip155Transition":"0x21e88e", + "eip211Transition":"0x21e88e", + "eip214Transition":"0x21e88e", + "eip658Transition":"0x21e88e", + "maxCodeSize":"0x6000" + }, + "genesis":{ + "seal":{ + "ethereum":{ + "nonce":"0x000000000000002a", + "mixHash":"0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty":"0x3d0900", + "author":"0x0000000000000000000000000000000000000000", + "timestamp":"0x00", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData":"", + "gasLimit":"0x7a1200" + }, + "nodes":[ + "enode://09fcd36d553044c8b499b9b9e13a228ffd99572c513f77073d41f009717c464cd4399c0e665d6aff1590324254ee4e698b2b2533b1998dd04d896b9d6aff7895@35.185.67.35:30303", + "enode://89e51a34770a0badf8ea18c4c4d2c361cde707abd60031d99b1ab3010363e1898230a516ddb37d974af8d8db1b322779d7fe0caae0617bed4924d1b4968cf92b@35.231.48.142:30303", + "enode://b58c0c71f08864c0cf7fa9dea2c4cbefae5ae7a36cc30d286603b24982d25f3ccc056b589119324c51768fc2054b8c529ecf682e06e1e9980170b93ff194ed7a@132.148.132.9:30303", + "enode://d302f52c8789ad87ee528f1431a67f1aa646c9bec17babb4665dfb3d61de5b9119a70aa77b2147a5f28854092ba09769323c1c552a6ac6f6a34cbcf767e2d2fe@158.69.248.48:30303", + "enode://c72564bce8331ae298fb8ece113a456e3927d7e5989c2be3e445678b3600579f722410ef9bbfe339335d676af77343cb21b5b1703b7bebc32be85fce937a2220@191.252.185.71:30303", + "enode://e3ae4d25ee64791ff98bf17c37acf90933359f2505c00f65c84f6863231a32a94153cadb0a462e428f18f35ded6bd91cd91033d26576a28558c22678be9cfaee@5.63.158.137:35555" + ], + "accounts":{ + "0000000000000000000000000000000000000001":{ + "balance":"1", + "builtin":{ + "name":"ecrecover", + "pricing":{ + "linear":{ + "base":3000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000002":{ + "balance":"1", + "builtin":{ + "name":"sha256", + "pricing":{ + "linear":{ + "base":60, + "word":12 + } + } + } + }, + "0000000000000000000000000000000000000003":{ + "balance":"1", + "builtin":{ + "name":"ripemd160", + "pricing":{ + "linear":{ + "base":600, + "word":120 + } + } + } + }, + "0000000000000000000000000000000000000004":{ + "balance":"1", + "builtin":{ + "name":"identity", + "pricing":{ + "linear":{ + "base":15, + "word":3 + } + } + } + }, + "0000000000000000000000000000000000000005":{ + "builtin":{ + "name":"modexp", + "activate_at":"0x21e88e", + "pricing":{ + "modexp":{ + "divisor":20 + } + } + } + }, + "0000000000000000000000000000000000000006":{ + "builtin":{ + "name":"alt_bn128_add", + "activate_at":"0x21e88e", + "pricing":{ + "linear":{ + "base":500, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000007":{ + "builtin":{ + "name":"alt_bn128_mul", + "activate_at":"0x21e88e", + "pricing":{ + "linear":{ + "base":40000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000008":{ + "builtin":{ + "name":"alt_bn128_pairing", + "activate_at":"0x21e88e", + "pricing":{ + "alt_bn128_pairing":{ + "base":100000, + "pair":80000 + } + } + } + } + } } diff --git a/ethcore/res/ethereum/olympic.json b/ethcore/res/ethereum/olympic.json index 6854f2b78a9..3ae9baddf2b 100644 --- a/ethcore/res/ethereum/olympic.json +++ b/ethcore/res/ethereum/olympic.json @@ -7,11 +7,7 @@ "difficultyBoundDivisor": "0x0800", "durationLimit": "0x08", "blockReward": "0x14D1120D7B160000", - "homesteadTransition": "0x7fffffffffffffff", - "eip150Transition": "0x7fffffffffffffff", - "eip160Transition": "0x7fffffffffffffff", - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "homesteadTransition": "0x7fffffffffffffff" } } }, @@ -22,6 +18,10 @@ "maximumExtraDataSize": "0x0400", "minGasLimit": "125000", "networkID" : "0x0", + "eip150Transition": "0x7fffffffffffffff", + "eip160Transition": "0x7fffffffffffffff", + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff" diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 065e3364438..bddf5c0084f 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -9,10 +9,6 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "homesteadTransition": 0, - "eip150Transition": 0, - "eip160Transition": 10, - "eip161abcTransition": 10, - "eip161dTransition": 10, "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": 1700000, "eip649Transition": 1700000 @@ -30,6 +26,10 @@ "forkCanonHash": "0x8033403e9fe5811a7b6d6b469905915de1c59207ce2172cbcf5d6ff14fa6a2eb", "maxCodeSize": 24576, "maxCodeSizeTransition": 10, + "eip150Transition": 0, + "eip160Transition": 10, + "eip161abcTransition": 10, + "eip161dTransition": 10, "eip155Transition": 10, "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff", diff --git a/ethcore/res/ethereum/social.json b/ethcore/res/ethereum/social.json index 87d1f2e4b1f..52b442d0886 100644 --- a/ethcore/res/ethereum/social.json +++ b/ethcore/res/ethereum/social.json @@ -1,8857 +1,8857 @@ { - "name": "Ethereum Social", - "dataDir": "social", - "engine": { - "Ethash": { - "params": { - "minimumDifficulty": "0x020000", - "difficultyBoundDivisor": "0x0800", - "durationLimit": "0x0d", - "blockReward": "0x2B5E3AF16B1880000", - "homesteadTransition": "0x0", - "bombDefuseTransition": "0x0", - "eip150Transition": "0x0", - "eip160Transition": "0x0", - "ecip1017EraRounds": 5000000, - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" - } - } - }, - "params": { - "gasLimitBoundDivisor": "0x0400", - "registrar": "0x0000000000000000000000000000000000000000", - "accountStartNonce": "0x00", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID": "0x1C", - "chainID": "0x1C", - "eip155Transition": "0x0", - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" - }, - "genesis": { - "seal": { - "ethereum": { - "nonce": "0x0000000000000042", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" - } - }, - "difficulty": "0x0400000000", - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x3230313820457468657265756d20536f6369616c2050726f6a656374", - "gasLimit": "0x1388" - }, - "nodes": [ - "enode://54d0824a268747046b6cabc7ee3afda48edba319f0d175e9e505aa9d425a1872b8b6f9ebf8f3b0a10dc7611a4c44ddec0fc691e5a5cde23e06fc4e4b3ff9dbef@13.125.185.147:30303", - "enode://7e150d47637177f675e20d663fc2500987f2149332caf23da522d92363be8a7880ef9150a6183e9031288a441e0457239474967a111eafce17e19a4288076ea9@18.219.40.235:30303", - "enode://6244c9d9cd288015d7ff165e90f3bb5649e34467e095a47c6d3c56e8fb8c849b3b4db683ff3c7ae8a654bbdc07ef12ee2fd7d72831ac213723281c1b0cc90599@13.250.220.98:30303", - "enode://e39f162b9f4b6ed6f098550f7867c2fb068fc66f362b3db0f45124c43ea18508f5ceef4e0e4de53d301e14a6f1683226aeb931d7401b4e83b5a583153ffdd7fd@52.57.98.157:30303", - "enode://54b4a117d66dc3aa93358dec1b31d4f38e72e4381b3e28a65ac6f1aaac3b304ebbe41d32cc864fa69a9a6815c34cf9b8965690dc174a5f72af14547b601b7924@222.239.255.71:30303", - "enode://851f14c5cc86cbc0a81acfcbe5dd99ad5c823435357219df736932c5f89ad4318f6973a553857a32d97a71793f5a35c062d46320be282aa0a80b06b9c6b624e4@13.125.232.71:30303" - ], - "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "ceed1c8254abaf069669fc6045e90482543d1f2e": { - "balance": "38000000000000000000000000" - }, - "6f22d7f8c38e0135e36be87e77fc8d4ae4b3d965": { - "balance": "38000000000000000000000000" - }, - "d016e982b7886302428d7c741392c658337513d2": { - "balance": "38000000000000000000000000" - }, - "defa96db5c8a41772bc56f68f95e307ff71a2c60": { - "balance": "38000000000000000000000000" - }, - "951ffd4253ffcf31b2895dd3f7f2a8a9bb2933e5": { - "balance": "38000000000000000000000000" - }, - "b7071dba21cfbe1b70abd7ddfd2f0f83d5d19a61": { - "balance": "38000000000000000000000000" - }, - "6ca420cd8d5407c61a9b14adcb38bee0f26e2848": { - "balance": "38000000000000000000000000" - }, - "b50d185b6cd04499a38afc0fcfcb59eaa74d0956": { - "balance": "38000000000000000000000000" - }, - "7ba8c49a444c117f2d2a50650b3f700d4ee659fe": { - "balance": "38000000000000000000000000" - }, - "83f9959ecc532dce071fcd0c62dc23cd571b689b": { - "balance": "38000000000000000000000000" - }, - "001327afce7ebb623a7d0f17b2ffc358fb863b5a": { - "balance": "9844198127334000000000" - }, - "0015ac7f8bb2a2c7d954fc2dbd4e20c0db5942a5": { - "balance": "1000000000000000000000000" - }, - "0021e69c041be2d28744b69361105ff51295da59": { - "balance": "1379639894000000000" - }, - "002cfd27bbb8164681b8762e71b2891beb127fdd": { - "balance": "25105286685000000000" - }, - "0033cf217bc765ccfc338869451588ce448fde65": { - "balance": "23425485280069000000000" - }, - "0048f1d1735979cd8ac9c0886088336b2d4a43a6": { - "balance": "10000000000000000000" - }, - "006a79cc154917cf204d8097728f290e29716d43": { - "balance": "20000000000000000000000" - }, - "007c8db36e4f649b14516dd78202670b671ba753": { - "balance": "1000000000000000000" - }, - "007d131b58388f251075a3c61020ce301106c5cf": { - "balance": "381079535880476000000000" - }, - "008e8fbffc2fdbefaa7e3be4f4a9160db826d05f": { - "balance": "10000000000000000000000" - }, - "0126d86b9814b0e78c4e01a3916bee6a7778145b": { - "balance": "10000000000000000000000" - }, - "012cb961297c837630251a173b7861e77724856d": { - "balance": "494562376059000000000" - }, - "0145886dfab5ef4f2def50a56b4a074cf5b18acf": { - "balance": "680585022951000000000" - }, - "0167918bab62aa2118cfa4d3eb80da0e71c71d8b": { - "balance": "122395119468000000000" - }, - "0182f7286ae9d4d6bc514d5175d14685d520bde7": { - "balance": "10000000000000000000000" - }, - "0184e9c8fe99d85100fe28a0e8877b14768b372a": { - "balance": "193295614762000000000" - }, - "019eff7dce7f31c2d4f7318da71d212cbf89d36e": { - "balance": "64004138198000000000" - }, - "01f3351ea66c352346244dbb79189066bed62fc5": { - "balance": "937056266523000000000" - }, - "0202ddd7f4f32bc575f7df24612f8aa9f9a7ae42": { - "balance": "106905151080000000000" - }, - "022b8c65e959cab71f56688b7073257b58bbef4a": { - "balance": "9682681149566000000000" - }, - "0245ff6382eb93ab1e8ed2e3c0bce7a1b9a9713d": { - "balance": "289000000000000000000" - }, - "025e117a69ca9244ed430732c11e550e3ee67577": { - "balance": "1861905310567000000000" - }, - "026e7457eeaeaec7898fdee1ad39be89e92733b3": { - "balance": "7529030978000000000" - }, - "028d2def8c54fcc77bf0191b183c0bc4570ec1c5": { - "balance": "9056720934000000000" - }, - "0291a087605b516e465134797b5459436d320e6a": { - "balance": "481100929805000000000" - }, - "02a4b18b3e13ec79307e712fba1867cbf7fb6155": { - "balance": "9000000000000000000" - }, - "02a812d4cebcac1a92ae470ade92fde7bead127d": { - "balance": "66793603497000000000" - }, - "02f718c94b2c8e8d62752f8632443504c1e4b6e2": { - "balance": "1000000000000000000000000" - }, - "030dab52b47b37505b72e5ca0985f65ead590816": { - "balance": "1376851176362000000000" - }, - "031c59846f75de1aefb0e8a95e0fb822fd06555b": { - "balance": "140978338628000000000" - }, - "031ee87c672d83ec73059c86a312a9e972142054": { - "balance": "96406273341000000000" - }, - "033182e860564cf695cb403c8c0f078053368d7d": { - "balance": "1504349255824000000000" - }, - "03788dc6528fa33a90e90e03295ae4b792d56644": { - "balance": "24356250426000000000" - }, - "037aae119047028157c5b3bc9d3d202b02cbce42": { - "balance": "105627739575000000000" - }, - "037d45b323cbc5cbac999c5001169646e690b94c": { - "balance": "2000000000000000000" - }, - "0390ba35c454a24519d845405a7e24df71250748": { - "balance": "1872501898509000000000" - }, - "03ab8c1e7f904db62437b16d28aeb539b2dee55e": { - "balance": "55000000000000000000000000" - }, - "03af4c69728a888fa26b1aefa439005989771fdf": { - "balance": "27704588237757000000000" - }, - "03b33fb19d165e5e33bcfbbfc009f418d71f30fb": { - "balance": "1999139000000000000" - }, - "03b34c79f8167a4e8be0f6133254d2b50cbd878d": { - "balance": "111065050160000000000" - }, - "03d7e8638b74ae44a2770287285489a95fa1ea11": { - "balance": "20000000000000000000000" - }, - "03d870bf719f03250c0dc5156a36751b3aa21f18": { - "balance": "981119649953000000000" - }, - "03de52c12b05fb8bcba3a1cfe02a0ad1bc9761d3": { - "balance": "362007990932000000000" - }, - "03e516db27b1abe008ffc57ced48f72f872d8b08": { - "balance": "3389116345657000000000" - }, - "03ef5ff863ee5f1167f38cdf316e4d52a242b750": { - "balance": "12395856876000000000" - }, - "03f27766760f2bd1cae1cb85ddf43ab59c871e47": { - "balance": "49000000000000000000" - }, - "03f4e1a8fb4eedc776f4835fcc85d0f236612f9c": { - "balance": "27210590272692000000000" - }, - "0404936ee04cc79cbb3aedfa33a53f94940f772c": { - "balance": "29919204637416000000000" - }, - "040501ffde9649be794b7d41643273ed6285ab39": { - "balance": "686000000000000000000" - }, - "040e449de680f69614120f0a2e894cde36e4adf1": { - "balance": "81993180085000000000" - }, - "041531e906dbdc70d89f5e255151d9865a059308": { - "balance": "2163418749315000000000" - }, - "041ad9f6bf970541e4ea8a14dde1e789d0fe4367": { - "balance": "44999979000000000000" - }, - "0446420c07cf73d2b3741b945c1cc8444b4ba6b6": { - "balance": "138749371512564000000000" - }, - "044c1a540b8ab286c218c2fa9d5bfbc2761e7626": { - "balance": "1" - }, - "04526b2c62911e78a939816aa4575fe30baa06c7": { - "balance": "2983093150081000000000" - }, - "04adf59f8a0ad3820a7972c6243202b3b0617fcf": { - "balance": "50000000000000000000" - }, - "04bbb42882a475eed58aae47fe530ed19c1cedaa": { - "balance": "278038763863000000000" - }, - "04cff7a7c2b9b0bf31c5ad4a5de8b0eade70aafc": { - "balance": "515406205244000000000" - }, - "04dcd325dc1fd37ff3c87da3b21c47ddfcc37cc2": { - "balance": "5831887315000000000" - }, - "04ec8d0b5157370f5a2671a2aa68ae486b7a7842": { - "balance": "10000000000000000000000" - }, - "04f50f2a6e89ee497a64c11baa90759a10a1247a": { - "balance": "25443071621949000000000" - }, - "0513a769ebef58ad3a4fd7011ddbe19799ff5600": { - "balance": "64369494797000000000" - }, - "0514c1151f356070ace281435f25c86b58280715": { - "balance": "38967380881301000000000" - }, - "052fda414fe1279c6276a237b07e1b4148a8cc77": { - "balance": "10000000000000000000000" - }, - "05431089cc62a987d0e99847e10a006233146f6d": { - "balance": "268977485219000000000" - }, - "054ed2f55028257212b996f9a3d34758d1d4ffd1": { - "balance": "100000000000000000000000" - }, - "05a68cc758560addde302baf814f2fdbe0ef2c2b": { - "balance": "10000000000000000000" - }, - "05c669d9ded79fe9e4e3718052bc7ca18a3205ab": { - "balance": "7347158140000000000" - }, - "05d77ce5c87477b05e90e829dafd8eb3a8c87823": { - "balance": "21191998933000000000" - }, - "05ef2894a2a1c6eb6c0a768d04ef5b573f357712": { - "balance": "20000000000000000000000" - }, - "0601011f80279190b96f641205c6a524a8ad5a28": { - "balance": "12025716447696000000000" - }, - "061a8acdb1a340ba7c550814831e27262708fc98": { - "balance": "234029764576000000000" - }, - "06219483e217c9ad479f76a95426f689ef4d5951": { - "balance": "1509408723551000000000" - }, - "062d0db8a650f2241f8a4295326a2570a7c771bb": { - "balance": "717459720227000000000" - }, - "0633ba746235d8fc8243751b1aa31646c299f262": { - "balance": "49000000000000000000" - }, - "06b6a5cadfe1fdc88015512e835d840e58ae4123": { - "balance": "1000000000000000000" - }, - "06d08fcbe96791514d900d2cb6c0f029d8d791d0": { - "balance": "19196168602258000000000" - }, - "06e5c0bad43a7011878b12a682abf01ccdfaa151": { - "balance": "30000000000000000000" - }, - "070656bb11ec36074d47c791c0b306394b703401": { - "balance": "1245216075291000000000" - }, - "070d84c938217163b60ed38e4937eea7158c03d9": { - "balance": "27507979787000000000" - }, - "07428c95ef3862026e54d3a963911cdc673dbcd9": { - "balance": "13792309994528000000000" - }, - "0781cb21df142ec5f67b956bf995f02f6f24985f": { - "balance": "224940990659000000000" - }, - "078c38c153b414cc4c12818fce2ea7ba09a34e51": { - "balance": "1410646136000000000" - }, - "07bfd0de7a9a1c927446aaf2d7ede55b471daa87": { - "balance": "77778844734000000000" - }, - "07d1ac83140188b8d7f4c8c607d0da22c5ba523f": { - "balance": "7713686418107000000000" - }, - "07d8ef8fc6dcde319a5af5b6cea18983bdc4c8fe": { - "balance": "3801361173000000000" - }, - "07dfab72dd3e44fcbb1ced625899bf20e0c52ffc": { - "balance": "154177778806000000000" - }, - "0817ce33d943e84c7b3261cc3e37b86b5d6d76ae": { - "balance": "90753785862000000000" - }, - "081be00a2ff62cbcb95a8eb020ac0efa33f93a42": { - "balance": "1027889807304000000000" - }, - "085ffdc6043b04653e51b1a34af20b609d158607": { - "balance": "3314058000000000" - }, - "0882c2228f5df24064bc37e8b7199199de308bb8": { - "balance": "98420617420000000000" - }, - "08918776e9a7136cedad5d0cee52f5d9dd833ece": { - "balance": "1263170315026000000000" - }, - "08bdbcff16919abc5e15fa68ece56eceef33f48d": { - "balance": "2552990000000000" - }, - "08fc8c7bd03fe1249266b233edfcf830693d0e10": { - "balance": "283490111768000000000" - }, - "090f79a4178b5180150444805f62c26cd21be897": { - "balance": "884195010282000000000" - }, - "0914a9dfc9d6ecc063a55e5320050112f305fe17": { - "balance": "15373898854941000000000" - }, - "091791ab5f8ab86f1d8f566ed221b268cbc55347": { - "balance": "2207516004000000000" - }, - "09529f8b1633ce4375451bb44b1025f6e5f9facd": { - "balance": "151697652792000000000" - }, - "09600bbb9d9b23661d269dbe1ed066d8e573b5e1": { - "balance": "802935104935000000000" - }, - "0964d2af1d5883fc0e0a77459f6a141824de7356": { - "balance": "9610980935058000000000" - }, - "097c731d1fc6792ac0f0ff92be4403c3749cc1dd": { - "balance": "165134479709000000000" - }, - "097f152b3f837d38ab1e8c0683d62f5a01d67902": { - "balance": "20000000000000000000000" - }, - "09a6772629ef0bf402ae6d27cd32e6eefb220a12": { - "balance": "20000000000000000000000" - }, - "09addb954d4e4b4e95e0c66d324115d609df5a99": { - "balance": "8435321515000000000" - }, - "09b2eb03e0fa321102196578eb40dcba3a46ec9c": { - "balance": "12723517962933000000000" - }, - "09ba0ed4dce470ba0bcb4d46b507c3b024b83070": { - "balance": "99999979000000000000" - }, - "09efbd6dfea375065be1b3a8f4541f024da21a34": { - "balance": "5870833623000000000" - }, - "0a24d4ae66edc7723bbb314e9b96dc7b9a31e813": { - "balance": "70000000000000000000" - }, - "0a3ee710909382f762648deff8ac7c8b30e2ce10": { - "balance": "407656462445000000000" - }, - "0a42b3145257154e76a97db8147c93be4cffd97b": { - "balance": "10000000000000000000000" - }, - "0a7cb6037f1eba5d19fe781335ecd37b7229c5f7": { - "balance": "74113322448000000000" - }, - "0a85d1bec4d44e309068b115abd517d3733fc56e": { - "balance": "14836218750000000000000" - }, - "0a891ba9ca7b99ecd815b1dcec9243dd4deff866": { - "balance": "178004857988000000000" - }, - "0ab69370b537d4ff5b45704fed293e46e3464f87": { - "balance": "1258876668246000000000" - }, - "0ab77a2e8ab9a3b659d1f1d37956c3607a0f9a60": { - "balance": "6283300817712000000000" - }, - "0abc7e8d52f5b0dcf1d4713e5fa4909102251dfb": { - "balance": "39307290577000000000" - }, - "0af2c0471c802d2e2b20aadf9dd4ec842d313ab0": { - "balance": "1529468143183000000000" - }, - "0b08c717bb3982fc8b92d5b3d30e5b41265a0d0f": { - "balance": "1184600154874000000000" - }, - "0b3f2aa9dc5b57b0469398d62f60a13774ec0e87": { - "balance": "132187640280004000000000" - }, - "0b3ffe85aa89e71a6e51e938c7265d2a7173061b": { - "balance": "2106793086824000000000" - }, - "0b468562e712d22b37e1a65f54b1fa825beebd1b": { - "balance": "15130906006000000000" - }, - "0b5333eb668dee29ebc0e335d74f33ffeaae9ac5": { - "balance": "125953133109000000000" - }, - "0b59a20107495e951b509187307782ca9dfa441f": { - "balance": "25000000000000000000" - }, - "0b8b7fb066601ea7744b81f6e1a21b8e489359cf": { - "balance": "101782000000000000000" - }, - "0bd7791097f79066d71ac0a2c94bce6628a63373": { - "balance": "44389955028000000000" - }, - "0be541af06e167206b5d1cbe08e8fb2b5ebc82cb": { - "balance": "9000000000000000000" - }, - "0bf178bba463f4f6c33e3d81b1a78d220f7b5d4b": { - "balance": "111784804790646000000000" - }, - "0c1f000249b1f1ac9e43c4f10e2da1cc2adf886f": { - "balance": "91251997635000000000" - }, - "0c74e46b115e19726997dd559d2b6ff1bfb79af6": { - "balance": "879229287149000000000" - }, - "0c7c1ec152c920a068c25626c22c4fae7f435536": { - "balance": "39849464104000000000" - }, - "0c85fbd7492d1ae87bf3d286c4750a34f1fd3121": { - "balance": "20000000000000000000000" - }, - "0c9fd6123e313f7d1f0cb25d99839102da08b2c5": { - "balance": "10000000000000000000000" - }, - "0cb051e3bdd9d96e667fbcc00a766d4f149f89e4": { - "balance": "1000000000000000000000" - }, - "0ce32bf6c433cbd26c6f09a1214db0374002784e": { - "balance": "3293279842000000000" - }, - "0ce6374ff04430e34edec8b6323feab2bccab92d": { - "balance": "93983447000000000" - }, - "0ce646412a1524c3f73edfd753c0ba3ee7338275": { - "balance": "10000000000000000000000" - }, - "0ced803e56eac3c99269ff7409d2d200d62d7c25": { - "balance": "49539379000000000" - }, - "0d1dc2be9f78ce2b2591e7f5b8af9dc778499bd5": { - "balance": "2235348003595000000000" - }, - "0d235583458a168e810275f907b5f87bebb2d1cf": { - "balance": "83106439283110000000000" - }, - "0d28fe6e8b7d4b8c90ef7c52b9656511ce5867f1": { - "balance": "1347248794799000000000" - }, - "0d5cbe0da660cbca831787efc45fecb20e06e02b": { - "balance": "297528508941000000000" - }, - "0d7a24f324176f6d793c3a2eb6c54d6ee47eca79": { - "balance": "25637813467000000000" - }, - "0da26a24e3650e84c52fedb36ef76225a8d9d259": { - "balance": "15467820321000000000" - }, - "0db7eaceaf3df21ebb49c56fa2d2e2c8e85dec52": { - "balance": "196000000000000000000" - }, - "0dde52823bd8fb2cb179e6d417c07ff285c31775": { - "balance": "347321514878000000000" - }, - "0df9585f1aa83189e0a813f5eac6e6e0b2bbb8d8": { - "balance": "2891430551000000000" - }, - "0e09af9368f05b476164953b7b9db60ac95248f0": { - "balance": "573644391203000000000" - }, - "0e18315dd2b663ce4859b5bed854403191452c2f": { - "balance": "24174325261000000000" - }, - "0e29bef5f4f66c38a0f05cca1e4938d57ff09c70": { - "balance": "10000000000000000000000" - }, - "0e443353b42e042ff5168e9b3c6de37070368223": { - "balance": "20000000000000000000000" - }, - "0e8cb6e439516b312158f169b546937b715db3f2": { - "balance": "8049136367000000000" - }, - "0e980fab23be601f3abec7b9a24e1335a5e765c8": { - "balance": "8301885845897000000000" - }, - "0ea63fef218ebf570a4ee62ef6ed712dbe623c44": { - "balance": "10000000000000000000000" - }, - "0eb60e3512336e4447ceeb8664ce0ecaa3eb0bdc": { - "balance": "41401696400000000000" - }, - "0edafc1058879a9568e711445b18ec4da31d2480": { - "balance": "10000000000000000000000" - }, - "0efce4565062b23b43dbc1e261463e363e4a5b4c": { - "balance": "10000000000000000000000" - }, - "0f08782c04bf7249ab08f4e251abc60aee792a96": { - "balance": "1380257622493000000000" - }, - "0f19bfe1eb24def828bf1be69791c63ba1de1263": { - "balance": "2223687184885000000000" - }, - "0f2171161eb9674218add261be61d18d86b846a6": { - "balance": "121000000000000000000" - }, - "0f42ef6c5690b6c95f8b8c9dbdc16f717c04852e": { - "balance": "81000000000000000000" - }, - "0f47f5063d321b34a0d800951bcdc3f53c07e32c": { - "balance": "5288516165000000000" - }, - "0f529a9beedb2c2a087a220f0013cea4f8454bfc": { - "balance": "114585457979000000000" - }, - "0f6751d10aaf855454a6e9e4241cfcae3b0ed732": { - "balance": "94160300063000000000" - }, - "0f6ed5a4c3ec100afcd59e9066ba7fcb63cfa6dc": { - "balance": "1000000000000000000" - }, - "0f77025519cc76c38e1cf0bd8721f4a5b9c814d4": { - "balance": "834620571043000000000" - }, - "0f773db2a1a96b775e4481575704f5f087b067e0": { - "balance": "554268361745000000000" - }, - "0fa0f73adbe82f8e09f8adbce15b051971e289c3": { - "balance": "11329911975000000000" - }, - "0fa6397d747d88a25d0c755b3be4eee0e3f68912": { - "balance": "31394936138000000000" - }, - "0fac8635a61bf7652d86725cc75c307949bd4f2a": { - "balance": "49000000000000000000" - }, - "0fb0ce787306ce13dcd614ab3d0e15d9772106ac": { - "balance": "50000000000000000000000" - }, - "0fb1d306d240360056f60f197dc7f68f732ac515": { - "balance": "20000000000000000000000" - }, - "0fe3571f498a6d945e123ac8ff6e3fed348d9432": { - "balance": "20000000000000000000000" - }, - "0ffd6b01ea9a7bd2576fe4a5838fe09e44c1639e": { - "balance": "100000000000000000000" - }, - "100bde3d73fda700369e78229127b58d2ade9177": { - "balance": "10000000000000000000000" - }, - "102028c7626970a28677bbdc7733484c8b14c2d2": { - "balance": "500000000000000000000000" - }, - "10245044be6a46ad41d4559129cb59e843379cf8": { - "balance": "857437279765000000000" - }, - "10417d0ff25c115b25915dd10ca57b16be497bf6": { - "balance": "10000000000000000000000" - }, - "10579870e6685ed7e97dd2c79a6dc3528bae968e": { - "balance": "5187866041491000000000" - }, - "109736465b4bbe31ea65ad01fc98f04498271e6c": { - "balance": "20000000000000000000000" - }, - "109c0535a4a86244c5094e99167d312a77657dd5": { - "balance": "138277702073000000000" - }, - "10aa08064689ee97d5f030a537f3cd4d8bbdaf74": { - "balance": "10000000000000000000000" - }, - "10d8bc8c3d3e2010e83009290586ad85b73321d1": { - "balance": "25000000000000000000" - }, - "10f22b82460252345753875555de2cebebe63a93": { - "balance": "765947730644000000000" - }, - "11111c3a2cfa55e52d6aacf533e1d412f8c8c01c": { - "balance": "4827254128275000000000" - }, - "11386103a0bf199db9504b617ccb3bbd780eb9fe": { - "balance": "10000000000000" - }, - "1156a129183e5bdfdf2bf7a70963285a979363a0": { - "balance": "10000000000000000000000" - }, - "11589cf70a6a4fbaac25224e2ddab222333f78e6": { - "balance": "49000000000000000000" - }, - "1162fabeb3eb1e4124179b00c4a1e01503023f54": { - "balance": "817145350625000000000" - }, - "116a7d140f4b7f9b4689063a8417ac07a32bae00": { - "balance": "106088220142108000000000" - }, - "116dc38ddb4b138b19ce6a51e5922c287da5c86b": { - "balance": "100000000000000000000" - }, - "1175f84f835a5ae40d49b8ca17e3e474c1eceef7": { - "balance": "1698584794716000000000" - }, - "119f822a796fee9c41a488949fcb14b589ffa628": { - "balance": "20000000000000000000000" - }, - "11a99f6019b6a53f5dc8cbd0c34f1ee75ced33b8": { - "balance": "102126982156000000000" - }, - "11b9324406068e8bf598d3a9ea59ef31c52f51fa": { - "balance": "6525925895203000000000" - }, - "11cb7be6869a10f5f9e8a47c6c92f729b083084b": { - "balance": "182959434323344000000000" - }, - "11d96a76166ec579e2b6cfa903f66da4af669351": { - "balance": "1000000000000000000000000" - }, - "11fcee55f78278df60f50096d45da1aafe72722d": { - "balance": "222859488179000000000" - }, - "120a1fc914718acd85bf92d9492330165d78075a": { - "balance": "3736627235906000000000" - }, - "12366136d83c77befdc30e04d4f5d808419f504f": { - "balance": "88008649003000000000" - }, - "12435af3f2f92ec43e8f2894be9c72fa932880fe": { - "balance": "1590548436852000000000" - }, - "124ff67125a00aed24e58b6d64ffa887a59b48a4": { - "balance": "20613022349070000000000" - }, - "1296f04910ebc89556ec7ab1b178fdbf14d0295c": { - "balance": "36000000000000000000" - }, - "1299f180e42bfaa1162d36110d29ab062e43e1c8": { - "balance": "321570118362000000000" - }, - "12abac62150c526866ec958cd0e3721b2c78d550": { - "balance": "51898545633262000000000" - }, - "12b345087cee385b9adccaaaa6741b767c82d7ea": { - "balance": "36000000000000000000" - }, - "12cd5e8c0c93f8e34b589b95954b719f54d1515b": { - "balance": "1000000000000000000" - }, - "12d262cdd25edc39b6fd9ae78184eb548e513927": { - "balance": "500976168000000000" - }, - "12d933448218629702c48547b3446b629ec65883": { - "balance": "2168010577395000000000" - }, - "13054aa42d3e119220ac359641c15f8b54bfffef": { - "balance": "24986834005530000000000" - }, - "130bda09f463a982199849ae617062a1d68f3a85": { - "balance": "154504844790000000000" - }, - "131a5da679863c05dc627d53634f2925ba0ce731": { - "balance": "10000000000000000000000" - }, - "1334f2752b5c21f681ba9e23a9fe95a85f8e05f1": { - "balance": "121000000000000000000" - }, - "13634512e2ae79fe3febb9e55e03b47bc350d7ba": { - "balance": "338331304738000000000" - }, - "136fae842aab625768bef9079ee1711e8c007d8f": { - "balance": "2759741687626000000000" - }, - "139fa969e8b74bee1f6113a362f15060ea998b15": { - "balance": "10000000000000000000000" - }, - "13c7e1d694bde6f8f6a31eb6c99f38dc739d61fe": { - "balance": "10901074773586000000000" - }, - "13c849944ad6ad12a46c46973d562bee8284f46d": { - "balance": "35114615504000000000" - }, - "13ec3aa8f4a427ecdecc7901060ccac9bea7a61e": { - "balance": "10000000000000000000000" - }, - "13f478c74acfd6897d13e602a8d362893f4fd038": { - "balance": "3521111850000000000" - }, - "14403970d0784a6458a7bf2584a53d14234e8860": { - "balance": "25000000000000000000" - }, - "14440bb7410337e34a064a92206075575f5362ee": { - "balance": "14918844868393000000000" - }, - "144a88e7a8af70b8bef5c4b70ee0cff771d0c252": { - "balance": "67961927542000000000" - }, - "146b79f474176a4b0069199b03669ab6467a4787": { - "balance": "122518123211000000000" - }, - "148893e7811c36c6bd1ada367681ab8327b3b2fa": { - "balance": "1313118418375000000000" - }, - "14900a17784e3b4d89d98b6cb31c74c685418b89": { - "balance": "131112181597000000000" - }, - "149a483758a98ffe28f7f25cfa17d7433f852ebe": { - "balance": "10000000000000000000000" - }, - "14a03c8e84f07c5596687a98d1e0b1859e9b34ac": { - "balance": "55000000000000000000000000" - }, - "14c7899cb34b5447d6363d4e8355113ebf4bcc66": { - "balance": "197554844582000000000" - }, - "14efa63ee285277c0f8e0d5cc22193e17984e11b": { - "balance": "106221254735000000000" - }, - "151c6099b3fb5b18e0e36a3335dff186dcd2904d": { - "balance": "4304311254087000000000" - }, - "1525dce233a971eb1387f130fdf0e5bf3455723b": { - "balance": "45004174531000000000" - }, - "15271904676f2bc2511294e500152d05ea9acc85": { - "balance": "9300898622566000000000" - }, - "1556ba42ea69d72c1d0faf802906645268e36aac": { - "balance": "171939212653000000000" - }, - "156558fb71ff986953d899c9916a121fd047675c": { - "balance": "290926338537000000000" - }, - "156fbf32614aac2cf462952ec1a3f141f797316e": { - "balance": "6084388860000000000" - }, - "15b9497d6bde8017baf3c29e12430e05a47efbf4": { - "balance": "206126229839000000000" - }, - "15d532e828bdcaf1246696d679a2eb66a154db5d": { - "balance": "69656571015000000000" - }, - "15e26a60cfaf23dfd9bbb999a30904d11b6ddd05": { - "balance": "9839303178835000000000" - }, - "15f3be2f11ee3b19472cc3d171931f050d8629a2": { - "balance": "13572825921000000000" - }, - "16254bed335420e5f793de2295b0081ac41a08d1": { - "balance": "144000000000000000000" - }, - "163aa91bc2ad588116141d48fcbd943985455cac": { - "balance": "618250979557000000000" - }, - "164cff4b9341d536b8aaf2d1dd0e3ed35ecb1db7": { - "balance": "671554639913000000000" - }, - "164d2a9a63868ac25bfe26ecba446d7ce256c351": { - "balance": "7233638188261000000000" - }, - "164e759b64d3ee0a23ec3030f50a1b454a6ec15b": { - "balance": "12281161499000000000" - }, - "165d4a0f23c016b8064adf0dcf7e31bc06350777": { - "balance": "256757922324741000000000" - }, - "166b862954dacddc3333aba4edbe523d693df858": { - "balance": "123677971414000000000" - }, - "16858eb1a6f0e7ff01b91aa9c92d0a433a5f767c": { - "balance": "500000000000000000000000" - }, - "168909a1c2a43cff1fe4faeac32a609c25fbd1e8": { - "balance": "62258808044224000000000" - }, - "16987ad8e10dda7f9e5d95c0f0ee36f46b10e168": { - "balance": "10000000000000000000000" - }, - "16b5dffce79573300a6514ace5f2e844d26fc64e": { - "balance": "5576805697087000000000" - }, - "16e01370a93befe24f6ae6076cd04c84cd3515b1": { - "balance": "1922179181578000000000" - }, - "16fbafd4fc871c7589e63062133793ab244c2019": { - "balance": "2865030627000000000" - }, - "16fdf76180796c6e4335eaa2842775b2e4a22e0b": { - "balance": "20000000000000000000000" - }, - "17081d4d6ebb9f4b163e181a59c2102c99fce6bd": { - "balance": "490625378000000000000" - }, - "17218ff455aa87b29ad4c4f7ba21e9c6f74fc97a": { - "balance": "1607392037652000000000" - }, - "1725bce47f3700f4646efb343f950e2e8ba66607": { - "balance": "58472967071000000000" - }, - "172c5f71aabf072507664471ebaa435779d74a32": { - "balance": "16000000000000000000" - }, - "173a065f351ee0513cfebfe9b950fd2c641fc8cc": { - "balance": "25000000000000000000" - }, - "174e1793c96cefb584ae0a67fff85c65065dafc5": { - "balance": "50221000010000000000" - }, - "1794bc4d622d514f95da5404358ed404b3f59aa3": { - "balance": "36000000000000000000" - }, - "179839d61e7c7a0382fe08e0573bcfbe42a108ca": { - "balance": "203299791419000000000" - }, - "179eb30b5b28a961eac70a919d26ca96e6472166": { - "balance": "55000000000000000000000000" - }, - "17be72168606fb5d27761157e48fc14789f84634": { - "balance": "311205588354000000000" - }, - "17cefb6611033759b8755197b983de2d7e98315e": { - "balance": "10000000000000000000000" - }, - "17e07cc7d89bcd1708b1f05ab6e1252c629d71cc": { - "balance": "903234908997000000000" - }, - "1811be559b657685c2f163122479101c404325b0": { - "balance": "10060694170000000000" - }, - "181417a4883c429ef26a4baeb48e70d4f00278b4": { - "balance": "4621446218088000000000" - }, - "181d345cd6b5f518bdab8d40f5d4896a725b3f3d": { - "balance": "114349561983000000000" - }, - "184625e544aa31552d2911023a892f739df84be7": { - "balance": "5303698708000000000" - }, - "185e4f6eee203ca3c089baa1e643ff1aab7cc8f4": { - "balance": "33969718257699000000000" - }, - "188e4a1a7b23ff35ec90b7bf7561db9e3c0f53bb": { - "balance": "394325508701000000000" - }, - "18a4dbf513be132f9ecfd69e3eb683d710e28c4b": { - "balance": "5997985132329000000000" - }, - "18c9298f62635ef47d0ef215b8a693af60829c27": { - "balance": "100000000000000000000" - }, - "18e7e2ee0c86bc1ba3595fee3d40257776fe8172": { - "balance": "185584626033000000000" - }, - "196575e74499b741877793f8c8facf2f3b1ddb8f": { - "balance": "30318381929000000000" - }, - "196df33f2d3ed473e6e07650419969f4a39fd03b": { - "balance": "15442864665000000000" - }, - "1975c5293ec9c72a28e6cc74173cdfd8de682fea": { - "balance": "103624886552134000000000" - }, - "19832cd1b2fc4138c8d9291a0f404d3c4326b48f": { - "balance": "4732362673000000000" - }, - "198705f46f31c7ca22f5b88fab210bc5b0c7647c": { - "balance": "548940869737000000000" - }, - "19a5a213e6abfee29f17e871222cbe9ac45322c8": { - "balance": "10000000000000000000000" - }, - "19ab9a7a4e9f9c08c9b4295c406b78389a864ba7": { - "balance": "369299839157000000000" - }, - "19f19f5f01b3f6a1c4f645dc7e3992b1196ccb7a": { - "balance": "97759406000000000000" - }, - "1a11a0b0081522e60e16f154e093ac2e005d24ee": { - "balance": "88024675252000000000" - }, - "1a27309b0c09be2234fd64afdbcfb099f8e2e7cd": { - "balance": "10000000000000000000000" - }, - "1a3d61754974bea23503a61ef0fe584b7b6e6cf3": { - "balance": "326950210355000000000" - }, - "1a49bbde1457a8d4c247606b206ac8d4d389da5a": { - "balance": "402438941516000000000" - }, - "1a7a4b41be64fff3a31eb6166db59741e073d0f7": { - "balance": "250000000000000000000" - }, - "1a8d282e82c606e992f69ce618ba634d98bf2683": { - "balance": "20000000000000000000000" - }, - "1aa0ba27662816e5e3d79e223cc18f5dfef089cf": { - "balance": "187581622694000000000" - }, - "1acab416a1d3e8caa65faca378c79aaf2065b851": { - "balance": "1000000000000000000" - }, - "1acd37af3f87da1dff743dfcb97038d178b1dc4f": { - "balance": "708034481300000000000" - }, - "1ad8f036022c3e5258455d6aa05fb4be5dd121b1": { - "balance": "42957064709000000000" - }, - "1aee811e06c579c21fbcc3b53d2dcf9d5f24808e": { - "balance": "52480060284048000000000" - }, - "1b03b7a4e9908c3531618f49f8d050ba6afb4de6": { - "balance": "28410489187000000000" - }, - "1b073d026e93de51db34d5a8e19047784c277ea1": { - "balance": "20579129628026000000000" - }, - "1b0b87e414bc8fe4920fe104b6de7d17db3a1a19": { - "balance": "10720000000000000000" - }, - "1b411c692c80948e59cd805a0f8574dd67519288": { - "balance": "5416615538000000000" - }, - "1b8d57e995749618c7bb3e60194ac6fc57e9b3eb": { - "balance": "10000000000000000000000" - }, - "1b913efde1255516346b40ae2a48ebf62251682d": { - "balance": "100000000000000000000" - }, - "1ba7276c133f93d43db2f2caddec08e0167eaf15": { - "balance": "82559173174000000000" - }, - "1ba919f7742160cabf2756eb6eae67b92530f3f3": { - "balance": "1102304139883000000000" - }, - "1bb20857de494694fe15bd11f8cac1218435fbc0": { - "balance": "10221322567000000000" - }, - "1bb5c5e81d451f03e899852edc8556a9f7aac5df": { - "balance": "18781017696028000000000" - }, - "1be3507349ed07d3e7902951d490f560a75e96be": { - "balance": "660691718918000000000" - }, - "1bf1c0b2e6f64b612f35f2bf98d894b13dda9bf7": { - "balance": "3050161851140000000000" - }, - "1bfd3c2ba6a537e97cedd542cd554a5050963d54": { - "balance": "20000000000000000000000" - }, - "1c4af5003f9e7223f4141107d21640e4a85a4827": { - "balance": "612390629874000000000" - }, - "1c6a94810bd0afcf79ceea11afe86c34f6813211": { - "balance": "10000000000000000000000" - }, - "1c7e277460191c886cb1647173d27122c2146252": { - "balance": "209062806527000000000" - }, - "1c818ffa9caa61d512fa5d7d6e566f3ae37d5434": { - "balance": "454897845316000000000" - }, - "1c9599d5f8e5eaf8f68d35d52132e15a153f6d3c": { - "balance": "36000000000000000000" - }, - "1c95ab5229fd08c638a1728c022f09291b8dc55d": { - "balance": "20000000000000000000000" - }, - "1c962808c175ee5e5e365483d066c8ea95993700": { - "balance": "1362779746855000000000" - }, - "1cafad295b2188f10192c8a32440931f7e3554e4": { - "balance": "36000000000000000000" - }, - "1cdc2899ec563d79569d1ba776bc03cff331e786": { - "balance": "572163587827000000000" - }, - "1ce0042e7b4f13589f5f8490836dc63e0ca60c3c": { - "balance": "25000000000000000000" - }, - "1ce62051fd7801d294bf31a7b44cd87510e8b545": { - "balance": "2008112411284000000000" - }, - "1cf20f30cd901b2e5fef3f948289dafaaabaa77d": { - "balance": "1444000000000000000000" - }, - "1d449764d38b7a4ac848f49e2dc99df02dfd8a53": { - "balance": "48215693645000000000" - }, - "1d635125c494b1137ca5f15ac95dd6d93c3a9546": { - "balance": "10000000000000000000000" - }, - "1d85a61353c3e0b6d34e105e35c8c7833b6a1e35": { - "balance": "16000000000000000000" - }, - "1d969134ee156c41c98c3721c5dbb092c0b581a6": { - "balance": "64000000000000000000" - }, - "1da12434596a9c318dab854f06d404fe61f0a69d": { - "balance": "16675185416000000000" - }, - "1db0d23fb63681958a66e716e99df3e0b848fd12": { - "balance": "1103581911968000000000" - }, - "1dc628820da657f07ab5eb887d5f512378b5b61f": { - "balance": "6272287019755000000000" - }, - "1e05cba75b0dd379037940352e0073564957b7d9": { - "balance": "12453446342664000000000" - }, - "1e13f037a92ab6f19c4484ae3301b3ac6f48575d": { - "balance": "106244918916000000000" - }, - "1e167bc07f094915c00e7aa4c43b607ed2c998b9": { - "balance": "1000000000000000000" - }, - "1e1f9409bf92c3ef59aa2fd82dce55cd90e23f19": { - "balance": "99139000000000000" - }, - "1e4dfea7871d941e72a161022b62fdb01818c86d": { - "balance": "81000000000000000000" - }, - "1e5d0b525228167334e94314a201388bba08153b": { - "balance": "1138044078759000000000" - }, - "1e6633290c9898abf5fcac54396de770164edc5a": { - "balance": "25052055674000000000" - }, - "1e76296584058670ea80fe9a39d8f457c03747c5": { - "balance": "10000000000000000000000" - }, - "1e88b2c8dcd289929e51a15c636d0b0f3b035569": { - "balance": "87357600832000000000" - }, - "1eb59a1732a159a91a9371650943840e0eb61174": { - "balance": "20542821429000000000" - }, - "1ee077bdef6d45d491602342cee008cd1e2912e3": { - "balance": "10000000000000000000000" - }, - "1f1ebf2f80afced68424cb7b0b966fdf42d508a4": { - "balance": "1460082126494000000000" - }, - "1f3d4a903bd32a537efae19592f5516698c95a20": { - "balance": "10000000000000000000000" - }, - "1f6431696efc6f1ab98dcc2ef0e8553da697e6f1": { - "balance": "20000000000000000000000" - }, - "1f657552b745acbdf731f2ad107d6362480abc88": { - "balance": "162042599568000000000" - }, - "1f699a7682c1266291a3f49e19cac0846470abf5": { - "balance": "712268213248000000000" - }, - "1f7a332dabb00851705274c59187817d859cb9a4": { - "balance": "199999999160000000000000" - }, - "1f7c333047e168f5d3408c42a4919bd44b8f7961": { - "balance": "3918096658000000000" - }, - "1f8226f7a4525b9f3cd4da3acc1bb34529f8d28a": { - "balance": "3530829464000000000" - }, - "1f8b6fcea9e0991ad0b0b25dc65748518a28713f": { - "balance": "142069368416000000000" - }, - "1fa3de6913e4de78cc4828e246554785950c3c8e": { - "balance": "178437291360000000000" - }, - "1faa75d57fd597d2b58d2ac6f65bc2bd5946911f": { - "balance": "13092024644362000000000" - }, - "1faf1721dba3266cde1e04a7e9c789bdabdd930d": { - "balance": "862698523071976000000000" - }, - "1fb861559361701fca1df6ab4ef4d2fb9d2d7e13": { - "balance": "100000000000000000000" - }, - "20154d678cdde9ca1c0acb94726f26617a4da0d8": { - "balance": "2288800561677000000000" - }, - "202484a46ca9d54d0d456bc38e2a74ec5f469349": { - "balance": "50178714107336000000000" - }, - "20324278018b4d8e0c49e0fd1be35d3494079165": { - "balance": "484082383314000000000" - }, - "2033ef68ef6297e9229bb73e6486330543aa3eb7": { - "balance": "51260669473000000000" - }, - "20b1e0ab7b9d62a314946b55a5775f24ae3cfa00": { - "balance": "1540424185584000000000" - }, - "20b61f2eb5e18b1e8568d18235918f9e2f596c32": { - "balance": "10000000000000000000000" - }, - "20ed8ca39dd148edf22e03b8021af32cecadd42a": { - "balance": "20000000000000000000000" - }, - "20fd5feb799fbb021ba262d28332b4dda8f44a2c": { - "balance": "7607475714434000000000" - }, - "215ab8aad1c8960838225294d086f0786c2dd796": { - "balance": "19929201327000000000" - }, - "21681cda53aa1a4cfb3e3ea645c8eeaecfc3ba4f": { - "balance": "10000000000000000000000" - }, - "217b75eaf2c0be12108120ba56ddb709e1885324": { - "balance": "36000000000000000000" - }, - "21be1d75b93e96017f088f1ca64ba7076c8edf07": { - "balance": "150798073752000000000" - }, - "21ccdbe0216b486cb39c94ed13767aa061c75ce9": { - "balance": "11070639373000000000" - }, - "21f2289f2d274bddd7928622fffdf3850d42d383": { - "balance": "268859368544000000000" - }, - "21f54f92a7d9a91915e1751ceb02cb8e3ed3d622": { - "balance": "10000000000000000000000" - }, - "2202c70ec23f4605394d69944edd9f90e488eb61": { - "balance": "9000000000000000000" - }, - "220e2253e1ab9ec348cc28d38bae4cb2d5d9cf8f": { - "balance": "116100821631000000000" - }, - "22328e434957107884854999e666ad0710187e3b": { - "balance": "233364805270000000000" - }, - "22851c0487d119ee3f150010515358d6ff14807a": { - "balance": "104464221701684000000000" - }, - "22a38000f5eca29001e387b52c18fb6030683fac": { - "balance": "55000000000000000000000000" - }, - "22b655a19810307750ed1b6b093da10a863d4fe2": { - "balance": "11840799203605000000000" - }, - "22cc48cf48e8ee207bc08411240f913a4e594529": { - "balance": "10000000000000000000000" - }, - "22d6ea6cb8a9206285ccddd3b6d0d1471ba66f17": { - "balance": "64000000000000000000" - }, - "22e2f41b31a0c69472a1a02d419886539b7b6197": { - "balance": "39885451304000000000" - }, - "22e962f91d01480d027ee0060030f529a7a64c8f": { - "balance": "93285203531000000000" - }, - "22f169328fb1104b386ad7fa69f0c7bf3e9a7d3b": { - "balance": "63366769386000000000" - }, - "22f35f5e0e7a8405714de66a5875c7ef84ec4891": { - "balance": "60944382032000000000" - }, - "23041bdc8d371dc29ffc890f19317dabeef12634": { - "balance": "402327389857000000000" - }, - "230eff5e8595f418686737ae671f1f1d225080a5": { - "balance": "114574598112000000000" - }, - "2331e1756d9800800fc9b54ee6e43e1150b6e58b": { - "balance": "44594796226000000000" - }, - "233a72b132e4ab1d3884274d4402d1a2a6399f0b": { - "balance": "1372148909093000000000" - }, - "2369d9dbbfd0f8aa8a3d84d8f2aea840a0cdf760": { - "balance": "500000000000000000000000" - }, - "23754e5cef31ab60aa97a0c8f9ccb4f2969f2d6c": { - "balance": "24764775861000000000" - }, - "2387973589fb07a8c1ec92492c0b8ba9ab5e52a2": { - "balance": "11642113696681000000000" - }, - "23950cd6f23912758ebe9d412166e27994fe6ec2": { - "balance": "100000000000000000000" - }, - "23b383e11573f3ca9be84e1e11694f58a432324b": { - "balance": "206558238838000000000" - }, - "23c329bb641fa51122ea476e3bc614f5d4f9cf00": { - "balance": "35908627324000000000" - }, - "23cb9f997c39853486adfc1a8b029874d1a6af15": { - "balance": "1400984459856000000000" - }, - "23ee14215c531f6ff1baef2c74b1754306f4532d": { - "balance": "10000000000000000000000" - }, - "23f641f765cf15665b6c28d77229d3b2a58fd857": { - "balance": "266570948120000000000" - }, - "23febb49d9541360b9d099377df16b5630dfbb52": { - "balance": "228513797641000000000" - }, - "24082040652a09cbed6504f3dd6491e0ee9d2bff": { - "balance": "91160839809000000000" - }, - "240d3edf4aaf42e99d366ca36d82c370271b8e8d": { - "balance": "65535355843947000000000" - }, - "242b63ebf47678f17c176d5d4a670e46e66a823c": { - "balance": "469668185647000000000" - }, - "2433612fb939236a87a97261ff7b3bc7b754afb1": { - "balance": "20000000000000000000000" - }, - "246bb03a3fab572b3c64fc23b03dfda42b7ea34c": { - "balance": "936364046000000000" - }, - "246c510dfaf5b49bc0fe01c8256d3879c1b5f89a": { - "balance": "100000000000000000000000" - }, - "24bf4d255bd3db4e33bff1effd73b5aa61ae1ac2": { - "balance": "302436106595000000000" - }, - "24c0378e1a02113c6f0c9f0f2f68167051735111": { - "balance": "36000000000000000000" - }, - "24cf04b7450a0fac4283fa6fcfef6215274b273e": { - "balance": "83714002622000000000" - }, - "24f5f8e7d6a23b55c95fcdc1300de05f9d2abd83": { - "balance": "20000000000000000000000" - }, - "25204bfb27a08dbdee826ad6d9c3398ec6d14fe1": { - "balance": "5929256591480000000000" - }, - "253d95911b4174805d13706b449879413b1672be": { - "balance": "37012901440000000000" - }, - "256065f7e919c508b68957b1d2c9120d29181e12": { - "balance": "25000000000000000000" - }, - "25624542c14c2ecb9a0fe7daec9ac5af16868ee7": { - "balance": "16000000000000000000" - }, - "256d05b6de445179e504a6c94ce1253ae159e19a": { - "balance": "12048598744001000000000" - }, - "256d37fc8980a969063b1f7e7fda8b87d4210da6": { - "balance": "107293553721000000000" - }, - "2588af91a0e8f3ba3ab636781bb84e263acd1f52": { - "balance": "8910000000000000000" - }, - "259774584d4fcae1d84f5997c00beee8a380e46c": { - "balance": "1140713354605000000000" - }, - "25bda1418853a22eb6a5380e8a2862d2a74949bc": { - "balance": "10000000000000000000000" - }, - "25cafdab7f79f7b95d55b4c2dda1f4080aa74d64": { - "balance": "2525573681000000000" - }, - "25cca69b41bb51c51b387c47ece83f30b9a78daa": { - "balance": "163449631440000000000" - }, - "25ce9dabd0a72b02e0056931155ba99c94cbc837": { - "balance": "230073284349000000000" - }, - "25d9d1785c96acddd926b3ed52987ff74f9083f6": { - "balance": "780460361789000000000" - }, - "25e56bd3e1461f27db4eb0cce8bb5ca1574401f8": { - "balance": "1001937531200000000000" - }, - "25fa2162d5c86cda10e4be42c14a24329e455ad8": { - "balance": "50000000000000000000000" - }, - "260a932a23b344056acb8e676714ffac0a13ad2b": { - "balance": "2000000000000000" - }, - "2622efe8836095fcf48d9c8019f48c8320d6e0f2": { - "balance": "5451866545636000000000" - }, - "262447c4d8826ed23ea25e9703a11b4ad3ae9388": { - "balance": "33992454005000000000" - }, - "263eee3badb9b0dd13579c09361806503705a1de": { - "balance": "1134831344000000000" - }, - "266f4c232ebc946c46979cd90d70868380e186d8": { - "balance": "20000000000000000000000" - }, - "267dfe6fa918686942f5e1d19d5fa615f6f2086d": { - "balance": "3569373363935000000000" - }, - "268ad2272c2b71243a7391020a600fd8dfa42d45": { - "balance": "122768017414906000000000" - }, - "269e4f43be9865f05a277933c2fbb466659ada7f": { - "balance": "22064992930948000000000" - }, - "26ae161c20acb26a320fbfbd60c97335cda28bca": { - "balance": "170710653621000000000" - }, - "26b4da905780fb0c5c3e7e5315989fed3aeef135": { - "balance": "20000000000000000000000" - }, - "2704312aa5a4202f14fa3b08e587e4f0ef13accf": { - "balance": "124259630994000000000" - }, - "2704e4b0e8df0c1f298843109ae3bb26c29a22c4": { - "balance": "3155521256785000000000" - }, - "2709347d12251c01aac6455108c6bebe72f0af2d": { - "balance": "220898650215000000000" - }, - "270a32b41dde877463d2106ea4f4529557a5e1d3": { - "balance": "10000000000000000000000" - }, - "2738b3746d6bda9bd72858eaa76f8b5ce7a88c8c": { - "balance": "10000000000000000000000" - }, - "27593d2271aced83e81034e8dd603d098238320c": { - "balance": "20000000000000000000000" - }, - "2771ba4b5944bb12d74b1888255c60e0db215fd2": { - "balance": "412946979808000000000" - }, - "27780086136ea3e97d264584d819dcb2176d7544": { - "balance": "292224348060000000000" - }, - "278936fff8afb553043f038c39fe93906bdb1f4f": { - "balance": "1448466441752000000000" - }, - "27aa0d45d3506f8446816e0e2e9675d46285f6e0": { - "balance": "20000000000000000000000" - }, - "27e655dcc5728b97b3b03fb2796c561090dced1a": { - "balance": "9841344000000000" - }, - "27eb0529279f7a71e50efb70bb1767cbe1ffa4ce": { - "balance": "10000000000000000000000" - }, - "27f564956c837d7949739f419d6ac99deb33d790": { - "balance": "1505247707018000000000" - }, - "280f5618a23c41ac8c60d8bef585aa1cc628a67d": { - "balance": "1316618646306000000000" - }, - "28167a591d66ae52ab22a990954a46e1555c8098": { - "balance": "1000000000000000000000000" - }, - "28257eeb8d20f2fe5f73b0ff2eca3214e30ece4f": { - "balance": "95924728584000000000" - }, - "2827abfc49828db0370b0e3f79de448d46af534e": { - "balance": "769862008499000000000" - }, - "2832b92434e3c922206c2408442bc8274606cbd9": { - "balance": "103421320914027000000000" - }, - "2854f190a38e9b9c04cf499259c6577a68b0b5ed": { - "balance": "144000000000000000000" - }, - "288923bd91be164496e5378ee484f0e4c6c16ed6": { - "balance": "10137243270703000000000" - }, - "2897ff80794153edb721801fb91c6d8373c965f4": { - "balance": "10000000000000000000000" - }, - "28aa06e2290010374097aa2f87a67556d8d68083": { - "balance": "84783245638916000000000" - }, - "28b04ec8eb18b0c6a384f9d92cfb44d1d43ecb51": { - "balance": "14364248730194000000000" - }, - "28db0c000cad3a524bb68dfdd74ffd47b42fb13a": { - "balance": "43586590410000000000" - }, - "28ecd4c5fe98cff66a5b8423f4a27cba9634e2d0": { - "balance": "56106658052000000000" - }, - "2930822031420731f09dce572554a8b8c1eaa09b": { - "balance": "1170839742000000000" - }, - "295154c4522d7bcb2e24b7de9c543dcd1c5f51d9": { - "balance": "179028680906000000000" - }, - "296be4ef7402b00d7af673c1770a50162d7ab602": { - "balance": "8206640005889000000000" - }, - "297b84150756fa89101dd59750a7beb36fb8785c": { - "balance": "1168894124400000000000" - }, - "297cfb72cd1b8b2808fd1b25cdcf7d8de279ad96": { - "balance": "500000000000000000000000" - }, - "29cec0eca9f8508a1ba192a90bb6dee18c40745a": { - "balance": "260217025084000000000" - }, - "29d8f7e72bfa297f17fdce9cf8f4a398f547e200": { - "balance": "307787433251000000000" - }, - "29e14b01c59ba894dd090382fb193ea441164b90": { - "balance": "229028661439000000000" - }, - "29ed634e165084b720e446d28893dbeecd6a7018": { - "balance": "226530464200000000000" - }, - "2a0f8136d43248233f652fe579ef3bd2281dde24": { - "balance": "4007544428000000000" - }, - "2a10204a0c7c9f7701e33c1b71c9427ea16e2e45": { - "balance": "50000000000000000000000" - }, - "2a319ee7a9dbe5b832beae324290f7df6d66f516": { - "balance": "28127560161000000000" - }, - "2a50bfda2b06a9fb28c73f14aaff4f7ef865db65": { - "balance": "10483823413828000000000" - }, - "2a7b7feb145c331cb385b9fcb9555859c16820f6": { - "balance": "1017182951264000000000" - }, - "2ae076c36b18a60f1e3c05d434276a1e16f3f838": { - "balance": "10000000000000000000000" - }, - "2ae2e51ea2ee6a848acde342db2bf6eac927e5af": { - "balance": "494279795271000000000" - }, - "2afd69fac54c167e7ca9d8198a8de386f3acee50": { - "balance": "227162683047000000000" - }, - "2b08018d6e65a7b74ddb5ce1af99976a484b9f50": { - "balance": "16000000000000000000" - }, - "2b0c1d629ad2958ab91e31f351a91219fdbca39e": { - "balance": "113239399820000000000" - }, - "2b2bb67fe9e44165d2108676579a9437c760da30": { - "balance": "20000000000000000000000" - }, - "2b2c99e88e938d1f1416a408a7d0041a605bce16": { - "balance": "6118539729000000000" - }, - "2b5c97b6402ac189e14bbca3e7759319ca8a9222": { - "balance": "10000000000000000000000" - }, - "2b813339c7f818f578b45f17c41c7e931c7828e2": { - "balance": "842834712955000000000" - }, - "2ba6fc21f743968d51f80113aadfc0fdfe8499ed": { - "balance": "309973507270000000000" - }, - "2bb75b272b279cb54498f12b6805261af643c8b1": { - "balance": "1426727673809000000000" - }, - "2bdac062364abd9cf67ba7de214a2cceb0511033": { - "balance": "1090525272063000000000" - }, - "2bea658caa805241aa921f48c8f10cb49e16ffae": { - "balance": "1295499213027000000000" - }, - "2befe7e34299a7c1ad53fc9988ce77e2d9fab20b": { - "balance": "4326342236300000000000" - }, - "2bf466a83cd44aaf0f627606a1c954fd31deb782": { - "balance": "1388986370166000000000" - }, - "2c016a23890e9633fc17b0a8d328ec1ec7ee0113": { - "balance": "92483174342000000000" - }, - "2c45a87a63cc5c8c102d12b83bd9a3501ee41995": { - "balance": "394657687589000000000" - }, - "2c600a596368405e584f3b869f7fabef4ce54aa4": { - "balance": "9879984853585000000000" - }, - "2c7032da8b7816e16095735aee43d1c3f1c43acb": { - "balance": "10000000000000000000" - }, - "2c7275511fe06ee86663b3a618497168b35b0cdf": { - "balance": "10000000000000000000000" - }, - "2ca4074843e9519265447c0dd9ac84ddc2033c1a": { - "balance": "179612279567000000000" - }, - "2cac03ba2c45a6c8186bdceb095b7c5feced3114": { - "balance": "2022060470376000000000" - }, - "2cb8c2cd506b2d7b4cac88ce63230022d412c62d": { - "balance": "211378154058000000000" - }, - "2cd27561cf37ec229982dd592c71d1aab9c2d7d8": { - "balance": "42189968284000000000" - }, - "2cd2e85310a4fbb7f296c3d0d1cee07b191239eb": { - "balance": "1940327317417000000000" - }, - "2ceca4501c5f2194518b411def28985e84d42913": { - "balance": "25000000000000000000" - }, - "2cf7abd42394634689aa2a36d263a6345116b7df": { - "balance": "3553167226295000000000" - }, - "2cf88f29356c166df8383d3312cea10397e25150": { - "balance": "76961677759000000000" - }, - "2d0b62fe49592752cfebaa19003a60b8b39b1cb9": { - "balance": "10277397502735000000000" - }, - "2d2051887107bbd8ed45b405b9be6974a13172d9": { - "balance": "1928781992000000000" - }, - "2d2c9525e2811f4d1016c042f476faf23274aa31": { - "balance": "1000000000000000000000000" - }, - "2d2ef9e1c7a6b66d9a2994adb3ac4a9921408e69": { - "balance": "10000000000000000000" - }, - "2d3bcd18e5c97ddbf1cd28ab37eabe070e9a04d1": { - "balance": "323879852538000000000" - }, - "2d3e60496d0092a4efc665389a916be1a9f8b378": { - "balance": "161958437779000000000" - }, - "2d3fb0ae9b17d3a57d23549ae5500fbb163de25d": { - "balance": "25000000000000000000" - }, - "2d8106dbee6f728c0ff11887690a6370a7d9f5a5": { - "balance": "3102418708000000000" - }, - "2da48eeb788686811ac8270ef3baf0159fc47446": { - "balance": "252187695395000000000" - }, - "2da9d2a6f0b92651a36b05c5e9d2a717c6e166de": { - "balance": "500000000000000000000000" - }, - "2dad81b23d8447190259119019c04a4ef61ab91f": { - "balance": "53428719965000000000" - }, - "2db1faf35901e272aee74a2469a278fdaa6e6e18": { - "balance": "100000000000000000000000" - }, - "2dbae8e1ad37384ca5ff0b4470d3dbc73559841c": { - "balance": "10000000000000000000000" - }, - "2ddf9e23945c181b8592d7965e782068b4c38b37": { - "balance": "100000000000000000" - }, - "2def05d1f2abbaa193a219b87e5319c7ecd48dea": { - "balance": "51359946957000000000" - }, - "2dfd221f96a21e41ffe4dca67b15cd352fe9637e": { - "balance": "36000000000000000000" - }, - "2e1371fcfea9d8dc8e692897a91753400caa9c3a": { - "balance": "5199902650733000000000" - }, - "2e2e04945adbfaeec698ea0f5275f1ad5ffd3d5b": { - "balance": "42034514567000000000" - }, - "2e41f865cfbcf8b89f848405e04de9114087f4ff": { - "balance": "44875730962000000000" - }, - "2e530254768ce94db0ef1204ede0e12b3558e7eb": { - "balance": "14319506377747000000000" - }, - "2e5c43868f45de268967fb22f3f4107da401510d": { - "balance": "20000000000000000000000" - }, - "2e5d2e117d2ba9af9697ec023a4d10b5a2436902": { - "balance": "16000000000000000000" - }, - "2e6000778fb225ddb3e1a2f297d56774e85d9c9d": { - "balance": "10000000000000000000000" - }, - "2eb64b8ab13f0d7823158217d15ba310ed3d0e58": { - "balance": "58724606000000000" - }, - "2ec3973ff33a06d355ad4e8f73b657af8a5ed8e9": { - "balance": "1165606294808000000000" - }, - "2ed4362ea5edf510e210af733089b294f87e8f67": { - "balance": "427561040806000000000" - }, - "2ed8788f1c31b508e37079098a7337bff77b49cc": { - "balance": "10000000000000000000000" - }, - "2edbbe1e2ea482920c76a4ff4c14602b4d37c955": { - "balance": "294409476945451000000000" - }, - "2edcba2bd76128750c8aa00f832c62db30aa7868": { - "balance": "25000000000000000000" - }, - "2ee5abcc0d0d51d4b18947b5aaaa95d037be4e2c": { - "balance": "20000000000000000000000" - }, - "2f058187ef141c06c7c87da86cc1953d2fcf70fa": { - "balance": "9000000000000000000" - }, - "2f16b101da9986a18f4b0d30a26557860338c4e0": { - "balance": "254907899725000000000" - }, - "2f4363df2c61273d230071286bb0157dfefee2cc": { - "balance": "64000000000000000000" - }, - "2f6099a8cb7bc3713b87dab20994d8dc09342003": { - "balance": "1902400000000000000000" - }, - "2f7b3902ce56f74adb0f83cc7d3a99df440cca1c": { - "balance": "825246221388000000000" - }, - "2f7d0298ff6a363375b7eecfe754fca0963c8a1b": { - "balance": "101000000000000000000" - }, - "2fb7c16232b3b1f2e3a676d6d5c93ae6fe5cb14e": { - "balance": "1000000000000000000" - }, - "2fbd5ccc716d2f510d10ec84def3fa69e49f46ca": { - "balance": "1000000000000000000" - }, - "2fd84376be11772e5d072cd74c96b0d9a49c27fb": { - "balance": "1000000000000000000" - }, - "2fdab070e20e2c8923a24c196bec72c33ff0f220": { - "balance": "64000000000000000000" - }, - "3003e6007f69902a0f5e4b4e6d0468277897fc70": { - "balance": "1501210602075000000000" - }, - "30095e6a4ccd1ac2014c3d1d98dce003d775708e": { - "balance": "500000000000000000000000" - }, - "300e47e0fa556371f6c882eb98423be44de7c239": { - "balance": "9108837665958000000000" - }, - "3011231224920b62bcfcbf0aed4fde35dd0a4bdb": { - "balance": "374689586073000000000" - }, - "304be24debce62e70943efddd20457d34e85ab40": { - "balance": "81000000000000000000" - }, - "30912555bb14023e9b7c90aa2314721918cdf1f9": { - "balance": "10000000000000000000000" - }, - "309a94ca7b44bc84a7909ee2b93ed1c94eaf75a1": { - "balance": "39000000000000" - }, - "30bcc93965fa36bbaabcd781326e42227c4e1a51": { - "balance": "10000000000000000000000" - }, - "30c71fed91d24bff69f286ff8f0c6c02a21736a8": { - "balance": "409782329653000000000" - }, - "30cbaf4103757013fd8fb71c44a985939e212b86": { - "balance": "7424807960947000000000" - }, - "30dd59e66093d0bfd87b09c5f6588b9857e9a6f7": { - "balance": "26123006239871345154" - }, - "30f692235f254b02f583d5b515f4701a35c7f692": { - "balance": "148184457997000000000" - }, - "310763019a24a927ce42b00604ee664ca53ff6d0": { - "balance": "393757908273000000000" - }, - "3118a5d4d06ca8b7c8835f4860e6973228000ee2": { - "balance": "56188713212579000000000" - }, - "311adec5bfcaed44680691cc644ee120a484aa05": { - "balance": "169000000000000000000" - }, - "3124e387aa7023995643344c782dac84b9d8c7d4": { - "balance": "1393596696367000000000" - }, - "31379702391cb5a737db3f3ffc336bd03aaa181f": { - "balance": "10000000000000000000000" - }, - "3145606c3ccbaf337610185ffac14ac4f0583c0b": { - "balance": "196454968572000000000" - }, - "315e11501d2c57a62af1631fc2662d4d8745401e": { - "balance": "225000000000000000000" - }, - "31a785ad3eea177c59fb575cad0b44f9a48a12e9": { - "balance": "38039017162416000000000" - }, - "31ae64035e95c1205bf957afb5e1636df00dea3d": { - "balance": "1718600907000000000" - }, - "31c0bb22fd2e9d22984f248a16ec3ed9ad834517": { - "balance": "5982762676000000000" - }, - "31e73a3b5451ebe1163571e9e0567c425bbbfb83": { - "balance": "10000000000000000000000" - }, - "322543c74039ef61fd051021b5e6f16b54bc7c1c": { - "balance": "101346282441000000000" - }, - "3233c7ed11c25bfc41d506c3ae0daf5a3c7c1278": { - "balance": "20000000000000000000" - }, - "325dae17b5225f6734a02c677d43fd126bea89b7": { - "balance": "365067246683000000000" - }, - "326ce8166a4094b93c15557f50f2b1d47811e72c": { - "balance": "16641460224765000000000" - }, - "32cf76046ae48b609524b1a6203eb6296d04853d": { - "balance": "1094839482061000000000" - }, - "33456a28f36aa240262cf95b78b4ac2cd8aa77f6": { - "balance": "3077123488326000000000" - }, - "3348bce2ef90ffd6a59ef5079e1af84b2dd604a7": { - "balance": "9000000000000000000" - }, - "334e5f0ae77dcd3d32dfc2c4ec6ab5e2826dc4b1": { - "balance": "3176777762079000000000" - }, - "335775e19200cd0305e529bc4cdf7295a47cb2d3": { - "balance": "2945631571804000000000" - }, - "336ba81ea6ec4f0da38c1a1761ed3d97fd3ca28c": { - "balance": "3587379203826000000000" - }, - "339191e03e9d5a08ae7b58f4c860235a0721b5a1": { - "balance": "2732237722000000000" - }, - "3399bf9f94c5488c89450257b39fdf3ec8c7f413": { - "balance": "477423805836000000000" - }, - "33cb8556a6c6c867e1be7de591cb22c1b7e9824e": { - "balance": "62293494164000000000" - }, - "33ed633804f39367078e830328dd223254be3366": { - "balance": "22842013797896000000000" - }, - "3409025dce86ad441a5a80f30ce03768d37e40bc": { - "balance": "1381667933000000000" - }, - "34153174cd4d3f1eaed7438638d302f6414d5965": { - "balance": "50000000000000000000000" - }, - "343c6b82b13f0dc82d4269e2c806d2d58e6dde35": { - "balance": "9546969736042000000000" - }, - "346089ea81f7dcb79caf2444df34bd6ee78be4bb": { - "balance": "4344080889000000000" - }, - "34984a8f96dbbfd1f977826a4c2187482559a2e4": { - "balance": "25000000000000000000" - }, - "34a5cce96d2211feb04472260c4cd368bda8432e": { - "balance": "1240050112677000000000" - }, - "34c026a39e44955d1051e8669f9cc58a027455c1": { - "balance": "20000000000000000000000" - }, - "34d730652f4aa002a9f39a47212ca3bc47506b8b": { - "balance": "418050617956000000000" - }, - "34e1d8c8a32ce0f6378abb9bd05ea1f9bfdc5782": { - "balance": "20000000000000000000000" - }, - "350b228870445141f4417ea5dba4f009d693b96c": { - "balance": "76995849736776000000000" - }, - "350eaec708d5d862831aa31be2c37b2fdcef97c6": { - "balance": "258753545822704000000000" - }, - "351fc1f25e88b4ccf090266ebb408593418d8fde": { - "balance": "10000000000000000000000" - }, - "3523ac7a6e79162bb8400bf161cb59389432aa51": { - "balance": "436606776923000000000" - }, - "354d490095e79a29bda2fa11823328450f14333b": { - "balance": "50000000000000000000" - }, - "355a555a36e319e76042e62875a15e1db3012b86": { - "balance": "20000000000000000000000" - }, - "3568840d0a26f39248ab088653ede831f150ce29": { - "balance": "16000000000000000000" - }, - "357096b9c1c7c8d51b682ed3c43d150f55629ff2": { - "balance": "900090781248000000000" - }, - "3588c47ba9204b672c456ee9b5c1ae70f3c738ac": { - "balance": "10000000000000000000000" - }, - "3591edeb9c036e871b4fc6fb3ae6d42e0c0d7203": { - "balance": "1000000000000000000" - }, - "359d92e3e8757a4a97187a96d408c0c11f5c7eb9": { - "balance": "22330509101591000000000" - }, - "35aac2a948f316ba93ed111ac127e29ee9a3adb0": { - "balance": "364387817746000000000" - }, - "35b20459a7daa5f44ae423fd4a1b451ea5090b09": { - "balance": "20000000000000000000000" - }, - "35cdaa84c1f3bc2673bc0c60222c133bae0d3db1": { - "balance": "15234182435000000000" - }, - "35d554233ca690130aaa43501e121a208c657226": { - "balance": "10000000000000000000000" - }, - "35ed399940ece44d01ac873b9c0d3212e659a97e": { - "balance": "55000000000000000000000000" - }, - "35f164612afc2d678bb770f317085ae68cce19bc": { - "balance": "693763596328000000000" - }, - "3601b36cb475101d0d0976a8de9d38e5f3483a08": { - "balance": "1000021000000000000" - }, - "361368bc42c8daf365bce9f9ff3b611373d7b690": { - "balance": "21658400518000000000" - }, - "361bc43be077a269e3e37c11e91479017c47f847": { - "balance": "268900383140000000000" - }, - "363c7a2203f6f93287de091bde3c87eb6800e7a7": { - "balance": "20874859005000000000" - }, - "365dc06856dc6ef35b75b1d4eabb00a7220f4fb5": { - "balance": "30000000000000000000" - }, - "3660e246bce68e2b6e4a802681f188587d2c1c99": { - "balance": "55000000000000000000000000" - }, - "366868ef8e193d7e649ee970d476e6774d5ff1ac": { - "balance": "2544456626840000000000" - }, - "366f7f762887cfb2d09cefa4a5108cf390bdeb41": { - "balance": "26837527714000000000" - }, - "36759f9c92a016b940424404de6548632c8721b1": { - "balance": "1033159825798000000000" - }, - "36a939be88508646709d36841110015bf7cedd90": { - "balance": "144000000000000000000" - }, - "36adca6635db6b00d28a250228532fe560127efb": { - "balance": "3370820618318000000000" - }, - "36bfaed8099ee9f216193ade26d21656c98ce4b5": { - "balance": "1353728563832000000000" - }, - "36df854d0123e271529a8767d1cded4e7b5f31d6": { - "balance": "10000000000000000000000" - }, - "36f59989a902cd10725ff7fe2cab1689aa4e9326": { - "balance": "20000000000000000000000" - }, - "370d6999ae70e781c81d12dc259ea304183b01eb": { - "balance": "45563989086590000000000" - }, - "370e8af59a64a3171b422913921a1e2f982dd512": { - "balance": "170263356254000000000" - }, - "372e01083072214134018f50bde3c8ac4f6e071d": { - "balance": "1400474252324000000000" - }, - "37410fda52f94185d824258ad5f3c9ad9a331257": { - "balance": "11830521097085000000000" - }, - "3752b7e1628275522cd693307787b9564501d959": { - "balance": "67839627078000000000" - }, - "3776f82701c384ce6cbf6a8fea40772cb882b66d": { - "balance": "50000000000000000000000" - }, - "379f63e538168925ba6313f9a6a3b6e7f0e8ed52": { - "balance": "292876625446000000000" - }, - "37a24c1a8080ab429a136c5582782b276eaa931f": { - "balance": "6099055841000000000" - }, - "37abbeaf24b5e6264c87633734852e243d377010": { - "balance": "1051360014489000000000" - }, - "37c50cecab8fe9dcd81aaede95050d27c53f4d45": { - "balance": "106051638566000000000" - }, - "37f82962c3097f0cd9ff605db66e792025a540cb": { - "balance": "10000000000000000000000" - }, - "382ba1e6c53cd7b9c360ef894962d281d557561f": { - "balance": "216789631461000000000" - }, - "38309b458993916efc1ac8b0b5d41302fec21095": { - "balance": "999139000000000000" - }, - "3847f25956a97a32caac059fd9e4cdc105756e25": { - "balance": "876497264905000000000" - }, - "384fe5f399638d277d4fb93f26d527497939287a": { - "balance": "280035151914000000000" - }, - "388335d8b92b445b1b19a3107547bb6ca7c0763c": { - "balance": "167140942784000000000" - }, - "3894a1e65973a542101caa4dc01e9553a5521d63": { - "balance": "34262479791000000000" - }, - "38a0e019c6120a19acaf0e651dd8338982cdaab1": { - "balance": "153843170492000000000" - }, - "38d4bdb10819a7d4ae9a32f4abb82402dff319b5": { - "balance": "1471131830647000000000" - }, - "38e56a55e2ac8320a480562f4a7cea9220306ee3": { - "balance": "907464312139000000000" - }, - "38f18123f3643e03d24ad759afbefc90ed923a2a": { - "balance": "943729130798000000000" - }, - "38f764c861def6d5d65e5ec099536f4cfcc3af55": { - "balance": "20000000000000000000000" - }, - "391e12b51fc85fb879a72fa746ca06c7a5659e6c": { - "balance": "9000000000000000000" - }, - "392342dc7b475c3975877a41622be0fed8e386be": { - "balance": "218719857770000000000" - }, - "3944cc960b8f1993ad841629a79e53d0535a88c8": { - "balance": "210571656485000000000" - }, - "396219864b8cfb0ffb3c675690ccd7026424ad4b": { - "balance": "138984508746000000000" - }, - "396403f26b388150b4876485b124a49845101464": { - "balance": "10000000000000000000000" - }, - "396f1e0f9e7ee86d1b2159ab8f9353677d12d340": { - "balance": "121000000000000000000" - }, - "397cc9f6254d56c721c767e41628a9078bea878c": { - "balance": "225000000000000000000" - }, - "39878b0c7049fb179aba0015279eff6cc3136816": { - "balance": "33962071375000000000" - }, - "3a06b58d0cceee5b091fe6aeb0fc0db5774e9395": { - "balance": "272033811720000000000" - }, - "3a3330e0152d86c5aa1d9bdfe9e1697645d3377e": { - "balance": "2165107207206000000000" - }, - "3a3bb8ed3130e09fbdfc21db3571d4711fc92d60": { - "balance": "885484658836000000000" - }, - "3a4ac96c489c864765cb1997a0084ba745b67a87": { - "balance": "1257436384863000000000" - }, - "3a69e1c351978ced418cea6cee019f220bcb065f": { - "balance": "579242822216000000000" - }, - "3a76a23d81929bed05ef7e1982d32b456e62aa7c": { - "balance": "1027078338792000000000" - }, - "3a7beadd1e11d0e3326c0dcd0f670530612931a5": { - "balance": "20633069818937000000000" - }, - "3a867c44d0dd06517a82ad467d0aefd7f11ce729": { - "balance": "12323708574000000000" - }, - "3a969ae486215e24c7ab89e38929562e2f85d923": { - "balance": "18955477335000000000" - }, - "3ab81366d898a8b798afb08a4b722ab0eb883652": { - "balance": "1220090012596000000000" - }, - "3ac1e14ed5929d382f6488c5444e717373ed29ba": { - "balance": "2030543873000000000" - }, - "3accf4b8ef20e4fea983f13f99ab257a5f9e988d": { - "balance": "156030342415000000000" - }, - "3ad38fa6e3c078025794e213d9dcc5aa397050c2": { - "balance": "36561766773000000000" - }, - "3adef81b2c861ae39c418d55be99aee2306e29fc": { - "balance": "15752410974000000000" - }, - "3b21ff4d5801d3976643899f195fbfd1b72a50b3": { - "balance": "8971221745646000000000" - }, - "3b2f2635dd428ac0b5873088a9a81800f09d6e02": { - "balance": "56922872447000000000" - }, - "3b39919c7bc8d0afec792288c56ab7f4934dc7d2": { - "balance": "1678237240464000000000" - }, - "3b468d9d5546810aa837c29ccb8349548b0e8170": { - "balance": "1100000000000000000" - }, - "3b83d1b651f117f1559a19b04ef408619c2dc4a7": { - "balance": "53628552066000000000" - }, - "3b9a72201bb1e8e678e36129cb1570e3ac99270e": { - "balance": "25000000000000000000" - }, - "3bcab1535b04a0a3fbb673bc41fedaa80bf7901c": { - "balance": "1526488015042000000000" - }, - "3bed42c3d0c49ffac87b9d482f6338fdc9e3880e": { - "balance": "26189771073000000000" - }, - "3bf736b57f0ae47f3714a6bb852090a543b9d367": { - "balance": "652395174320000000000" - }, - "3bfd481651956105ed909eeb98be404ec5ae77e9": { - "balance": "177520143473000000000" - }, - "3c0a12a327545b5f8b7b5c1f7a1ec6a341ec9578": { - "balance": "4184342789398000000000" - }, - "3c132698d59927fe08cba433a41d08acc96c0edd": { - "balance": "151913899135971000000000" - }, - "3c27bd92c4be1a19974ec773bd20b13afe582c9f": { - "balance": "10000000000000000000000" - }, - "3c2ad171573a608286f1fa3f5ef9e6099823983e": { - "balance": "3240802189194000000000" - }, - "3c4b5e808b9fb8baab1144b981b6cd53e216fcdd": { - "balance": "61214114118619000000000" - }, - "3c4cfc6ead044819ceb41c1c64ceda1a228af801": { - "balance": "9000000000000000000" - }, - "3c553afd45535f7c2a70c701d00890e607b96ffe": { - "balance": "2678827200938000000000" - }, - "3c620d55268c55b6deea3b7dc7f59dbe93b6e141": { - "balance": "55494311990000000000" - }, - "3c9b204db23b902d4295e6aba3405917efd59449": { - "balance": "55543672571000000000" - }, - "3cf233b7730a175d05a861318b7bb917bb5bee06": { - "balance": "1867187351033000000000" - }, - "3d292272992397ed5f27d5202da693128d023d35": { - "balance": "79770828413000000000" - }, - "3d353cfe84e9a93aef90547fbeb6e4b4bef83069": { - "balance": "36000000000000000000" - }, - "3d54da4ddd0621822a114581ecd15572e6488be9": { - "balance": "1623867132383000000000" - }, - "3d62ddc67d366fb055eaf92c936a6e7df5085454": { - "balance": "124933526793000000000" - }, - "3d754df1151b9b62a6ed48b477225121c29af063": { - "balance": "50000000000000000000000" - }, - "3d79d1ebd5224ffdc13e27924ab7f9f8e3452ec9": { - "balance": "520163228474000000000" - }, - "3d84fd9785a6bd3148847038c6f1e135042a892e": { - "balance": "10000000000000000000000" - }, - "3d9574c3860f30bcb42523a0cbb08aa7dd83e733": { - "balance": "15259904884000000000" - }, - "3da809a5911ccc77f892034049a97a9022c35e7d": { - "balance": "1415009021101000000000" - }, - "3db9a6c6ab3d0cf6d3bd7e04bdad39b4d419ab13": { - "balance": "9999781764000000000" - }, - "3dc7367c3218f88de8867c425f89102d2f2056f4": { - "balance": "10000000000000000000000" - }, - "3dd273dedb28824d1309c7d60a0744a6b6353e79": { - "balance": "9000000000000000000" - }, - "3dd6b25eb91dd2f3468e0786e8beb465abe7f515": { - "balance": "275172962210000000000" - }, - "3e0d14f83b304136311a33bbac2720c0cd66f117": { - "balance": "3390479675000000000" - }, - "3e15e947ee76f52f0f2a7d84da7c4ab060eb5cbf": { - "balance": "6751398714759000000000" - }, - "3e1b5469e1da4ec27537513f4df3f1a338a7dc2d": { - "balance": "161899580000000000000" - }, - "3e3329bcc90e47e4dabb5c93572b18b5e0efa024": { - "balance": "10000000000000000000000" - }, - "3e5a585ad0f34d78899433edaed574af052616f0": { - "balance": "910225655353000000000" - }, - "3e6be9615713bb06198bf354ef434a9db649699b": { - "balance": "783525278181000000000" - }, - "3e7c7c082f2f99b1ad579400a2e93586a24ed992": { - "balance": "159035553843000000000" - }, - "3e86ea5713f90022c0914fcc25e97c39487eb957": { - "balance": "101867287023438000000000" - }, - "3e9dabab6e50a696edfba6bcd44230d087c8d04c": { - "balance": "3315882414579000000000" - }, - "3ed956f86fe78223c86e164e4f372c9a0bf4a279": { - "balance": "119959915220000000000" - }, - "3ee87e776fb12e9c894e36fd5a61daa984e8a5cb": { - "balance": "50000000000000000000" - }, - "3ef1c8f294443f776a794563ce7569a8fe4d5d20": { - "balance": "25000000000000000000" - }, - "3ef6a396d6611df6c79ec1e6ad6bbd253917fbe9": { - "balance": "10000000000000000000000" - }, - "3ef727346fc631ae6473e9a36e2e5e54df696195": { - "balance": "121000000000000000000" - }, - "3efdcf2c0998637cb82d2b5fc24f27162578d207": { - "balance": "1054861112990000000000" - }, - "3f2cb2335e2bc07744175c497e2f437e87c2a146": { - "balance": "48999979000000000000" - }, - "3f4d16663a4f76ade93eb8bd6ca8fe2158e24322": { - "balance": "237117597268000000000" - }, - "3f7c5e6aea7f3f74d764df50f0fc1aa758fc99a7": { - "balance": "63372222562060000000000" - }, - "3f92239fdb41c6ec228252248c2db3f23675e275": { - "balance": "28538064487000000000" - }, - "3f9610454b621c04f00f01f4d54046502edb21fb": { - "balance": "16000000000000000000" - }, - "3fcfb30cbfe53c0c43f58c28386d9a6e5b49f7cd": { - "balance": "79080579219000000000" - }, - "3fda0c9a3d3f0000635376f064481d05d1b930bb": { - "balance": "10599947385000000000" - }, - "3ffce0475430de0bd9b09a412e404bc63aa28eea": { - "balance": "10000000000000000000000" - }, - "3ffe7583b568448ded5183e1544bca0d283680d2": { - "balance": "1076944549283000000000" - }, - "4003a137e577351a4ad7e42d1fc2d2cf1f906b6f": { - "balance": "25000000000000000000" - }, - "40215fc4c6300d8d8179383d9028fd2d909c6cc4": { - "balance": "3941346079000000000" - }, - "4027d7bbfa5d12c1ab9d08933a1659ae8dd023ee": { - "balance": "1156537386462000000000" - }, - "4039439c960070394dbda457726d97121c7b3669": { - "balance": "4444061364102000000000" - }, - "405978c24a12d930ada6163a44fc4a70c16569e1": { - "balance": "707298643296000000000" - }, - "405d2c1b55ba3f67c8634456b99c19092b407a10": { - "balance": "1462185951849000000000" - }, - "405ddfcf45005cf5a0ee1bfa605a7346a0167945": { - "balance": "88775535985000000000" - }, - "405f72a6940acf5d36a29498075f2d0d7a75bc22": { - "balance": "402796678569000000000" - }, - "407253b005ae97857f812fc60d441e5367b4bac8": { - "balance": "1484147810895000000000" - }, - "4091e1fb1c7af51a64c201d6a0c8f0183dfb7ca5": { - "balance": "10000000000000000000000" - }, - "40950bad9580d4b111955da7d3f9ada26dd9f05a": { - "balance": "500000000000000000000000" - }, - "409a28106192cae7a76c6aa8add0f73dcd63d2c0": { - "balance": "214832616721000000000" - }, - "409d5b872b059aea9a773e854f9a17ed2d5c2ef3": { - "balance": "64000000000000000000" - }, - "40a6e3c753b04c42fcf89cc30df8f50418caecb8": { - "balance": "754228409494000000000" - }, - "40e5ce1e18c78d6c792f46ed6246bfb31bcdb6af": { - "balance": "500000000000000000000000" - }, - "4121692a14554ddca1ca662fb577d7152d4fa7d0": { - "balance": "49000000000000000000" - }, - "412acb10c8ca937ddd64cf0d413b1dd34760f72b": { - "balance": "6073360870000000000" - }, - "4166a5c94d5ae48ced410f950d40656182bf8990": { - "balance": "55000000000000000000000000" - }, - "41752b7d0d3ee58a6b69d8ba721c0894ff701237": { - "balance": "585556720807000000000" - }, - "417c86d6bf734e99892a15294230771bbfd7e1e1": { - "balance": "38233258264000000000" - }, - "418414498f7361b29428c54732e1f49fb394f813": { - "balance": "2063786326155000000000" - }, - "41a424dcbff6bf31686f5c936e00d21e8a4e0f78": { - "balance": "33554754580438000000000" - }, - "41a893429d5f8487c1866b87779155d4bfe33198": { - "balance": "20000000000000000000000" - }, - "41bbedd607fa576d130305486824cd2871bf6b05": { - "balance": "649728993301000000000" - }, - "41ee42c1fb1bcdc9c7a97a199fdcf9b63623521a": { - "balance": "7906012418597000000000" - }, - "41feffaf56d1712af6965fa6eee1b06bd624e7b8": { - "balance": "49000000000000000000" - }, - "42107e765e77ea76b3d6069d3775bc3aef7d692c": { - "balance": "25320783684183000000000" - }, - "421f4dab3240e15a1c78e3ce8642de9b578b8e4a": { - "balance": "832511242936000000000" - }, - "4246c52c3601541a873d4bbaafedf28b9bad5b73": { - "balance": "10000000000000000000" - }, - "424efe1ba28bb1aeedc38a3a5135547d0fe80751": { - "balance": "25622294162729000000000" - }, - "424fb0a3ec325bf42e7edbef7e450f2ffd1cf318": { - "balance": "20000000000000000000000" - }, - "42714c04d17f6c29029daf7f50d1cbad6590cfad": { - "balance": "271755674161000000000" - }, - "42b66e9123d304b70fef3dbcfe8587fd6189b5c4": { - "balance": "1030481609000000000" - }, - "42dacbc412b829cb304ffbc316b3f81b379bfc80": { - "balance": "304208485736000000000" - }, - "42e3d9832c8b6cdea39c97525570391803dee276": { - "balance": "2581020833000000000" - }, - "42f757898f95c1b46f64a4a6b7f86ab03022d672": { - "balance": "100000000000000000000" - }, - "42f7956fd659e00d3be2f3d1d4f3ed187aef04d6": { - "balance": "50000000000000000000000" - }, - "43160b2bc00f7f8f7fc806e2f6e2ffdc62b3a651": { - "balance": "1000000000000000000000000" - }, - "431b77cdd067003eeed26c1aee32f67fb94f7092": { - "balance": "902514849986000000000" - }, - "434e44583786e354731bca250d94ef0d8860a538": { - "balance": "1187789683866000000000" - }, - "434f1b9b193c88bf58685124aac0167fe69f9014": { - "balance": "500000000000000000000000" - }, - "43535982688844fa703cb9bd5723790cab364049": { - "balance": "100000000000000000000000" - }, - "43559f405590592c254e427fa25f03e774d8defd": { - "balance": "6913200000000000000" - }, - "435c08c481d59308a64afec0d6f936321bb120bf": { - "balance": "9005920819593000000000" - }, - "43629748a92b846f21f637aac5103412fbabb9a6": { - "balance": "1177513692845000000000" - }, - "43650b37552882d225ccc977aa2b7a86a4ca9bb1": { - "balance": "16000000000000000000" - }, - "4385de394371d26a45f18e8b3842effd015027bf": { - "balance": "187331693412000000000" - }, - "4386ff9648fe420503c9a36fe7b97c079de3b770": { - "balance": "2714401478778000000000" - }, - "43b370c4457cf39a3be86cc00c2b27614ca6e638": { - "balance": "8316429850934000000000" - }, - "43c464ea740172fe6f4f09974106fd24029837b9": { - "balance": "129643160399000000000" - }, - "43ddd2d33dcb7e578f4e59ad6b9c61a24c793aa8": { - "balance": "500000000000000000000000" - }, - "43e0f8065eb7faf3bbd13bc7c5d5d8f5ff1bdac3": { - "balance": "4454324716300000000000" - }, - "43e96cd065d7934b246d0fec8cd2dc6b36d56d7a": { - "balance": "81721481452000000000" - }, - "43e99acabfbdc6cafee3afb12fa7ed1345370b2d": { - "balance": "4595292398872000000000" - }, - "43fae764c7555b859b93d2126edfa59cfbf298b5": { - "balance": "105746805109558000000000" - }, - "44052eb938c02776b5240f38ec99f5ef51ef0d87": { - "balance": "38446396949881000000000" - }, - "440fc7621cc17f121f0bdf2a68c5be2c3af4fd3b": { - "balance": "1026958147051000000000" - }, - "4440ccbc77249a4d891d9ab5a5f2026b17aff7c7": { - "balance": "10000000000000000000000" - }, - "447f3f702c13a3fbdc8675c6285702b5aa2b66bc": { - "balance": "1089533398014000000000" - }, - "448f152be153fdb0497403f70e37d876946a5021": { - "balance": "614429461682000000000" - }, - "44a1e3a044f5d1fb00f4beb3772a3ee08d8b7093": { - "balance": "1000000000000000000" - }, - "4515edc7154bedd7143b69a04c4e738f8aa4ab18": { - "balance": "10000000000000000000000" - }, - "4572148fe5ea9d4795e1f1ed93097aac1d70991c": { - "balance": "2873782218000000000" - }, - "457581f223b8eacd757abb292613e317d6f59305": { - "balance": "3582446780073000000000" - }, - "45b450961882850f7038d5cdcd2a8fa2dc4b5469": { - "balance": "20000000000000000000000" - }, - "45bdfdf3840d4341503cd7fc87e4b66f6179e5fe": { - "balance": "10000000000000000000000" - }, - "45dd9baa87b3c94df66308d8ed4f3a5bb65c3dcb": { - "balance": "25000000000000000000" - }, - "45de332b8ee95d886cf11b99291b46f46c1ddd45": { - "balance": "36000000000000000000" - }, - "45e06afdbc70288a2cc55bccc4fb2d8195aea028": { - "balance": "790360485306000000000" - }, - "45fce5fd1acb2bc5507723c897cb340437e39735": { - "balance": "100000000000000000000" - }, - "46045cddd940d80596826ce5354489b3047663bb": { - "balance": "100000000000000000000000" - }, - "4610286f8a2649dcfbc6d91735745f418a6abc75": { - "balance": "10000000000000000000000" - }, - "4615905ecc6f7df0ccb7b86a3e1d3770adb2f874": { - "balance": "1000000000000000" - }, - "46256e00ff927d54b0ca139ddccac2148784273b": { - "balance": "10000000000000000000000" - }, - "465e40e7d129ad310fc60ff0f17c0f968611118f": { - "balance": "677971225649000000000" - }, - "4664a920f7fe9b0d78a665e1a4aeb95f287d6059": { - "balance": "20000000000000000000000" - }, - "46679de1c6143138fd9c44ff05853a52371915ff": { - "balance": "363627463229000000000" - }, - "467cdc210ae48ba99740d37ee79fa57c4216bc81": { - "balance": "10000000000000000000000" - }, - "468053d193debb88735571acb24b764f2676272e": { - "balance": "49000000000000000000" - }, - "46826d1f1418abbe4e7b9236d643e5b57a0f0208": { - "balance": "37752144164916000000000" - }, - "468df2ea57972ddeb88d470a5f3c2c0e2284ac17": { - "balance": "757320434551000000000" - }, - "4695ad5b686520ee8426d24b50ff7a5f0d703443": { - "balance": "2851082366000000000" - }, - "46a149bc8ec2b85fdf938f753a6c53777dcca2b1": { - "balance": "10123698633000000000" - }, - "46c081440f760a21b74c2499bdda13aef8245930": { - "balance": "180752319265000000000" - }, - "46e615324f6e4fb242f9bfecffc0c802ba7733c9": { - "balance": "10000000000000000000000" - }, - "46eb54f09dbdaaf3b97a1f79a3d82ee2e902b3b8": { - "balance": "3430510380318000000000" - }, - "46ebb24b04919ec0164f0bafcebca2309f2d3035": { - "balance": "129155832233000000000" - }, - "4701f9fe78111011f820fe28c47522e601655678": { - "balance": "9000000000000000000" - }, - "473f44e2c1d5d7aa53cf7041d7ad19a0d9eaf1d8": { - "balance": "162679637505000000000" - }, - "474f8bf4d03a7efa4d190905ce062eea7c75118c": { - "balance": "1259904506149000000000" - }, - "47598330e862a4f7cbda8be74ac10cd5d370a55e": { - "balance": "291763101699000000000" - }, - "476455d48fc858a06bd7854fcf1bd60bcfde9ed3": { - "balance": "10000000000000000000000" - }, - "476826d58192ad822f4686311d6c6d4d4f66ee5f": { - "balance": "453184657722000000000" - }, - "47a231eb3fdbc24f2d008f06228624b2a45ae5fa": { - "balance": "1000000000000000000" - }, - "4805f4c0eb1c83c436118ec9148019e5fc1962e3": { - "balance": "1311161626928000000000" - }, - "4809f373cdd56c8481ba3bce5a401d55a7e50a50": { - "balance": "2284845194349000000000" - }, - "4839bf9ad56873abd5695057bf71972806cde827": { - "balance": "42264923611000000000" - }, - "486dba2a47decabc9a85d1d64d74687983ab273b": { - "balance": "49000000000000000000" - }, - "4877993f5ecf02451f8d4591594cb2f30dcf9f26": { - "balance": "100000000000000000000" - }, - "489723e325f609e27be14528c4111fb3eec13f7c": { - "balance": "2489030141000000000" - }, - "48b710d16e9da736b773453089d69cc6ede116b5": { - "balance": "26651593216000000000" - }, - "491088e1e4b5c3d65870f2deef9be6ec3dc6c7c7": { - "balance": "1446809481953000000000" - }, - "49174451320ad2e14cb2b05ecdd251b75ace3038": { - "balance": "15533380764616000000000" - }, - "4956ead915594b621131b2fc2dbbb49ba43c5559": { - "balance": "1175638488000000000" - }, - "4973a0d32147ba89f525a18f989518dcfce93b0e": { - "balance": "522848489444000000000" - }, - "498c6f9063705054fae07260d4176c3d55a97650": { - "balance": "732941433000000000" - }, - "49991f68f2a76bd1cffa3e9721be36f3fd8351b8": { - "balance": "17742568700019000000000" - }, - "499a8af194e0040f349e893937fe3858f8267fca": { - "balance": "80704784160862000000000" - }, - "49bcbb7b263febf54f8ff498525bac8e7241f966": { - "balance": "603044032468000000000" - }, - "49bd72773656c4e1a4d16284aea2fb05546d2b31": { - "balance": "1896607093054000000000" - }, - "49bf80fcdefebe8cd4830ba09e46ccd7231c8e6f": { - "balance": "10000000000000000000" - }, - "49c9d82dea78f14b1c52efc0196b67f508f7859b": { - "balance": "2313040051399000000000" - }, - "4a2daeacf0468d137e3bc464d6d5fa3893a9136b": { - "balance": "10000000000000000000000" - }, - "4a6c428f245e8d9115b34764bab17eb86ac472be": { - "balance": "10000000000000000000000" - }, - "4a6e8d037acf1960dbbf14e7a02fec0ac656f9c1": { - "balance": "6516295825438000000000" - }, - "4a7e7fc3c72f2f9b92bf0dcd5297cfb19f077d7c": { - "balance": "99426213999999999" - }, - "4aaa6817a5000bb7596e000135b3051c5931e7c5": { - "balance": "102884105546478000000000" - }, - "4abcdc3d7d3d314a163da92aee53a56b87313a2e": { - "balance": "44402243657000000000" - }, - "4ac9385ade2377b061f4211b392ed6a6e7fb83cc": { - "balance": "1000000000000000000" - }, - "4ac96e1e26cb66ff788ed8c62db811d7b4fdbc74": { - "balance": "68476115774000000000" - }, - "4b10c247caf33fb872d9bf86572424410aa86752": { - "balance": "337915294240000000000" - }, - "4b23ffff1894df49005c7afc0828880924571299": { - "balance": "169848767272000000000" - }, - "4b486895caf3a0b5afa198df744de7082eec8666": { - "balance": "1672587376054000000000" - }, - "4b98fc960610573be456c0e1e319f4f863bf9095": { - "balance": "259382246718303000000000" - }, - "4bc0cc483be20223f40ed6deef63dd9645c216c4": { - "balance": "4322684620000000000" - }, - "4bf4a046afdd4ec9d0e50730ff6ded5ef2327442": { - "balance": "70601389160000000000" - }, - "4c0149058e2e74f7c900e6d6e5fa12eea882c5e0": { - "balance": "2017399852886000000000" - }, - "4c17a3997fb70599794d01a33a27a6d5b52b6f01": { - "balance": "469002093209000000000" - }, - "4c4559e7b32340dce112cf7a021ced1b113f6dd9": { - "balance": "25000000000000000000" - }, - "4c4f02b3f232b8ce8485d425639271510cd0486f": { - "balance": "68828038140000000000" - }, - "4c52ec56142bb6e8c8830e5c17b01b5165915f3c": { - "balance": "321766233041000000000" - }, - "4c58defa57875e709ca039a54a2be5aed6672f6d": { - "balance": "121000000000000000000" - }, - "4c5a886ab90b6bac68677a7eb92a06bf33ff2930": { - "balance": "236899852150000000000" - }, - "4c60539363edbd812334a54543c40ecab8af2ac8": { - "balance": "3281904094699000000000" - }, - "4c76897d0d5d39195354194710c5e7f99bef63d1": { - "balance": "10232271258305000000000" - }, - "4ca3c03780c20a64f3b5ebb75669982a71ee8a71": { - "balance": "377172198976000000000" - }, - "4caf77eefe062a6f053a464171bc75254b47f52b": { - "balance": "20000000000000000000000" - }, - "4cb7d7ce805e56f6e47e94cd755b6d97f8f996a0": { - "balance": "120998866000000000000" - }, - "4cd34f8f3299d3b7aaee180baa0b432369e1b3d6": { - "balance": "197088135242000000000" - }, - "4cd7aaa5415d809f405f520e4c0319a6029b981b": { - "balance": "686627368232000000000" - }, - "4d01067555f1ef63883f25c562b07168f79fa80d": { - "balance": "17547055698000000000" - }, - "4d2cb4c1da53e227b08c0a269402e9243a13f08d": { - "balance": "324000000000000000000" - }, - "4d38bb5f48ec37b751d16de32a4896fbda479ce1": { - "balance": "802530078718000000000" - }, - "4db3e76e2f68896cecc9826e10a5e09df0352c28": { - "balance": "555180306924000000000" - }, - "4dc8730d9f032d33dc493bcd3c6375b38f41afff": { - "balance": "5726933881000000000" - }, - "4ddde96556f5185a13617f01ebd9102800bc9e9c": { - "balance": "1181822708402000000000" - }, - "4df9359cb204bf649668ff8086a7f5e24709083c": { - "balance": "262998978400000000000" - }, - "4e0a1a3dff0d33c418758263664b490140da9e01": { - "balance": "100000000000000000000" - }, - "4e0dd6d8de5caa3a3bf9fdd6f2d7b30618623cc0": { - "balance": "10000000000000000000" - }, - "4e11af85d184b7f5e56d6b54a99198e4a5594b38": { - "balance": "76658631121000000000" - }, - "4e314349abc52c686d47dc771ebc8040966be386": { - "balance": "632341985941000000000" - }, - "4e3fb09c35375106bece137dbe0e5491e872871b": { - "balance": "153648535396000000000" - }, - "4e4f0d606f7065bfb1545e60b5e684ae1934e055": { - "balance": "48998635468000000000" - }, - "4e50957aa6c91c548075add8ec625b74c0973abd": { - "balance": "1000000000000000000" - }, - "4e5c6efa76493f0e9422582016aac50539ae60d9": { - "balance": "2078967343000000000" - }, - "4e70bbcb50c4e875fd573dcb694908abf3b30b37": { - "balance": "20000000000000000000000" - }, - "4e7f5670a7dd168a0803e53b8bf72f4db280e3ae": { - "balance": "1658463113665000000000" - }, - "4edaf859990a10977bf378df45b32f93422c84b4": { - "balance": "121000000000000000000" - }, - "4ef41923a1a426772832d3c267adbd84e5994edd": { - "balance": "5432615017384000000000" - }, - "4f11a70d80f36f46ed0c2a5fff1a39b711f3bae5": { - "balance": "8415785077000000000" - }, - "4f159095afcc75b8f5cfc90c9d07a0d77ac8ed69": { - "balance": "25000000000000000000" - }, - "4f2652322736cc18b24af582d4022fe329a9dfb7": { - "balance": "9000000000000000000" - }, - "4f328173f352f3dfdca0ff5e3185f26de77c6f75": { - "balance": "10722917874680000000000" - }, - "4f47a62aba6ea049fc0e92d8afbe1682472d98bf": { - "balance": "10000000000000000000000" - }, - "4f4c3e89f1474fe0f20125fae97db0054e9e14e0": { - "balance": "50203638983000000000" - }, - "4f5ac8dfe79c366010eb340c6135fbee56f781d8": { - "balance": "50000000000000000000000" - }, - "4f672cbd373183d77d8bd791096c6ebb82fa9a2a": { - "balance": "978111227765000000000" - }, - "4fb179c9c88decaa9b21d8fc165889b8b5c56706": { - "balance": "24750205150000000000" - }, - "4fbcf391c765b244b321875d6ab4381c44d0747a": { - "balance": "99999580000000000000" - }, - "4fc979b38b981fca67dfa96c6a38a17816d00013": { - "balance": "1088876196468000000000" - }, - "4fdfdd1832b114b4404aae23305c346beee14e1d": { - "balance": "278724179057000000000" - }, - "4feffb1836029cd0e9b8f4aa94b35ae3982fa770": { - "balance": "1674590934924000000000" - }, - "50045745a859f8fce8a2becf2c2b883b3723b2c8": { - "balance": "169000000000000000000" - }, - "5028bde29fe88e03e3de069b3907fa9df551c379": { - "balance": "196000000000000000000" - }, - "507096ed771fa8a1d004ee5377c01506df461b32": { - "balance": "2669205000000000" - }, - "50788574a0967580fdaddc4758f834d8978455f6": { - "balance": "1648581593000000000" - }, - "508d8e8f338ca98d3c09f0f15fd9e7baa80701e8": { - "balance": "16000000000000000000" - }, - "50a4dc916845172b83764a6c8b4b00d6d02d41d3": { - "balance": "3020744393592000000000" - }, - "50da06418780c220ced4898af0b1fca533f73cca": { - "balance": "36486700700823000000000" - }, - "50fb6fd8432a66219e754234e9eea1dabcc07676": { - "balance": "489500000000000000" - }, - "5104bb1b831902333732dd25209afee810dfb4fe": { - "balance": "1333614132000000000" - }, - "513963743ec6ec9dc91abf356b807ebad64df221": { - "balance": "1508002412172000000000" - }, - "51397ca69d36e515a58882a04266179843727304": { - "balance": "941648956414000000000" - }, - "514a58f2b36c2cf1b6293c36360cf658d8af30ed": { - "balance": "1233397704089000000000" - }, - "514fe0cdb3de692cab9f2ef2fd774244df71be66": { - "balance": "9670444445882000000000" - }, - "51583128081fd800d9550144afebdf3fe88149cb": { - "balance": "231190355520000000000" - }, - "517384fe92391187d0e65747a17bfaadf967c331": { - "balance": "1943121865489000000000" - }, - "51aebfaa26a54071cfe6c2d8f81157ec313984ad": { - "balance": "1422225031261000000000" - }, - "51d4f1205b272e491e94fe21f0341465f14141fc": { - "balance": "552384783614000000000" - }, - "51de598faa85276bb26a68b135028755304b6700": { - "balance": "2068484560002000000000" - }, - "51e08e0304f08ef768c80ca149da4721fcf482b0": { - "balance": "194629207228000000000" - }, - "51fa3da695e24f602952a71966f37ac3596a94a4": { - "balance": "17008166261720000000000" - }, - "520b22776b1befd3064636da0dd251afe569ef13": { - "balance": "18538137781909000000000" - }, - "52219a1e1aa82b78b971088c30583a3bbe675c8e": { - "balance": "411959222637000000000" - }, - "5252b8a0688096523498cb5c1f42bcd1f61923d7": { - "balance": "1863936864000000000" - }, - "5259154e1a5a809b2e3dab80372124cebbfd56e2": { - "balance": "110000000000000" - }, - "5264f2de516835e549710bfe34ef03b08b8557dd": { - "balance": "1216000000000000000000" - }, - "52b17fae7e9cac447f026db71dba4034a1d53174": { - "balance": "99001631977000000000" - }, - "52b3363ae882a99354faeb76733d0fa2cbb89787": { - "balance": "102517584327000000000" - }, - "52bee7fb24a7fc1f34cf0874ec2f06c5fe847cb1": { - "balance": "54443400591000000000" - }, - "52d1f12d391c7a2f3b52939a61a20da5f85eecc3": { - "balance": "2707175772061000000000" - }, - "52f27099483589e883e7eb789896de39c61e46da": { - "balance": "358944977251000000000" - }, - "52f3b715b678de95d1befb292de14c70f89f5e03": { - "balance": "2989868434000000000" - }, - "53259780569f6dd6753c1da1d53d0b155c5b30d2": { - "balance": "200489122590000000000" - }, - "532e4908e8297c90d75d2280b432b469aaafa2ac": { - "balance": "20000000000000000" - }, - "5334d1e399feacabc9648cebcd93172db95d43be": { - "balance": "25000000000000000000" - }, - "5341665addfb5e367f7a7d35de95b87a0cceb3a9": { - "balance": "60544291695000000000" - }, - "535a39a854ed1c2f0afbc5944f1ee0e2e68cf65a": { - "balance": "2141913781000000000" - }, - "536515c0c08988ee69da1d75f18c706f6b9bf7a3": { - "balance": "169000000000000000000" - }, - "5387a1ce4cd2ef4f90075c15dc3c0744948ec356": { - "balance": "50000000000000000000000" - }, - "539a30ee5724978010990718bb8b0dd25f89fd15": { - "balance": "1306896514000000000" - }, - "53a5f87dfb17149b8c2934a2a9d519ace4ac9724": { - "balance": "4569449510000000000" - }, - "53b24fb36e72c22eb830dc93857a8188b03397a9": { - "balance": "64000000000000000000" - }, - "53cc35b3daf4b8e1982e0e63d0bc68d7252e7fcc": { - "balance": "68213426853658000000000" - }, - "53e1f85147e000ae1ff6a5910407395e388c683c": { - "balance": "20000000000000000000000" - }, - "541f43ff66ed5eb1a1ea0ae3f86355ecff665274": { - "balance": "49562725831000000000" - }, - "5428a31f736c0d2b3c4e80baefb75a76ed44d3f7": { - "balance": "10000000000000000000000" - }, - "542f732aec0873bf531f6941828b6f0ed0611106": { - "balance": "8407722276000000000" - }, - "54300b6a77b95545373b2bba73e60f37c31eb1c6": { - "balance": "1581215621996000000000" - }, - "5434bd65a492a4d14d3b97eb49f6e491350ef73c": { - "balance": "484000000000000000000" - }, - "5444a1735913eeac177d947ef38de7cd6bdfc0a6": { - "balance": "1000000000000000000000000" - }, - "544ffeab53bdc59ef8edaff0042b03c2ea123615": { - "balance": "10000000000000000000000" - }, - "54613713df6c5b89c3012a7835651f25cdac8331": { - "balance": "98684037547000000000" - }, - "5471fb39b4e48c118f855492830ad9e2eaa68179": { - "balance": "91791250228000000000" - }, - "5472591efd048dd60a4d6afdb549e95a65578b0a": { - "balance": "50000000000000000000000" - }, - "547b4c1ae70567fd77a896dc05eb536f502ac8a4": { - "balance": "14037444012000000000" - }, - "547fa9f6f86a2939f9144aacb74e0af60d434535": { - "balance": "428416957729000000000" - }, - "54841d6a478cb9b6e717a9de35577a1a4a504b0d": { - "balance": "144000000000000000000" - }, - "549157e5b1c92a88a0eef335b1bcf4d162482017": { - "balance": "21019502942000000000" - }, - "5492757c55c72ac5946b21514ee16c5065ecde7b": { - "balance": "10446737491000000000" - }, - "54984a41eeaa8e710e4e5b8a7f68c96057b7df3a": { - "balance": "10000000000000000000000" - }, - "549a3717a1bca3f38d24655197c3ccef1e8c273e": { - "balance": "4416133255000000000" - }, - "54b047fbe004191cd02f31163d29bd61ccfaadf7": { - "balance": "52649445905000000000" - }, - "54b125d8b260386633b756056b7d7e78e7071715": { - "balance": "10000000000000000000000" - }, - "54ffad1ae76ab45c4218ced27e49bf2745b2a2e7": { - "balance": "1426474871178000000000" - }, - "550b28968bae36f4e99780c6d7deb54c158be6d8": { - "balance": "10000000000000000000" - }, - "55117923e8393dbf233c0f10819e7de75569962c": { - "balance": "470094520022000000000" - }, - "554a2471e6ecf2320da545d559c40b8b622465ab": { - "balance": "4052895973949000000000" - }, - "55607b39da9480ed8f54d74d0818ab8798136589": { - "balance": "13704276648975000000000" - }, - "5561cbe99fd775f5d0f05903fd62ba4877b3319d": { - "balance": "1007596371374000000000" - }, - "559ba7ab58670d4a0b118bbf6aed7f6fdb276594": { - "balance": "3127762973000000000" - }, - "55b0bc444f2a5952a98f216f61cf07382da1e156": { - "balance": "18683409750727000000000" - }, - "55c0a02dc68123aca7ee0c9cd073ead50b16406e": { - "balance": "99999999580000000000000" - }, - "55c47d593952afd637050c5758a921a204f23fc6": { - "balance": "1615608723958000000000" - }, - "55c6855b3970e5a550f0c75d5727329476406d91": { - "balance": "600705012673000000000" - }, - "55eadbe33899f53138d0fb204f42e272f447cfd6": { - "balance": "1671128311341000000000" - }, - "55fa59fa0fbba06b7184ea78868d438176eb96eb": { - "balance": "1553000000000000000000" - }, - "560a11493b5a0ec28589e80276fe975ee26c6a3e": { - "balance": "10000000000000000000000" - }, - "560fbb31d83bf6dc49e5fb15bd582d70c49fd273": { - "balance": "46015432815000000000" - }, - "5620e17ccf094b1be1a93f6f3388fb96e3a90165": { - "balance": "484000000000000000000" - }, - "5633512298cf74f4d2b8663e6f291e9e25436e7f": { - "balance": "10026444446000000000" - }, - "564423f92b8841b3b1f8bdba443067b580916e65": { - "balance": "465451550122000000000" - }, - "56730e1d11a84970355c43ac7659f2f4786dadcd": { - "balance": "20000000000000000000000" - }, - "5678851984add045f3d054623c198dfd4665d54e": { - "balance": "227651903234000000000" - }, - "569cf18b4bcb99e3f3d27235f2c4c0d8d160af03": { - "balance": "4124979731000000000" - }, - "56ac5f2c3486a9ce744a71599ab89a606e7464a7": { - "balance": "9000000000000000000" - }, - "56bc5936a6ea37c1d0839bf64bcec0d366840ace": { - "balance": "14741201469670000000000" - }, - "56bf62e0135e903525cc46b0a3cce33f4a16880a": { - "balance": "534970476270000000000" - }, - "56da0781a80a0abf5dcda4da35861e9de601bfbb": { - "balance": "166898390441000000000" - }, - "56db15729e52d615a744a04f8a59d63e3b9f735b": { - "balance": "10000000000000000000000" - }, - "56e32ed78e7f5be6b00c28847efe7b3589cdae1a": { - "balance": "1046236086484000000000" - }, - "570f7a08150e0088178276f8116bc4103f885903": { - "balance": "1124393518440000000000" - }, - "57147fdd9b52ef53b4ebd4b5712d29da83f99374": { - "balance": "39000000000000" - }, - "57395fb355fe51f1b32c1baa4e9ee0fc2b8fe05c": { - "balance": "7701013675397000000000" - }, - "5752f0f11ed12bb1d5041b0cee4ddd500cd8806f": { - "balance": "151337200533000000000" - }, - "575907d73ad5ad4980a2037efbd20860afc67ad9": { - "balance": "3568754158000000000000" - }, - "576acb4c0bccc89903ad285ac08c70fde514aaf2": { - "balance": "25000000000000000000" - }, - "5784cb8a17cfb5392c4aeec2edbd173849ca6ee3": { - "balance": "15804767597000000000" - }, - "579234645eb857a3ca51230b3a02b964f8efa2f6": { - "balance": "20576922380000000000" - }, - "57989f9fa52b4c0502e7d0c3caac0c37a0b20516": { - "balance": "462711082812000000000" - }, - "57a55c376ea03c22e21c797d83e2fb039508ad3c": { - "balance": "10000000000000000000" - }, - "57d1612ea1fddacf088b62f625ad8cd49d7517cd": { - "balance": "18001023230648000000000" - }, - "5811590907050746b897efe65fea7b65710e1a2c": { - "balance": "310984892882000000000" - }, - "582ffd8c43966aa8ad3c6cecdfc18eddc56fe5c0": { - "balance": "69136214255000000000" - }, - "583b90b3c4d00b9ddf101efbce75bb811d969fe2": { - "balance": "7839200298177000000000" - }, - "5841fee8b1965141e51b8c146b6af00f6a879a8c": { - "balance": "1210322907244000000000" - }, - "5847a576f7799ba1a35e36906b2c2a5aadeb99b1": { - "balance": "183765768447000000000" - }, - "586dea7ada0a54150f5afcf54198db473ed046a2": { - "balance": "7123598380000000000" - }, - "586f545062ec7dc0ffc213eacd59af80660df570": { - "balance": "10000000000000000000000" - }, - "587187488758f67912bd5bb8a5be787a73d97ee3": { - "balance": "702757402654000000000" - }, - "58be0a3482dc3411571f047f4128387049cb9798": { - "balance": "1000000000000000000" - }, - "58d546e2ae82efc4d8efc887ac6fd30f7eb5dac6": { - "balance": "1486717153455000000000" - }, - "58e7010e6b8d97a556c0e7f0d90151224ebf674e": { - "balance": "20000000000000000000000" - }, - "58f991b3b12d29f09ff4cc2c6e83d576e95b1f59": { - "balance": "25000000000000000000" - }, - "5923a65a796934e69081715657e8dfec8874e40d": { - "balance": "10000000000000000000000" - }, - "593b7c43073b8954355ed76020ff3780dd6ae783": { - "balance": "1403468567787000000000" - }, - "5947f1dbd79a622bcc3fa64b19f9b6eda164dcce": { - "balance": "50000000000000000000" - }, - "596311e2fc09ae1eaee57900f2ca188afd5e68a6": { - "balance": "448723397560091000000000" - }, - "597a3adac4607d457c90817220f67eb4abcf129f": { - "balance": "18000240000000000000" - }, - "598201a9bcff0a773e9323338a8a094e9d9b3999": { - "balance": "74904485722481000000000" - }, - "599e93031704c2ce36308f44d4ff8166e71ae516": { - "balance": "100000000000000000000" - }, - "59af0178699f9f3d8f0ea645dda75356119a6e2e": { - "balance": "152462578058000000000" - }, - "59b0c06e40475cd75728797add9c69c3fdb17b4e": { - "balance": "23147237210000000000" - }, - "59b79577f183b9d39c2b458646a26b2fd6ed806e": { - "balance": "4244859516807000000000" - }, - "5a03b51d67a9c660258ebc030120d5d1d4f687c5": { - "balance": "4451691855300000000000" - }, - "5a0d03dff6754963c757eb15a3339ac6c4ba6196": { - "balance": "215126489934000000000" - }, - "5a34ab3937854e407a8739fa14574d3d20e30d6f": { - "balance": "1375979293937000000000" - }, - "5a352fbeb2fd78bbe0268b0efd34f68d401e2769": { - "balance": "27929247671418000000000" - }, - "5a47c2ca4c0fad7e2fc7bbdf5f2356d68843c564": { - "balance": "3218227936000000000" - }, - "5a538adb2c7f6a80634b0ec20ec5152ff6bb4d5f": { - "balance": "10000000000000000000000" - }, - "5a8fe770c221072a7cba79ae7759cae0185adde7": { - "balance": "11913943233694000000000" - }, - "5aafe1efac688583d7facb09d3e569d58fb5a357": { - "balance": "4713219466825000000000" - }, - "5ab68d762750d5185138187db7751c9f71db5836": { - "balance": "500000000000000000000000" - }, - "5acab69851959dd5a6f0673ef757009ed36dfa3b": { - "balance": "974443209942000000000" - }, - "5ad9f2ab11b5e59b756404395f350aad6019d7a7": { - "balance": "54151179981663000000000" - }, - "5b1dc013ba1a28235cc70e785a00eff8808faef6": { - "balance": "516289257133000000000" - }, - "5b1eeb44ef61c7f35482503b7041162bec9b1e32": { - "balance": "125493885394000000000" - }, - "5b3db31996bca4625d22330686128ec234270206": { - "balance": "362316593128000000000" - }, - "5b401fc9ff3be7cdf5f0df870843bbef94f43285": { - "balance": "1373804724122000000000" - }, - "5b47ba296069041f25768e61be14437b8a469e81": { - "balance": "3152706392234000000000" - }, - "5b5030b5057c0457c190489c5d709d7dbdddee8f": { - "balance": "1154404278000000000" - }, - "5b5a4a782d37154a307868cd79bec9cb2a8f0161": { - "balance": "100277816425153000000000" - }, - "5b5e0b6b7cc27b06456ba4c7816ac4e89e1e26a3": { - "balance": "1023749119000000000" - }, - "5b638e4b6dfdb6928b07586e63d5879dce69a1f8": { - "balance": "1000000000000000000000000" - }, - "5b7be81d6ff5228a2b8c2913deea3f86823f1dee": { - "balance": "36000000000000000000" - }, - "5b7c4804bc2b8c72f3112b73d44b59c0711f83cf": { - "balance": "6803857604000000000" - }, - "5ba26d941544d07100744d8ffd6595a8eb7770bc": { - "balance": "583051897662000000000" - }, - "5bd58fc88733632b63d4f26893bc5c08fb60e2ad": { - "balance": "3480620567502000000000" - }, - "5bd85b5f0ecad08133fceb486c43998e537b3451": { - "balance": "484263880245000000000" - }, - "5c12639a5ab107f9e580cbd2278568dde10758d6": { - "balance": "101293252434000000000" - }, - "5c5522df05d6c6d960394c4762599e74247ab102": { - "balance": "149088856773000000000" - }, - "5c722f3ac94421f95389756af9cd97d0eaa6b696": { - "balance": "1435349483553000000000" - }, - "5c7b14ce51abf629bb0953ee4e2d9d87fc86eb4d": { - "balance": "10000000000000000000000" - }, - "5c8b215403da4e7912c1a1704a949087e091b111": { - "balance": "1440961256910000000000" - }, - "5cab313964f6730888e4158234bbd4806db0286e": { - "balance": "32284637230203000000000" - }, - "5cd736bf65c99469490d0523b10a658178cab10b": { - "balance": "99740204082000000000" - }, - "5ce91ef7ae254b2bd6d910cbf0d380814200811b": { - "balance": "50000000000000000000000" - }, - "5d15fc3a0ba8b3d87b80f9bbf972320112c644f9": { - "balance": "64000000000000000000" - }, - "5d2ccc795b19df400f21f24c0dca4d0e9e898093": { - "balance": "10000000000000000000000" - }, - "5d879b8b31af1e400cf53eb7170f82583190b96f": { - "balance": "93765337844000000000" - }, - "5d8dd54178b68bb36e1963d47d29c123864fd0ef": { - "balance": "20000000000000000000000" - }, - "5da1653bbe8353134edfff6158211ad7ee21dbef": { - "balance": "1491149937915000000000" - }, - "5da733ef41a7bdc0cf7975f83ed24604fbb4d40b": { - "balance": "10343699901151000000000" - }, - "5ddf5d7306f7c603b8d3ff993f03906dca14cd8b": { - "balance": "862558469755000000000" - }, - "5de87ec54e2160c7c2a8eff2d859414737501ae2": { - "balance": "21579321171000000000" - }, - "5df1b805b1361c1f39ca844aebe5ecee8a8d06b2": { - "balance": "411820472746000000000" - }, - "5df86b0a183b5e7f702e4da582ce9a8116a05f61": { - "balance": "256000000000000000000" - }, - "5e22359e20dc14be6930c6c1ce5a0c81c039cac7": { - "balance": "10000000000000000000" - }, - "5e2d38a06f33c784303abf2012f9af12622d9e5a": { - "balance": "10000000000000000000000" - }, - "5e479e616585e7fa84bd6f7465d394a1c0302be7": { - "balance": "10000000000000000000000" - }, - "5e4a55027a0d372f6da042b7f73720b143347d9c": { - "balance": "16175516772000000000" - }, - "5e52e86eda3e05f96e353d7e3f0ee90f08864f84": { - "balance": "21255916842000000000" - }, - "5e91c4d3a21c9dfac2c0994ed8890c78d58626d5": { - "balance": "325349462011000000000" - }, - "5ea797b18caba45d5504e57b80b12f5f5ae630aa": { - "balance": "7805696321000000000" - }, - "5eaec8815e859c34dba88cfe7b7fe28572c964ba": { - "balance": "145852682588000000000" - }, - "5eb974b5716fc4712d431bec7fbb2c49057a7b84": { - "balance": "4890681156035000000000" - }, - "5ee5f8407dedbac839f509419051106219458006": { - "balance": "3042761975468000000000" - }, - "5ef782abb28d1ca889ceb3039eef98713effbf32": { - "balance": "40915083108000000000" - }, - "5f23b88f06430c42570ac3fa33b1c7503b388a3c": { - "balance": "2376070180325000000000" - }, - "5f2b1641c0f2605b090039851aacf297e35632ef": { - "balance": "141615261000000000" - }, - "5f44cc8083340e644d19d3debc84dc14a0cbc53f": { - "balance": "291829106275000000000" - }, - "5f633f89adcc70e9da0b66611a5da108b4b221cd": { - "balance": "50835573000000000" - }, - "5f94ef8e9612b03a5c6ffcf423ada9a19a40818f": { - "balance": "102566595099430000000000" - }, - "5fae1977b76a5e899b384f572e4d94855f9cb52f": { - "balance": "773616125740000000000" - }, - "5fbd22cb3de462c794e523fd1ce36f230cc84b83": { - "balance": "1009995132839000000000" - }, - "5fd91676bc95bd6b5e69db8b9216dc83ed9dddaa": { - "balance": "1000000000000000000" - }, - "5fdda8f5271a08cf1b830faa497019d75fa9d231": { - "balance": "4149626365000000000" - }, - "5fdea351c5eccedf2394fb54437b149ae423ecf3": { - "balance": "100000000000000000000000" - }, - "5fe70ee123cb2e03c768138b2f71c1e1ea75ad17": { - "balance": "1074496282650000000000" - }, - "5fec9df797214459f85a040a559b186ee9161c88": { - "balance": "205282872821268000000000" - }, - "60037df7e4092466656a6b9571437fc4600c66e3": { - "balance": "1000000000000000000000000" - }, - "6009a0bcf531640a5a7f1664a69fe0f64b564ede": { - "balance": "50170000000000000000" - }, - "601668d8b678c95ec5ef98d9d2624decbdd52e9b": { - "balance": "23592727870000000000" - }, - "6027bafcd0ade24fda8c345dcbc812d59df74bf7": { - "balance": "10000000000000000000000" - }, - "6029514f24825c1fadc68cf8614951de5d53268f": { - "balance": "1389262963614000000000" - }, - "606de6db14272a314d778cf0e67913b7fabea45c": { - "balance": "144000000000000000000" - }, - "6074f20675f975ae2c081930cae8f299710f0bba": { - "balance": "10000000000000000000000" - }, - "60850fa9e09d414af3690e4b5daefb1b906b0d20": { - "balance": "10000000000000000000000" - }, - "60ad0b6239dda5df7ac0f0ca941684cf20ae0fd8": { - "balance": "81000000000000000000" - }, - "60d6136e6db631be45fefb9667c3dfa69e9d6054": { - "balance": "651902184266000000000" - }, - "60d733dedec6886908520ba57cab8c9d5c2d7f7a": { - "balance": "555461746642000000000" - }, - "61202238aea4010d115c5c64322ad790576cee43": { - "balance": "10465801848035000000000" - }, - "6142d92b61111657de4b2d65698a3621411e3adc": { - "balance": "100000000000000000000" - }, - "61879bc1a022d9cac8b7d57c8f528065beb10bb2": { - "balance": "72766025231000000000" - }, - "618b15c9a60ad89e7fc28afc79bbf7f28d4998cf": { - "balance": "444855210015000000000" - }, - "61c1169e8ba43ee6b919e5be2eac19542eb913b4": { - "balance": "500000000000000000000000" - }, - "61f1cd6efce17f5458325f022f363fd9772d8f20": { - "balance": "19704989598372000000000" - }, - "61f7d39211a0af2e226d8cbc95fb673168653b0a": { - "balance": "484884476279000000000" - }, - "621aa67f09e6506efb2fd141f080fb1d96693a57": { - "balance": "1694451603196000000000" - }, - "62332fa5127b98bd2a627a0ac22d3a1bdb418efd": { - "balance": "926882233406000000000" - }, - "624a465696ad409586a2e67d84750ba50a971fee": { - "balance": "25000000000000000000" - }, - "624d866f0d61bdefc3ec2210bfe36b6d51018f9c": { - "balance": "199592183194000000000" - }, - "6255d6d3b49443891661b209056d530ecd63bcca": { - "balance": "10000000000000000000000" - }, - "626c484055e6739d46e2ff25190c8b3a4af3fe0f": { - "balance": "1485276462321000000000" - }, - "62865e637d723393ab9654d6439db7fb5abf8803": { - "balance": "10000000000000000000000" - }, - "628a47761d5ce755de88444aaf6d7736b911672f": { - "balance": "18625552918216000000000" - }, - "62df6a38e8b15a1c4f4a7aa7c1736c612f54a0e4": { - "balance": "16468111299582000000000" - }, - "631d7916ddbb5f7c469f8ba07cd48e377560319d": { - "balance": "2493487426430000000000" - }, - "632754f5afcae7dc36d9286cfcd91c14abf0f7bd": { - "balance": "1424933496931000000000" - }, - "635788343997ea9f145c508b0cd2ed36e180f46d": { - "balance": "143040938538000000000" - }, - "636973e7dbda9e3042a8c03e25696d0faf27f025": { - "balance": "5491869128148000000000" - }, - "63707efa26d34d7ceadf4e6439324e7bde0ebc3f": { - "balance": "1000000000000000000" - }, - "637d92494f7872d397340c9b5183dce354c8c43b": { - "balance": "724687404033000000000" - }, - "63b9c2e6762a431752f7669b8bbedae9f37120b3": { - "balance": "1360967549741000000000" - }, - "63bd281d8c4d1279519237a2b68f2a73c228f7e1": { - "balance": "217457311664000000000" - }, - "63c0eb8c9a0019e36ec9a731b4bd947271a5bed0": { - "balance": "36693488147419103230" - }, - "63c6362eff56de328a29b7e9d32ced28f3602b6b": { - "balance": "148335309448000000000" - }, - "63c979c787a7b037693cadfeda738ae33178c009": { - "balance": "81000000000000000000" - }, - "63d4621d91906215d32f6fbcee1ac48bd773f630": { - "balance": "1006939236069000000000" - }, - "63ff99fec1cbd2f6e83c0e6de3c0ea4b7c7e1398": { - "balance": "1201300688980000000000" - }, - "640ffd856e48528b05d5ef1e60348048ce291960": { - "balance": "20000000000000000000000" - }, - "641c25f7c380e2745c81a268384a029b2e2be0cf": { - "balance": "635133477665000000000" - }, - "6427792a164bbeab45f6c3acf17c76f721b90e81": { - "balance": "10000000000000000000000" - }, - "6437986b4c545af9c4a5ee96371a5807275e9221": { - "balance": "2951152516627000000000" - }, - "64460d09d1bc5c425d62bef5969eb0c5916963c3": { - "balance": "1680000000000000000" - }, - "646381f92216b97abbd86ca100a773eebdf7545b": { - "balance": "211234535515000000000" - }, - "649f73d1cafeb3ab0631432f04c9d08b9f438c22": { - "balance": "248900746448000000000" - }, - "64a239be45a92df83bb85b25f8ed7de5d82313b9": { - "balance": "100000000000000000000000" - }, - "64a3d97f82e3d42eea78bbcee31a95d33767b055": { - "balance": "2511466286000000000" - }, - "64ad579975888f455217e0f801e371900d9814c9": { - "balance": "7118859416319000000000" - }, - "64af5edbfec8adea679951662c08a781175688bb": { - "balance": "822966999709000000000" - }, - "64b7f2c22c20a59c07cb0dd7f8f692153c68f3f8": { - "balance": "20000000000000000000000" - }, - "64bc17e28d468b7b8368ee8a8375710d21c3ac5d": { - "balance": "875002262415000000000" - }, - "64d17aa662e56061cebb3c2e2421e637163e8dd3": { - "balance": "363241251465000000000" - }, - "64d714ec3145308e8f939bab7591b0773038b886": { - "balance": "338231954012000000000" - }, - "65199fc9ba95434382c108b44ac553534a9a3670": { - "balance": "2537340957145000000000" - }, - "6527c67c29e47833dc2440570596023318a7bd99": { - "balance": "555434226832000000000" - }, - "654b9d299077c90768c5ca6635e5802e8099f51a": { - "balance": "119004827465000000000" - }, - "655908513607cc38de35351ff3738b201bbf39d4": { - "balance": "652902936029000000000" - }, - "656ad16063b2d397788c231e537384ece94eb0d2": { - "balance": "63116382606000000000" - }, - "656e622970b8829a7cfe24f5b82696c7777683ba": { - "balance": "20390269890405000000000" - }, - "6583a6ff4dfcf447e3b163a61b0d5cb84ceee375": { - "balance": "3858529344000000000" - }, - "658d2b7e8a6517256efafd74321757d5c384a2b9": { - "balance": "221114751567000000000" - }, - "65920758857ee5b27b0f31487ccc3c5d6986df3a": { - "balance": "16272975796000000000" - }, - "659d60d67a07774ecc5cfea9e56809bec024d639": { - "balance": "20000000000000000000000" - }, - "65a1a3f968bab5fc1f097b8e297099a3d34ef45a": { - "balance": "16000000000000000000" - }, - "65b5e3163d20b2a6fc75c0219b7f97d83479a26d": { - "balance": "1716459529041000000000" - }, - "65c9bc3b8b0ce7c4d16b35abe1a5c285a59f672e": { - "balance": "20000000000000000000000" - }, - "65d5b458d9b1a9659c1125d20d970d5e6c29dc3e": { - "balance": "20000000000000000000000" - }, - "65e75bb8ade25eb7975ea12b9afdb17ac21063b3": { - "balance": "2270407774714000000000" - }, - "65ed78d0c4ef1150e8765b24b210f056e079cd59": { - "balance": "500000000000000000000000" - }, - "664ee5e334b8378928becfbf5d5e51daaf001125": { - "balance": "860160259186000000000" - }, - "6679bdb26adc179d046607d49f4b10c65d8a40d1": { - "balance": "436794739763000000000" - }, - "6680fe9d6eda3ab9fc4ac1ac933339b533eb682b": { - "balance": "551296206326000000000" - }, - "66a1249501cc5076b040bbb165ce032ace216ea2": { - "balance": "36000000000000000000" - }, - "66a475d014c2f976704bfb93ce78dbabbfc5e072": { - "balance": "1140135640169000000000" - }, - "66ae43d92e8fb2231fee8c72d720ff90cdd267ff": { - "balance": "796696150339000000000" - }, - "66b7e0c810d6959afa8210f6ca67e3e40bd24eb9": { - "balance": "16000000000000000000" - }, - "66bf8be16f33b111b2a425743bb7ebcdfbb35034": { - "balance": "538590591000000000" - }, - "66d2eaf7fe10900d93eab17823ebfde5486aa2b7": { - "balance": "121000000000000000000" - }, - "66e525bb01b3ede1a4a105bb6087ec8a76200616": { - "balance": "1506610219207000000000" - }, - "67291e0df83d6e9f1386e87a1792d7d147341df9": { - "balance": "272330177662000000000" - }, - "6730b27b62e064b9d63df3bcbb8c4bbb0e500afe": { - "balance": "331282968154000000000" - }, - "67318617bfe19b739fac9a126fd129223db52498": { - "balance": "12699924981000000000" - }, - "674dd0b036c91f3a83288af44897b4ceb2e15a12": { - "balance": "4352791270187000000000" - }, - "6751bffd04be55c86692994fed06694cb78b62ff": { - "balance": "26049487516000000000" - }, - "6768d99a0cdcd7bb7c7d0aeee466d6bdc7208bbc": { - "balance": "309909685000000000000" - }, - "677ba2de3e5c68a4c354c9e3129ed1c41025312b": { - "balance": "127426274611000000000" - }, - "67b83745856551f1878027843be20e1473191944": { - "balance": "185757248875000000000" - }, - "68170edcfaf2c6df4e6542b2856ad33e9e2d6623": { - "balance": "4003453949471000000000" - }, - "684ae403d9a08e4f4f971cfedf81094074daa77f": { - "balance": "25139713925794000000000" - }, - "684f3b8a749c002aa434bad6af7a3e2579c69315": { - "balance": "16000000000000000000" - }, - "68538a9e8246be5a5c5ea315cb325344062cf8c4": { - "balance": "14009193210480000000000" - }, - "68935ff3a3a3b6ef16ae7df58cee50b157658dd2": { - "balance": "20000000000000000000000" - }, - "689f508256ea64f5dbd6bb77f1ce1bdaf36d7152": { - "balance": "10000000000000000000000" - }, - "68a3e6e7c191a8c1add988bfbbb9b51d4f36f521": { - "balance": "10000000000000000000000" - }, - "68a74ff2a5577321f854b56d3834a55d3c41bd94": { - "balance": "88873831171000000000" - }, - "68e6da521bde13cf4e4f423a78fda2f69b3d1c2a": { - "balance": "538392460838000000000" - }, - "68ecd5cf8cf8d9704fafc36d8da53930afeb0553": { - "balance": "1090923641219767000000000" - }, - "68fd0b8e000bd2788be6cb10fc0496fe2cbe155d": { - "balance": "32853847745000000000" - }, - "6904045feb5ef94e096894b863d314ff8a0f206b": { - "balance": "9892165615000000000" - }, - "690fbae5153849bb20797af7b8dea66a728a06c3": { - "balance": "6082107223716000000000" - }, - "693d909842877d017e0f102e37a55024517dd0ae": { - "balance": "20000000000000000000000" - }, - "694cd00fac9cded484ef2cfcd44faf161354f288": { - "balance": "3049716150137000000000" - }, - "6964c3c2c7bc719ec94a51bc4bf412e137d2b4e9": { - "balance": "1000000000000000000000000" - }, - "69a5c692516940bebad8efaa2243a8fbdf2ade62": { - "balance": "2803346939929000000000" - }, - "69f566c44802b0140f5e1c9234f46006773c03d4": { - "balance": "20000000000000000000000" - }, - "6a17eef3a6bd407260f52067592226448182cdc3": { - "balance": "1116509364305000000000" - }, - "6a200e99a0f50aab32fa7373c7880817c81f472a": { - "balance": "1836680122795000000000" - }, - "6a2a29f5f441876816dd17856051040787f48a64": { - "balance": "1131603204000000000" - }, - "6a3f855c7dceb75d0de7fa18fbc2f40c81b76756": { - "balance": "32267494586000000000" - }, - "6a46af653b938643e781cc4a0edcf5357852fd21": { - "balance": "1140718780752000000000" - }, - "6a4b2e5b45da0d70621ce71f165a11078a1745e2": { - "balance": "3768326643000000000" - }, - "6a530c813595a5b7776cced05a865dedcb110d94": { - "balance": "270559347097000000000" - }, - "6a6e3e82f98ce891f47721770301dbe2652a9e25": { - "balance": "10000000000000000000000" - }, - "6a828d6f2f7f68bde4a12608024020e593540010": { - "balance": "7531817000000000" - }, - "6aaddd1f4ff6b4d414c87271619b826ead27f09f": { - "balance": "64000000000000000000" - }, - "6ae6bce1e2865ade0d02eff9899ea3767b5511cd": { - "balance": "6893781798524000000000" - }, - "6b04e7c6a837d218fd3322b87a267fdd979358ef": { - "balance": "302679180175000000000" - }, - "6b2210b8536803b134e69c5046904acafef48cdd": { - "balance": "47823456459000000000" - }, - "6b2da6f36c2e7f61cabd7580480065360c995c93": { - "balance": "55000000000000000000000000" - }, - "6b3401986f2be7ae5a4ec160b8f96b2a651fce73": { - "balance": "16000000000000000000" - }, - "6b3847774e99dec307dcf5bf5adba49df4a9f145": { - "balance": "43276069579000000000" - }, - "6b57f2d9d95cac67fd2f70c0911d48c7f09de072": { - "balance": "1000000000000000000" - }, - "6b65d736a8ca89ec8508b52e4aca5166f9703732": { - "balance": "766421968820000000000" - }, - "6bcc55d897829e98fc3f3ac8beb331e59c33b942": { - "balance": "318115956882000000000" - }, - "6bd76e7af1775b88743d5f53ede0ce846d3d7ced": { - "balance": "139548017482371000000000" - }, - "6bd7cca99acf6eed5842417c2327c642df5473fd": { - "balance": "3321731000000000" - }, - "6bf72c4d39d6700181954a8d386c3df216634412": { - "balance": "12742769034078000000000" - }, - "6bfd3aedeac7c6ec086c0a4ec29d2d0f5bd69bc5": { - "balance": "50000000000000000000000" - }, - "6c025962810a6fb8374af5e07d7fcd631d10b1ce": { - "balance": "674126722005000000000" - }, - "6c1b72df836f410038af9e020fa2ff2ead398ef4": { - "balance": "1851293017364000000000" - }, - "6c1fddb4254ff46b3750de322ebb7d6238c0a606": { - "balance": "9977629348276000000000" - }, - "6c37069a361c5c72355bb5a56879dd0a9735a237": { - "balance": "1062230154063000000000" - }, - "6cb166eeca248a234c971b2a864a7b3fdbe5a737": { - "balance": "390222992865000000000" - }, - "6cb797289059cadcfa77eab0365e6bf1ae12df46": { - "balance": "100000000000000000000" - }, - "6cc787e6bb4f484828b080330667b93953e7a3c9": { - "balance": "16106440380234000000000" - }, - "6cdf7b334fb2ef8115198d475d431eeb7d88df77": { - "balance": "1940904395351000000000" - }, - "6ced85b035b787e9e427d0904aaf96e011417310": { - "balance": "103417697874000000000" - }, - "6d6e09acc07f388cbab99e53959f75e9ad8f07bc": { - "balance": "1305917678000000000" - }, - "6da91b02f512f412d374392247a9aaa853e9dd59": { - "balance": "2300525907893000000000" - }, - "6de5d70481cd40db468f64227228cdd362ad9980": { - "balance": "10447389944082000000000" - }, - "6dea87255c9ebfa63f017209046e894ecbbc03b7": { - "balance": "1527216854064000000000" - }, - "6df6f6b9953c2f2a8ce5985e19dd6835ae2c566c": { - "balance": "6539856530000000000" - }, - "6e013c83cac111a38fbbf8d47778fda0d3af25d5": { - "balance": "12139181929380000000000" - }, - "6e18a484f402fd433a5ac4dee5a4b8bf6f22db47": { - "balance": "23215906572368000000000" - }, - "6e4fd058e4dcd502c2015f83f3677f680ec58110": { - "balance": "480059342014000000000" - }, - "6e501ac7357fc758caf5dff6c29a995c806a1a7f": { - "balance": "1573491311733000000000" - }, - "6e6912f9fc21dfba736055e6ccef074dd62dcc59": { - "balance": "256000000000000000000" - }, - "6e869c68511c1458f4fbed9a4c5296fe961eb47e": { - "balance": "68488423994541000000000" - }, - "6ea6827b377b3d3ecf7c7628ed8daad7fd8eab1e": { - "balance": "188825714738000000000" - }, - "6eb9237738339fcaad3763466509f23efd0c5054": { - "balance": "48417242786000000000" - }, - "6eb92a61390f9d9ecdac80a8833aa801c3926b13": { - "balance": "1412936326723000000000" - }, - "6ecb93f18153ef2d2a552286ea3b7436f1f8168c": { - "balance": "20272577229669000000000" - }, - "6ee087c04cf16f4768c783a548686448fd125914": { - "balance": "1397039628538000000000" - }, - "6efbae7a34c71233329d0bb4cbec45274824ebf4": { - "balance": "8910000000000000000" - }, - "6efcd6776f287c25a6eb3cf71018adc282eeab6d": { - "balance": "1310659853178000000000" - }, - "6f9ca805ddaaea5205e85778dedb2eff4a5aaa75": { - "balance": "2585733757016000000000" - }, - "6fbbea927469f4d18942ce0aade164828fe23a2a": { - "balance": "4671857880000000000" - }, - "6fbe9df6c42151c453502960d99170445dd3ac0a": { - "balance": "20060296562115000000000" - }, - "6fed121fb310431f1659e637f35f4c878a7256c7": { - "balance": "55170085399000000000" - }, - "6ff2dd5373bd72966ef48d3183c60d74a6549cb9": { - "balance": "24103445361000000000" - }, - "703a490c4783776da244384c964897491aed3711": { - "balance": "2001677632732000000000" - }, - "704dcd2d9f75f0bbfb73f2fe58bcbf4508374381": { - "balance": "439603954369000000000" - }, - "70859a14f33b8ab873fa5781a4af1ce40dff65c0": { - "balance": "10000000000000000000000" - }, - "70b9cdfa5f6d41c60e1c0d3f544f569c9b340ea2": { - "balance": "198355566698000000000" - }, - "70d0ee793e28e320b34267ef2df69050fca0a9e0": { - "balance": "8010660534227000000000" - }, - "70dc7e5951752c22a0e3c50e8e7b1f7af4971d51": { - "balance": "3991137321749000000000" - }, - "71057f5afbed7d82c92d50790e3797fd7395d036": { - "balance": "49000000000000000000" - }, - "7109a3b3d5d6af49693549728691099d696ce016": { - "balance": "4119694297000000000" - }, - "712231a5161745fa1b33c7b0f6e8c767e1de4f81": { - "balance": "1353809351914000000000" - }, - "712aa38999c0be211654e5c84f59e3b2e018f597": { - "balance": "160199774000000000000" - }, - "713229fc94a86b71a5bd1ea6498b9373e3f3c549": { - "balance": "98289185940000000000" - }, - "715de29a0b6f467b94d4a90dc767ad52d0fb3b9e": { - "balance": "948824982990000000000" - }, - "71776853ac97ce04b008c9a7b64156a3cafc52a4": { - "balance": "608309596513759000000000" - }, - "7189f6dcfe64e1ddbfb5e51fd5f3174bc636dd0e": { - "balance": "5674608906899000000000" - }, - "718a4da87464caf6e83ca374d5ef9255b8f7cc3e": { - "balance": "761891873568000000000" - }, - "71bc447761cdb68915cc2288b4929fdc0adce02d": { - "balance": "10000000000000000000" - }, - "71d78531896642069b725bf82fc385789c63217c": { - "balance": "33103960195000000000" - }, - "71e328deeafbb1724051d1062609c43eef56ecdf": { - "balance": "493550967964000000000" - }, - "71ed0310fb51b86a61794aea17a3c792dd301e3c": { - "balance": "3234918634449000000000" - }, - "71fa264f58041e41cfe36e8f8d4e0cb22ab71925": { - "balance": "5558941960000000000" - }, - "72059c57d0fc05bc02ba54ebea6cefd1efbeadf1": { - "balance": "4458278271443000000000" - }, - "720847a28916a532bcab33e1fcbde5d1c4d820bc": { - "balance": "1392418942284000000000" - }, - "723cd2b5b836b0ee8481d37b9c51b5f3f1beddd2": { - "balance": "1856420455522000000000" - }, - "72430c6664d23c7051b0e99912fa54dfadcfdeff": { - "balance": "102078926010505000000000" - }, - "72652c4320dda25348f15c0ecfeb4b3b3ceeb7c8": { - "balance": "307639955659000000000" - }, - "7288bd1b9f4c068dd5df9bcd6fec1ccecd240195": { - "balance": "80161087899000000000" - }, - "7299cb8a288abe8e1a22c11b53a903acb7db5827": { - "balance": "752198565719000000000" - }, - "72f6bc0c3ae437756c099e02e9c084febedc5569": { - "balance": "696294297587000000000" - }, - "730e5907b344c80e0a6115723a90a23e3635192f": { - "balance": "6056082041729000000000" - }, - "732e97b992e4f8a53034cf29cf11aacba7452261": { - "balance": "100000000000000000000000" - }, - "7339df65ce293b3d501647a04c83819099f0bd38": { - "balance": "706500983417000000000" - }, - "73482f8135ca2231db5e0e034a235a9d244a8656": { - "balance": "1143989148865000000000" - }, - "73769e43058d30a530048e5a2bea7e9333534e93": { - "balance": "113542901996000000000" - }, - "73bb9e6f1709fbb7964df7b3cc0f9170c3152f38": { - "balance": "1639793026701000000000" - }, - "73e261da7978764044ee916f88bf66680952607f": { - "balance": "100000000000000000000" - }, - "740154120c4f41c50b0aaa0636a2000ff1e870ad": { - "balance": "10000000000000000000000" - }, - "741fe2a1537284b70e97e3ff659eedfd7fc5b1b6": { - "balance": "75911502037000000000" - }, - "7420bb277d834763e4429db9bf37f053f71ab769": { - "balance": "3100160195046000000000" - }, - "74281371c3b569c774da6bab686e7d7a45d4dc4c": { - "balance": "25666397941223000000000" - }, - "7428d261b5418652c5ab248d6abc3d2af25d904a": { - "balance": "56252809397000000000" - }, - "742c876433297f5a8fd4a25f75ee9a607726bd3c": { - "balance": "4132793019677000000000" - }, - "74302036cf52e11aa3f32a371bb4992e2bdc3f39": { - "balance": "19557661364000000000" - }, - "7445c657c24d014f3a9dddc3e446868bc2dbd13e": { - "balance": "10000000000000000000000" - }, - "744b8fa69d2542be3557267edaeaf2cfa8a9e991": { - "balance": "16000000000000000000" - }, - "74728999963524e7cc1736abcb4deac630142c44": { - "balance": "37000250991000000000" - }, - "74926cbdacd0e871cad0d926c8e17cb2c00475b9": { - "balance": "20000000000000000000000" - }, - "749e115a9e675bb15af5e1c04f81fede07c40120": { - "balance": "440913547154000000000" - }, - "74b7e01acf825898544d6c1b61e53356be759c56": { - "balance": "25000000000000000000" - }, - "74c5fcf875e2e9b726a7cf6e176dc2f7eb84c200": { - "balance": "59208835472000000000" - }, - "74f44579859e4a7944dda7bd810088e116ae9910": { - "balance": "1038454108527000000000" - }, - "750b1e2955ba05c1fc8a1f9dbb1624ed11587edd": { - "balance": "9545712605000000000" - }, - "75375129cff2a051f656b91f868325c3b35ee1ae": { - "balance": "25000000000000000000" - }, - "753ca28fbd89081382a996fe938da7e6c3ae6cfd": { - "balance": "156582454263000000000" - }, - "753d91c04e554680cc32a97c1abc96280e8263ee": { - "balance": "725101425969000000000" - }, - "754e5b5d64c267e83fd4804d112725531cf5abe9": { - "balance": "83276113115000000000" - }, - "7588a96a2bc65569a6c124c4a4acc55863a8ab78": { - "balance": "24062602342000000000" - }, - "759075dc3a6b9d2499a74bc57e346c9ed7ff834e": { - "balance": "225000000000000000000" - }, - "7591d6fa043801fe12462e11d9e33a53f438c073": { - "balance": "1863874274000000000" - }, - "75bda5bdf6aa749bbd62b6107941a7dd9ce3880a": { - "balance": "36000000000000000000" - }, - "75c2d3a99f144c4b9962b49be9d0a81b203906e8": { - "balance": "9000000000000000000" - }, - "75f587a69a97eb4d1c4c4078418d5fa85dff6f94": { - "balance": "10000000000000000000000" - }, - "75f67649605f49d98d866102ea2d6881ead9bea0": { - "balance": "814929108418000000000" - }, - "7602abce0f510b6ca471fd8d734e21a2591886f6": { - "balance": "50000000001006000000000" - }, - "7629b788160531b0be28bf445bf305fbe2c514d2": { - "balance": "23022256366212000000000" - }, - "762aed2e3aa2293e69dc2110b1fc6c806ae799a5": { - "balance": "10000000000000000000000" - }, - "7637b89130bc3f87e90c618fd02d6dd27179101d": { - "balance": "77765738300000000000" - }, - "765136022facade53e7a95c0c7aa510787e674d5": { - "balance": "1478178932688000000000" - }, - "765274015a308a9e6b1f264e5bac592d267f2f7b": { - "balance": "3058788819393000000000" - }, - "765cbc0a89fd727a2c1a6b055139faee53f11330": { - "balance": "500000000000000000000000" - }, - "768bb6d4b190c18a0946d92073ee446d68d98a6f": { - "balance": "144000000000000000000" - }, - "76ae8079894c760f2850c02cf5a0d7bb41e5864d": { - "balance": "156059816821000000000" - }, - "76af4103a231b1302d314c486a0ba524d0427899": { - "balance": "10000000000000000000000" - }, - "76b6394cd02ddf761e981b6a6ce1654c0e575443": { - "balance": "1078304803757000000000" - }, - "76db33eafeaf965dcf15d5460b64a48b37285259": { - "balance": "1000000000000000000" - }, - "76e5721c0a39d41274f84cb572039967a07e9beb": { - "balance": "156298167226000000000" - }, - "76e6ca6ef145d2711ab27f82376a065cc6f62a29": { - "balance": "100000000000000000" - }, - "7705d637cf9f6ceaa452deaca7ccc581beb5fa34": { - "balance": "36254762908065000000000" - }, - "7706c80af4eb372e168501eedfe7bda6dc942243": { - "balance": "50000000000000000000000" - }, - "771493da92c9fc6c6b39a4071ae70d99f6a588d3": { - "balance": "2000677471360000000000" - }, - "7719206286f26144c0f20b5e1c35cf4495271152": { - "balance": "1380480863056000000000" - }, - "771adcba1409fa2df6db19d9f784abc81a7bbf36": { - "balance": "15416381820915000000000" - }, - "772f7baa80a852e05b2fb3903a36061da132b2d8": { - "balance": "121000000000000000000" - }, - "7731a4175eee5077e2ede48878e6e2a18fce0f9e": { - "balance": "10000000000000000000000" - }, - "77385deeba01e3cd7a63e13d6048011020f56724": { - "balance": "57204247488000000000" - }, - "776808e7688432755b9e91a838410d29e532c624": { - "balance": "120318608715941000000000" - }, - "776d1b406f63082b80e250c4a0073fa0d83b9090": { - "balance": "243779839900000000000" - }, - "779848a59036ee3cd23b93ff6d53620d874f0bee": { - "balance": "82228810849000000000" - }, - "77d02a031274bd4ed2a16f3cc29d94e755142036": { - "balance": "408567696646000000000" - }, - "77d609a407aa0d126d58090b8d635f5ab7a02d6d": { - "balance": "776754055755000000000" - }, - "77dec41e116301dbd6e542f139816bfd9bf6d154": { - "balance": "16335989583000000000" - }, - "780398b42f81167731a8ef6a8bd1d14942b83267": { - "balance": "25000000000000000000" - }, - "780a645d59027e7b0670d9565898dc00704cbe5f": { - "balance": "20000000000000000000000" - }, - "78182a7711c773f306ec42ce6da3e983cd49b00b": { - "balance": "580861257254000000000" - }, - "7822622f07fec12995c4bb8eb32d62aa7f00be05": { - "balance": "5018461926846000000000" - }, - "786410c679101c0ebf06fb4f36102368121f3c8b": { - "balance": "16098386724761000000000" - }, - "787d5476038ab0a09b846645285ada23ffd7318c": { - "balance": "492047430907000000000" - }, - "788e9e27ed979d1e7aefadda798f69df1de1d1bd": { - "balance": "30965301214000000000" - }, - "78ab2d2dfaf5d2580ed89c970e771572bc91d3be": { - "balance": "36000000000000000000" - }, - "78ab7ac6f379ff084a7acf4a1a31fe2e5a6834c0": { - "balance": "107332516726000000000" - }, - "78aba95da37385c736ef93d0ca8318baf6c5ff3e": { - "balance": "9000000000000000000" - }, - "78cecbd82229dc91a530bd555c9e45125e2a6bc7": { - "balance": "28474069251604000000000" - }, - "78d4df90990248f3ac67e492a0a1e3f4ee455507": { - "balance": "10000000000000000000" - }, - "78f6de3768abc604c49b10d798e0656948cd334e": { - "balance": "9000000000000000000" - }, - "7909aca95ed899743de222e56c231f9bed1b518a": { - "balance": "5355599376491000000000" - }, - "79193e660b4431e8aca9c821b7daa88064e33750": { - "balance": "100000000000000000000000" - }, - "792487caa23b0d9b9998002810cf29439f7190bb": { - "balance": "4828579961131000000000" - }, - "793f56adea51063243a9633ecc1d1e620a91f327": { - "balance": "926742377449000000000" - }, - "796d187077c1d7591583436ae64d10a641490ca5": { - "balance": "242664407084091000000000" - }, - "79a6b7fad3b5a655679450ca82818ec2d6f58688": { - "balance": "1400472715109000000000" - }, - "79acf627e67cedf48297c26fd135973bff6c57da": { - "balance": "444598475759000000000" - }, - "79ae0dda1964ff0191b98d28c9b52a79dc9ab078": { - "balance": "325908985422000000000" - }, - "79e71dcc52fa1b28226c519f715faa3cf63cfb09": { - "balance": "497898493594000000000" - }, - "79e98193ff8770f26af824734bbb1c2ce8197b6f": { - "balance": "10000000000000000000000" - }, - "79ff3d790d52c58b7317a415278e9058915d5241": { - "balance": "48502649691864000000000" - }, - "7a0b02d16d26e8f31e57106bbdad308f513d436c": { - "balance": "841000000000000000000" - }, - "7a1d422352ec7e6ca46131728e4b71f20ed84e2f": { - "balance": "50496873413000000000" - }, - "7a2a3fbe27e33df867ba8800788995d7662c046b": { - "balance": "100000000000000000000000" - }, - "7a629c4783079cd55633661d2b02e6706b45cf8e": { - "balance": "50000000000000000000000" - }, - "7a62d8875f53e54b775ee2f67f7e2ec137bf724f": { - "balance": "25000000000000000000" - }, - "7a67285fd883d36ea3107aa3fe7727c68a99eb2d": { - "balance": "254787158217000000000" - }, - "7a90fbec48492473d54b0fad128ceda94ea66100": { - "balance": "313715004199000000000" - }, - "7a9e11463d84a08140d698972e32e66bacf7a7c9": { - "balance": "3602603216258000000000" - }, - "7ac4f33e1b93ef0f9c15014e06da24904ef4419e": { - "balance": "101000000000000000" - }, - "7ae082ad247275fd5a9e77b127cee5693784e9e1": { - "balance": "1921957343533000000000" - }, - "7b27e070ca4158d13f8333b34842d4c28b678c92": { - "balance": "10000000000000000000000" - }, - "7b2e34374921e4dc10fd9cfc670a40f5d092da1b": { - "balance": "2098457950503000000000" - }, - "7b54c6c8041c8b09240de1ff06e0d3d2d8d877e0": { - "balance": "944752036841000000000" - }, - "7b5aecb798d8f4f5a04bdaef909e09a35bde8d47": { - "balance": "21975115049000000000" - }, - "7b88a7ef9201966bd1ca634779c3b7f40c22f0d7": { - "balance": "64344833519732000000000" - }, - "7b8c22ddc5c7e59e571587d7c776fa50e65f4845": { - "balance": "225108110445000000000" - }, - "7bb4d8a169f72432494ac362eeab005ce1e02d81": { - "balance": "2098993419448000000000" - }, - "7bbaaa6690698e749d095447bdd27207c0caee43": { - "balance": "490069993631000000000" - }, - "7bbf27f92f9f726381d4f68b21ed86af8f792d04": { - "balance": "806346082666000000000" - }, - "7bc6f172fd78953c3456c571ac8394756715d5fd": { - "balance": "81000000000000000000" - }, - "7bcca29b477730ee8f219a5d1bca24415c7a4625": { - "balance": "36273885000000000000" - }, - "7bd296e1cb29ad87ed28b0ed18440ee686b157e0": { - "balance": "35964679698000000000" - }, - "7bde6d49a1af34a5a9dac0b9007e9a5583c65ebd": { - "balance": "1041474566346000000000" - }, - "7bea6240f245e649563253fa4c1da39b12625da7": { - "balance": "100000000000000000000" - }, - "7bf096396c56f27f9c39c4056ee6cfcb0db44bc6": { - "balance": "407261849111000000000" - }, - "7c3b58d3ba283bd9b1580832e9d014eff48bff7f": { - "balance": "7074518779349000000000" - }, - "7c5a56c45f23c353ff9f6f71ec86c9a6a1a0ca67": { - "balance": "11277879639596900000000" - }, - "7c783ac9b07bc6576835635f37e7e3c137055c8c": { - "balance": "16253676225000000000" - }, - "7ca2fbc0a0d1370e95048a21a300eac4d6056df3": { - "balance": "2772084065617000000000" - }, - "7cbe95802a20eb765f9fcff0a068859cc35d2660": { - "balance": "255153842674000000000" - }, - "7d004fb3a6a81c00fd2872e8079ad2912841b0e0": { - "balance": "642630220843000000000" - }, - "7d30c788d4ea18849ebae1173373c8915ffd7a35": { - "balance": "61062263242000000000" - }, - "7d39324f5ff62e849b0f0f46ab8ee396fbd85581": { - "balance": "100000000000000000000000" - }, - "7db0ce6c04537417dca1dd3415a5bf213edc2028": { - "balance": "30393443462000000000" - }, - "7dcfaa795586c92f1ce7d5c7b10608fe6a773fe4": { - "balance": "183173395920000000000" - }, - "7ddd111cfdc3133f59b82568e3deefc3cf10b0d0": { - "balance": "5622149283840000000000" - }, - "7de81daaa7ed5cbf4d379cdd26ae353cbd5a2489": { - "balance": "10000000000000000000000" - }, - "7e0a11af993a41626c5564f719442c0dfd608ec5": { - "balance": "1532083534600000000000" - }, - "7e34971b187047e7f7980650630b936eedc11023": { - "balance": "10000000000000000000000" - }, - "7e5214e16851b33c4a4d29e5a06929461d3d9555": { - "balance": "371790231197000000000" - }, - "7e52ae9c7e4b888015a3a5af7a91444510aa18e2": { - "balance": "109879329128000000000" - }, - "7e69b383671f96b7abc2d1fed8b61477b87a58dd": { - "balance": "10000000000000000000000" - }, - "7e733b1fcadc9a20dc038fba74e236af0b5a39b3": { - "balance": "43583614302000000000" - }, - "7eadcf955c90040668fb0f75a61f687e4e41f314": { - "balance": "332201682206000000000" - }, - "7eb51f3ead1dd0f5384c199ad5518ec55f77d35c": { - "balance": "38487884822000000000" - }, - "7ee73c0d64caf46f47f439969060092ecafdecd9": { - "balance": "15063618320000000000" - }, - "7ee8e4c6742a4c6d8efbfacc4d56119bc6c74ea4": { - "balance": "31882319329000000000" - }, - "7f16d981521c06347db8324da38b25eab3cee23c": { - "balance": "400000000000000" - }, - "7f6ff7db81a26fe78dd80636f0b178c669344393": { - "balance": "10000000000000000" - }, - "7f792b094c0b96d6819823cf21bc0c402fc27bf9": { - "balance": "50000000000000000000000" - }, - "7f84ae97c21cc45a7e56603ddf97449d803fb246": { - "balance": "81000000000000000000" - }, - "7f89c2b9daba034841f19ae843cfb6cd6f75b1d7": { - "balance": "20000000000000000000000" - }, - "7fb18f8b0e1fd1ed8c863a66226082bdc0429ee6": { - "balance": "11465417544634000000000" - }, - "7fb4e30579c64efe981d0057204e5bd8770a1f87": { - "balance": "249801873762000000000" - }, - "7fcc4de10e837d98691acc52732e1568c890304a": { - "balance": "1000000000000000000" - }, - "7fcc77798cd50345b2784a78b81a25dd4c1e64ab": { - "balance": "2676882485895000000000" - }, - "7fe33e773a02b995278ff595d55a0741813b19d4": { - "balance": "5788279057355000000000" - }, - "7ff32b13d531ceef500ca6c6806ffc0773639264": { - "balance": "1000000000000000" - }, - "801380158ef8f24316bdceaa00eb89c3d886707e": { - "balance": "35627521347898000000000" - }, - "804fdccdc8603858d15dec88666437505b2a106a": { - "balance": "14607090269617000000000" - }, - "807915567eed99bb9146354a32409812b9490d70": { - "balance": "1083142734057000000000" - }, - "8092ceeb2be5b271f4c156d85fe14977e919c7e0": { - "balance": "761607160308000000000" - }, - "80962bf961d0d713395dbe00379a6e207b425a76": { - "balance": "524215754483000000000" - }, - "80a9787124075c8cd44b9c8674967a54445e2354": { - "balance": "7600078997429000000000" - }, - "80aacd59dd76bf443c47ca02976178af8453f23a": { - "balance": "411856023767000000000" - }, - "80db788f7fbd7613f0fff66c21389eedbbd4bd35": { - "balance": "956888725645000000000" - }, - "80e449a70e3c7707d6441ae8863a44aee2d7f3f2": { - "balance": "16260784762856000000000" - }, - "811a2c3d0ba4e1c36a848495585da824ec3a7620": { - "balance": "36000000000000000000" - }, - "812a3c55234d5849a854ad76891c34ee90c8a0e3": { - "balance": "703378980438000000000" - }, - "814b4b5eb67afb8d1a60e3d240fe804bb752f632": { - "balance": "17578964576000000000" - }, - "817025619f37838470b90d0a25af2c02de80dae6": { - "balance": "96000000000000000000" - }, - "817233a104d87cac34d9c90243aebd7f68e0a9ea": { - "balance": "510051038684000000000" - }, - "818be95c0c13c3018b4084ea177556705e84c1f5": { - "balance": "332239667000000000" - }, - "819618c19a4a490b821f8156c5633749ea782ca2": { - "balance": "10000000000000000000000" - }, - "81a80d26b70626e07e8747bc1569dd2855834f7c": { - "balance": "521696417321000000000" - }, - "81b2fb0db882bf2538cf8788bae1ad850cef3bab": { - "balance": "102457067052000000000" - }, - "81d4c3bf72837b21203b2a4f90bf42fda10acf48": { - "balance": "10000000000000000000000" - }, - "81df59e5d7b9a2db5463b53be83b4d7c7673d163": { - "balance": "887372337013000000000" - }, - "81ef38d074e0aa9ad618deaab01bcd135301fb67": { - "balance": "24072930558567000000000" - }, - "81f3a4c5291f13f8f97a067a6ed744a686331eaf": { - "balance": "56612148225000000000" - }, - "820610d0ddd3e9f3893f7cc13f32b1ad0d169f81": { - "balance": "50000000000000000000" - }, - "822d6388145e96cdeb2900420a0e0436e940b670": { - "balance": "20000000000000000000000" - }, - "82323b748fdee9f18e34aefc4ddebd4993ac6293": { - "balance": "112752706047881000000000" - }, - "82324995b36f4ff15be3559ccee14742d5b4c75a": { - "balance": "1184047304377000000000" - }, - "8235bfba0bf0fb664271ebe534616456a78852ce": { - "balance": "6804584686000000000" - }, - "824df7b17a61392f88f7e3067f8c261abb48806b": { - "balance": "144857897574000000000" - }, - "82555a7aebfc95a01a3773aa5370394cadef0302": { - "balance": "40069354268401000000000" - }, - "82831d451b8f92fbf6a763adb708010a3e66bb60": { - "balance": "8750983992240000000000" - }, - "8294176178418f46bb18440cc87a07cf40c1669d": { - "balance": "4439783816461000000000" - }, - "82a1c733c3c937ba0a1a49481e4d1f6226157d2a": { - "balance": "50000000000000000000000" - }, - "82ad0b5dc23bc763da0352f5983efceeaee6ea08": { - "balance": "171723633433000000000" - }, - "82b4a3d16655fd71f4020e6a562592a621ff6e1c": { - "balance": "190211621484000000000" - }, - "8357d5a016a00aa5e3ef05d3ce210826adf4c501": { - "balance": "10000000000000000" - }, - "836c41d7f9e72131eff839b7d510fd0ed412f939": { - "balance": "15575572364757000000000" - }, - "8377fff2b0eb03393543ddf5ffae90b3311af5d3": { - "balance": "2058810049054000000000" - }, - "838859e6fd751539a88d00581b0e19bc98c37e47": { - "balance": "338264241636000000000" - }, - "838da0414211392b644e73541e51e9f0fba26615": { - "balance": "20000000000000000000000" - }, - "83958896a43d23ef4ba01bdf6757c36105985096": { - "balance": "9000000000000000000" - }, - "83b88314b606df40d5e716df488980bc64125b46": { - "balance": "10985538717083000000000" - }, - "83bf53fa162e1d85751be0bc6f46e8ec881392e2": { - "balance": "1497107276676000000000" - }, - "83d7c52608b445e18fb1e28dc6198908d66bb6d8": { - "balance": "265446362740000000000" - }, - "83ee8ebaed62092d2116de6b4e90778454e8dfc4": { - "balance": "1000000000000000000000000" - }, - "8402fe573658250f50fbe111596ce35ea9ec01ca": { - "balance": "3479737676000000000" - }, - "8412b877e708a7d5db2a38d9b0f4f23d12231f63": { - "balance": "9225027744855000000000" - }, - "8418dcc09fe052febf2946ee22bcc8c53d548eb6": { - "balance": "3000000000000000" - }, - "84199f54ef96bda5e14f60aa1723e811f755d3bb": { - "balance": "129197612052433000000000" - }, - "841b1400f97ecd2ca008e7b4f5a95274bc3e99dc": { - "balance": "2095180906854000000000" - }, - "844177191a120d2dc4be9169ddbc3b5430e9e238": { - "balance": "3620793599287000000000" - }, - "84578fcffc73be7d65bfa81b0cdafd26885bafbc": { - "balance": "37592478429000000000" - }, - "8460acb05c6c476ca26495aec7224c2bf90996fc": { - "balance": "8999580000000000000" - }, - "84696cdb9f018d3e7bf453efdc174e1a586e9c25": { - "balance": "118007806297016000000000" - }, - "846a8a91d2890000d1e995fc1663cf5b7c22211c": { - "balance": "27266838638307000000000" - }, - "846b5ef52d5f7ccc17d9c7e5f49db807908c63f3": { - "balance": "375423381758000000000" - }, - "847409e5d6ed2c4e54ff97f2ed58217ac5fc3d68": { - "balance": "23972870617025000000000" - }, - "84bf432c967540caafb8bf49cdc9983e8953a18a": { - "balance": "453476687224000000000" - }, - "84eba1bb76f7a3f6d2b9052d068cc6c48d449d76": { - "balance": "17655334922000000000" - }, - "851245ef1637a07578241b3c35acf215908e1898": { - "balance": "1269389304110000000000" - }, - "853708e974fd4810655d9cd19fc8dbfd3d5e1e36": { - "balance": "18000534000000000000" - }, - "8547989af8c99a3432038a03d3fb30a054d90413": { - "balance": "10000000000000000000000" - }, - "854ba39bac4c7bf619804b6773fe43bc71f3255d": { - "balance": "15999580000000000000" - }, - "85636f3e113cbe1d1bbd1b3a23e9e98edbcb94f2": { - "balance": "1199038399611000000000" - }, - "857167896b859394babf897c4c6fa57b3a057117": { - "balance": "921057404898000000000" - }, - "85799226a1474371ca76f05597a1e3835c17e7d7": { - "balance": "562141544946000000000" - }, - "85a2221cbbb47e8b74fc2617d6087a98f47e2738": { - "balance": "10000000000000000000000" - }, - "85be0bd55fb9143ff17387914a82d0a2650224c4": { - "balance": "4038654147145000000000" - }, - "85c5ff0e4956ef0fb662a2cbf6a86325a53dac8a": { - "balance": "28690160424000000000" - }, - "85caff4ec0e1719ad963e97c1c02828683070370": { - "balance": "2022427900763000000000" - }, - "8630cc2780fee566f172ed0437264c45421ce675": { - "balance": "669721278148000000000" - }, - "8633d245c5f1b63403e3d7828dc197ce1cfafc0f": { - "balance": "10000000000000000000000" - }, - "867ccceae3192a27751d870ae13b1d3d2c3584dc": { - "balance": "1491436265909000000000" - }, - "868bed241f77983ff4a7a8d0bf121299b6b2248b": { - "balance": "5600000000000000000" - }, - "868ddd283a76a26c8bbb9761df3ca647bea267e2": { - "balance": "9000000000000000000" - }, - "8696e546f96f6e51f405905e095902db8bb90118": { - "balance": "533558981421000000000" - }, - "86ac0eae4e4c20cb7019325f4dbebad053f92213": { - "balance": "697960117764000000000" - }, - "86bef47f9d2cd7526495454eb4d1737510696a5f": { - "balance": "2938307902381000000000" - }, - "86ddd4e3f444b395be8b2b2b75c35c78877fefb7": { - "balance": "15615434748526000000000" - }, - "86f115ed19a32aba4f98270b8ad45820abbc4653": { - "balance": "151868798605000000000" - }, - "870f19e7ee358de61ad0fd3c7710441156d68f66": { - "balance": "674715936435000000000" - }, - "87141a2d3857fb8a328ef8e7b503ed965294c85d": { - "balance": "1609607183158000000000" - }, - "87257783d866af25a7a71b46ea6c2bd1e9ab9596": { - "balance": "64000000000000000000" - }, - "87298979a9a0dbc272b0e15b7e5f2e42639c9912": { - "balance": "722087160930000000000" - }, - "8757b784015f88d072229176cabefa358a0e95a4": { - "balance": "204003337866000000000" - }, - "8760e60a56c5b8b61276634a571400023f08e3ac": { - "balance": "1000000000000000000" - }, - "877e54ea7e8ab03bb8e2b842dadab16bf4ae0a4c": { - "balance": "341020957932000000000" - }, - "87919285fc5d98169bbd073cebb1b3a564264dd8": { - "balance": "579080463078000000000" - }, - "87c39cfaa9c82d84119f306e6a233a3abfbb0ad1": { - "balance": "121753433796000000000" - }, - "87d479659a472af7c8ea78a3c658605f8c40bec6": { - "balance": "20000000000000000000000" - }, - "87d933ad6fba603950da9d245b9387880e6d9def": { - "balance": "1087642723520000000000" - }, - "87ec448309024bb1b756116b81652ea518cf353d": { - "balance": "344562808694000000000" - }, - "87fbbe010837f8907cc01a5bbd967f402a216488": { - "balance": "185411503628000000000" - }, - "8805a3c529bef4d19a6491f3b7d7b1b7232bb93d": { - "balance": "264150205918000000000" - }, - "880ec9548864fcd51f711ab731d847260ed0e3d5": { - "balance": "723225945994000000000" - }, - "8818d160b56b18e196871a6c7ccf02112dc13342": { - "balance": "2857439182291000000000" - }, - "8836e25baa08c19a9b0155c57072582b49f7dbef": { - "balance": "5468425690148000000000" - }, - "885b6303d06142accf2ddddbbdd4a9379d1cd124": { - "balance": "11853214736000000000" - }, - "88656958d9cd758d71546ba52c4ea646b658c84c": { - "balance": "10000000000000000000000" - }, - "88740acdf9ab5711d015391fe8cf4a7c70a0bc86": { - "balance": "510027156671000000000" - }, - "8874966976d776c3154261afa802692afedf3d3d": { - "balance": "305634301700000000000" - }, - "88aea53c727d7a5dd8a416e49faba1c4f741f01a": { - "balance": "15358334295959000000000" - }, - "88b67d05997ae3852259ca638a00ce9b9e7e4a61": { - "balance": "278125551806452000000000" - }, - "88d730e074a102048008de81d3adcba831335736": { - "balance": "5984576042159000000000" - }, - "88da27b1f0a604a87fdedd9ea51087a331179cb4": { - "balance": "10000000000000000000000" - }, - "88efaa91dab9671f5c903e69aa6ca4d9a04b5ddb": { - "balance": "1996126782729000000000" - }, - "89a9d702f64f14fae4d1a69717744dd700208d9a": { - "balance": "251686323241000000000" - }, - "89ac81571265bebbf9d3c09e9459fd1ba7fb1297": { - "balance": "162368080974000000000" - }, - "89c75c4f0ce41d283587beba1a3e3efab05ca6ad": { - "balance": "16000000000000000000" - }, - "89d44cb81cc5a1bdf4d573c4954ee641f3cb91d1": { - "balance": "97965629614355000000000" - }, - "89e2fef4f7b7c255b36afa81cf4033b22de3db25": { - "balance": "7278615226888000000000" - }, - "89fe5d3cb5283c7b87daf6103bb568f92a230631": { - "balance": "64000000000000000000" - }, - "8a07242231f4a654aeea65b857d1519385a18065": { - "balance": "20000000000000000000000" - }, - "8a5a415f0fe2a8329e14628493d11ca20d4e482a": { - "balance": "157274758238000000000" - }, - "8a6ce9f270fe3ec33a013be9e5b1ef823c0dab53": { - "balance": "20672772672000000000" - }, - "8a6fe4fa2f86f879ec9b2bf643beeb0876da46d4": { - "balance": "1041983771868000000000" - }, - "8a765ff2b429dcdf59b65a34c4bb41798dfb5886": { - "balance": "355487172996000000000" - }, - "8a9b9b65a3d443a6e4dcf696a64983f3b625774f": { - "balance": "3185351572575000000000" - }, - "8ab1f5443cf9149773b9ddb69de3e6ea047ae38f": { - "balance": "161619949415000000000" - }, - "8abeacee0078e07fb417277e8bf15dcc2cdb9fa7": { - "balance": "144000000000000000000" - }, - "8ac0d9e0e77aa4ada4080604f2118b3a5a0f8102": { - "balance": "100000000000000000" - }, - "8adae0dc99300f60d31bfa619ec83d45b48ea22b": { - "balance": "697262590215000000000" - }, - "8aef59e59a27a8662043f1a4abcaf945a5e3fafc": { - "balance": "26780431538000000000" - }, - "8b3386f32e2d77526c223ee8bb95b7dd111ced92": { - "balance": "2179932854210000000000" - }, - "8b34d5e457ef6451bb7f5ecc93c80678a30e3194": { - "balance": "31492358338840000000000" - }, - "8b47e07f192c33bd7d298bae717dfcd68a8097ae": { - "balance": "1000000000000000000000000" - }, - "8b55bff4b281f6a24ab428d66b91f9bab06f7b96": { - "balance": "1596248680941000000000" - }, - "8b576b1e2391f22193bb4f91bec5f2a8aec02af7": { - "balance": "29660301836269000000000" - }, - "8b9097b762c7bc38a487974f3551fea697087553": { - "balance": "260887123991000000000" - }, - "8b92c50e1c39466f900a578edb20a49356c4fe24": { - "balance": "35654824979000000000" - }, - "8ba3933337108841a997accf0b5735e005373f53": { - "balance": "574965182000000000" - }, - "8ba3eeb2d1b27e021ed6bf5827280807f32c7897": { - "balance": "64000000000000000000" - }, - "8bb23a5b8c48ec5bde84f39b463559b7c048c853": { - "balance": "16186405874000000000" - }, - "8be0b6ab14e15b46905335d07df03726fb1df0e8": { - "balance": "500000000000000000000000" - }, - "8bfc53af1ae6931f47ad7f7ed2f807f70fddb24e": { - "balance": "20000000000000000000" - }, - "8c0599df87df142d3aea37d50c975c1813ecb642": { - "balance": "871085782287000000000" - }, - "8c2deeeaf095be075a2646ed7b8764d3665acf14": { - "balance": "10000000000000000000000" - }, - "8c3e7381b0598356ff81e860faf25390ae7de9d9": { - "balance": "36000000000000000000" - }, - "8c5671a6f4610ddbd05a5139659c7190f54117b5": { - "balance": "50000000000000000000000" - }, - "8c60582c4e4e60da665b4a5a2d18f514ded6c49d": { - "balance": "16806447782991000000000" - }, - "8c8464ea6b17687eec36ef04966d59c7c91fa092": { - "balance": "1872124465602000000000" - }, - "8c85c5a318cc0227576adba3e91dce6adc73f6a2": { - "balance": "52479305517000000000" - }, - "8c8f3796a2942a2298d14ff1a9e3264e9f63f2bd": { - "balance": "10000000000000000000000" - }, - "8cec1886f2cc71b09ca32a1cf77a280ae3a6a9fe": { - "balance": "500000000000000000000000" - }, - "8d0b26d57eb52a62814d7876d64c8274f4371464": { - "balance": "20794037603000000000" - }, - "8d40b92e41f3cfec06e767d64b4dafc5612133b6": { - "balance": "25000000000000000000" - }, - "8d41ea1cfb70d0ef1f6572fd72a6b417739ac7dc": { - "balance": "738777348304000000000" - }, - "8d4eb54646f9d14882fc8ebb0ef15f6056d1afbb": { - "balance": "1003867239086000000000" - }, - "8d51ab29ccd190bfe12bcd94a651e9f49a003253": { - "balance": "442251355663000000000" - }, - "8d6c0c8e4ca47626115433b39feb939014b8738f": { - "balance": "119828137027000000000" - }, - "8d7acd92d664a485625bb9884e7cac9cc6077f41": { - "balance": "1381910232084000000000" - }, - "8d7ee7a9c1c263ba8061f54dcf62d9f8420e2008": { - "balance": "20000000000000000000000" - }, - "8d941c5d0c6e2b8e2934c9f80f8a63e2fb5868ef": { - "balance": "116443644149000000000" - }, - "8da0dc43ed3ccefb18f21aa13f3fa42c13e540a6": { - "balance": "516000000000000000000" - }, - "8dab4500316475e8fc3bb6494be09f549dedf026": { - "balance": "2736245677000000000" - }, - "8db39a95f4e63bde0bd8c02e386122ce2c57a30f": { - "balance": "12577347153000000000" - }, - "8dc718b49fb68584d9472490743f9be1b0ad683b": { - "balance": "50000000000000000000000" - }, - "8dd05e26224aa8a6deb0904b6d3bbb34d268e901": { - "balance": "613146658282863000000000" - }, - "8dda0e7ddde515480ef08cf90a1eb4e78f50a2c4": { - "balance": "19265526663314000000000" - }, - "8dedad1511c11798c338334dde7be967de96e9b2": { - "balance": "50000000000000000000000" - }, - "8df63c04f18a854d7bb397bca3e2ba19202e9da1": { - "balance": "1479940547081000000000" - }, - "8dfd7edb7d28e8b3df1faab70a8ef9e3b923d998": { - "balance": "10000000000000000000000" - }, - "8e2c3af057e931b5f82e83873b336a7f68e7eb03": { - "balance": "27138009123000000000" - }, - "8e2f4eaddd60468bdc09d47f65839b96f50596ef": { - "balance": "970529157231000000000" - }, - "8e750010c88ba99d75b0b5943c716d6fc0d01802": { - "balance": "42271114987000000000" - }, - "8e889d47f3307a18490e53f2108dc31b14d6300e": { - "balance": "115722965933000000000" - }, - "8e9e1953c82217ba56365e7a9c54b1ded73914bd": { - "balance": "6248835752208000000000" - }, - "8ec980d3066cb6afa793577cf88ccb46ce8d13f2": { - "balance": "100000000000000000000000" - }, - "8ef324c861de7e042c445776bcc8ac026533bc15": { - "balance": "1869634994148000000000" - }, - "8efd14464465e50af087a80a5fbe652445de373d": { - "balance": "1157403424927000000000" - }, - "8f1b57304406fd8b2eb5dabcbd322e326dd873f5": { - "balance": "194188733254000000000" - }, - "8f36ffd921e12083e374335d3cc43fcfeeadfa46": { - "balance": "100000000000000000000000" - }, - "8f813b88e6e125eab71a63455f326322ef505501": { - "balance": "19087691927734000000000" - }, - "8f83892d4d2892cd57828fde2318610a54b14498": { - "balance": "22833507983000000000" - }, - "8f89c1bcba85757cf1718d5b9eb007e27e5195ab": { - "balance": "2241600478705000000000" - }, - "8f927ab63df4c2ce46f1ea35bc875a0c006d2d4f": { - "balance": "327487123409000000000" - }, - "8fc3c231df0f93a84bbe348aff12ab576284d70f": { - "balance": "25000000000000000000" - }, - "8ffa089b07ed1388a5d1a428daf54d9591e734e6": { - "balance": "1347580402248000000000" - }, - "90040e00f585f8be44c82597037fde452472e741": { - "balance": "2746884591879000000000" - }, - "9034eb46aad2a76bdb812c981565d4701dc10718": { - "balance": "10000000000000000000" - }, - "904ca1ac2381702bd18472b175262a8928cde5f1": { - "balance": "304421909590000000000" - }, - "90502c1123692c3b86e99b328d07fae473d4a283": { - "balance": "227491252462000000000" - }, - "9052ca7e9623c1bbe3568668673d6d252b56a764": { - "balance": "35268091378000000000" - }, - "9093d12d8410193293e1fda0cca98a43b85b91a8": { - "balance": "6829489147119000000000" - }, - "909ba8cdc707c12ba577dcd8ed1df1c02a7ce2ef": { - "balance": "60524108169000000000" - }, - "90a2cc3aa73495531691e027a8c02783cea7941d": { - "balance": "65263780625000000000" - }, - "90d7c82615f151953a8d71a68096cee4d428619c": { - "balance": "298774379499000000000" - }, - "90e02deb31d98b9c85fcaa7876eb5ec51d721dd4": { - "balance": "2000000000000000000" - }, - "90e538746bbfc6181514338a608181a3c4286d1d": { - "balance": "6069511690189000000000" - }, - "9106dddc1b693e7dcb85f1dc13563d6c7c9d8a6e": { - "balance": "1977000091291000000000" - }, - "910d1e0d3f71054835ee0d4cd87054dd7add3e38": { - "balance": "40104690362000000000" - }, - "912e2349b791fe702692a6c1ccbf6f0f06b826db": { - "balance": "6305336897000000000" - }, - "9144cc61c01eb819e654b46730620c230da9e936": { - "balance": "144000000000000000000" - }, - "91478d4c15d9ba02816456030915be08fa3aa208": { - "balance": "200078339107000000000" - }, - "9160c466b5f9020b0ab1c0ff497bf0345598ec90": { - "balance": "17705350930000000000" - }, - "919025625787101c572d8340ead1444a96593424": { - "balance": "2418027749789000000000" - }, - "91926323868c65f91b6d74c85c07279610651ede": { - "balance": "538073886450000000000" - }, - "91950cd6e2dd99e024854b65c09c5a7476777a21": { - "balance": "11629505934425000000000" - }, - "91ae8d74c26d3dcc291db208fc0783347fcc197f": { - "balance": "7604593786920000000000" - }, - "91b9ac26869abc9eb3090f1d8140eabe97f41001": { - "balance": "25000000000000000000" - }, - "91c349651afb604f9b00a08e097e02c0964e148a": { - "balance": "117290771022000000000" - }, - "91ddc95cadeb6dcf6ebbdb3300a29699ac8ded39": { - "balance": "20000000000000000000000" - }, - "91ebbd36714cc069f8ce46f3e0eda5504fdd3aa2": { - "balance": "203944728497000000000" - }, - "91f2765125b84923bd506a719d72b0c1de030e32": { - "balance": "452269960816000000000" - }, - "91f2e54a9d61ef52a33d150da50d5a8f2ebcd6bf": { - "balance": "242321058694000000000" - }, - "920dc90d11e087a0d8912c1d43db102e9ba4f43e": { - "balance": "20000000000000000000000" - }, - "922ff522cf7f3ce0bab9312132df51704caa755b": { - "balance": "1414824682473000000000" - }, - "9251449b0f757ef62f63c2774eb63ba15bf3712b": { - "balance": "102688517037000000000" - }, - "926255c17386720fdc1701747a2f024475063d4a": { - "balance": "25000000000000000000" - }, - "92808a38ffc5a339b1ab6b0b472f9975718d4a07": { - "balance": "500000000000000000000000" - }, - "9286c4497e820845341e3b9127813c1b7c884830": { - "balance": "101241387488275000000000" - }, - "9298e1df6730e91e9892d19f7ce18a3db9b5d2a1": { - "balance": "169000000000000000000" - }, - "92d98aed335c29402a43ba96c610251bed97308b": { - "balance": "3032350763000000000" - }, - "9319153f24814a81d920c60cbee9b5f2f275fac0": { - "balance": "56619610984000000000" - }, - "9347532d6396bc0b86bcd34eb80facd4c3690684": { - "balance": "258912194626000000000" - }, - "93487691d71e6248d88f06b1fbaee58b6fe34615": { - "balance": "1593901704394000000000" - }, - "9375154a7f19783b26ae1c9e48f114e1cfd1307a": { - "balance": "9000000000000000000" - }, - "9377947e0db688bb09c9ca3838ca2197fb262a1e": { - "balance": "323993393587000000000" - }, - "939ca9030b28d356dc1b071169f98b0728a9aef3": { - "balance": "218900305967000000000" - }, - "93b71636b8332515c2af031aac7a8805de716a62": { - "balance": "1640174743698000000000" - }, - "93bca153afd427b0c3c1de4a5584610e4a6595b7": { - "balance": "654782426410000000000" - }, - "93cb3b73fee80cedacf5197f8b4ac8f18f0d0184": { - "balance": "100000000000000000000" - }, - "940fcd215bab373d1b736e354f2def501244885a": { - "balance": "13133641534585000000000" - }, - "943f4bc76f20580b6546b6aff2800448f82cfdc0": { - "balance": "1927982550280000000000" - }, - "946ddb5c46fb13010b9c7ec56e4055b4f3e24b4a": { - "balance": "1410000000000000000" - }, - "947961dc367226f78d722361d5821cced52db01b": { - "balance": "115598797369000000000" - }, - "948eab3ffe44d5f1f381de2c8cadcb311c25df2a": { - "balance": "870664355820000000000" - }, - "94bf674593378243fb6b811f331f77561efb4106": { - "balance": "226539311455000000000" - }, - "94ce082887dd6324d7dcfa6cae17b653be021b25": { - "balance": "420000000000000000000" - }, - "94e2aaa4b5e2b36a12f866c96e3382a1150a97b4": { - "balance": "7344059136611000000000" - }, - "94ea5b1cdceb3f1a9d5ecacb6ac8dd2db9a461d7": { - "balance": "1951787237292000000000" - }, - "95218633176c0fe2f32fb55ad3df9f387e63aed1": { - "balance": "99999999580000000000000" - }, - "9543cb22853a46cce3aadc60e46cbddbd3fcf593": { - "balance": "2806074281914000000000" - }, - "958842c5389656d156aab05ac1731a20656716ff": { - "balance": "391064461038000000000" - }, - "958fd9bbc96531a00adc5c484d06dc61ccd717b6": { - "balance": "8021794447667000000000" - }, - "9593ce72919cb0648ddacc58af233d942963e2e6": { - "balance": "32322940730755000000000" - }, - "95a8e371af9128c97c9d4d7c4d58f5f75f2d07d4": { - "balance": "49000000000000000000" - }, - "95b9a9ad563a4c1ff7b6ebcf5fabcf5dbdb4a6a3": { - "balance": "10000000000000000000000" - }, - "95ef5fac6aa3ab1b4a87246fa800cfceff43dec7": { - "balance": "119666779022000000000" - }, - "961a3aa8015cd520de43bd47d81f5194ee4dfdc2": { - "balance": "248589901007000000000" - }, - "962bad39df25d64ee1c6b4ae9c14a18d316bfc06": { - "balance": "2404608291000000000" - }, - "96392119198c4b644c64284c9a75f61210a6292d": { - "balance": "1000000000000000000" - }, - "963c82319380587eeba0bd7b07eb63ea7042984b": { - "balance": "1480123630618000000000" - }, - "963e05fb6245ec11d67ed80e9feba6e2c0a8b4ae": { - "balance": "276053287417000000000" - }, - "964452b86b0d1d4b34aa881509a99e7b631d4a85": { - "balance": "64000000000000000000" - }, - "9644a2af2ff70eb43584a4351bfbe027c42ba3f9": { - "balance": "500000000000000000000000" - }, - "96572a017489450f2dfc0e31928576acd3bc6808": { - "balance": "1140183097730000000000" - }, - "9686bfcc0dc3de20604eb77787d0dba818cc5016": { - "balance": "10593448987804000000000" - }, - "96879780764b4433589d26573fc221f5218f1877": { - "balance": "154136576560000000000" - }, - "96ac1e62c95e33dbbd4f6ed389007e16c00b205e": { - "balance": "4130528000000000" - }, - "96ba703df3a8a6dc3c5d6be02cbf6a4afa2d1650": { - "balance": "2885298549532000000000" - }, - "96d516ded110f1d7e0290716689fd1b7964d9d42": { - "balance": "40665675241000000000" - }, - "96d75950c9354cec6084ba11058dd52d00fdb1f2": { - "balance": "903158106646000000000" - }, - "96f362c59c72fa1d39ae3ec37a7b715d2dd23679": { - "balance": "110000000000000000" - }, - "97115f7544cb05009b3fad2f0c2817f3ee77dd4d": { - "balance": "10000000000000000000000" - }, - "971cbaeafd4b0fdbad24fab946051b8949efaebf": { - "balance": "8462381628000000000" - }, - "971e195e980b4fd4db8d279c80968ca1bd390edd": { - "balance": "10000000000000000000" - }, - "9722648970c455929d621546fddbff27c49acd3c": { - "balance": "70337427969000000000" - }, - "9772027a4ea991eb9eb5ae6b8f34d750a917538b": { - "balance": "148918416138000000000" - }, - "97797e3919aa35567b9eb1224be87f96c6c2e1b4": { - "balance": "973342196399000000000" - }, - "9780a9c86160e27f627179535c3d3f23b6b29917": { - "balance": "10000000000000000000000" - }, - "97a85f4e3f53aa066825de15f1d0e25d4189b037": { - "balance": "2435764858719000000000" - }, - "97f46465e99910539bd3593c16a572e159bac87d": { - "balance": "25000000000000000000" - }, - "9882505fcb54ca2d2f4f79b03f0a5ead61936979": { - "balance": "249999580000000000000" - }, - "9898e969629502a891b758efecc9fdc5ada7d32c": { - "balance": "20000000000000000000000" - }, - "98a52d325e28ca9b4474846c7e4c07a223440fab": { - "balance": "418260286015000000000" - }, - "98a9b2f7d1ba7838e3242b5e4cbf1f2897aa4bc5": { - "balance": "500000000000000000000000" - }, - "98b8308c37a2f6cc1bb382dba2ba95a3c5ca2834": { - "balance": "10000000000000000000000" - }, - "98bf0170a61f98ab0710a68810bf152b7f6c56fd": { - "balance": "2279761566089000000000" - }, - "98c8a323a0022bd147a466fa1ac867977e12eb92": { - "balance": "10000000000000000000000" - }, - "98cd102caf0866ba0a74604b01f54049503905d6": { - "balance": "34739921273310000000000" - }, - "98d7e89c2765aaac224d4015aa277fef208953c3": { - "balance": "1291811952000000000" - }, - "98fe96bfd1e10fb60b343e512b15e955aefc0778": { - "balance": "464922897623000000000" - }, - "99064a57d693e45559a1a910c9ef7d46cce0e703": { - "balance": "8969733492948000000000" - }, - "991ea5429b91a8bfc4352a1d93304dc463be5b90": { - "balance": "149367286734000000000" - }, - "9921d405fada890fee6bf76acc39141fd34e5d2b": { - "balance": "5021308706457000000000" - }, - "9938d357d3d5dcc6f6fc7fb47a98405c0ab6830e": { - "balance": "516293591974000000000" - }, - "994f4e6521a3a5752359308b9f6b2722922c60b1": { - "balance": "23993133615000000000" - }, - "995a6a1c38f037b3a9f0a2e915b8fc0efdea082a": { - "balance": "1403498530728000000000" - }, - "99709e57748a7da6556b1670ba4f15c45aef4689": { - "balance": "36000000000000000000" - }, - "99789f65655c6f917d575169f4ba8192440e659a": { - "balance": "393071814319000000000" - }, - "998f66cbde2693603fa109ad7aaa8bc42a8765a9": { - "balance": "49000000000000000000" - }, - "99afd42a58af31daa54ad9ba35b06954330107ba": { - "balance": "25000000000000000000" - }, - "99b6a9ff2b2ac9ac0361af007aba107695ff5fad": { - "balance": "12860157225353000000000" - }, - "99d16a5955d43723ed8e2b1a642f8f1195f38b64": { - "balance": "62907829047000000000" - }, - "99df609926ca536ed3be80e35dbaecc42ae67f2f": { - "balance": "316809833612000000000" - }, - "99f3faf97a36fabea7306979b30b08fa70110e29": { - "balance": "173292373556000000000" - }, - "9a26110067b473e3bdc0fc32951b39596c967a56": { - "balance": "78192198764000000000" - }, - "9a3a8eff6fb82377da6c17ba658dca87ca0dfe26": { - "balance": "50000000000000000000000" - }, - "9a3b06257088ef8c17410a8f2d63392edb9b55ce": { - "balance": "239567000000000" - }, - "9a426842301802866cca0ef89794d928d3e8f843": { - "balance": "776173297821000000000" - }, - "9a5f2c0a6d41131d9aacdb4f8c274958cbdd377e": { - "balance": "441954000000000000000" - }, - "9a6893023ac6f34b493d33e4dc63ef697169a58d": { - "balance": "439689418527000000000" - }, - "9a86eefd848acafcbd9960003e90b22162b15ef9": { - "balance": "294190908093575000000000" - }, - "9aa711f3e4eb67d2f6405b5ee6290a014d203a72": { - "balance": "9101556549634000000000" - }, - "9abf9ccf6abb8d55ede458d2d12a279d0a823944": { - "balance": "17609693072000000000" - }, - "9ac1909b983c754f0800559174025c0f0baa9d31": { - "balance": "80921948093000000000" - }, - "9ad62cd855d629e1ddab632874a6dc2b812f2348": { - "balance": "2068118534000000000" - }, - "9afc2c33aa2c9a42600abb18aedaefa433326122": { - "balance": "2485353229354000000000" - }, - "9b18d230b221a99c74877d4a1dbdee2214c7d60c": { - "balance": "4024172228743000000000" - }, - "9b18e27788c9d59053072032a480569e142595a0": { - "balance": "110789164888000000000" - }, - "9b4535b23af0b8e5f488a6f318ff6badf71d16c1": { - "balance": "84756740661000000000" - }, - "9b5e7cf43aece7b38ea2af6d08bebe2d3b926840": { - "balance": "262771268227000000000" - }, - "9b77dac92fedd0ad3eb4326d4fafe0f4315a8844": { - "balance": "3616321626000000000" - }, - "9b8f6f223641f9b1bab319dd1e88c49fd411a765": { - "balance": "2054417462086000000000" - }, - "9b9f94861d80365464912e5c7213403405a6cd8d": { - "balance": "2367093088000000000" - }, - "9ba24397002929e6239848596b67b18a8dea1eef": { - "balance": "5000000000000000000" - }, - "9ba99736c5ac468d6b644e39b8d515c39151f51d": { - "balance": "311900650761999999999" - }, - "9bf2d4ff366e1bb2313ae9a93ccca75d6bc0d232": { - "balance": "764870206925000000000" - }, - "9bfce7dbfc9ae62d450e862261d1e21e68bac92c": { - "balance": "1000000000000000000000" - }, - "9c003e74b62f192a864045d678639580c672fc22": { - "balance": "50000000000000000000000" - }, - "9c128bd2c0c96b896db6c0f398e908c98302809e": { - "balance": "3251059363800000000000" - }, - "9c255daa89ee16f32fc0ab1ed8e22db39342e6ca": { - "balance": "37695843594589000000000" - }, - "9c32e714bcb601a56a8a4e6b3f7bcd9e1c7a1b54": { - "balance": "50000000000000000000" - }, - "9c503e087b04a540ed87056c9371d591afa72df2": { - "balance": "64229084991000000000" - }, - "9c54297dd3527cbbb8ca8c305291b89bfb7ab39d": { - "balance": "61682466962052000000000" - }, - "9c55bb1db3b2bb06e605a66ced9ea2ac95718205": { - "balance": "16512365324000000000" - }, - "9c59dbc48b9cf53fe668784e89d30493da9995b3": { - "balance": "50000000000000000000000" - }, - "9c61b58aa760265f7fd1b9e749df70122ea81175": { - "balance": "50590272373000000000" - }, - "9c6c7eaf4bec0566a7bf8acd30e10311a963267c": { - "balance": "999999999580000000000000" - }, - "9c91dd4006f9d01d8caf5f5fb4f2c4f35ee63ffc": { - "balance": "175730980227000000000" - }, - "9c99275f5dee14b426302b1a47a8488c16432f2b": { - "balance": "2000000000000000000" - }, - "9ccf7b23528d062da63f6af3e26531b775c83c52": { - "balance": "928373869120000000000" - }, - "9cd21c30ccbc1087c9b351395fdea17ad669cc2e": { - "balance": "529762292313000000000" - }, - "9cfee47d6f24880af7b281cc00e1fc58e0a4a718": { - "balance": "198888257958000000000" - }, - "9d08251f7d4cfd66d15c17e1ea6bae5c795e290b": { - "balance": "813841349140000000000" - }, - "9d5411490ce89359bfbacf9f9957ebfbbc18debb": { - "balance": "22263187467000000000" - }, - "9d61e1dfaa7d0e0c5f5d733a24a1883c4e201f3d": { - "balance": "144000000000000000000" - }, - "9d754d94a15ab6d738e511fe4c775ee6d20a53ee": { - "balance": "20000000000000000000000" - }, - "9daccedf104fdcc3c39f2961ddfa1c64eb632476": { - "balance": "1237093270947000000000" - }, - "9dad4968c0e44aa729fc5732f3ee903c6799637b": { - "balance": "838788687517000000000" - }, - "9db73ca677bacbb622f44fe90b53ee1d9f0c2009": { - "balance": "472858335000000000" - }, - "9dbcb5026e0f444a33197da240856f108db14ff0": { - "balance": "10000000000000000000000" - }, - "9dc46cf729187ceed8001c4ab14fa4fc21c35f32": { - "balance": "3320792646995000000000" - }, - "9dd895c1bdac2ed9864134aaa8c543473ee5f19b": { - "balance": "1430620966869000000000" - }, - "9de2687242cbf9fb94fee0ad873acc7494ebd2bf": { - "balance": "20000000000000000000000" - }, - "9deec036282717aac93ad5cc1b6d4a5354e85c2e": { - "balance": "2048627955362000000000" - }, - "9df8dc66395aeae9b4c831b4d63bdf48db08811a": { - "balance": "215874670561486000000000" - }, - "9e1fe68a70abd8ab517878b03961da8564b43eb5": { - "balance": "67908329894526000000000" - }, - "9e33293006982abc668e199aab20260b9b754463": { - "balance": "49000000000000000000" - }, - "9e65616282a0baf89469a58915fd8fdbed210e3f": { - "balance": "829209872657000000000" - }, - "9e7b7b522834dd7e83ff2bb6b6e4cd2972330899": { - "balance": "500000000000000000000000" - }, - "9ed134b3a8feccb4056b2e511cea9a8ec58a3e77": { - "balance": "18787546978390000000000" - }, - "9edcf477687a9dee79341ed5d89d576c9a854c2d": { - "balance": "500449025554000000000" - }, - "9eeb06d4b532118afa013a01c9e89216fe0475ae": { - "balance": "1823939486758000000000" - }, - "9ef20a338e85044922f08f3648355e834874d551": { - "balance": "50000000000000000000000" - }, - "9f0855f9cc429fd3590c6ad05bb66a9e038efdca": { - "balance": "8017999878252000000000" - }, - "9f3befcc1884d16b65ae429228d26fffc146c8dc": { - "balance": "1016482445089000000000" - }, - "9f4571748463eee19e59ff9bd734a62a66613850": { - "balance": "20000000000000000000000" - }, - "9f51de282745f77b8e531e1de0b7c14e3369ba54": { - "balance": "1010657089383000000000" - }, - "9f6527175a2b581cc79f2a68c35202e0a7f2af20": { - "balance": "216495522463000000000" - }, - "9f70204d1194f539c042a8b0f9a88b0a03bbcd8b": { - "balance": "10000000000000000000000" - }, - "9f70e44704049633110ecd444f9540e241b50783": { - "balance": "9139000000000000" - }, - "9f73fea741e8506ba7acb477745dab1cfab8366e": { - "balance": "4461472359634000000000" - }, - "9f88d33d26c90e74c39c9676b8b580d21bbad124": { - "balance": "54437240781000000000" - }, - "9fa47455be14ad2eecce495281ed0eea926ec6a6": { - "balance": "10000000000000000000000" - }, - "9fbb15b595d154754a2ae77c77283db9d4e9f27b": { - "balance": "6195722646556000000000" - }, - "9fc480ab1823a59fd6130c3948980f95ac99f1d2": { - "balance": "24101151540000000000" - }, - "9fe5f054165fbf1943b1b02c01063f04e0c3890b": { - "balance": "1000000000000000000" - }, - "9fe7d3d5976e7b8b5ad6baa15ceae96c43c60fea": { - "balance": "55000000000000000000000000" - }, - "9ff116ea0e219814970cf0030932f5ce2cd9a56f": { - "balance": "36000000000000000000" - }, - "a01f6c36193839bc3a31e6d0792324771040fc05": { - "balance": "48298750000000000000" - }, - "a0264706d668522b737bbdbe949ce3e5a60fe314": { - "balance": "1423066922869000000000" - }, - "a02b13bb3b13027045ffb9b44bc7380a942e8ebb": { - "balance": "86845430807181000000000" - }, - "a03d246a931c3d422e5d2bf90f64975923a93643": { - "balance": "5834171660287000000000" - }, - "a046caaee59425ea1040867c62a6fcda11652a23": { - "balance": "83087966538000000000" - }, - "a04b57b2dd8b2082c53517d956f5909d25e14b69": { - "balance": "4518538234851000000000" - }, - "a074ef9e0ffe15619103e3de490f5813be53dcbb": { - "balance": "4568113810000000000" - }, - "a07bae42b44c085067de16e7d9846db529059acf": { - "balance": "4000000000000000000" - }, - "a08530e5fb7e569102b2c226aa5e53dc74483e4e": { - "balance": "2325665286793000000000" - }, - "a095a2c666f4f3203a2714fb04867c13c2add4be": { - "balance": "14768043990000000000" - }, - "a0a967418a3fcb3ee3827a08efa851347c528a60": { - "balance": "20000000000000000000000" - }, - "a0bb293071e07418ecb2fefc073136569ebd1736": { - "balance": "25871128320000000000" - }, - "a0c6c220a53b7dc790f7a5b462a106245c761f70": { - "balance": "1000000000000000000000000" - }, - "a0f06c86c49b248f4835bff405b620d12ec80d07": { - "balance": "484572382390000000000" - }, - "a10bc9f4d05678b26c4ffd2d92ab358163020b61": { - "balance": "10000000000000000000000" - }, - "a10c1197f7bc96639d01a652df73e49c669165dc": { - "balance": "1205859101575000000000" - }, - "a1221b2001f85f71e0655551e300ce115284b8dd": { - "balance": "1376698025177000000000" - }, - "a13fce836d65124fe5bcfa2d817ab2a043acbcf8": { - "balance": "55000000000000000000000000" - }, - "a15f1f609f7464906e0eb9d5e1d26468b90d9198": { - "balance": "16000000000000000000" - }, - "a1617dcf3acda60737e5ca9e4d0ecd82a98ef667": { - "balance": "500000000000000000000000" - }, - "a165c5f151d0daab905ba4a6d1fe5d5114fd7686": { - "balance": "41039049526000000000" - }, - "a17d5bed36c1059561e184a8a90a38ce955b92e4": { - "balance": "10000000000000000000000" - }, - "a18efb4e0950e7ac95970cd4591dacc286241246": { - "balance": "12403188476000000000" - }, - "a191fa6be64f2f6d2b4a7fb5a586416a605552c6": { - "balance": "60340281461000000000" - }, - "a194c15518cefbe94edbef3a2421586b51f7e1f6": { - "balance": "4153525550636000000000" - }, - "a1d0e41aacf83fc62fbecf35f8e873f8d734ecaf": { - "balance": "9000000000000000000" - }, - "a1ddd1f615ed483ef895e341f3266b6891f9b59c": { - "balance": "180411786335000000000" - }, - "a1f4d1e03114707a56ef9069bc20c6094e810d34": { - "balance": "51949145435222000000000" - }, - "a1fe101a65616cd03e3af03092be63434b7bf203": { - "balance": "1005401878265000000000" - }, - "a25a8225ce67c54048737601eac5e0d063c2fa17": { - "balance": "272038848571000000000" - }, - "a2714999233bcaff7294fa3e3b64c63ad45a928b": { - "balance": "14560781294000000000" - }, - "a28db3f7fb1771a3d77dfb19b54f88fd55b15c8c": { - "balance": "8000940572576000000000" - }, - "a290101bfe5fbc73146c4ec3ab5266c043eb701c": { - "balance": "1397563244603000000000" - }, - "a2924cfbcd37d0b321d6abbe57c645f9ce32340e": { - "balance": "200000000000000000" - }, - "a2a26c34f3d950c795fc965f6b1df3990e111403": { - "balance": "34525064429023000000000" - }, - "a2a2855851711bfc051c1f298821ae89e4c872c5": { - "balance": "491025000000000" - }, - "a2b956dd6f1934a4a44a026a18ac345ddabe42d5": { - "balance": "20096625821563000000000" - }, - "a2b9a118a79be81711d95485aa12e3efe78ca256": { - "balance": "10451051632647000000000" - }, - "a2bcf08ddd1778b30ea7882518148edfba2d9b20": { - "balance": "347033754668000000000" - }, - "a2bd489ec4790f4145f8a9a95c9c829c5c020146": { - "balance": "100311110878000000000" - }, - "a2ee35300ddf6a2491ec0e1848f8b56defafd7fe": { - "balance": "500000000000000000000000" - }, - "a31adf082ffd212df18d5a84b105a937e83b1b1a": { - "balance": "7124891785000000000" - }, - "a32c944e6c5fe186794b88d6bcbf51c47bea55ab": { - "balance": "732129357042000000000" - }, - "a33105d543f5d2b1220d4e1ecfdcf85699324dad": { - "balance": "74798779358000000000" - }, - "a3330c73e2d79355a14e570da1ec2e80f8048c69": { - "balance": "10000000000000000000000" - }, - "a3580034590e3052b9de5abd635e514ec5ba8694": { - "balance": "10000000000000000000000" - }, - "a360d8e2519dc6d7793cc371d91ad6add75e3314": { - "balance": "192622260840000000000" - }, - "a36b9b8b2adb20fb4a84d3025bf2e35baa8b7fef": { - "balance": "20000000000000000000000" - }, - "a3771b191237bef48339aa77ad5357f6227b358c": { - "balance": "512633055119000000000" - }, - "a3892bfd25705387cfb4eeb6d21089753c22e3e2": { - "balance": "258136912825000000000" - }, - "a38c793775ebfc7330b4331fe2dc848abb862b73": { - "balance": "1193250172232000000000" - }, - "a39417002ab94845541aded4a614a5a04af8187b": { - "balance": "1185722898000000000" - }, - "a3a79a9f929b54075de43689adb665ef914812ca": { - "balance": "100000000000000000000" - }, - "a3b59ea3d366f818ca09980846ac533d4685c121": { - "balance": "59734700360000000000" - }, - "a3c7b7c594a64225922e02039669e4d0b43fc458": { - "balance": "11779233750000000000" - }, - "a3cc39a68184e51f6445d3ba681a55f4157d4383": { - "balance": "10000000000000000000" - }, - "a3d414d9f210f7b77f90790ce09f6128abe50adc": { - "balance": "10000000000000000000000" - }, - "a3dfda16e5ae534ac100f56741b77b6f86786615": { - "balance": "9000000000000000000" - }, - "a3f79b9d1fc9d6dbaaef49d48fa9c9fb5a822536": { - "balance": "108910000000000000000" - }, - "a3f87414bc9e6f01c2fbde966fc8fb6edbf58c29": { - "balance": "441000000000000000000" - }, - "a3fa3f58c802d9a9690de760716275f14449045a": { - "balance": "437227558095000000000" - }, - "a417ec5a9749064a6521ca2bf9d05f208eeaed54": { - "balance": "959205202638000000000" - }, - "a484d5b883d2b99b81b7bef27e307957ecb64b15": { - "balance": "126491152120000000000" - }, - "a488cd48258e57d66f44e73a60c121f963cb29f5": { - "balance": "20000000000000000000000" - }, - "a488e3b5096e964b21cdeba12ab423f391765b6d": { - "balance": "1712050478592000000000" - }, - "a49dba65f28909e9bd2ce5675bd091f498c6c5db": { - "balance": "216802821062000000000" - }, - "a49eb6a791022c1324facc23d8813f9954d1c639": { - "balance": "287438914902000000000" - }, - "a4cc080a5c4649f511b5844a8e0b031927e13a87": { - "balance": "20333578449000000000" - }, - "a4d2624ac5e027f72edaa625ef22134217203b5d": { - "balance": "1000000000000000000" - }, - "a4d30e35c9617eafeda82866c96c3ce6bf14400e": { - "balance": "1223254927978000000000" - }, - "a4deae7355bd2e1d57eefa56600601b8b475a501": { - "balance": "36000000000000000000" - }, - "a4ff3b5abfe4e50adad16d01aaf62c3d4cdb5260": { - "balance": "20000000000000000000000" - }, - "a502b109869ef07451576bf0e13ab294e1f236b9": { - "balance": "94843398055000000000" - }, - "a517a3b5e4324197902e16f8a29e47335cf39c11": { - "balance": "100000000000000000000" - }, - "a51e101088da23c82907e3e2c65a058f0454b131": { - "balance": "196000000000000000000" - }, - "a52bcff6a7e2e70cd714058bc30a16138fe39899": { - "balance": "30429750204000000000" - }, - "a544e84c2bc4b17859d06f136b6e377e4e398b22": { - "balance": "143977568178000000000" - }, - "a54ddacbc17a98b9fb6292aab3d92f4c5753fd0a": { - "balance": "100583192014000000000" - }, - "a557754f6637a19c1a48cb9bf58c1fe897acf434": { - "balance": "2087038692036000000000" - }, - "a56649205d9ea247b49e03dacbed6c78c21beb4a": { - "balance": "5046177099585000000000" - }, - "a568136446ee6b3bf62a20238db3b11397a065f2": { - "balance": "11652249158033000000000" - }, - "a56a7865b526e315a9eb41f4847485c7e0c952fd": { - "balance": "50000000000000000000000" - }, - "a56bab2a9aac9d08a7bc9265864a80089b68570d": { - "balance": "37138466291329000000000" - }, - "a5965a601c5df7765cd70e5dad27dd23da67ac99": { - "balance": "10000000000000000" - }, - "a5a3161c44c34c441784b7df795067760b0ee569": { - "balance": "35053289069000000000" - }, - "a5c245cf843e691956007b94e259b437a4e6b7e3": { - "balance": "18749166170000000000" - }, - "a5d7de961c3b991dc78f2d6c0448fa6225116d3f": { - "balance": "1574510758868000000000" - }, - "a5f47d2081ef728808786128549a28a5662e92a8": { - "balance": "1750000000000000000" - }, - "a610c90f5b7e5f33044956ba431a3887de1c969f": { - "balance": "25000000000000000000" - }, - "a61c1919bc3f3181dc94e2230d35574cfc972d78": { - "balance": "8990565120000000000" - }, - "a62f1aabd91cbc0112e796d1ec3727fcd26fa293": { - "balance": "1311277302001000000000" - }, - "a64fff0bb32e32f81a541c393982bc59fa183b1e": { - "balance": "8291357610655000000000" - }, - "a673dae555d367b8d4a784274577a1884615b9d9": { - "balance": "27416452091330000000000" - }, - "a6c780b585355d84d9d3c13be5bd05374588e240": { - "balance": "913657165911000000000" - }, - "a6cc1f6f51862c2798adaa1d266988022005a71a": { - "balance": "284500645805000000000" - }, - "a6d9c82784fa20dcf28266d047db441cfeb8855b": { - "balance": "10000000000000000000000" - }, - "a6dae08f99e4fb57b066a645a259d8e4f7ac2bc8": { - "balance": "9044922773690000000000" - }, - "a6f49f36f8d10a796bc2afc9e069cb0c76004ddd": { - "balance": "128555691078000000000" - }, - "a721ce1c294a0f1957ebf9be20b0fffcf90111ad": { - "balance": "3392103457630000000000" - }, - "a72b82c33bd3d6060e8a04392d236775d48ec3ae": { - "balance": "1434465940701000000000" - }, - "a7344654f2a1a44b3774e236f130dff8a4721e82": { - "balance": "100000000000000000000000" - }, - "a748cced92a87066db8b29f931fb92e827488a9e": { - "balance": "5487679824758000000000" - }, - "a78dcb2bcbec2d0a60661e1715c9a95c9d573a68": { - "balance": "346798292989000000000" - }, - "a7a6c0505e7090e0b2c21394877f91c50be6b45f": { - "balance": "4125233658872000000000" - }, - "a7dcdd9b9785a44a2dd4c5eeeb863ac1feae0f66": { - "balance": "10000000000000000000000" - }, - "a8013e9dca1bd38975748de2fb6cb3af5cae74d9": { - "balance": "10000000000000000000000" - }, - "a807bf78b15c15cd9e8edcf586849db716fedbb1": { - "balance": "1458293606310000000000" - }, - "a83410ff00fb4b913dd0ea2003b38c5c3247350a": { - "balance": "2876442029807000000000" - }, - "a848f61298a409e77a03900712017572f35a3319": { - "balance": "2783106133600000000000" - }, - "a85bb81d0dc57f824a763814759fd93fe3020569": { - "balance": "4558027813744000000000" - }, - "a860611cd098ce98974313030d9f6f462bb274d4": { - "balance": "961594154368000000000" - }, - "a8799eeff72929ee6cbfb5b0c02985cd4841be3c": { - "balance": "500000000000000000000000" - }, - "a8c29b9b1349fac0be9a65873e1911b7439c9a63": { - "balance": "1264035560749000000000" - }, - "a8c321024a3c015d881efca33bd1b2c1788b379e": { - "balance": "528752788000000000" - }, - "a8d02e8925ed48f4274d8bee62253dc0d4f2989c": { - "balance": "209083880937000000000" - }, - "a8d2bde2ccd6bad67ee1b9550c9310accb37cd79": { - "balance": "49000000000000000000" - }, - "a8d61abc6a403adc183aeb74c83e4221fd28ee1e": { - "balance": "50000000000000000000" - }, - "a8eb6aa5a0c5b6d9260a202dc76ab674d9a5f3b9": { - "balance": "1041257515142000000000" - }, - "a8efc57efc776dcaaf4003a8cfa63f215ab0284d": { - "balance": "166144142685000000000" - }, - "a8faba86d87678294e311cfa7f8cbeb6f9d8a499": { - "balance": "124541781000000000" - }, - "a912e02f8eab0cb620316129875f919455201117": { - "balance": "6454482105955000000000" - }, - "a929ac95281d1a77a3eda3b5ac90a761ef03ff16": { - "balance": "1074305309650000000000" - }, - "a92a4e40519003813f5574397ce328d046f75802": { - "balance": "9188437500000000000" - }, - "a93850ba8fff3bd18ab259f87c58bbce84165fff": { - "balance": "39018890852058000000000" - }, - "a9843660a17c2d972246028cb8045472abdd346d": { - "balance": "1052681604185000000000" - }, - "a9866c6271733971e46df3c9bb27b3d3c513c166": { - "balance": "200000000000000000000" - }, - "a9b1299c0c064e766f9f29f4301a78c6e4931fcd": { - "balance": "267785134400000000000" - }, - "a9bc33b9c99dd5a3967387c1e99766f9bc74d591": { - "balance": "65356157048000000000" - }, - "a9ccf1cd2f816b15182997e3207d9a681bf21b06": { - "balance": "17521053440000000000" - }, - "a9e54bd9826f853f65e0be1ec0bb9c28f95e0eea": { - "balance": "6260000000000000000000" - }, - "a9ef563c872342f49817a903a5725b504d455ea9": { - "balance": "50134015139000000000000" - }, - "aa0d69c7e1382cd16c527a3fee48db19c38e1398": { - "balance": "142562301500000000000" - }, - "aa12abcc3ab373d07bf560fd200652c8580fd967": { - "balance": "5509242259903000000000" - }, - "aa1d6b968b3f8046a94f128864bfc612fc2e2700": { - "balance": "489179780895000000000" - }, - "aa20b8559d6dd1543e8c528775ae4b04c6242471": { - "balance": "169000000000000000000" - }, - "aa227e9d6074a60ecd43e1cc24092ee58560374c": { - "balance": "596190898010000000000" - }, - "aa7b660fec7b05968ba656eae9a8aaef4481720e": { - "balance": "674642002744000000000" - }, - "aa9e04077d44d288978a3a3ab0d7c251c0447a4c": { - "balance": "10000000000000000000000" - }, - "aaaac1e72955e9d67625cf8bed73fa643fb1cc1a": { - "balance": "9781187987000000000" - }, - "aab46c0c2db4e330834081f97678906252746f97": { - "balance": "16440184245000000000" - }, - "aade5358c52b8aa5ad8ff285c6b297e86f49fa0f": { - "balance": "982846000000000" - }, - "aaedb3fa2cf0ebca0ef4a121a28a406264ccc900": { - "balance": "100000000000000000000000" - }, - "aaf30bf76362a03450aefaf5bd68d28b84eb4962": { - "balance": "509106199370000000000" - }, - "aafbaaa6b6369e986ba72b196bd5f08cc458e344": { - "balance": "216372214000000000" - }, - "abb03c888d61c9102827a1dc0950145beb9d96b3": { - "balance": "144000000000000000000" - }, - "abc6dc937d7703a6b0c83659a328cde0d5008e32": { - "balance": "4052429106341000000000" - }, - "abd3910139a97cb92dc09a8a0352575bcc9ebed3": { - "balance": "24028359215749000000000" - }, - "abdc3953ef293c98989802063f8cb55e0e506432": { - "balance": "64000000000000000000" - }, - "abf1a47c582bc87d36e47cfce24e0ad249f42e73": { - "balance": "71947491720909000000000" - }, - "ac0b6e7aadfb5ffafd5cb3ef3620ebb0691cc3fe": { - "balance": "10000000000000000000000" - }, - "ac1a182607046b56e7a4bbab87cc1182874f79ef": { - "balance": "453499500178000000000" - }, - "ac251b311f781ad7a43d01b0b4b20fe891004e7e": { - "balance": "304621378298000000000" - }, - "ac258cec5ef49f96612d659f66dd4e6ea88e3c87": { - "balance": "255185373455000000000" - }, - "ac4000d9ad080740ef4a2ebe4a3075877bea277e": { - "balance": "10000000000000000000000" - }, - "ac7445c09372f15259fd852cc458783d6140c0db": { - "balance": "10000000000000000000000" - }, - "ac8d29dc05ea6c2f5409a76abe04321bf9381f32": { - "balance": "22464474197854000000000" - }, - "accd52b63822d8cb5117d9deb56596e072462614": { - "balance": "20000000000000000000000" - }, - "ace63a86a2ddfc79f677344e93dc0c4750b8fdcf": { - "balance": "1355066360964000000000" - }, - "ace83deb83fa8d319979658592b75ed13bdf97c7": { - "balance": "20000000000000000000000" - }, - "acf91515df16b21f1e5f5474dbefe596e4929b96": { - "balance": "1153047238967000000000" - }, - "ad04381f7ba89220e8fcd7e200f98a476683a904": { - "balance": "2000000000000000000" - }, - "ad22225bf225d8f705f93bdcda8d301180ea28dd": { - "balance": "1272512717188000000000" - }, - "ad3f74034ff5ca89f97b2585edf12376820307ab": { - "balance": "12303261515593000000000" - }, - "ad43a3527ad2b9445417cb73cbcb42965a5f469c": { - "balance": "67607364133000000000" - }, - "ad61cf9bf560bd5da75d55738477bd9aa25fb0b8": { - "balance": "4358939446693000000000" - }, - "ad649e8a3e1436e0604b0b8c9b1a5f1c09e06d7c": { - "balance": "344000000000000000000" - }, - "ad6b584813814db4c72c4c7eb31447d224074b46": { - "balance": "18445595367000000000" - }, - "ad7d404afc67c0e457fd3ce142cd30b506408683": { - "balance": "48218702840000000000" - }, - "adaf4d39b6806d132128ac438c2862c0a1650cff": { - "balance": "500000000000000000000000" - }, - "adda124baed2e1fdc1acc7b4a048eab0cd249212": { - "balance": "1074765673925000000000" - }, - "adef437c429d90a350b99750d4b72bc8538c5f98": { - "balance": "931901903135000000000" - }, - "adf826a0ea7dc4322d26e9d8c54c4180c1827216": { - "balance": "323567723315099000000000" - }, - "ae01d8b1668f8bfe6e225bd9bc746f7e839ac0d8": { - "balance": "321211880744000000000" - }, - "ae17de3ae6127022e53ebcf9e08457174cdee0e9": { - "balance": "3817903000000000" - }, - "ae243b0186793eddc6ebbb1a2c1f0b1cd574b07c": { - "balance": "9000000000000000000" - }, - "ae3ae1d41dfb16e19a1817b3639cd4300fd166c1": { - "balance": "55437674845679000000000" - }, - "ae506999882d4c6f05cc7979c342c0ce559a8df0": { - "balance": "1391755905401000000000" - }, - "ae524cee5aa23025d6ad185ccab75a6974335d53": { - "balance": "797132751509000000000" - }, - "ae5a55075d0541f179b085152bfc8c72c74abe23": { - "balance": "589408139567000000000" - }, - "ae63d02b18b464f0bbab4de943766bdc7ba2926d": { - "balance": "300261019201000000000" - }, - "aed8ffb86a49c09ae3a83e93d9045851434a9f0c": { - "balance": "1031991707237000000000" - }, - "aee18a9a2ccdf6025d61005827753ce4f510f7e8": { - "balance": "1818639022863000000000" - }, - "aee67910c514fa63a228769d5e15ca40bc4b26c2": { - "balance": "5688989238568000000000" - }, - "aef744eb2ec682dca128dc3149afcf881e367121": { - "balance": "818801643225000000000" - }, - "af04430b3e40e746127623532353a0f177a88fe3": { - "balance": "100000000000000000000000" - }, - "af181833edb15c9b2ee2329dcf1845b977361b7d": { - "balance": "93228805338000000000" - }, - "af30db29765b4fda6f075af96e8acd5046b099c4": { - "balance": "1000000000000000000" - }, - "af31fd30cfb10f1b0a12c2e7dd7ca56bdf517745": { - "balance": "36000000000000000000" - }, - "af70d6820e1d26194b0a9965b55254a287b162f3": { - "balance": "87593999609754000000000" - }, - "af96a573fa86c07389a71db797bea689419b23ca": { - "balance": "36000000000000000000" - }, - "afa4c5b674934e31a9aa5e3e723d85060d51c4d0": { - "balance": "10000000000000000000000" - }, - "afa6e4b4060c2e5969c2329d13cc42924412efde": { - "balance": "127502378589556000000000" - }, - "aff2308ac607f85392f4c8a6a043af67b7b849cd": { - "balance": "11130371831000000000" - }, - "b00ea9c459105b650def1e8569c85fa01837454d": { - "balance": "94928352162000000000" - }, - "b02a7d16ea8663c88416e6f64eaf57787d230be3": { - "balance": "17215604601000000000" - }, - "b03f4e9aa5c352cb1cec953d1123c2f22cd94b5b": { - "balance": "206022552274000000000" - }, - "b051459b91d253c5e8251a5a68282c291833466a": { - "balance": "297127749975000000000" - }, - "b055bdc874ca5a7d2f4bcbc51f1cfc3671b55f72": { - "balance": "1421913523478000000000" - }, - "b06156b99b891b756262c5b40db9bbe39fddc77f": { - "balance": "49000000000000000000" - }, - "b076893b9841d2775ec8883f05b74f1e5aec327c": { - "balance": "22591055478000000000" - }, - "b095de644af3c9f960f67502da6ac5eb050a158e": { - "balance": "4958067562725000000000" - }, - "b0a1f794cf70422395f74395abc9a7d0b271846c": { - "balance": "812057322000000000" - }, - "b0d36e0f426a99416425689c657fc6d64ad698ca": { - "balance": "1157727077158000000000" - }, - "b0f35fa554d6ed657bf3996cc027d045c3971fcc": { - "balance": "64000000000000000000" - }, - "b0f76b4c9afdfe35c41d588265642da60f1b97d1": { - "balance": "1000000000000000000000000" - }, - "b0f76b4c9afdfe35c41d588265b42da60f1b97d1": { - "balance": "2028311808491377000000000" - }, - "b1445842d56c56bc532d2f33ab9b93509c732a3b": { - "balance": "13522982470164000000000" - }, - "b156bafe05973bc839c4f115be847bbde8a67cb1": { - "balance": "10000000000000000000000" - }, - "b182e4d318893dc1c4c585195dbde52a84ed4ffd": { - "balance": "329498977335000000000" - }, - "b18f506e77df4db80ca57cefeaca4f1010f78f50": { - "balance": "956339304078000000000" - }, - "b1b6f617b110dd79c8fd77e729584d1fdfa9aa09": { - "balance": "16000000000000000000" - }, - "b1bba36e2d9e272e0131f4bae09bcfd92e0a63db": { - "balance": "64000000000000000000" - }, - "b2285651e57ae0ff27c619207cceacd20884d152": { - "balance": "1345938295122000000000" - }, - "b2419a93732d0d324daf7707fac3782a77b0dff8": { - "balance": "625000000000000000000" - }, - "b27206e9f2ac430841fb8da69b49d505f1558b8b": { - "balance": "29507819229000000000" - }, - "b2801fe902c7bbc987ba12ecae98765c99980fef": { - "balance": "240016083000000000" - }, - "b2843d5215ceb761e78f281402a1660c3abadf5b": { - "balance": "3335539720927000000000" - }, - "b2a22e6a04a2ce3287da3b8b6eed4ea1f18f05dd": { - "balance": "99999978999999999999" - }, - "b2d55a061fc6f90d2a05e0cbd26ffe0a1c3321c2": { - "balance": "1000000000000000000" - }, - "b326aec1cd523948ffec2fd1e8f21bd2b4308f40": { - "balance": "913000000000000000" - }, - "b32abc82b251e2d310ea7588cae4ad4acb657cd9": { - "balance": "26946233911000000000" - }, - "b36924d578973aec05ce7ab556d7ed00004949ca": { - "balance": "393041705867000000000" - }, - "b37482114c83e857c730588d7d959d300b8142da": { - "balance": "29429544454000000000" - }, - "b39998bade135ac6ccadff41cd709e161d01aa60": { - "balance": "26272579375000000000" - }, - "b3a995ee94f1d63d12f10cea5ab3d596c7c6f284": { - "balance": "64000000000000000000" - }, - "b3bf35e936fdbb7d0bbeeb1cf076f243855ed477": { - "balance": "754081187934000000000" - }, - "b3c2ac85b99abed4a2a52b5f96a2c98040d16022": { - "balance": "50000000000000000000000" - }, - "b3d1a2c0ab2d8987446d74f49e357adf5bf15986": { - "balance": "10000000000000000000000" - }, - "b3fbcd24c8394a5d2b7fe877f18681a109a404e5": { - "balance": "2558689648423000000000" - }, - "b4110f4e38405adfc054e55ff73c55842db8e2cd": { - "balance": "129000000000000000000" - }, - "b417f4681fdd4e53cfdf8550e3d326dbb0a557ec": { - "balance": "1000000000000000000" - }, - "b422970fb8799d83642b7ff715fc941d69e86053": { - "balance": "81000000000000000000" - }, - "b4237be71920497715826eae8d85c26cb3c111a8": { - "balance": "10499979000000000000" - }, - "b431839de4b21dfb44150cfc6ed00ea430a81687": { - "balance": "26839560174813000000000" - }, - "b43a0d6399c7d1be943c4b45838156a47c88f909": { - "balance": "10000000000000000000" - }, - "b44ec608b95d0d51105ce5f4b48de5dd72f346fd": { - "balance": "448125120000000000" - }, - "b47f63e14f6de6c3413b2be95a725e367ac18fb6": { - "balance": "500000000000000000000000" - }, - "b48071cd1b15f45028e9dec2237f14f10b7aedf9": { - "balance": "38042711385000000000" - }, - "b4b874b323b560aa0e4811ca574bd48b65b3fc72": { - "balance": "18063913676592000000000" - }, - "b4e4d4af0667f8158cf817bf1bc3eada08a551ca": { - "balance": "2149067370317000000000" - }, - "b4ecd625ffe470ee1fa1d97832e42ddf3f9ddf6a": { - "balance": "1181738860120000000000" - }, - "b53f380ce92787c1db461524290e8fcede552fe7": { - "balance": "12640674931821000000000" - }, - "b547e04ab8a44d3cae38704356f1f59408457b67": { - "balance": "286604155735000000000" - }, - "b562e4010a0a5fd0906a4cd9f47fc28f6f51e210": { - "balance": "1000000000000000000000000" - }, - "b584de7b38a2a2e3d9ff9c055b309ca56e5da5a9": { - "balance": "237896887904000000000" - }, - "b5c1129961c4a43673324aaedb8296f5ade82516": { - "balance": "4213058948283000000000" - }, - "b5da6711c72bf27c87923aed4a39349b4192e6b4": { - "balance": "55180742586465000000000" - }, - "b5eac5e7e03b9d31e40393e16e956cd588cb7566": { - "balance": "4508019435556000000000" - }, - "b5fd46ee4e02946dca3485439f98bdab290c82b7": { - "balance": "108321600045000000000" - }, - "b5ff2a3caef6ec30365f4f0ecbecbdeec1cacbba": { - "balance": "979696597242000000000" - }, - "b609d05242f7c13a4ae4036f6da9c0bae18dd70c": { - "balance": "229121731278000000000" - }, - "b611156a2f87fb45c431a5cf5740ded90c2dc542": { - "balance": "401783365700000000000" - }, - "b61c7623144afbd0f6cf44c951e4219ef8096119": { - "balance": "36000000000000000000" - }, - "b61cbe0e58ff6fa4c810ad03c759c79d9ff052a5": { - "balance": "1034495371371000000000" - }, - "b622bb67e95a03f58dc9aecf82c217e86f2cf7c3": { - "balance": "500000000000000000000000" - }, - "b62a50be3ce0e7cf8f61991daf8fa7e23775141e": { - "balance": "1000000000000000000" - }, - "b63cbff6b1747ad5cda101d5f919ce81dd67e363": { - "balance": "2570089937000000000000" - }, - "b65e80551a8687c9cef2d852949177c0e3b56e51": { - "balance": "100000000000000000000" - }, - "b68126ebbcb5ab9b0371b62597a38d5c1685b0df": { - "balance": "671140851028000000000" - }, - "b69f5830c371cad5a74ae823eb8892d153ef3c23": { - "balance": "18446744063709551616" - }, - "b6b4468c4db64e0b85cddc251d02f32fffcd1f7c": { - "balance": "10308006217291000000000" - }, - "b6c129312505e571148dbe69833d30550efc12c9": { - "balance": "5105834767567000000000" - }, - "b6cee8ef00b8674a9a96447e4511b30d6564ff67": { - "balance": "667754569888000000000" - }, - "b70f805aeba260d44f0730f0a9dec60f2b4f54a1": { - "balance": "2751303297000000000" - }, - "b71a901dc4b6c6463f7d221f868677bcadbcc680": { - "balance": "169000000000000000000" - }, - "b7385bd8f8257331f4c7a87c7a23724f615cff8e": { - "balance": "196000000000000000000" - }, - "b755692bc027e30730dc1d0e0b2a883830a84115": { - "balance": "30713083153428000000000" - }, - "b765305dda3c1e069a7a022ec127ff2140d0a820": { - "balance": "603122990932000000000" - }, - "b77403a4c56ffc7715b4bfdfe4b054336aeca466": { - "balance": "130840969728386000000000" - }, - "b78b2f6dc731d7d84b7eea151805f9208a1d0cf0": { - "balance": "142084687500000000000" - }, - "b792a0fd762c002a7585cfdefd36cf7ffb42fc05": { - "balance": "10000000000000000000000" - }, - "b7ccd7164aa7fb871726d9d043a8f8f890068c0f": { - "balance": "1170997140237000000000" - }, - "b801f49018317caf30f310dbe116f4e876184874": { - "balance": "50000000000000000000000" - }, - "b81ca2bc63cb4008cebdda3ce8f4eaba322efca6": { - "balance": "4678481047354000000000" - }, - "b82e3d50bf8c5b471c525ec8dd37b06688ed6178": { - "balance": "1202448975553000000000" - }, - "b841162a7a8876296f10794d8847d8095426aa54": { - "balance": "73500210754000000000" - }, - "b8421d375c3f954e22b6fd304235dd7c43b68bd0": { - "balance": "6499782706009000000000" - }, - "b859b76d77eb604728093c61fcabe6f9d22433b0": { - "balance": "196000000000000000000" - }, - "b86536268ace9be93a1db2012d6e3e59023ef2cb": { - "balance": "52878034904067000000000" - }, - "b87e1ac4fc423ab37e10ffd221df8056537b1d03": { - "balance": "119159824674000000000" - }, - "b8825a99806c5a968423e69d22f2b61a2f0ae9e4": { - "balance": "999999999580000000000000" - }, - "b8835acaf63e0e5d41fb743eb0f954040a38d381": { - "balance": "64000000000000000000" - }, - "b8844c74b227781d4b3fafd32e39ff6fa9857f77": { - "balance": "490694157000000000" - }, - "b8962e8bcbcf0f69144f8fcd2ec3ae8e54c05034": { - "balance": "1425313342735000000000" - }, - "b898b4ece8e0eea375f6eb85615652cc5c221593": { - "balance": "2284038029169000000000" - }, - "b8a949bfd9751c29c4cd547cca2e584d8dac4e12": { - "balance": "50000000000000000000000" - }, - "b8ad5ce2ae781e2d245919c15bbbc992185e5ada": { - "balance": "733786526623000000000" - }, - "b8cb6a9bc5a52b9cfce26869e627b2af0ff5ed4a": { - "balance": "98364826821577000000000" - }, - "b8cf6aac7b9028649f0d55a57b61640d70cef120": { - "balance": "104799890645000000000" - }, - "b8e827b5d1e10a3944039adb1a3dd7ff6949145c": { - "balance": "172413427060000000000" - }, - "b8f6d7f33ee5755ba56647ab8fc9ca27b8aba677": { - "balance": "1430769696978000000000" - }, - "b9221177e2b09725bc95f08c72c17c42887eea62": { - "balance": "1212779749827000000000" - }, - "b936e0d83cde9bb810b85ad58eb5ff0fa9c11654": { - "balance": "4999580000000000000" - }, - "b961d435c457e205fdbed5442c8614ecfd59616c": { - "balance": "27847452621284000000000" - }, - "b969e9d89f32002cd4f90ef5907bebbbdca6fe6a": { - "balance": "12455448454838000000000" - }, - "b981c9137cfca5389f0123927852278d2d7ff618": { - "balance": "92180707865000000000" - }, - "b98abf0fe91b0d3a16c6ed37aea446baea33fd23": { - "balance": "560454425563614000000000" - }, - "b99ab4e6ae277b9fb04537adbb781e8390b490ad": { - "balance": "32814665223319000000000" - }, - "b99d0a433d7994743dd675894c18ed03164436e1": { - "balance": "16000000000000000000" - }, - "b9d8b6f0a505d217709bb9327f3b9b3f84813e00": { - "balance": "81000000000000000000" - }, - "b9dbd64e3c8e6ad84c9c67c66e678c06ea7bcb91": { - "balance": "1161140466507000000000" - }, - "ba361f7a6dff16a96f957c63e08267dec8f9ecf7": { - "balance": "2170060167590000000000" - }, - "ba47f4136f74b566f62ba373651332b59e74e1db": { - "balance": "906249296535000000000" - }, - "ba5287cf15de91daeaea2465da4d4c1a14dea716": { - "balance": "98978398162000000000" - }, - "ba77d056d52f84e740579aa527792f826591c858": { - "balance": "50000000000000000000000" - }, - "ba895406774ced5fd2e759b58f9ffaed5e04fb14": { - "balance": "10000000000000000000000" - }, - "ba96fab21a4926fd1137558ae996b52ec14538a6": { - "balance": "10000000000000000000000" - }, - "baacc247801eddbf152fd6ec39d659f265935743": { - "balance": "2661902597584000000000" - }, - "bab2eb9fab8e699a958699b15ddc7ada5428d33a": { - "balance": "27006404153000000000" - }, - "babeacd7933c817472875c86bf126e6d11886f8c": { - "balance": "2461234517292000000000" - }, - "baf7021d4d754d4478d3c3624c2376e3f1d4ee5e": { - "balance": "1352066301857000000000" - }, - "bb0760bd1da973d8f70dd0caa6cadfcfd8199231": { - "balance": "177674700430000000000" - }, - "bb278c6a52eebd0b8950e9b78ba211453ccb1b6a": { - "balance": "25000000000000000000" - }, - "bb327e5f260b2dfe25fb180c2d3f4b63211c1dee": { - "balance": "7694972715000000000" - }, - "bb643e768ab20c135e7df3f400284cf04c40a6f7": { - "balance": "385756449779000000000" - }, - "bb73d1d1c289b4953d0033b52d9d2d0d92573d22": { - "balance": "11000000000000000000" - }, - "bb89936d562b19e4c599826ce7cd0c60cb02b512": { - "balance": "725910446589000000000" - }, - "bbc509b7999b0e94534477b98ec8927cba879677": { - "balance": "20000000000000000000000" - }, - "bbcfa9ab62f4eab14d6a1b09c1aa554dae113183": { - "balance": "589417352665000000000" - }, - "bbe78301134249b52b74d73ee3855e7e3d288a40": { - "balance": "4456159000000000" - }, - "bbe7bb4c4f1b506b58f7e3334e6c89011cf2d6a7": { - "balance": "3889127030000000000" - }, - "bc016690596e077273465d1728d18553b185654c": { - "balance": "185932953686000000000" - }, - "bc16b2ab9c7ab309249f93b496b75c6a7392cb10": { - "balance": "5000000000000000000" - }, - "bc254e5405b154b98abb5fe5508d3e7c98663f4e": { - "balance": "144000000000000000000" - }, - "bc258aeb0f18150d3ca253c6bb04f63d657d99ac": { - "balance": "6011905701701000000000" - }, - "bc2620b5ebac12a88b287b625fa5b336568e7869": { - "balance": "534886892259000000000" - }, - "bc318687cfaae2be4c5ece4a18bb9252486a19d0": { - "balance": "147226513970000000000" - }, - "bc32dd123fcc2ef0dc36484c3ab1bae5d9890761": { - "balance": "16000000000000000000" - }, - "bc5c5151be06aaf6180bc9c1058b181a5a30366e": { - "balance": "113865120384000000000" - }, - "bc66241ca430dc31a3e2f44dedba868e16b9a6a1": { - "balance": "50000000000000000000000" - }, - "bc7c371af0688b1c409f4b07662609a1c9efd120": { - "balance": "20000000000000000000000" - }, - "bc9454f7efc86e25d18a8e8b6e230de42a51d967": { - "balance": "148103676062000000000" - }, - "bc9d5456b975bf0b95c161c3355e4ceb28898fd9": { - "balance": "28083912047000000000" - }, - "bce0b47bf13e4517c53bbbe6e51544b99f3147f6": { - "balance": "919711480389000000000" - }, - "bce2d1ec7c41b426f72b352f5f2b7da3edac4157": { - "balance": "908085365725000000000" - }, - "bcf0756789a57f16206dd78bf6e1322ba9b9b85b": { - "balance": "110888224252000000000" - }, - "bd0bc4a0730f9f55a2f65f62662c7553db52238e": { - "balance": "8440290043000000000" - }, - "bd29fda37c2581a3f040c77eead3143cff24a346": { - "balance": "126022762542000000000" - }, - "bd4c1270322a26a1b825040b239008a447c31918": { - "balance": "727012140904000000000" - }, - "bd6a3da2db66dc9fa26fa2b63b14003d26ef91d0": { - "balance": "5492112771780000000000" - }, - "bd80fcccac60078fcf09f5bddd8a25a92fb9cfdf": { - "balance": "10000000000000000000" - }, - "bd92dc94b6e81a3da5dc3ae6bd80782622658196": { - "balance": "10000000000000000000000" - }, - "bdb35c2c595fe7a2864ebe20dd56d6ddaf9d447c": { - "balance": "4346566125000000000" - }, - "bded4718cbad2150c9b6df9ee7356e0f5c713cea": { - "balance": "311694803600000000000" - }, - "be1804630ecd95ac411b935566cecc5a24c6f18a": { - "balance": "85033246331000000000" - }, - "be2318ad50b0a85b95870a81dce5c31029636159": { - "balance": "5185298019030000000000" - }, - "be3de52fc1119f02f4707f353c040b7c4222d847": { - "balance": "25267399461000000000" - }, - "be4feae01d429c872601ae84dfae8fddc3372686": { - "balance": "20000000000000000000000" - }, - "be7c09d704d16e4b2c9e19cc8c07808bb335f926": { - "balance": "25000000000000000000" - }, - "be873a9525899bdad5e4376b0115950e534dea2f": { - "balance": "404116929377000000000" - }, - "be891b1680ad835aab1ac05a30c0813306cf20f2": { - "balance": "144000000000000000000" - }, - "be8ed2d85a5e3f83c6105db1a1f304e9f174bfce": { - "balance": "50000000000000000000" - }, - "beb1cd80c2f8fabc27ee3a3b2a15e35fa52e7879": { - "balance": "11539095431000000000" - }, - "beb67375e46950830906bf281209be133075452f": { - "balance": "1305262446956000000000" - }, - "bebe54437722c6000bc6a8843f159538a2abf613": { - "balance": "41042548942568000000000" - }, - "bef2a05e283ae948efa9b0e3a6ab5d26a57f1de0": { - "balance": "180614450853000000000" - }, - "bf03950f265a4182b4402703723a0311158eef4f": { - "balance": "158997402149000000000" - }, - "bf06393654baa1ad15c2e717e06dbaa61834c214": { - "balance": "34409427774000000000" - }, - "bf2b867313a44bd04aceaa644771d1e95317c881": { - "balance": "10000000000000000000000" - }, - "bf350ccad91a2a2aff4cf27a291323a297a78009": { - "balance": "124593326152000000000" - }, - "bf3d86edfcf52733e91a9c59be606a95bd921885": { - "balance": "20000000000000000000000" - }, - "bf5b21d5e339752b33b180064d0e6047338650a5": { - "balance": "1000000000000000000" - }, - "bf64c2715db8f353600a45b9264e1f22a40ef8c1": { - "balance": "2952972677360000000000" - }, - "bfaff32c8b04a61658ff94f94e4687232b8d2d7a": { - "balance": "1117691379350000000000" - }, - "bfb00182321502e0729d9a0862ec1df1b3e2208e": { - "balance": "500000000000000000000000" - }, - "bfcdfc9f60610f0ca279ca2c89b9af831332aece": { - "balance": "1431082635308000000000" - }, - "bfe14356e86f6b2ad470bc77d250517c8dc03d15": { - "balance": "310115085185000000000" - }, - "c008bd3fb881da9dca4cadcc56b1d99c56db9abd": { - "balance": "12899598792000000000" - }, - "c01efea456d30360a78ee10c790d46bcb889ee61": { - "balance": "103203021492000000000" - }, - "c03d622627bba7d5db1a9f699924e9d5ff5640f2": { - "balance": "95102233308870000000000" - }, - "c0465ed806ce7ee730e5b6eb7b86a754bfd196a9": { - "balance": "1654379359619000000000" - }, - "c061c5b0d0ce7af95ded1805abb23f743e13c455": { - "balance": "500000000000000000000000" - }, - "c074f2024f79cf8d7aab2d858dd110fc2ee89d41": { - "balance": "18382732686000000000" - }, - "c085147a76d0336b4bd6e7d5b60d394bfd3c6f42": { - "balance": "3236912707535000000000" - }, - "c089416d2d679cb2abf44251de227d0a08fa1206": { - "balance": "497124416350000000000" - }, - "c09d8cfd85989397dc723f2df821dbfb2c0c39b3": { - "balance": "833485701262000000000" - }, - "c0aaf130e3b67250d9775d62e7cd3963daf0a627": { - "balance": "1249947125780000000000" - }, - "c0aebdb5c2e8c5ff9870535c738bfe892c9365dd": { - "balance": "360097616959000000000" - }, - "c0db5680ba88052652bfd5a617c4e8a5be188077": { - "balance": "509051625766000000000" - }, - "c0ee350e5e09a2daeff332a66a6e117fad102112": { - "balance": "10000000000000000000000" - }, - "c12c0a3fd42501f8772e4ad5d262eef3f0bc4701": { - "balance": "120398848512531000000000" - }, - "c135b48c7fd11670bbfba923b28767d21d7923ea": { - "balance": "20000000000000000000" - }, - "c1397c66b7f150c0062b0e87c981c107d771b109": { - "balance": "87751498250000000000" - }, - "c1507ee435cf506fc5d8e4cb62515f2ea0f3a7ae": { - "balance": "4935384099000000000" - }, - "c150d185e2cf203054a6e328b72d8c35bfbbcc33": { - "balance": "21044148271000000000" - }, - "c163098f8b8f0736862274860b3842cf14bd2288": { - "balance": "119025568966000000000" - }, - "c1687fbbc7d504b73fe3e71af440b3dec0da88b2": { - "balance": "229520711528000000000" - }, - "c172bf224080d448261b3b66453074b28628daf7": { - "balance": "7903438287958000000000" - }, - "c18e9bc05dfee2a39fe2b6778a24a48d5bf0f141": { - "balance": "500000000000000000000000" - }, - "c198fec4069c95300d34b9c7109d7441b8e62745": { - "balance": "50000000000000000" - }, - "c1b4134f4757d19a687d05bd7087872b5625405f": { - "balance": "20000000000000000000000" - }, - "c1b43ca2af534ac6bcad8f23c30c07ba07e7e8fb": { - "balance": "194999622000000000000" - }, - "c1c2249507d2dcaf4a9103fcea2cfb47aa4957f7": { - "balance": "571416394325000000000" - }, - "c1e90af40fb64427aeb79a13607debbae9270b52": { - "balance": "50000000000000000000" - }, - "c1ffc8938f3412d19d428b8450f17fd394ae539a": { - "balance": "36000000000000000000" - }, - "c20013e25ae53d0d41bf365aa767822bbbe70936": { - "balance": "10000000000000000000000" - }, - "c20e9eadffa5529ce58a39f5898f39906dcd4b78": { - "balance": "757301065305000000000" - }, - "c211fc2623d51846d26952628d140643efa5156c": { - "balance": "865384323985000000000" - }, - "c2546c312570b30ad2ed05edb13b6469494c5b92": { - "balance": "5000000000000000000" - }, - "c25b2280ed0f835538f8ffd9dfc08a3b853f1ccf": { - "balance": "1000000000000000000" - }, - "c260e43b89a7a4e84bcc4c21dc43d4b5e6923f3a": { - "balance": "1000000000000000000" - }, - "c26aeef0e1f382c88bbdb1eb8c01afa7f58218ce": { - "balance": "79774757760000000000" - }, - "c27dd2645254bc30b6cf7bf418803b02ac808b5e": { - "balance": "4419594173874000000000" - }, - "c2b4f6cf92d6d63a20034e409a358df1803159b8": { - "balance": "1630820442000000000" - }, - "c2ba4a7ea6ca2d17231fb17ebd5dd2dfc0964de4": { - "balance": "221662324727000000000" - }, - "c2bc18f24b8097208a8b2418c444ea58beb94281": { - "balance": "1766754009521000000000" - }, - "c2c028dd17f8a89b9131b7daaeae9cb1dddf86e7": { - "balance": "10000000000000000000000" - }, - "c2ed78a0cb850c12ce8e6ff3873e8c18ffc9f4b9": { - "balance": "1017518755567000000000" - }, - "c2fd7296210b7013d476205d2517d51b21c9e76c": { - "balance": "500000000000000000000000" - }, - "c3041d3d650ff6ac3e35b60371b6798360727651": { - "balance": "1011071365226000000000" - }, - "c328ab9ce1fddd5623e0383828714a7e3ff12eff": { - "balance": "285042661579000000000" - }, - "c34ab008ddddf376dd866cccae4a4d6eb88403e2": { - "balance": "2798642711076000000000" - }, - "c3511391c4515cf8f27e9bc0f777a02a4125c8b1": { - "balance": "20000000000000000000000" - }, - "c36916a9fdf656bb1a8c2f7fb752a3489020f6ff": { - "balance": "689483152953000000000" - }, - "c37598a388d6f4e8e046923265ee9256456e40ab": { - "balance": "62865106394696000000000" - }, - "c38813db256eb221a7142d042b81ba2babab2c31": { - "balance": "98477603778000000000" - }, - "c3acd30f0bc3146fc2cab8d54904f98289021374": { - "balance": "17820000000000000000" - }, - "c3ede34dc1cd995fda1c5cb6e9ffd0c0da080587": { - "balance": "1080428143758000000000" - }, - "c3f04dffe2be55a1d6cdaa78e5c09a79d0477e7b": { - "balance": "59747493842929000000000" - }, - "c3f09f681cfb57d3cabc547dc32a71d2a6585c1a": { - "balance": "1757648436173000000000" - }, - "c3f3bb6444d853614f18c04a3c81f7d26e62e96a": { - "balance": "9022830778000000000" - }, - "c3fe4534327a2fc4144e2d3d3392f7b78d2aabc5": { - "balance": "1759225739027000000000" - }, - "c424f5be9490ec7f0f1e2debc3f72bd83e35f587": { - "balance": "1774372626989000000000" - }, - "c434f64eb937207f80e9a02d2f77ca34bfc63aa2": { - "balance": "960850858644000000000" - }, - "c438b6fa5801a4b8dea450530d975f174cdd47ef": { - "balance": "64000000000000000000" - }, - "c446effb984ff3e5ed92280e7b3dcdb1284230b3": { - "balance": "503490303680000000000" - }, - "c453ae9f94253ebdb871e9dac19056b13d1747a3": { - "balance": "1621494076559000000000" - }, - "c4a473b5e3a6bfb51f963d4dcf109bddedf4fb43": { - "balance": "104273242373000000000" - }, - "c4b8058e9e5416e526ea16e37f29dc221d28a003": { - "balance": "1833513486496000000000" - }, - "c4c09f4bbae0ee06f2a52ff0ef0de1978b5305e9": { - "balance": "20000000000000000000000" - }, - "c4c5981f5ac0a9a3701663b887c4aaac3a3a4d1d": { - "balance": "1411640000000000" - }, - "c4f7a493d16aab4d18e88e530e75e3095a3439ee": { - "balance": "191606419322000000000" - }, - "c5259c18bbd8b0485ca83d069d5ac235b28f24ea": { - "balance": "1276479076242000000000" - }, - "c526ef1124c7d0549b117e7b7463539a24209290": { - "balance": "9106523141000000000" - }, - "c5278b9eeff2221604f30f002c307ca2882fba97": { - "balance": "20875716591000000000" - }, - "c527ca73562846de9fca1649fe5144e5068a2f6e": { - "balance": "25000000000000000000" - }, - "c52a960c5df55169ed5d5cb0109a576321ab82fa": { - "balance": "1097338876493000000000" - }, - "c533ab799e5a04e0ba4e4780d632e0044262d216": { - "balance": "200529941482000000000" - }, - "c5389e3ee2f043ac2b6481f254440a97a9cf3bdb": { - "balance": "84047554571000000000" - }, - "c5594292b324c1d63f797c588a589c895c680ed0": { - "balance": "334298857161000000000" - }, - "c55d7ae4f29d857182d5f1ac2a78cbf35a694dc2": { - "balance": "500000000000000000000000" - }, - "c55ead0ece8fcfbecc573666c0170228e089aefb": { - "balance": "438775082956000000000" - }, - "c55f7d73491cdba391b631581029de32755a09b8": { - "balance": "1340000000000000000" - }, - "c56cb4e8308d6462eded0bbc74965ee135e23e11": { - "balance": "568187503785000000000" - }, - "c5b0c5f840f579536d5977a77262458d72ef1490": { - "balance": "5880686297881000000000" - }, - "c5b129c764daac8bfbf023646b9306d817a8ebdd": { - "balance": "10000000000000000000000" - }, - "c5bba43db949e2ed3de3036caf7a6e42558b1ef2": { - "balance": "763947031151000000000" - }, - "c5d57171e5b9cbafaba7d2c13cca3ec9d81bda49": { - "balance": "25000000000000000000" - }, - "c604e6c539c857ae9e60ca20d1906308ba431892": { - "balance": "100000000000000000000" - }, - "c607bdc5ad2f189e9356edb4d7975c7ba9300836": { - "balance": "55828814399000000000" - }, - "c60b0d2341ecada6c3faf1efcc9027125d99e17a": { - "balance": "121000000000000000000" - }, - "c61e1b993c3fd91a1023ba5b92d06a0aa539d92c": { - "balance": "23863993763643000000000" - }, - "c624656ee5298786cb3d0de045b0ac089c5341d6": { - "balance": "2210389938000000000" - }, - "c6573a023d6f4b5e151f266af4ec0045df0d1518": { - "balance": "52505006485983000000000" - }, - "c66b1d84c42018b16dbc4777409bf50a49febba9": { - "balance": "9078953000000000" - }, - "c69e4de93457f251b1e0879b5250b26e57839fec": { - "balance": "500000000000000000000000" - }, - "c6c51205c9f0bcaea05dce8e47e91d94a3f63c2a": { - "balance": "2720612321571000000000" - }, - "c6d237e0936c4714e701823aadb368fdc471451d": { - "balance": "541700595551000000000" - }, - "c6dcac15739872089cb3d23287e8cd546487ecf2": { - "balance": "1023857245227000000000" - }, - "c6f40b81a5860dece34305f53570be61cdf9a8fa": { - "balance": "20000000000000000000000" - }, - "c7147a95cc4f6bedce6292e8f95539caf550e9d6": { - "balance": "20000000000000000000000" - }, - "c7185b1a680d8b0893065d8213de54375d086420": { - "balance": "11564622085000000000" - }, - "c71b3876613c928197aadf3dd7888db3665f28f0": { - "balance": "112276274428000000000" - }, - "c72200bb380db62a3fd741713d332be77bc1a4ed": { - "balance": "6962060809000000000" - }, - "c7345cd5a7eafc9d7ebdc17d674f83e23336538c": { - "balance": "4425703195684000000000" - }, - "c734f9dc3ee2d857ac826b101129eb77a4a22256": { - "balance": "100000000000000000000" - }, - "c736fa9550b73f4a4ca0ac1cd94bf6f42ccbb11b": { - "balance": "449139000000000000" - }, - "c74128ea37f5d1ee016086a38e470bb332eb5270": { - "balance": "40479951869000000000" - }, - "c7647ec91e823cfe57e8a3433ddafd7b4f675b80": { - "balance": "307102062000000000000" - }, - "c76d49334ce25f5fc62841e5a87d4e03ab3edd9f": { - "balance": "109999979000000000000" - }, - "c771093ed5c4df518536b76e013e8142ecc3f9ed": { - "balance": "5247752820195000000000" - }, - "c780dfb4cdcba4dc89245a8be8a93de1a3e82d3c": { - "balance": "205580199482642000000000" - }, - "c79c6c3a0a46052f723a26b1f107a332474df3a1": { - "balance": "50370325181000000000" - }, - "c7a4e02d2c0f00fa56662cc9f323cabeff82759f": { - "balance": "1163435680762000000000" - }, - "c7c0632cff11812130c30163c83746839a625f95": { - "balance": "10000000000000000000000" - }, - "c82238664bedfa8ded51e91969a39f13a8262a37": { - "balance": "10000000000000000000000" - }, - "c877d228c350ec0d8d97802e7d874d3130171813": { - "balance": "199845203467946000000000" - }, - "c88b8a2e498fee366a1290a575a7f09da12ea8b2": { - "balance": "50895598476000000000" - }, - "c8bbd0e52b11ae6a20adc5f6bbe4d34d7440e8ca": { - "balance": "114566193776000000000" - }, - "c8ca2bd1bef02b505f0333996bcb6bf730648390": { - "balance": "1177250974576000000000" - }, - "c92c3358910418fdb3950e1a378af7246553ae38": { - "balance": "81000000000000000000" - }, - "c9325c9b6d2af226bc5ae1cc975e00cc11274cd1": { - "balance": "2927587698197000000000" - }, - "c95ae8dbc8bb075e7dcb2b2c6d9411bedf26244e": { - "balance": "931878010706000000000" - }, - "c98fc33c1d980052d75fee8b34d08796734b6a4d": { - "balance": "8671327034000000000" - }, - "c99fba8321d16cb19c55703b407c54ed106dcdc4": { - "balance": "20000000000000000000000" - }, - "c9a0da2a3be799e751738e61b9cc376eb06e2b00": { - "balance": "50000000000000000000000" - }, - "c9afc551058c32e89bc2d6704d0d00e92f5ef6d7": { - "balance": "11135553563900000000000" - }, - "c9bfa2ad4b3e9c624255c6ede116421b04487d65": { - "balance": "105514983171000000000" - }, - "c9e4b61d8ddeee339e31ba088efb5d608c3464a5": { - "balance": "20000000000000000000000" - }, - "c9e9090d9f95f401c87c7240f3bf88ca9b540f8b": { - "balance": "553735838243000000000" - }, - "c9fd40bb35284e3d7f0dd3b43a1d9e958f7c86e0": { - "balance": "50480449695128000000000" - }, - "ca038c7c9e66531ad79e4d67b42d7920b7f05c26": { - "balance": "64000000000000000000" - }, - "ca0d08f6019884f94f2b5b191ac9bb247150cd13": { - "balance": "25078089364984000000000" - }, - "ca2c6e6ed3d6a1d030807f91e1fd5c79d36af86f": { - "balance": "849454139892000000000" - }, - "ca7c7bbc24cac0f3aabfdccc77df21004672e634": { - "balance": "6952718700000000000" - }, - "ca998c74383b55c8dcddd46b49f95456fb056b7a": { - "balance": "2000000000000000000000" - }, - "caa989e6a1e934532aaae6cad282c18b1a0b9fd6": { - "balance": "2335540529729000000000" - }, - "cab32ee5cce74e0ee88bbd4b505aa587ef2e4bbf": { - "balance": "75914058971000000000" - }, - "cabe9f0d0a18de8d3495dd063b04c6a33584a8c1": { - "balance": "116083536145000000000" - }, - "cacde94daeafc06e46c86b1e20387a23d909ace8": { - "balance": "1521003430346000000000" - }, - "cafbad01b81ad6cc401883773994a9dd6e6ed913": { - "balance": "10000000000000000000" - }, - "cb343b882cfe866f73cd5f0f31fc68cebaddd882": { - "balance": "221801563082000000000" - }, - "cb3a7aa2e97517b6ea8d9ed0ac270a6a9cc6e079": { - "balance": "958830201738000000000" - }, - "cbd2c4916211ab2c234bc8a51e6f680b59aff782": { - "balance": "24279462419000000000" - }, - "cbea4ed5e8d2ffad442e482fa5f8d551ef2a58e6": { - "balance": "26730000000000000000" - }, - "cc001ce4f4417505116486bed9fdf04bf97ca246": { - "balance": "31740534557000000000" - }, - "cc0b53b26b6dee9f8226f25b834085bde13f5eb5": { - "balance": "132440104515963000000000" - }, - "cc174862456f02f349303d1b8328495de8ccd789": { - "balance": "155951512603000000000" - }, - "cc2af3921727d6d2de31d5f656f837a5475de6cf": { - "balance": "10000000000000000000000" - }, - "cc3201749f55f0d7b450110bc11f65b1ce165d2a": { - "balance": "123428947550000000000" - }, - "cc3f37ad6b449e39c544e26bbdf4d7be66b9dab0": { - "balance": "348574664284000000000" - }, - "cc5b36c9ecea12ebfd0721a58ac11b0c340a3f44": { - "balance": "384197170701000000000" - }, - "cc5b410c7797faa05ac4233eb31b468ee4bf279f": { - "balance": "10000000000000000" - }, - "cc60b223554cc6425374c5e2424df7007621368a": { - "balance": "1128118098000000000" - }, - "cc7027381d98c2e883c82bb9c2f85b985e1e7b4c": { - "balance": "1370000000000000000000" - }, - "cca378f16e07258b9c15921233110fb4729645d2": { - "balance": "151974946930000000000" - }, - "cca781d996c3ef985bf7d2b4d68d55f52efe1905": { - "balance": "2217463190039000000000" - }, - "ccd0b9f6ffb0383553c355c6a14be1200966d47d": { - "balance": "12917165349191000000000" - }, - "ccfa4594129bbb9d07cb4ae8dc2b1c8f3bf98508": { - "balance": "524845286088000000000" - }, - "cd19c879df458106d179bbb5b7f44609d68e6e5f": { - "balance": "8601633489844000000000" - }, - "cd1c55037a0570e8f9aaa95ef157ae81a1969250": { - "balance": "10000000000000000000" - }, - "cd1e47695b0fc93b82cffd0326852dc04d8441f0": { - "balance": "144000000000000000000" - }, - "cd1f90c388d76b3aeaf77850f2191f12a2311f51": { - "balance": "1728456799866000000000" - }, - "cd3aecd58de07f80b64044875fa6ad4f18f72789": { - "balance": "2648597880142000000000" - }, - "cd4f39123ece1e0ab52cfa2a5d059b49c4d63c3f": { - "balance": "1661718859439000000000" - }, - "cd6ed2f7ab49515f8fd70aeb4d72bfae8956b5f1": { - "balance": "183807926254000000000" - }, - "cd9d9d07fcf476a8ee7240324a602449606d75f4": { - "balance": "100000000000000000000000" - }, - "cda66d375a10a22f13dff8a9c40b63461daddab3": { - "balance": "1116940051064000000000" - }, - "cdb0832ee5b26da24b1775c4cf0dfd669b94ce00": { - "balance": "23919219542965000000000" - }, - "cdba5805f17df1f3e47647464de978944ed36b62": { - "balance": "4204539000000000" - }, - "cdd1df8bd54941e26ea26eebbd537e751f64f5f7": { - "balance": "5000000000000000000000" - }, - "cddf5b34342200c37ba96eb0dd662ca4c29f89f8": { - "balance": "10000000000000000000000" - }, - "cdf6c838980afd91a600e3fff755a4848d138568": { - "balance": "25000000000000000000" - }, - "cdf7f55a5a16572d2f2bbf7faeffe3c4d64f86ab": { - "balance": "3115969322502000000000" - }, - "ce0f1dbbfa3490a21ee4b28232db612f44bb7bf1": { - "balance": "9227310122000000000" - }, - "ce33184573c33dd859450304984fa63ea4f2b62d": { - "balance": "7055925237496000000000" - }, - "ce33a3db107f01c51d30b24a8db80faf05308bb7": { - "balance": "10996113113089000000000" - }, - "ce4922b3daef62914f0580a55c524e6a02e31d83": { - "balance": "5541295938315000000000" - }, - "ce4ce8a8540678dda16380c211482dd8c8b71092": { - "balance": "6224176337062000000000" - }, - "ce62cfd71abb9979a0acc398c17dbb5cb6da4721": { - "balance": "13448605175000000000" - }, - "ce724bb30c7821a9c847e0a3e9c12843c3471f9d": { - "balance": "252657175031000000000" - }, - "ce8af01494c2c5b4e74bb02dc6de982e7234fed2": { - "balance": "77349533545000000000" - }, - "ce8c774b7f92045faec43e9cc1711224a3b32435": { - "balance": "370287579971000000000" - }, - "ce8c9ed5018559f36ec72e5a9b0701724e498b51": { - "balance": "142866501748000000000" - }, - "ce995c13568a8b1521d4c9721cfc11da4891860b": { - "balance": "1000000000000000000" - }, - "ceab9dddc767a9651e98527fcf51f6e85c9ae402": { - "balance": "5251411770975000000000" - }, - "ceace25f8c7cf853500a461df007f9c9703ac4a5": { - "balance": "1428847332255000000000" - }, - "ceb0c49dad36f6169ec82a2f0d80da36c87e4209": { - "balance": "459821324064000000000" - }, - "cee8083233bcb4d50ddbf2121c90b5c2019ca58d": { - "balance": "557985245088000000000" - }, - "cf0c6bcc66eb75899bc7f8ed4b8d2b29437bfe85": { - "balance": "3252418478000000000" - }, - "cf32c5bf1d7ef0cb0f2f190f8468b01a4f2d93e2": { - "balance": "6593164924646000000000" - }, - "cf6e47463382153fcf0ec6738880925dbc08116a": { - "balance": "1091910654350000000000" - }, - "cf7539096fd0cd97cd316efcfe9d3c87a101a74c": { - "balance": "741847588809000000000" - }, - "cf9439bf2fbab65cecd783e135a37127f585f1e5": { - "balance": "50100000000000000000" - }, - "cf9bdc902604fab070c611ebf6a989ac4a785c82": { - "balance": "1501000000000000000000" - }, - "cfbbefc0e6013fa2caeabc54ac05f45dbf17ca13": { - "balance": "230809632301000000000" - }, - "cfd53f18ac7d94cadd032a0f4cdbdffaf4765d6e": { - "balance": "64000000000000000000" - }, - "cfe66dc4aa9ac9c9f87fdd05c1b2b95da5211703": { - "balance": "1656993051100000000000" - }, - "cff376eef4d69c4a47d6c7916583228fab3b5967": { - "balance": "5904462494391000000000" - }, - "cfffcb819302d05ed763026bdf84b48818938fb0": { - "balance": "289619807900000000000" - }, - "d000aa72a77d55911a5e66c2906da9206db86633": { - "balance": "3008989624945000000000" - }, - "d02d7b42213e873f91e789cbaffc734ffabd1087": { - "balance": "144960809826000000000" - }, - "d02db5279e918b3e93ff81d00d4025cc71dccaf6": { - "balance": "2386625717975000000000" - }, - "d0802cbcca2bb516f251b873eb20bb5e94af7f37": { - "balance": "9287997718210000000000" - }, - "d0c07380308972a36f57d1cd9081d7389d0421cb": { - "balance": "1280367167470000000000" - }, - "d0c131c1b60891b91e58fbed787ee4567e3f2038": { - "balance": "6360752089492000000000" - }, - "d0c71159d46c4d2af7699f682a055c79a1a68a0d": { - "balance": "1527974433762000000000" - }, - "d0d5d9f242f2613079b3b443c359c2e18ed5faab": { - "balance": "637334647476000000000" - }, - "d0dd208ce92da02eee3ee3de335e67f819581a33": { - "balance": "100000000000000000000" - }, - "d0e55ec0ad0f8986dd9fa9d738007c5bdc22f840": { - "balance": "53012893797000000000" - }, - "d0f222cec657ee444e284c07228d585155b82c0a": { - "balance": "7368748129592000000000" - }, - "d11efb07887d8b5b87a77d8fd388190614e8c077": { - "balance": "4703283503278000000000" - }, - "d129f1b89045ebfb4d1df1d9077e9359fd2990f7": { - "balance": "14496053137000000000" - }, - "d15a509424c4e04868bdcf59cbee09882ba04c8d": { - "balance": "65042393236903000000000" - }, - "d162416912b03fa65f3972a63e357ceaa3b621f7": { - "balance": "325650177224000000000" - }, - "d166183164b81bd049b2146a3ccfcc78cc6a0bdd": { - "balance": "1000000000000000000" - }, - "d173d759f0916e61400d56ca690cbf1743fe27b0": { - "balance": "53550838679000000000" - }, - "d18dc883e3881bf4c7db2afaa097bc2d33656724": { - "balance": "5000000000000000000" - }, - "d19dc9b5ae689dea1ccbfea8b44ec6034559e326": { - "balance": "135552499885000000000" - }, - "d1c79160d0b8c1a1546b86db5123e87645a45d13": { - "balance": "10000000000000000000000" - }, - "d1cccaa22259c547993df3c147d5b545f003adb8": { - "balance": "10000000000000000000000" - }, - "d209c9f32f3292ac4d15ef353fbe6f6efcd4e49d": { - "balance": "81000000000000000000" - }, - "d21ac89a20d67e309f96f64adf05fc48f55918a9": { - "balance": "500000000000000000000000" - }, - "d21f6e7adbf480600295af683091f9b9833f5330": { - "balance": "1229445878922000000000" - }, - "d22700a47a0edb137d2f0348aa0f8d4b6dbc5850": { - "balance": "21301422923000000000" - }, - "d258ddc9372e3b70ff53da171252239655ca9886": { - "balance": "16000000000000000000" - }, - "d274c69317dd836df48562455e8f5a7bd2e47d19": { - "balance": "156091832558000000000" - }, - "d286b68a358fcf8a6cec70b83467079664632ae9": { - "balance": "90377010699000000000" - }, - "d29284915d9b924ae5673e8a4a557478f68a7471": { - "balance": "324678197320000000000" - }, - "d297e64ac2bd8e98e6d276d6fe080679c398a26a": { - "balance": "3401930527000000000" - }, - "d2a1e7b51f6b5930a0d9e2ee55736f3d83a1b323": { - "balance": "44578900750000000000" - }, - "d2c9b0b0bbe61de504e4f210c168fa5999c9c23d": { - "balance": "76537483113000000000" - }, - "d2d49f650d222ec3e2cecba163ee92f0e934ca14": { - "balance": "3312486482635000000000" - }, - "d2d803bf10ba18adef5716b4056c1b1d61c45abf": { - "balance": "964679698000000000" - }, - "d2f673b589df7ef5cb32fdeef842d48d66130567": { - "balance": "1079010447581000000000" - }, - "d2ffaceef1af3f1c3e3f35e4062cd9f9abd1da59": { - "balance": "3041453068594000000000" - }, - "d30a74f5041ec6e73d066a375a105116699ce177": { - "balance": "21814020745000000000" - }, - "d30d849a2d8ff5041304014ecf6752dc769bf004": { - "balance": "1247532881540000000000" - }, - "d3113f558c6376321691931c9b21205e31f4a56e": { - "balance": "572224428451000000000" - }, - "d314bac1bf85eedeac0b359dd2106dbae8fc6947": { - "balance": "20000000000000000000000" - }, - "d3283e17112028b324327ef64a238183ba189207": { - "balance": "136000000000000000000" - }, - "d33ce3c3b64d1b3d399651432c15ecb943d16c70": { - "balance": "10000000000000000000000" - }, - "d33e1e4b10a98e82810f6d161df5d35e5677e35f": { - "balance": "10169656674000000000" - }, - "d34699fd152fe38caacd3c096f6abb1cd79e88b2": { - "balance": "25056644550000000000" - }, - "d369c0e01b9a9d519b3b099a98fead19867c019c": { - "balance": "100000000000000000000000" - }, - "d388dcfe55a9b710d05c686f033fdbdd7861ab71": { - "balance": "1439589263065000000000" - }, - "d391a7d45c7b454b743bd867f8f62f56894f9b65": { - "balance": "484904747488000000000" - }, - "d39a75b4831543e1bc99e7a5ca8875c4f69da45b": { - "balance": "10000000000000000000000" - }, - "d39ed6978b6a90fea29e735f8ea3f1d20e0fbd15": { - "balance": "144000000000000000000" - }, - "d3a0a1a00dcbd6bc44c9803ce351a4b36a69c929": { - "balance": "191222401916000000000" - }, - "d3bf1c0a6b0470c30fc49d995025af5e6b639e61": { - "balance": "10000000000000000000000" - }, - "d3cda762bafaf204469f85e6896ec64147a3452c": { - "balance": "468094119213000000000" - }, - "d3d04d78c1ab9e6887a9467b8b1e31b5c9910e5c": { - "balance": "81000000000000000000" - }, - "d3e1bfdd9396aba00d3e78646ddcdaf139a967c0": { - "balance": "833333174120000000000" - }, - "d3e502c42ff0274da12ba87ffd45fa593bba052a": { - "balance": "100409899947269000000000" - }, - "d3e76066c2e32d9a693161de07f2d3b7e6ea07eb": { - "balance": "10000000000000000000000" - }, - "d3e8d577323d97407246b198c4c61f7943c468cd": { - "balance": "10000000000000000000000" - }, - "d3fd4d1b0edbc314b103d350fff023ab75b7d7cd": { - "balance": "84129547428000000000" - }, - "d40087fca8feb72d130bbc9622575d4987f12895": { - "balance": "1000000000000000000" - }, - "d407d4126cbf3619a422c532ccf20c3da1495dbd": { - "balance": "99622000000000000" - }, - "d41a28761c8e5de8c803813667f1dc0918a105be": { - "balance": "157507410260000000000" - }, - "d46ed38228a3c3d78065b2d8b71b325bf0f0e685": { - "balance": "6787045850000000000" - }, - "d4a7463d202e804b39a93bccd77491d8791baf58": { - "balance": "171694163573000000000" - }, - "d4c20716ff7288d811d05fd6f0696a9f5627a11d": { - "balance": "100000000000000000000" - }, - "d4d95059c808cf41e64f7f353246ffae635419d4": { - "balance": "10000000000000000000000" - }, - "d4ef925157c6d0e2d649332f44416b85f8abe69e": { - "balance": "1392945162611000000000" - }, - "d4f0cb25801794f6d803306878763e08209d19f4": { - "balance": "64000000000000000000" - }, - "d55fbebc4dcf2de6341c2325448e9c198f0f06a3": { - "balance": "14206622892000000000" - }, - "d566968c40211fb25114105e36b5a7219cde9d5f": { - "balance": "4898442964000000000" - }, - "d5817b95c6b504a6d07f64faccc9aedf408b0ac4": { - "balance": "54387832478000000000" - }, - "d59679fc40a71897065bf1b3a73f331226cdae72": { - "balance": "20000000000000000000000" - }, - "d5a7deec4a5898f094e1600f9b15768d8aada258": { - "balance": "100000000000000000000000" - }, - "d5b91c29bf772ad3ba04033dfb86b672b245ad77": { - "balance": "100500000000000000000" - }, - "d5c1a9bcc5e68b7547354178fefb3d870572fd67": { - "balance": "2252066779089000000000" - }, - "d5da2a826f5909a221bfd8561dbd7dbf4aca4c35": { - "balance": "13839784966766000000000" - }, - "d5dcc82fa169b4677a3fc26d78f38e27dcc763f3": { - "balance": "10000000000000000000000" - }, - "d5f344ee8a1b954ae5fd8fc7ac702174749bc8a4": { - "balance": "1398836216771000000000" - }, - "d61cd03afbfc1bea186e5a3a51347c2c4ee3a2c3": { - "balance": "109879472702000000000" - }, - "d647fd7ca17203a0049c28ec6759612d767cfcce": { - "balance": "162681136487000000000" - }, - "d656d14acfb2f0fbde2ed2a137a52d852bb6288b": { - "balance": "20000000000000000000000" - }, - "d68130b421b19c193d03a9017b2dc687c7307d26": { - "balance": "128569735484000000000" - }, - "d69a41f7ca76b40ee94b0d04a3780a00c6c651ba": { - "balance": "2801054372864000000000" - }, - "d69af2a796a737a103f12d2f0bcc563a13900e6f": { - "balance": "7412286547000000000" - }, - "d6a5a7e149cbccb72a50b0a3ae00e6756b0a7eda": { - "balance": "1075352201657000000000" - }, - "d6aa9957f141f0dfed77e943c39aeed978834fdf": { - "balance": "20920740110000000000" - }, - "d6e99ccb72d24e8a60f24d47afd4074b1d1fd336": { - "balance": "15415994387186000000000" - }, - "d6ea4a9dda8d5bc832229c916fa45f05f99c093a": { - "balance": "27075799893190000000000" - }, - "d71de419d746ac277baa955761cced4b34c376ec": { - "balance": "1388473506822000000000" - }, - "d71ec6b5e5d4c604f741bafde0974eca49c56156": { - "balance": "61938809628000000000" - }, - "d72f90d9879f6d2d407b4fdf5d128b98d518f1a5": { - "balance": "10000000000000000000000" - }, - "d743d7925a0cfd08150814cce8cd5d3f7099e1c9": { - "balance": "25681376856000000000" - }, - "d7575a09e7498f21cda3e9e7266b7fde91dfe19b": { - "balance": "9841565066000000000" - }, - "d75c2eb5e0a2b2ee72ef4fa7249c1a1ce03f333d": { - "balance": "134491489751000000000" - }, - "d77088329ec1e280ea7a087ad20c5e965721ff4d": { - "balance": "3949070941222000000000" - }, - "d78d564bb79ea19e4a93975a38fe0882018f177c": { - "balance": "992717434142000000000" - }, - "d78efb176b252ce67b5648e04088d12c4668aad1": { - "balance": "10070463674000000000" - }, - "d7a25e43d7d4e23744f0b10e2b4f2911fd3b3bc1": { - "balance": "1000000000000000000" - }, - "d7a941cd82f8aa63c55baa81db44bcb347b8e529": { - "balance": "49000000000000000000" - }, - "d7b34387880daede6cbdad11bb3db67daf942975": { - "balance": "20000000000000000000000" - }, - "d7bca0770e2f890c1e93c3595641241454a31045": { - "balance": "2000000000000000000" - }, - "d7cb675cea1c0dafded44f611c9c344e2a5e053c": { - "balance": "25000000000000000000" - }, - "d7e53a2d8eaefd18e02bbadb7e64906ca8613151": { - "balance": "166599594268000000000" - }, - "d8076b9db0b7496efbd198b73c4bfcf51ac080fd": { - "balance": "210272077089000000000" - }, - "d81dcf5756da397ff1f783ffe5391d1ffd4ff227": { - "balance": "500000000000000000000000" - }, - "d833c6d08f5fff8f77628ab1e86584d052976d1f": { - "balance": "10000000000000000000000" - }, - "d835732e85953baf2af9e49f770bac1caa1dac23": { - "balance": "152211441541000000000" - }, - "d84005fea447e8c6aa0b5436ad79654a75348456": { - "balance": "22563694224690000000000" - }, - "d84d9c59a445911922e88c0f22cc6534f33ca3de": { - "balance": "3054115413381000000000" - }, - "d84e69926216065749e624d87783e90ce3015b82": { - "balance": "1420803164313000000000" - }, - "d884bdbdb7e13cc523e7f192310230c7bdbb4a07": { - "balance": "10000000000000000000000" - }, - "d88eedca1dd9249702f5ffc807c1e439eee1c5e5": { - "balance": "36000000000000000000" - }, - "d8a23fd234bada1c726622925ade62d3021e0037": { - "balance": "1567046607931000000000" - }, - "d8b1aee24264efebd1c677fcab6ada6e0f000cc5": { - "balance": "20000000000000000000000" - }, - "d8ba7afbb8bf2910b983a114aedec626eb7426c1": { - "balance": "275491152435000000000" - }, - "d8c8af55ebf116ba3c3904f8ac39d3a7d31aadc5": { - "balance": "1499999998278000000000000" - }, - "d8d97645f5f62aa89bf0046362dd0f45d40f821f": { - "balance": "25000000000000000000" - }, - "d8ea0e24a7e28285c4454f54181d581324da2583": { - "balance": "53039425000000000" - }, - "d8f5d258164747ccf790f5ed358162c756de49db": { - "balance": "323009990690000000000" - }, - "d9477bb62d3eb668a83a9679f3a7ef43f17c9e4d": { - "balance": "14045557127869000000000" - }, - "d9585e1b03fc86636dde1e64aed3cad77868549a": { - "balance": "1000000000000000000000" - }, - "d975f9ce3fe773fac3f8338a034a757c58f6e11f": { - "balance": "25000000000000000000" - }, - "d97e490faf19de612fb49c041d3f9e7877d3c0bb": { - "balance": "65766847746000000000" - }, - "d98117b74b2f2888d7078d3116d5758e2d09bfca": { - "balance": "1749157484422000000000" - }, - "d990b3f69ec700bdc095c184b3804551c832d612": { - "balance": "509385034698000000000" - }, - "d99b35298e709e5f54e6a5c612a326a83f4268c4": { - "balance": "71963571266000000000" - }, - "d99d9ec76005da26ccc721ec26be4ed9b3b1c586": { - "balance": "469607736824000000000" - }, - "d9bc61075c3201351584a026e5bdfb7cf9a7b6ab": { - "balance": "200000000000000000000" - }, - "d9d07b72f83491b6db26602f6b7039aeebfe6b61": { - "balance": "144000000000000000000" - }, - "d9f6f1ddf03e836b3744d008b62a6424544c67a5": { - "balance": "74347470143000000000" - }, - "d9fceff07ad69bf3b4aef54a7eee541368980cf6": { - "balance": "1143407707495000000000" - }, - "da0285fb7e37fd4be66fb862b248cea94ea8f6db": { - "balance": "80770216661309000000000" - }, - "da05c7aa330fcc5834e19deeb0a808e9ab7f3d99": { - "balance": "169000000000000000000" - }, - "da129e4481bd25450e6c7b42fe417c87ee2ce7a7": { - "balance": "256000000000000000000" - }, - "da32e3ec421993db088c71e256263158f7855b61": { - "balance": "18540215888567000000000" - }, - "da3c99669acd202ccbe6f80902c807588eca0880": { - "balance": "1000000000000000" - }, - "da72a7bec114d43aee6449db830d2d3f16e4d9b6": { - "balance": "744534872932000000000" - }, - "da72ec2cd7b8e3924f8baaea75d5ed23ef39394c": { - "balance": "38646377617204000000000" - }, - "da73078957f491827d62cb3ca0c484c2d1004ba7": { - "balance": "891774109242000000000" - }, - "da828e50c7c8580c6ce81718f11fbd43b2b0541f": { - "balance": "66094097819000000000" - }, - "da91483db6a6a034e068e69a6b46674838c5bc80": { - "balance": "4000000000000000000000" - }, - "da9551b635c3619f81641571e267755b89f7fe1e": { - "balance": "670841942250000000000" - }, - "da9b43a9c1c574580ec43da9f6acb687fc2f8c68": { - "balance": "761695404114000000000" - }, - "daa7f446923f7481115ad285ca468c865147e563": { - "balance": "10000000000000000000000" - }, - "dac6bfd15954efa4c9254e24e5831ab1884f8d67": { - "balance": "960042043423000000000" - }, - "dad85d0b8bb5ebf6ef811d0d35c89f9f343c833c": { - "balance": "37664599958479000000000" - }, - "dad9b01652de5d50bf30f9bcb0c6edc6315139e3": { - "balance": "21500996724000000000" - }, - "dae9c7d6bb0efe3f7ea20442b184f6d99b2a2c12": { - "balance": "937830189066000000000" - }, - "db0d6c28e9b913f611accaab15cc887f9b770f58": { - "balance": "20000000000000000000000" - }, - "db0e5341d64817885721c5abff04c30bd38df40f": { - "balance": "62600679700000000000" - }, - "db387dd404d14478babb60bad2391720d68b92ed": { - "balance": "115096708329000000000" - }, - "db3fb19e8a4a6ace4d8c6c02085d4cbba528b532": { - "balance": "1000000000000000000" - }, - "db4f05a66c0ccf0532ea1ecb931e05a400a6f4a7": { - "balance": "20000000000000000000000" - }, - "db571f1cdf8e83fbff6fb48cc0c81ef95ede12a0": { - "balance": "118317387393000000000" - }, - "db6a6a6db2aef3f43afbfe23027b670ebb3d33bf": { - "balance": "9960755220000000000" - }, - "db8bed34f8f34f45cb83ab19ed33fad76437d217": { - "balance": "21003651205000000000" - }, - "dbeba6a2a7f66c20c6db7b9270a5aee74de3f441": { - "balance": "4086905723945000000000" - }, - "dc04efeac13b2dab3d07833a7e7fa728fc23d18a": { - "balance": "1161834099120000000000" - }, - "dc092386c3a3e28b6b2d7d70db8f3d11e79ef5df": { - "balance": "124362293793000000000" - }, - "dc10be66aa11acbd42a2b1953714f09b5281681b": { - "balance": "20000000000000000000000" - }, - "dc2d58a383ce0bd40bed859ec2f25412b68eca0a": { - "balance": "104917823922000000000" - }, - "dc2e38183dceb2bc82b23e8ccf48dd96ea1c97b6": { - "balance": "2847787376064000000000" - }, - "dc5d9d94530d88451cf081fe7f2ac33667af9d8f": { - "balance": "65321904051000000000000" - }, - "dc993112a8d89136e0e73d67e2f26191583a50ec": { - "balance": "1000000000000000000" - }, - "dc9bb69b295945589a41feb794406558ce65dedc": { - "balance": "104077637254454000000000" - }, - "dcb0109d4fca2dace08ddca5d989a09d470161a0": { - "balance": "28897833222000000000" - }, - "dcce3a4ec516d833f5a9790c40ad0334b0d2dd01": { - "balance": "25000000000000000000" - }, - "dcdb21cc811ab733c2a80a2d5c8e5bb49cb2ddc4": { - "balance": "16000000000000000000" - }, - "dcdf8dd3ce03a2fe0d72835dbbd58725e1ed2c57": { - "balance": "113330414284000000000" - }, - "dd2165839ab95d6b24591307adcde9ee1819927a": { - "balance": "20260199589072000000000" - }, - "dd3015a5fdef66e749a000585d5574f975e3432d": { - "balance": "85465001652000000000" - }, - "dd37c478727f44943c5fd79ace30f21fae5a589a": { - "balance": "108577233510000000000" - }, - "dd3fb5810c31d37652bd17b92497ed479faf123d": { - "balance": "669996966072000000000" - }, - "ddc3bda30f7cf36bd535de4e20c9becb78d159f4": { - "balance": "99998278000000000000" - }, - "ddcce2d2431b67d4157c7ac4bd77f20c24831de6": { - "balance": "36160893899000000000" - }, - "dddcebe609f8b4354a1f27ab1915135e25800344": { - "balance": "1457846339959000000000" - }, - "dde223eb48f81748abde6cbc08cf1e6b0e8e4e5a": { - "balance": "1501921107087000000000" - }, - "ddf4ba402007060d9940a96f8e7c39f0a2c6108a": { - "balance": "377268151287000000000" - }, - "de05d9ada6626a8492acd137c7c7f7080a987cd1": { - "balance": "222144234923000000000" - }, - "de0fab89f79c4edf9766c3b7b1f508cb43c5495e": { - "balance": "8278000000000000" - }, - "de1070f3ff6c47237768fbdead88b2d5184fbe2f": { - "balance": "1000000000000000000" - }, - "de2b16d7f36f630329287822f550ec19415acb3a": { - "balance": "25000000000000000000" - }, - "de3faf6884337a99e54ac5d3f08b34be51b0755b": { - "balance": "51926806905184000000000" - }, - "de4614fd632ddac888d177de0858e62bbbf7dc11": { - "balance": "52506376589000000000" - }, - "de54cabb241dc5def530191f948f67db942a85b0": { - "balance": "9691177060000000000" - }, - "de81e488284acc4f8f6061d3a73bad112efa7a40": { - "balance": "14654060992000000000" - }, - "dea86ac3a661272691c877c1bad8355789382b69": { - "balance": "903877103000000000" - }, - "deadfc79f2a722dbf1c1a92f2824da8874189fea": { - "balance": "98905944986000000000" - }, - "decf1af47e153f6f3749a1b7abadefdcf1607a0f": { - "balance": "529000000000000000000" - }, - "dede5fa984f0def639d5b633f54c60fc5aaa272a": { - "balance": "8193771708654000000000" - }, - "df23607c63b3fd4b5fde6aab093c0c56d1188f95": { - "balance": "14687379916000000000" - }, - "df5b74bf02902e4c466821de798406b663d4d73e": { - "balance": "9000000000000000000" - }, - "df6402ee3f37389e7f65720561b54e26e5f1cbaf": { - "balance": "358266132937000000000" - }, - "df83ea5b770d5abeccac7f0cae803e8bd7b9831d": { - "balance": "25000000000000000000" - }, - "df92802ffe9892c7704875755bdec648914430e6": { - "balance": "20000000000000000000000" - }, - "dfa108bcd80e824a255679a38b2450d428e2f939": { - "balance": "489209553654000000000" - }, - "dfa9f18e859353796afe384d05353dc80b3ffc43": { - "balance": "121000000000000000000" - }, - "dfb0d6580f011e68a39d7727818b0890e70f3036": { - "balance": "537675412560000000000" - }, - "dfdf006abf2293aadc58feea6af6b35db428675e": { - "balance": "9000000000000000000" - }, - "dfdf2ba93bd47d7243b7419413458a947effcf67": { - "balance": "45080282196110000000000" - }, - "dff01277ac23a8cf93383595a80a7c070eafe5c6": { - "balance": "312778552103000000000" - }, - "e0450154c441e52c5e507e8316d4e9376c59c12b": { - "balance": "170163401434000000000" - }, - "e059374d6a7e6c63e609b65642272869fa3b2b3c": { - "balance": "300122497803000000000" - }, - "e0c0d8e739a2f274a43f019a07f7f61d7d8e11a7": { - "balance": "2630310240000000000" - }, - "e0e779e4e3573ea77096daec252ac2b3f1c0013a": { - "balance": "10000000000000000000000" - }, - "e1325eb586180a67873718a2016172afeb03c6a5": { - "balance": "531691399657000000000" - }, - "e13958af480da6443b9ec1067f0f33440634a282": { - "balance": "10000000000000000000000" - }, - "e142daac753b2c4d215372797999e9c88b65dfc9": { - "balance": "585813299366000000000" - }, - "e142ea343bc36ec49989fd43ad5c403c70a40dbe": { - "balance": "656734902975000000000" - }, - "e14d0a3d259db6bfec2fc4ef6e18729e4d93b007": { - "balance": "210234446279000000000" - }, - "e16a5316e3a113f27bafdf3d4fe44fe30ae9c210": { - "balance": "16000000000000000000" - }, - "e1770944aec145a96c9491497eacf7f3fb03c1b2": { - "balance": "335417250470000000000" - }, - "e199ac237661dcac0a4cfab404876abde72ee209": { - "balance": "340000000000000000000" - }, - "e1ad427471023f38cbdf07fdca3728ec343810c4": { - "balance": "343957267368000000000" - }, - "e1ae0223cecd738c8e530a0007ef05e8f3b33769": { - "balance": "950528515289000000000" - }, - "e1d2d4ef39f01a60c3bb5d671af91c5298d87711": { - "balance": "121000000000000000000" - }, - "e1d4a8888cbb383f3671ca96e7b55310b59a2541": { - "balance": "242387826125000000000" - }, - "e1da9039ddfe117e6a0b484fd3962426c112871c": { - "balance": "3710499693813000000000" - }, - "e1da9f16d57c601af8b6d102323c20408af8531a": { - "balance": "3135322588771000000000" - }, - "e1e1c163f391ffad2d0be68641253b0860485a95": { - "balance": "10000000000000000000000" - }, - "e1ec6361df67ad915df9e9661cd0932186db034a": { - "balance": "4279936304854000000000" - }, - "e224050bcd723e63f1fc0567a86942546aaf8d13": { - "balance": "12007628539000000000" - }, - "e2342c7f411d7ca3a86484af59a9c3f3180e2f0f": { - "balance": "16000000000000000000" - }, - "e26f2b026a258ce5801c90bb8fd6f7a152b8d267": { - "balance": "304593714834000000000" - }, - "e2717eb5fd0a1da51272b50ca8d12858009c7016": { - "balance": "506943817535000000000" - }, - "e27546d5620e6398829260e58e8cf4a3a03f4164": { - "balance": "3000000000000000000000" - }, - "e2762bb64e0606a5d635032e15164b01f612a74f": { - "balance": "884716158811000000000" - }, - "e2882066ed0a3c041d09c00c8532850fc42eac06": { - "balance": "42441412728970000000000" - }, - "e294c5d64daf7b7c0994aa9d03669c4b2658c9cf": { - "balance": "6996693830997000000000" - }, - "e2b179f0ed6870a6268aea64b0c7b39d98d97fcf": { - "balance": "334205318353000000000" - }, - "e2d1f6f7e3128340b789565b527bb91de96d54bf": { - "balance": "100000000000000000000" - }, - "e2f136d3693aa0b2346a968a22aca6707fc1d0e5": { - "balance": "10000000000000000000000" - }, - "e2f229054293e32cf3e83f9bb88d9cf1d6acd66b": { - "balance": "20000000000000000000000" - }, - "e33b8f4c9a49554c8b134861f88c8fffc399e456": { - "balance": "83552502198000000000" - }, - "e33cfc7727b1460324b34277dde14cc49bcb273d": { - "balance": "100000000000000000" - }, - "e36af9bfed4f912cae21f3d899f7354e1c902601": { - "balance": "31474316356000000000" - }, - "e36eff7c061dec48446d47675f176b4da3c2e950": { - "balance": "10000000000000000000000" - }, - "e383f3cf431f3cf645f26c7d5e5e2f77348ede6f": { - "balance": "776224304171000000000" - }, - "e398b9f004a4f891cf871a57d9124a97b56e89e9": { - "balance": "84846187740000000000" - }, - "e39ab2415144b46db522e92ed51b8089a5ec01fd": { - "balance": "4158925896363000000000" - }, - "e3aa7ac7e15e9a8a6f54565067234a9d4bf7b569": { - "balance": "1080385576951000000000" - }, - "e3ec5ebd3e822c972d802a0ee4e0ec080b8237ba": { - "balance": "2129139289000000000" - }, - "e3f1fbff8686af23ab95eeeee6a6a03782d72416": { - "balance": "401776848194000000000" - }, - "e4001b830fbd86df257ebab54aec0c66314ef9aa": { - "balance": "518220809325000000000" - }, - "e40790bff894f0b3e534942b5ad6f6592cd6e896": { - "balance": "25000000000000000000" - }, - "e409170a296e46fc96d85a2395e4324212a470ee": { - "balance": "1072528749756000000000" - }, - "e41546f68bbe1771febbdac2a4a5999eef50edf3": { - "balance": "1000000000000000000000000" - }, - "e425d63d711a9996c09d928ba8df94c88163aea9": { - "balance": "10000000000000000000000" - }, - "e4432ff1aee13f97f73a8407e4c7d6e768b8040b": { - "balance": "700508995102000000000" - }, - "e4690f5d024a395355a7cb5238fb7e0dc921b1e8": { - "balance": "1000000000000000000000000" - }, - "e4829684fb36f054766a61fb2a8f6ecdf27c9e87": { - "balance": "73885178137000000000" - }, - "e48a68e1ac007e14ac08c1b3b0df2b5602081ec2": { - "balance": "1389262869176000000000" - }, - "e4d699b3f4117eba7ed27b323048c9ffcb46ed42": { - "balance": "183131036697000000000" - }, - "e4db688c29fdf9a1c16114f99797d8409545955f": { - "balance": "16000000000000000000" - }, - "e535b94d370190d1e0955d3c0d12480e558f00dd": { - "balance": "20000000000000000000000" - }, - "e53966d4bb17fa9b50d29b44ddf3951c9ca67caa": { - "balance": "6400630678000000000" - }, - "e56f2656fdd1a5f7d3716e65dd89a37dd6e42dcc": { - "balance": "1000000000000000000" - }, - "e5a364113076273352e0c31bf505028e0b7edbaa": { - "balance": "10000000000000000000000" - }, - "e5a3c80518fab6a0a721ccbdc3e673680a65f6de": { - "balance": "171727917465000000000" - }, - "e5c71c7170e5c9b07e62cc307d81a4a3053ed64c": { - "balance": "10000000000000000000000" - }, - "e5fb6408db128c55cfb3e7fa1942d6347e34932c": { - "balance": "10000000000000000000" - }, - "e606883236f8b2045393c574153a100675cd4b90": { - "balance": "14005226900000000000" - }, - "e61869d1cf72f25e195898217f5bf5bcec9c9038": { - "balance": "50000000000000000000000" - }, - "e61e2e29c0719457ab1bf7d6d9fe442bd6107b07": { - "balance": "30943034333100000000000" - }, - "e61eb97093e9ee609647bd55f434a27bb30a9401": { - "balance": "200951434577471000000000" - }, - "e62812ad5834747f17c92435d863639e84d132fc": { - "balance": "3017271391299000000000" - }, - "e630b92aa8443eb077e1f6990a2e194d99cf53ec": { - "balance": "1000000000000000000000000" - }, - "e656fd1641c15e1a4b753be41bc4aa438b44b42c": { - "balance": "26972744083000000000" - }, - "e663f0257b98dfa80602a2af1bea1f901c4a7612": { - "balance": "97075813547000000000" - }, - "e66e411a8a9d019b53bf2e0a7e44703e1aa93ac1": { - "balance": "25000000000000000000" - }, - "e6712675d13fff27af43bb1cb3f2f283755bacf5": { - "balance": "227572496234000000000" - }, - "e68e8f04b2cff484da2d41dd639ae8880920f781": { - "balance": "20000000000000000000000" - }, - "e6972b5d7e0fe8c722dec9146b92f89291a0207a": { - "balance": "2115924954211000000000" - }, - "e698b491330cb55ecc4cc4b74015cd94eb927fc4": { - "balance": "1038111785278000000000" - }, - "e6c411e67b90109dbb0fa75f0f07ae8a504e9637": { - "balance": "123792105420000000000" - }, - "e6fb1dabc624edb45b040ad66f30dae010a6b634": { - "balance": "16076893670852000000000" - }, - "e71dac161206e7d3686d13b98fd922ab73587988": { - "balance": "500000000000000000000000" - }, - "e773f9be9b3f4b35ac149b4d759b9e47c8000bdb": { - "balance": "329623043336000000000" - }, - "e781cbbd2dccfdf68595d54fa44104a80d52dd22": { - "balance": "188679476509000000000" - }, - "e793666c7850a409b1d5494f576d122e85cfed9c": { - "balance": "1141845197779000000000" - }, - "e7a5527c6deb922e9f84309c502048f49f0c8f14": { - "balance": "81415566708000000000" - }, - "e7b0f75f9c69ae464b1b63cf295555d0815fc532": { - "balance": "10000000000000000000000" - }, - "e7b43cc673e321e607190a6fde996b71508f4d81": { - "balance": "103958781426000000000" - }, - "e7bfcf3125e37755e57804dfe4479657b212a8ca": { - "balance": "10000000000000000000000" - }, - "e7d33cbbd4eb38365c5be04ce32658a5ac741cfa": { - "balance": "1545192252109000000000" - }, - "e84cfbd7844f6aa3e830258a6b1069b6a7ff5b7e": { - "balance": "543989509107945000000000" - }, - "e8aa0cbc5c1f59fadf3ec122fa8a59ebfc60b5b6": { - "balance": "61271973066000000000" - }, - "e8adb5303c30a8ee044dc09c49818c02a16f4254": { - "balance": "737375689166000000000" - }, - "e8aeef5114e19d467c3064938c5965d04830f2ae": { - "balance": "51130466380000000000" - }, - "e8b5a83497198a513fb2e244bcf05f9d4cf09d62": { - "balance": "10000000000000000000000" - }, - "e8b6818cf0d24bd0e7ded854b3d368662a150dab": { - "balance": "63697741112000000000" - }, - "e8b68b9cb24169fd688db7a626d79d0363777c75": { - "balance": "427222669643000000000" - }, - "e8b8b57b23ea953943da3ef7efaefced9cdbb44c": { - "balance": "16000000000000000000" - }, - "e8f85dca364d26c2149b767904c6c06249c3d88a": { - "balance": "199342917246000000000" - }, - "e916c7801cdcf1b6cf640fcd9dcc1e3148c80105": { - "balance": "9000756000000000000" - }, - "e93cbef13277324caae7816c3d601e2f6bb42589": { - "balance": "121000000000000000000" - }, - "e9415fedcdf8939b551999900128530195a2a5f0": { - "balance": "85165078941891000000000" - }, - "e9a79ade714ce48a07fe88532a20d8f8ed27bac9": { - "balance": "30768493367842000000000" - }, - "e9b35c7ca775661bbd3a4844e2c6bc5effcdea58": { - "balance": "134719523000000000" - }, - "e9b819dffb600373bfd1b1608fc9744cc9167855": { - "balance": "1537634693002000000000" - }, - "e9c5ef50d4a194e53928659b4486a1c456df9e56": { - "balance": "50000000000000000000000" - }, - "e9e21f4523b11567516f6fc525e8967ac707f988": { - "balance": "2498740681000000000" - }, - "ea02821d6c730e061a9947b75188eb8bc0bbf9f1": { - "balance": "12822292582000000000" - }, - "ea3bca3a17c7e724ac0e15acab6442f222cd8688": { - "balance": "2789689549000000000" - }, - "ea4f7923d7045a148d50153f5f4620dbd31a74da": { - "balance": "113595858930000000000" - }, - "ea6d4cbae3cfe49ffd36653bb0d64c01b2bbc0b8": { - "balance": "49325017701000000000" - }, - "ea76cd4cff825301932a5c1d3a1de55a0ff00797": { - "balance": "1282028021000000000" - }, - "ea8e4c8c6500856777e2b41832ff00443db291ce": { - "balance": "553674550359000000000" - }, - "eab52191e5afc804b8685fe13d7ad6f5dc64fc12": { - "balance": "244412435341000000000" - }, - "eac1b0868b710e40d6d5c66a461dfc8f78abbaa9": { - "balance": "10000000000000000000000" - }, - "eacac2c75920b8f6e65f37ad81deb113d526d031": { - "balance": "53028042076000000000" - }, - "eacc9ef8b534143560f420031a8a7f030ff1a36e": { - "balance": "381111853842000000000" - }, - "eaf2cc9fdfe6272de269f32486b2d4c248a05afe": { - "balance": "2793234915237000000000" - }, - "eb0220406832a8a5d4f242538e82c80bd83d0ac6": { - "balance": "10000000000000000000000" - }, - "eb20efc0e0af48c8e6da4b21efa9c9f02d92d29f": { - "balance": "152958793764000000000" - }, - "eb41bce8e3aac2bcf662854a3151e3c83d98c6f3": { - "balance": "219455327737000000000" - }, - "eb44c591306972c29a7084079720d8ee5fb9b0a1": { - "balance": "49000000000000000000" - }, - "eb4b26ab55dc35df2e78d47a90fc43148a6de881": { - "balance": "12139574483030000000000" - }, - "eb4f53510db5edcaad6ea169e521bd094e8da4b1": { - "balance": "100000000000000000" - }, - "eb4fbfb7c0082aa0e7edaed934c5166fee955e5b": { - "balance": "299713748180000000000" - }, - "eb6067ab544af6289a73111e7693dc449d5c2134": { - "balance": "20000000000000000000" - }, - "eb86fea82d10d309b1365237e4855a48684e0e49": { - "balance": "81510415589000000000" - }, - "eb8abbcadeb6e19ab4392cded7a407c8d5df2d5c": { - "balance": "25000000000000000000" - }, - "eba44ca2d6f36df8221a2021bf0644cf6cb59452": { - "balance": "500000000000000000000000" - }, - "ebacbc0eace170f66415df48f74d98eb31828d15": { - "balance": "19046465915296000000000" - }, - "ebc72fb8a1029139d8abdc08da23dc559f87e1a8": { - "balance": "24177703742991000000000" - }, - "ebd561bb9001991cb6b02c8ff9e7ece8a3d73dde": { - "balance": "6684606759000000000" - }, - "ebe1dc3ee857ae4add6fa6636b678af8451d1701": { - "balance": "1485349608007000000000" - }, - "ebe68dc904c737be83aa2ee7f613dd51a6d436e4": { - "balance": "11206782120918000000000" - }, - "ebecf4db55a99f018bf136173ae823528f211380": { - "balance": "191817711082000000000" - }, - "ec15ad0aafe0c0f18089de50b2397509e15a20de": { - "balance": "20000000000000000000000" - }, - "ec2e56973a6cbd8b37d0294b16ef806ab5943ec7": { - "balance": "12031630315394000000000" - }, - "ec432a6a4685ebf6c1e872001d1de246140c8d98": { - "balance": "280056522277000000000" - }, - "ec866ba1bdadb91ca25f5ae035b0f69421ed4377": { - "balance": "431849961155000000000" - }, - "ec9be854224d3d371b79ffc1230fe704ba03be2b": { - "balance": "3692428502391000000000" - }, - "ecc2d6e129c7daa37a93f559c6d4f575171d8386": { - "balance": "20000000000000000000000" - }, - "ecc3aca2a21cb317c5b9debdcb2090f3931d5cd7": { - "balance": "100000000000000000000000" - }, - "eccc9a49ff40aa4b07aa0e1271cfb6713de683dd": { - "balance": "617207728367000000000" - }, - "ecccf24530629033fd6234ae32bde2052ebaa640": { - "balance": "16000000000000000000" - }, - "ed16770d5a56dced87224d4ff68a361a2285fef2": { - "balance": "10000000000000000000000" - }, - "ed23b8e782d5ddf203f9b80e5df83ec32e484fc6": { - "balance": "5000000000000000000" - }, - "ed3244e4168e669ae9d54175173c3f0f0e7c4c7a": { - "balance": "803397672115000000000" - }, - "ed48f39d3f022b321c0864d4955e1cdc8cf54834": { - "balance": "64000000000000000000" - }, - "ed4cb42fa6737cbbbf095f181e1425b3bc3ab4f6": { - "balance": "8974148344000000000" - }, - "ed560f7d83c27a26965f84dcface3930bc447fc5": { - "balance": "2092287996000000000" - }, - "ed6ace91369ec3b06cce474e67d1ce4aba6475a6": { - "balance": "1227081000000000000" - }, - "ed8249dd4a91f70176ffff310e5546e7e0c30b91": { - "balance": "813069034369000000000" - }, - "ed8987fa3d4d42bb8f009c99cda5868633d94f5a": { - "balance": "174952234860000000000" - }, - "ed99b72a58a519ca7aa8f46b8d254c3f1eeea0d6": { - "balance": "10000000000000000000000" - }, - "edb720c9bde4801e204e90282de2a6cf1c44c4ad": { - "balance": "10000000000000000000000" - }, - "edbea23cd0cfde3705d83aada88e78b9f4bb1a50": { - "balance": "4000000000000000000000" - }, - "edc1f174655205bb961ddf94a997cdfd24f1c2ed": { - "balance": "65211537189000000000" - }, - "edd1d2dcba881202bc546943194d64e59bf74bfd": { - "balance": "10000000000000000000000" - }, - "eded28fbd959f2351b4252abc71f0e809562fd4c": { - "balance": "1000000000000000000" - }, - "edfe4d4c83c7db76e5e8a9ccafa34d9841669dac": { - "balance": "2578239411258000000000" - }, - "ee1ef79de869b89334d883ba766e65150f3f6cf5": { - "balance": "779780646165000000000" - }, - "ee27b2da240e862f0848d31116a7b4ed91835c8d": { - "balance": "111637484977461000000000" - }, - "ee3195bdb69e97796911c63fdd3fcebad61ffe9b": { - "balance": "214483035823000000000" - }, - "ee43306530c21793c4fd6039b51cf54fbc912bf0": { - "balance": "374531713769000000000" - }, - "ee4515e30ee1b8dba4779ef213d89e8dfff26ea6": { - "balance": "1166743135013000000000" - }, - "ee591e9ca7948b8485eb210e2a3f706b97e6f9e2": { - "balance": "27793157052774000000000" - }, - "ee5ba6c854d633a04f7656d311817e5104c6de14": { - "balance": "289361919166000000000" - }, - "ee909db4ee48bff3adb9e43db940245a8e5e094d": { - "balance": "582143490064000000000" - }, - "ee94d1afa82de70eb65aad0662f48ef3170495cb": { - "balance": "242490158636000000000" - }, - "ee97e18e09bbb16137a7b4aaae464e97d70e6606": { - "balance": "442709862861000000000" - }, - "eebe957af00050c2841f3ef8768c6a77a5394012": { - "balance": "9000000000000000000" - }, - "eec052f4e2902f7cc496162ca6525997d2b3ede4": { - "balance": "69349303517000000000" - }, - "eed30e1a939d5f0b4a39598967a5f149a7b7cb8c": { - "balance": "1637195595000000000" - }, - "eed7bf1ba39bfdad0ce1b6b8d4c9bb31dc1a9843": { - "balance": "203331701702000000000" - }, - "eee276140ea24e36eccb4fd748f675df1acd3b73": { - "balance": "1000000000000000000000000" - }, - "eefb33b290741c4cded862cea777efe4b14a76da": { - "balance": "64000000000000000000" - }, - "ef17a60d15ecf68a62b4bfd5e3acd6201e1931af": { - "balance": "113292502078000000000" - }, - "ef3f4df42127d3e94b4b5883ca97ee63f90b68b5": { - "balance": "17819622000000000000" - }, - "ef4aa6833a69cf72fbf3eaac57da236970aa4241": { - "balance": "1638520372091000000000" - }, - "ef958a1db06e5b8e12547148f3b01da9a8841aad": { - "balance": "12847752197000000000" - }, - "ef9fa861eefe12a3b4c161a47db5d94b1fa873a9": { - "balance": "49000000000000000000" - }, - "efd9b1ce6bc3932961e41e875edaaa367d318b36": { - "balance": "1626378762077000000000" - }, - "efdce7f577c77f0dac6afc78dcbf5ebadc1c3a73": { - "balance": "627500067619000000000" - }, - "eff3f26bc45638d89f28b3ea7a5471af0b680b72": { - "balance": "1650959950189000000000" - }, - "eff6d78814ddae79d6d09d830dd44de55f3f919d": { - "balance": "44409266093000000000" - }, - "eff739e22b9aeb3781dc301da70761fdd178f08f": { - "balance": "574842224234000000000" - }, - "f0059b3c8a32d3d012b4fcb993431a484b67762f": { - "balance": "516933429840000000000" - }, - "f06747d8e2c76b8827bbd0bf4ea3a68d390ee8f3": { - "balance": "8124594790100000000000" - }, - "f0e29fc0aecc36d1bdd818148878ea7d01957476": { - "balance": "79821431871000000000" - }, - "f0e42acf4e027aa61ac2f56e3d2c171ec0fd6ebf": { - "balance": "672499252575000000000" - }, - "f14338307bc5e6ab71fa202447ce240947568b3c": { - "balance": "13990001528784000000000" - }, - "f14f9a1206eb436a3d2e4ba9b3976137f67a6596": { - "balance": "1086707451000000000" - }, - "f15fcf1772fa5b2a578ce4f9270996430d533000": { - "balance": "496026996898000000000" - }, - "f18c691a5827ff1fdc44b54bd9a64fabd53c1cf4": { - "balance": "3112912699000000000000" - }, - "f1960640b52af75fc71101aec2611499c17cd9c6": { - "balance": "195957678178000000000" - }, - "f1abf01ddd474949713bd7fa67ec81d6b56c87b7": { - "balance": "121000000000000000000" - }, - "f1b93a6cfd4b1c7e0e89ebed119c5fe55af2035e": { - "balance": "1000000000000000000000000" - }, - "f1d14c7659a10ff38f4ea74ff5b07ac035984b6a": { - "balance": "9986323720000000000" - }, - "f1dbf37470a2c4fef98b1023026870ae8f7df2c0": { - "balance": "132757602000000000000" - }, - "f220b958b619d5d848597dd00824ab8b1401ebd2": { - "balance": "1461699635849000000000" - }, - "f2484911e0aa707f88d9dd970db21e8f24b9de2f": { - "balance": "20000000000000000000000" - }, - "f264c15790fd7a36d9ce7a454f6bfbe878708a50": { - "balance": "64000000000000000000" - }, - "f2662356cb3ae7b82efd6c82c3591ee40854892b": { - "balance": "50000000000000000000000" - }, - "f27ae5783b96ef637bde4179080a8f5af63ae692": { - "balance": "784985848611000000000" - }, - "f2a62fc212717e411f72f9a694e30b8da21bb31b": { - "balance": "614971541702000000000" - }, - "f2d0a9594231efb87ac833c365b80944251f29d7": { - "balance": "478622654587000000000" - }, - "f2df99a3df0b9b448d0ea48b9fd5cb1ce9ce50cf": { - "balance": "851116673037000000000" - }, - "f2dff0ae1f5f74808624e4f26fa814e4e19c216a": { - "balance": "404457730686000000000" - }, - "f2ea1ac6282364ad5904c6f058827a4382111d94": { - "balance": "5502482915000000000" - }, - "f2fafdcdb2d887eb13b5362eb76be2a682868643": { - "balance": "6174264174000000000" - }, - "f314adfc2fbf632a6e5d8a261385b6054aca31b6": { - "balance": "1267558242119000000000" - }, - "f31a66a88394ed7dd6609aff07dd26a60a219bd8": { - "balance": "346102834465000000000" - }, - "f3535f2b42d8613363e6d9717cc21a8ec3a74fe0": { - "balance": "35723093185103000000000" - }, - "f36a149466982c030ce3b9717f34b593613804d5": { - "balance": "10000000000000000000000" - }, - "f3828b0eaba4acfbbcf3c58277ceb4616a34b630": { - "balance": "633998941064000000000" - }, - "f38f767eeb8002ef051b32fe2f40193bf0751d92": { - "balance": "50000000000000000000000" - }, - "f39bce177817a7338b1adaf713222e515c0d762b": { - "balance": "1128231726329000000000" - }, - "f3ac7ea27a1cefc7787e5ba54dacfd8385ee4afc": { - "balance": "11364602682758000000000" - }, - "f3d9ea511335ed418b1837766da11832aedf5578": { - "balance": "29188596603509000000000" - }, - "f3ef05ccd19df167e06797d962f6afe16037e134": { - "balance": "144000000000000000000" - }, - "f3f630148eccea0ad7bd67bb806bd5676a4ea4cb": { - "balance": "87187208643000000000" - }, - "f3ff31784e0b8c3cd2f7e18cfd07c682a42d1c8d": { - "balance": "10515373125000000000" - }, - "f40b976e8519a2c97f64783bca495ed3f2e4a7c0": { - "balance": "780184503985000000000" - }, - "f416a3af7f3181ad9c8a916989949d35b0b636ec": { - "balance": "16114504005275000000000" - }, - "f419759927eea6afe77701c4cf4a98791a709ad1": { - "balance": "1032589347112000000000" - }, - "f4368f9c9ad8236b56413f174562d6b6fef21d1c": { - "balance": "5447645343000000000" - }, - "f43c57f984b0e2b7ce4d703e82f41195585504a4": { - "balance": "1135809111749000000000" - }, - "f4449f52895de96a4638c927dc389f010bbd530c": { - "balance": "693196063498000000000" - }, - "f449bd417a674c8bfa1db3a3e09c2b03da0f0c04": { - "balance": "106343287319000000000" - }, - "f44dec8340986c06d64dc98d78772a8a9cdc41ec": { - "balance": "1379381904815000000000" - }, - "f4642be1a7685aea0dc7b362d36f58f15d806b72": { - "balance": "4717509847323000000000" - }, - "f4712925f57391043e0cc2e671f33124a0bc8613": { - "balance": "419736833200000000000" - }, - "f47317fba5927dd8dffc4049d4f3277fcef503d6": { - "balance": "149279442682000000000" - }, - "f47ce4c5aaef82692e47f7a810ba38d1faec0eea": { - "balance": "10000000000000000000000" - }, - "f491ffc412bf142788bb82d48bd4eccbe9e0a286": { - "balance": "77276422315000000000" - }, - "f4a1e27e669c29f15b9f89ac15f702340a135743": { - "balance": "324000000000000000000" - }, - "f4b5cbfa50a6c4f5f7db7a93fa565362cc7aceac": { - "balance": "195951823248000000000" - }, - "f4b949c6e10615b651675016f0d7d6ff64e31aee": { - "balance": "35516207325223000000000" - }, - "f4c5e2f043ef3548a2c1c27d968087bec65e2f7d": { - "balance": "100000000000000000000000" - }, - "f4c79ea9c6f7297e016c39296d86f0304070c31d": { - "balance": "71036374423000000000" - }, - "f4dde3733a72872a7efc095cb412672c50928f1b": { - "balance": "129914864759880000000000" - }, - "f4ed736a413464eb93f8a430e093a64f0bd4222d": { - "balance": "10000000000000000000000" - }, - "f4f07e45560fb63d5207ed7e8d7cf4fe29e06d18": { - "balance": "293103814503448000000000" - }, - "f50eac35eef0a1bfa23ba31020ef60e89bf8e9df": { - "balance": "10000000000000000000000" - }, - "f51236dfd888929ccb2fe1f1fc5554abc5df4ce2": { - "balance": "25000000000000000000" - }, - "f521eb42e9092350f2ad4391ddb42bfe7abb4db9": { - "balance": "217462745186000000000" - }, - "f54e7062b6a9a8b283acf00fcbad58aca0737676": { - "balance": "7327357122437000000000" - }, - "f553301efd81629d0856d9c95c70f4a962e602ed": { - "balance": "1500355826530000000000" - }, - "f55c555b0991b2413f2f2764d8ed6a0d77825965": { - "balance": "1174679810163000000000" - }, - "f56ff110d521ceaec29dbf2842f1e78b24463cea": { - "balance": "20000000000000000000000" - }, - "f573fec366236ab87ba041f7dc6a88d92b1fc9b7": { - "balance": "4659857040000000000" - }, - "f59987743b239379aac9353e17e0e4442aa2c684": { - "balance": "25000000000000000000" - }, - "f5a9ca298e88c5492dd44a66d815b649c2f01d39": { - "balance": "95879585325000000000" - }, - "f5b4933164c55b5ba99db906ecaa52bba4f95164": { - "balance": "25663623936000000000" - }, - "f5d20af68c6fed98144718b6beab82fde00dfedc": { - "balance": "16000000000000000000" - }, - "f5e49ce72be9b17ff39688860e5cf6fd500a886c": { - "balance": "106142276914000000000" - }, - "f5f472405a4530075805fbc11928544770fd61fe": { - "balance": "64000000000000000000" - }, - "f62096c7305eb97b221bb637f4269246fe59262b": { - "balance": "855993602798000000000" - }, - "f622bf9b8f7be2f75d5ed73d318a0e7fa62a587f": { - "balance": "20000000000000000000000" - }, - "f6231f31d524ccc444bd046123ba33bc224bdd52": { - "balance": "97550810879000000000" - }, - "f641b4a721dcefa497274fd06888eb998b9bc038": { - "balance": "39401014566340000000000" - }, - "f64f0c5172c99d74b2450a4685c3ec715b379922": { - "balance": "28337413668000000000" - }, - "f65841061cd55cbf20843d9594bce9ee133aa644": { - "balance": "9064540188290000000000" - }, - "f65f0106f3d148d0660547f0683ded4dffc12fe9": { - "balance": "87334071785367000000000" - }, - "f677961296ed933db9e1dd887711387540c0436d": { - "balance": "3982789899000000000" - }, - "f68ba7530f423b8df1625cee36f8df2363a57c49": { - "balance": "5000000000000000000000" - }, - "f69c6eaf077b795f19a9590ee8b578543558e4c4": { - "balance": "10000000000000000000000" - }, - "f69dfe3f0f76e50e2850e44e9e36b6966e277eaa": { - "balance": "288231750575462000000000" - }, - "f6a73c4b958b4d6044f3f4da7147d0fa80e2ea31": { - "balance": "50000000000000000000000" - }, - "f6b0864be5f7bbc4210a3420aa3ead614a8fe7e2": { - "balance": "880968828000000000" - }, - "f6f43a6d9517471436d2ce5047a2b707580e7149": { - "balance": "20000000000000000000000" - }, - "f6fb414d1ca7c29be35b5f97096c817bbf70b070": { - "balance": "15156317416682000000000" - }, - "f707b491ac27b2d2e5e1f9d4123635ee0af92c5c": { - "balance": "500000000000000000000000" - }, - "f71179583a471767a1b399842d7d29caefe57a5e": { - "balance": "429648186876000000000" - }, - "f71ed909eca6bfd574cd670389bc9250493d686d": { - "balance": "38189267531000000000" - }, - "f72ccdc70b7878cdb94f42ee72ca5b4b35a46238": { - "balance": "86065647347000000000" - }, - "f74035e85dbfdb961037bf689ee7dfdcfaf32d64": { - "balance": "398451682882000000000" - }, - "f77668db085a87b0a0405a275e1c2516d3e02b66": { - "balance": "10000000000000000000000" - }, - "f78990d9e50876b49f933e9d74bda44197e9aa7d": { - "balance": "51984216556000000000" - }, - "f79b9df28b7d94d1b4491fca1cbe50bd36aedb3a": { - "balance": "11546152485156000000000" - }, - "f7c773b89be413848dc4a96f064693a0c3a2eab0": { - "balance": "7084247258755000000000" - }, - "f7e29c20bb0023e9ae079da589346fdfd960dae3": { - "balance": "93132014782000000000" - }, - "f8124428ea619d30a335ecc4c2f64e36500abdcb": { - "balance": "8838170798391000000000" - }, - "f843c9d70226e6c2c8cd4cef78e2db66a8eac027": { - "balance": "498377670361000000000" - }, - "f84bb3c0d872dcdbe99d6abcc57c6b5c2b2e35ad": { - "balance": "1405105232436000000000" - }, - "f8679b915ae94e4668f2e27d1094cbb2d97cf428": { - "balance": "1000000000000000000" - }, - "f86dbb82c634cdfa818e4d0dbcfcc9a5c47a9ddb": { - "balance": "196000000000000000000" - }, - "f88bad7726aa66bc1d0ca5824044072f3551fd15": { - "balance": "37432374800000000000" - }, - "f8ab07d0751a2c283ebe2a7e28c5b6e57867e1d1": { - "balance": "25000000000000000000" - }, - "f8afb4f5684c56ff7ce71b4e4cf7e42062470e08": { - "balance": "10000000000000000000000" - }, - "f8c28df0d1a0982289ddfa2a6d562e5c75a5dd01": { - "balance": "1447386977682000000000" - }, - "f8cca137f9c12b48eafd43f038e55e2d3c481919": { - "balance": "35370515421000000000" - }, - "f8e50d1816a5e5c649756ae208209b03b1ece0c3": { - "balance": "48449640035000000000" - }, - "f8fb33ba1d93112d9c3672806e0939083f09a88e": { - "balance": "419743187776000000000" - }, - "f903bebfcc6a7050fc2c5bd14248af9b300f1600": { - "balance": "473363252199000000000" - }, - "f90ab9078f26dd881fb054b4b6e3b3e17fa94718": { - "balance": "156449634345000000000" - }, - "f93e3f392efc057f0af3a91416858a515c1ed996": { - "balance": "1147663044625000000000" - }, - "f94eac538ca66931869c312acb67721c4337842f": { - "balance": "368103335377000000000" - }, - "f94fda503c3f792491fa77b3702fd465f028810d": { - "balance": "317241487661000000000" - }, - "f95dcedbefee8ed01086c91d91a4c115ad8fc947": { - "balance": "147059838786000000000" - }, - "f961a293bbce366a6fcc98d2ba0342e2ef3c5519": { - "balance": "10000000000000000000000" - }, - "f966fdbc4a42f055f8f52d31c23ad7b6a07a5e22": { - "balance": "10000000000000000000000" - }, - "f9a3a61a2f1469835240bb0641eae40c07451e30": { - "balance": "218000000000000" - }, - "f9adcf232180378b08a46d6c8d9d97f01802e01b": { - "balance": "15658216517944000000000" - }, - "f9c68991ff7ac307e41ea1c673f8ebb1a6afbd99": { - "balance": "10000000000000000000000" - }, - "f9cc0c60431d7bdb0c7581a9ae7f011b0abefeb1": { - "balance": "16000000000000000000" - }, - "f9d43c329b61ca2169600e45c8fad3c94226adb8": { - "balance": "120128558137000000000" - }, - "f9ef5d4e2ca8888216b939d3d938438a34dd9da2": { - "balance": "144000000000000000000" - }, - "f9f3d14cd3bd09e2c4c89035b4f50e93f6175cef": { - "balance": "725000000000000000000" - }, - "fa0f5a03601bd1fc76865cdd69d9671ba6073592": { - "balance": "225298289139000000000" - }, - "fa12f10db0eb552b719194becef20af9f45de8db": { - "balance": "1012484659496000000000" - }, - "fa146c58a0709951bc2e9bccddcd002c5a0bb7dd": { - "balance": "199563276701000000000" - }, - "fa159185c156f35fa450b77c48846c2dab6349b7": { - "balance": "100660066567000000000" - }, - "fa193312655f79c7b0ee7d7ef904486836180026": { - "balance": "48141690266000000000" - }, - "fa2484de744918bd8c91350fbabc0dab8b8a44f0": { - "balance": "36000000000000000000" - }, - "fa36dc463b026d8edfeb8ac4acac43a51d643457": { - "balance": "9608761064478000000000" - }, - "fa84199010be2bf53e803c23771e0d15fd025386": { - "balance": "1474902394742000000000" - }, - "fa958bbfa367a745bcd0904db2c4e30445edaefb": { - "balance": "175679888121000000000" - }, - "fa98bcaeb55285ad7ead12ccaa15cf488f567ede": { - "balance": "136105143781000000000" - }, - "faa1be631da42b41a026774f4166c1b831ef41e9": { - "balance": "86358861589000000000" - }, - "faaa857e7f149968434f313ab8db596e1b0ae75d": { - "balance": "36000000000000000000" - }, - "fac2b85ab274055cf1415d57394e8aca4541857d": { - "balance": "289000000000000000000" - }, - "fb23a508ccdb4e91b252f5c06c465c55ed59b1db": { - "balance": "14698710175236000000000" - }, - "fb24d4e47ba70aa4b984372b4852ad3d082daa24": { - "balance": "4526648424830000000000" - }, - "fb27a7e8b8b4ae43c69ce025b46187e538608769": { - "balance": "121000000000000000000" - }, - "fb2cdb5e85872f52c99985f219b8fb4125c6a8b7": { - "balance": "8568367153000000000" - }, - "fb3d76c8165bcb3c93fd3b2b10c20588d0fa97aa": { - "balance": "500000000000000000000000" - }, - "fb5161b2cc9d48a53f47d66002905f0458e3cd9e": { - "balance": "225000000000000000000" - }, - "fb72756c4845f18ab35d29f632b662c0c0d4b94f": { - "balance": "883095068524000000000" - }, - "fb8b7efb02ea5292304c0f0abc8c555684653587": { - "balance": "10000000000000000000000" - }, - "fb9ee61e337a5c7b57c5140e84919101570e2cb7": { - "balance": "16000000000000000000" - }, - "fbae69f44b116c186a86cb0de79323ca3d6b99eb": { - "balance": "1359504686067000000000" - }, - "fbbd399eb9e5d3dd67efc48927973601dcd84321": { - "balance": "2049018637367000000000" - }, - "fbc9a3c3c429990cc306710b3dd44174dcc72ad4": { - "balance": "55507457947000000000" - }, - "fbce66a6898ecd70893db6b4b8c3d00afef8e20b": { - "balance": "20857164902458000000000" - }, - "fbe8fe04084fc93dff8228861fe100bfeeb057b6": { - "balance": "10000000000000000000000" - }, - "fbfb717f902ad79ef63565f9ab57f041ff5f7626": { - "balance": "16000000000000000000" - }, - "fc0b6c8c6be79bf0c9554f7855dc8c4a617d02c9": { - "balance": "17347593956000000000" - }, - "fc17518d05e605807847bbf6f407da89037bca00": { - "balance": "1796383702108000000000" - }, - "fc2793424c809cc80938a1be1292813adbc8ac8c": { - "balance": "10000000000000000000" - }, - "fc35930abb108ae6cae33fd065dfb799808ea326": { - "balance": "912737460000000000000" - }, - "fc5a9209799e563ae8d958774dc86345a3bc7ed2": { - "balance": "29049176573000000000" - }, - "fc8011850c09c9288e737ea58ca5c15cded6dc8d": { - "balance": "10000000000000000000000" - }, - "fc9183ed137be071ad183d025395a0ebe2674654": { - "balance": "500000000000000000000000" - }, - "fc98c9d88b1fbbb68dbdd6448aa6a32e8282800d": { - "balance": "900000000000000000000" - }, - "fc9f4b9da7a46c2bfcd50cafe1f892b9984be0ee": { - "balance": "21577116424370000000000" - }, - "fca525b732a673b953f1c23083c276cc8cbcb86c": { - "balance": "77653618624000000000" - }, - "fca57b6a4798f33478b6e23622173cda3fe1b9a0": { - "balance": "793368066098000000000" - }, - "fca79b446c513a7bed643603c42f35ff0fa89f49": { - "balance": "998082799053000000000" - }, - "fcab42f7f07735a7b09074c1f1769287069c88c8": { - "balance": "94824830574000000000" - }, - "fcacbbc6810c586522012ad32c3dfac80eb563b4": { - "balance": "10000000000000000000000" - }, - "fcb38809b63810b6673dcb4c947e01f7b49fb1b3": { - "balance": "725937240372000000000" - }, - "fcc0e531d9f6265672aa885af361534464a11015": { - "balance": "22121462657000000000" - }, - "fcc49c62d7738fa1b92aa6a69a12b671e4c7c8d9": { - "balance": "50000000000000000000000" - }, - "fcc95394fd796ca5bd8f3814883b1150d74dd9a5": { - "balance": "144000000000000000000" - }, - "fccdb068dfd599d7d5c290a6ae65eba9151d5b29": { - "balance": "5369426564000000000" - }, - "fcde41ae28bdf9084a28f47a9348d8aac5b3dd43": { - "balance": "409599263197000000000" - }, - "fce5816f066ca32d1fa02e9e8b5eb8a7fa3e4dea": { - "balance": "1193272309645000000000" - }, - "fcf9fb8996d6d9175ade6d6063be0742de20ea1f": { - "balance": "16852526239339000000000" - }, - "fd10488d55e6861cb67f7f50950d78892e7032ad": { - "balance": "165069902909000000000" - }, - "fd23e8263d89256add0dfe93da153d305ad917c7": { - "balance": "26633825496000000000" - }, - "fd3a98cc3b3f1439af35f806de2fb05fef98f279": { - "balance": "1043321187464000000000" - }, - "fd3d79185a91984a117ee6f9fd304725875094e2": { - "balance": "2349991833898000000000" - }, - "fd5e6ac22634f04ec4ace5da8996c2b7b70b22f4": { - "balance": "10000000000000000" - }, - "fd62ed1cf7a535c989fbd742b1660205a2f69dd0": { - "balance": "49000000000000000000" - }, - "fd645043bd4d7b71e63e30409b91e9fdda3a86c0": { - "balance": "362957768837969000000000" - }, - "fd7014fc1c70af482115247ff94ff6bdbd3d364d": { - "balance": "743383172317000000000" - }, - "fda0cfe95df9021497752b04863c3ec44d13e853": { - "balance": "15586809617955000000000" - }, - "fdb5b964808bcb974d3e888cbb45bcd57e57c907": { - "balance": "5549247772273000000000" - }, - "fdbaaa865ec38da13e80554b6d0abc437f60d8a5": { - "balance": "3736861227131000000000" - }, - "fdbb8693b3c20c0eac5fb585e2347d41debbffce": { - "balance": "100000000000000000" - }, - "fdbdaec57829f25ad48e18d94e0b8533f2801818": { - "balance": "6934630922926000000000" - }, - "fdc318ba5b1f8ad33e00528828b93a840592e2fb": { - "balance": "10000000000000000000000" - }, - "fdcf6a997bb10806e4d87eb4222e9f93b4202179": { - "balance": "1000000000000000000" - }, - "fde5a9911a10770d733db4d32ca9a5493478399c": { - "balance": "20000000000000000000000" - }, - "fe39185a6b84378820ee215f630533e658731ca9": { - "balance": "17022202932000000000" - }, - "fe3b1032e524674cba5f329f940c837850fa53ed": { - "balance": "50000000000000000000000" - }, - "fe3bc4ff2c3b66bc582558314b80030407e7de96": { - "balance": "1669870860988000000000" - }, - "fe668dbb1f3de744d16e13e0ed6f5708c2c15d1f": { - "balance": "39974355655263000000000" - }, - "fe95bfb97fa60341f8af2ad621e606b85e3c2e57": { - "balance": "528601649597478000000000" - }, - "fe99cf2a1fbbe7c46e4235b2d135a3a093fcf16c": { - "balance": "7271022106877000000000" - }, - "fec1f6ed4b3ff01e7ebe13fb53f60ee5a3b9e191": { - "balance": "1316316072034000000000" - }, - "fed9bec1b2145452ed5535e4ba29fafac6c35fbb": { - "balance": "10799354586000000000" - }, - "fedced7aa1cf3f3a7eec321cc0274759b154ea8e": { - "balance": "11740927210323000000000" - }, - "fef5063701a93ad02676fe0b99d0f4d2da0ccd67": { - "balance": "10178531012000000000" - }, - "fefd5627a408ca099587892ee2a46fa8cc89be19": { - "balance": "458504035686000000000" - }, - "ff1fc0f6f26188cbe18cf65d8a344d3775aecc6d": { - "balance": "81000000000000000000" - }, - "ff4fe483b3c04ebc8d6705c699ecee3e92071715": { - "balance": "1000000000000000000" - }, - "ff51bfe823394b2bce05947a6068bd5158d4af0e": { - "balance": "692533626783000000000" - }, - "ff6652e4e45f6b0f95ad4c9ec2bc80476e3f7fc6": { - "balance": "46457898024000000000" - }, - "ff68246ac7640091e5e58345736b249e036364fc": { - "balance": "2626125272000000000" - }, - "ff6d4b8a8393a503047ff829dbf2bf8e9172dc6d": { - "balance": "2865001878255000000000" - }, - "ff6fe19e056a7211b7e484c2c540d5aa5f1d83e5": { - "balance": "36000000000000000000" - }, - "ff7fa33529e1781c1b2951e57581780b229e3fda": { - "balance": "10000000000000000000" - }, - "ff82d1052538539d07cf3955476cc9a5027d8e4e": { - "balance": "83572023121000000000" - }, - "ff8acfe75afcc1efb1bc44be9f9bb242a94f73f7": { - "balance": "7556034521000000000" - }, - "ffa2b5f1685de9fcf1af4653cd3a584db1beed64": { - "balance": "114892199805000000000" - }, - "ffb1e9be68ae8be8d7d066c473589921e68825a2": { - "balance": "484660652980000000000" - }, - "ffbf91a9d1a6377b7435e3e734132e7b34188dac": { - "balance": "20000000000000000000000" - }, - "ffbff1fab9f2bc2f387d0cc9cc28f6aac533c813": { - "balance": "10000000000000000000000" - }, - "ffc4ff6433ea35544e7a07fda170e62c451301df": { - "balance": "29238210920000000000" - }, - "ffc7534b64a8fe8760e931a710883119d28ae106": { - "balance": "500000000000000000000000" - }, - "ffda6b8e3de72d7f7c18b892e6a8b80b886d5fa5": { - "balance": "214366938289000000000" - }, - "ffddb1fb7521c9772ea4886aaf022c4375ef904d": { - "balance": "554864446437000000000" - } - } + "name": "Ethereum Social", + "dataDir": "social", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x2B5E3AF16B1880000", + "homesteadTransition": "0x0", + "bombDefuseTransition": "0x0", + "ecip1017EraRounds": 5000000 + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "registrar": "0x0000000000000000000000000000000000000000", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID": "0x1C", + "chainID": "0x1C", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff", + "eip155Transition": "0x0", + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x0400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x3230313820457468657265756d20536f6369616c2050726f6a656374", + "gasLimit": "0x1388" + }, + "nodes": [ + "enode://54d0824a268747046b6cabc7ee3afda48edba319f0d175e9e505aa9d425a1872b8b6f9ebf8f3b0a10dc7611a4c44ddec0fc691e5a5cde23e06fc4e4b3ff9dbef@13.125.185.147:30303", + "enode://7e150d47637177f675e20d663fc2500987f2149332caf23da522d92363be8a7880ef9150a6183e9031288a441e0457239474967a111eafce17e19a4288076ea9@18.219.40.235:30303", + "enode://6244c9d9cd288015d7ff165e90f3bb5649e34467e095a47c6d3c56e8fb8c849b3b4db683ff3c7ae8a654bbdc07ef12ee2fd7d72831ac213723281c1b0cc90599@13.250.220.98:30303", + "enode://e39f162b9f4b6ed6f098550f7867c2fb068fc66f362b3db0f45124c43ea18508f5ceef4e0e4de53d301e14a6f1683226aeb931d7401b4e83b5a583153ffdd7fd@52.57.98.157:30303", + "enode://54b4a117d66dc3aa93358dec1b31d4f38e72e4381b3e28a65ac6f1aaac3b304ebbe41d32cc864fa69a9a6815c34cf9b8965690dc174a5f72af14547b601b7924@222.239.255.71:30303", + "enode://851f14c5cc86cbc0a81acfcbe5dd99ad5c823435357219df736932c5f89ad4318f6973a553857a32d97a71793f5a35c062d46320be282aa0a80b06b9c6b624e4@13.125.232.71:30303" + ], + "accounts": { + "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "ceed1c8254abaf069669fc6045e90482543d1f2e": { + "balance": "38000000000000000000000000" + }, + "6f22d7f8c38e0135e36be87e77fc8d4ae4b3d965": { + "balance": "38000000000000000000000000" + }, + "d016e982b7886302428d7c741392c658337513d2": { + "balance": "38000000000000000000000000" + }, + "defa96db5c8a41772bc56f68f95e307ff71a2c60": { + "balance": "38000000000000000000000000" + }, + "951ffd4253ffcf31b2895dd3f7f2a8a9bb2933e5": { + "balance": "38000000000000000000000000" + }, + "b7071dba21cfbe1b70abd7ddfd2f0f83d5d19a61": { + "balance": "38000000000000000000000000" + }, + "6ca420cd8d5407c61a9b14adcb38bee0f26e2848": { + "balance": "38000000000000000000000000" + }, + "b50d185b6cd04499a38afc0fcfcb59eaa74d0956": { + "balance": "38000000000000000000000000" + }, + "7ba8c49a444c117f2d2a50650b3f700d4ee659fe": { + "balance": "38000000000000000000000000" + }, + "83f9959ecc532dce071fcd0c62dc23cd571b689b": { + "balance": "38000000000000000000000000" + }, + "001327afce7ebb623a7d0f17b2ffc358fb863b5a": { + "balance": "9844198127334000000000" + }, + "0015ac7f8bb2a2c7d954fc2dbd4e20c0db5942a5": { + "balance": "1000000000000000000000000" + }, + "0021e69c041be2d28744b69361105ff51295da59": { + "balance": "1379639894000000000" + }, + "002cfd27bbb8164681b8762e71b2891beb127fdd": { + "balance": "25105286685000000000" + }, + "0033cf217bc765ccfc338869451588ce448fde65": { + "balance": "23425485280069000000000" + }, + "0048f1d1735979cd8ac9c0886088336b2d4a43a6": { + "balance": "10000000000000000000" + }, + "006a79cc154917cf204d8097728f290e29716d43": { + "balance": "20000000000000000000000" + }, + "007c8db36e4f649b14516dd78202670b671ba753": { + "balance": "1000000000000000000" + }, + "007d131b58388f251075a3c61020ce301106c5cf": { + "balance": "381079535880476000000000" + }, + "008e8fbffc2fdbefaa7e3be4f4a9160db826d05f": { + "balance": "10000000000000000000000" + }, + "0126d86b9814b0e78c4e01a3916bee6a7778145b": { + "balance": "10000000000000000000000" + }, + "012cb961297c837630251a173b7861e77724856d": { + "balance": "494562376059000000000" + }, + "0145886dfab5ef4f2def50a56b4a074cf5b18acf": { + "balance": "680585022951000000000" + }, + "0167918bab62aa2118cfa4d3eb80da0e71c71d8b": { + "balance": "122395119468000000000" + }, + "0182f7286ae9d4d6bc514d5175d14685d520bde7": { + "balance": "10000000000000000000000" + }, + "0184e9c8fe99d85100fe28a0e8877b14768b372a": { + "balance": "193295614762000000000" + }, + "019eff7dce7f31c2d4f7318da71d212cbf89d36e": { + "balance": "64004138198000000000" + }, + "01f3351ea66c352346244dbb79189066bed62fc5": { + "balance": "937056266523000000000" + }, + "0202ddd7f4f32bc575f7df24612f8aa9f9a7ae42": { + "balance": "106905151080000000000" + }, + "022b8c65e959cab71f56688b7073257b58bbef4a": { + "balance": "9682681149566000000000" + }, + "0245ff6382eb93ab1e8ed2e3c0bce7a1b9a9713d": { + "balance": "289000000000000000000" + }, + "025e117a69ca9244ed430732c11e550e3ee67577": { + "balance": "1861905310567000000000" + }, + "026e7457eeaeaec7898fdee1ad39be89e92733b3": { + "balance": "7529030978000000000" + }, + "028d2def8c54fcc77bf0191b183c0bc4570ec1c5": { + "balance": "9056720934000000000" + }, + "0291a087605b516e465134797b5459436d320e6a": { + "balance": "481100929805000000000" + }, + "02a4b18b3e13ec79307e712fba1867cbf7fb6155": { + "balance": "9000000000000000000" + }, + "02a812d4cebcac1a92ae470ade92fde7bead127d": { + "balance": "66793603497000000000" + }, + "02f718c94b2c8e8d62752f8632443504c1e4b6e2": { + "balance": "1000000000000000000000000" + }, + "030dab52b47b37505b72e5ca0985f65ead590816": { + "balance": "1376851176362000000000" + }, + "031c59846f75de1aefb0e8a95e0fb822fd06555b": { + "balance": "140978338628000000000" + }, + "031ee87c672d83ec73059c86a312a9e972142054": { + "balance": "96406273341000000000" + }, + "033182e860564cf695cb403c8c0f078053368d7d": { + "balance": "1504349255824000000000" + }, + "03788dc6528fa33a90e90e03295ae4b792d56644": { + "balance": "24356250426000000000" + }, + "037aae119047028157c5b3bc9d3d202b02cbce42": { + "balance": "105627739575000000000" + }, + "037d45b323cbc5cbac999c5001169646e690b94c": { + "balance": "2000000000000000000" + }, + "0390ba35c454a24519d845405a7e24df71250748": { + "balance": "1872501898509000000000" + }, + "03ab8c1e7f904db62437b16d28aeb539b2dee55e": { + "balance": "55000000000000000000000000" + }, + "03af4c69728a888fa26b1aefa439005989771fdf": { + "balance": "27704588237757000000000" + }, + "03b33fb19d165e5e33bcfbbfc009f418d71f30fb": { + "balance": "1999139000000000000" + }, + "03b34c79f8167a4e8be0f6133254d2b50cbd878d": { + "balance": "111065050160000000000" + }, + "03d7e8638b74ae44a2770287285489a95fa1ea11": { + "balance": "20000000000000000000000" + }, + "03d870bf719f03250c0dc5156a36751b3aa21f18": { + "balance": "981119649953000000000" + }, + "03de52c12b05fb8bcba3a1cfe02a0ad1bc9761d3": { + "balance": "362007990932000000000" + }, + "03e516db27b1abe008ffc57ced48f72f872d8b08": { + "balance": "3389116345657000000000" + }, + "03ef5ff863ee5f1167f38cdf316e4d52a242b750": { + "balance": "12395856876000000000" + }, + "03f27766760f2bd1cae1cb85ddf43ab59c871e47": { + "balance": "49000000000000000000" + }, + "03f4e1a8fb4eedc776f4835fcc85d0f236612f9c": { + "balance": "27210590272692000000000" + }, + "0404936ee04cc79cbb3aedfa33a53f94940f772c": { + "balance": "29919204637416000000000" + }, + "040501ffde9649be794b7d41643273ed6285ab39": { + "balance": "686000000000000000000" + }, + "040e449de680f69614120f0a2e894cde36e4adf1": { + "balance": "81993180085000000000" + }, + "041531e906dbdc70d89f5e255151d9865a059308": { + "balance": "2163418749315000000000" + }, + "041ad9f6bf970541e4ea8a14dde1e789d0fe4367": { + "balance": "44999979000000000000" + }, + "0446420c07cf73d2b3741b945c1cc8444b4ba6b6": { + "balance": "138749371512564000000000" + }, + "044c1a540b8ab286c218c2fa9d5bfbc2761e7626": { + "balance": "1" + }, + "04526b2c62911e78a939816aa4575fe30baa06c7": { + "balance": "2983093150081000000000" + }, + "04adf59f8a0ad3820a7972c6243202b3b0617fcf": { + "balance": "50000000000000000000" + }, + "04bbb42882a475eed58aae47fe530ed19c1cedaa": { + "balance": "278038763863000000000" + }, + "04cff7a7c2b9b0bf31c5ad4a5de8b0eade70aafc": { + "balance": "515406205244000000000" + }, + "04dcd325dc1fd37ff3c87da3b21c47ddfcc37cc2": { + "balance": "5831887315000000000" + }, + "04ec8d0b5157370f5a2671a2aa68ae486b7a7842": { + "balance": "10000000000000000000000" + }, + "04f50f2a6e89ee497a64c11baa90759a10a1247a": { + "balance": "25443071621949000000000" + }, + "0513a769ebef58ad3a4fd7011ddbe19799ff5600": { + "balance": "64369494797000000000" + }, + "0514c1151f356070ace281435f25c86b58280715": { + "balance": "38967380881301000000000" + }, + "052fda414fe1279c6276a237b07e1b4148a8cc77": { + "balance": "10000000000000000000000" + }, + "05431089cc62a987d0e99847e10a006233146f6d": { + "balance": "268977485219000000000" + }, + "054ed2f55028257212b996f9a3d34758d1d4ffd1": { + "balance": "100000000000000000000000" + }, + "05a68cc758560addde302baf814f2fdbe0ef2c2b": { + "balance": "10000000000000000000" + }, + "05c669d9ded79fe9e4e3718052bc7ca18a3205ab": { + "balance": "7347158140000000000" + }, + "05d77ce5c87477b05e90e829dafd8eb3a8c87823": { + "balance": "21191998933000000000" + }, + "05ef2894a2a1c6eb6c0a768d04ef5b573f357712": { + "balance": "20000000000000000000000" + }, + "0601011f80279190b96f641205c6a524a8ad5a28": { + "balance": "12025716447696000000000" + }, + "061a8acdb1a340ba7c550814831e27262708fc98": { + "balance": "234029764576000000000" + }, + "06219483e217c9ad479f76a95426f689ef4d5951": { + "balance": "1509408723551000000000" + }, + "062d0db8a650f2241f8a4295326a2570a7c771bb": { + "balance": "717459720227000000000" + }, + "0633ba746235d8fc8243751b1aa31646c299f262": { + "balance": "49000000000000000000" + }, + "06b6a5cadfe1fdc88015512e835d840e58ae4123": { + "balance": "1000000000000000000" + }, + "06d08fcbe96791514d900d2cb6c0f029d8d791d0": { + "balance": "19196168602258000000000" + }, + "06e5c0bad43a7011878b12a682abf01ccdfaa151": { + "balance": "30000000000000000000" + }, + "070656bb11ec36074d47c791c0b306394b703401": { + "balance": "1245216075291000000000" + }, + "070d84c938217163b60ed38e4937eea7158c03d9": { + "balance": "27507979787000000000" + }, + "07428c95ef3862026e54d3a963911cdc673dbcd9": { + "balance": "13792309994528000000000" + }, + "0781cb21df142ec5f67b956bf995f02f6f24985f": { + "balance": "224940990659000000000" + }, + "078c38c153b414cc4c12818fce2ea7ba09a34e51": { + "balance": "1410646136000000000" + }, + "07bfd0de7a9a1c927446aaf2d7ede55b471daa87": { + "balance": "77778844734000000000" + }, + "07d1ac83140188b8d7f4c8c607d0da22c5ba523f": { + "balance": "7713686418107000000000" + }, + "07d8ef8fc6dcde319a5af5b6cea18983bdc4c8fe": { + "balance": "3801361173000000000" + }, + "07dfab72dd3e44fcbb1ced625899bf20e0c52ffc": { + "balance": "154177778806000000000" + }, + "0817ce33d943e84c7b3261cc3e37b86b5d6d76ae": { + "balance": "90753785862000000000" + }, + "081be00a2ff62cbcb95a8eb020ac0efa33f93a42": { + "balance": "1027889807304000000000" + }, + "085ffdc6043b04653e51b1a34af20b609d158607": { + "balance": "3314058000000000" + }, + "0882c2228f5df24064bc37e8b7199199de308bb8": { + "balance": "98420617420000000000" + }, + "08918776e9a7136cedad5d0cee52f5d9dd833ece": { + "balance": "1263170315026000000000" + }, + "08bdbcff16919abc5e15fa68ece56eceef33f48d": { + "balance": "2552990000000000" + }, + "08fc8c7bd03fe1249266b233edfcf830693d0e10": { + "balance": "283490111768000000000" + }, + "090f79a4178b5180150444805f62c26cd21be897": { + "balance": "884195010282000000000" + }, + "0914a9dfc9d6ecc063a55e5320050112f305fe17": { + "balance": "15373898854941000000000" + }, + "091791ab5f8ab86f1d8f566ed221b268cbc55347": { + "balance": "2207516004000000000" + }, + "09529f8b1633ce4375451bb44b1025f6e5f9facd": { + "balance": "151697652792000000000" + }, + "09600bbb9d9b23661d269dbe1ed066d8e573b5e1": { + "balance": "802935104935000000000" + }, + "0964d2af1d5883fc0e0a77459f6a141824de7356": { + "balance": "9610980935058000000000" + }, + "097c731d1fc6792ac0f0ff92be4403c3749cc1dd": { + "balance": "165134479709000000000" + }, + "097f152b3f837d38ab1e8c0683d62f5a01d67902": { + "balance": "20000000000000000000000" + }, + "09a6772629ef0bf402ae6d27cd32e6eefb220a12": { + "balance": "20000000000000000000000" + }, + "09addb954d4e4b4e95e0c66d324115d609df5a99": { + "balance": "8435321515000000000" + }, + "09b2eb03e0fa321102196578eb40dcba3a46ec9c": { + "balance": "12723517962933000000000" + }, + "09ba0ed4dce470ba0bcb4d46b507c3b024b83070": { + "balance": "99999979000000000000" + }, + "09efbd6dfea375065be1b3a8f4541f024da21a34": { + "balance": "5870833623000000000" + }, + "0a24d4ae66edc7723bbb314e9b96dc7b9a31e813": { + "balance": "70000000000000000000" + }, + "0a3ee710909382f762648deff8ac7c8b30e2ce10": { + "balance": "407656462445000000000" + }, + "0a42b3145257154e76a97db8147c93be4cffd97b": { + "balance": "10000000000000000000000" + }, + "0a7cb6037f1eba5d19fe781335ecd37b7229c5f7": { + "balance": "74113322448000000000" + }, + "0a85d1bec4d44e309068b115abd517d3733fc56e": { + "balance": "14836218750000000000000" + }, + "0a891ba9ca7b99ecd815b1dcec9243dd4deff866": { + "balance": "178004857988000000000" + }, + "0ab69370b537d4ff5b45704fed293e46e3464f87": { + "balance": "1258876668246000000000" + }, + "0ab77a2e8ab9a3b659d1f1d37956c3607a0f9a60": { + "balance": "6283300817712000000000" + }, + "0abc7e8d52f5b0dcf1d4713e5fa4909102251dfb": { + "balance": "39307290577000000000" + }, + "0af2c0471c802d2e2b20aadf9dd4ec842d313ab0": { + "balance": "1529468143183000000000" + }, + "0b08c717bb3982fc8b92d5b3d30e5b41265a0d0f": { + "balance": "1184600154874000000000" + }, + "0b3f2aa9dc5b57b0469398d62f60a13774ec0e87": { + "balance": "132187640280004000000000" + }, + "0b3ffe85aa89e71a6e51e938c7265d2a7173061b": { + "balance": "2106793086824000000000" + }, + "0b468562e712d22b37e1a65f54b1fa825beebd1b": { + "balance": "15130906006000000000" + }, + "0b5333eb668dee29ebc0e335d74f33ffeaae9ac5": { + "balance": "125953133109000000000" + }, + "0b59a20107495e951b509187307782ca9dfa441f": { + "balance": "25000000000000000000" + }, + "0b8b7fb066601ea7744b81f6e1a21b8e489359cf": { + "balance": "101782000000000000000" + }, + "0bd7791097f79066d71ac0a2c94bce6628a63373": { + "balance": "44389955028000000000" + }, + "0be541af06e167206b5d1cbe08e8fb2b5ebc82cb": { + "balance": "9000000000000000000" + }, + "0bf178bba463f4f6c33e3d81b1a78d220f7b5d4b": { + "balance": "111784804790646000000000" + }, + "0c1f000249b1f1ac9e43c4f10e2da1cc2adf886f": { + "balance": "91251997635000000000" + }, + "0c74e46b115e19726997dd559d2b6ff1bfb79af6": { + "balance": "879229287149000000000" + }, + "0c7c1ec152c920a068c25626c22c4fae7f435536": { + "balance": "39849464104000000000" + }, + "0c85fbd7492d1ae87bf3d286c4750a34f1fd3121": { + "balance": "20000000000000000000000" + }, + "0c9fd6123e313f7d1f0cb25d99839102da08b2c5": { + "balance": "10000000000000000000000" + }, + "0cb051e3bdd9d96e667fbcc00a766d4f149f89e4": { + "balance": "1000000000000000000000" + }, + "0ce32bf6c433cbd26c6f09a1214db0374002784e": { + "balance": "3293279842000000000" + }, + "0ce6374ff04430e34edec8b6323feab2bccab92d": { + "balance": "93983447000000000" + }, + "0ce646412a1524c3f73edfd753c0ba3ee7338275": { + "balance": "10000000000000000000000" + }, + "0ced803e56eac3c99269ff7409d2d200d62d7c25": { + "balance": "49539379000000000" + }, + "0d1dc2be9f78ce2b2591e7f5b8af9dc778499bd5": { + "balance": "2235348003595000000000" + }, + "0d235583458a168e810275f907b5f87bebb2d1cf": { + "balance": "83106439283110000000000" + }, + "0d28fe6e8b7d4b8c90ef7c52b9656511ce5867f1": { + "balance": "1347248794799000000000" + }, + "0d5cbe0da660cbca831787efc45fecb20e06e02b": { + "balance": "297528508941000000000" + }, + "0d7a24f324176f6d793c3a2eb6c54d6ee47eca79": { + "balance": "25637813467000000000" + }, + "0da26a24e3650e84c52fedb36ef76225a8d9d259": { + "balance": "15467820321000000000" + }, + "0db7eaceaf3df21ebb49c56fa2d2e2c8e85dec52": { + "balance": "196000000000000000000" + }, + "0dde52823bd8fb2cb179e6d417c07ff285c31775": { + "balance": "347321514878000000000" + }, + "0df9585f1aa83189e0a813f5eac6e6e0b2bbb8d8": { + "balance": "2891430551000000000" + }, + "0e09af9368f05b476164953b7b9db60ac95248f0": { + "balance": "573644391203000000000" + }, + "0e18315dd2b663ce4859b5bed854403191452c2f": { + "balance": "24174325261000000000" + }, + "0e29bef5f4f66c38a0f05cca1e4938d57ff09c70": { + "balance": "10000000000000000000000" + }, + "0e443353b42e042ff5168e9b3c6de37070368223": { + "balance": "20000000000000000000000" + }, + "0e8cb6e439516b312158f169b546937b715db3f2": { + "balance": "8049136367000000000" + }, + "0e980fab23be601f3abec7b9a24e1335a5e765c8": { + "balance": "8301885845897000000000" + }, + "0ea63fef218ebf570a4ee62ef6ed712dbe623c44": { + "balance": "10000000000000000000000" + }, + "0eb60e3512336e4447ceeb8664ce0ecaa3eb0bdc": { + "balance": "41401696400000000000" + }, + "0edafc1058879a9568e711445b18ec4da31d2480": { + "balance": "10000000000000000000000" + }, + "0efce4565062b23b43dbc1e261463e363e4a5b4c": { + "balance": "10000000000000000000000" + }, + "0f08782c04bf7249ab08f4e251abc60aee792a96": { + "balance": "1380257622493000000000" + }, + "0f19bfe1eb24def828bf1be69791c63ba1de1263": { + "balance": "2223687184885000000000" + }, + "0f2171161eb9674218add261be61d18d86b846a6": { + "balance": "121000000000000000000" + }, + "0f42ef6c5690b6c95f8b8c9dbdc16f717c04852e": { + "balance": "81000000000000000000" + }, + "0f47f5063d321b34a0d800951bcdc3f53c07e32c": { + "balance": "5288516165000000000" + }, + "0f529a9beedb2c2a087a220f0013cea4f8454bfc": { + "balance": "114585457979000000000" + }, + "0f6751d10aaf855454a6e9e4241cfcae3b0ed732": { + "balance": "94160300063000000000" + }, + "0f6ed5a4c3ec100afcd59e9066ba7fcb63cfa6dc": { + "balance": "1000000000000000000" + }, + "0f77025519cc76c38e1cf0bd8721f4a5b9c814d4": { + "balance": "834620571043000000000" + }, + "0f773db2a1a96b775e4481575704f5f087b067e0": { + "balance": "554268361745000000000" + }, + "0fa0f73adbe82f8e09f8adbce15b051971e289c3": { + "balance": "11329911975000000000" + }, + "0fa6397d747d88a25d0c755b3be4eee0e3f68912": { + "balance": "31394936138000000000" + }, + "0fac8635a61bf7652d86725cc75c307949bd4f2a": { + "balance": "49000000000000000000" + }, + "0fb0ce787306ce13dcd614ab3d0e15d9772106ac": { + "balance": "50000000000000000000000" + }, + "0fb1d306d240360056f60f197dc7f68f732ac515": { + "balance": "20000000000000000000000" + }, + "0fe3571f498a6d945e123ac8ff6e3fed348d9432": { + "balance": "20000000000000000000000" + }, + "0ffd6b01ea9a7bd2576fe4a5838fe09e44c1639e": { + "balance": "100000000000000000000" + }, + "100bde3d73fda700369e78229127b58d2ade9177": { + "balance": "10000000000000000000000" + }, + "102028c7626970a28677bbdc7733484c8b14c2d2": { + "balance": "500000000000000000000000" + }, + "10245044be6a46ad41d4559129cb59e843379cf8": { + "balance": "857437279765000000000" + }, + "10417d0ff25c115b25915dd10ca57b16be497bf6": { + "balance": "10000000000000000000000" + }, + "10579870e6685ed7e97dd2c79a6dc3528bae968e": { + "balance": "5187866041491000000000" + }, + "109736465b4bbe31ea65ad01fc98f04498271e6c": { + "balance": "20000000000000000000000" + }, + "109c0535a4a86244c5094e99167d312a77657dd5": { + "balance": "138277702073000000000" + }, + "10aa08064689ee97d5f030a537f3cd4d8bbdaf74": { + "balance": "10000000000000000000000" + }, + "10d8bc8c3d3e2010e83009290586ad85b73321d1": { + "balance": "25000000000000000000" + }, + "10f22b82460252345753875555de2cebebe63a93": { + "balance": "765947730644000000000" + }, + "11111c3a2cfa55e52d6aacf533e1d412f8c8c01c": { + "balance": "4827254128275000000000" + }, + "11386103a0bf199db9504b617ccb3bbd780eb9fe": { + "balance": "10000000000000" + }, + "1156a129183e5bdfdf2bf7a70963285a979363a0": { + "balance": "10000000000000000000000" + }, + "11589cf70a6a4fbaac25224e2ddab222333f78e6": { + "balance": "49000000000000000000" + }, + "1162fabeb3eb1e4124179b00c4a1e01503023f54": { + "balance": "817145350625000000000" + }, + "116a7d140f4b7f9b4689063a8417ac07a32bae00": { + "balance": "106088220142108000000000" + }, + "116dc38ddb4b138b19ce6a51e5922c287da5c86b": { + "balance": "100000000000000000000" + }, + "1175f84f835a5ae40d49b8ca17e3e474c1eceef7": { + "balance": "1698584794716000000000" + }, + "119f822a796fee9c41a488949fcb14b589ffa628": { + "balance": "20000000000000000000000" + }, + "11a99f6019b6a53f5dc8cbd0c34f1ee75ced33b8": { + "balance": "102126982156000000000" + }, + "11b9324406068e8bf598d3a9ea59ef31c52f51fa": { + "balance": "6525925895203000000000" + }, + "11cb7be6869a10f5f9e8a47c6c92f729b083084b": { + "balance": "182959434323344000000000" + }, + "11d96a76166ec579e2b6cfa903f66da4af669351": { + "balance": "1000000000000000000000000" + }, + "11fcee55f78278df60f50096d45da1aafe72722d": { + "balance": "222859488179000000000" + }, + "120a1fc914718acd85bf92d9492330165d78075a": { + "balance": "3736627235906000000000" + }, + "12366136d83c77befdc30e04d4f5d808419f504f": { + "balance": "88008649003000000000" + }, + "12435af3f2f92ec43e8f2894be9c72fa932880fe": { + "balance": "1590548436852000000000" + }, + "124ff67125a00aed24e58b6d64ffa887a59b48a4": { + "balance": "20613022349070000000000" + }, + "1296f04910ebc89556ec7ab1b178fdbf14d0295c": { + "balance": "36000000000000000000" + }, + "1299f180e42bfaa1162d36110d29ab062e43e1c8": { + "balance": "321570118362000000000" + }, + "12abac62150c526866ec958cd0e3721b2c78d550": { + "balance": "51898545633262000000000" + }, + "12b345087cee385b9adccaaaa6741b767c82d7ea": { + "balance": "36000000000000000000" + }, + "12cd5e8c0c93f8e34b589b95954b719f54d1515b": { + "balance": "1000000000000000000" + }, + "12d262cdd25edc39b6fd9ae78184eb548e513927": { + "balance": "500976168000000000" + }, + "12d933448218629702c48547b3446b629ec65883": { + "balance": "2168010577395000000000" + }, + "13054aa42d3e119220ac359641c15f8b54bfffef": { + "balance": "24986834005530000000000" + }, + "130bda09f463a982199849ae617062a1d68f3a85": { + "balance": "154504844790000000000" + }, + "131a5da679863c05dc627d53634f2925ba0ce731": { + "balance": "10000000000000000000000" + }, + "1334f2752b5c21f681ba9e23a9fe95a85f8e05f1": { + "balance": "121000000000000000000" + }, + "13634512e2ae79fe3febb9e55e03b47bc350d7ba": { + "balance": "338331304738000000000" + }, + "136fae842aab625768bef9079ee1711e8c007d8f": { + "balance": "2759741687626000000000" + }, + "139fa969e8b74bee1f6113a362f15060ea998b15": { + "balance": "10000000000000000000000" + }, + "13c7e1d694bde6f8f6a31eb6c99f38dc739d61fe": { + "balance": "10901074773586000000000" + }, + "13c849944ad6ad12a46c46973d562bee8284f46d": { + "balance": "35114615504000000000" + }, + "13ec3aa8f4a427ecdecc7901060ccac9bea7a61e": { + "balance": "10000000000000000000000" + }, + "13f478c74acfd6897d13e602a8d362893f4fd038": { + "balance": "3521111850000000000" + }, + "14403970d0784a6458a7bf2584a53d14234e8860": { + "balance": "25000000000000000000" + }, + "14440bb7410337e34a064a92206075575f5362ee": { + "balance": "14918844868393000000000" + }, + "144a88e7a8af70b8bef5c4b70ee0cff771d0c252": { + "balance": "67961927542000000000" + }, + "146b79f474176a4b0069199b03669ab6467a4787": { + "balance": "122518123211000000000" + }, + "148893e7811c36c6bd1ada367681ab8327b3b2fa": { + "balance": "1313118418375000000000" + }, + "14900a17784e3b4d89d98b6cb31c74c685418b89": { + "balance": "131112181597000000000" + }, + "149a483758a98ffe28f7f25cfa17d7433f852ebe": { + "balance": "10000000000000000000000" + }, + "14a03c8e84f07c5596687a98d1e0b1859e9b34ac": { + "balance": "55000000000000000000000000" + }, + "14c7899cb34b5447d6363d4e8355113ebf4bcc66": { + "balance": "197554844582000000000" + }, + "14efa63ee285277c0f8e0d5cc22193e17984e11b": { + "balance": "106221254735000000000" + }, + "151c6099b3fb5b18e0e36a3335dff186dcd2904d": { + "balance": "4304311254087000000000" + }, + "1525dce233a971eb1387f130fdf0e5bf3455723b": { + "balance": "45004174531000000000" + }, + "15271904676f2bc2511294e500152d05ea9acc85": { + "balance": "9300898622566000000000" + }, + "1556ba42ea69d72c1d0faf802906645268e36aac": { + "balance": "171939212653000000000" + }, + "156558fb71ff986953d899c9916a121fd047675c": { + "balance": "290926338537000000000" + }, + "156fbf32614aac2cf462952ec1a3f141f797316e": { + "balance": "6084388860000000000" + }, + "15b9497d6bde8017baf3c29e12430e05a47efbf4": { + "balance": "206126229839000000000" + }, + "15d532e828bdcaf1246696d679a2eb66a154db5d": { + "balance": "69656571015000000000" + }, + "15e26a60cfaf23dfd9bbb999a30904d11b6ddd05": { + "balance": "9839303178835000000000" + }, + "15f3be2f11ee3b19472cc3d171931f050d8629a2": { + "balance": "13572825921000000000" + }, + "16254bed335420e5f793de2295b0081ac41a08d1": { + "balance": "144000000000000000000" + }, + "163aa91bc2ad588116141d48fcbd943985455cac": { + "balance": "618250979557000000000" + }, + "164cff4b9341d536b8aaf2d1dd0e3ed35ecb1db7": { + "balance": "671554639913000000000" + }, + "164d2a9a63868ac25bfe26ecba446d7ce256c351": { + "balance": "7233638188261000000000" + }, + "164e759b64d3ee0a23ec3030f50a1b454a6ec15b": { + "balance": "12281161499000000000" + }, + "165d4a0f23c016b8064adf0dcf7e31bc06350777": { + "balance": "256757922324741000000000" + }, + "166b862954dacddc3333aba4edbe523d693df858": { + "balance": "123677971414000000000" + }, + "16858eb1a6f0e7ff01b91aa9c92d0a433a5f767c": { + "balance": "500000000000000000000000" + }, + "168909a1c2a43cff1fe4faeac32a609c25fbd1e8": { + "balance": "62258808044224000000000" + }, + "16987ad8e10dda7f9e5d95c0f0ee36f46b10e168": { + "balance": "10000000000000000000000" + }, + "16b5dffce79573300a6514ace5f2e844d26fc64e": { + "balance": "5576805697087000000000" + }, + "16e01370a93befe24f6ae6076cd04c84cd3515b1": { + "balance": "1922179181578000000000" + }, + "16fbafd4fc871c7589e63062133793ab244c2019": { + "balance": "2865030627000000000" + }, + "16fdf76180796c6e4335eaa2842775b2e4a22e0b": { + "balance": "20000000000000000000000" + }, + "17081d4d6ebb9f4b163e181a59c2102c99fce6bd": { + "balance": "490625378000000000000" + }, + "17218ff455aa87b29ad4c4f7ba21e9c6f74fc97a": { + "balance": "1607392037652000000000" + }, + "1725bce47f3700f4646efb343f950e2e8ba66607": { + "balance": "58472967071000000000" + }, + "172c5f71aabf072507664471ebaa435779d74a32": { + "balance": "16000000000000000000" + }, + "173a065f351ee0513cfebfe9b950fd2c641fc8cc": { + "balance": "25000000000000000000" + }, + "174e1793c96cefb584ae0a67fff85c65065dafc5": { + "balance": "50221000010000000000" + }, + "1794bc4d622d514f95da5404358ed404b3f59aa3": { + "balance": "36000000000000000000" + }, + "179839d61e7c7a0382fe08e0573bcfbe42a108ca": { + "balance": "203299791419000000000" + }, + "179eb30b5b28a961eac70a919d26ca96e6472166": { + "balance": "55000000000000000000000000" + }, + "17be72168606fb5d27761157e48fc14789f84634": { + "balance": "311205588354000000000" + }, + "17cefb6611033759b8755197b983de2d7e98315e": { + "balance": "10000000000000000000000" + }, + "17e07cc7d89bcd1708b1f05ab6e1252c629d71cc": { + "balance": "903234908997000000000" + }, + "1811be559b657685c2f163122479101c404325b0": { + "balance": "10060694170000000000" + }, + "181417a4883c429ef26a4baeb48e70d4f00278b4": { + "balance": "4621446218088000000000" + }, + "181d345cd6b5f518bdab8d40f5d4896a725b3f3d": { + "balance": "114349561983000000000" + }, + "184625e544aa31552d2911023a892f739df84be7": { + "balance": "5303698708000000000" + }, + "185e4f6eee203ca3c089baa1e643ff1aab7cc8f4": { + "balance": "33969718257699000000000" + }, + "188e4a1a7b23ff35ec90b7bf7561db9e3c0f53bb": { + "balance": "394325508701000000000" + }, + "18a4dbf513be132f9ecfd69e3eb683d710e28c4b": { + "balance": "5997985132329000000000" + }, + "18c9298f62635ef47d0ef215b8a693af60829c27": { + "balance": "100000000000000000000" + }, + "18e7e2ee0c86bc1ba3595fee3d40257776fe8172": { + "balance": "185584626033000000000" + }, + "196575e74499b741877793f8c8facf2f3b1ddb8f": { + "balance": "30318381929000000000" + }, + "196df33f2d3ed473e6e07650419969f4a39fd03b": { + "balance": "15442864665000000000" + }, + "1975c5293ec9c72a28e6cc74173cdfd8de682fea": { + "balance": "103624886552134000000000" + }, + "19832cd1b2fc4138c8d9291a0f404d3c4326b48f": { + "balance": "4732362673000000000" + }, + "198705f46f31c7ca22f5b88fab210bc5b0c7647c": { + "balance": "548940869737000000000" + }, + "19a5a213e6abfee29f17e871222cbe9ac45322c8": { + "balance": "10000000000000000000000" + }, + "19ab9a7a4e9f9c08c9b4295c406b78389a864ba7": { + "balance": "369299839157000000000" + }, + "19f19f5f01b3f6a1c4f645dc7e3992b1196ccb7a": { + "balance": "97759406000000000000" + }, + "1a11a0b0081522e60e16f154e093ac2e005d24ee": { + "balance": "88024675252000000000" + }, + "1a27309b0c09be2234fd64afdbcfb099f8e2e7cd": { + "balance": "10000000000000000000000" + }, + "1a3d61754974bea23503a61ef0fe584b7b6e6cf3": { + "balance": "326950210355000000000" + }, + "1a49bbde1457a8d4c247606b206ac8d4d389da5a": { + "balance": "402438941516000000000" + }, + "1a7a4b41be64fff3a31eb6166db59741e073d0f7": { + "balance": "250000000000000000000" + }, + "1a8d282e82c606e992f69ce618ba634d98bf2683": { + "balance": "20000000000000000000000" + }, + "1aa0ba27662816e5e3d79e223cc18f5dfef089cf": { + "balance": "187581622694000000000" + }, + "1acab416a1d3e8caa65faca378c79aaf2065b851": { + "balance": "1000000000000000000" + }, + "1acd37af3f87da1dff743dfcb97038d178b1dc4f": { + "balance": "708034481300000000000" + }, + "1ad8f036022c3e5258455d6aa05fb4be5dd121b1": { + "balance": "42957064709000000000" + }, + "1aee811e06c579c21fbcc3b53d2dcf9d5f24808e": { + "balance": "52480060284048000000000" + }, + "1b03b7a4e9908c3531618f49f8d050ba6afb4de6": { + "balance": "28410489187000000000" + }, + "1b073d026e93de51db34d5a8e19047784c277ea1": { + "balance": "20579129628026000000000" + }, + "1b0b87e414bc8fe4920fe104b6de7d17db3a1a19": { + "balance": "10720000000000000000" + }, + "1b411c692c80948e59cd805a0f8574dd67519288": { + "balance": "5416615538000000000" + }, + "1b8d57e995749618c7bb3e60194ac6fc57e9b3eb": { + "balance": "10000000000000000000000" + }, + "1b913efde1255516346b40ae2a48ebf62251682d": { + "balance": "100000000000000000000" + }, + "1ba7276c133f93d43db2f2caddec08e0167eaf15": { + "balance": "82559173174000000000" + }, + "1ba919f7742160cabf2756eb6eae67b92530f3f3": { + "balance": "1102304139883000000000" + }, + "1bb20857de494694fe15bd11f8cac1218435fbc0": { + "balance": "10221322567000000000" + }, + "1bb5c5e81d451f03e899852edc8556a9f7aac5df": { + "balance": "18781017696028000000000" + }, + "1be3507349ed07d3e7902951d490f560a75e96be": { + "balance": "660691718918000000000" + }, + "1bf1c0b2e6f64b612f35f2bf98d894b13dda9bf7": { + "balance": "3050161851140000000000" + }, + "1bfd3c2ba6a537e97cedd542cd554a5050963d54": { + "balance": "20000000000000000000000" + }, + "1c4af5003f9e7223f4141107d21640e4a85a4827": { + "balance": "612390629874000000000" + }, + "1c6a94810bd0afcf79ceea11afe86c34f6813211": { + "balance": "10000000000000000000000" + }, + "1c7e277460191c886cb1647173d27122c2146252": { + "balance": "209062806527000000000" + }, + "1c818ffa9caa61d512fa5d7d6e566f3ae37d5434": { + "balance": "454897845316000000000" + }, + "1c9599d5f8e5eaf8f68d35d52132e15a153f6d3c": { + "balance": "36000000000000000000" + }, + "1c95ab5229fd08c638a1728c022f09291b8dc55d": { + "balance": "20000000000000000000000" + }, + "1c962808c175ee5e5e365483d066c8ea95993700": { + "balance": "1362779746855000000000" + }, + "1cafad295b2188f10192c8a32440931f7e3554e4": { + "balance": "36000000000000000000" + }, + "1cdc2899ec563d79569d1ba776bc03cff331e786": { + "balance": "572163587827000000000" + }, + "1ce0042e7b4f13589f5f8490836dc63e0ca60c3c": { + "balance": "25000000000000000000" + }, + "1ce62051fd7801d294bf31a7b44cd87510e8b545": { + "balance": "2008112411284000000000" + }, + "1cf20f30cd901b2e5fef3f948289dafaaabaa77d": { + "balance": "1444000000000000000000" + }, + "1d449764d38b7a4ac848f49e2dc99df02dfd8a53": { + "balance": "48215693645000000000" + }, + "1d635125c494b1137ca5f15ac95dd6d93c3a9546": { + "balance": "10000000000000000000000" + }, + "1d85a61353c3e0b6d34e105e35c8c7833b6a1e35": { + "balance": "16000000000000000000" + }, + "1d969134ee156c41c98c3721c5dbb092c0b581a6": { + "balance": "64000000000000000000" + }, + "1da12434596a9c318dab854f06d404fe61f0a69d": { + "balance": "16675185416000000000" + }, + "1db0d23fb63681958a66e716e99df3e0b848fd12": { + "balance": "1103581911968000000000" + }, + "1dc628820da657f07ab5eb887d5f512378b5b61f": { + "balance": "6272287019755000000000" + }, + "1e05cba75b0dd379037940352e0073564957b7d9": { + "balance": "12453446342664000000000" + }, + "1e13f037a92ab6f19c4484ae3301b3ac6f48575d": { + "balance": "106244918916000000000" + }, + "1e167bc07f094915c00e7aa4c43b607ed2c998b9": { + "balance": "1000000000000000000" + }, + "1e1f9409bf92c3ef59aa2fd82dce55cd90e23f19": { + "balance": "99139000000000000" + }, + "1e4dfea7871d941e72a161022b62fdb01818c86d": { + "balance": "81000000000000000000" + }, + "1e5d0b525228167334e94314a201388bba08153b": { + "balance": "1138044078759000000000" + }, + "1e6633290c9898abf5fcac54396de770164edc5a": { + "balance": "25052055674000000000" + }, + "1e76296584058670ea80fe9a39d8f457c03747c5": { + "balance": "10000000000000000000000" + }, + "1e88b2c8dcd289929e51a15c636d0b0f3b035569": { + "balance": "87357600832000000000" + }, + "1eb59a1732a159a91a9371650943840e0eb61174": { + "balance": "20542821429000000000" + }, + "1ee077bdef6d45d491602342cee008cd1e2912e3": { + "balance": "10000000000000000000000" + }, + "1f1ebf2f80afced68424cb7b0b966fdf42d508a4": { + "balance": "1460082126494000000000" + }, + "1f3d4a903bd32a537efae19592f5516698c95a20": { + "balance": "10000000000000000000000" + }, + "1f6431696efc6f1ab98dcc2ef0e8553da697e6f1": { + "balance": "20000000000000000000000" + }, + "1f657552b745acbdf731f2ad107d6362480abc88": { + "balance": "162042599568000000000" + }, + "1f699a7682c1266291a3f49e19cac0846470abf5": { + "balance": "712268213248000000000" + }, + "1f7a332dabb00851705274c59187817d859cb9a4": { + "balance": "199999999160000000000000" + }, + "1f7c333047e168f5d3408c42a4919bd44b8f7961": { + "balance": "3918096658000000000" + }, + "1f8226f7a4525b9f3cd4da3acc1bb34529f8d28a": { + "balance": "3530829464000000000" + }, + "1f8b6fcea9e0991ad0b0b25dc65748518a28713f": { + "balance": "142069368416000000000" + }, + "1fa3de6913e4de78cc4828e246554785950c3c8e": { + "balance": "178437291360000000000" + }, + "1faa75d57fd597d2b58d2ac6f65bc2bd5946911f": { + "balance": "13092024644362000000000" + }, + "1faf1721dba3266cde1e04a7e9c789bdabdd930d": { + "balance": "862698523071976000000000" + }, + "1fb861559361701fca1df6ab4ef4d2fb9d2d7e13": { + "balance": "100000000000000000000" + }, + "20154d678cdde9ca1c0acb94726f26617a4da0d8": { + "balance": "2288800561677000000000" + }, + "202484a46ca9d54d0d456bc38e2a74ec5f469349": { + "balance": "50178714107336000000000" + }, + "20324278018b4d8e0c49e0fd1be35d3494079165": { + "balance": "484082383314000000000" + }, + "2033ef68ef6297e9229bb73e6486330543aa3eb7": { + "balance": "51260669473000000000" + }, + "20b1e0ab7b9d62a314946b55a5775f24ae3cfa00": { + "balance": "1540424185584000000000" + }, + "20b61f2eb5e18b1e8568d18235918f9e2f596c32": { + "balance": "10000000000000000000000" + }, + "20ed8ca39dd148edf22e03b8021af32cecadd42a": { + "balance": "20000000000000000000000" + }, + "20fd5feb799fbb021ba262d28332b4dda8f44a2c": { + "balance": "7607475714434000000000" + }, + "215ab8aad1c8960838225294d086f0786c2dd796": { + "balance": "19929201327000000000" + }, + "21681cda53aa1a4cfb3e3ea645c8eeaecfc3ba4f": { + "balance": "10000000000000000000000" + }, + "217b75eaf2c0be12108120ba56ddb709e1885324": { + "balance": "36000000000000000000" + }, + "21be1d75b93e96017f088f1ca64ba7076c8edf07": { + "balance": "150798073752000000000" + }, + "21ccdbe0216b486cb39c94ed13767aa061c75ce9": { + "balance": "11070639373000000000" + }, + "21f2289f2d274bddd7928622fffdf3850d42d383": { + "balance": "268859368544000000000" + }, + "21f54f92a7d9a91915e1751ceb02cb8e3ed3d622": { + "balance": "10000000000000000000000" + }, + "2202c70ec23f4605394d69944edd9f90e488eb61": { + "balance": "9000000000000000000" + }, + "220e2253e1ab9ec348cc28d38bae4cb2d5d9cf8f": { + "balance": "116100821631000000000" + }, + "22328e434957107884854999e666ad0710187e3b": { + "balance": "233364805270000000000" + }, + "22851c0487d119ee3f150010515358d6ff14807a": { + "balance": "104464221701684000000000" + }, + "22a38000f5eca29001e387b52c18fb6030683fac": { + "balance": "55000000000000000000000000" + }, + "22b655a19810307750ed1b6b093da10a863d4fe2": { + "balance": "11840799203605000000000" + }, + "22cc48cf48e8ee207bc08411240f913a4e594529": { + "balance": "10000000000000000000000" + }, + "22d6ea6cb8a9206285ccddd3b6d0d1471ba66f17": { + "balance": "64000000000000000000" + }, + "22e2f41b31a0c69472a1a02d419886539b7b6197": { + "balance": "39885451304000000000" + }, + "22e962f91d01480d027ee0060030f529a7a64c8f": { + "balance": "93285203531000000000" + }, + "22f169328fb1104b386ad7fa69f0c7bf3e9a7d3b": { + "balance": "63366769386000000000" + }, + "22f35f5e0e7a8405714de66a5875c7ef84ec4891": { + "balance": "60944382032000000000" + }, + "23041bdc8d371dc29ffc890f19317dabeef12634": { + "balance": "402327389857000000000" + }, + "230eff5e8595f418686737ae671f1f1d225080a5": { + "balance": "114574598112000000000" + }, + "2331e1756d9800800fc9b54ee6e43e1150b6e58b": { + "balance": "44594796226000000000" + }, + "233a72b132e4ab1d3884274d4402d1a2a6399f0b": { + "balance": "1372148909093000000000" + }, + "2369d9dbbfd0f8aa8a3d84d8f2aea840a0cdf760": { + "balance": "500000000000000000000000" + }, + "23754e5cef31ab60aa97a0c8f9ccb4f2969f2d6c": { + "balance": "24764775861000000000" + }, + "2387973589fb07a8c1ec92492c0b8ba9ab5e52a2": { + "balance": "11642113696681000000000" + }, + "23950cd6f23912758ebe9d412166e27994fe6ec2": { + "balance": "100000000000000000000" + }, + "23b383e11573f3ca9be84e1e11694f58a432324b": { + "balance": "206558238838000000000" + }, + "23c329bb641fa51122ea476e3bc614f5d4f9cf00": { + "balance": "35908627324000000000" + }, + "23cb9f997c39853486adfc1a8b029874d1a6af15": { + "balance": "1400984459856000000000" + }, + "23ee14215c531f6ff1baef2c74b1754306f4532d": { + "balance": "10000000000000000000000" + }, + "23f641f765cf15665b6c28d77229d3b2a58fd857": { + "balance": "266570948120000000000" + }, + "23febb49d9541360b9d099377df16b5630dfbb52": { + "balance": "228513797641000000000" + }, + "24082040652a09cbed6504f3dd6491e0ee9d2bff": { + "balance": "91160839809000000000" + }, + "240d3edf4aaf42e99d366ca36d82c370271b8e8d": { + "balance": "65535355843947000000000" + }, + "242b63ebf47678f17c176d5d4a670e46e66a823c": { + "balance": "469668185647000000000" + }, + "2433612fb939236a87a97261ff7b3bc7b754afb1": { + "balance": "20000000000000000000000" + }, + "246bb03a3fab572b3c64fc23b03dfda42b7ea34c": { + "balance": "936364046000000000" + }, + "246c510dfaf5b49bc0fe01c8256d3879c1b5f89a": { + "balance": "100000000000000000000000" + }, + "24bf4d255bd3db4e33bff1effd73b5aa61ae1ac2": { + "balance": "302436106595000000000" + }, + "24c0378e1a02113c6f0c9f0f2f68167051735111": { + "balance": "36000000000000000000" + }, + "24cf04b7450a0fac4283fa6fcfef6215274b273e": { + "balance": "83714002622000000000" + }, + "24f5f8e7d6a23b55c95fcdc1300de05f9d2abd83": { + "balance": "20000000000000000000000" + }, + "25204bfb27a08dbdee826ad6d9c3398ec6d14fe1": { + "balance": "5929256591480000000000" + }, + "253d95911b4174805d13706b449879413b1672be": { + "balance": "37012901440000000000" + }, + "256065f7e919c508b68957b1d2c9120d29181e12": { + "balance": "25000000000000000000" + }, + "25624542c14c2ecb9a0fe7daec9ac5af16868ee7": { + "balance": "16000000000000000000" + }, + "256d05b6de445179e504a6c94ce1253ae159e19a": { + "balance": "12048598744001000000000" + }, + "256d37fc8980a969063b1f7e7fda8b87d4210da6": { + "balance": "107293553721000000000" + }, + "2588af91a0e8f3ba3ab636781bb84e263acd1f52": { + "balance": "8910000000000000000" + }, + "259774584d4fcae1d84f5997c00beee8a380e46c": { + "balance": "1140713354605000000000" + }, + "25bda1418853a22eb6a5380e8a2862d2a74949bc": { + "balance": "10000000000000000000000" + }, + "25cafdab7f79f7b95d55b4c2dda1f4080aa74d64": { + "balance": "2525573681000000000" + }, + "25cca69b41bb51c51b387c47ece83f30b9a78daa": { + "balance": "163449631440000000000" + }, + "25ce9dabd0a72b02e0056931155ba99c94cbc837": { + "balance": "230073284349000000000" + }, + "25d9d1785c96acddd926b3ed52987ff74f9083f6": { + "balance": "780460361789000000000" + }, + "25e56bd3e1461f27db4eb0cce8bb5ca1574401f8": { + "balance": "1001937531200000000000" + }, + "25fa2162d5c86cda10e4be42c14a24329e455ad8": { + "balance": "50000000000000000000000" + }, + "260a932a23b344056acb8e676714ffac0a13ad2b": { + "balance": "2000000000000000" + }, + "2622efe8836095fcf48d9c8019f48c8320d6e0f2": { + "balance": "5451866545636000000000" + }, + "262447c4d8826ed23ea25e9703a11b4ad3ae9388": { + "balance": "33992454005000000000" + }, + "263eee3badb9b0dd13579c09361806503705a1de": { + "balance": "1134831344000000000" + }, + "266f4c232ebc946c46979cd90d70868380e186d8": { + "balance": "20000000000000000000000" + }, + "267dfe6fa918686942f5e1d19d5fa615f6f2086d": { + "balance": "3569373363935000000000" + }, + "268ad2272c2b71243a7391020a600fd8dfa42d45": { + "balance": "122768017414906000000000" + }, + "269e4f43be9865f05a277933c2fbb466659ada7f": { + "balance": "22064992930948000000000" + }, + "26ae161c20acb26a320fbfbd60c97335cda28bca": { + "balance": "170710653621000000000" + }, + "26b4da905780fb0c5c3e7e5315989fed3aeef135": { + "balance": "20000000000000000000000" + }, + "2704312aa5a4202f14fa3b08e587e4f0ef13accf": { + "balance": "124259630994000000000" + }, + "2704e4b0e8df0c1f298843109ae3bb26c29a22c4": { + "balance": "3155521256785000000000" + }, + "2709347d12251c01aac6455108c6bebe72f0af2d": { + "balance": "220898650215000000000" + }, + "270a32b41dde877463d2106ea4f4529557a5e1d3": { + "balance": "10000000000000000000000" + }, + "2738b3746d6bda9bd72858eaa76f8b5ce7a88c8c": { + "balance": "10000000000000000000000" + }, + "27593d2271aced83e81034e8dd603d098238320c": { + "balance": "20000000000000000000000" + }, + "2771ba4b5944bb12d74b1888255c60e0db215fd2": { + "balance": "412946979808000000000" + }, + "27780086136ea3e97d264584d819dcb2176d7544": { + "balance": "292224348060000000000" + }, + "278936fff8afb553043f038c39fe93906bdb1f4f": { + "balance": "1448466441752000000000" + }, + "27aa0d45d3506f8446816e0e2e9675d46285f6e0": { + "balance": "20000000000000000000000" + }, + "27e655dcc5728b97b3b03fb2796c561090dced1a": { + "balance": "9841344000000000" + }, + "27eb0529279f7a71e50efb70bb1767cbe1ffa4ce": { + "balance": "10000000000000000000000" + }, + "27f564956c837d7949739f419d6ac99deb33d790": { + "balance": "1505247707018000000000" + }, + "280f5618a23c41ac8c60d8bef585aa1cc628a67d": { + "balance": "1316618646306000000000" + }, + "28167a591d66ae52ab22a990954a46e1555c8098": { + "balance": "1000000000000000000000000" + }, + "28257eeb8d20f2fe5f73b0ff2eca3214e30ece4f": { + "balance": "95924728584000000000" + }, + "2827abfc49828db0370b0e3f79de448d46af534e": { + "balance": "769862008499000000000" + }, + "2832b92434e3c922206c2408442bc8274606cbd9": { + "balance": "103421320914027000000000" + }, + "2854f190a38e9b9c04cf499259c6577a68b0b5ed": { + "balance": "144000000000000000000" + }, + "288923bd91be164496e5378ee484f0e4c6c16ed6": { + "balance": "10137243270703000000000" + }, + "2897ff80794153edb721801fb91c6d8373c965f4": { + "balance": "10000000000000000000000" + }, + "28aa06e2290010374097aa2f87a67556d8d68083": { + "balance": "84783245638916000000000" + }, + "28b04ec8eb18b0c6a384f9d92cfb44d1d43ecb51": { + "balance": "14364248730194000000000" + }, + "28db0c000cad3a524bb68dfdd74ffd47b42fb13a": { + "balance": "43586590410000000000" + }, + "28ecd4c5fe98cff66a5b8423f4a27cba9634e2d0": { + "balance": "56106658052000000000" + }, + "2930822031420731f09dce572554a8b8c1eaa09b": { + "balance": "1170839742000000000" + }, + "295154c4522d7bcb2e24b7de9c543dcd1c5f51d9": { + "balance": "179028680906000000000" + }, + "296be4ef7402b00d7af673c1770a50162d7ab602": { + "balance": "8206640005889000000000" + }, + "297b84150756fa89101dd59750a7beb36fb8785c": { + "balance": "1168894124400000000000" + }, + "297cfb72cd1b8b2808fd1b25cdcf7d8de279ad96": { + "balance": "500000000000000000000000" + }, + "29cec0eca9f8508a1ba192a90bb6dee18c40745a": { + "balance": "260217025084000000000" + }, + "29d8f7e72bfa297f17fdce9cf8f4a398f547e200": { + "balance": "307787433251000000000" + }, + "29e14b01c59ba894dd090382fb193ea441164b90": { + "balance": "229028661439000000000" + }, + "29ed634e165084b720e446d28893dbeecd6a7018": { + "balance": "226530464200000000000" + }, + "2a0f8136d43248233f652fe579ef3bd2281dde24": { + "balance": "4007544428000000000" + }, + "2a10204a0c7c9f7701e33c1b71c9427ea16e2e45": { + "balance": "50000000000000000000000" + }, + "2a319ee7a9dbe5b832beae324290f7df6d66f516": { + "balance": "28127560161000000000" + }, + "2a50bfda2b06a9fb28c73f14aaff4f7ef865db65": { + "balance": "10483823413828000000000" + }, + "2a7b7feb145c331cb385b9fcb9555859c16820f6": { + "balance": "1017182951264000000000" + }, + "2ae076c36b18a60f1e3c05d434276a1e16f3f838": { + "balance": "10000000000000000000000" + }, + "2ae2e51ea2ee6a848acde342db2bf6eac927e5af": { + "balance": "494279795271000000000" + }, + "2afd69fac54c167e7ca9d8198a8de386f3acee50": { + "balance": "227162683047000000000" + }, + "2b08018d6e65a7b74ddb5ce1af99976a484b9f50": { + "balance": "16000000000000000000" + }, + "2b0c1d629ad2958ab91e31f351a91219fdbca39e": { + "balance": "113239399820000000000" + }, + "2b2bb67fe9e44165d2108676579a9437c760da30": { + "balance": "20000000000000000000000" + }, + "2b2c99e88e938d1f1416a408a7d0041a605bce16": { + "balance": "6118539729000000000" + }, + "2b5c97b6402ac189e14bbca3e7759319ca8a9222": { + "balance": "10000000000000000000000" + }, + "2b813339c7f818f578b45f17c41c7e931c7828e2": { + "balance": "842834712955000000000" + }, + "2ba6fc21f743968d51f80113aadfc0fdfe8499ed": { + "balance": "309973507270000000000" + }, + "2bb75b272b279cb54498f12b6805261af643c8b1": { + "balance": "1426727673809000000000" + }, + "2bdac062364abd9cf67ba7de214a2cceb0511033": { + "balance": "1090525272063000000000" + }, + "2bea658caa805241aa921f48c8f10cb49e16ffae": { + "balance": "1295499213027000000000" + }, + "2befe7e34299a7c1ad53fc9988ce77e2d9fab20b": { + "balance": "4326342236300000000000" + }, + "2bf466a83cd44aaf0f627606a1c954fd31deb782": { + "balance": "1388986370166000000000" + }, + "2c016a23890e9633fc17b0a8d328ec1ec7ee0113": { + "balance": "92483174342000000000" + }, + "2c45a87a63cc5c8c102d12b83bd9a3501ee41995": { + "balance": "394657687589000000000" + }, + "2c600a596368405e584f3b869f7fabef4ce54aa4": { + "balance": "9879984853585000000000" + }, + "2c7032da8b7816e16095735aee43d1c3f1c43acb": { + "balance": "10000000000000000000" + }, + "2c7275511fe06ee86663b3a618497168b35b0cdf": { + "balance": "10000000000000000000000" + }, + "2ca4074843e9519265447c0dd9ac84ddc2033c1a": { + "balance": "179612279567000000000" + }, + "2cac03ba2c45a6c8186bdceb095b7c5feced3114": { + "balance": "2022060470376000000000" + }, + "2cb8c2cd506b2d7b4cac88ce63230022d412c62d": { + "balance": "211378154058000000000" + }, + "2cd27561cf37ec229982dd592c71d1aab9c2d7d8": { + "balance": "42189968284000000000" + }, + "2cd2e85310a4fbb7f296c3d0d1cee07b191239eb": { + "balance": "1940327317417000000000" + }, + "2ceca4501c5f2194518b411def28985e84d42913": { + "balance": "25000000000000000000" + }, + "2cf7abd42394634689aa2a36d263a6345116b7df": { + "balance": "3553167226295000000000" + }, + "2cf88f29356c166df8383d3312cea10397e25150": { + "balance": "76961677759000000000" + }, + "2d0b62fe49592752cfebaa19003a60b8b39b1cb9": { + "balance": "10277397502735000000000" + }, + "2d2051887107bbd8ed45b405b9be6974a13172d9": { + "balance": "1928781992000000000" + }, + "2d2c9525e2811f4d1016c042f476faf23274aa31": { + "balance": "1000000000000000000000000" + }, + "2d2ef9e1c7a6b66d9a2994adb3ac4a9921408e69": { + "balance": "10000000000000000000" + }, + "2d3bcd18e5c97ddbf1cd28ab37eabe070e9a04d1": { + "balance": "323879852538000000000" + }, + "2d3e60496d0092a4efc665389a916be1a9f8b378": { + "balance": "161958437779000000000" + }, + "2d3fb0ae9b17d3a57d23549ae5500fbb163de25d": { + "balance": "25000000000000000000" + }, + "2d8106dbee6f728c0ff11887690a6370a7d9f5a5": { + "balance": "3102418708000000000" + }, + "2da48eeb788686811ac8270ef3baf0159fc47446": { + "balance": "252187695395000000000" + }, + "2da9d2a6f0b92651a36b05c5e9d2a717c6e166de": { + "balance": "500000000000000000000000" + }, + "2dad81b23d8447190259119019c04a4ef61ab91f": { + "balance": "53428719965000000000" + }, + "2db1faf35901e272aee74a2469a278fdaa6e6e18": { + "balance": "100000000000000000000000" + }, + "2dbae8e1ad37384ca5ff0b4470d3dbc73559841c": { + "balance": "10000000000000000000000" + }, + "2ddf9e23945c181b8592d7965e782068b4c38b37": { + "balance": "100000000000000000" + }, + "2def05d1f2abbaa193a219b87e5319c7ecd48dea": { + "balance": "51359946957000000000" + }, + "2dfd221f96a21e41ffe4dca67b15cd352fe9637e": { + "balance": "36000000000000000000" + }, + "2e1371fcfea9d8dc8e692897a91753400caa9c3a": { + "balance": "5199902650733000000000" + }, + "2e2e04945adbfaeec698ea0f5275f1ad5ffd3d5b": { + "balance": "42034514567000000000" + }, + "2e41f865cfbcf8b89f848405e04de9114087f4ff": { + "balance": "44875730962000000000" + }, + "2e530254768ce94db0ef1204ede0e12b3558e7eb": { + "balance": "14319506377747000000000" + }, + "2e5c43868f45de268967fb22f3f4107da401510d": { + "balance": "20000000000000000000000" + }, + "2e5d2e117d2ba9af9697ec023a4d10b5a2436902": { + "balance": "16000000000000000000" + }, + "2e6000778fb225ddb3e1a2f297d56774e85d9c9d": { + "balance": "10000000000000000000000" + }, + "2eb64b8ab13f0d7823158217d15ba310ed3d0e58": { + "balance": "58724606000000000" + }, + "2ec3973ff33a06d355ad4e8f73b657af8a5ed8e9": { + "balance": "1165606294808000000000" + }, + "2ed4362ea5edf510e210af733089b294f87e8f67": { + "balance": "427561040806000000000" + }, + "2ed8788f1c31b508e37079098a7337bff77b49cc": { + "balance": "10000000000000000000000" + }, + "2edbbe1e2ea482920c76a4ff4c14602b4d37c955": { + "balance": "294409476945451000000000" + }, + "2edcba2bd76128750c8aa00f832c62db30aa7868": { + "balance": "25000000000000000000" + }, + "2ee5abcc0d0d51d4b18947b5aaaa95d037be4e2c": { + "balance": "20000000000000000000000" + }, + "2f058187ef141c06c7c87da86cc1953d2fcf70fa": { + "balance": "9000000000000000000" + }, + "2f16b101da9986a18f4b0d30a26557860338c4e0": { + "balance": "254907899725000000000" + }, + "2f4363df2c61273d230071286bb0157dfefee2cc": { + "balance": "64000000000000000000" + }, + "2f6099a8cb7bc3713b87dab20994d8dc09342003": { + "balance": "1902400000000000000000" + }, + "2f7b3902ce56f74adb0f83cc7d3a99df440cca1c": { + "balance": "825246221388000000000" + }, + "2f7d0298ff6a363375b7eecfe754fca0963c8a1b": { + "balance": "101000000000000000000" + }, + "2fb7c16232b3b1f2e3a676d6d5c93ae6fe5cb14e": { + "balance": "1000000000000000000" + }, + "2fbd5ccc716d2f510d10ec84def3fa69e49f46ca": { + "balance": "1000000000000000000" + }, + "2fd84376be11772e5d072cd74c96b0d9a49c27fb": { + "balance": "1000000000000000000" + }, + "2fdab070e20e2c8923a24c196bec72c33ff0f220": { + "balance": "64000000000000000000" + }, + "3003e6007f69902a0f5e4b4e6d0468277897fc70": { + "balance": "1501210602075000000000" + }, + "30095e6a4ccd1ac2014c3d1d98dce003d775708e": { + "balance": "500000000000000000000000" + }, + "300e47e0fa556371f6c882eb98423be44de7c239": { + "balance": "9108837665958000000000" + }, + "3011231224920b62bcfcbf0aed4fde35dd0a4bdb": { + "balance": "374689586073000000000" + }, + "304be24debce62e70943efddd20457d34e85ab40": { + "balance": "81000000000000000000" + }, + "30912555bb14023e9b7c90aa2314721918cdf1f9": { + "balance": "10000000000000000000000" + }, + "309a94ca7b44bc84a7909ee2b93ed1c94eaf75a1": { + "balance": "39000000000000" + }, + "30bcc93965fa36bbaabcd781326e42227c4e1a51": { + "balance": "10000000000000000000000" + }, + "30c71fed91d24bff69f286ff8f0c6c02a21736a8": { + "balance": "409782329653000000000" + }, + "30cbaf4103757013fd8fb71c44a985939e212b86": { + "balance": "7424807960947000000000" + }, + "30dd59e66093d0bfd87b09c5f6588b9857e9a6f7": { + "balance": "26123006239871345154" + }, + "30f692235f254b02f583d5b515f4701a35c7f692": { + "balance": "148184457997000000000" + }, + "310763019a24a927ce42b00604ee664ca53ff6d0": { + "balance": "393757908273000000000" + }, + "3118a5d4d06ca8b7c8835f4860e6973228000ee2": { + "balance": "56188713212579000000000" + }, + "311adec5bfcaed44680691cc644ee120a484aa05": { + "balance": "169000000000000000000" + }, + "3124e387aa7023995643344c782dac84b9d8c7d4": { + "balance": "1393596696367000000000" + }, + "31379702391cb5a737db3f3ffc336bd03aaa181f": { + "balance": "10000000000000000000000" + }, + "3145606c3ccbaf337610185ffac14ac4f0583c0b": { + "balance": "196454968572000000000" + }, + "315e11501d2c57a62af1631fc2662d4d8745401e": { + "balance": "225000000000000000000" + }, + "31a785ad3eea177c59fb575cad0b44f9a48a12e9": { + "balance": "38039017162416000000000" + }, + "31ae64035e95c1205bf957afb5e1636df00dea3d": { + "balance": "1718600907000000000" + }, + "31c0bb22fd2e9d22984f248a16ec3ed9ad834517": { + "balance": "5982762676000000000" + }, + "31e73a3b5451ebe1163571e9e0567c425bbbfb83": { + "balance": "10000000000000000000000" + }, + "322543c74039ef61fd051021b5e6f16b54bc7c1c": { + "balance": "101346282441000000000" + }, + "3233c7ed11c25bfc41d506c3ae0daf5a3c7c1278": { + "balance": "20000000000000000000" + }, + "325dae17b5225f6734a02c677d43fd126bea89b7": { + "balance": "365067246683000000000" + }, + "326ce8166a4094b93c15557f50f2b1d47811e72c": { + "balance": "16641460224765000000000" + }, + "32cf76046ae48b609524b1a6203eb6296d04853d": { + "balance": "1094839482061000000000" + }, + "33456a28f36aa240262cf95b78b4ac2cd8aa77f6": { + "balance": "3077123488326000000000" + }, + "3348bce2ef90ffd6a59ef5079e1af84b2dd604a7": { + "balance": "9000000000000000000" + }, + "334e5f0ae77dcd3d32dfc2c4ec6ab5e2826dc4b1": { + "balance": "3176777762079000000000" + }, + "335775e19200cd0305e529bc4cdf7295a47cb2d3": { + "balance": "2945631571804000000000" + }, + "336ba81ea6ec4f0da38c1a1761ed3d97fd3ca28c": { + "balance": "3587379203826000000000" + }, + "339191e03e9d5a08ae7b58f4c860235a0721b5a1": { + "balance": "2732237722000000000" + }, + "3399bf9f94c5488c89450257b39fdf3ec8c7f413": { + "balance": "477423805836000000000" + }, + "33cb8556a6c6c867e1be7de591cb22c1b7e9824e": { + "balance": "62293494164000000000" + }, + "33ed633804f39367078e830328dd223254be3366": { + "balance": "22842013797896000000000" + }, + "3409025dce86ad441a5a80f30ce03768d37e40bc": { + "balance": "1381667933000000000" + }, + "34153174cd4d3f1eaed7438638d302f6414d5965": { + "balance": "50000000000000000000000" + }, + "343c6b82b13f0dc82d4269e2c806d2d58e6dde35": { + "balance": "9546969736042000000000" + }, + "346089ea81f7dcb79caf2444df34bd6ee78be4bb": { + "balance": "4344080889000000000" + }, + "34984a8f96dbbfd1f977826a4c2187482559a2e4": { + "balance": "25000000000000000000" + }, + "34a5cce96d2211feb04472260c4cd368bda8432e": { + "balance": "1240050112677000000000" + }, + "34c026a39e44955d1051e8669f9cc58a027455c1": { + "balance": "20000000000000000000000" + }, + "34d730652f4aa002a9f39a47212ca3bc47506b8b": { + "balance": "418050617956000000000" + }, + "34e1d8c8a32ce0f6378abb9bd05ea1f9bfdc5782": { + "balance": "20000000000000000000000" + }, + "350b228870445141f4417ea5dba4f009d693b96c": { + "balance": "76995849736776000000000" + }, + "350eaec708d5d862831aa31be2c37b2fdcef97c6": { + "balance": "258753545822704000000000" + }, + "351fc1f25e88b4ccf090266ebb408593418d8fde": { + "balance": "10000000000000000000000" + }, + "3523ac7a6e79162bb8400bf161cb59389432aa51": { + "balance": "436606776923000000000" + }, + "354d490095e79a29bda2fa11823328450f14333b": { + "balance": "50000000000000000000" + }, + "355a555a36e319e76042e62875a15e1db3012b86": { + "balance": "20000000000000000000000" + }, + "3568840d0a26f39248ab088653ede831f150ce29": { + "balance": "16000000000000000000" + }, + "357096b9c1c7c8d51b682ed3c43d150f55629ff2": { + "balance": "900090781248000000000" + }, + "3588c47ba9204b672c456ee9b5c1ae70f3c738ac": { + "balance": "10000000000000000000000" + }, + "3591edeb9c036e871b4fc6fb3ae6d42e0c0d7203": { + "balance": "1000000000000000000" + }, + "359d92e3e8757a4a97187a96d408c0c11f5c7eb9": { + "balance": "22330509101591000000000" + }, + "35aac2a948f316ba93ed111ac127e29ee9a3adb0": { + "balance": "364387817746000000000" + }, + "35b20459a7daa5f44ae423fd4a1b451ea5090b09": { + "balance": "20000000000000000000000" + }, + "35cdaa84c1f3bc2673bc0c60222c133bae0d3db1": { + "balance": "15234182435000000000" + }, + "35d554233ca690130aaa43501e121a208c657226": { + "balance": "10000000000000000000000" + }, + "35ed399940ece44d01ac873b9c0d3212e659a97e": { + "balance": "55000000000000000000000000" + }, + "35f164612afc2d678bb770f317085ae68cce19bc": { + "balance": "693763596328000000000" + }, + "3601b36cb475101d0d0976a8de9d38e5f3483a08": { + "balance": "1000021000000000000" + }, + "361368bc42c8daf365bce9f9ff3b611373d7b690": { + "balance": "21658400518000000000" + }, + "361bc43be077a269e3e37c11e91479017c47f847": { + "balance": "268900383140000000000" + }, + "363c7a2203f6f93287de091bde3c87eb6800e7a7": { + "balance": "20874859005000000000" + }, + "365dc06856dc6ef35b75b1d4eabb00a7220f4fb5": { + "balance": "30000000000000000000" + }, + "3660e246bce68e2b6e4a802681f188587d2c1c99": { + "balance": "55000000000000000000000000" + }, + "366868ef8e193d7e649ee970d476e6774d5ff1ac": { + "balance": "2544456626840000000000" + }, + "366f7f762887cfb2d09cefa4a5108cf390bdeb41": { + "balance": "26837527714000000000" + }, + "36759f9c92a016b940424404de6548632c8721b1": { + "balance": "1033159825798000000000" + }, + "36a939be88508646709d36841110015bf7cedd90": { + "balance": "144000000000000000000" + }, + "36adca6635db6b00d28a250228532fe560127efb": { + "balance": "3370820618318000000000" + }, + "36bfaed8099ee9f216193ade26d21656c98ce4b5": { + "balance": "1353728563832000000000" + }, + "36df854d0123e271529a8767d1cded4e7b5f31d6": { + "balance": "10000000000000000000000" + }, + "36f59989a902cd10725ff7fe2cab1689aa4e9326": { + "balance": "20000000000000000000000" + }, + "370d6999ae70e781c81d12dc259ea304183b01eb": { + "balance": "45563989086590000000000" + }, + "370e8af59a64a3171b422913921a1e2f982dd512": { + "balance": "170263356254000000000" + }, + "372e01083072214134018f50bde3c8ac4f6e071d": { + "balance": "1400474252324000000000" + }, + "37410fda52f94185d824258ad5f3c9ad9a331257": { + "balance": "11830521097085000000000" + }, + "3752b7e1628275522cd693307787b9564501d959": { + "balance": "67839627078000000000" + }, + "3776f82701c384ce6cbf6a8fea40772cb882b66d": { + "balance": "50000000000000000000000" + }, + "379f63e538168925ba6313f9a6a3b6e7f0e8ed52": { + "balance": "292876625446000000000" + }, + "37a24c1a8080ab429a136c5582782b276eaa931f": { + "balance": "6099055841000000000" + }, + "37abbeaf24b5e6264c87633734852e243d377010": { + "balance": "1051360014489000000000" + }, + "37c50cecab8fe9dcd81aaede95050d27c53f4d45": { + "balance": "106051638566000000000" + }, + "37f82962c3097f0cd9ff605db66e792025a540cb": { + "balance": "10000000000000000000000" + }, + "382ba1e6c53cd7b9c360ef894962d281d557561f": { + "balance": "216789631461000000000" + }, + "38309b458993916efc1ac8b0b5d41302fec21095": { + "balance": "999139000000000000" + }, + "3847f25956a97a32caac059fd9e4cdc105756e25": { + "balance": "876497264905000000000" + }, + "384fe5f399638d277d4fb93f26d527497939287a": { + "balance": "280035151914000000000" + }, + "388335d8b92b445b1b19a3107547bb6ca7c0763c": { + "balance": "167140942784000000000" + }, + "3894a1e65973a542101caa4dc01e9553a5521d63": { + "balance": "34262479791000000000" + }, + "38a0e019c6120a19acaf0e651dd8338982cdaab1": { + "balance": "153843170492000000000" + }, + "38d4bdb10819a7d4ae9a32f4abb82402dff319b5": { + "balance": "1471131830647000000000" + }, + "38e56a55e2ac8320a480562f4a7cea9220306ee3": { + "balance": "907464312139000000000" + }, + "38f18123f3643e03d24ad759afbefc90ed923a2a": { + "balance": "943729130798000000000" + }, + "38f764c861def6d5d65e5ec099536f4cfcc3af55": { + "balance": "20000000000000000000000" + }, + "391e12b51fc85fb879a72fa746ca06c7a5659e6c": { + "balance": "9000000000000000000" + }, + "392342dc7b475c3975877a41622be0fed8e386be": { + "balance": "218719857770000000000" + }, + "3944cc960b8f1993ad841629a79e53d0535a88c8": { + "balance": "210571656485000000000" + }, + "396219864b8cfb0ffb3c675690ccd7026424ad4b": { + "balance": "138984508746000000000" + }, + "396403f26b388150b4876485b124a49845101464": { + "balance": "10000000000000000000000" + }, + "396f1e0f9e7ee86d1b2159ab8f9353677d12d340": { + "balance": "121000000000000000000" + }, + "397cc9f6254d56c721c767e41628a9078bea878c": { + "balance": "225000000000000000000" + }, + "39878b0c7049fb179aba0015279eff6cc3136816": { + "balance": "33962071375000000000" + }, + "3a06b58d0cceee5b091fe6aeb0fc0db5774e9395": { + "balance": "272033811720000000000" + }, + "3a3330e0152d86c5aa1d9bdfe9e1697645d3377e": { + "balance": "2165107207206000000000" + }, + "3a3bb8ed3130e09fbdfc21db3571d4711fc92d60": { + "balance": "885484658836000000000" + }, + "3a4ac96c489c864765cb1997a0084ba745b67a87": { + "balance": "1257436384863000000000" + }, + "3a69e1c351978ced418cea6cee019f220bcb065f": { + "balance": "579242822216000000000" + }, + "3a76a23d81929bed05ef7e1982d32b456e62aa7c": { + "balance": "1027078338792000000000" + }, + "3a7beadd1e11d0e3326c0dcd0f670530612931a5": { + "balance": "20633069818937000000000" + }, + "3a867c44d0dd06517a82ad467d0aefd7f11ce729": { + "balance": "12323708574000000000" + }, + "3a969ae486215e24c7ab89e38929562e2f85d923": { + "balance": "18955477335000000000" + }, + "3ab81366d898a8b798afb08a4b722ab0eb883652": { + "balance": "1220090012596000000000" + }, + "3ac1e14ed5929d382f6488c5444e717373ed29ba": { + "balance": "2030543873000000000" + }, + "3accf4b8ef20e4fea983f13f99ab257a5f9e988d": { + "balance": "156030342415000000000" + }, + "3ad38fa6e3c078025794e213d9dcc5aa397050c2": { + "balance": "36561766773000000000" + }, + "3adef81b2c861ae39c418d55be99aee2306e29fc": { + "balance": "15752410974000000000" + }, + "3b21ff4d5801d3976643899f195fbfd1b72a50b3": { + "balance": "8971221745646000000000" + }, + "3b2f2635dd428ac0b5873088a9a81800f09d6e02": { + "balance": "56922872447000000000" + }, + "3b39919c7bc8d0afec792288c56ab7f4934dc7d2": { + "balance": "1678237240464000000000" + }, + "3b468d9d5546810aa837c29ccb8349548b0e8170": { + "balance": "1100000000000000000" + }, + "3b83d1b651f117f1559a19b04ef408619c2dc4a7": { + "balance": "53628552066000000000" + }, + "3b9a72201bb1e8e678e36129cb1570e3ac99270e": { + "balance": "25000000000000000000" + }, + "3bcab1535b04a0a3fbb673bc41fedaa80bf7901c": { + "balance": "1526488015042000000000" + }, + "3bed42c3d0c49ffac87b9d482f6338fdc9e3880e": { + "balance": "26189771073000000000" + }, + "3bf736b57f0ae47f3714a6bb852090a543b9d367": { + "balance": "652395174320000000000" + }, + "3bfd481651956105ed909eeb98be404ec5ae77e9": { + "balance": "177520143473000000000" + }, + "3c0a12a327545b5f8b7b5c1f7a1ec6a341ec9578": { + "balance": "4184342789398000000000" + }, + "3c132698d59927fe08cba433a41d08acc96c0edd": { + "balance": "151913899135971000000000" + }, + "3c27bd92c4be1a19974ec773bd20b13afe582c9f": { + "balance": "10000000000000000000000" + }, + "3c2ad171573a608286f1fa3f5ef9e6099823983e": { + "balance": "3240802189194000000000" + }, + "3c4b5e808b9fb8baab1144b981b6cd53e216fcdd": { + "balance": "61214114118619000000000" + }, + "3c4cfc6ead044819ceb41c1c64ceda1a228af801": { + "balance": "9000000000000000000" + }, + "3c553afd45535f7c2a70c701d00890e607b96ffe": { + "balance": "2678827200938000000000" + }, + "3c620d55268c55b6deea3b7dc7f59dbe93b6e141": { + "balance": "55494311990000000000" + }, + "3c9b204db23b902d4295e6aba3405917efd59449": { + "balance": "55543672571000000000" + }, + "3cf233b7730a175d05a861318b7bb917bb5bee06": { + "balance": "1867187351033000000000" + }, + "3d292272992397ed5f27d5202da693128d023d35": { + "balance": "79770828413000000000" + }, + "3d353cfe84e9a93aef90547fbeb6e4b4bef83069": { + "balance": "36000000000000000000" + }, + "3d54da4ddd0621822a114581ecd15572e6488be9": { + "balance": "1623867132383000000000" + }, + "3d62ddc67d366fb055eaf92c936a6e7df5085454": { + "balance": "124933526793000000000" + }, + "3d754df1151b9b62a6ed48b477225121c29af063": { + "balance": "50000000000000000000000" + }, + "3d79d1ebd5224ffdc13e27924ab7f9f8e3452ec9": { + "balance": "520163228474000000000" + }, + "3d84fd9785a6bd3148847038c6f1e135042a892e": { + "balance": "10000000000000000000000" + }, + "3d9574c3860f30bcb42523a0cbb08aa7dd83e733": { + "balance": "15259904884000000000" + }, + "3da809a5911ccc77f892034049a97a9022c35e7d": { + "balance": "1415009021101000000000" + }, + "3db9a6c6ab3d0cf6d3bd7e04bdad39b4d419ab13": { + "balance": "9999781764000000000" + }, + "3dc7367c3218f88de8867c425f89102d2f2056f4": { + "balance": "10000000000000000000000" + }, + "3dd273dedb28824d1309c7d60a0744a6b6353e79": { + "balance": "9000000000000000000" + }, + "3dd6b25eb91dd2f3468e0786e8beb465abe7f515": { + "balance": "275172962210000000000" + }, + "3e0d14f83b304136311a33bbac2720c0cd66f117": { + "balance": "3390479675000000000" + }, + "3e15e947ee76f52f0f2a7d84da7c4ab060eb5cbf": { + "balance": "6751398714759000000000" + }, + "3e1b5469e1da4ec27537513f4df3f1a338a7dc2d": { + "balance": "161899580000000000000" + }, + "3e3329bcc90e47e4dabb5c93572b18b5e0efa024": { + "balance": "10000000000000000000000" + }, + "3e5a585ad0f34d78899433edaed574af052616f0": { + "balance": "910225655353000000000" + }, + "3e6be9615713bb06198bf354ef434a9db649699b": { + "balance": "783525278181000000000" + }, + "3e7c7c082f2f99b1ad579400a2e93586a24ed992": { + "balance": "159035553843000000000" + }, + "3e86ea5713f90022c0914fcc25e97c39487eb957": { + "balance": "101867287023438000000000" + }, + "3e9dabab6e50a696edfba6bcd44230d087c8d04c": { + "balance": "3315882414579000000000" + }, + "3ed956f86fe78223c86e164e4f372c9a0bf4a279": { + "balance": "119959915220000000000" + }, + "3ee87e776fb12e9c894e36fd5a61daa984e8a5cb": { + "balance": "50000000000000000000" + }, + "3ef1c8f294443f776a794563ce7569a8fe4d5d20": { + "balance": "25000000000000000000" + }, + "3ef6a396d6611df6c79ec1e6ad6bbd253917fbe9": { + "balance": "10000000000000000000000" + }, + "3ef727346fc631ae6473e9a36e2e5e54df696195": { + "balance": "121000000000000000000" + }, + "3efdcf2c0998637cb82d2b5fc24f27162578d207": { + "balance": "1054861112990000000000" + }, + "3f2cb2335e2bc07744175c497e2f437e87c2a146": { + "balance": "48999979000000000000" + }, + "3f4d16663a4f76ade93eb8bd6ca8fe2158e24322": { + "balance": "237117597268000000000" + }, + "3f7c5e6aea7f3f74d764df50f0fc1aa758fc99a7": { + "balance": "63372222562060000000000" + }, + "3f92239fdb41c6ec228252248c2db3f23675e275": { + "balance": "28538064487000000000" + }, + "3f9610454b621c04f00f01f4d54046502edb21fb": { + "balance": "16000000000000000000" + }, + "3fcfb30cbfe53c0c43f58c28386d9a6e5b49f7cd": { + "balance": "79080579219000000000" + }, + "3fda0c9a3d3f0000635376f064481d05d1b930bb": { + "balance": "10599947385000000000" + }, + "3ffce0475430de0bd9b09a412e404bc63aa28eea": { + "balance": "10000000000000000000000" + }, + "3ffe7583b568448ded5183e1544bca0d283680d2": { + "balance": "1076944549283000000000" + }, + "4003a137e577351a4ad7e42d1fc2d2cf1f906b6f": { + "balance": "25000000000000000000" + }, + "40215fc4c6300d8d8179383d9028fd2d909c6cc4": { + "balance": "3941346079000000000" + }, + "4027d7bbfa5d12c1ab9d08933a1659ae8dd023ee": { + "balance": "1156537386462000000000" + }, + "4039439c960070394dbda457726d97121c7b3669": { + "balance": "4444061364102000000000" + }, + "405978c24a12d930ada6163a44fc4a70c16569e1": { + "balance": "707298643296000000000" + }, + "405d2c1b55ba3f67c8634456b99c19092b407a10": { + "balance": "1462185951849000000000" + }, + "405ddfcf45005cf5a0ee1bfa605a7346a0167945": { + "balance": "88775535985000000000" + }, + "405f72a6940acf5d36a29498075f2d0d7a75bc22": { + "balance": "402796678569000000000" + }, + "407253b005ae97857f812fc60d441e5367b4bac8": { + "balance": "1484147810895000000000" + }, + "4091e1fb1c7af51a64c201d6a0c8f0183dfb7ca5": { + "balance": "10000000000000000000000" + }, + "40950bad9580d4b111955da7d3f9ada26dd9f05a": { + "balance": "500000000000000000000000" + }, + "409a28106192cae7a76c6aa8add0f73dcd63d2c0": { + "balance": "214832616721000000000" + }, + "409d5b872b059aea9a773e854f9a17ed2d5c2ef3": { + "balance": "64000000000000000000" + }, + "40a6e3c753b04c42fcf89cc30df8f50418caecb8": { + "balance": "754228409494000000000" + }, + "40e5ce1e18c78d6c792f46ed6246bfb31bcdb6af": { + "balance": "500000000000000000000000" + }, + "4121692a14554ddca1ca662fb577d7152d4fa7d0": { + "balance": "49000000000000000000" + }, + "412acb10c8ca937ddd64cf0d413b1dd34760f72b": { + "balance": "6073360870000000000" + }, + "4166a5c94d5ae48ced410f950d40656182bf8990": { + "balance": "55000000000000000000000000" + }, + "41752b7d0d3ee58a6b69d8ba721c0894ff701237": { + "balance": "585556720807000000000" + }, + "417c86d6bf734e99892a15294230771bbfd7e1e1": { + "balance": "38233258264000000000" + }, + "418414498f7361b29428c54732e1f49fb394f813": { + "balance": "2063786326155000000000" + }, + "41a424dcbff6bf31686f5c936e00d21e8a4e0f78": { + "balance": "33554754580438000000000" + }, + "41a893429d5f8487c1866b87779155d4bfe33198": { + "balance": "20000000000000000000000" + }, + "41bbedd607fa576d130305486824cd2871bf6b05": { + "balance": "649728993301000000000" + }, + "41ee42c1fb1bcdc9c7a97a199fdcf9b63623521a": { + "balance": "7906012418597000000000" + }, + "41feffaf56d1712af6965fa6eee1b06bd624e7b8": { + "balance": "49000000000000000000" + }, + "42107e765e77ea76b3d6069d3775bc3aef7d692c": { + "balance": "25320783684183000000000" + }, + "421f4dab3240e15a1c78e3ce8642de9b578b8e4a": { + "balance": "832511242936000000000" + }, + "4246c52c3601541a873d4bbaafedf28b9bad5b73": { + "balance": "10000000000000000000" + }, + "424efe1ba28bb1aeedc38a3a5135547d0fe80751": { + "balance": "25622294162729000000000" + }, + "424fb0a3ec325bf42e7edbef7e450f2ffd1cf318": { + "balance": "20000000000000000000000" + }, + "42714c04d17f6c29029daf7f50d1cbad6590cfad": { + "balance": "271755674161000000000" + }, + "42b66e9123d304b70fef3dbcfe8587fd6189b5c4": { + "balance": "1030481609000000000" + }, + "42dacbc412b829cb304ffbc316b3f81b379bfc80": { + "balance": "304208485736000000000" + }, + "42e3d9832c8b6cdea39c97525570391803dee276": { + "balance": "2581020833000000000" + }, + "42f757898f95c1b46f64a4a6b7f86ab03022d672": { + "balance": "100000000000000000000" + }, + "42f7956fd659e00d3be2f3d1d4f3ed187aef04d6": { + "balance": "50000000000000000000000" + }, + "43160b2bc00f7f8f7fc806e2f6e2ffdc62b3a651": { + "balance": "1000000000000000000000000" + }, + "431b77cdd067003eeed26c1aee32f67fb94f7092": { + "balance": "902514849986000000000" + }, + "434e44583786e354731bca250d94ef0d8860a538": { + "balance": "1187789683866000000000" + }, + "434f1b9b193c88bf58685124aac0167fe69f9014": { + "balance": "500000000000000000000000" + }, + "43535982688844fa703cb9bd5723790cab364049": { + "balance": "100000000000000000000000" + }, + "43559f405590592c254e427fa25f03e774d8defd": { + "balance": "6913200000000000000" + }, + "435c08c481d59308a64afec0d6f936321bb120bf": { + "balance": "9005920819593000000000" + }, + "43629748a92b846f21f637aac5103412fbabb9a6": { + "balance": "1177513692845000000000" + }, + "43650b37552882d225ccc977aa2b7a86a4ca9bb1": { + "balance": "16000000000000000000" + }, + "4385de394371d26a45f18e8b3842effd015027bf": { + "balance": "187331693412000000000" + }, + "4386ff9648fe420503c9a36fe7b97c079de3b770": { + "balance": "2714401478778000000000" + }, + "43b370c4457cf39a3be86cc00c2b27614ca6e638": { + "balance": "8316429850934000000000" + }, + "43c464ea740172fe6f4f09974106fd24029837b9": { + "balance": "129643160399000000000" + }, + "43ddd2d33dcb7e578f4e59ad6b9c61a24c793aa8": { + "balance": "500000000000000000000000" + }, + "43e0f8065eb7faf3bbd13bc7c5d5d8f5ff1bdac3": { + "balance": "4454324716300000000000" + }, + "43e96cd065d7934b246d0fec8cd2dc6b36d56d7a": { + "balance": "81721481452000000000" + }, + "43e99acabfbdc6cafee3afb12fa7ed1345370b2d": { + "balance": "4595292398872000000000" + }, + "43fae764c7555b859b93d2126edfa59cfbf298b5": { + "balance": "105746805109558000000000" + }, + "44052eb938c02776b5240f38ec99f5ef51ef0d87": { + "balance": "38446396949881000000000" + }, + "440fc7621cc17f121f0bdf2a68c5be2c3af4fd3b": { + "balance": "1026958147051000000000" + }, + "4440ccbc77249a4d891d9ab5a5f2026b17aff7c7": { + "balance": "10000000000000000000000" + }, + "447f3f702c13a3fbdc8675c6285702b5aa2b66bc": { + "balance": "1089533398014000000000" + }, + "448f152be153fdb0497403f70e37d876946a5021": { + "balance": "614429461682000000000" + }, + "44a1e3a044f5d1fb00f4beb3772a3ee08d8b7093": { + "balance": "1000000000000000000" + }, + "4515edc7154bedd7143b69a04c4e738f8aa4ab18": { + "balance": "10000000000000000000000" + }, + "4572148fe5ea9d4795e1f1ed93097aac1d70991c": { + "balance": "2873782218000000000" + }, + "457581f223b8eacd757abb292613e317d6f59305": { + "balance": "3582446780073000000000" + }, + "45b450961882850f7038d5cdcd2a8fa2dc4b5469": { + "balance": "20000000000000000000000" + }, + "45bdfdf3840d4341503cd7fc87e4b66f6179e5fe": { + "balance": "10000000000000000000000" + }, + "45dd9baa87b3c94df66308d8ed4f3a5bb65c3dcb": { + "balance": "25000000000000000000" + }, + "45de332b8ee95d886cf11b99291b46f46c1ddd45": { + "balance": "36000000000000000000" + }, + "45e06afdbc70288a2cc55bccc4fb2d8195aea028": { + "balance": "790360485306000000000" + }, + "45fce5fd1acb2bc5507723c897cb340437e39735": { + "balance": "100000000000000000000" + }, + "46045cddd940d80596826ce5354489b3047663bb": { + "balance": "100000000000000000000000" + }, + "4610286f8a2649dcfbc6d91735745f418a6abc75": { + "balance": "10000000000000000000000" + }, + "4615905ecc6f7df0ccb7b86a3e1d3770adb2f874": { + "balance": "1000000000000000" + }, + "46256e00ff927d54b0ca139ddccac2148784273b": { + "balance": "10000000000000000000000" + }, + "465e40e7d129ad310fc60ff0f17c0f968611118f": { + "balance": "677971225649000000000" + }, + "4664a920f7fe9b0d78a665e1a4aeb95f287d6059": { + "balance": "20000000000000000000000" + }, + "46679de1c6143138fd9c44ff05853a52371915ff": { + "balance": "363627463229000000000" + }, + "467cdc210ae48ba99740d37ee79fa57c4216bc81": { + "balance": "10000000000000000000000" + }, + "468053d193debb88735571acb24b764f2676272e": { + "balance": "49000000000000000000" + }, + "46826d1f1418abbe4e7b9236d643e5b57a0f0208": { + "balance": "37752144164916000000000" + }, + "468df2ea57972ddeb88d470a5f3c2c0e2284ac17": { + "balance": "757320434551000000000" + }, + "4695ad5b686520ee8426d24b50ff7a5f0d703443": { + "balance": "2851082366000000000" + }, + "46a149bc8ec2b85fdf938f753a6c53777dcca2b1": { + "balance": "10123698633000000000" + }, + "46c081440f760a21b74c2499bdda13aef8245930": { + "balance": "180752319265000000000" + }, + "46e615324f6e4fb242f9bfecffc0c802ba7733c9": { + "balance": "10000000000000000000000" + }, + "46eb54f09dbdaaf3b97a1f79a3d82ee2e902b3b8": { + "balance": "3430510380318000000000" + }, + "46ebb24b04919ec0164f0bafcebca2309f2d3035": { + "balance": "129155832233000000000" + }, + "4701f9fe78111011f820fe28c47522e601655678": { + "balance": "9000000000000000000" + }, + "473f44e2c1d5d7aa53cf7041d7ad19a0d9eaf1d8": { + "balance": "162679637505000000000" + }, + "474f8bf4d03a7efa4d190905ce062eea7c75118c": { + "balance": "1259904506149000000000" + }, + "47598330e862a4f7cbda8be74ac10cd5d370a55e": { + "balance": "291763101699000000000" + }, + "476455d48fc858a06bd7854fcf1bd60bcfde9ed3": { + "balance": "10000000000000000000000" + }, + "476826d58192ad822f4686311d6c6d4d4f66ee5f": { + "balance": "453184657722000000000" + }, + "47a231eb3fdbc24f2d008f06228624b2a45ae5fa": { + "balance": "1000000000000000000" + }, + "4805f4c0eb1c83c436118ec9148019e5fc1962e3": { + "balance": "1311161626928000000000" + }, + "4809f373cdd56c8481ba3bce5a401d55a7e50a50": { + "balance": "2284845194349000000000" + }, + "4839bf9ad56873abd5695057bf71972806cde827": { + "balance": "42264923611000000000" + }, + "486dba2a47decabc9a85d1d64d74687983ab273b": { + "balance": "49000000000000000000" + }, + "4877993f5ecf02451f8d4591594cb2f30dcf9f26": { + "balance": "100000000000000000000" + }, + "489723e325f609e27be14528c4111fb3eec13f7c": { + "balance": "2489030141000000000" + }, + "48b710d16e9da736b773453089d69cc6ede116b5": { + "balance": "26651593216000000000" + }, + "491088e1e4b5c3d65870f2deef9be6ec3dc6c7c7": { + "balance": "1446809481953000000000" + }, + "49174451320ad2e14cb2b05ecdd251b75ace3038": { + "balance": "15533380764616000000000" + }, + "4956ead915594b621131b2fc2dbbb49ba43c5559": { + "balance": "1175638488000000000" + }, + "4973a0d32147ba89f525a18f989518dcfce93b0e": { + "balance": "522848489444000000000" + }, + "498c6f9063705054fae07260d4176c3d55a97650": { + "balance": "732941433000000000" + }, + "49991f68f2a76bd1cffa3e9721be36f3fd8351b8": { + "balance": "17742568700019000000000" + }, + "499a8af194e0040f349e893937fe3858f8267fca": { + "balance": "80704784160862000000000" + }, + "49bcbb7b263febf54f8ff498525bac8e7241f966": { + "balance": "603044032468000000000" + }, + "49bd72773656c4e1a4d16284aea2fb05546d2b31": { + "balance": "1896607093054000000000" + }, + "49bf80fcdefebe8cd4830ba09e46ccd7231c8e6f": { + "balance": "10000000000000000000" + }, + "49c9d82dea78f14b1c52efc0196b67f508f7859b": { + "balance": "2313040051399000000000" + }, + "4a2daeacf0468d137e3bc464d6d5fa3893a9136b": { + "balance": "10000000000000000000000" + }, + "4a6c428f245e8d9115b34764bab17eb86ac472be": { + "balance": "10000000000000000000000" + }, + "4a6e8d037acf1960dbbf14e7a02fec0ac656f9c1": { + "balance": "6516295825438000000000" + }, + "4a7e7fc3c72f2f9b92bf0dcd5297cfb19f077d7c": { + "balance": "99426213999999999" + }, + "4aaa6817a5000bb7596e000135b3051c5931e7c5": { + "balance": "102884105546478000000000" + }, + "4abcdc3d7d3d314a163da92aee53a56b87313a2e": { + "balance": "44402243657000000000" + }, + "4ac9385ade2377b061f4211b392ed6a6e7fb83cc": { + "balance": "1000000000000000000" + }, + "4ac96e1e26cb66ff788ed8c62db811d7b4fdbc74": { + "balance": "68476115774000000000" + }, + "4b10c247caf33fb872d9bf86572424410aa86752": { + "balance": "337915294240000000000" + }, + "4b23ffff1894df49005c7afc0828880924571299": { + "balance": "169848767272000000000" + }, + "4b486895caf3a0b5afa198df744de7082eec8666": { + "balance": "1672587376054000000000" + }, + "4b98fc960610573be456c0e1e319f4f863bf9095": { + "balance": "259382246718303000000000" + }, + "4bc0cc483be20223f40ed6deef63dd9645c216c4": { + "balance": "4322684620000000000" + }, + "4bf4a046afdd4ec9d0e50730ff6ded5ef2327442": { + "balance": "70601389160000000000" + }, + "4c0149058e2e74f7c900e6d6e5fa12eea882c5e0": { + "balance": "2017399852886000000000" + }, + "4c17a3997fb70599794d01a33a27a6d5b52b6f01": { + "balance": "469002093209000000000" + }, + "4c4559e7b32340dce112cf7a021ced1b113f6dd9": { + "balance": "25000000000000000000" + }, + "4c4f02b3f232b8ce8485d425639271510cd0486f": { + "balance": "68828038140000000000" + }, + "4c52ec56142bb6e8c8830e5c17b01b5165915f3c": { + "balance": "321766233041000000000" + }, + "4c58defa57875e709ca039a54a2be5aed6672f6d": { + "balance": "121000000000000000000" + }, + "4c5a886ab90b6bac68677a7eb92a06bf33ff2930": { + "balance": "236899852150000000000" + }, + "4c60539363edbd812334a54543c40ecab8af2ac8": { + "balance": "3281904094699000000000" + }, + "4c76897d0d5d39195354194710c5e7f99bef63d1": { + "balance": "10232271258305000000000" + }, + "4ca3c03780c20a64f3b5ebb75669982a71ee8a71": { + "balance": "377172198976000000000" + }, + "4caf77eefe062a6f053a464171bc75254b47f52b": { + "balance": "20000000000000000000000" + }, + "4cb7d7ce805e56f6e47e94cd755b6d97f8f996a0": { + "balance": "120998866000000000000" + }, + "4cd34f8f3299d3b7aaee180baa0b432369e1b3d6": { + "balance": "197088135242000000000" + }, + "4cd7aaa5415d809f405f520e4c0319a6029b981b": { + "balance": "686627368232000000000" + }, + "4d01067555f1ef63883f25c562b07168f79fa80d": { + "balance": "17547055698000000000" + }, + "4d2cb4c1da53e227b08c0a269402e9243a13f08d": { + "balance": "324000000000000000000" + }, + "4d38bb5f48ec37b751d16de32a4896fbda479ce1": { + "balance": "802530078718000000000" + }, + "4db3e76e2f68896cecc9826e10a5e09df0352c28": { + "balance": "555180306924000000000" + }, + "4dc8730d9f032d33dc493bcd3c6375b38f41afff": { + "balance": "5726933881000000000" + }, + "4ddde96556f5185a13617f01ebd9102800bc9e9c": { + "balance": "1181822708402000000000" + }, + "4df9359cb204bf649668ff8086a7f5e24709083c": { + "balance": "262998978400000000000" + }, + "4e0a1a3dff0d33c418758263664b490140da9e01": { + "balance": "100000000000000000000" + }, + "4e0dd6d8de5caa3a3bf9fdd6f2d7b30618623cc0": { + "balance": "10000000000000000000" + }, + "4e11af85d184b7f5e56d6b54a99198e4a5594b38": { + "balance": "76658631121000000000" + }, + "4e314349abc52c686d47dc771ebc8040966be386": { + "balance": "632341985941000000000" + }, + "4e3fb09c35375106bece137dbe0e5491e872871b": { + "balance": "153648535396000000000" + }, + "4e4f0d606f7065bfb1545e60b5e684ae1934e055": { + "balance": "48998635468000000000" + }, + "4e50957aa6c91c548075add8ec625b74c0973abd": { + "balance": "1000000000000000000" + }, + "4e5c6efa76493f0e9422582016aac50539ae60d9": { + "balance": "2078967343000000000" + }, + "4e70bbcb50c4e875fd573dcb694908abf3b30b37": { + "balance": "20000000000000000000000" + }, + "4e7f5670a7dd168a0803e53b8bf72f4db280e3ae": { + "balance": "1658463113665000000000" + }, + "4edaf859990a10977bf378df45b32f93422c84b4": { + "balance": "121000000000000000000" + }, + "4ef41923a1a426772832d3c267adbd84e5994edd": { + "balance": "5432615017384000000000" + }, + "4f11a70d80f36f46ed0c2a5fff1a39b711f3bae5": { + "balance": "8415785077000000000" + }, + "4f159095afcc75b8f5cfc90c9d07a0d77ac8ed69": { + "balance": "25000000000000000000" + }, + "4f2652322736cc18b24af582d4022fe329a9dfb7": { + "balance": "9000000000000000000" + }, + "4f328173f352f3dfdca0ff5e3185f26de77c6f75": { + "balance": "10722917874680000000000" + }, + "4f47a62aba6ea049fc0e92d8afbe1682472d98bf": { + "balance": "10000000000000000000000" + }, + "4f4c3e89f1474fe0f20125fae97db0054e9e14e0": { + "balance": "50203638983000000000" + }, + "4f5ac8dfe79c366010eb340c6135fbee56f781d8": { + "balance": "50000000000000000000000" + }, + "4f672cbd373183d77d8bd791096c6ebb82fa9a2a": { + "balance": "978111227765000000000" + }, + "4fb179c9c88decaa9b21d8fc165889b8b5c56706": { + "balance": "24750205150000000000" + }, + "4fbcf391c765b244b321875d6ab4381c44d0747a": { + "balance": "99999580000000000000" + }, + "4fc979b38b981fca67dfa96c6a38a17816d00013": { + "balance": "1088876196468000000000" + }, + "4fdfdd1832b114b4404aae23305c346beee14e1d": { + "balance": "278724179057000000000" + }, + "4feffb1836029cd0e9b8f4aa94b35ae3982fa770": { + "balance": "1674590934924000000000" + }, + "50045745a859f8fce8a2becf2c2b883b3723b2c8": { + "balance": "169000000000000000000" + }, + "5028bde29fe88e03e3de069b3907fa9df551c379": { + "balance": "196000000000000000000" + }, + "507096ed771fa8a1d004ee5377c01506df461b32": { + "balance": "2669205000000000" + }, + "50788574a0967580fdaddc4758f834d8978455f6": { + "balance": "1648581593000000000" + }, + "508d8e8f338ca98d3c09f0f15fd9e7baa80701e8": { + "balance": "16000000000000000000" + }, + "50a4dc916845172b83764a6c8b4b00d6d02d41d3": { + "balance": "3020744393592000000000" + }, + "50da06418780c220ced4898af0b1fca533f73cca": { + "balance": "36486700700823000000000" + }, + "50fb6fd8432a66219e754234e9eea1dabcc07676": { + "balance": "489500000000000000" + }, + "5104bb1b831902333732dd25209afee810dfb4fe": { + "balance": "1333614132000000000" + }, + "513963743ec6ec9dc91abf356b807ebad64df221": { + "balance": "1508002412172000000000" + }, + "51397ca69d36e515a58882a04266179843727304": { + "balance": "941648956414000000000" + }, + "514a58f2b36c2cf1b6293c36360cf658d8af30ed": { + "balance": "1233397704089000000000" + }, + "514fe0cdb3de692cab9f2ef2fd774244df71be66": { + "balance": "9670444445882000000000" + }, + "51583128081fd800d9550144afebdf3fe88149cb": { + "balance": "231190355520000000000" + }, + "517384fe92391187d0e65747a17bfaadf967c331": { + "balance": "1943121865489000000000" + }, + "51aebfaa26a54071cfe6c2d8f81157ec313984ad": { + "balance": "1422225031261000000000" + }, + "51d4f1205b272e491e94fe21f0341465f14141fc": { + "balance": "552384783614000000000" + }, + "51de598faa85276bb26a68b135028755304b6700": { + "balance": "2068484560002000000000" + }, + "51e08e0304f08ef768c80ca149da4721fcf482b0": { + "balance": "194629207228000000000" + }, + "51fa3da695e24f602952a71966f37ac3596a94a4": { + "balance": "17008166261720000000000" + }, + "520b22776b1befd3064636da0dd251afe569ef13": { + "balance": "18538137781909000000000" + }, + "52219a1e1aa82b78b971088c30583a3bbe675c8e": { + "balance": "411959222637000000000" + }, + "5252b8a0688096523498cb5c1f42bcd1f61923d7": { + "balance": "1863936864000000000" + }, + "5259154e1a5a809b2e3dab80372124cebbfd56e2": { + "balance": "110000000000000" + }, + "5264f2de516835e549710bfe34ef03b08b8557dd": { + "balance": "1216000000000000000000" + }, + "52b17fae7e9cac447f026db71dba4034a1d53174": { + "balance": "99001631977000000000" + }, + "52b3363ae882a99354faeb76733d0fa2cbb89787": { + "balance": "102517584327000000000" + }, + "52bee7fb24a7fc1f34cf0874ec2f06c5fe847cb1": { + "balance": "54443400591000000000" + }, + "52d1f12d391c7a2f3b52939a61a20da5f85eecc3": { + "balance": "2707175772061000000000" + }, + "52f27099483589e883e7eb789896de39c61e46da": { + "balance": "358944977251000000000" + }, + "52f3b715b678de95d1befb292de14c70f89f5e03": { + "balance": "2989868434000000000" + }, + "53259780569f6dd6753c1da1d53d0b155c5b30d2": { + "balance": "200489122590000000000" + }, + "532e4908e8297c90d75d2280b432b469aaafa2ac": { + "balance": "20000000000000000" + }, + "5334d1e399feacabc9648cebcd93172db95d43be": { + "balance": "25000000000000000000" + }, + "5341665addfb5e367f7a7d35de95b87a0cceb3a9": { + "balance": "60544291695000000000" + }, + "535a39a854ed1c2f0afbc5944f1ee0e2e68cf65a": { + "balance": "2141913781000000000" + }, + "536515c0c08988ee69da1d75f18c706f6b9bf7a3": { + "balance": "169000000000000000000" + }, + "5387a1ce4cd2ef4f90075c15dc3c0744948ec356": { + "balance": "50000000000000000000000" + }, + "539a30ee5724978010990718bb8b0dd25f89fd15": { + "balance": "1306896514000000000" + }, + "53a5f87dfb17149b8c2934a2a9d519ace4ac9724": { + "balance": "4569449510000000000" + }, + "53b24fb36e72c22eb830dc93857a8188b03397a9": { + "balance": "64000000000000000000" + }, + "53cc35b3daf4b8e1982e0e63d0bc68d7252e7fcc": { + "balance": "68213426853658000000000" + }, + "53e1f85147e000ae1ff6a5910407395e388c683c": { + "balance": "20000000000000000000000" + }, + "541f43ff66ed5eb1a1ea0ae3f86355ecff665274": { + "balance": "49562725831000000000" + }, + "5428a31f736c0d2b3c4e80baefb75a76ed44d3f7": { + "balance": "10000000000000000000000" + }, + "542f732aec0873bf531f6941828b6f0ed0611106": { + "balance": "8407722276000000000" + }, + "54300b6a77b95545373b2bba73e60f37c31eb1c6": { + "balance": "1581215621996000000000" + }, + "5434bd65a492a4d14d3b97eb49f6e491350ef73c": { + "balance": "484000000000000000000" + }, + "5444a1735913eeac177d947ef38de7cd6bdfc0a6": { + "balance": "1000000000000000000000000" + }, + "544ffeab53bdc59ef8edaff0042b03c2ea123615": { + "balance": "10000000000000000000000" + }, + "54613713df6c5b89c3012a7835651f25cdac8331": { + "balance": "98684037547000000000" + }, + "5471fb39b4e48c118f855492830ad9e2eaa68179": { + "balance": "91791250228000000000" + }, + "5472591efd048dd60a4d6afdb549e95a65578b0a": { + "balance": "50000000000000000000000" + }, + "547b4c1ae70567fd77a896dc05eb536f502ac8a4": { + "balance": "14037444012000000000" + }, + "547fa9f6f86a2939f9144aacb74e0af60d434535": { + "balance": "428416957729000000000" + }, + "54841d6a478cb9b6e717a9de35577a1a4a504b0d": { + "balance": "144000000000000000000" + }, + "549157e5b1c92a88a0eef335b1bcf4d162482017": { + "balance": "21019502942000000000" + }, + "5492757c55c72ac5946b21514ee16c5065ecde7b": { + "balance": "10446737491000000000" + }, + "54984a41eeaa8e710e4e5b8a7f68c96057b7df3a": { + "balance": "10000000000000000000000" + }, + "549a3717a1bca3f38d24655197c3ccef1e8c273e": { + "balance": "4416133255000000000" + }, + "54b047fbe004191cd02f31163d29bd61ccfaadf7": { + "balance": "52649445905000000000" + }, + "54b125d8b260386633b756056b7d7e78e7071715": { + "balance": "10000000000000000000000" + }, + "54ffad1ae76ab45c4218ced27e49bf2745b2a2e7": { + "balance": "1426474871178000000000" + }, + "550b28968bae36f4e99780c6d7deb54c158be6d8": { + "balance": "10000000000000000000" + }, + "55117923e8393dbf233c0f10819e7de75569962c": { + "balance": "470094520022000000000" + }, + "554a2471e6ecf2320da545d559c40b8b622465ab": { + "balance": "4052895973949000000000" + }, + "55607b39da9480ed8f54d74d0818ab8798136589": { + "balance": "13704276648975000000000" + }, + "5561cbe99fd775f5d0f05903fd62ba4877b3319d": { + "balance": "1007596371374000000000" + }, + "559ba7ab58670d4a0b118bbf6aed7f6fdb276594": { + "balance": "3127762973000000000" + }, + "55b0bc444f2a5952a98f216f61cf07382da1e156": { + "balance": "18683409750727000000000" + }, + "55c0a02dc68123aca7ee0c9cd073ead50b16406e": { + "balance": "99999999580000000000000" + }, + "55c47d593952afd637050c5758a921a204f23fc6": { + "balance": "1615608723958000000000" + }, + "55c6855b3970e5a550f0c75d5727329476406d91": { + "balance": "600705012673000000000" + }, + "55eadbe33899f53138d0fb204f42e272f447cfd6": { + "balance": "1671128311341000000000" + }, + "55fa59fa0fbba06b7184ea78868d438176eb96eb": { + "balance": "1553000000000000000000" + }, + "560a11493b5a0ec28589e80276fe975ee26c6a3e": { + "balance": "10000000000000000000000" + }, + "560fbb31d83bf6dc49e5fb15bd582d70c49fd273": { + "balance": "46015432815000000000" + }, + "5620e17ccf094b1be1a93f6f3388fb96e3a90165": { + "balance": "484000000000000000000" + }, + "5633512298cf74f4d2b8663e6f291e9e25436e7f": { + "balance": "10026444446000000000" + }, + "564423f92b8841b3b1f8bdba443067b580916e65": { + "balance": "465451550122000000000" + }, + "56730e1d11a84970355c43ac7659f2f4786dadcd": { + "balance": "20000000000000000000000" + }, + "5678851984add045f3d054623c198dfd4665d54e": { + "balance": "227651903234000000000" + }, + "569cf18b4bcb99e3f3d27235f2c4c0d8d160af03": { + "balance": "4124979731000000000" + }, + "56ac5f2c3486a9ce744a71599ab89a606e7464a7": { + "balance": "9000000000000000000" + }, + "56bc5936a6ea37c1d0839bf64bcec0d366840ace": { + "balance": "14741201469670000000000" + }, + "56bf62e0135e903525cc46b0a3cce33f4a16880a": { + "balance": "534970476270000000000" + }, + "56da0781a80a0abf5dcda4da35861e9de601bfbb": { + "balance": "166898390441000000000" + }, + "56db15729e52d615a744a04f8a59d63e3b9f735b": { + "balance": "10000000000000000000000" + }, + "56e32ed78e7f5be6b00c28847efe7b3589cdae1a": { + "balance": "1046236086484000000000" + }, + "570f7a08150e0088178276f8116bc4103f885903": { + "balance": "1124393518440000000000" + }, + "57147fdd9b52ef53b4ebd4b5712d29da83f99374": { + "balance": "39000000000000" + }, + "57395fb355fe51f1b32c1baa4e9ee0fc2b8fe05c": { + "balance": "7701013675397000000000" + }, + "5752f0f11ed12bb1d5041b0cee4ddd500cd8806f": { + "balance": "151337200533000000000" + }, + "575907d73ad5ad4980a2037efbd20860afc67ad9": { + "balance": "3568754158000000000000" + }, + "576acb4c0bccc89903ad285ac08c70fde514aaf2": { + "balance": "25000000000000000000" + }, + "5784cb8a17cfb5392c4aeec2edbd173849ca6ee3": { + "balance": "15804767597000000000" + }, + "579234645eb857a3ca51230b3a02b964f8efa2f6": { + "balance": "20576922380000000000" + }, + "57989f9fa52b4c0502e7d0c3caac0c37a0b20516": { + "balance": "462711082812000000000" + }, + "57a55c376ea03c22e21c797d83e2fb039508ad3c": { + "balance": "10000000000000000000" + }, + "57d1612ea1fddacf088b62f625ad8cd49d7517cd": { + "balance": "18001023230648000000000" + }, + "5811590907050746b897efe65fea7b65710e1a2c": { + "balance": "310984892882000000000" + }, + "582ffd8c43966aa8ad3c6cecdfc18eddc56fe5c0": { + "balance": "69136214255000000000" + }, + "583b90b3c4d00b9ddf101efbce75bb811d969fe2": { + "balance": "7839200298177000000000" + }, + "5841fee8b1965141e51b8c146b6af00f6a879a8c": { + "balance": "1210322907244000000000" + }, + "5847a576f7799ba1a35e36906b2c2a5aadeb99b1": { + "balance": "183765768447000000000" + }, + "586dea7ada0a54150f5afcf54198db473ed046a2": { + "balance": "7123598380000000000" + }, + "586f545062ec7dc0ffc213eacd59af80660df570": { + "balance": "10000000000000000000000" + }, + "587187488758f67912bd5bb8a5be787a73d97ee3": { + "balance": "702757402654000000000" + }, + "58be0a3482dc3411571f047f4128387049cb9798": { + "balance": "1000000000000000000" + }, + "58d546e2ae82efc4d8efc887ac6fd30f7eb5dac6": { + "balance": "1486717153455000000000" + }, + "58e7010e6b8d97a556c0e7f0d90151224ebf674e": { + "balance": "20000000000000000000000" + }, + "58f991b3b12d29f09ff4cc2c6e83d576e95b1f59": { + "balance": "25000000000000000000" + }, + "5923a65a796934e69081715657e8dfec8874e40d": { + "balance": "10000000000000000000000" + }, + "593b7c43073b8954355ed76020ff3780dd6ae783": { + "balance": "1403468567787000000000" + }, + "5947f1dbd79a622bcc3fa64b19f9b6eda164dcce": { + "balance": "50000000000000000000" + }, + "596311e2fc09ae1eaee57900f2ca188afd5e68a6": { + "balance": "448723397560091000000000" + }, + "597a3adac4607d457c90817220f67eb4abcf129f": { + "balance": "18000240000000000000" + }, + "598201a9bcff0a773e9323338a8a094e9d9b3999": { + "balance": "74904485722481000000000" + }, + "599e93031704c2ce36308f44d4ff8166e71ae516": { + "balance": "100000000000000000000" + }, + "59af0178699f9f3d8f0ea645dda75356119a6e2e": { + "balance": "152462578058000000000" + }, + "59b0c06e40475cd75728797add9c69c3fdb17b4e": { + "balance": "23147237210000000000" + }, + "59b79577f183b9d39c2b458646a26b2fd6ed806e": { + "balance": "4244859516807000000000" + }, + "5a03b51d67a9c660258ebc030120d5d1d4f687c5": { + "balance": "4451691855300000000000" + }, + "5a0d03dff6754963c757eb15a3339ac6c4ba6196": { + "balance": "215126489934000000000" + }, + "5a34ab3937854e407a8739fa14574d3d20e30d6f": { + "balance": "1375979293937000000000" + }, + "5a352fbeb2fd78bbe0268b0efd34f68d401e2769": { + "balance": "27929247671418000000000" + }, + "5a47c2ca4c0fad7e2fc7bbdf5f2356d68843c564": { + "balance": "3218227936000000000" + }, + "5a538adb2c7f6a80634b0ec20ec5152ff6bb4d5f": { + "balance": "10000000000000000000000" + }, + "5a8fe770c221072a7cba79ae7759cae0185adde7": { + "balance": "11913943233694000000000" + }, + "5aafe1efac688583d7facb09d3e569d58fb5a357": { + "balance": "4713219466825000000000" + }, + "5ab68d762750d5185138187db7751c9f71db5836": { + "balance": "500000000000000000000000" + }, + "5acab69851959dd5a6f0673ef757009ed36dfa3b": { + "balance": "974443209942000000000" + }, + "5ad9f2ab11b5e59b756404395f350aad6019d7a7": { + "balance": "54151179981663000000000" + }, + "5b1dc013ba1a28235cc70e785a00eff8808faef6": { + "balance": "516289257133000000000" + }, + "5b1eeb44ef61c7f35482503b7041162bec9b1e32": { + "balance": "125493885394000000000" + }, + "5b3db31996bca4625d22330686128ec234270206": { + "balance": "362316593128000000000" + }, + "5b401fc9ff3be7cdf5f0df870843bbef94f43285": { + "balance": "1373804724122000000000" + }, + "5b47ba296069041f25768e61be14437b8a469e81": { + "balance": "3152706392234000000000" + }, + "5b5030b5057c0457c190489c5d709d7dbdddee8f": { + "balance": "1154404278000000000" + }, + "5b5a4a782d37154a307868cd79bec9cb2a8f0161": { + "balance": "100277816425153000000000" + }, + "5b5e0b6b7cc27b06456ba4c7816ac4e89e1e26a3": { + "balance": "1023749119000000000" + }, + "5b638e4b6dfdb6928b07586e63d5879dce69a1f8": { + "balance": "1000000000000000000000000" + }, + "5b7be81d6ff5228a2b8c2913deea3f86823f1dee": { + "balance": "36000000000000000000" + }, + "5b7c4804bc2b8c72f3112b73d44b59c0711f83cf": { + "balance": "6803857604000000000" + }, + "5ba26d941544d07100744d8ffd6595a8eb7770bc": { + "balance": "583051897662000000000" + }, + "5bd58fc88733632b63d4f26893bc5c08fb60e2ad": { + "balance": "3480620567502000000000" + }, + "5bd85b5f0ecad08133fceb486c43998e537b3451": { + "balance": "484263880245000000000" + }, + "5c12639a5ab107f9e580cbd2278568dde10758d6": { + "balance": "101293252434000000000" + }, + "5c5522df05d6c6d960394c4762599e74247ab102": { + "balance": "149088856773000000000" + }, + "5c722f3ac94421f95389756af9cd97d0eaa6b696": { + "balance": "1435349483553000000000" + }, + "5c7b14ce51abf629bb0953ee4e2d9d87fc86eb4d": { + "balance": "10000000000000000000000" + }, + "5c8b215403da4e7912c1a1704a949087e091b111": { + "balance": "1440961256910000000000" + }, + "5cab313964f6730888e4158234bbd4806db0286e": { + "balance": "32284637230203000000000" + }, + "5cd736bf65c99469490d0523b10a658178cab10b": { + "balance": "99740204082000000000" + }, + "5ce91ef7ae254b2bd6d910cbf0d380814200811b": { + "balance": "50000000000000000000000" + }, + "5d15fc3a0ba8b3d87b80f9bbf972320112c644f9": { + "balance": "64000000000000000000" + }, + "5d2ccc795b19df400f21f24c0dca4d0e9e898093": { + "balance": "10000000000000000000000" + }, + "5d879b8b31af1e400cf53eb7170f82583190b96f": { + "balance": "93765337844000000000" + }, + "5d8dd54178b68bb36e1963d47d29c123864fd0ef": { + "balance": "20000000000000000000000" + }, + "5da1653bbe8353134edfff6158211ad7ee21dbef": { + "balance": "1491149937915000000000" + }, + "5da733ef41a7bdc0cf7975f83ed24604fbb4d40b": { + "balance": "10343699901151000000000" + }, + "5ddf5d7306f7c603b8d3ff993f03906dca14cd8b": { + "balance": "862558469755000000000" + }, + "5de87ec54e2160c7c2a8eff2d859414737501ae2": { + "balance": "21579321171000000000" + }, + "5df1b805b1361c1f39ca844aebe5ecee8a8d06b2": { + "balance": "411820472746000000000" + }, + "5df86b0a183b5e7f702e4da582ce9a8116a05f61": { + "balance": "256000000000000000000" + }, + "5e22359e20dc14be6930c6c1ce5a0c81c039cac7": { + "balance": "10000000000000000000" + }, + "5e2d38a06f33c784303abf2012f9af12622d9e5a": { + "balance": "10000000000000000000000" + }, + "5e479e616585e7fa84bd6f7465d394a1c0302be7": { + "balance": "10000000000000000000000" + }, + "5e4a55027a0d372f6da042b7f73720b143347d9c": { + "balance": "16175516772000000000" + }, + "5e52e86eda3e05f96e353d7e3f0ee90f08864f84": { + "balance": "21255916842000000000" + }, + "5e91c4d3a21c9dfac2c0994ed8890c78d58626d5": { + "balance": "325349462011000000000" + }, + "5ea797b18caba45d5504e57b80b12f5f5ae630aa": { + "balance": "7805696321000000000" + }, + "5eaec8815e859c34dba88cfe7b7fe28572c964ba": { + "balance": "145852682588000000000" + }, + "5eb974b5716fc4712d431bec7fbb2c49057a7b84": { + "balance": "4890681156035000000000" + }, + "5ee5f8407dedbac839f509419051106219458006": { + "balance": "3042761975468000000000" + }, + "5ef782abb28d1ca889ceb3039eef98713effbf32": { + "balance": "40915083108000000000" + }, + "5f23b88f06430c42570ac3fa33b1c7503b388a3c": { + "balance": "2376070180325000000000" + }, + "5f2b1641c0f2605b090039851aacf297e35632ef": { + "balance": "141615261000000000" + }, + "5f44cc8083340e644d19d3debc84dc14a0cbc53f": { + "balance": "291829106275000000000" + }, + "5f633f89adcc70e9da0b66611a5da108b4b221cd": { + "balance": "50835573000000000" + }, + "5f94ef8e9612b03a5c6ffcf423ada9a19a40818f": { + "balance": "102566595099430000000000" + }, + "5fae1977b76a5e899b384f572e4d94855f9cb52f": { + "balance": "773616125740000000000" + }, + "5fbd22cb3de462c794e523fd1ce36f230cc84b83": { + "balance": "1009995132839000000000" + }, + "5fd91676bc95bd6b5e69db8b9216dc83ed9dddaa": { + "balance": "1000000000000000000" + }, + "5fdda8f5271a08cf1b830faa497019d75fa9d231": { + "balance": "4149626365000000000" + }, + "5fdea351c5eccedf2394fb54437b149ae423ecf3": { + "balance": "100000000000000000000000" + }, + "5fe70ee123cb2e03c768138b2f71c1e1ea75ad17": { + "balance": "1074496282650000000000" + }, + "5fec9df797214459f85a040a559b186ee9161c88": { + "balance": "205282872821268000000000" + }, + "60037df7e4092466656a6b9571437fc4600c66e3": { + "balance": "1000000000000000000000000" + }, + "6009a0bcf531640a5a7f1664a69fe0f64b564ede": { + "balance": "50170000000000000000" + }, + "601668d8b678c95ec5ef98d9d2624decbdd52e9b": { + "balance": "23592727870000000000" + }, + "6027bafcd0ade24fda8c345dcbc812d59df74bf7": { + "balance": "10000000000000000000000" + }, + "6029514f24825c1fadc68cf8614951de5d53268f": { + "balance": "1389262963614000000000" + }, + "606de6db14272a314d778cf0e67913b7fabea45c": { + "balance": "144000000000000000000" + }, + "6074f20675f975ae2c081930cae8f299710f0bba": { + "balance": "10000000000000000000000" + }, + "60850fa9e09d414af3690e4b5daefb1b906b0d20": { + "balance": "10000000000000000000000" + }, + "60ad0b6239dda5df7ac0f0ca941684cf20ae0fd8": { + "balance": "81000000000000000000" + }, + "60d6136e6db631be45fefb9667c3dfa69e9d6054": { + "balance": "651902184266000000000" + }, + "60d733dedec6886908520ba57cab8c9d5c2d7f7a": { + "balance": "555461746642000000000" + }, + "61202238aea4010d115c5c64322ad790576cee43": { + "balance": "10465801848035000000000" + }, + "6142d92b61111657de4b2d65698a3621411e3adc": { + "balance": "100000000000000000000" + }, + "61879bc1a022d9cac8b7d57c8f528065beb10bb2": { + "balance": "72766025231000000000" + }, + "618b15c9a60ad89e7fc28afc79bbf7f28d4998cf": { + "balance": "444855210015000000000" + }, + "61c1169e8ba43ee6b919e5be2eac19542eb913b4": { + "balance": "500000000000000000000000" + }, + "61f1cd6efce17f5458325f022f363fd9772d8f20": { + "balance": "19704989598372000000000" + }, + "61f7d39211a0af2e226d8cbc95fb673168653b0a": { + "balance": "484884476279000000000" + }, + "621aa67f09e6506efb2fd141f080fb1d96693a57": { + "balance": "1694451603196000000000" + }, + "62332fa5127b98bd2a627a0ac22d3a1bdb418efd": { + "balance": "926882233406000000000" + }, + "624a465696ad409586a2e67d84750ba50a971fee": { + "balance": "25000000000000000000" + }, + "624d866f0d61bdefc3ec2210bfe36b6d51018f9c": { + "balance": "199592183194000000000" + }, + "6255d6d3b49443891661b209056d530ecd63bcca": { + "balance": "10000000000000000000000" + }, + "626c484055e6739d46e2ff25190c8b3a4af3fe0f": { + "balance": "1485276462321000000000" + }, + "62865e637d723393ab9654d6439db7fb5abf8803": { + "balance": "10000000000000000000000" + }, + "628a47761d5ce755de88444aaf6d7736b911672f": { + "balance": "18625552918216000000000" + }, + "62df6a38e8b15a1c4f4a7aa7c1736c612f54a0e4": { + "balance": "16468111299582000000000" + }, + "631d7916ddbb5f7c469f8ba07cd48e377560319d": { + "balance": "2493487426430000000000" + }, + "632754f5afcae7dc36d9286cfcd91c14abf0f7bd": { + "balance": "1424933496931000000000" + }, + "635788343997ea9f145c508b0cd2ed36e180f46d": { + "balance": "143040938538000000000" + }, + "636973e7dbda9e3042a8c03e25696d0faf27f025": { + "balance": "5491869128148000000000" + }, + "63707efa26d34d7ceadf4e6439324e7bde0ebc3f": { + "balance": "1000000000000000000" + }, + "637d92494f7872d397340c9b5183dce354c8c43b": { + "balance": "724687404033000000000" + }, + "63b9c2e6762a431752f7669b8bbedae9f37120b3": { + "balance": "1360967549741000000000" + }, + "63bd281d8c4d1279519237a2b68f2a73c228f7e1": { + "balance": "217457311664000000000" + }, + "63c0eb8c9a0019e36ec9a731b4bd947271a5bed0": { + "balance": "36693488147419103230" + }, + "63c6362eff56de328a29b7e9d32ced28f3602b6b": { + "balance": "148335309448000000000" + }, + "63c979c787a7b037693cadfeda738ae33178c009": { + "balance": "81000000000000000000" + }, + "63d4621d91906215d32f6fbcee1ac48bd773f630": { + "balance": "1006939236069000000000" + }, + "63ff99fec1cbd2f6e83c0e6de3c0ea4b7c7e1398": { + "balance": "1201300688980000000000" + }, + "640ffd856e48528b05d5ef1e60348048ce291960": { + "balance": "20000000000000000000000" + }, + "641c25f7c380e2745c81a268384a029b2e2be0cf": { + "balance": "635133477665000000000" + }, + "6427792a164bbeab45f6c3acf17c76f721b90e81": { + "balance": "10000000000000000000000" + }, + "6437986b4c545af9c4a5ee96371a5807275e9221": { + "balance": "2951152516627000000000" + }, + "64460d09d1bc5c425d62bef5969eb0c5916963c3": { + "balance": "1680000000000000000" + }, + "646381f92216b97abbd86ca100a773eebdf7545b": { + "balance": "211234535515000000000" + }, + "649f73d1cafeb3ab0631432f04c9d08b9f438c22": { + "balance": "248900746448000000000" + }, + "64a239be45a92df83bb85b25f8ed7de5d82313b9": { + "balance": "100000000000000000000000" + }, + "64a3d97f82e3d42eea78bbcee31a95d33767b055": { + "balance": "2511466286000000000" + }, + "64ad579975888f455217e0f801e371900d9814c9": { + "balance": "7118859416319000000000" + }, + "64af5edbfec8adea679951662c08a781175688bb": { + "balance": "822966999709000000000" + }, + "64b7f2c22c20a59c07cb0dd7f8f692153c68f3f8": { + "balance": "20000000000000000000000" + }, + "64bc17e28d468b7b8368ee8a8375710d21c3ac5d": { + "balance": "875002262415000000000" + }, + "64d17aa662e56061cebb3c2e2421e637163e8dd3": { + "balance": "363241251465000000000" + }, + "64d714ec3145308e8f939bab7591b0773038b886": { + "balance": "338231954012000000000" + }, + "65199fc9ba95434382c108b44ac553534a9a3670": { + "balance": "2537340957145000000000" + }, + "6527c67c29e47833dc2440570596023318a7bd99": { + "balance": "555434226832000000000" + }, + "654b9d299077c90768c5ca6635e5802e8099f51a": { + "balance": "119004827465000000000" + }, + "655908513607cc38de35351ff3738b201bbf39d4": { + "balance": "652902936029000000000" + }, + "656ad16063b2d397788c231e537384ece94eb0d2": { + "balance": "63116382606000000000" + }, + "656e622970b8829a7cfe24f5b82696c7777683ba": { + "balance": "20390269890405000000000" + }, + "6583a6ff4dfcf447e3b163a61b0d5cb84ceee375": { + "balance": "3858529344000000000" + }, + "658d2b7e8a6517256efafd74321757d5c384a2b9": { + "balance": "221114751567000000000" + }, + "65920758857ee5b27b0f31487ccc3c5d6986df3a": { + "balance": "16272975796000000000" + }, + "659d60d67a07774ecc5cfea9e56809bec024d639": { + "balance": "20000000000000000000000" + }, + "65a1a3f968bab5fc1f097b8e297099a3d34ef45a": { + "balance": "16000000000000000000" + }, + "65b5e3163d20b2a6fc75c0219b7f97d83479a26d": { + "balance": "1716459529041000000000" + }, + "65c9bc3b8b0ce7c4d16b35abe1a5c285a59f672e": { + "balance": "20000000000000000000000" + }, + "65d5b458d9b1a9659c1125d20d970d5e6c29dc3e": { + "balance": "20000000000000000000000" + }, + "65e75bb8ade25eb7975ea12b9afdb17ac21063b3": { + "balance": "2270407774714000000000" + }, + "65ed78d0c4ef1150e8765b24b210f056e079cd59": { + "balance": "500000000000000000000000" + }, + "664ee5e334b8378928becfbf5d5e51daaf001125": { + "balance": "860160259186000000000" + }, + "6679bdb26adc179d046607d49f4b10c65d8a40d1": { + "balance": "436794739763000000000" + }, + "6680fe9d6eda3ab9fc4ac1ac933339b533eb682b": { + "balance": "551296206326000000000" + }, + "66a1249501cc5076b040bbb165ce032ace216ea2": { + "balance": "36000000000000000000" + }, + "66a475d014c2f976704bfb93ce78dbabbfc5e072": { + "balance": "1140135640169000000000" + }, + "66ae43d92e8fb2231fee8c72d720ff90cdd267ff": { + "balance": "796696150339000000000" + }, + "66b7e0c810d6959afa8210f6ca67e3e40bd24eb9": { + "balance": "16000000000000000000" + }, + "66bf8be16f33b111b2a425743bb7ebcdfbb35034": { + "balance": "538590591000000000" + }, + "66d2eaf7fe10900d93eab17823ebfde5486aa2b7": { + "balance": "121000000000000000000" + }, + "66e525bb01b3ede1a4a105bb6087ec8a76200616": { + "balance": "1506610219207000000000" + }, + "67291e0df83d6e9f1386e87a1792d7d147341df9": { + "balance": "272330177662000000000" + }, + "6730b27b62e064b9d63df3bcbb8c4bbb0e500afe": { + "balance": "331282968154000000000" + }, + "67318617bfe19b739fac9a126fd129223db52498": { + "balance": "12699924981000000000" + }, + "674dd0b036c91f3a83288af44897b4ceb2e15a12": { + "balance": "4352791270187000000000" + }, + "6751bffd04be55c86692994fed06694cb78b62ff": { + "balance": "26049487516000000000" + }, + "6768d99a0cdcd7bb7c7d0aeee466d6bdc7208bbc": { + "balance": "309909685000000000000" + }, + "677ba2de3e5c68a4c354c9e3129ed1c41025312b": { + "balance": "127426274611000000000" + }, + "67b83745856551f1878027843be20e1473191944": { + "balance": "185757248875000000000" + }, + "68170edcfaf2c6df4e6542b2856ad33e9e2d6623": { + "balance": "4003453949471000000000" + }, + "684ae403d9a08e4f4f971cfedf81094074daa77f": { + "balance": "25139713925794000000000" + }, + "684f3b8a749c002aa434bad6af7a3e2579c69315": { + "balance": "16000000000000000000" + }, + "68538a9e8246be5a5c5ea315cb325344062cf8c4": { + "balance": "14009193210480000000000" + }, + "68935ff3a3a3b6ef16ae7df58cee50b157658dd2": { + "balance": "20000000000000000000000" + }, + "689f508256ea64f5dbd6bb77f1ce1bdaf36d7152": { + "balance": "10000000000000000000000" + }, + "68a3e6e7c191a8c1add988bfbbb9b51d4f36f521": { + "balance": "10000000000000000000000" + }, + "68a74ff2a5577321f854b56d3834a55d3c41bd94": { + "balance": "88873831171000000000" + }, + "68e6da521bde13cf4e4f423a78fda2f69b3d1c2a": { + "balance": "538392460838000000000" + }, + "68ecd5cf8cf8d9704fafc36d8da53930afeb0553": { + "balance": "1090923641219767000000000" + }, + "68fd0b8e000bd2788be6cb10fc0496fe2cbe155d": { + "balance": "32853847745000000000" + }, + "6904045feb5ef94e096894b863d314ff8a0f206b": { + "balance": "9892165615000000000" + }, + "690fbae5153849bb20797af7b8dea66a728a06c3": { + "balance": "6082107223716000000000" + }, + "693d909842877d017e0f102e37a55024517dd0ae": { + "balance": "20000000000000000000000" + }, + "694cd00fac9cded484ef2cfcd44faf161354f288": { + "balance": "3049716150137000000000" + }, + "6964c3c2c7bc719ec94a51bc4bf412e137d2b4e9": { + "balance": "1000000000000000000000000" + }, + "69a5c692516940bebad8efaa2243a8fbdf2ade62": { + "balance": "2803346939929000000000" + }, + "69f566c44802b0140f5e1c9234f46006773c03d4": { + "balance": "20000000000000000000000" + }, + "6a17eef3a6bd407260f52067592226448182cdc3": { + "balance": "1116509364305000000000" + }, + "6a200e99a0f50aab32fa7373c7880817c81f472a": { + "balance": "1836680122795000000000" + }, + "6a2a29f5f441876816dd17856051040787f48a64": { + "balance": "1131603204000000000" + }, + "6a3f855c7dceb75d0de7fa18fbc2f40c81b76756": { + "balance": "32267494586000000000" + }, + "6a46af653b938643e781cc4a0edcf5357852fd21": { + "balance": "1140718780752000000000" + }, + "6a4b2e5b45da0d70621ce71f165a11078a1745e2": { + "balance": "3768326643000000000" + }, + "6a530c813595a5b7776cced05a865dedcb110d94": { + "balance": "270559347097000000000" + }, + "6a6e3e82f98ce891f47721770301dbe2652a9e25": { + "balance": "10000000000000000000000" + }, + "6a828d6f2f7f68bde4a12608024020e593540010": { + "balance": "7531817000000000" + }, + "6aaddd1f4ff6b4d414c87271619b826ead27f09f": { + "balance": "64000000000000000000" + }, + "6ae6bce1e2865ade0d02eff9899ea3767b5511cd": { + "balance": "6893781798524000000000" + }, + "6b04e7c6a837d218fd3322b87a267fdd979358ef": { + "balance": "302679180175000000000" + }, + "6b2210b8536803b134e69c5046904acafef48cdd": { + "balance": "47823456459000000000" + }, + "6b2da6f36c2e7f61cabd7580480065360c995c93": { + "balance": "55000000000000000000000000" + }, + "6b3401986f2be7ae5a4ec160b8f96b2a651fce73": { + "balance": "16000000000000000000" + }, + "6b3847774e99dec307dcf5bf5adba49df4a9f145": { + "balance": "43276069579000000000" + }, + "6b57f2d9d95cac67fd2f70c0911d48c7f09de072": { + "balance": "1000000000000000000" + }, + "6b65d736a8ca89ec8508b52e4aca5166f9703732": { + "balance": "766421968820000000000" + }, + "6bcc55d897829e98fc3f3ac8beb331e59c33b942": { + "balance": "318115956882000000000" + }, + "6bd76e7af1775b88743d5f53ede0ce846d3d7ced": { + "balance": "139548017482371000000000" + }, + "6bd7cca99acf6eed5842417c2327c642df5473fd": { + "balance": "3321731000000000" + }, + "6bf72c4d39d6700181954a8d386c3df216634412": { + "balance": "12742769034078000000000" + }, + "6bfd3aedeac7c6ec086c0a4ec29d2d0f5bd69bc5": { + "balance": "50000000000000000000000" + }, + "6c025962810a6fb8374af5e07d7fcd631d10b1ce": { + "balance": "674126722005000000000" + }, + "6c1b72df836f410038af9e020fa2ff2ead398ef4": { + "balance": "1851293017364000000000" + }, + "6c1fddb4254ff46b3750de322ebb7d6238c0a606": { + "balance": "9977629348276000000000" + }, + "6c37069a361c5c72355bb5a56879dd0a9735a237": { + "balance": "1062230154063000000000" + }, + "6cb166eeca248a234c971b2a864a7b3fdbe5a737": { + "balance": "390222992865000000000" + }, + "6cb797289059cadcfa77eab0365e6bf1ae12df46": { + "balance": "100000000000000000000" + }, + "6cc787e6bb4f484828b080330667b93953e7a3c9": { + "balance": "16106440380234000000000" + }, + "6cdf7b334fb2ef8115198d475d431eeb7d88df77": { + "balance": "1940904395351000000000" + }, + "6ced85b035b787e9e427d0904aaf96e011417310": { + "balance": "103417697874000000000" + }, + "6d6e09acc07f388cbab99e53959f75e9ad8f07bc": { + "balance": "1305917678000000000" + }, + "6da91b02f512f412d374392247a9aaa853e9dd59": { + "balance": "2300525907893000000000" + }, + "6de5d70481cd40db468f64227228cdd362ad9980": { + "balance": "10447389944082000000000" + }, + "6dea87255c9ebfa63f017209046e894ecbbc03b7": { + "balance": "1527216854064000000000" + }, + "6df6f6b9953c2f2a8ce5985e19dd6835ae2c566c": { + "balance": "6539856530000000000" + }, + "6e013c83cac111a38fbbf8d47778fda0d3af25d5": { + "balance": "12139181929380000000000" + }, + "6e18a484f402fd433a5ac4dee5a4b8bf6f22db47": { + "balance": "23215906572368000000000" + }, + "6e4fd058e4dcd502c2015f83f3677f680ec58110": { + "balance": "480059342014000000000" + }, + "6e501ac7357fc758caf5dff6c29a995c806a1a7f": { + "balance": "1573491311733000000000" + }, + "6e6912f9fc21dfba736055e6ccef074dd62dcc59": { + "balance": "256000000000000000000" + }, + "6e869c68511c1458f4fbed9a4c5296fe961eb47e": { + "balance": "68488423994541000000000" + }, + "6ea6827b377b3d3ecf7c7628ed8daad7fd8eab1e": { + "balance": "188825714738000000000" + }, + "6eb9237738339fcaad3763466509f23efd0c5054": { + "balance": "48417242786000000000" + }, + "6eb92a61390f9d9ecdac80a8833aa801c3926b13": { + "balance": "1412936326723000000000" + }, + "6ecb93f18153ef2d2a552286ea3b7436f1f8168c": { + "balance": "20272577229669000000000" + }, + "6ee087c04cf16f4768c783a548686448fd125914": { + "balance": "1397039628538000000000" + }, + "6efbae7a34c71233329d0bb4cbec45274824ebf4": { + "balance": "8910000000000000000" + }, + "6efcd6776f287c25a6eb3cf71018adc282eeab6d": { + "balance": "1310659853178000000000" + }, + "6f9ca805ddaaea5205e85778dedb2eff4a5aaa75": { + "balance": "2585733757016000000000" + }, + "6fbbea927469f4d18942ce0aade164828fe23a2a": { + "balance": "4671857880000000000" + }, + "6fbe9df6c42151c453502960d99170445dd3ac0a": { + "balance": "20060296562115000000000" + }, + "6fed121fb310431f1659e637f35f4c878a7256c7": { + "balance": "55170085399000000000" + }, + "6ff2dd5373bd72966ef48d3183c60d74a6549cb9": { + "balance": "24103445361000000000" + }, + "703a490c4783776da244384c964897491aed3711": { + "balance": "2001677632732000000000" + }, + "704dcd2d9f75f0bbfb73f2fe58bcbf4508374381": { + "balance": "439603954369000000000" + }, + "70859a14f33b8ab873fa5781a4af1ce40dff65c0": { + "balance": "10000000000000000000000" + }, + "70b9cdfa5f6d41c60e1c0d3f544f569c9b340ea2": { + "balance": "198355566698000000000" + }, + "70d0ee793e28e320b34267ef2df69050fca0a9e0": { + "balance": "8010660534227000000000" + }, + "70dc7e5951752c22a0e3c50e8e7b1f7af4971d51": { + "balance": "3991137321749000000000" + }, + "71057f5afbed7d82c92d50790e3797fd7395d036": { + "balance": "49000000000000000000" + }, + "7109a3b3d5d6af49693549728691099d696ce016": { + "balance": "4119694297000000000" + }, + "712231a5161745fa1b33c7b0f6e8c767e1de4f81": { + "balance": "1353809351914000000000" + }, + "712aa38999c0be211654e5c84f59e3b2e018f597": { + "balance": "160199774000000000000" + }, + "713229fc94a86b71a5bd1ea6498b9373e3f3c549": { + "balance": "98289185940000000000" + }, + "715de29a0b6f467b94d4a90dc767ad52d0fb3b9e": { + "balance": "948824982990000000000" + }, + "71776853ac97ce04b008c9a7b64156a3cafc52a4": { + "balance": "608309596513759000000000" + }, + "7189f6dcfe64e1ddbfb5e51fd5f3174bc636dd0e": { + "balance": "5674608906899000000000" + }, + "718a4da87464caf6e83ca374d5ef9255b8f7cc3e": { + "balance": "761891873568000000000" + }, + "71bc447761cdb68915cc2288b4929fdc0adce02d": { + "balance": "10000000000000000000" + }, + "71d78531896642069b725bf82fc385789c63217c": { + "balance": "33103960195000000000" + }, + "71e328deeafbb1724051d1062609c43eef56ecdf": { + "balance": "493550967964000000000" + }, + "71ed0310fb51b86a61794aea17a3c792dd301e3c": { + "balance": "3234918634449000000000" + }, + "71fa264f58041e41cfe36e8f8d4e0cb22ab71925": { + "balance": "5558941960000000000" + }, + "72059c57d0fc05bc02ba54ebea6cefd1efbeadf1": { + "balance": "4458278271443000000000" + }, + "720847a28916a532bcab33e1fcbde5d1c4d820bc": { + "balance": "1392418942284000000000" + }, + "723cd2b5b836b0ee8481d37b9c51b5f3f1beddd2": { + "balance": "1856420455522000000000" + }, + "72430c6664d23c7051b0e99912fa54dfadcfdeff": { + "balance": "102078926010505000000000" + }, + "72652c4320dda25348f15c0ecfeb4b3b3ceeb7c8": { + "balance": "307639955659000000000" + }, + "7288bd1b9f4c068dd5df9bcd6fec1ccecd240195": { + "balance": "80161087899000000000" + }, + "7299cb8a288abe8e1a22c11b53a903acb7db5827": { + "balance": "752198565719000000000" + }, + "72f6bc0c3ae437756c099e02e9c084febedc5569": { + "balance": "696294297587000000000" + }, + "730e5907b344c80e0a6115723a90a23e3635192f": { + "balance": "6056082041729000000000" + }, + "732e97b992e4f8a53034cf29cf11aacba7452261": { + "balance": "100000000000000000000000" + }, + "7339df65ce293b3d501647a04c83819099f0bd38": { + "balance": "706500983417000000000" + }, + "73482f8135ca2231db5e0e034a235a9d244a8656": { + "balance": "1143989148865000000000" + }, + "73769e43058d30a530048e5a2bea7e9333534e93": { + "balance": "113542901996000000000" + }, + "73bb9e6f1709fbb7964df7b3cc0f9170c3152f38": { + "balance": "1639793026701000000000" + }, + "73e261da7978764044ee916f88bf66680952607f": { + "balance": "100000000000000000000" + }, + "740154120c4f41c50b0aaa0636a2000ff1e870ad": { + "balance": "10000000000000000000000" + }, + "741fe2a1537284b70e97e3ff659eedfd7fc5b1b6": { + "balance": "75911502037000000000" + }, + "7420bb277d834763e4429db9bf37f053f71ab769": { + "balance": "3100160195046000000000" + }, + "74281371c3b569c774da6bab686e7d7a45d4dc4c": { + "balance": "25666397941223000000000" + }, + "7428d261b5418652c5ab248d6abc3d2af25d904a": { + "balance": "56252809397000000000" + }, + "742c876433297f5a8fd4a25f75ee9a607726bd3c": { + "balance": "4132793019677000000000" + }, + "74302036cf52e11aa3f32a371bb4992e2bdc3f39": { + "balance": "19557661364000000000" + }, + "7445c657c24d014f3a9dddc3e446868bc2dbd13e": { + "balance": "10000000000000000000000" + }, + "744b8fa69d2542be3557267edaeaf2cfa8a9e991": { + "balance": "16000000000000000000" + }, + "74728999963524e7cc1736abcb4deac630142c44": { + "balance": "37000250991000000000" + }, + "74926cbdacd0e871cad0d926c8e17cb2c00475b9": { + "balance": "20000000000000000000000" + }, + "749e115a9e675bb15af5e1c04f81fede07c40120": { + "balance": "440913547154000000000" + }, + "74b7e01acf825898544d6c1b61e53356be759c56": { + "balance": "25000000000000000000" + }, + "74c5fcf875e2e9b726a7cf6e176dc2f7eb84c200": { + "balance": "59208835472000000000" + }, + "74f44579859e4a7944dda7bd810088e116ae9910": { + "balance": "1038454108527000000000" + }, + "750b1e2955ba05c1fc8a1f9dbb1624ed11587edd": { + "balance": "9545712605000000000" + }, + "75375129cff2a051f656b91f868325c3b35ee1ae": { + "balance": "25000000000000000000" + }, + "753ca28fbd89081382a996fe938da7e6c3ae6cfd": { + "balance": "156582454263000000000" + }, + "753d91c04e554680cc32a97c1abc96280e8263ee": { + "balance": "725101425969000000000" + }, + "754e5b5d64c267e83fd4804d112725531cf5abe9": { + "balance": "83276113115000000000" + }, + "7588a96a2bc65569a6c124c4a4acc55863a8ab78": { + "balance": "24062602342000000000" + }, + "759075dc3a6b9d2499a74bc57e346c9ed7ff834e": { + "balance": "225000000000000000000" + }, + "7591d6fa043801fe12462e11d9e33a53f438c073": { + "balance": "1863874274000000000" + }, + "75bda5bdf6aa749bbd62b6107941a7dd9ce3880a": { + "balance": "36000000000000000000" + }, + "75c2d3a99f144c4b9962b49be9d0a81b203906e8": { + "balance": "9000000000000000000" + }, + "75f587a69a97eb4d1c4c4078418d5fa85dff6f94": { + "balance": "10000000000000000000000" + }, + "75f67649605f49d98d866102ea2d6881ead9bea0": { + "balance": "814929108418000000000" + }, + "7602abce0f510b6ca471fd8d734e21a2591886f6": { + "balance": "50000000001006000000000" + }, + "7629b788160531b0be28bf445bf305fbe2c514d2": { + "balance": "23022256366212000000000" + }, + "762aed2e3aa2293e69dc2110b1fc6c806ae799a5": { + "balance": "10000000000000000000000" + }, + "7637b89130bc3f87e90c618fd02d6dd27179101d": { + "balance": "77765738300000000000" + }, + "765136022facade53e7a95c0c7aa510787e674d5": { + "balance": "1478178932688000000000" + }, + "765274015a308a9e6b1f264e5bac592d267f2f7b": { + "balance": "3058788819393000000000" + }, + "765cbc0a89fd727a2c1a6b055139faee53f11330": { + "balance": "500000000000000000000000" + }, + "768bb6d4b190c18a0946d92073ee446d68d98a6f": { + "balance": "144000000000000000000" + }, + "76ae8079894c760f2850c02cf5a0d7bb41e5864d": { + "balance": "156059816821000000000" + }, + "76af4103a231b1302d314c486a0ba524d0427899": { + "balance": "10000000000000000000000" + }, + "76b6394cd02ddf761e981b6a6ce1654c0e575443": { + "balance": "1078304803757000000000" + }, + "76db33eafeaf965dcf15d5460b64a48b37285259": { + "balance": "1000000000000000000" + }, + "76e5721c0a39d41274f84cb572039967a07e9beb": { + "balance": "156298167226000000000" + }, + "76e6ca6ef145d2711ab27f82376a065cc6f62a29": { + "balance": "100000000000000000" + }, + "7705d637cf9f6ceaa452deaca7ccc581beb5fa34": { + "balance": "36254762908065000000000" + }, + "7706c80af4eb372e168501eedfe7bda6dc942243": { + "balance": "50000000000000000000000" + }, + "771493da92c9fc6c6b39a4071ae70d99f6a588d3": { + "balance": "2000677471360000000000" + }, + "7719206286f26144c0f20b5e1c35cf4495271152": { + "balance": "1380480863056000000000" + }, + "771adcba1409fa2df6db19d9f784abc81a7bbf36": { + "balance": "15416381820915000000000" + }, + "772f7baa80a852e05b2fb3903a36061da132b2d8": { + "balance": "121000000000000000000" + }, + "7731a4175eee5077e2ede48878e6e2a18fce0f9e": { + "balance": "10000000000000000000000" + }, + "77385deeba01e3cd7a63e13d6048011020f56724": { + "balance": "57204247488000000000" + }, + "776808e7688432755b9e91a838410d29e532c624": { + "balance": "120318608715941000000000" + }, + "776d1b406f63082b80e250c4a0073fa0d83b9090": { + "balance": "243779839900000000000" + }, + "779848a59036ee3cd23b93ff6d53620d874f0bee": { + "balance": "82228810849000000000" + }, + "77d02a031274bd4ed2a16f3cc29d94e755142036": { + "balance": "408567696646000000000" + }, + "77d609a407aa0d126d58090b8d635f5ab7a02d6d": { + "balance": "776754055755000000000" + }, + "77dec41e116301dbd6e542f139816bfd9bf6d154": { + "balance": "16335989583000000000" + }, + "780398b42f81167731a8ef6a8bd1d14942b83267": { + "balance": "25000000000000000000" + }, + "780a645d59027e7b0670d9565898dc00704cbe5f": { + "balance": "20000000000000000000000" + }, + "78182a7711c773f306ec42ce6da3e983cd49b00b": { + "balance": "580861257254000000000" + }, + "7822622f07fec12995c4bb8eb32d62aa7f00be05": { + "balance": "5018461926846000000000" + }, + "786410c679101c0ebf06fb4f36102368121f3c8b": { + "balance": "16098386724761000000000" + }, + "787d5476038ab0a09b846645285ada23ffd7318c": { + "balance": "492047430907000000000" + }, + "788e9e27ed979d1e7aefadda798f69df1de1d1bd": { + "balance": "30965301214000000000" + }, + "78ab2d2dfaf5d2580ed89c970e771572bc91d3be": { + "balance": "36000000000000000000" + }, + "78ab7ac6f379ff084a7acf4a1a31fe2e5a6834c0": { + "balance": "107332516726000000000" + }, + "78aba95da37385c736ef93d0ca8318baf6c5ff3e": { + "balance": "9000000000000000000" + }, + "78cecbd82229dc91a530bd555c9e45125e2a6bc7": { + "balance": "28474069251604000000000" + }, + "78d4df90990248f3ac67e492a0a1e3f4ee455507": { + "balance": "10000000000000000000" + }, + "78f6de3768abc604c49b10d798e0656948cd334e": { + "balance": "9000000000000000000" + }, + "7909aca95ed899743de222e56c231f9bed1b518a": { + "balance": "5355599376491000000000" + }, + "79193e660b4431e8aca9c821b7daa88064e33750": { + "balance": "100000000000000000000000" + }, + "792487caa23b0d9b9998002810cf29439f7190bb": { + "balance": "4828579961131000000000" + }, + "793f56adea51063243a9633ecc1d1e620a91f327": { + "balance": "926742377449000000000" + }, + "796d187077c1d7591583436ae64d10a641490ca5": { + "balance": "242664407084091000000000" + }, + "79a6b7fad3b5a655679450ca82818ec2d6f58688": { + "balance": "1400472715109000000000" + }, + "79acf627e67cedf48297c26fd135973bff6c57da": { + "balance": "444598475759000000000" + }, + "79ae0dda1964ff0191b98d28c9b52a79dc9ab078": { + "balance": "325908985422000000000" + }, + "79e71dcc52fa1b28226c519f715faa3cf63cfb09": { + "balance": "497898493594000000000" + }, + "79e98193ff8770f26af824734bbb1c2ce8197b6f": { + "balance": "10000000000000000000000" + }, + "79ff3d790d52c58b7317a415278e9058915d5241": { + "balance": "48502649691864000000000" + }, + "7a0b02d16d26e8f31e57106bbdad308f513d436c": { + "balance": "841000000000000000000" + }, + "7a1d422352ec7e6ca46131728e4b71f20ed84e2f": { + "balance": "50496873413000000000" + }, + "7a2a3fbe27e33df867ba8800788995d7662c046b": { + "balance": "100000000000000000000000" + }, + "7a629c4783079cd55633661d2b02e6706b45cf8e": { + "balance": "50000000000000000000000" + }, + "7a62d8875f53e54b775ee2f67f7e2ec137bf724f": { + "balance": "25000000000000000000" + }, + "7a67285fd883d36ea3107aa3fe7727c68a99eb2d": { + "balance": "254787158217000000000" + }, + "7a90fbec48492473d54b0fad128ceda94ea66100": { + "balance": "313715004199000000000" + }, + "7a9e11463d84a08140d698972e32e66bacf7a7c9": { + "balance": "3602603216258000000000" + }, + "7ac4f33e1b93ef0f9c15014e06da24904ef4419e": { + "balance": "101000000000000000" + }, + "7ae082ad247275fd5a9e77b127cee5693784e9e1": { + "balance": "1921957343533000000000" + }, + "7b27e070ca4158d13f8333b34842d4c28b678c92": { + "balance": "10000000000000000000000" + }, + "7b2e34374921e4dc10fd9cfc670a40f5d092da1b": { + "balance": "2098457950503000000000" + }, + "7b54c6c8041c8b09240de1ff06e0d3d2d8d877e0": { + "balance": "944752036841000000000" + }, + "7b5aecb798d8f4f5a04bdaef909e09a35bde8d47": { + "balance": "21975115049000000000" + }, + "7b88a7ef9201966bd1ca634779c3b7f40c22f0d7": { + "balance": "64344833519732000000000" + }, + "7b8c22ddc5c7e59e571587d7c776fa50e65f4845": { + "balance": "225108110445000000000" + }, + "7bb4d8a169f72432494ac362eeab005ce1e02d81": { + "balance": "2098993419448000000000" + }, + "7bbaaa6690698e749d095447bdd27207c0caee43": { + "balance": "490069993631000000000" + }, + "7bbf27f92f9f726381d4f68b21ed86af8f792d04": { + "balance": "806346082666000000000" + }, + "7bc6f172fd78953c3456c571ac8394756715d5fd": { + "balance": "81000000000000000000" + }, + "7bcca29b477730ee8f219a5d1bca24415c7a4625": { + "balance": "36273885000000000000" + }, + "7bd296e1cb29ad87ed28b0ed18440ee686b157e0": { + "balance": "35964679698000000000" + }, + "7bde6d49a1af34a5a9dac0b9007e9a5583c65ebd": { + "balance": "1041474566346000000000" + }, + "7bea6240f245e649563253fa4c1da39b12625da7": { + "balance": "100000000000000000000" + }, + "7bf096396c56f27f9c39c4056ee6cfcb0db44bc6": { + "balance": "407261849111000000000" + }, + "7c3b58d3ba283bd9b1580832e9d014eff48bff7f": { + "balance": "7074518779349000000000" + }, + "7c5a56c45f23c353ff9f6f71ec86c9a6a1a0ca67": { + "balance": "11277879639596900000000" + }, + "7c783ac9b07bc6576835635f37e7e3c137055c8c": { + "balance": "16253676225000000000" + }, + "7ca2fbc0a0d1370e95048a21a300eac4d6056df3": { + "balance": "2772084065617000000000" + }, + "7cbe95802a20eb765f9fcff0a068859cc35d2660": { + "balance": "255153842674000000000" + }, + "7d004fb3a6a81c00fd2872e8079ad2912841b0e0": { + "balance": "642630220843000000000" + }, + "7d30c788d4ea18849ebae1173373c8915ffd7a35": { + "balance": "61062263242000000000" + }, + "7d39324f5ff62e849b0f0f46ab8ee396fbd85581": { + "balance": "100000000000000000000000" + }, + "7db0ce6c04537417dca1dd3415a5bf213edc2028": { + "balance": "30393443462000000000" + }, + "7dcfaa795586c92f1ce7d5c7b10608fe6a773fe4": { + "balance": "183173395920000000000" + }, + "7ddd111cfdc3133f59b82568e3deefc3cf10b0d0": { + "balance": "5622149283840000000000" + }, + "7de81daaa7ed5cbf4d379cdd26ae353cbd5a2489": { + "balance": "10000000000000000000000" + }, + "7e0a11af993a41626c5564f719442c0dfd608ec5": { + "balance": "1532083534600000000000" + }, + "7e34971b187047e7f7980650630b936eedc11023": { + "balance": "10000000000000000000000" + }, + "7e5214e16851b33c4a4d29e5a06929461d3d9555": { + "balance": "371790231197000000000" + }, + "7e52ae9c7e4b888015a3a5af7a91444510aa18e2": { + "balance": "109879329128000000000" + }, + "7e69b383671f96b7abc2d1fed8b61477b87a58dd": { + "balance": "10000000000000000000000" + }, + "7e733b1fcadc9a20dc038fba74e236af0b5a39b3": { + "balance": "43583614302000000000" + }, + "7eadcf955c90040668fb0f75a61f687e4e41f314": { + "balance": "332201682206000000000" + }, + "7eb51f3ead1dd0f5384c199ad5518ec55f77d35c": { + "balance": "38487884822000000000" + }, + "7ee73c0d64caf46f47f439969060092ecafdecd9": { + "balance": "15063618320000000000" + }, + "7ee8e4c6742a4c6d8efbfacc4d56119bc6c74ea4": { + "balance": "31882319329000000000" + }, + "7f16d981521c06347db8324da38b25eab3cee23c": { + "balance": "400000000000000" + }, + "7f6ff7db81a26fe78dd80636f0b178c669344393": { + "balance": "10000000000000000" + }, + "7f792b094c0b96d6819823cf21bc0c402fc27bf9": { + "balance": "50000000000000000000000" + }, + "7f84ae97c21cc45a7e56603ddf97449d803fb246": { + "balance": "81000000000000000000" + }, + "7f89c2b9daba034841f19ae843cfb6cd6f75b1d7": { + "balance": "20000000000000000000000" + }, + "7fb18f8b0e1fd1ed8c863a66226082bdc0429ee6": { + "balance": "11465417544634000000000" + }, + "7fb4e30579c64efe981d0057204e5bd8770a1f87": { + "balance": "249801873762000000000" + }, + "7fcc4de10e837d98691acc52732e1568c890304a": { + "balance": "1000000000000000000" + }, + "7fcc77798cd50345b2784a78b81a25dd4c1e64ab": { + "balance": "2676882485895000000000" + }, + "7fe33e773a02b995278ff595d55a0741813b19d4": { + "balance": "5788279057355000000000" + }, + "7ff32b13d531ceef500ca6c6806ffc0773639264": { + "balance": "1000000000000000" + }, + "801380158ef8f24316bdceaa00eb89c3d886707e": { + "balance": "35627521347898000000000" + }, + "804fdccdc8603858d15dec88666437505b2a106a": { + "balance": "14607090269617000000000" + }, + "807915567eed99bb9146354a32409812b9490d70": { + "balance": "1083142734057000000000" + }, + "8092ceeb2be5b271f4c156d85fe14977e919c7e0": { + "balance": "761607160308000000000" + }, + "80962bf961d0d713395dbe00379a6e207b425a76": { + "balance": "524215754483000000000" + }, + "80a9787124075c8cd44b9c8674967a54445e2354": { + "balance": "7600078997429000000000" + }, + "80aacd59dd76bf443c47ca02976178af8453f23a": { + "balance": "411856023767000000000" + }, + "80db788f7fbd7613f0fff66c21389eedbbd4bd35": { + "balance": "956888725645000000000" + }, + "80e449a70e3c7707d6441ae8863a44aee2d7f3f2": { + "balance": "16260784762856000000000" + }, + "811a2c3d0ba4e1c36a848495585da824ec3a7620": { + "balance": "36000000000000000000" + }, + "812a3c55234d5849a854ad76891c34ee90c8a0e3": { + "balance": "703378980438000000000" + }, + "814b4b5eb67afb8d1a60e3d240fe804bb752f632": { + "balance": "17578964576000000000" + }, + "817025619f37838470b90d0a25af2c02de80dae6": { + "balance": "96000000000000000000" + }, + "817233a104d87cac34d9c90243aebd7f68e0a9ea": { + "balance": "510051038684000000000" + }, + "818be95c0c13c3018b4084ea177556705e84c1f5": { + "balance": "332239667000000000" + }, + "819618c19a4a490b821f8156c5633749ea782ca2": { + "balance": "10000000000000000000000" + }, + "81a80d26b70626e07e8747bc1569dd2855834f7c": { + "balance": "521696417321000000000" + }, + "81b2fb0db882bf2538cf8788bae1ad850cef3bab": { + "balance": "102457067052000000000" + }, + "81d4c3bf72837b21203b2a4f90bf42fda10acf48": { + "balance": "10000000000000000000000" + }, + "81df59e5d7b9a2db5463b53be83b4d7c7673d163": { + "balance": "887372337013000000000" + }, + "81ef38d074e0aa9ad618deaab01bcd135301fb67": { + "balance": "24072930558567000000000" + }, + "81f3a4c5291f13f8f97a067a6ed744a686331eaf": { + "balance": "56612148225000000000" + }, + "820610d0ddd3e9f3893f7cc13f32b1ad0d169f81": { + "balance": "50000000000000000000" + }, + "822d6388145e96cdeb2900420a0e0436e940b670": { + "balance": "20000000000000000000000" + }, + "82323b748fdee9f18e34aefc4ddebd4993ac6293": { + "balance": "112752706047881000000000" + }, + "82324995b36f4ff15be3559ccee14742d5b4c75a": { + "balance": "1184047304377000000000" + }, + "8235bfba0bf0fb664271ebe534616456a78852ce": { + "balance": "6804584686000000000" + }, + "824df7b17a61392f88f7e3067f8c261abb48806b": { + "balance": "144857897574000000000" + }, + "82555a7aebfc95a01a3773aa5370394cadef0302": { + "balance": "40069354268401000000000" + }, + "82831d451b8f92fbf6a763adb708010a3e66bb60": { + "balance": "8750983992240000000000" + }, + "8294176178418f46bb18440cc87a07cf40c1669d": { + "balance": "4439783816461000000000" + }, + "82a1c733c3c937ba0a1a49481e4d1f6226157d2a": { + "balance": "50000000000000000000000" + }, + "82ad0b5dc23bc763da0352f5983efceeaee6ea08": { + "balance": "171723633433000000000" + }, + "82b4a3d16655fd71f4020e6a562592a621ff6e1c": { + "balance": "190211621484000000000" + }, + "8357d5a016a00aa5e3ef05d3ce210826adf4c501": { + "balance": "10000000000000000" + }, + "836c41d7f9e72131eff839b7d510fd0ed412f939": { + "balance": "15575572364757000000000" + }, + "8377fff2b0eb03393543ddf5ffae90b3311af5d3": { + "balance": "2058810049054000000000" + }, + "838859e6fd751539a88d00581b0e19bc98c37e47": { + "balance": "338264241636000000000" + }, + "838da0414211392b644e73541e51e9f0fba26615": { + "balance": "20000000000000000000000" + }, + "83958896a43d23ef4ba01bdf6757c36105985096": { + "balance": "9000000000000000000" + }, + "83b88314b606df40d5e716df488980bc64125b46": { + "balance": "10985538717083000000000" + }, + "83bf53fa162e1d85751be0bc6f46e8ec881392e2": { + "balance": "1497107276676000000000" + }, + "83d7c52608b445e18fb1e28dc6198908d66bb6d8": { + "balance": "265446362740000000000" + }, + "83ee8ebaed62092d2116de6b4e90778454e8dfc4": { + "balance": "1000000000000000000000000" + }, + "8402fe573658250f50fbe111596ce35ea9ec01ca": { + "balance": "3479737676000000000" + }, + "8412b877e708a7d5db2a38d9b0f4f23d12231f63": { + "balance": "9225027744855000000000" + }, + "8418dcc09fe052febf2946ee22bcc8c53d548eb6": { + "balance": "3000000000000000" + }, + "84199f54ef96bda5e14f60aa1723e811f755d3bb": { + "balance": "129197612052433000000000" + }, + "841b1400f97ecd2ca008e7b4f5a95274bc3e99dc": { + "balance": "2095180906854000000000" + }, + "844177191a120d2dc4be9169ddbc3b5430e9e238": { + "balance": "3620793599287000000000" + }, + "84578fcffc73be7d65bfa81b0cdafd26885bafbc": { + "balance": "37592478429000000000" + }, + "8460acb05c6c476ca26495aec7224c2bf90996fc": { + "balance": "8999580000000000000" + }, + "84696cdb9f018d3e7bf453efdc174e1a586e9c25": { + "balance": "118007806297016000000000" + }, + "846a8a91d2890000d1e995fc1663cf5b7c22211c": { + "balance": "27266838638307000000000" + }, + "846b5ef52d5f7ccc17d9c7e5f49db807908c63f3": { + "balance": "375423381758000000000" + }, + "847409e5d6ed2c4e54ff97f2ed58217ac5fc3d68": { + "balance": "23972870617025000000000" + }, + "84bf432c967540caafb8bf49cdc9983e8953a18a": { + "balance": "453476687224000000000" + }, + "84eba1bb76f7a3f6d2b9052d068cc6c48d449d76": { + "balance": "17655334922000000000" + }, + "851245ef1637a07578241b3c35acf215908e1898": { + "balance": "1269389304110000000000" + }, + "853708e974fd4810655d9cd19fc8dbfd3d5e1e36": { + "balance": "18000534000000000000" + }, + "8547989af8c99a3432038a03d3fb30a054d90413": { + "balance": "10000000000000000000000" + }, + "854ba39bac4c7bf619804b6773fe43bc71f3255d": { + "balance": "15999580000000000000" + }, + "85636f3e113cbe1d1bbd1b3a23e9e98edbcb94f2": { + "balance": "1199038399611000000000" + }, + "857167896b859394babf897c4c6fa57b3a057117": { + "balance": "921057404898000000000" + }, + "85799226a1474371ca76f05597a1e3835c17e7d7": { + "balance": "562141544946000000000" + }, + "85a2221cbbb47e8b74fc2617d6087a98f47e2738": { + "balance": "10000000000000000000000" + }, + "85be0bd55fb9143ff17387914a82d0a2650224c4": { + "balance": "4038654147145000000000" + }, + "85c5ff0e4956ef0fb662a2cbf6a86325a53dac8a": { + "balance": "28690160424000000000" + }, + "85caff4ec0e1719ad963e97c1c02828683070370": { + "balance": "2022427900763000000000" + }, + "8630cc2780fee566f172ed0437264c45421ce675": { + "balance": "669721278148000000000" + }, + "8633d245c5f1b63403e3d7828dc197ce1cfafc0f": { + "balance": "10000000000000000000000" + }, + "867ccceae3192a27751d870ae13b1d3d2c3584dc": { + "balance": "1491436265909000000000" + }, + "868bed241f77983ff4a7a8d0bf121299b6b2248b": { + "balance": "5600000000000000000" + }, + "868ddd283a76a26c8bbb9761df3ca647bea267e2": { + "balance": "9000000000000000000" + }, + "8696e546f96f6e51f405905e095902db8bb90118": { + "balance": "533558981421000000000" + }, + "86ac0eae4e4c20cb7019325f4dbebad053f92213": { + "balance": "697960117764000000000" + }, + "86bef47f9d2cd7526495454eb4d1737510696a5f": { + "balance": "2938307902381000000000" + }, + "86ddd4e3f444b395be8b2b2b75c35c78877fefb7": { + "balance": "15615434748526000000000" + }, + "86f115ed19a32aba4f98270b8ad45820abbc4653": { + "balance": "151868798605000000000" + }, + "870f19e7ee358de61ad0fd3c7710441156d68f66": { + "balance": "674715936435000000000" + }, + "87141a2d3857fb8a328ef8e7b503ed965294c85d": { + "balance": "1609607183158000000000" + }, + "87257783d866af25a7a71b46ea6c2bd1e9ab9596": { + "balance": "64000000000000000000" + }, + "87298979a9a0dbc272b0e15b7e5f2e42639c9912": { + "balance": "722087160930000000000" + }, + "8757b784015f88d072229176cabefa358a0e95a4": { + "balance": "204003337866000000000" + }, + "8760e60a56c5b8b61276634a571400023f08e3ac": { + "balance": "1000000000000000000" + }, + "877e54ea7e8ab03bb8e2b842dadab16bf4ae0a4c": { + "balance": "341020957932000000000" + }, + "87919285fc5d98169bbd073cebb1b3a564264dd8": { + "balance": "579080463078000000000" + }, + "87c39cfaa9c82d84119f306e6a233a3abfbb0ad1": { + "balance": "121753433796000000000" + }, + "87d479659a472af7c8ea78a3c658605f8c40bec6": { + "balance": "20000000000000000000000" + }, + "87d933ad6fba603950da9d245b9387880e6d9def": { + "balance": "1087642723520000000000" + }, + "87ec448309024bb1b756116b81652ea518cf353d": { + "balance": "344562808694000000000" + }, + "87fbbe010837f8907cc01a5bbd967f402a216488": { + "balance": "185411503628000000000" + }, + "8805a3c529bef4d19a6491f3b7d7b1b7232bb93d": { + "balance": "264150205918000000000" + }, + "880ec9548864fcd51f711ab731d847260ed0e3d5": { + "balance": "723225945994000000000" + }, + "8818d160b56b18e196871a6c7ccf02112dc13342": { + "balance": "2857439182291000000000" + }, + "8836e25baa08c19a9b0155c57072582b49f7dbef": { + "balance": "5468425690148000000000" + }, + "885b6303d06142accf2ddddbbdd4a9379d1cd124": { + "balance": "11853214736000000000" + }, + "88656958d9cd758d71546ba52c4ea646b658c84c": { + "balance": "10000000000000000000000" + }, + "88740acdf9ab5711d015391fe8cf4a7c70a0bc86": { + "balance": "510027156671000000000" + }, + "8874966976d776c3154261afa802692afedf3d3d": { + "balance": "305634301700000000000" + }, + "88aea53c727d7a5dd8a416e49faba1c4f741f01a": { + "balance": "15358334295959000000000" + }, + "88b67d05997ae3852259ca638a00ce9b9e7e4a61": { + "balance": "278125551806452000000000" + }, + "88d730e074a102048008de81d3adcba831335736": { + "balance": "5984576042159000000000" + }, + "88da27b1f0a604a87fdedd9ea51087a331179cb4": { + "balance": "10000000000000000000000" + }, + "88efaa91dab9671f5c903e69aa6ca4d9a04b5ddb": { + "balance": "1996126782729000000000" + }, + "89a9d702f64f14fae4d1a69717744dd700208d9a": { + "balance": "251686323241000000000" + }, + "89ac81571265bebbf9d3c09e9459fd1ba7fb1297": { + "balance": "162368080974000000000" + }, + "89c75c4f0ce41d283587beba1a3e3efab05ca6ad": { + "balance": "16000000000000000000" + }, + "89d44cb81cc5a1bdf4d573c4954ee641f3cb91d1": { + "balance": "97965629614355000000000" + }, + "89e2fef4f7b7c255b36afa81cf4033b22de3db25": { + "balance": "7278615226888000000000" + }, + "89fe5d3cb5283c7b87daf6103bb568f92a230631": { + "balance": "64000000000000000000" + }, + "8a07242231f4a654aeea65b857d1519385a18065": { + "balance": "20000000000000000000000" + }, + "8a5a415f0fe2a8329e14628493d11ca20d4e482a": { + "balance": "157274758238000000000" + }, + "8a6ce9f270fe3ec33a013be9e5b1ef823c0dab53": { + "balance": "20672772672000000000" + }, + "8a6fe4fa2f86f879ec9b2bf643beeb0876da46d4": { + "balance": "1041983771868000000000" + }, + "8a765ff2b429dcdf59b65a34c4bb41798dfb5886": { + "balance": "355487172996000000000" + }, + "8a9b9b65a3d443a6e4dcf696a64983f3b625774f": { + "balance": "3185351572575000000000" + }, + "8ab1f5443cf9149773b9ddb69de3e6ea047ae38f": { + "balance": "161619949415000000000" + }, + "8abeacee0078e07fb417277e8bf15dcc2cdb9fa7": { + "balance": "144000000000000000000" + }, + "8ac0d9e0e77aa4ada4080604f2118b3a5a0f8102": { + "balance": "100000000000000000" + }, + "8adae0dc99300f60d31bfa619ec83d45b48ea22b": { + "balance": "697262590215000000000" + }, + "8aef59e59a27a8662043f1a4abcaf945a5e3fafc": { + "balance": "26780431538000000000" + }, + "8b3386f32e2d77526c223ee8bb95b7dd111ced92": { + "balance": "2179932854210000000000" + }, + "8b34d5e457ef6451bb7f5ecc93c80678a30e3194": { + "balance": "31492358338840000000000" + }, + "8b47e07f192c33bd7d298bae717dfcd68a8097ae": { + "balance": "1000000000000000000000000" + }, + "8b55bff4b281f6a24ab428d66b91f9bab06f7b96": { + "balance": "1596248680941000000000" + }, + "8b576b1e2391f22193bb4f91bec5f2a8aec02af7": { + "balance": "29660301836269000000000" + }, + "8b9097b762c7bc38a487974f3551fea697087553": { + "balance": "260887123991000000000" + }, + "8b92c50e1c39466f900a578edb20a49356c4fe24": { + "balance": "35654824979000000000" + }, + "8ba3933337108841a997accf0b5735e005373f53": { + "balance": "574965182000000000" + }, + "8ba3eeb2d1b27e021ed6bf5827280807f32c7897": { + "balance": "64000000000000000000" + }, + "8bb23a5b8c48ec5bde84f39b463559b7c048c853": { + "balance": "16186405874000000000" + }, + "8be0b6ab14e15b46905335d07df03726fb1df0e8": { + "balance": "500000000000000000000000" + }, + "8bfc53af1ae6931f47ad7f7ed2f807f70fddb24e": { + "balance": "20000000000000000000" + }, + "8c0599df87df142d3aea37d50c975c1813ecb642": { + "balance": "871085782287000000000" + }, + "8c2deeeaf095be075a2646ed7b8764d3665acf14": { + "balance": "10000000000000000000000" + }, + "8c3e7381b0598356ff81e860faf25390ae7de9d9": { + "balance": "36000000000000000000" + }, + "8c5671a6f4610ddbd05a5139659c7190f54117b5": { + "balance": "50000000000000000000000" + }, + "8c60582c4e4e60da665b4a5a2d18f514ded6c49d": { + "balance": "16806447782991000000000" + }, + "8c8464ea6b17687eec36ef04966d59c7c91fa092": { + "balance": "1872124465602000000000" + }, + "8c85c5a318cc0227576adba3e91dce6adc73f6a2": { + "balance": "52479305517000000000" + }, + "8c8f3796a2942a2298d14ff1a9e3264e9f63f2bd": { + "balance": "10000000000000000000000" + }, + "8cec1886f2cc71b09ca32a1cf77a280ae3a6a9fe": { + "balance": "500000000000000000000000" + }, + "8d0b26d57eb52a62814d7876d64c8274f4371464": { + "balance": "20794037603000000000" + }, + "8d40b92e41f3cfec06e767d64b4dafc5612133b6": { + "balance": "25000000000000000000" + }, + "8d41ea1cfb70d0ef1f6572fd72a6b417739ac7dc": { + "balance": "738777348304000000000" + }, + "8d4eb54646f9d14882fc8ebb0ef15f6056d1afbb": { + "balance": "1003867239086000000000" + }, + "8d51ab29ccd190bfe12bcd94a651e9f49a003253": { + "balance": "442251355663000000000" + }, + "8d6c0c8e4ca47626115433b39feb939014b8738f": { + "balance": "119828137027000000000" + }, + "8d7acd92d664a485625bb9884e7cac9cc6077f41": { + "balance": "1381910232084000000000" + }, + "8d7ee7a9c1c263ba8061f54dcf62d9f8420e2008": { + "balance": "20000000000000000000000" + }, + "8d941c5d0c6e2b8e2934c9f80f8a63e2fb5868ef": { + "balance": "116443644149000000000" + }, + "8da0dc43ed3ccefb18f21aa13f3fa42c13e540a6": { + "balance": "516000000000000000000" + }, + "8dab4500316475e8fc3bb6494be09f549dedf026": { + "balance": "2736245677000000000" + }, + "8db39a95f4e63bde0bd8c02e386122ce2c57a30f": { + "balance": "12577347153000000000" + }, + "8dc718b49fb68584d9472490743f9be1b0ad683b": { + "balance": "50000000000000000000000" + }, + "8dd05e26224aa8a6deb0904b6d3bbb34d268e901": { + "balance": "613146658282863000000000" + }, + "8dda0e7ddde515480ef08cf90a1eb4e78f50a2c4": { + "balance": "19265526663314000000000" + }, + "8dedad1511c11798c338334dde7be967de96e9b2": { + "balance": "50000000000000000000000" + }, + "8df63c04f18a854d7bb397bca3e2ba19202e9da1": { + "balance": "1479940547081000000000" + }, + "8dfd7edb7d28e8b3df1faab70a8ef9e3b923d998": { + "balance": "10000000000000000000000" + }, + "8e2c3af057e931b5f82e83873b336a7f68e7eb03": { + "balance": "27138009123000000000" + }, + "8e2f4eaddd60468bdc09d47f65839b96f50596ef": { + "balance": "970529157231000000000" + }, + "8e750010c88ba99d75b0b5943c716d6fc0d01802": { + "balance": "42271114987000000000" + }, + "8e889d47f3307a18490e53f2108dc31b14d6300e": { + "balance": "115722965933000000000" + }, + "8e9e1953c82217ba56365e7a9c54b1ded73914bd": { + "balance": "6248835752208000000000" + }, + "8ec980d3066cb6afa793577cf88ccb46ce8d13f2": { + "balance": "100000000000000000000000" + }, + "8ef324c861de7e042c445776bcc8ac026533bc15": { + "balance": "1869634994148000000000" + }, + "8efd14464465e50af087a80a5fbe652445de373d": { + "balance": "1157403424927000000000" + }, + "8f1b57304406fd8b2eb5dabcbd322e326dd873f5": { + "balance": "194188733254000000000" + }, + "8f36ffd921e12083e374335d3cc43fcfeeadfa46": { + "balance": "100000000000000000000000" + }, + "8f813b88e6e125eab71a63455f326322ef505501": { + "balance": "19087691927734000000000" + }, + "8f83892d4d2892cd57828fde2318610a54b14498": { + "balance": "22833507983000000000" + }, + "8f89c1bcba85757cf1718d5b9eb007e27e5195ab": { + "balance": "2241600478705000000000" + }, + "8f927ab63df4c2ce46f1ea35bc875a0c006d2d4f": { + "balance": "327487123409000000000" + }, + "8fc3c231df0f93a84bbe348aff12ab576284d70f": { + "balance": "25000000000000000000" + }, + "8ffa089b07ed1388a5d1a428daf54d9591e734e6": { + "balance": "1347580402248000000000" + }, + "90040e00f585f8be44c82597037fde452472e741": { + "balance": "2746884591879000000000" + }, + "9034eb46aad2a76bdb812c981565d4701dc10718": { + "balance": "10000000000000000000" + }, + "904ca1ac2381702bd18472b175262a8928cde5f1": { + "balance": "304421909590000000000" + }, + "90502c1123692c3b86e99b328d07fae473d4a283": { + "balance": "227491252462000000000" + }, + "9052ca7e9623c1bbe3568668673d6d252b56a764": { + "balance": "35268091378000000000" + }, + "9093d12d8410193293e1fda0cca98a43b85b91a8": { + "balance": "6829489147119000000000" + }, + "909ba8cdc707c12ba577dcd8ed1df1c02a7ce2ef": { + "balance": "60524108169000000000" + }, + "90a2cc3aa73495531691e027a8c02783cea7941d": { + "balance": "65263780625000000000" + }, + "90d7c82615f151953a8d71a68096cee4d428619c": { + "balance": "298774379499000000000" + }, + "90e02deb31d98b9c85fcaa7876eb5ec51d721dd4": { + "balance": "2000000000000000000" + }, + "90e538746bbfc6181514338a608181a3c4286d1d": { + "balance": "6069511690189000000000" + }, + "9106dddc1b693e7dcb85f1dc13563d6c7c9d8a6e": { + "balance": "1977000091291000000000" + }, + "910d1e0d3f71054835ee0d4cd87054dd7add3e38": { + "balance": "40104690362000000000" + }, + "912e2349b791fe702692a6c1ccbf6f0f06b826db": { + "balance": "6305336897000000000" + }, + "9144cc61c01eb819e654b46730620c230da9e936": { + "balance": "144000000000000000000" + }, + "91478d4c15d9ba02816456030915be08fa3aa208": { + "balance": "200078339107000000000" + }, + "9160c466b5f9020b0ab1c0ff497bf0345598ec90": { + "balance": "17705350930000000000" + }, + "919025625787101c572d8340ead1444a96593424": { + "balance": "2418027749789000000000" + }, + "91926323868c65f91b6d74c85c07279610651ede": { + "balance": "538073886450000000000" + }, + "91950cd6e2dd99e024854b65c09c5a7476777a21": { + "balance": "11629505934425000000000" + }, + "91ae8d74c26d3dcc291db208fc0783347fcc197f": { + "balance": "7604593786920000000000" + }, + "91b9ac26869abc9eb3090f1d8140eabe97f41001": { + "balance": "25000000000000000000" + }, + "91c349651afb604f9b00a08e097e02c0964e148a": { + "balance": "117290771022000000000" + }, + "91ddc95cadeb6dcf6ebbdb3300a29699ac8ded39": { + "balance": "20000000000000000000000" + }, + "91ebbd36714cc069f8ce46f3e0eda5504fdd3aa2": { + "balance": "203944728497000000000" + }, + "91f2765125b84923bd506a719d72b0c1de030e32": { + "balance": "452269960816000000000" + }, + "91f2e54a9d61ef52a33d150da50d5a8f2ebcd6bf": { + "balance": "242321058694000000000" + }, + "920dc90d11e087a0d8912c1d43db102e9ba4f43e": { + "balance": "20000000000000000000000" + }, + "922ff522cf7f3ce0bab9312132df51704caa755b": { + "balance": "1414824682473000000000" + }, + "9251449b0f757ef62f63c2774eb63ba15bf3712b": { + "balance": "102688517037000000000" + }, + "926255c17386720fdc1701747a2f024475063d4a": { + "balance": "25000000000000000000" + }, + "92808a38ffc5a339b1ab6b0b472f9975718d4a07": { + "balance": "500000000000000000000000" + }, + "9286c4497e820845341e3b9127813c1b7c884830": { + "balance": "101241387488275000000000" + }, + "9298e1df6730e91e9892d19f7ce18a3db9b5d2a1": { + "balance": "169000000000000000000" + }, + "92d98aed335c29402a43ba96c610251bed97308b": { + "balance": "3032350763000000000" + }, + "9319153f24814a81d920c60cbee9b5f2f275fac0": { + "balance": "56619610984000000000" + }, + "9347532d6396bc0b86bcd34eb80facd4c3690684": { + "balance": "258912194626000000000" + }, + "93487691d71e6248d88f06b1fbaee58b6fe34615": { + "balance": "1593901704394000000000" + }, + "9375154a7f19783b26ae1c9e48f114e1cfd1307a": { + "balance": "9000000000000000000" + }, + "9377947e0db688bb09c9ca3838ca2197fb262a1e": { + "balance": "323993393587000000000" + }, + "939ca9030b28d356dc1b071169f98b0728a9aef3": { + "balance": "218900305967000000000" + }, + "93b71636b8332515c2af031aac7a8805de716a62": { + "balance": "1640174743698000000000" + }, + "93bca153afd427b0c3c1de4a5584610e4a6595b7": { + "balance": "654782426410000000000" + }, + "93cb3b73fee80cedacf5197f8b4ac8f18f0d0184": { + "balance": "100000000000000000000" + }, + "940fcd215bab373d1b736e354f2def501244885a": { + "balance": "13133641534585000000000" + }, + "943f4bc76f20580b6546b6aff2800448f82cfdc0": { + "balance": "1927982550280000000000" + }, + "946ddb5c46fb13010b9c7ec56e4055b4f3e24b4a": { + "balance": "1410000000000000000" + }, + "947961dc367226f78d722361d5821cced52db01b": { + "balance": "115598797369000000000" + }, + "948eab3ffe44d5f1f381de2c8cadcb311c25df2a": { + "balance": "870664355820000000000" + }, + "94bf674593378243fb6b811f331f77561efb4106": { + "balance": "226539311455000000000" + }, + "94ce082887dd6324d7dcfa6cae17b653be021b25": { + "balance": "420000000000000000000" + }, + "94e2aaa4b5e2b36a12f866c96e3382a1150a97b4": { + "balance": "7344059136611000000000" + }, + "94ea5b1cdceb3f1a9d5ecacb6ac8dd2db9a461d7": { + "balance": "1951787237292000000000" + }, + "95218633176c0fe2f32fb55ad3df9f387e63aed1": { + "balance": "99999999580000000000000" + }, + "9543cb22853a46cce3aadc60e46cbddbd3fcf593": { + "balance": "2806074281914000000000" + }, + "958842c5389656d156aab05ac1731a20656716ff": { + "balance": "391064461038000000000" + }, + "958fd9bbc96531a00adc5c484d06dc61ccd717b6": { + "balance": "8021794447667000000000" + }, + "9593ce72919cb0648ddacc58af233d942963e2e6": { + "balance": "32322940730755000000000" + }, + "95a8e371af9128c97c9d4d7c4d58f5f75f2d07d4": { + "balance": "49000000000000000000" + }, + "95b9a9ad563a4c1ff7b6ebcf5fabcf5dbdb4a6a3": { + "balance": "10000000000000000000000" + }, + "95ef5fac6aa3ab1b4a87246fa800cfceff43dec7": { + "balance": "119666779022000000000" + }, + "961a3aa8015cd520de43bd47d81f5194ee4dfdc2": { + "balance": "248589901007000000000" + }, + "962bad39df25d64ee1c6b4ae9c14a18d316bfc06": { + "balance": "2404608291000000000" + }, + "96392119198c4b644c64284c9a75f61210a6292d": { + "balance": "1000000000000000000" + }, + "963c82319380587eeba0bd7b07eb63ea7042984b": { + "balance": "1480123630618000000000" + }, + "963e05fb6245ec11d67ed80e9feba6e2c0a8b4ae": { + "balance": "276053287417000000000" + }, + "964452b86b0d1d4b34aa881509a99e7b631d4a85": { + "balance": "64000000000000000000" + }, + "9644a2af2ff70eb43584a4351bfbe027c42ba3f9": { + "balance": "500000000000000000000000" + }, + "96572a017489450f2dfc0e31928576acd3bc6808": { + "balance": "1140183097730000000000" + }, + "9686bfcc0dc3de20604eb77787d0dba818cc5016": { + "balance": "10593448987804000000000" + }, + "96879780764b4433589d26573fc221f5218f1877": { + "balance": "154136576560000000000" + }, + "96ac1e62c95e33dbbd4f6ed389007e16c00b205e": { + "balance": "4130528000000000" + }, + "96ba703df3a8a6dc3c5d6be02cbf6a4afa2d1650": { + "balance": "2885298549532000000000" + }, + "96d516ded110f1d7e0290716689fd1b7964d9d42": { + "balance": "40665675241000000000" + }, + "96d75950c9354cec6084ba11058dd52d00fdb1f2": { + "balance": "903158106646000000000" + }, + "96f362c59c72fa1d39ae3ec37a7b715d2dd23679": { + "balance": "110000000000000000" + }, + "97115f7544cb05009b3fad2f0c2817f3ee77dd4d": { + "balance": "10000000000000000000000" + }, + "971cbaeafd4b0fdbad24fab946051b8949efaebf": { + "balance": "8462381628000000000" + }, + "971e195e980b4fd4db8d279c80968ca1bd390edd": { + "balance": "10000000000000000000" + }, + "9722648970c455929d621546fddbff27c49acd3c": { + "balance": "70337427969000000000" + }, + "9772027a4ea991eb9eb5ae6b8f34d750a917538b": { + "balance": "148918416138000000000" + }, + "97797e3919aa35567b9eb1224be87f96c6c2e1b4": { + "balance": "973342196399000000000" + }, + "9780a9c86160e27f627179535c3d3f23b6b29917": { + "balance": "10000000000000000000000" + }, + "97a85f4e3f53aa066825de15f1d0e25d4189b037": { + "balance": "2435764858719000000000" + }, + "97f46465e99910539bd3593c16a572e159bac87d": { + "balance": "25000000000000000000" + }, + "9882505fcb54ca2d2f4f79b03f0a5ead61936979": { + "balance": "249999580000000000000" + }, + "9898e969629502a891b758efecc9fdc5ada7d32c": { + "balance": "20000000000000000000000" + }, + "98a52d325e28ca9b4474846c7e4c07a223440fab": { + "balance": "418260286015000000000" + }, + "98a9b2f7d1ba7838e3242b5e4cbf1f2897aa4bc5": { + "balance": "500000000000000000000000" + }, + "98b8308c37a2f6cc1bb382dba2ba95a3c5ca2834": { + "balance": "10000000000000000000000" + }, + "98bf0170a61f98ab0710a68810bf152b7f6c56fd": { + "balance": "2279761566089000000000" + }, + "98c8a323a0022bd147a466fa1ac867977e12eb92": { + "balance": "10000000000000000000000" + }, + "98cd102caf0866ba0a74604b01f54049503905d6": { + "balance": "34739921273310000000000" + }, + "98d7e89c2765aaac224d4015aa277fef208953c3": { + "balance": "1291811952000000000" + }, + "98fe96bfd1e10fb60b343e512b15e955aefc0778": { + "balance": "464922897623000000000" + }, + "99064a57d693e45559a1a910c9ef7d46cce0e703": { + "balance": "8969733492948000000000" + }, + "991ea5429b91a8bfc4352a1d93304dc463be5b90": { + "balance": "149367286734000000000" + }, + "9921d405fada890fee6bf76acc39141fd34e5d2b": { + "balance": "5021308706457000000000" + }, + "9938d357d3d5dcc6f6fc7fb47a98405c0ab6830e": { + "balance": "516293591974000000000" + }, + "994f4e6521a3a5752359308b9f6b2722922c60b1": { + "balance": "23993133615000000000" + }, + "995a6a1c38f037b3a9f0a2e915b8fc0efdea082a": { + "balance": "1403498530728000000000" + }, + "99709e57748a7da6556b1670ba4f15c45aef4689": { + "balance": "36000000000000000000" + }, + "99789f65655c6f917d575169f4ba8192440e659a": { + "balance": "393071814319000000000" + }, + "998f66cbde2693603fa109ad7aaa8bc42a8765a9": { + "balance": "49000000000000000000" + }, + "99afd42a58af31daa54ad9ba35b06954330107ba": { + "balance": "25000000000000000000" + }, + "99b6a9ff2b2ac9ac0361af007aba107695ff5fad": { + "balance": "12860157225353000000000" + }, + "99d16a5955d43723ed8e2b1a642f8f1195f38b64": { + "balance": "62907829047000000000" + }, + "99df609926ca536ed3be80e35dbaecc42ae67f2f": { + "balance": "316809833612000000000" + }, + "99f3faf97a36fabea7306979b30b08fa70110e29": { + "balance": "173292373556000000000" + }, + "9a26110067b473e3bdc0fc32951b39596c967a56": { + "balance": "78192198764000000000" + }, + "9a3a8eff6fb82377da6c17ba658dca87ca0dfe26": { + "balance": "50000000000000000000000" + }, + "9a3b06257088ef8c17410a8f2d63392edb9b55ce": { + "balance": "239567000000000" + }, + "9a426842301802866cca0ef89794d928d3e8f843": { + "balance": "776173297821000000000" + }, + "9a5f2c0a6d41131d9aacdb4f8c274958cbdd377e": { + "balance": "441954000000000000000" + }, + "9a6893023ac6f34b493d33e4dc63ef697169a58d": { + "balance": "439689418527000000000" + }, + "9a86eefd848acafcbd9960003e90b22162b15ef9": { + "balance": "294190908093575000000000" + }, + "9aa711f3e4eb67d2f6405b5ee6290a014d203a72": { + "balance": "9101556549634000000000" + }, + "9abf9ccf6abb8d55ede458d2d12a279d0a823944": { + "balance": "17609693072000000000" + }, + "9ac1909b983c754f0800559174025c0f0baa9d31": { + "balance": "80921948093000000000" + }, + "9ad62cd855d629e1ddab632874a6dc2b812f2348": { + "balance": "2068118534000000000" + }, + "9afc2c33aa2c9a42600abb18aedaefa433326122": { + "balance": "2485353229354000000000" + }, + "9b18d230b221a99c74877d4a1dbdee2214c7d60c": { + "balance": "4024172228743000000000" + }, + "9b18e27788c9d59053072032a480569e142595a0": { + "balance": "110789164888000000000" + }, + "9b4535b23af0b8e5f488a6f318ff6badf71d16c1": { + "balance": "84756740661000000000" + }, + "9b5e7cf43aece7b38ea2af6d08bebe2d3b926840": { + "balance": "262771268227000000000" + }, + "9b77dac92fedd0ad3eb4326d4fafe0f4315a8844": { + "balance": "3616321626000000000" + }, + "9b8f6f223641f9b1bab319dd1e88c49fd411a765": { + "balance": "2054417462086000000000" + }, + "9b9f94861d80365464912e5c7213403405a6cd8d": { + "balance": "2367093088000000000" + }, + "9ba24397002929e6239848596b67b18a8dea1eef": { + "balance": "5000000000000000000" + }, + "9ba99736c5ac468d6b644e39b8d515c39151f51d": { + "balance": "311900650761999999999" + }, + "9bf2d4ff366e1bb2313ae9a93ccca75d6bc0d232": { + "balance": "764870206925000000000" + }, + "9bfce7dbfc9ae62d450e862261d1e21e68bac92c": { + "balance": "1000000000000000000000" + }, + "9c003e74b62f192a864045d678639580c672fc22": { + "balance": "50000000000000000000000" + }, + "9c128bd2c0c96b896db6c0f398e908c98302809e": { + "balance": "3251059363800000000000" + }, + "9c255daa89ee16f32fc0ab1ed8e22db39342e6ca": { + "balance": "37695843594589000000000" + }, + "9c32e714bcb601a56a8a4e6b3f7bcd9e1c7a1b54": { + "balance": "50000000000000000000" + }, + "9c503e087b04a540ed87056c9371d591afa72df2": { + "balance": "64229084991000000000" + }, + "9c54297dd3527cbbb8ca8c305291b89bfb7ab39d": { + "balance": "61682466962052000000000" + }, + "9c55bb1db3b2bb06e605a66ced9ea2ac95718205": { + "balance": "16512365324000000000" + }, + "9c59dbc48b9cf53fe668784e89d30493da9995b3": { + "balance": "50000000000000000000000" + }, + "9c61b58aa760265f7fd1b9e749df70122ea81175": { + "balance": "50590272373000000000" + }, + "9c6c7eaf4bec0566a7bf8acd30e10311a963267c": { + "balance": "999999999580000000000000" + }, + "9c91dd4006f9d01d8caf5f5fb4f2c4f35ee63ffc": { + "balance": "175730980227000000000" + }, + "9c99275f5dee14b426302b1a47a8488c16432f2b": { + "balance": "2000000000000000000" + }, + "9ccf7b23528d062da63f6af3e26531b775c83c52": { + "balance": "928373869120000000000" + }, + "9cd21c30ccbc1087c9b351395fdea17ad669cc2e": { + "balance": "529762292313000000000" + }, + "9cfee47d6f24880af7b281cc00e1fc58e0a4a718": { + "balance": "198888257958000000000" + }, + "9d08251f7d4cfd66d15c17e1ea6bae5c795e290b": { + "balance": "813841349140000000000" + }, + "9d5411490ce89359bfbacf9f9957ebfbbc18debb": { + "balance": "22263187467000000000" + }, + "9d61e1dfaa7d0e0c5f5d733a24a1883c4e201f3d": { + "balance": "144000000000000000000" + }, + "9d754d94a15ab6d738e511fe4c775ee6d20a53ee": { + "balance": "20000000000000000000000" + }, + "9daccedf104fdcc3c39f2961ddfa1c64eb632476": { + "balance": "1237093270947000000000" + }, + "9dad4968c0e44aa729fc5732f3ee903c6799637b": { + "balance": "838788687517000000000" + }, + "9db73ca677bacbb622f44fe90b53ee1d9f0c2009": { + "balance": "472858335000000000" + }, + "9dbcb5026e0f444a33197da240856f108db14ff0": { + "balance": "10000000000000000000000" + }, + "9dc46cf729187ceed8001c4ab14fa4fc21c35f32": { + "balance": "3320792646995000000000" + }, + "9dd895c1bdac2ed9864134aaa8c543473ee5f19b": { + "balance": "1430620966869000000000" + }, + "9de2687242cbf9fb94fee0ad873acc7494ebd2bf": { + "balance": "20000000000000000000000" + }, + "9deec036282717aac93ad5cc1b6d4a5354e85c2e": { + "balance": "2048627955362000000000" + }, + "9df8dc66395aeae9b4c831b4d63bdf48db08811a": { + "balance": "215874670561486000000000" + }, + "9e1fe68a70abd8ab517878b03961da8564b43eb5": { + "balance": "67908329894526000000000" + }, + "9e33293006982abc668e199aab20260b9b754463": { + "balance": "49000000000000000000" + }, + "9e65616282a0baf89469a58915fd8fdbed210e3f": { + "balance": "829209872657000000000" + }, + "9e7b7b522834dd7e83ff2bb6b6e4cd2972330899": { + "balance": "500000000000000000000000" + }, + "9ed134b3a8feccb4056b2e511cea9a8ec58a3e77": { + "balance": "18787546978390000000000" + }, + "9edcf477687a9dee79341ed5d89d576c9a854c2d": { + "balance": "500449025554000000000" + }, + "9eeb06d4b532118afa013a01c9e89216fe0475ae": { + "balance": "1823939486758000000000" + }, + "9ef20a338e85044922f08f3648355e834874d551": { + "balance": "50000000000000000000000" + }, + "9f0855f9cc429fd3590c6ad05bb66a9e038efdca": { + "balance": "8017999878252000000000" + }, + "9f3befcc1884d16b65ae429228d26fffc146c8dc": { + "balance": "1016482445089000000000" + }, + "9f4571748463eee19e59ff9bd734a62a66613850": { + "balance": "20000000000000000000000" + }, + "9f51de282745f77b8e531e1de0b7c14e3369ba54": { + "balance": "1010657089383000000000" + }, + "9f6527175a2b581cc79f2a68c35202e0a7f2af20": { + "balance": "216495522463000000000" + }, + "9f70204d1194f539c042a8b0f9a88b0a03bbcd8b": { + "balance": "10000000000000000000000" + }, + "9f70e44704049633110ecd444f9540e241b50783": { + "balance": "9139000000000000" + }, + "9f73fea741e8506ba7acb477745dab1cfab8366e": { + "balance": "4461472359634000000000" + }, + "9f88d33d26c90e74c39c9676b8b580d21bbad124": { + "balance": "54437240781000000000" + }, + "9fa47455be14ad2eecce495281ed0eea926ec6a6": { + "balance": "10000000000000000000000" + }, + "9fbb15b595d154754a2ae77c77283db9d4e9f27b": { + "balance": "6195722646556000000000" + }, + "9fc480ab1823a59fd6130c3948980f95ac99f1d2": { + "balance": "24101151540000000000" + }, + "9fe5f054165fbf1943b1b02c01063f04e0c3890b": { + "balance": "1000000000000000000" + }, + "9fe7d3d5976e7b8b5ad6baa15ceae96c43c60fea": { + "balance": "55000000000000000000000000" + }, + "9ff116ea0e219814970cf0030932f5ce2cd9a56f": { + "balance": "36000000000000000000" + }, + "a01f6c36193839bc3a31e6d0792324771040fc05": { + "balance": "48298750000000000000" + }, + "a0264706d668522b737bbdbe949ce3e5a60fe314": { + "balance": "1423066922869000000000" + }, + "a02b13bb3b13027045ffb9b44bc7380a942e8ebb": { + "balance": "86845430807181000000000" + }, + "a03d246a931c3d422e5d2bf90f64975923a93643": { + "balance": "5834171660287000000000" + }, + "a046caaee59425ea1040867c62a6fcda11652a23": { + "balance": "83087966538000000000" + }, + "a04b57b2dd8b2082c53517d956f5909d25e14b69": { + "balance": "4518538234851000000000" + }, + "a074ef9e0ffe15619103e3de490f5813be53dcbb": { + "balance": "4568113810000000000" + }, + "a07bae42b44c085067de16e7d9846db529059acf": { + "balance": "4000000000000000000" + }, + "a08530e5fb7e569102b2c226aa5e53dc74483e4e": { + "balance": "2325665286793000000000" + }, + "a095a2c666f4f3203a2714fb04867c13c2add4be": { + "balance": "14768043990000000000" + }, + "a0a967418a3fcb3ee3827a08efa851347c528a60": { + "balance": "20000000000000000000000" + }, + "a0bb293071e07418ecb2fefc073136569ebd1736": { + "balance": "25871128320000000000" + }, + "a0c6c220a53b7dc790f7a5b462a106245c761f70": { + "balance": "1000000000000000000000000" + }, + "a0f06c86c49b248f4835bff405b620d12ec80d07": { + "balance": "484572382390000000000" + }, + "a10bc9f4d05678b26c4ffd2d92ab358163020b61": { + "balance": "10000000000000000000000" + }, + "a10c1197f7bc96639d01a652df73e49c669165dc": { + "balance": "1205859101575000000000" + }, + "a1221b2001f85f71e0655551e300ce115284b8dd": { + "balance": "1376698025177000000000" + }, + "a13fce836d65124fe5bcfa2d817ab2a043acbcf8": { + "balance": "55000000000000000000000000" + }, + "a15f1f609f7464906e0eb9d5e1d26468b90d9198": { + "balance": "16000000000000000000" + }, + "a1617dcf3acda60737e5ca9e4d0ecd82a98ef667": { + "balance": "500000000000000000000000" + }, + "a165c5f151d0daab905ba4a6d1fe5d5114fd7686": { + "balance": "41039049526000000000" + }, + "a17d5bed36c1059561e184a8a90a38ce955b92e4": { + "balance": "10000000000000000000000" + }, + "a18efb4e0950e7ac95970cd4591dacc286241246": { + "balance": "12403188476000000000" + }, + "a191fa6be64f2f6d2b4a7fb5a586416a605552c6": { + "balance": "60340281461000000000" + }, + "a194c15518cefbe94edbef3a2421586b51f7e1f6": { + "balance": "4153525550636000000000" + }, + "a1d0e41aacf83fc62fbecf35f8e873f8d734ecaf": { + "balance": "9000000000000000000" + }, + "a1ddd1f615ed483ef895e341f3266b6891f9b59c": { + "balance": "180411786335000000000" + }, + "a1f4d1e03114707a56ef9069bc20c6094e810d34": { + "balance": "51949145435222000000000" + }, + "a1fe101a65616cd03e3af03092be63434b7bf203": { + "balance": "1005401878265000000000" + }, + "a25a8225ce67c54048737601eac5e0d063c2fa17": { + "balance": "272038848571000000000" + }, + "a2714999233bcaff7294fa3e3b64c63ad45a928b": { + "balance": "14560781294000000000" + }, + "a28db3f7fb1771a3d77dfb19b54f88fd55b15c8c": { + "balance": "8000940572576000000000" + }, + "a290101bfe5fbc73146c4ec3ab5266c043eb701c": { + "balance": "1397563244603000000000" + }, + "a2924cfbcd37d0b321d6abbe57c645f9ce32340e": { + "balance": "200000000000000000" + }, + "a2a26c34f3d950c795fc965f6b1df3990e111403": { + "balance": "34525064429023000000000" + }, + "a2a2855851711bfc051c1f298821ae89e4c872c5": { + "balance": "491025000000000" + }, + "a2b956dd6f1934a4a44a026a18ac345ddabe42d5": { + "balance": "20096625821563000000000" + }, + "a2b9a118a79be81711d95485aa12e3efe78ca256": { + "balance": "10451051632647000000000" + }, + "a2bcf08ddd1778b30ea7882518148edfba2d9b20": { + "balance": "347033754668000000000" + }, + "a2bd489ec4790f4145f8a9a95c9c829c5c020146": { + "balance": "100311110878000000000" + }, + "a2ee35300ddf6a2491ec0e1848f8b56defafd7fe": { + "balance": "500000000000000000000000" + }, + "a31adf082ffd212df18d5a84b105a937e83b1b1a": { + "balance": "7124891785000000000" + }, + "a32c944e6c5fe186794b88d6bcbf51c47bea55ab": { + "balance": "732129357042000000000" + }, + "a33105d543f5d2b1220d4e1ecfdcf85699324dad": { + "balance": "74798779358000000000" + }, + "a3330c73e2d79355a14e570da1ec2e80f8048c69": { + "balance": "10000000000000000000000" + }, + "a3580034590e3052b9de5abd635e514ec5ba8694": { + "balance": "10000000000000000000000" + }, + "a360d8e2519dc6d7793cc371d91ad6add75e3314": { + "balance": "192622260840000000000" + }, + "a36b9b8b2adb20fb4a84d3025bf2e35baa8b7fef": { + "balance": "20000000000000000000000" + }, + "a3771b191237bef48339aa77ad5357f6227b358c": { + "balance": "512633055119000000000" + }, + "a3892bfd25705387cfb4eeb6d21089753c22e3e2": { + "balance": "258136912825000000000" + }, + "a38c793775ebfc7330b4331fe2dc848abb862b73": { + "balance": "1193250172232000000000" + }, + "a39417002ab94845541aded4a614a5a04af8187b": { + "balance": "1185722898000000000" + }, + "a3a79a9f929b54075de43689adb665ef914812ca": { + "balance": "100000000000000000000" + }, + "a3b59ea3d366f818ca09980846ac533d4685c121": { + "balance": "59734700360000000000" + }, + "a3c7b7c594a64225922e02039669e4d0b43fc458": { + "balance": "11779233750000000000" + }, + "a3cc39a68184e51f6445d3ba681a55f4157d4383": { + "balance": "10000000000000000000" + }, + "a3d414d9f210f7b77f90790ce09f6128abe50adc": { + "balance": "10000000000000000000000" + }, + "a3dfda16e5ae534ac100f56741b77b6f86786615": { + "balance": "9000000000000000000" + }, + "a3f79b9d1fc9d6dbaaef49d48fa9c9fb5a822536": { + "balance": "108910000000000000000" + }, + "a3f87414bc9e6f01c2fbde966fc8fb6edbf58c29": { + "balance": "441000000000000000000" + }, + "a3fa3f58c802d9a9690de760716275f14449045a": { + "balance": "437227558095000000000" + }, + "a417ec5a9749064a6521ca2bf9d05f208eeaed54": { + "balance": "959205202638000000000" + }, + "a484d5b883d2b99b81b7bef27e307957ecb64b15": { + "balance": "126491152120000000000" + }, + "a488cd48258e57d66f44e73a60c121f963cb29f5": { + "balance": "20000000000000000000000" + }, + "a488e3b5096e964b21cdeba12ab423f391765b6d": { + "balance": "1712050478592000000000" + }, + "a49dba65f28909e9bd2ce5675bd091f498c6c5db": { + "balance": "216802821062000000000" + }, + "a49eb6a791022c1324facc23d8813f9954d1c639": { + "balance": "287438914902000000000" + }, + "a4cc080a5c4649f511b5844a8e0b031927e13a87": { + "balance": "20333578449000000000" + }, + "a4d2624ac5e027f72edaa625ef22134217203b5d": { + "balance": "1000000000000000000" + }, + "a4d30e35c9617eafeda82866c96c3ce6bf14400e": { + "balance": "1223254927978000000000" + }, + "a4deae7355bd2e1d57eefa56600601b8b475a501": { + "balance": "36000000000000000000" + }, + "a4ff3b5abfe4e50adad16d01aaf62c3d4cdb5260": { + "balance": "20000000000000000000000" + }, + "a502b109869ef07451576bf0e13ab294e1f236b9": { + "balance": "94843398055000000000" + }, + "a517a3b5e4324197902e16f8a29e47335cf39c11": { + "balance": "100000000000000000000" + }, + "a51e101088da23c82907e3e2c65a058f0454b131": { + "balance": "196000000000000000000" + }, + "a52bcff6a7e2e70cd714058bc30a16138fe39899": { + "balance": "30429750204000000000" + }, + "a544e84c2bc4b17859d06f136b6e377e4e398b22": { + "balance": "143977568178000000000" + }, + "a54ddacbc17a98b9fb6292aab3d92f4c5753fd0a": { + "balance": "100583192014000000000" + }, + "a557754f6637a19c1a48cb9bf58c1fe897acf434": { + "balance": "2087038692036000000000" + }, + "a56649205d9ea247b49e03dacbed6c78c21beb4a": { + "balance": "5046177099585000000000" + }, + "a568136446ee6b3bf62a20238db3b11397a065f2": { + "balance": "11652249158033000000000" + }, + "a56a7865b526e315a9eb41f4847485c7e0c952fd": { + "balance": "50000000000000000000000" + }, + "a56bab2a9aac9d08a7bc9265864a80089b68570d": { + "balance": "37138466291329000000000" + }, + "a5965a601c5df7765cd70e5dad27dd23da67ac99": { + "balance": "10000000000000000" + }, + "a5a3161c44c34c441784b7df795067760b0ee569": { + "balance": "35053289069000000000" + }, + "a5c245cf843e691956007b94e259b437a4e6b7e3": { + "balance": "18749166170000000000" + }, + "a5d7de961c3b991dc78f2d6c0448fa6225116d3f": { + "balance": "1574510758868000000000" + }, + "a5f47d2081ef728808786128549a28a5662e92a8": { + "balance": "1750000000000000000" + }, + "a610c90f5b7e5f33044956ba431a3887de1c969f": { + "balance": "25000000000000000000" + }, + "a61c1919bc3f3181dc94e2230d35574cfc972d78": { + "balance": "8990565120000000000" + }, + "a62f1aabd91cbc0112e796d1ec3727fcd26fa293": { + "balance": "1311277302001000000000" + }, + "a64fff0bb32e32f81a541c393982bc59fa183b1e": { + "balance": "8291357610655000000000" + }, + "a673dae555d367b8d4a784274577a1884615b9d9": { + "balance": "27416452091330000000000" + }, + "a6c780b585355d84d9d3c13be5bd05374588e240": { + "balance": "913657165911000000000" + }, + "a6cc1f6f51862c2798adaa1d266988022005a71a": { + "balance": "284500645805000000000" + }, + "a6d9c82784fa20dcf28266d047db441cfeb8855b": { + "balance": "10000000000000000000000" + }, + "a6dae08f99e4fb57b066a645a259d8e4f7ac2bc8": { + "balance": "9044922773690000000000" + }, + "a6f49f36f8d10a796bc2afc9e069cb0c76004ddd": { + "balance": "128555691078000000000" + }, + "a721ce1c294a0f1957ebf9be20b0fffcf90111ad": { + "balance": "3392103457630000000000" + }, + "a72b82c33bd3d6060e8a04392d236775d48ec3ae": { + "balance": "1434465940701000000000" + }, + "a7344654f2a1a44b3774e236f130dff8a4721e82": { + "balance": "100000000000000000000000" + }, + "a748cced92a87066db8b29f931fb92e827488a9e": { + "balance": "5487679824758000000000" + }, + "a78dcb2bcbec2d0a60661e1715c9a95c9d573a68": { + "balance": "346798292989000000000" + }, + "a7a6c0505e7090e0b2c21394877f91c50be6b45f": { + "balance": "4125233658872000000000" + }, + "a7dcdd9b9785a44a2dd4c5eeeb863ac1feae0f66": { + "balance": "10000000000000000000000" + }, + "a8013e9dca1bd38975748de2fb6cb3af5cae74d9": { + "balance": "10000000000000000000000" + }, + "a807bf78b15c15cd9e8edcf586849db716fedbb1": { + "balance": "1458293606310000000000" + }, + "a83410ff00fb4b913dd0ea2003b38c5c3247350a": { + "balance": "2876442029807000000000" + }, + "a848f61298a409e77a03900712017572f35a3319": { + "balance": "2783106133600000000000" + }, + "a85bb81d0dc57f824a763814759fd93fe3020569": { + "balance": "4558027813744000000000" + }, + "a860611cd098ce98974313030d9f6f462bb274d4": { + "balance": "961594154368000000000" + }, + "a8799eeff72929ee6cbfb5b0c02985cd4841be3c": { + "balance": "500000000000000000000000" + }, + "a8c29b9b1349fac0be9a65873e1911b7439c9a63": { + "balance": "1264035560749000000000" + }, + "a8c321024a3c015d881efca33bd1b2c1788b379e": { + "balance": "528752788000000000" + }, + "a8d02e8925ed48f4274d8bee62253dc0d4f2989c": { + "balance": "209083880937000000000" + }, + "a8d2bde2ccd6bad67ee1b9550c9310accb37cd79": { + "balance": "49000000000000000000" + }, + "a8d61abc6a403adc183aeb74c83e4221fd28ee1e": { + "balance": "50000000000000000000" + }, + "a8eb6aa5a0c5b6d9260a202dc76ab674d9a5f3b9": { + "balance": "1041257515142000000000" + }, + "a8efc57efc776dcaaf4003a8cfa63f215ab0284d": { + "balance": "166144142685000000000" + }, + "a8faba86d87678294e311cfa7f8cbeb6f9d8a499": { + "balance": "124541781000000000" + }, + "a912e02f8eab0cb620316129875f919455201117": { + "balance": "6454482105955000000000" + }, + "a929ac95281d1a77a3eda3b5ac90a761ef03ff16": { + "balance": "1074305309650000000000" + }, + "a92a4e40519003813f5574397ce328d046f75802": { + "balance": "9188437500000000000" + }, + "a93850ba8fff3bd18ab259f87c58bbce84165fff": { + "balance": "39018890852058000000000" + }, + "a9843660a17c2d972246028cb8045472abdd346d": { + "balance": "1052681604185000000000" + }, + "a9866c6271733971e46df3c9bb27b3d3c513c166": { + "balance": "200000000000000000000" + }, + "a9b1299c0c064e766f9f29f4301a78c6e4931fcd": { + "balance": "267785134400000000000" + }, + "a9bc33b9c99dd5a3967387c1e99766f9bc74d591": { + "balance": "65356157048000000000" + }, + "a9ccf1cd2f816b15182997e3207d9a681bf21b06": { + "balance": "17521053440000000000" + }, + "a9e54bd9826f853f65e0be1ec0bb9c28f95e0eea": { + "balance": "6260000000000000000000" + }, + "a9ef563c872342f49817a903a5725b504d455ea9": { + "balance": "50134015139000000000000" + }, + "aa0d69c7e1382cd16c527a3fee48db19c38e1398": { + "balance": "142562301500000000000" + }, + "aa12abcc3ab373d07bf560fd200652c8580fd967": { + "balance": "5509242259903000000000" + }, + "aa1d6b968b3f8046a94f128864bfc612fc2e2700": { + "balance": "489179780895000000000" + }, + "aa20b8559d6dd1543e8c528775ae4b04c6242471": { + "balance": "169000000000000000000" + }, + "aa227e9d6074a60ecd43e1cc24092ee58560374c": { + "balance": "596190898010000000000" + }, + "aa7b660fec7b05968ba656eae9a8aaef4481720e": { + "balance": "674642002744000000000" + }, + "aa9e04077d44d288978a3a3ab0d7c251c0447a4c": { + "balance": "10000000000000000000000" + }, + "aaaac1e72955e9d67625cf8bed73fa643fb1cc1a": { + "balance": "9781187987000000000" + }, + "aab46c0c2db4e330834081f97678906252746f97": { + "balance": "16440184245000000000" + }, + "aade5358c52b8aa5ad8ff285c6b297e86f49fa0f": { + "balance": "982846000000000" + }, + "aaedb3fa2cf0ebca0ef4a121a28a406264ccc900": { + "balance": "100000000000000000000000" + }, + "aaf30bf76362a03450aefaf5bd68d28b84eb4962": { + "balance": "509106199370000000000" + }, + "aafbaaa6b6369e986ba72b196bd5f08cc458e344": { + "balance": "216372214000000000" + }, + "abb03c888d61c9102827a1dc0950145beb9d96b3": { + "balance": "144000000000000000000" + }, + "abc6dc937d7703a6b0c83659a328cde0d5008e32": { + "balance": "4052429106341000000000" + }, + "abd3910139a97cb92dc09a8a0352575bcc9ebed3": { + "balance": "24028359215749000000000" + }, + "abdc3953ef293c98989802063f8cb55e0e506432": { + "balance": "64000000000000000000" + }, + "abf1a47c582bc87d36e47cfce24e0ad249f42e73": { + "balance": "71947491720909000000000" + }, + "ac0b6e7aadfb5ffafd5cb3ef3620ebb0691cc3fe": { + "balance": "10000000000000000000000" + }, + "ac1a182607046b56e7a4bbab87cc1182874f79ef": { + "balance": "453499500178000000000" + }, + "ac251b311f781ad7a43d01b0b4b20fe891004e7e": { + "balance": "304621378298000000000" + }, + "ac258cec5ef49f96612d659f66dd4e6ea88e3c87": { + "balance": "255185373455000000000" + }, + "ac4000d9ad080740ef4a2ebe4a3075877bea277e": { + "balance": "10000000000000000000000" + }, + "ac7445c09372f15259fd852cc458783d6140c0db": { + "balance": "10000000000000000000000" + }, + "ac8d29dc05ea6c2f5409a76abe04321bf9381f32": { + "balance": "22464474197854000000000" + }, + "accd52b63822d8cb5117d9deb56596e072462614": { + "balance": "20000000000000000000000" + }, + "ace63a86a2ddfc79f677344e93dc0c4750b8fdcf": { + "balance": "1355066360964000000000" + }, + "ace83deb83fa8d319979658592b75ed13bdf97c7": { + "balance": "20000000000000000000000" + }, + "acf91515df16b21f1e5f5474dbefe596e4929b96": { + "balance": "1153047238967000000000" + }, + "ad04381f7ba89220e8fcd7e200f98a476683a904": { + "balance": "2000000000000000000" + }, + "ad22225bf225d8f705f93bdcda8d301180ea28dd": { + "balance": "1272512717188000000000" + }, + "ad3f74034ff5ca89f97b2585edf12376820307ab": { + "balance": "12303261515593000000000" + }, + "ad43a3527ad2b9445417cb73cbcb42965a5f469c": { + "balance": "67607364133000000000" + }, + "ad61cf9bf560bd5da75d55738477bd9aa25fb0b8": { + "balance": "4358939446693000000000" + }, + "ad649e8a3e1436e0604b0b8c9b1a5f1c09e06d7c": { + "balance": "344000000000000000000" + }, + "ad6b584813814db4c72c4c7eb31447d224074b46": { + "balance": "18445595367000000000" + }, + "ad7d404afc67c0e457fd3ce142cd30b506408683": { + "balance": "48218702840000000000" + }, + "adaf4d39b6806d132128ac438c2862c0a1650cff": { + "balance": "500000000000000000000000" + }, + "adda124baed2e1fdc1acc7b4a048eab0cd249212": { + "balance": "1074765673925000000000" + }, + "adef437c429d90a350b99750d4b72bc8538c5f98": { + "balance": "931901903135000000000" + }, + "adf826a0ea7dc4322d26e9d8c54c4180c1827216": { + "balance": "323567723315099000000000" + }, + "ae01d8b1668f8bfe6e225bd9bc746f7e839ac0d8": { + "balance": "321211880744000000000" + }, + "ae17de3ae6127022e53ebcf9e08457174cdee0e9": { + "balance": "3817903000000000" + }, + "ae243b0186793eddc6ebbb1a2c1f0b1cd574b07c": { + "balance": "9000000000000000000" + }, + "ae3ae1d41dfb16e19a1817b3639cd4300fd166c1": { + "balance": "55437674845679000000000" + }, + "ae506999882d4c6f05cc7979c342c0ce559a8df0": { + "balance": "1391755905401000000000" + }, + "ae524cee5aa23025d6ad185ccab75a6974335d53": { + "balance": "797132751509000000000" + }, + "ae5a55075d0541f179b085152bfc8c72c74abe23": { + "balance": "589408139567000000000" + }, + "ae63d02b18b464f0bbab4de943766bdc7ba2926d": { + "balance": "300261019201000000000" + }, + "aed8ffb86a49c09ae3a83e93d9045851434a9f0c": { + "balance": "1031991707237000000000" + }, + "aee18a9a2ccdf6025d61005827753ce4f510f7e8": { + "balance": "1818639022863000000000" + }, + "aee67910c514fa63a228769d5e15ca40bc4b26c2": { + "balance": "5688989238568000000000" + }, + "aef744eb2ec682dca128dc3149afcf881e367121": { + "balance": "818801643225000000000" + }, + "af04430b3e40e746127623532353a0f177a88fe3": { + "balance": "100000000000000000000000" + }, + "af181833edb15c9b2ee2329dcf1845b977361b7d": { + "balance": "93228805338000000000" + }, + "af30db29765b4fda6f075af96e8acd5046b099c4": { + "balance": "1000000000000000000" + }, + "af31fd30cfb10f1b0a12c2e7dd7ca56bdf517745": { + "balance": "36000000000000000000" + }, + "af70d6820e1d26194b0a9965b55254a287b162f3": { + "balance": "87593999609754000000000" + }, + "af96a573fa86c07389a71db797bea689419b23ca": { + "balance": "36000000000000000000" + }, + "afa4c5b674934e31a9aa5e3e723d85060d51c4d0": { + "balance": "10000000000000000000000" + }, + "afa6e4b4060c2e5969c2329d13cc42924412efde": { + "balance": "127502378589556000000000" + }, + "aff2308ac607f85392f4c8a6a043af67b7b849cd": { + "balance": "11130371831000000000" + }, + "b00ea9c459105b650def1e8569c85fa01837454d": { + "balance": "94928352162000000000" + }, + "b02a7d16ea8663c88416e6f64eaf57787d230be3": { + "balance": "17215604601000000000" + }, + "b03f4e9aa5c352cb1cec953d1123c2f22cd94b5b": { + "balance": "206022552274000000000" + }, + "b051459b91d253c5e8251a5a68282c291833466a": { + "balance": "297127749975000000000" + }, + "b055bdc874ca5a7d2f4bcbc51f1cfc3671b55f72": { + "balance": "1421913523478000000000" + }, + "b06156b99b891b756262c5b40db9bbe39fddc77f": { + "balance": "49000000000000000000" + }, + "b076893b9841d2775ec8883f05b74f1e5aec327c": { + "balance": "22591055478000000000" + }, + "b095de644af3c9f960f67502da6ac5eb050a158e": { + "balance": "4958067562725000000000" + }, + "b0a1f794cf70422395f74395abc9a7d0b271846c": { + "balance": "812057322000000000" + }, + "b0d36e0f426a99416425689c657fc6d64ad698ca": { + "balance": "1157727077158000000000" + }, + "b0f35fa554d6ed657bf3996cc027d045c3971fcc": { + "balance": "64000000000000000000" + }, + "b0f76b4c9afdfe35c41d588265642da60f1b97d1": { + "balance": "1000000000000000000000000" + }, + "b0f76b4c9afdfe35c41d588265b42da60f1b97d1": { + "balance": "2028311808491377000000000" + }, + "b1445842d56c56bc532d2f33ab9b93509c732a3b": { + "balance": "13522982470164000000000" + }, + "b156bafe05973bc839c4f115be847bbde8a67cb1": { + "balance": "10000000000000000000000" + }, + "b182e4d318893dc1c4c585195dbde52a84ed4ffd": { + "balance": "329498977335000000000" + }, + "b18f506e77df4db80ca57cefeaca4f1010f78f50": { + "balance": "956339304078000000000" + }, + "b1b6f617b110dd79c8fd77e729584d1fdfa9aa09": { + "balance": "16000000000000000000" + }, + "b1bba36e2d9e272e0131f4bae09bcfd92e0a63db": { + "balance": "64000000000000000000" + }, + "b2285651e57ae0ff27c619207cceacd20884d152": { + "balance": "1345938295122000000000" + }, + "b2419a93732d0d324daf7707fac3782a77b0dff8": { + "balance": "625000000000000000000" + }, + "b27206e9f2ac430841fb8da69b49d505f1558b8b": { + "balance": "29507819229000000000" + }, + "b2801fe902c7bbc987ba12ecae98765c99980fef": { + "balance": "240016083000000000" + }, + "b2843d5215ceb761e78f281402a1660c3abadf5b": { + "balance": "3335539720927000000000" + }, + "b2a22e6a04a2ce3287da3b8b6eed4ea1f18f05dd": { + "balance": "99999978999999999999" + }, + "b2d55a061fc6f90d2a05e0cbd26ffe0a1c3321c2": { + "balance": "1000000000000000000" + }, + "b326aec1cd523948ffec2fd1e8f21bd2b4308f40": { + "balance": "913000000000000000" + }, + "b32abc82b251e2d310ea7588cae4ad4acb657cd9": { + "balance": "26946233911000000000" + }, + "b36924d578973aec05ce7ab556d7ed00004949ca": { + "balance": "393041705867000000000" + }, + "b37482114c83e857c730588d7d959d300b8142da": { + "balance": "29429544454000000000" + }, + "b39998bade135ac6ccadff41cd709e161d01aa60": { + "balance": "26272579375000000000" + }, + "b3a995ee94f1d63d12f10cea5ab3d596c7c6f284": { + "balance": "64000000000000000000" + }, + "b3bf35e936fdbb7d0bbeeb1cf076f243855ed477": { + "balance": "754081187934000000000" + }, + "b3c2ac85b99abed4a2a52b5f96a2c98040d16022": { + "balance": "50000000000000000000000" + }, + "b3d1a2c0ab2d8987446d74f49e357adf5bf15986": { + "balance": "10000000000000000000000" + }, + "b3fbcd24c8394a5d2b7fe877f18681a109a404e5": { + "balance": "2558689648423000000000" + }, + "b4110f4e38405adfc054e55ff73c55842db8e2cd": { + "balance": "129000000000000000000" + }, + "b417f4681fdd4e53cfdf8550e3d326dbb0a557ec": { + "balance": "1000000000000000000" + }, + "b422970fb8799d83642b7ff715fc941d69e86053": { + "balance": "81000000000000000000" + }, + "b4237be71920497715826eae8d85c26cb3c111a8": { + "balance": "10499979000000000000" + }, + "b431839de4b21dfb44150cfc6ed00ea430a81687": { + "balance": "26839560174813000000000" + }, + "b43a0d6399c7d1be943c4b45838156a47c88f909": { + "balance": "10000000000000000000" + }, + "b44ec608b95d0d51105ce5f4b48de5dd72f346fd": { + "balance": "448125120000000000" + }, + "b47f63e14f6de6c3413b2be95a725e367ac18fb6": { + "balance": "500000000000000000000000" + }, + "b48071cd1b15f45028e9dec2237f14f10b7aedf9": { + "balance": "38042711385000000000" + }, + "b4b874b323b560aa0e4811ca574bd48b65b3fc72": { + "balance": "18063913676592000000000" + }, + "b4e4d4af0667f8158cf817bf1bc3eada08a551ca": { + "balance": "2149067370317000000000" + }, + "b4ecd625ffe470ee1fa1d97832e42ddf3f9ddf6a": { + "balance": "1181738860120000000000" + }, + "b53f380ce92787c1db461524290e8fcede552fe7": { + "balance": "12640674931821000000000" + }, + "b547e04ab8a44d3cae38704356f1f59408457b67": { + "balance": "286604155735000000000" + }, + "b562e4010a0a5fd0906a4cd9f47fc28f6f51e210": { + "balance": "1000000000000000000000000" + }, + "b584de7b38a2a2e3d9ff9c055b309ca56e5da5a9": { + "balance": "237896887904000000000" + }, + "b5c1129961c4a43673324aaedb8296f5ade82516": { + "balance": "4213058948283000000000" + }, + "b5da6711c72bf27c87923aed4a39349b4192e6b4": { + "balance": "55180742586465000000000" + }, + "b5eac5e7e03b9d31e40393e16e956cd588cb7566": { + "balance": "4508019435556000000000" + }, + "b5fd46ee4e02946dca3485439f98bdab290c82b7": { + "balance": "108321600045000000000" + }, + "b5ff2a3caef6ec30365f4f0ecbecbdeec1cacbba": { + "balance": "979696597242000000000" + }, + "b609d05242f7c13a4ae4036f6da9c0bae18dd70c": { + "balance": "229121731278000000000" + }, + "b611156a2f87fb45c431a5cf5740ded90c2dc542": { + "balance": "401783365700000000000" + }, + "b61c7623144afbd0f6cf44c951e4219ef8096119": { + "balance": "36000000000000000000" + }, + "b61cbe0e58ff6fa4c810ad03c759c79d9ff052a5": { + "balance": "1034495371371000000000" + }, + "b622bb67e95a03f58dc9aecf82c217e86f2cf7c3": { + "balance": "500000000000000000000000" + }, + "b62a50be3ce0e7cf8f61991daf8fa7e23775141e": { + "balance": "1000000000000000000" + }, + "b63cbff6b1747ad5cda101d5f919ce81dd67e363": { + "balance": "2570089937000000000000" + }, + "b65e80551a8687c9cef2d852949177c0e3b56e51": { + "balance": "100000000000000000000" + }, + "b68126ebbcb5ab9b0371b62597a38d5c1685b0df": { + "balance": "671140851028000000000" + }, + "b69f5830c371cad5a74ae823eb8892d153ef3c23": { + "balance": "18446744063709551616" + }, + "b6b4468c4db64e0b85cddc251d02f32fffcd1f7c": { + "balance": "10308006217291000000000" + }, + "b6c129312505e571148dbe69833d30550efc12c9": { + "balance": "5105834767567000000000" + }, + "b6cee8ef00b8674a9a96447e4511b30d6564ff67": { + "balance": "667754569888000000000" + }, + "b70f805aeba260d44f0730f0a9dec60f2b4f54a1": { + "balance": "2751303297000000000" + }, + "b71a901dc4b6c6463f7d221f868677bcadbcc680": { + "balance": "169000000000000000000" + }, + "b7385bd8f8257331f4c7a87c7a23724f615cff8e": { + "balance": "196000000000000000000" + }, + "b755692bc027e30730dc1d0e0b2a883830a84115": { + "balance": "30713083153428000000000" + }, + "b765305dda3c1e069a7a022ec127ff2140d0a820": { + "balance": "603122990932000000000" + }, + "b77403a4c56ffc7715b4bfdfe4b054336aeca466": { + "balance": "130840969728386000000000" + }, + "b78b2f6dc731d7d84b7eea151805f9208a1d0cf0": { + "balance": "142084687500000000000" + }, + "b792a0fd762c002a7585cfdefd36cf7ffb42fc05": { + "balance": "10000000000000000000000" + }, + "b7ccd7164aa7fb871726d9d043a8f8f890068c0f": { + "balance": "1170997140237000000000" + }, + "b801f49018317caf30f310dbe116f4e876184874": { + "balance": "50000000000000000000000" + }, + "b81ca2bc63cb4008cebdda3ce8f4eaba322efca6": { + "balance": "4678481047354000000000" + }, + "b82e3d50bf8c5b471c525ec8dd37b06688ed6178": { + "balance": "1202448975553000000000" + }, + "b841162a7a8876296f10794d8847d8095426aa54": { + "balance": "73500210754000000000" + }, + "b8421d375c3f954e22b6fd304235dd7c43b68bd0": { + "balance": "6499782706009000000000" + }, + "b859b76d77eb604728093c61fcabe6f9d22433b0": { + "balance": "196000000000000000000" + }, + "b86536268ace9be93a1db2012d6e3e59023ef2cb": { + "balance": "52878034904067000000000" + }, + "b87e1ac4fc423ab37e10ffd221df8056537b1d03": { + "balance": "119159824674000000000" + }, + "b8825a99806c5a968423e69d22f2b61a2f0ae9e4": { + "balance": "999999999580000000000000" + }, + "b8835acaf63e0e5d41fb743eb0f954040a38d381": { + "balance": "64000000000000000000" + }, + "b8844c74b227781d4b3fafd32e39ff6fa9857f77": { + "balance": "490694157000000000" + }, + "b8962e8bcbcf0f69144f8fcd2ec3ae8e54c05034": { + "balance": "1425313342735000000000" + }, + "b898b4ece8e0eea375f6eb85615652cc5c221593": { + "balance": "2284038029169000000000" + }, + "b8a949bfd9751c29c4cd547cca2e584d8dac4e12": { + "balance": "50000000000000000000000" + }, + "b8ad5ce2ae781e2d245919c15bbbc992185e5ada": { + "balance": "733786526623000000000" + }, + "b8cb6a9bc5a52b9cfce26869e627b2af0ff5ed4a": { + "balance": "98364826821577000000000" + }, + "b8cf6aac7b9028649f0d55a57b61640d70cef120": { + "balance": "104799890645000000000" + }, + "b8e827b5d1e10a3944039adb1a3dd7ff6949145c": { + "balance": "172413427060000000000" + }, + "b8f6d7f33ee5755ba56647ab8fc9ca27b8aba677": { + "balance": "1430769696978000000000" + }, + "b9221177e2b09725bc95f08c72c17c42887eea62": { + "balance": "1212779749827000000000" + }, + "b936e0d83cde9bb810b85ad58eb5ff0fa9c11654": { + "balance": "4999580000000000000" + }, + "b961d435c457e205fdbed5442c8614ecfd59616c": { + "balance": "27847452621284000000000" + }, + "b969e9d89f32002cd4f90ef5907bebbbdca6fe6a": { + "balance": "12455448454838000000000" + }, + "b981c9137cfca5389f0123927852278d2d7ff618": { + "balance": "92180707865000000000" + }, + "b98abf0fe91b0d3a16c6ed37aea446baea33fd23": { + "balance": "560454425563614000000000" + }, + "b99ab4e6ae277b9fb04537adbb781e8390b490ad": { + "balance": "32814665223319000000000" + }, + "b99d0a433d7994743dd675894c18ed03164436e1": { + "balance": "16000000000000000000" + }, + "b9d8b6f0a505d217709bb9327f3b9b3f84813e00": { + "balance": "81000000000000000000" + }, + "b9dbd64e3c8e6ad84c9c67c66e678c06ea7bcb91": { + "balance": "1161140466507000000000" + }, + "ba361f7a6dff16a96f957c63e08267dec8f9ecf7": { + "balance": "2170060167590000000000" + }, + "ba47f4136f74b566f62ba373651332b59e74e1db": { + "balance": "906249296535000000000" + }, + "ba5287cf15de91daeaea2465da4d4c1a14dea716": { + "balance": "98978398162000000000" + }, + "ba77d056d52f84e740579aa527792f826591c858": { + "balance": "50000000000000000000000" + }, + "ba895406774ced5fd2e759b58f9ffaed5e04fb14": { + "balance": "10000000000000000000000" + }, + "ba96fab21a4926fd1137558ae996b52ec14538a6": { + "balance": "10000000000000000000000" + }, + "baacc247801eddbf152fd6ec39d659f265935743": { + "balance": "2661902597584000000000" + }, + "bab2eb9fab8e699a958699b15ddc7ada5428d33a": { + "balance": "27006404153000000000" + }, + "babeacd7933c817472875c86bf126e6d11886f8c": { + "balance": "2461234517292000000000" + }, + "baf7021d4d754d4478d3c3624c2376e3f1d4ee5e": { + "balance": "1352066301857000000000" + }, + "bb0760bd1da973d8f70dd0caa6cadfcfd8199231": { + "balance": "177674700430000000000" + }, + "bb278c6a52eebd0b8950e9b78ba211453ccb1b6a": { + "balance": "25000000000000000000" + }, + "bb327e5f260b2dfe25fb180c2d3f4b63211c1dee": { + "balance": "7694972715000000000" + }, + "bb643e768ab20c135e7df3f400284cf04c40a6f7": { + "balance": "385756449779000000000" + }, + "bb73d1d1c289b4953d0033b52d9d2d0d92573d22": { + "balance": "11000000000000000000" + }, + "bb89936d562b19e4c599826ce7cd0c60cb02b512": { + "balance": "725910446589000000000" + }, + "bbc509b7999b0e94534477b98ec8927cba879677": { + "balance": "20000000000000000000000" + }, + "bbcfa9ab62f4eab14d6a1b09c1aa554dae113183": { + "balance": "589417352665000000000" + }, + "bbe78301134249b52b74d73ee3855e7e3d288a40": { + "balance": "4456159000000000" + }, + "bbe7bb4c4f1b506b58f7e3334e6c89011cf2d6a7": { + "balance": "3889127030000000000" + }, + "bc016690596e077273465d1728d18553b185654c": { + "balance": "185932953686000000000" + }, + "bc16b2ab9c7ab309249f93b496b75c6a7392cb10": { + "balance": "5000000000000000000" + }, + "bc254e5405b154b98abb5fe5508d3e7c98663f4e": { + "balance": "144000000000000000000" + }, + "bc258aeb0f18150d3ca253c6bb04f63d657d99ac": { + "balance": "6011905701701000000000" + }, + "bc2620b5ebac12a88b287b625fa5b336568e7869": { + "balance": "534886892259000000000" + }, + "bc318687cfaae2be4c5ece4a18bb9252486a19d0": { + "balance": "147226513970000000000" + }, + "bc32dd123fcc2ef0dc36484c3ab1bae5d9890761": { + "balance": "16000000000000000000" + }, + "bc5c5151be06aaf6180bc9c1058b181a5a30366e": { + "balance": "113865120384000000000" + }, + "bc66241ca430dc31a3e2f44dedba868e16b9a6a1": { + "balance": "50000000000000000000000" + }, + "bc7c371af0688b1c409f4b07662609a1c9efd120": { + "balance": "20000000000000000000000" + }, + "bc9454f7efc86e25d18a8e8b6e230de42a51d967": { + "balance": "148103676062000000000" + }, + "bc9d5456b975bf0b95c161c3355e4ceb28898fd9": { + "balance": "28083912047000000000" + }, + "bce0b47bf13e4517c53bbbe6e51544b99f3147f6": { + "balance": "919711480389000000000" + }, + "bce2d1ec7c41b426f72b352f5f2b7da3edac4157": { + "balance": "908085365725000000000" + }, + "bcf0756789a57f16206dd78bf6e1322ba9b9b85b": { + "balance": "110888224252000000000" + }, + "bd0bc4a0730f9f55a2f65f62662c7553db52238e": { + "balance": "8440290043000000000" + }, + "bd29fda37c2581a3f040c77eead3143cff24a346": { + "balance": "126022762542000000000" + }, + "bd4c1270322a26a1b825040b239008a447c31918": { + "balance": "727012140904000000000" + }, + "bd6a3da2db66dc9fa26fa2b63b14003d26ef91d0": { + "balance": "5492112771780000000000" + }, + "bd80fcccac60078fcf09f5bddd8a25a92fb9cfdf": { + "balance": "10000000000000000000" + }, + "bd92dc94b6e81a3da5dc3ae6bd80782622658196": { + "balance": "10000000000000000000000" + }, + "bdb35c2c595fe7a2864ebe20dd56d6ddaf9d447c": { + "balance": "4346566125000000000" + }, + "bded4718cbad2150c9b6df9ee7356e0f5c713cea": { + "balance": "311694803600000000000" + }, + "be1804630ecd95ac411b935566cecc5a24c6f18a": { + "balance": "85033246331000000000" + }, + "be2318ad50b0a85b95870a81dce5c31029636159": { + "balance": "5185298019030000000000" + }, + "be3de52fc1119f02f4707f353c040b7c4222d847": { + "balance": "25267399461000000000" + }, + "be4feae01d429c872601ae84dfae8fddc3372686": { + "balance": "20000000000000000000000" + }, + "be7c09d704d16e4b2c9e19cc8c07808bb335f926": { + "balance": "25000000000000000000" + }, + "be873a9525899bdad5e4376b0115950e534dea2f": { + "balance": "404116929377000000000" + }, + "be891b1680ad835aab1ac05a30c0813306cf20f2": { + "balance": "144000000000000000000" + }, + "be8ed2d85a5e3f83c6105db1a1f304e9f174bfce": { + "balance": "50000000000000000000" + }, + "beb1cd80c2f8fabc27ee3a3b2a15e35fa52e7879": { + "balance": "11539095431000000000" + }, + "beb67375e46950830906bf281209be133075452f": { + "balance": "1305262446956000000000" + }, + "bebe54437722c6000bc6a8843f159538a2abf613": { + "balance": "41042548942568000000000" + }, + "bef2a05e283ae948efa9b0e3a6ab5d26a57f1de0": { + "balance": "180614450853000000000" + }, + "bf03950f265a4182b4402703723a0311158eef4f": { + "balance": "158997402149000000000" + }, + "bf06393654baa1ad15c2e717e06dbaa61834c214": { + "balance": "34409427774000000000" + }, + "bf2b867313a44bd04aceaa644771d1e95317c881": { + "balance": "10000000000000000000000" + }, + "bf350ccad91a2a2aff4cf27a291323a297a78009": { + "balance": "124593326152000000000" + }, + "bf3d86edfcf52733e91a9c59be606a95bd921885": { + "balance": "20000000000000000000000" + }, + "bf5b21d5e339752b33b180064d0e6047338650a5": { + "balance": "1000000000000000000" + }, + "bf64c2715db8f353600a45b9264e1f22a40ef8c1": { + "balance": "2952972677360000000000" + }, + "bfaff32c8b04a61658ff94f94e4687232b8d2d7a": { + "balance": "1117691379350000000000" + }, + "bfb00182321502e0729d9a0862ec1df1b3e2208e": { + "balance": "500000000000000000000000" + }, + "bfcdfc9f60610f0ca279ca2c89b9af831332aece": { + "balance": "1431082635308000000000" + }, + "bfe14356e86f6b2ad470bc77d250517c8dc03d15": { + "balance": "310115085185000000000" + }, + "c008bd3fb881da9dca4cadcc56b1d99c56db9abd": { + "balance": "12899598792000000000" + }, + "c01efea456d30360a78ee10c790d46bcb889ee61": { + "balance": "103203021492000000000" + }, + "c03d622627bba7d5db1a9f699924e9d5ff5640f2": { + "balance": "95102233308870000000000" + }, + "c0465ed806ce7ee730e5b6eb7b86a754bfd196a9": { + "balance": "1654379359619000000000" + }, + "c061c5b0d0ce7af95ded1805abb23f743e13c455": { + "balance": "500000000000000000000000" + }, + "c074f2024f79cf8d7aab2d858dd110fc2ee89d41": { + "balance": "18382732686000000000" + }, + "c085147a76d0336b4bd6e7d5b60d394bfd3c6f42": { + "balance": "3236912707535000000000" + }, + "c089416d2d679cb2abf44251de227d0a08fa1206": { + "balance": "497124416350000000000" + }, + "c09d8cfd85989397dc723f2df821dbfb2c0c39b3": { + "balance": "833485701262000000000" + }, + "c0aaf130e3b67250d9775d62e7cd3963daf0a627": { + "balance": "1249947125780000000000" + }, + "c0aebdb5c2e8c5ff9870535c738bfe892c9365dd": { + "balance": "360097616959000000000" + }, + "c0db5680ba88052652bfd5a617c4e8a5be188077": { + "balance": "509051625766000000000" + }, + "c0ee350e5e09a2daeff332a66a6e117fad102112": { + "balance": "10000000000000000000000" + }, + "c12c0a3fd42501f8772e4ad5d262eef3f0bc4701": { + "balance": "120398848512531000000000" + }, + "c135b48c7fd11670bbfba923b28767d21d7923ea": { + "balance": "20000000000000000000" + }, + "c1397c66b7f150c0062b0e87c981c107d771b109": { + "balance": "87751498250000000000" + }, + "c1507ee435cf506fc5d8e4cb62515f2ea0f3a7ae": { + "balance": "4935384099000000000" + }, + "c150d185e2cf203054a6e328b72d8c35bfbbcc33": { + "balance": "21044148271000000000" + }, + "c163098f8b8f0736862274860b3842cf14bd2288": { + "balance": "119025568966000000000" + }, + "c1687fbbc7d504b73fe3e71af440b3dec0da88b2": { + "balance": "229520711528000000000" + }, + "c172bf224080d448261b3b66453074b28628daf7": { + "balance": "7903438287958000000000" + }, + "c18e9bc05dfee2a39fe2b6778a24a48d5bf0f141": { + "balance": "500000000000000000000000" + }, + "c198fec4069c95300d34b9c7109d7441b8e62745": { + "balance": "50000000000000000" + }, + "c1b4134f4757d19a687d05bd7087872b5625405f": { + "balance": "20000000000000000000000" + }, + "c1b43ca2af534ac6bcad8f23c30c07ba07e7e8fb": { + "balance": "194999622000000000000" + }, + "c1c2249507d2dcaf4a9103fcea2cfb47aa4957f7": { + "balance": "571416394325000000000" + }, + "c1e90af40fb64427aeb79a13607debbae9270b52": { + "balance": "50000000000000000000" + }, + "c1ffc8938f3412d19d428b8450f17fd394ae539a": { + "balance": "36000000000000000000" + }, + "c20013e25ae53d0d41bf365aa767822bbbe70936": { + "balance": "10000000000000000000000" + }, + "c20e9eadffa5529ce58a39f5898f39906dcd4b78": { + "balance": "757301065305000000000" + }, + "c211fc2623d51846d26952628d140643efa5156c": { + "balance": "865384323985000000000" + }, + "c2546c312570b30ad2ed05edb13b6469494c5b92": { + "balance": "5000000000000000000" + }, + "c25b2280ed0f835538f8ffd9dfc08a3b853f1ccf": { + "balance": "1000000000000000000" + }, + "c260e43b89a7a4e84bcc4c21dc43d4b5e6923f3a": { + "balance": "1000000000000000000" + }, + "c26aeef0e1f382c88bbdb1eb8c01afa7f58218ce": { + "balance": "79774757760000000000" + }, + "c27dd2645254bc30b6cf7bf418803b02ac808b5e": { + "balance": "4419594173874000000000" + }, + "c2b4f6cf92d6d63a20034e409a358df1803159b8": { + "balance": "1630820442000000000" + }, + "c2ba4a7ea6ca2d17231fb17ebd5dd2dfc0964de4": { + "balance": "221662324727000000000" + }, + "c2bc18f24b8097208a8b2418c444ea58beb94281": { + "balance": "1766754009521000000000" + }, + "c2c028dd17f8a89b9131b7daaeae9cb1dddf86e7": { + "balance": "10000000000000000000000" + }, + "c2ed78a0cb850c12ce8e6ff3873e8c18ffc9f4b9": { + "balance": "1017518755567000000000" + }, + "c2fd7296210b7013d476205d2517d51b21c9e76c": { + "balance": "500000000000000000000000" + }, + "c3041d3d650ff6ac3e35b60371b6798360727651": { + "balance": "1011071365226000000000" + }, + "c328ab9ce1fddd5623e0383828714a7e3ff12eff": { + "balance": "285042661579000000000" + }, + "c34ab008ddddf376dd866cccae4a4d6eb88403e2": { + "balance": "2798642711076000000000" + }, + "c3511391c4515cf8f27e9bc0f777a02a4125c8b1": { + "balance": "20000000000000000000000" + }, + "c36916a9fdf656bb1a8c2f7fb752a3489020f6ff": { + "balance": "689483152953000000000" + }, + "c37598a388d6f4e8e046923265ee9256456e40ab": { + "balance": "62865106394696000000000" + }, + "c38813db256eb221a7142d042b81ba2babab2c31": { + "balance": "98477603778000000000" + }, + "c3acd30f0bc3146fc2cab8d54904f98289021374": { + "balance": "17820000000000000000" + }, + "c3ede34dc1cd995fda1c5cb6e9ffd0c0da080587": { + "balance": "1080428143758000000000" + }, + "c3f04dffe2be55a1d6cdaa78e5c09a79d0477e7b": { + "balance": "59747493842929000000000" + }, + "c3f09f681cfb57d3cabc547dc32a71d2a6585c1a": { + "balance": "1757648436173000000000" + }, + "c3f3bb6444d853614f18c04a3c81f7d26e62e96a": { + "balance": "9022830778000000000" + }, + "c3fe4534327a2fc4144e2d3d3392f7b78d2aabc5": { + "balance": "1759225739027000000000" + }, + "c424f5be9490ec7f0f1e2debc3f72bd83e35f587": { + "balance": "1774372626989000000000" + }, + "c434f64eb937207f80e9a02d2f77ca34bfc63aa2": { + "balance": "960850858644000000000" + }, + "c438b6fa5801a4b8dea450530d975f174cdd47ef": { + "balance": "64000000000000000000" + }, + "c446effb984ff3e5ed92280e7b3dcdb1284230b3": { + "balance": "503490303680000000000" + }, + "c453ae9f94253ebdb871e9dac19056b13d1747a3": { + "balance": "1621494076559000000000" + }, + "c4a473b5e3a6bfb51f963d4dcf109bddedf4fb43": { + "balance": "104273242373000000000" + }, + "c4b8058e9e5416e526ea16e37f29dc221d28a003": { + "balance": "1833513486496000000000" + }, + "c4c09f4bbae0ee06f2a52ff0ef0de1978b5305e9": { + "balance": "20000000000000000000000" + }, + "c4c5981f5ac0a9a3701663b887c4aaac3a3a4d1d": { + "balance": "1411640000000000" + }, + "c4f7a493d16aab4d18e88e530e75e3095a3439ee": { + "balance": "191606419322000000000" + }, + "c5259c18bbd8b0485ca83d069d5ac235b28f24ea": { + "balance": "1276479076242000000000" + }, + "c526ef1124c7d0549b117e7b7463539a24209290": { + "balance": "9106523141000000000" + }, + "c5278b9eeff2221604f30f002c307ca2882fba97": { + "balance": "20875716591000000000" + }, + "c527ca73562846de9fca1649fe5144e5068a2f6e": { + "balance": "25000000000000000000" + }, + "c52a960c5df55169ed5d5cb0109a576321ab82fa": { + "balance": "1097338876493000000000" + }, + "c533ab799e5a04e0ba4e4780d632e0044262d216": { + "balance": "200529941482000000000" + }, + "c5389e3ee2f043ac2b6481f254440a97a9cf3bdb": { + "balance": "84047554571000000000" + }, + "c5594292b324c1d63f797c588a589c895c680ed0": { + "balance": "334298857161000000000" + }, + "c55d7ae4f29d857182d5f1ac2a78cbf35a694dc2": { + "balance": "500000000000000000000000" + }, + "c55ead0ece8fcfbecc573666c0170228e089aefb": { + "balance": "438775082956000000000" + }, + "c55f7d73491cdba391b631581029de32755a09b8": { + "balance": "1340000000000000000" + }, + "c56cb4e8308d6462eded0bbc74965ee135e23e11": { + "balance": "568187503785000000000" + }, + "c5b0c5f840f579536d5977a77262458d72ef1490": { + "balance": "5880686297881000000000" + }, + "c5b129c764daac8bfbf023646b9306d817a8ebdd": { + "balance": "10000000000000000000000" + }, + "c5bba43db949e2ed3de3036caf7a6e42558b1ef2": { + "balance": "763947031151000000000" + }, + "c5d57171e5b9cbafaba7d2c13cca3ec9d81bda49": { + "balance": "25000000000000000000" + }, + "c604e6c539c857ae9e60ca20d1906308ba431892": { + "balance": "100000000000000000000" + }, + "c607bdc5ad2f189e9356edb4d7975c7ba9300836": { + "balance": "55828814399000000000" + }, + "c60b0d2341ecada6c3faf1efcc9027125d99e17a": { + "balance": "121000000000000000000" + }, + "c61e1b993c3fd91a1023ba5b92d06a0aa539d92c": { + "balance": "23863993763643000000000" + }, + "c624656ee5298786cb3d0de045b0ac089c5341d6": { + "balance": "2210389938000000000" + }, + "c6573a023d6f4b5e151f266af4ec0045df0d1518": { + "balance": "52505006485983000000000" + }, + "c66b1d84c42018b16dbc4777409bf50a49febba9": { + "balance": "9078953000000000" + }, + "c69e4de93457f251b1e0879b5250b26e57839fec": { + "balance": "500000000000000000000000" + }, + "c6c51205c9f0bcaea05dce8e47e91d94a3f63c2a": { + "balance": "2720612321571000000000" + }, + "c6d237e0936c4714e701823aadb368fdc471451d": { + "balance": "541700595551000000000" + }, + "c6dcac15739872089cb3d23287e8cd546487ecf2": { + "balance": "1023857245227000000000" + }, + "c6f40b81a5860dece34305f53570be61cdf9a8fa": { + "balance": "20000000000000000000000" + }, + "c7147a95cc4f6bedce6292e8f95539caf550e9d6": { + "balance": "20000000000000000000000" + }, + "c7185b1a680d8b0893065d8213de54375d086420": { + "balance": "11564622085000000000" + }, + "c71b3876613c928197aadf3dd7888db3665f28f0": { + "balance": "112276274428000000000" + }, + "c72200bb380db62a3fd741713d332be77bc1a4ed": { + "balance": "6962060809000000000" + }, + "c7345cd5a7eafc9d7ebdc17d674f83e23336538c": { + "balance": "4425703195684000000000" + }, + "c734f9dc3ee2d857ac826b101129eb77a4a22256": { + "balance": "100000000000000000000" + }, + "c736fa9550b73f4a4ca0ac1cd94bf6f42ccbb11b": { + "balance": "449139000000000000" + }, + "c74128ea37f5d1ee016086a38e470bb332eb5270": { + "balance": "40479951869000000000" + }, + "c7647ec91e823cfe57e8a3433ddafd7b4f675b80": { + "balance": "307102062000000000000" + }, + "c76d49334ce25f5fc62841e5a87d4e03ab3edd9f": { + "balance": "109999979000000000000" + }, + "c771093ed5c4df518536b76e013e8142ecc3f9ed": { + "balance": "5247752820195000000000" + }, + "c780dfb4cdcba4dc89245a8be8a93de1a3e82d3c": { + "balance": "205580199482642000000000" + }, + "c79c6c3a0a46052f723a26b1f107a332474df3a1": { + "balance": "50370325181000000000" + }, + "c7a4e02d2c0f00fa56662cc9f323cabeff82759f": { + "balance": "1163435680762000000000" + }, + "c7c0632cff11812130c30163c83746839a625f95": { + "balance": "10000000000000000000000" + }, + "c82238664bedfa8ded51e91969a39f13a8262a37": { + "balance": "10000000000000000000000" + }, + "c877d228c350ec0d8d97802e7d874d3130171813": { + "balance": "199845203467946000000000" + }, + "c88b8a2e498fee366a1290a575a7f09da12ea8b2": { + "balance": "50895598476000000000" + }, + "c8bbd0e52b11ae6a20adc5f6bbe4d34d7440e8ca": { + "balance": "114566193776000000000" + }, + "c8ca2bd1bef02b505f0333996bcb6bf730648390": { + "balance": "1177250974576000000000" + }, + "c92c3358910418fdb3950e1a378af7246553ae38": { + "balance": "81000000000000000000" + }, + "c9325c9b6d2af226bc5ae1cc975e00cc11274cd1": { + "balance": "2927587698197000000000" + }, + "c95ae8dbc8bb075e7dcb2b2c6d9411bedf26244e": { + "balance": "931878010706000000000" + }, + "c98fc33c1d980052d75fee8b34d08796734b6a4d": { + "balance": "8671327034000000000" + }, + "c99fba8321d16cb19c55703b407c54ed106dcdc4": { + "balance": "20000000000000000000000" + }, + "c9a0da2a3be799e751738e61b9cc376eb06e2b00": { + "balance": "50000000000000000000000" + }, + "c9afc551058c32e89bc2d6704d0d00e92f5ef6d7": { + "balance": "11135553563900000000000" + }, + "c9bfa2ad4b3e9c624255c6ede116421b04487d65": { + "balance": "105514983171000000000" + }, + "c9e4b61d8ddeee339e31ba088efb5d608c3464a5": { + "balance": "20000000000000000000000" + }, + "c9e9090d9f95f401c87c7240f3bf88ca9b540f8b": { + "balance": "553735838243000000000" + }, + "c9fd40bb35284e3d7f0dd3b43a1d9e958f7c86e0": { + "balance": "50480449695128000000000" + }, + "ca038c7c9e66531ad79e4d67b42d7920b7f05c26": { + "balance": "64000000000000000000" + }, + "ca0d08f6019884f94f2b5b191ac9bb247150cd13": { + "balance": "25078089364984000000000" + }, + "ca2c6e6ed3d6a1d030807f91e1fd5c79d36af86f": { + "balance": "849454139892000000000" + }, + "ca7c7bbc24cac0f3aabfdccc77df21004672e634": { + "balance": "6952718700000000000" + }, + "ca998c74383b55c8dcddd46b49f95456fb056b7a": { + "balance": "2000000000000000000000" + }, + "caa989e6a1e934532aaae6cad282c18b1a0b9fd6": { + "balance": "2335540529729000000000" + }, + "cab32ee5cce74e0ee88bbd4b505aa587ef2e4bbf": { + "balance": "75914058971000000000" + }, + "cabe9f0d0a18de8d3495dd063b04c6a33584a8c1": { + "balance": "116083536145000000000" + }, + "cacde94daeafc06e46c86b1e20387a23d909ace8": { + "balance": "1521003430346000000000" + }, + "cafbad01b81ad6cc401883773994a9dd6e6ed913": { + "balance": "10000000000000000000" + }, + "cb343b882cfe866f73cd5f0f31fc68cebaddd882": { + "balance": "221801563082000000000" + }, + "cb3a7aa2e97517b6ea8d9ed0ac270a6a9cc6e079": { + "balance": "958830201738000000000" + }, + "cbd2c4916211ab2c234bc8a51e6f680b59aff782": { + "balance": "24279462419000000000" + }, + "cbea4ed5e8d2ffad442e482fa5f8d551ef2a58e6": { + "balance": "26730000000000000000" + }, + "cc001ce4f4417505116486bed9fdf04bf97ca246": { + "balance": "31740534557000000000" + }, + "cc0b53b26b6dee9f8226f25b834085bde13f5eb5": { + "balance": "132440104515963000000000" + }, + "cc174862456f02f349303d1b8328495de8ccd789": { + "balance": "155951512603000000000" + }, + "cc2af3921727d6d2de31d5f656f837a5475de6cf": { + "balance": "10000000000000000000000" + }, + "cc3201749f55f0d7b450110bc11f65b1ce165d2a": { + "balance": "123428947550000000000" + }, + "cc3f37ad6b449e39c544e26bbdf4d7be66b9dab0": { + "balance": "348574664284000000000" + }, + "cc5b36c9ecea12ebfd0721a58ac11b0c340a3f44": { + "balance": "384197170701000000000" + }, + "cc5b410c7797faa05ac4233eb31b468ee4bf279f": { + "balance": "10000000000000000" + }, + "cc60b223554cc6425374c5e2424df7007621368a": { + "balance": "1128118098000000000" + }, + "cc7027381d98c2e883c82bb9c2f85b985e1e7b4c": { + "balance": "1370000000000000000000" + }, + "cca378f16e07258b9c15921233110fb4729645d2": { + "balance": "151974946930000000000" + }, + "cca781d996c3ef985bf7d2b4d68d55f52efe1905": { + "balance": "2217463190039000000000" + }, + "ccd0b9f6ffb0383553c355c6a14be1200966d47d": { + "balance": "12917165349191000000000" + }, + "ccfa4594129bbb9d07cb4ae8dc2b1c8f3bf98508": { + "balance": "524845286088000000000" + }, + "cd19c879df458106d179bbb5b7f44609d68e6e5f": { + "balance": "8601633489844000000000" + }, + "cd1c55037a0570e8f9aaa95ef157ae81a1969250": { + "balance": "10000000000000000000" + }, + "cd1e47695b0fc93b82cffd0326852dc04d8441f0": { + "balance": "144000000000000000000" + }, + "cd1f90c388d76b3aeaf77850f2191f12a2311f51": { + "balance": "1728456799866000000000" + }, + "cd3aecd58de07f80b64044875fa6ad4f18f72789": { + "balance": "2648597880142000000000" + }, + "cd4f39123ece1e0ab52cfa2a5d059b49c4d63c3f": { + "balance": "1661718859439000000000" + }, + "cd6ed2f7ab49515f8fd70aeb4d72bfae8956b5f1": { + "balance": "183807926254000000000" + }, + "cd9d9d07fcf476a8ee7240324a602449606d75f4": { + "balance": "100000000000000000000000" + }, + "cda66d375a10a22f13dff8a9c40b63461daddab3": { + "balance": "1116940051064000000000" + }, + "cdb0832ee5b26da24b1775c4cf0dfd669b94ce00": { + "balance": "23919219542965000000000" + }, + "cdba5805f17df1f3e47647464de978944ed36b62": { + "balance": "4204539000000000" + }, + "cdd1df8bd54941e26ea26eebbd537e751f64f5f7": { + "balance": "5000000000000000000000" + }, + "cddf5b34342200c37ba96eb0dd662ca4c29f89f8": { + "balance": "10000000000000000000000" + }, + "cdf6c838980afd91a600e3fff755a4848d138568": { + "balance": "25000000000000000000" + }, + "cdf7f55a5a16572d2f2bbf7faeffe3c4d64f86ab": { + "balance": "3115969322502000000000" + }, + "ce0f1dbbfa3490a21ee4b28232db612f44bb7bf1": { + "balance": "9227310122000000000" + }, + "ce33184573c33dd859450304984fa63ea4f2b62d": { + "balance": "7055925237496000000000" + }, + "ce33a3db107f01c51d30b24a8db80faf05308bb7": { + "balance": "10996113113089000000000" + }, + "ce4922b3daef62914f0580a55c524e6a02e31d83": { + "balance": "5541295938315000000000" + }, + "ce4ce8a8540678dda16380c211482dd8c8b71092": { + "balance": "6224176337062000000000" + }, + "ce62cfd71abb9979a0acc398c17dbb5cb6da4721": { + "balance": "13448605175000000000" + }, + "ce724bb30c7821a9c847e0a3e9c12843c3471f9d": { + "balance": "252657175031000000000" + }, + "ce8af01494c2c5b4e74bb02dc6de982e7234fed2": { + "balance": "77349533545000000000" + }, + "ce8c774b7f92045faec43e9cc1711224a3b32435": { + "balance": "370287579971000000000" + }, + "ce8c9ed5018559f36ec72e5a9b0701724e498b51": { + "balance": "142866501748000000000" + }, + "ce995c13568a8b1521d4c9721cfc11da4891860b": { + "balance": "1000000000000000000" + }, + "ceab9dddc767a9651e98527fcf51f6e85c9ae402": { + "balance": "5251411770975000000000" + }, + "ceace25f8c7cf853500a461df007f9c9703ac4a5": { + "balance": "1428847332255000000000" + }, + "ceb0c49dad36f6169ec82a2f0d80da36c87e4209": { + "balance": "459821324064000000000" + }, + "cee8083233bcb4d50ddbf2121c90b5c2019ca58d": { + "balance": "557985245088000000000" + }, + "cf0c6bcc66eb75899bc7f8ed4b8d2b29437bfe85": { + "balance": "3252418478000000000" + }, + "cf32c5bf1d7ef0cb0f2f190f8468b01a4f2d93e2": { + "balance": "6593164924646000000000" + }, + "cf6e47463382153fcf0ec6738880925dbc08116a": { + "balance": "1091910654350000000000" + }, + "cf7539096fd0cd97cd316efcfe9d3c87a101a74c": { + "balance": "741847588809000000000" + }, + "cf9439bf2fbab65cecd783e135a37127f585f1e5": { + "balance": "50100000000000000000" + }, + "cf9bdc902604fab070c611ebf6a989ac4a785c82": { + "balance": "1501000000000000000000" + }, + "cfbbefc0e6013fa2caeabc54ac05f45dbf17ca13": { + "balance": "230809632301000000000" + }, + "cfd53f18ac7d94cadd032a0f4cdbdffaf4765d6e": { + "balance": "64000000000000000000" + }, + "cfe66dc4aa9ac9c9f87fdd05c1b2b95da5211703": { + "balance": "1656993051100000000000" + }, + "cff376eef4d69c4a47d6c7916583228fab3b5967": { + "balance": "5904462494391000000000" + }, + "cfffcb819302d05ed763026bdf84b48818938fb0": { + "balance": "289619807900000000000" + }, + "d000aa72a77d55911a5e66c2906da9206db86633": { + "balance": "3008989624945000000000" + }, + "d02d7b42213e873f91e789cbaffc734ffabd1087": { + "balance": "144960809826000000000" + }, + "d02db5279e918b3e93ff81d00d4025cc71dccaf6": { + "balance": "2386625717975000000000" + }, + "d0802cbcca2bb516f251b873eb20bb5e94af7f37": { + "balance": "9287997718210000000000" + }, + "d0c07380308972a36f57d1cd9081d7389d0421cb": { + "balance": "1280367167470000000000" + }, + "d0c131c1b60891b91e58fbed787ee4567e3f2038": { + "balance": "6360752089492000000000" + }, + "d0c71159d46c4d2af7699f682a055c79a1a68a0d": { + "balance": "1527974433762000000000" + }, + "d0d5d9f242f2613079b3b443c359c2e18ed5faab": { + "balance": "637334647476000000000" + }, + "d0dd208ce92da02eee3ee3de335e67f819581a33": { + "balance": "100000000000000000000" + }, + "d0e55ec0ad0f8986dd9fa9d738007c5bdc22f840": { + "balance": "53012893797000000000" + }, + "d0f222cec657ee444e284c07228d585155b82c0a": { + "balance": "7368748129592000000000" + }, + "d11efb07887d8b5b87a77d8fd388190614e8c077": { + "balance": "4703283503278000000000" + }, + "d129f1b89045ebfb4d1df1d9077e9359fd2990f7": { + "balance": "14496053137000000000" + }, + "d15a509424c4e04868bdcf59cbee09882ba04c8d": { + "balance": "65042393236903000000000" + }, + "d162416912b03fa65f3972a63e357ceaa3b621f7": { + "balance": "325650177224000000000" + }, + "d166183164b81bd049b2146a3ccfcc78cc6a0bdd": { + "balance": "1000000000000000000" + }, + "d173d759f0916e61400d56ca690cbf1743fe27b0": { + "balance": "53550838679000000000" + }, + "d18dc883e3881bf4c7db2afaa097bc2d33656724": { + "balance": "5000000000000000000" + }, + "d19dc9b5ae689dea1ccbfea8b44ec6034559e326": { + "balance": "135552499885000000000" + }, + "d1c79160d0b8c1a1546b86db5123e87645a45d13": { + "balance": "10000000000000000000000" + }, + "d1cccaa22259c547993df3c147d5b545f003adb8": { + "balance": "10000000000000000000000" + }, + "d209c9f32f3292ac4d15ef353fbe6f6efcd4e49d": { + "balance": "81000000000000000000" + }, + "d21ac89a20d67e309f96f64adf05fc48f55918a9": { + "balance": "500000000000000000000000" + }, + "d21f6e7adbf480600295af683091f9b9833f5330": { + "balance": "1229445878922000000000" + }, + "d22700a47a0edb137d2f0348aa0f8d4b6dbc5850": { + "balance": "21301422923000000000" + }, + "d258ddc9372e3b70ff53da171252239655ca9886": { + "balance": "16000000000000000000" + }, + "d274c69317dd836df48562455e8f5a7bd2e47d19": { + "balance": "156091832558000000000" + }, + "d286b68a358fcf8a6cec70b83467079664632ae9": { + "balance": "90377010699000000000" + }, + "d29284915d9b924ae5673e8a4a557478f68a7471": { + "balance": "324678197320000000000" + }, + "d297e64ac2bd8e98e6d276d6fe080679c398a26a": { + "balance": "3401930527000000000" + }, + "d2a1e7b51f6b5930a0d9e2ee55736f3d83a1b323": { + "balance": "44578900750000000000" + }, + "d2c9b0b0bbe61de504e4f210c168fa5999c9c23d": { + "balance": "76537483113000000000" + }, + "d2d49f650d222ec3e2cecba163ee92f0e934ca14": { + "balance": "3312486482635000000000" + }, + "d2d803bf10ba18adef5716b4056c1b1d61c45abf": { + "balance": "964679698000000000" + }, + "d2f673b589df7ef5cb32fdeef842d48d66130567": { + "balance": "1079010447581000000000" + }, + "d2ffaceef1af3f1c3e3f35e4062cd9f9abd1da59": { + "balance": "3041453068594000000000" + }, + "d30a74f5041ec6e73d066a375a105116699ce177": { + "balance": "21814020745000000000" + }, + "d30d849a2d8ff5041304014ecf6752dc769bf004": { + "balance": "1247532881540000000000" + }, + "d3113f558c6376321691931c9b21205e31f4a56e": { + "balance": "572224428451000000000" + }, + "d314bac1bf85eedeac0b359dd2106dbae8fc6947": { + "balance": "20000000000000000000000" + }, + "d3283e17112028b324327ef64a238183ba189207": { + "balance": "136000000000000000000" + }, + "d33ce3c3b64d1b3d399651432c15ecb943d16c70": { + "balance": "10000000000000000000000" + }, + "d33e1e4b10a98e82810f6d161df5d35e5677e35f": { + "balance": "10169656674000000000" + }, + "d34699fd152fe38caacd3c096f6abb1cd79e88b2": { + "balance": "25056644550000000000" + }, + "d369c0e01b9a9d519b3b099a98fead19867c019c": { + "balance": "100000000000000000000000" + }, + "d388dcfe55a9b710d05c686f033fdbdd7861ab71": { + "balance": "1439589263065000000000" + }, + "d391a7d45c7b454b743bd867f8f62f56894f9b65": { + "balance": "484904747488000000000" + }, + "d39a75b4831543e1bc99e7a5ca8875c4f69da45b": { + "balance": "10000000000000000000000" + }, + "d39ed6978b6a90fea29e735f8ea3f1d20e0fbd15": { + "balance": "144000000000000000000" + }, + "d3a0a1a00dcbd6bc44c9803ce351a4b36a69c929": { + "balance": "191222401916000000000" + }, + "d3bf1c0a6b0470c30fc49d995025af5e6b639e61": { + "balance": "10000000000000000000000" + }, + "d3cda762bafaf204469f85e6896ec64147a3452c": { + "balance": "468094119213000000000" + }, + "d3d04d78c1ab9e6887a9467b8b1e31b5c9910e5c": { + "balance": "81000000000000000000" + }, + "d3e1bfdd9396aba00d3e78646ddcdaf139a967c0": { + "balance": "833333174120000000000" + }, + "d3e502c42ff0274da12ba87ffd45fa593bba052a": { + "balance": "100409899947269000000000" + }, + "d3e76066c2e32d9a693161de07f2d3b7e6ea07eb": { + "balance": "10000000000000000000000" + }, + "d3e8d577323d97407246b198c4c61f7943c468cd": { + "balance": "10000000000000000000000" + }, + "d3fd4d1b0edbc314b103d350fff023ab75b7d7cd": { + "balance": "84129547428000000000" + }, + "d40087fca8feb72d130bbc9622575d4987f12895": { + "balance": "1000000000000000000" + }, + "d407d4126cbf3619a422c532ccf20c3da1495dbd": { + "balance": "99622000000000000" + }, + "d41a28761c8e5de8c803813667f1dc0918a105be": { + "balance": "157507410260000000000" + }, + "d46ed38228a3c3d78065b2d8b71b325bf0f0e685": { + "balance": "6787045850000000000" + }, + "d4a7463d202e804b39a93bccd77491d8791baf58": { + "balance": "171694163573000000000" + }, + "d4c20716ff7288d811d05fd6f0696a9f5627a11d": { + "balance": "100000000000000000000" + }, + "d4d95059c808cf41e64f7f353246ffae635419d4": { + "balance": "10000000000000000000000" + }, + "d4ef925157c6d0e2d649332f44416b85f8abe69e": { + "balance": "1392945162611000000000" + }, + "d4f0cb25801794f6d803306878763e08209d19f4": { + "balance": "64000000000000000000" + }, + "d55fbebc4dcf2de6341c2325448e9c198f0f06a3": { + "balance": "14206622892000000000" + }, + "d566968c40211fb25114105e36b5a7219cde9d5f": { + "balance": "4898442964000000000" + }, + "d5817b95c6b504a6d07f64faccc9aedf408b0ac4": { + "balance": "54387832478000000000" + }, + "d59679fc40a71897065bf1b3a73f331226cdae72": { + "balance": "20000000000000000000000" + }, + "d5a7deec4a5898f094e1600f9b15768d8aada258": { + "balance": "100000000000000000000000" + }, + "d5b91c29bf772ad3ba04033dfb86b672b245ad77": { + "balance": "100500000000000000000" + }, + "d5c1a9bcc5e68b7547354178fefb3d870572fd67": { + "balance": "2252066779089000000000" + }, + "d5da2a826f5909a221bfd8561dbd7dbf4aca4c35": { + "balance": "13839784966766000000000" + }, + "d5dcc82fa169b4677a3fc26d78f38e27dcc763f3": { + "balance": "10000000000000000000000" + }, + "d5f344ee8a1b954ae5fd8fc7ac702174749bc8a4": { + "balance": "1398836216771000000000" + }, + "d61cd03afbfc1bea186e5a3a51347c2c4ee3a2c3": { + "balance": "109879472702000000000" + }, + "d647fd7ca17203a0049c28ec6759612d767cfcce": { + "balance": "162681136487000000000" + }, + "d656d14acfb2f0fbde2ed2a137a52d852bb6288b": { + "balance": "20000000000000000000000" + }, + "d68130b421b19c193d03a9017b2dc687c7307d26": { + "balance": "128569735484000000000" + }, + "d69a41f7ca76b40ee94b0d04a3780a00c6c651ba": { + "balance": "2801054372864000000000" + }, + "d69af2a796a737a103f12d2f0bcc563a13900e6f": { + "balance": "7412286547000000000" + }, + "d6a5a7e149cbccb72a50b0a3ae00e6756b0a7eda": { + "balance": "1075352201657000000000" + }, + "d6aa9957f141f0dfed77e943c39aeed978834fdf": { + "balance": "20920740110000000000" + }, + "d6e99ccb72d24e8a60f24d47afd4074b1d1fd336": { + "balance": "15415994387186000000000" + }, + "d6ea4a9dda8d5bc832229c916fa45f05f99c093a": { + "balance": "27075799893190000000000" + }, + "d71de419d746ac277baa955761cced4b34c376ec": { + "balance": "1388473506822000000000" + }, + "d71ec6b5e5d4c604f741bafde0974eca49c56156": { + "balance": "61938809628000000000" + }, + "d72f90d9879f6d2d407b4fdf5d128b98d518f1a5": { + "balance": "10000000000000000000000" + }, + "d743d7925a0cfd08150814cce8cd5d3f7099e1c9": { + "balance": "25681376856000000000" + }, + "d7575a09e7498f21cda3e9e7266b7fde91dfe19b": { + "balance": "9841565066000000000" + }, + "d75c2eb5e0a2b2ee72ef4fa7249c1a1ce03f333d": { + "balance": "134491489751000000000" + }, + "d77088329ec1e280ea7a087ad20c5e965721ff4d": { + "balance": "3949070941222000000000" + }, + "d78d564bb79ea19e4a93975a38fe0882018f177c": { + "balance": "992717434142000000000" + }, + "d78efb176b252ce67b5648e04088d12c4668aad1": { + "balance": "10070463674000000000" + }, + "d7a25e43d7d4e23744f0b10e2b4f2911fd3b3bc1": { + "balance": "1000000000000000000" + }, + "d7a941cd82f8aa63c55baa81db44bcb347b8e529": { + "balance": "49000000000000000000" + }, + "d7b34387880daede6cbdad11bb3db67daf942975": { + "balance": "20000000000000000000000" + }, + "d7bca0770e2f890c1e93c3595641241454a31045": { + "balance": "2000000000000000000" + }, + "d7cb675cea1c0dafded44f611c9c344e2a5e053c": { + "balance": "25000000000000000000" + }, + "d7e53a2d8eaefd18e02bbadb7e64906ca8613151": { + "balance": "166599594268000000000" + }, + "d8076b9db0b7496efbd198b73c4bfcf51ac080fd": { + "balance": "210272077089000000000" + }, + "d81dcf5756da397ff1f783ffe5391d1ffd4ff227": { + "balance": "500000000000000000000000" + }, + "d833c6d08f5fff8f77628ab1e86584d052976d1f": { + "balance": "10000000000000000000000" + }, + "d835732e85953baf2af9e49f770bac1caa1dac23": { + "balance": "152211441541000000000" + }, + "d84005fea447e8c6aa0b5436ad79654a75348456": { + "balance": "22563694224690000000000" + }, + "d84d9c59a445911922e88c0f22cc6534f33ca3de": { + "balance": "3054115413381000000000" + }, + "d84e69926216065749e624d87783e90ce3015b82": { + "balance": "1420803164313000000000" + }, + "d884bdbdb7e13cc523e7f192310230c7bdbb4a07": { + "balance": "10000000000000000000000" + }, + "d88eedca1dd9249702f5ffc807c1e439eee1c5e5": { + "balance": "36000000000000000000" + }, + "d8a23fd234bada1c726622925ade62d3021e0037": { + "balance": "1567046607931000000000" + }, + "d8b1aee24264efebd1c677fcab6ada6e0f000cc5": { + "balance": "20000000000000000000000" + }, + "d8ba7afbb8bf2910b983a114aedec626eb7426c1": { + "balance": "275491152435000000000" + }, + "d8c8af55ebf116ba3c3904f8ac39d3a7d31aadc5": { + "balance": "1499999998278000000000000" + }, + "d8d97645f5f62aa89bf0046362dd0f45d40f821f": { + "balance": "25000000000000000000" + }, + "d8ea0e24a7e28285c4454f54181d581324da2583": { + "balance": "53039425000000000" + }, + "d8f5d258164747ccf790f5ed358162c756de49db": { + "balance": "323009990690000000000" + }, + "d9477bb62d3eb668a83a9679f3a7ef43f17c9e4d": { + "balance": "14045557127869000000000" + }, + "d9585e1b03fc86636dde1e64aed3cad77868549a": { + "balance": "1000000000000000000000" + }, + "d975f9ce3fe773fac3f8338a034a757c58f6e11f": { + "balance": "25000000000000000000" + }, + "d97e490faf19de612fb49c041d3f9e7877d3c0bb": { + "balance": "65766847746000000000" + }, + "d98117b74b2f2888d7078d3116d5758e2d09bfca": { + "balance": "1749157484422000000000" + }, + "d990b3f69ec700bdc095c184b3804551c832d612": { + "balance": "509385034698000000000" + }, + "d99b35298e709e5f54e6a5c612a326a83f4268c4": { + "balance": "71963571266000000000" + }, + "d99d9ec76005da26ccc721ec26be4ed9b3b1c586": { + "balance": "469607736824000000000" + }, + "d9bc61075c3201351584a026e5bdfb7cf9a7b6ab": { + "balance": "200000000000000000000" + }, + "d9d07b72f83491b6db26602f6b7039aeebfe6b61": { + "balance": "144000000000000000000" + }, + "d9f6f1ddf03e836b3744d008b62a6424544c67a5": { + "balance": "74347470143000000000" + }, + "d9fceff07ad69bf3b4aef54a7eee541368980cf6": { + "balance": "1143407707495000000000" + }, + "da0285fb7e37fd4be66fb862b248cea94ea8f6db": { + "balance": "80770216661309000000000" + }, + "da05c7aa330fcc5834e19deeb0a808e9ab7f3d99": { + "balance": "169000000000000000000" + }, + "da129e4481bd25450e6c7b42fe417c87ee2ce7a7": { + "balance": "256000000000000000000" + }, + "da32e3ec421993db088c71e256263158f7855b61": { + "balance": "18540215888567000000000" + }, + "da3c99669acd202ccbe6f80902c807588eca0880": { + "balance": "1000000000000000" + }, + "da72a7bec114d43aee6449db830d2d3f16e4d9b6": { + "balance": "744534872932000000000" + }, + "da72ec2cd7b8e3924f8baaea75d5ed23ef39394c": { + "balance": "38646377617204000000000" + }, + "da73078957f491827d62cb3ca0c484c2d1004ba7": { + "balance": "891774109242000000000" + }, + "da828e50c7c8580c6ce81718f11fbd43b2b0541f": { + "balance": "66094097819000000000" + }, + "da91483db6a6a034e068e69a6b46674838c5bc80": { + "balance": "4000000000000000000000" + }, + "da9551b635c3619f81641571e267755b89f7fe1e": { + "balance": "670841942250000000000" + }, + "da9b43a9c1c574580ec43da9f6acb687fc2f8c68": { + "balance": "761695404114000000000" + }, + "daa7f446923f7481115ad285ca468c865147e563": { + "balance": "10000000000000000000000" + }, + "dac6bfd15954efa4c9254e24e5831ab1884f8d67": { + "balance": "960042043423000000000" + }, + "dad85d0b8bb5ebf6ef811d0d35c89f9f343c833c": { + "balance": "37664599958479000000000" + }, + "dad9b01652de5d50bf30f9bcb0c6edc6315139e3": { + "balance": "21500996724000000000" + }, + "dae9c7d6bb0efe3f7ea20442b184f6d99b2a2c12": { + "balance": "937830189066000000000" + }, + "db0d6c28e9b913f611accaab15cc887f9b770f58": { + "balance": "20000000000000000000000" + }, + "db0e5341d64817885721c5abff04c30bd38df40f": { + "balance": "62600679700000000000" + }, + "db387dd404d14478babb60bad2391720d68b92ed": { + "balance": "115096708329000000000" + }, + "db3fb19e8a4a6ace4d8c6c02085d4cbba528b532": { + "balance": "1000000000000000000" + }, + "db4f05a66c0ccf0532ea1ecb931e05a400a6f4a7": { + "balance": "20000000000000000000000" + }, + "db571f1cdf8e83fbff6fb48cc0c81ef95ede12a0": { + "balance": "118317387393000000000" + }, + "db6a6a6db2aef3f43afbfe23027b670ebb3d33bf": { + "balance": "9960755220000000000" + }, + "db8bed34f8f34f45cb83ab19ed33fad76437d217": { + "balance": "21003651205000000000" + }, + "dbeba6a2a7f66c20c6db7b9270a5aee74de3f441": { + "balance": "4086905723945000000000" + }, + "dc04efeac13b2dab3d07833a7e7fa728fc23d18a": { + "balance": "1161834099120000000000" + }, + "dc092386c3a3e28b6b2d7d70db8f3d11e79ef5df": { + "balance": "124362293793000000000" + }, + "dc10be66aa11acbd42a2b1953714f09b5281681b": { + "balance": "20000000000000000000000" + }, + "dc2d58a383ce0bd40bed859ec2f25412b68eca0a": { + "balance": "104917823922000000000" + }, + "dc2e38183dceb2bc82b23e8ccf48dd96ea1c97b6": { + "balance": "2847787376064000000000" + }, + "dc5d9d94530d88451cf081fe7f2ac33667af9d8f": { + "balance": "65321904051000000000000" + }, + "dc993112a8d89136e0e73d67e2f26191583a50ec": { + "balance": "1000000000000000000" + }, + "dc9bb69b295945589a41feb794406558ce65dedc": { + "balance": "104077637254454000000000" + }, + "dcb0109d4fca2dace08ddca5d989a09d470161a0": { + "balance": "28897833222000000000" + }, + "dcce3a4ec516d833f5a9790c40ad0334b0d2dd01": { + "balance": "25000000000000000000" + }, + "dcdb21cc811ab733c2a80a2d5c8e5bb49cb2ddc4": { + "balance": "16000000000000000000" + }, + "dcdf8dd3ce03a2fe0d72835dbbd58725e1ed2c57": { + "balance": "113330414284000000000" + }, + "dd2165839ab95d6b24591307adcde9ee1819927a": { + "balance": "20260199589072000000000" + }, + "dd3015a5fdef66e749a000585d5574f975e3432d": { + "balance": "85465001652000000000" + }, + "dd37c478727f44943c5fd79ace30f21fae5a589a": { + "balance": "108577233510000000000" + }, + "dd3fb5810c31d37652bd17b92497ed479faf123d": { + "balance": "669996966072000000000" + }, + "ddc3bda30f7cf36bd535de4e20c9becb78d159f4": { + "balance": "99998278000000000000" + }, + "ddcce2d2431b67d4157c7ac4bd77f20c24831de6": { + "balance": "36160893899000000000" + }, + "dddcebe609f8b4354a1f27ab1915135e25800344": { + "balance": "1457846339959000000000" + }, + "dde223eb48f81748abde6cbc08cf1e6b0e8e4e5a": { + "balance": "1501921107087000000000" + }, + "ddf4ba402007060d9940a96f8e7c39f0a2c6108a": { + "balance": "377268151287000000000" + }, + "de05d9ada6626a8492acd137c7c7f7080a987cd1": { + "balance": "222144234923000000000" + }, + "de0fab89f79c4edf9766c3b7b1f508cb43c5495e": { + "balance": "8278000000000000" + }, + "de1070f3ff6c47237768fbdead88b2d5184fbe2f": { + "balance": "1000000000000000000" + }, + "de2b16d7f36f630329287822f550ec19415acb3a": { + "balance": "25000000000000000000" + }, + "de3faf6884337a99e54ac5d3f08b34be51b0755b": { + "balance": "51926806905184000000000" + }, + "de4614fd632ddac888d177de0858e62bbbf7dc11": { + "balance": "52506376589000000000" + }, + "de54cabb241dc5def530191f948f67db942a85b0": { + "balance": "9691177060000000000" + }, + "de81e488284acc4f8f6061d3a73bad112efa7a40": { + "balance": "14654060992000000000" + }, + "dea86ac3a661272691c877c1bad8355789382b69": { + "balance": "903877103000000000" + }, + "deadfc79f2a722dbf1c1a92f2824da8874189fea": { + "balance": "98905944986000000000" + }, + "decf1af47e153f6f3749a1b7abadefdcf1607a0f": { + "balance": "529000000000000000000" + }, + "dede5fa984f0def639d5b633f54c60fc5aaa272a": { + "balance": "8193771708654000000000" + }, + "df23607c63b3fd4b5fde6aab093c0c56d1188f95": { + "balance": "14687379916000000000" + }, + "df5b74bf02902e4c466821de798406b663d4d73e": { + "balance": "9000000000000000000" + }, + "df6402ee3f37389e7f65720561b54e26e5f1cbaf": { + "balance": "358266132937000000000" + }, + "df83ea5b770d5abeccac7f0cae803e8bd7b9831d": { + "balance": "25000000000000000000" + }, + "df92802ffe9892c7704875755bdec648914430e6": { + "balance": "20000000000000000000000" + }, + "dfa108bcd80e824a255679a38b2450d428e2f939": { + "balance": "489209553654000000000" + }, + "dfa9f18e859353796afe384d05353dc80b3ffc43": { + "balance": "121000000000000000000" + }, + "dfb0d6580f011e68a39d7727818b0890e70f3036": { + "balance": "537675412560000000000" + }, + "dfdf006abf2293aadc58feea6af6b35db428675e": { + "balance": "9000000000000000000" + }, + "dfdf2ba93bd47d7243b7419413458a947effcf67": { + "balance": "45080282196110000000000" + }, + "dff01277ac23a8cf93383595a80a7c070eafe5c6": { + "balance": "312778552103000000000" + }, + "e0450154c441e52c5e507e8316d4e9376c59c12b": { + "balance": "170163401434000000000" + }, + "e059374d6a7e6c63e609b65642272869fa3b2b3c": { + "balance": "300122497803000000000" + }, + "e0c0d8e739a2f274a43f019a07f7f61d7d8e11a7": { + "balance": "2630310240000000000" + }, + "e0e779e4e3573ea77096daec252ac2b3f1c0013a": { + "balance": "10000000000000000000000" + }, + "e1325eb586180a67873718a2016172afeb03c6a5": { + "balance": "531691399657000000000" + }, + "e13958af480da6443b9ec1067f0f33440634a282": { + "balance": "10000000000000000000000" + }, + "e142daac753b2c4d215372797999e9c88b65dfc9": { + "balance": "585813299366000000000" + }, + "e142ea343bc36ec49989fd43ad5c403c70a40dbe": { + "balance": "656734902975000000000" + }, + "e14d0a3d259db6bfec2fc4ef6e18729e4d93b007": { + "balance": "210234446279000000000" + }, + "e16a5316e3a113f27bafdf3d4fe44fe30ae9c210": { + "balance": "16000000000000000000" + }, + "e1770944aec145a96c9491497eacf7f3fb03c1b2": { + "balance": "335417250470000000000" + }, + "e199ac237661dcac0a4cfab404876abde72ee209": { + "balance": "340000000000000000000" + }, + "e1ad427471023f38cbdf07fdca3728ec343810c4": { + "balance": "343957267368000000000" + }, + "e1ae0223cecd738c8e530a0007ef05e8f3b33769": { + "balance": "950528515289000000000" + }, + "e1d2d4ef39f01a60c3bb5d671af91c5298d87711": { + "balance": "121000000000000000000" + }, + "e1d4a8888cbb383f3671ca96e7b55310b59a2541": { + "balance": "242387826125000000000" + }, + "e1da9039ddfe117e6a0b484fd3962426c112871c": { + "balance": "3710499693813000000000" + }, + "e1da9f16d57c601af8b6d102323c20408af8531a": { + "balance": "3135322588771000000000" + }, + "e1e1c163f391ffad2d0be68641253b0860485a95": { + "balance": "10000000000000000000000" + }, + "e1ec6361df67ad915df9e9661cd0932186db034a": { + "balance": "4279936304854000000000" + }, + "e224050bcd723e63f1fc0567a86942546aaf8d13": { + "balance": "12007628539000000000" + }, + "e2342c7f411d7ca3a86484af59a9c3f3180e2f0f": { + "balance": "16000000000000000000" + }, + "e26f2b026a258ce5801c90bb8fd6f7a152b8d267": { + "balance": "304593714834000000000" + }, + "e2717eb5fd0a1da51272b50ca8d12858009c7016": { + "balance": "506943817535000000000" + }, + "e27546d5620e6398829260e58e8cf4a3a03f4164": { + "balance": "3000000000000000000000" + }, + "e2762bb64e0606a5d635032e15164b01f612a74f": { + "balance": "884716158811000000000" + }, + "e2882066ed0a3c041d09c00c8532850fc42eac06": { + "balance": "42441412728970000000000" + }, + "e294c5d64daf7b7c0994aa9d03669c4b2658c9cf": { + "balance": "6996693830997000000000" + }, + "e2b179f0ed6870a6268aea64b0c7b39d98d97fcf": { + "balance": "334205318353000000000" + }, + "e2d1f6f7e3128340b789565b527bb91de96d54bf": { + "balance": "100000000000000000000" + }, + "e2f136d3693aa0b2346a968a22aca6707fc1d0e5": { + "balance": "10000000000000000000000" + }, + "e2f229054293e32cf3e83f9bb88d9cf1d6acd66b": { + "balance": "20000000000000000000000" + }, + "e33b8f4c9a49554c8b134861f88c8fffc399e456": { + "balance": "83552502198000000000" + }, + "e33cfc7727b1460324b34277dde14cc49bcb273d": { + "balance": "100000000000000000" + }, + "e36af9bfed4f912cae21f3d899f7354e1c902601": { + "balance": "31474316356000000000" + }, + "e36eff7c061dec48446d47675f176b4da3c2e950": { + "balance": "10000000000000000000000" + }, + "e383f3cf431f3cf645f26c7d5e5e2f77348ede6f": { + "balance": "776224304171000000000" + }, + "e398b9f004a4f891cf871a57d9124a97b56e89e9": { + "balance": "84846187740000000000" + }, + "e39ab2415144b46db522e92ed51b8089a5ec01fd": { + "balance": "4158925896363000000000" + }, + "e3aa7ac7e15e9a8a6f54565067234a9d4bf7b569": { + "balance": "1080385576951000000000" + }, + "e3ec5ebd3e822c972d802a0ee4e0ec080b8237ba": { + "balance": "2129139289000000000" + }, + "e3f1fbff8686af23ab95eeeee6a6a03782d72416": { + "balance": "401776848194000000000" + }, + "e4001b830fbd86df257ebab54aec0c66314ef9aa": { + "balance": "518220809325000000000" + }, + "e40790bff894f0b3e534942b5ad6f6592cd6e896": { + "balance": "25000000000000000000" + }, + "e409170a296e46fc96d85a2395e4324212a470ee": { + "balance": "1072528749756000000000" + }, + "e41546f68bbe1771febbdac2a4a5999eef50edf3": { + "balance": "1000000000000000000000000" + }, + "e425d63d711a9996c09d928ba8df94c88163aea9": { + "balance": "10000000000000000000000" + }, + "e4432ff1aee13f97f73a8407e4c7d6e768b8040b": { + "balance": "700508995102000000000" + }, + "e4690f5d024a395355a7cb5238fb7e0dc921b1e8": { + "balance": "1000000000000000000000000" + }, + "e4829684fb36f054766a61fb2a8f6ecdf27c9e87": { + "balance": "73885178137000000000" + }, + "e48a68e1ac007e14ac08c1b3b0df2b5602081ec2": { + "balance": "1389262869176000000000" + }, + "e4d699b3f4117eba7ed27b323048c9ffcb46ed42": { + "balance": "183131036697000000000" + }, + "e4db688c29fdf9a1c16114f99797d8409545955f": { + "balance": "16000000000000000000" + }, + "e535b94d370190d1e0955d3c0d12480e558f00dd": { + "balance": "20000000000000000000000" + }, + "e53966d4bb17fa9b50d29b44ddf3951c9ca67caa": { + "balance": "6400630678000000000" + }, + "e56f2656fdd1a5f7d3716e65dd89a37dd6e42dcc": { + "balance": "1000000000000000000" + }, + "e5a364113076273352e0c31bf505028e0b7edbaa": { + "balance": "10000000000000000000000" + }, + "e5a3c80518fab6a0a721ccbdc3e673680a65f6de": { + "balance": "171727917465000000000" + }, + "e5c71c7170e5c9b07e62cc307d81a4a3053ed64c": { + "balance": "10000000000000000000000" + }, + "e5fb6408db128c55cfb3e7fa1942d6347e34932c": { + "balance": "10000000000000000000" + }, + "e606883236f8b2045393c574153a100675cd4b90": { + "balance": "14005226900000000000" + }, + "e61869d1cf72f25e195898217f5bf5bcec9c9038": { + "balance": "50000000000000000000000" + }, + "e61e2e29c0719457ab1bf7d6d9fe442bd6107b07": { + "balance": "30943034333100000000000" + }, + "e61eb97093e9ee609647bd55f434a27bb30a9401": { + "balance": "200951434577471000000000" + }, + "e62812ad5834747f17c92435d863639e84d132fc": { + "balance": "3017271391299000000000" + }, + "e630b92aa8443eb077e1f6990a2e194d99cf53ec": { + "balance": "1000000000000000000000000" + }, + "e656fd1641c15e1a4b753be41bc4aa438b44b42c": { + "balance": "26972744083000000000" + }, + "e663f0257b98dfa80602a2af1bea1f901c4a7612": { + "balance": "97075813547000000000" + }, + "e66e411a8a9d019b53bf2e0a7e44703e1aa93ac1": { + "balance": "25000000000000000000" + }, + "e6712675d13fff27af43bb1cb3f2f283755bacf5": { + "balance": "227572496234000000000" + }, + "e68e8f04b2cff484da2d41dd639ae8880920f781": { + "balance": "20000000000000000000000" + }, + "e6972b5d7e0fe8c722dec9146b92f89291a0207a": { + "balance": "2115924954211000000000" + }, + "e698b491330cb55ecc4cc4b74015cd94eb927fc4": { + "balance": "1038111785278000000000" + }, + "e6c411e67b90109dbb0fa75f0f07ae8a504e9637": { + "balance": "123792105420000000000" + }, + "e6fb1dabc624edb45b040ad66f30dae010a6b634": { + "balance": "16076893670852000000000" + }, + "e71dac161206e7d3686d13b98fd922ab73587988": { + "balance": "500000000000000000000000" + }, + "e773f9be9b3f4b35ac149b4d759b9e47c8000bdb": { + "balance": "329623043336000000000" + }, + "e781cbbd2dccfdf68595d54fa44104a80d52dd22": { + "balance": "188679476509000000000" + }, + "e793666c7850a409b1d5494f576d122e85cfed9c": { + "balance": "1141845197779000000000" + }, + "e7a5527c6deb922e9f84309c502048f49f0c8f14": { + "balance": "81415566708000000000" + }, + "e7b0f75f9c69ae464b1b63cf295555d0815fc532": { + "balance": "10000000000000000000000" + }, + "e7b43cc673e321e607190a6fde996b71508f4d81": { + "balance": "103958781426000000000" + }, + "e7bfcf3125e37755e57804dfe4479657b212a8ca": { + "balance": "10000000000000000000000" + }, + "e7d33cbbd4eb38365c5be04ce32658a5ac741cfa": { + "balance": "1545192252109000000000" + }, + "e84cfbd7844f6aa3e830258a6b1069b6a7ff5b7e": { + "balance": "543989509107945000000000" + }, + "e8aa0cbc5c1f59fadf3ec122fa8a59ebfc60b5b6": { + "balance": "61271973066000000000" + }, + "e8adb5303c30a8ee044dc09c49818c02a16f4254": { + "balance": "737375689166000000000" + }, + "e8aeef5114e19d467c3064938c5965d04830f2ae": { + "balance": "51130466380000000000" + }, + "e8b5a83497198a513fb2e244bcf05f9d4cf09d62": { + "balance": "10000000000000000000000" + }, + "e8b6818cf0d24bd0e7ded854b3d368662a150dab": { + "balance": "63697741112000000000" + }, + "e8b68b9cb24169fd688db7a626d79d0363777c75": { + "balance": "427222669643000000000" + }, + "e8b8b57b23ea953943da3ef7efaefced9cdbb44c": { + "balance": "16000000000000000000" + }, + "e8f85dca364d26c2149b767904c6c06249c3d88a": { + "balance": "199342917246000000000" + }, + "e916c7801cdcf1b6cf640fcd9dcc1e3148c80105": { + "balance": "9000756000000000000" + }, + "e93cbef13277324caae7816c3d601e2f6bb42589": { + "balance": "121000000000000000000" + }, + "e9415fedcdf8939b551999900128530195a2a5f0": { + "balance": "85165078941891000000000" + }, + "e9a79ade714ce48a07fe88532a20d8f8ed27bac9": { + "balance": "30768493367842000000000" + }, + "e9b35c7ca775661bbd3a4844e2c6bc5effcdea58": { + "balance": "134719523000000000" + }, + "e9b819dffb600373bfd1b1608fc9744cc9167855": { + "balance": "1537634693002000000000" + }, + "e9c5ef50d4a194e53928659b4486a1c456df9e56": { + "balance": "50000000000000000000000" + }, + "e9e21f4523b11567516f6fc525e8967ac707f988": { + "balance": "2498740681000000000" + }, + "ea02821d6c730e061a9947b75188eb8bc0bbf9f1": { + "balance": "12822292582000000000" + }, + "ea3bca3a17c7e724ac0e15acab6442f222cd8688": { + "balance": "2789689549000000000" + }, + "ea4f7923d7045a148d50153f5f4620dbd31a74da": { + "balance": "113595858930000000000" + }, + "ea6d4cbae3cfe49ffd36653bb0d64c01b2bbc0b8": { + "balance": "49325017701000000000" + }, + "ea76cd4cff825301932a5c1d3a1de55a0ff00797": { + "balance": "1282028021000000000" + }, + "ea8e4c8c6500856777e2b41832ff00443db291ce": { + "balance": "553674550359000000000" + }, + "eab52191e5afc804b8685fe13d7ad6f5dc64fc12": { + "balance": "244412435341000000000" + }, + "eac1b0868b710e40d6d5c66a461dfc8f78abbaa9": { + "balance": "10000000000000000000000" + }, + "eacac2c75920b8f6e65f37ad81deb113d526d031": { + "balance": "53028042076000000000" + }, + "eacc9ef8b534143560f420031a8a7f030ff1a36e": { + "balance": "381111853842000000000" + }, + "eaf2cc9fdfe6272de269f32486b2d4c248a05afe": { + "balance": "2793234915237000000000" + }, + "eb0220406832a8a5d4f242538e82c80bd83d0ac6": { + "balance": "10000000000000000000000" + }, + "eb20efc0e0af48c8e6da4b21efa9c9f02d92d29f": { + "balance": "152958793764000000000" + }, + "eb41bce8e3aac2bcf662854a3151e3c83d98c6f3": { + "balance": "219455327737000000000" + }, + "eb44c591306972c29a7084079720d8ee5fb9b0a1": { + "balance": "49000000000000000000" + }, + "eb4b26ab55dc35df2e78d47a90fc43148a6de881": { + "balance": "12139574483030000000000" + }, + "eb4f53510db5edcaad6ea169e521bd094e8da4b1": { + "balance": "100000000000000000" + }, + "eb4fbfb7c0082aa0e7edaed934c5166fee955e5b": { + "balance": "299713748180000000000" + }, + "eb6067ab544af6289a73111e7693dc449d5c2134": { + "balance": "20000000000000000000" + }, + "eb86fea82d10d309b1365237e4855a48684e0e49": { + "balance": "81510415589000000000" + }, + "eb8abbcadeb6e19ab4392cded7a407c8d5df2d5c": { + "balance": "25000000000000000000" + }, + "eba44ca2d6f36df8221a2021bf0644cf6cb59452": { + "balance": "500000000000000000000000" + }, + "ebacbc0eace170f66415df48f74d98eb31828d15": { + "balance": "19046465915296000000000" + }, + "ebc72fb8a1029139d8abdc08da23dc559f87e1a8": { + "balance": "24177703742991000000000" + }, + "ebd561bb9001991cb6b02c8ff9e7ece8a3d73dde": { + "balance": "6684606759000000000" + }, + "ebe1dc3ee857ae4add6fa6636b678af8451d1701": { + "balance": "1485349608007000000000" + }, + "ebe68dc904c737be83aa2ee7f613dd51a6d436e4": { + "balance": "11206782120918000000000" + }, + "ebecf4db55a99f018bf136173ae823528f211380": { + "balance": "191817711082000000000" + }, + "ec15ad0aafe0c0f18089de50b2397509e15a20de": { + "balance": "20000000000000000000000" + }, + "ec2e56973a6cbd8b37d0294b16ef806ab5943ec7": { + "balance": "12031630315394000000000" + }, + "ec432a6a4685ebf6c1e872001d1de246140c8d98": { + "balance": "280056522277000000000" + }, + "ec866ba1bdadb91ca25f5ae035b0f69421ed4377": { + "balance": "431849961155000000000" + }, + "ec9be854224d3d371b79ffc1230fe704ba03be2b": { + "balance": "3692428502391000000000" + }, + "ecc2d6e129c7daa37a93f559c6d4f575171d8386": { + "balance": "20000000000000000000000" + }, + "ecc3aca2a21cb317c5b9debdcb2090f3931d5cd7": { + "balance": "100000000000000000000000" + }, + "eccc9a49ff40aa4b07aa0e1271cfb6713de683dd": { + "balance": "617207728367000000000" + }, + "ecccf24530629033fd6234ae32bde2052ebaa640": { + "balance": "16000000000000000000" + }, + "ed16770d5a56dced87224d4ff68a361a2285fef2": { + "balance": "10000000000000000000000" + }, + "ed23b8e782d5ddf203f9b80e5df83ec32e484fc6": { + "balance": "5000000000000000000" + }, + "ed3244e4168e669ae9d54175173c3f0f0e7c4c7a": { + "balance": "803397672115000000000" + }, + "ed48f39d3f022b321c0864d4955e1cdc8cf54834": { + "balance": "64000000000000000000" + }, + "ed4cb42fa6737cbbbf095f181e1425b3bc3ab4f6": { + "balance": "8974148344000000000" + }, + "ed560f7d83c27a26965f84dcface3930bc447fc5": { + "balance": "2092287996000000000" + }, + "ed6ace91369ec3b06cce474e67d1ce4aba6475a6": { + "balance": "1227081000000000000" + }, + "ed8249dd4a91f70176ffff310e5546e7e0c30b91": { + "balance": "813069034369000000000" + }, + "ed8987fa3d4d42bb8f009c99cda5868633d94f5a": { + "balance": "174952234860000000000" + }, + "ed99b72a58a519ca7aa8f46b8d254c3f1eeea0d6": { + "balance": "10000000000000000000000" + }, + "edb720c9bde4801e204e90282de2a6cf1c44c4ad": { + "balance": "10000000000000000000000" + }, + "edbea23cd0cfde3705d83aada88e78b9f4bb1a50": { + "balance": "4000000000000000000000" + }, + "edc1f174655205bb961ddf94a997cdfd24f1c2ed": { + "balance": "65211537189000000000" + }, + "edd1d2dcba881202bc546943194d64e59bf74bfd": { + "balance": "10000000000000000000000" + }, + "eded28fbd959f2351b4252abc71f0e809562fd4c": { + "balance": "1000000000000000000" + }, + "edfe4d4c83c7db76e5e8a9ccafa34d9841669dac": { + "balance": "2578239411258000000000" + }, + "ee1ef79de869b89334d883ba766e65150f3f6cf5": { + "balance": "779780646165000000000" + }, + "ee27b2da240e862f0848d31116a7b4ed91835c8d": { + "balance": "111637484977461000000000" + }, + "ee3195bdb69e97796911c63fdd3fcebad61ffe9b": { + "balance": "214483035823000000000" + }, + "ee43306530c21793c4fd6039b51cf54fbc912bf0": { + "balance": "374531713769000000000" + }, + "ee4515e30ee1b8dba4779ef213d89e8dfff26ea6": { + "balance": "1166743135013000000000" + }, + "ee591e9ca7948b8485eb210e2a3f706b97e6f9e2": { + "balance": "27793157052774000000000" + }, + "ee5ba6c854d633a04f7656d311817e5104c6de14": { + "balance": "289361919166000000000" + }, + "ee909db4ee48bff3adb9e43db940245a8e5e094d": { + "balance": "582143490064000000000" + }, + "ee94d1afa82de70eb65aad0662f48ef3170495cb": { + "balance": "242490158636000000000" + }, + "ee97e18e09bbb16137a7b4aaae464e97d70e6606": { + "balance": "442709862861000000000" + }, + "eebe957af00050c2841f3ef8768c6a77a5394012": { + "balance": "9000000000000000000" + }, + "eec052f4e2902f7cc496162ca6525997d2b3ede4": { + "balance": "69349303517000000000" + }, + "eed30e1a939d5f0b4a39598967a5f149a7b7cb8c": { + "balance": "1637195595000000000" + }, + "eed7bf1ba39bfdad0ce1b6b8d4c9bb31dc1a9843": { + "balance": "203331701702000000000" + }, + "eee276140ea24e36eccb4fd748f675df1acd3b73": { + "balance": "1000000000000000000000000" + }, + "eefb33b290741c4cded862cea777efe4b14a76da": { + "balance": "64000000000000000000" + }, + "ef17a60d15ecf68a62b4bfd5e3acd6201e1931af": { + "balance": "113292502078000000000" + }, + "ef3f4df42127d3e94b4b5883ca97ee63f90b68b5": { + "balance": "17819622000000000000" + }, + "ef4aa6833a69cf72fbf3eaac57da236970aa4241": { + "balance": "1638520372091000000000" + }, + "ef958a1db06e5b8e12547148f3b01da9a8841aad": { + "balance": "12847752197000000000" + }, + "ef9fa861eefe12a3b4c161a47db5d94b1fa873a9": { + "balance": "49000000000000000000" + }, + "efd9b1ce6bc3932961e41e875edaaa367d318b36": { + "balance": "1626378762077000000000" + }, + "efdce7f577c77f0dac6afc78dcbf5ebadc1c3a73": { + "balance": "627500067619000000000" + }, + "eff3f26bc45638d89f28b3ea7a5471af0b680b72": { + "balance": "1650959950189000000000" + }, + "eff6d78814ddae79d6d09d830dd44de55f3f919d": { + "balance": "44409266093000000000" + }, + "eff739e22b9aeb3781dc301da70761fdd178f08f": { + "balance": "574842224234000000000" + }, + "f0059b3c8a32d3d012b4fcb993431a484b67762f": { + "balance": "516933429840000000000" + }, + "f06747d8e2c76b8827bbd0bf4ea3a68d390ee8f3": { + "balance": "8124594790100000000000" + }, + "f0e29fc0aecc36d1bdd818148878ea7d01957476": { + "balance": "79821431871000000000" + }, + "f0e42acf4e027aa61ac2f56e3d2c171ec0fd6ebf": { + "balance": "672499252575000000000" + }, + "f14338307bc5e6ab71fa202447ce240947568b3c": { + "balance": "13990001528784000000000" + }, + "f14f9a1206eb436a3d2e4ba9b3976137f67a6596": { + "balance": "1086707451000000000" + }, + "f15fcf1772fa5b2a578ce4f9270996430d533000": { + "balance": "496026996898000000000" + }, + "f18c691a5827ff1fdc44b54bd9a64fabd53c1cf4": { + "balance": "3112912699000000000000" + }, + "f1960640b52af75fc71101aec2611499c17cd9c6": { + "balance": "195957678178000000000" + }, + "f1abf01ddd474949713bd7fa67ec81d6b56c87b7": { + "balance": "121000000000000000000" + }, + "f1b93a6cfd4b1c7e0e89ebed119c5fe55af2035e": { + "balance": "1000000000000000000000000" + }, + "f1d14c7659a10ff38f4ea74ff5b07ac035984b6a": { + "balance": "9986323720000000000" + }, + "f1dbf37470a2c4fef98b1023026870ae8f7df2c0": { + "balance": "132757602000000000000" + }, + "f220b958b619d5d848597dd00824ab8b1401ebd2": { + "balance": "1461699635849000000000" + }, + "f2484911e0aa707f88d9dd970db21e8f24b9de2f": { + "balance": "20000000000000000000000" + }, + "f264c15790fd7a36d9ce7a454f6bfbe878708a50": { + "balance": "64000000000000000000" + }, + "f2662356cb3ae7b82efd6c82c3591ee40854892b": { + "balance": "50000000000000000000000" + }, + "f27ae5783b96ef637bde4179080a8f5af63ae692": { + "balance": "784985848611000000000" + }, + "f2a62fc212717e411f72f9a694e30b8da21bb31b": { + "balance": "614971541702000000000" + }, + "f2d0a9594231efb87ac833c365b80944251f29d7": { + "balance": "478622654587000000000" + }, + "f2df99a3df0b9b448d0ea48b9fd5cb1ce9ce50cf": { + "balance": "851116673037000000000" + }, + "f2dff0ae1f5f74808624e4f26fa814e4e19c216a": { + "balance": "404457730686000000000" + }, + "f2ea1ac6282364ad5904c6f058827a4382111d94": { + "balance": "5502482915000000000" + }, + "f2fafdcdb2d887eb13b5362eb76be2a682868643": { + "balance": "6174264174000000000" + }, + "f314adfc2fbf632a6e5d8a261385b6054aca31b6": { + "balance": "1267558242119000000000" + }, + "f31a66a88394ed7dd6609aff07dd26a60a219bd8": { + "balance": "346102834465000000000" + }, + "f3535f2b42d8613363e6d9717cc21a8ec3a74fe0": { + "balance": "35723093185103000000000" + }, + "f36a149466982c030ce3b9717f34b593613804d5": { + "balance": "10000000000000000000000" + }, + "f3828b0eaba4acfbbcf3c58277ceb4616a34b630": { + "balance": "633998941064000000000" + }, + "f38f767eeb8002ef051b32fe2f40193bf0751d92": { + "balance": "50000000000000000000000" + }, + "f39bce177817a7338b1adaf713222e515c0d762b": { + "balance": "1128231726329000000000" + }, + "f3ac7ea27a1cefc7787e5ba54dacfd8385ee4afc": { + "balance": "11364602682758000000000" + }, + "f3d9ea511335ed418b1837766da11832aedf5578": { + "balance": "29188596603509000000000" + }, + "f3ef05ccd19df167e06797d962f6afe16037e134": { + "balance": "144000000000000000000" + }, + "f3f630148eccea0ad7bd67bb806bd5676a4ea4cb": { + "balance": "87187208643000000000" + }, + "f3ff31784e0b8c3cd2f7e18cfd07c682a42d1c8d": { + "balance": "10515373125000000000" + }, + "f40b976e8519a2c97f64783bca495ed3f2e4a7c0": { + "balance": "780184503985000000000" + }, + "f416a3af7f3181ad9c8a916989949d35b0b636ec": { + "balance": "16114504005275000000000" + }, + "f419759927eea6afe77701c4cf4a98791a709ad1": { + "balance": "1032589347112000000000" + }, + "f4368f9c9ad8236b56413f174562d6b6fef21d1c": { + "balance": "5447645343000000000" + }, + "f43c57f984b0e2b7ce4d703e82f41195585504a4": { + "balance": "1135809111749000000000" + }, + "f4449f52895de96a4638c927dc389f010bbd530c": { + "balance": "693196063498000000000" + }, + "f449bd417a674c8bfa1db3a3e09c2b03da0f0c04": { + "balance": "106343287319000000000" + }, + "f44dec8340986c06d64dc98d78772a8a9cdc41ec": { + "balance": "1379381904815000000000" + }, + "f4642be1a7685aea0dc7b362d36f58f15d806b72": { + "balance": "4717509847323000000000" + }, + "f4712925f57391043e0cc2e671f33124a0bc8613": { + "balance": "419736833200000000000" + }, + "f47317fba5927dd8dffc4049d4f3277fcef503d6": { + "balance": "149279442682000000000" + }, + "f47ce4c5aaef82692e47f7a810ba38d1faec0eea": { + "balance": "10000000000000000000000" + }, + "f491ffc412bf142788bb82d48bd4eccbe9e0a286": { + "balance": "77276422315000000000" + }, + "f4a1e27e669c29f15b9f89ac15f702340a135743": { + "balance": "324000000000000000000" + }, + "f4b5cbfa50a6c4f5f7db7a93fa565362cc7aceac": { + "balance": "195951823248000000000" + }, + "f4b949c6e10615b651675016f0d7d6ff64e31aee": { + "balance": "35516207325223000000000" + }, + "f4c5e2f043ef3548a2c1c27d968087bec65e2f7d": { + "balance": "100000000000000000000000" + }, + "f4c79ea9c6f7297e016c39296d86f0304070c31d": { + "balance": "71036374423000000000" + }, + "f4dde3733a72872a7efc095cb412672c50928f1b": { + "balance": "129914864759880000000000" + }, + "f4ed736a413464eb93f8a430e093a64f0bd4222d": { + "balance": "10000000000000000000000" + }, + "f4f07e45560fb63d5207ed7e8d7cf4fe29e06d18": { + "balance": "293103814503448000000000" + }, + "f50eac35eef0a1bfa23ba31020ef60e89bf8e9df": { + "balance": "10000000000000000000000" + }, + "f51236dfd888929ccb2fe1f1fc5554abc5df4ce2": { + "balance": "25000000000000000000" + }, + "f521eb42e9092350f2ad4391ddb42bfe7abb4db9": { + "balance": "217462745186000000000" + }, + "f54e7062b6a9a8b283acf00fcbad58aca0737676": { + "balance": "7327357122437000000000" + }, + "f553301efd81629d0856d9c95c70f4a962e602ed": { + "balance": "1500355826530000000000" + }, + "f55c555b0991b2413f2f2764d8ed6a0d77825965": { + "balance": "1174679810163000000000" + }, + "f56ff110d521ceaec29dbf2842f1e78b24463cea": { + "balance": "20000000000000000000000" + }, + "f573fec366236ab87ba041f7dc6a88d92b1fc9b7": { + "balance": "4659857040000000000" + }, + "f59987743b239379aac9353e17e0e4442aa2c684": { + "balance": "25000000000000000000" + }, + "f5a9ca298e88c5492dd44a66d815b649c2f01d39": { + "balance": "95879585325000000000" + }, + "f5b4933164c55b5ba99db906ecaa52bba4f95164": { + "balance": "25663623936000000000" + }, + "f5d20af68c6fed98144718b6beab82fde00dfedc": { + "balance": "16000000000000000000" + }, + "f5e49ce72be9b17ff39688860e5cf6fd500a886c": { + "balance": "106142276914000000000" + }, + "f5f472405a4530075805fbc11928544770fd61fe": { + "balance": "64000000000000000000" + }, + "f62096c7305eb97b221bb637f4269246fe59262b": { + "balance": "855993602798000000000" + }, + "f622bf9b8f7be2f75d5ed73d318a0e7fa62a587f": { + "balance": "20000000000000000000000" + }, + "f6231f31d524ccc444bd046123ba33bc224bdd52": { + "balance": "97550810879000000000" + }, + "f641b4a721dcefa497274fd06888eb998b9bc038": { + "balance": "39401014566340000000000" + }, + "f64f0c5172c99d74b2450a4685c3ec715b379922": { + "balance": "28337413668000000000" + }, + "f65841061cd55cbf20843d9594bce9ee133aa644": { + "balance": "9064540188290000000000" + }, + "f65f0106f3d148d0660547f0683ded4dffc12fe9": { + "balance": "87334071785367000000000" + }, + "f677961296ed933db9e1dd887711387540c0436d": { + "balance": "3982789899000000000" + }, + "f68ba7530f423b8df1625cee36f8df2363a57c49": { + "balance": "5000000000000000000000" + }, + "f69c6eaf077b795f19a9590ee8b578543558e4c4": { + "balance": "10000000000000000000000" + }, + "f69dfe3f0f76e50e2850e44e9e36b6966e277eaa": { + "balance": "288231750575462000000000" + }, + "f6a73c4b958b4d6044f3f4da7147d0fa80e2ea31": { + "balance": "50000000000000000000000" + }, + "f6b0864be5f7bbc4210a3420aa3ead614a8fe7e2": { + "balance": "880968828000000000" + }, + "f6f43a6d9517471436d2ce5047a2b707580e7149": { + "balance": "20000000000000000000000" + }, + "f6fb414d1ca7c29be35b5f97096c817bbf70b070": { + "balance": "15156317416682000000000" + }, + "f707b491ac27b2d2e5e1f9d4123635ee0af92c5c": { + "balance": "500000000000000000000000" + }, + "f71179583a471767a1b399842d7d29caefe57a5e": { + "balance": "429648186876000000000" + }, + "f71ed909eca6bfd574cd670389bc9250493d686d": { + "balance": "38189267531000000000" + }, + "f72ccdc70b7878cdb94f42ee72ca5b4b35a46238": { + "balance": "86065647347000000000" + }, + "f74035e85dbfdb961037bf689ee7dfdcfaf32d64": { + "balance": "398451682882000000000" + }, + "f77668db085a87b0a0405a275e1c2516d3e02b66": { + "balance": "10000000000000000000000" + }, + "f78990d9e50876b49f933e9d74bda44197e9aa7d": { + "balance": "51984216556000000000" + }, + "f79b9df28b7d94d1b4491fca1cbe50bd36aedb3a": { + "balance": "11546152485156000000000" + }, + "f7c773b89be413848dc4a96f064693a0c3a2eab0": { + "balance": "7084247258755000000000" + }, + "f7e29c20bb0023e9ae079da589346fdfd960dae3": { + "balance": "93132014782000000000" + }, + "f8124428ea619d30a335ecc4c2f64e36500abdcb": { + "balance": "8838170798391000000000" + }, + "f843c9d70226e6c2c8cd4cef78e2db66a8eac027": { + "balance": "498377670361000000000" + }, + "f84bb3c0d872dcdbe99d6abcc57c6b5c2b2e35ad": { + "balance": "1405105232436000000000" + }, + "f8679b915ae94e4668f2e27d1094cbb2d97cf428": { + "balance": "1000000000000000000" + }, + "f86dbb82c634cdfa818e4d0dbcfcc9a5c47a9ddb": { + "balance": "196000000000000000000" + }, + "f88bad7726aa66bc1d0ca5824044072f3551fd15": { + "balance": "37432374800000000000" + }, + "f8ab07d0751a2c283ebe2a7e28c5b6e57867e1d1": { + "balance": "25000000000000000000" + }, + "f8afb4f5684c56ff7ce71b4e4cf7e42062470e08": { + "balance": "10000000000000000000000" + }, + "f8c28df0d1a0982289ddfa2a6d562e5c75a5dd01": { + "balance": "1447386977682000000000" + }, + "f8cca137f9c12b48eafd43f038e55e2d3c481919": { + "balance": "35370515421000000000" + }, + "f8e50d1816a5e5c649756ae208209b03b1ece0c3": { + "balance": "48449640035000000000" + }, + "f8fb33ba1d93112d9c3672806e0939083f09a88e": { + "balance": "419743187776000000000" + }, + "f903bebfcc6a7050fc2c5bd14248af9b300f1600": { + "balance": "473363252199000000000" + }, + "f90ab9078f26dd881fb054b4b6e3b3e17fa94718": { + "balance": "156449634345000000000" + }, + "f93e3f392efc057f0af3a91416858a515c1ed996": { + "balance": "1147663044625000000000" + }, + "f94eac538ca66931869c312acb67721c4337842f": { + "balance": "368103335377000000000" + }, + "f94fda503c3f792491fa77b3702fd465f028810d": { + "balance": "317241487661000000000" + }, + "f95dcedbefee8ed01086c91d91a4c115ad8fc947": { + "balance": "147059838786000000000" + }, + "f961a293bbce366a6fcc98d2ba0342e2ef3c5519": { + "balance": "10000000000000000000000" + }, + "f966fdbc4a42f055f8f52d31c23ad7b6a07a5e22": { + "balance": "10000000000000000000000" + }, + "f9a3a61a2f1469835240bb0641eae40c07451e30": { + "balance": "218000000000000" + }, + "f9adcf232180378b08a46d6c8d9d97f01802e01b": { + "balance": "15658216517944000000000" + }, + "f9c68991ff7ac307e41ea1c673f8ebb1a6afbd99": { + "balance": "10000000000000000000000" + }, + "f9cc0c60431d7bdb0c7581a9ae7f011b0abefeb1": { + "balance": "16000000000000000000" + }, + "f9d43c329b61ca2169600e45c8fad3c94226adb8": { + "balance": "120128558137000000000" + }, + "f9ef5d4e2ca8888216b939d3d938438a34dd9da2": { + "balance": "144000000000000000000" + }, + "f9f3d14cd3bd09e2c4c89035b4f50e93f6175cef": { + "balance": "725000000000000000000" + }, + "fa0f5a03601bd1fc76865cdd69d9671ba6073592": { + "balance": "225298289139000000000" + }, + "fa12f10db0eb552b719194becef20af9f45de8db": { + "balance": "1012484659496000000000" + }, + "fa146c58a0709951bc2e9bccddcd002c5a0bb7dd": { + "balance": "199563276701000000000" + }, + "fa159185c156f35fa450b77c48846c2dab6349b7": { + "balance": "100660066567000000000" + }, + "fa193312655f79c7b0ee7d7ef904486836180026": { + "balance": "48141690266000000000" + }, + "fa2484de744918bd8c91350fbabc0dab8b8a44f0": { + "balance": "36000000000000000000" + }, + "fa36dc463b026d8edfeb8ac4acac43a51d643457": { + "balance": "9608761064478000000000" + }, + "fa84199010be2bf53e803c23771e0d15fd025386": { + "balance": "1474902394742000000000" + }, + "fa958bbfa367a745bcd0904db2c4e30445edaefb": { + "balance": "175679888121000000000" + }, + "fa98bcaeb55285ad7ead12ccaa15cf488f567ede": { + "balance": "136105143781000000000" + }, + "faa1be631da42b41a026774f4166c1b831ef41e9": { + "balance": "86358861589000000000" + }, + "faaa857e7f149968434f313ab8db596e1b0ae75d": { + "balance": "36000000000000000000" + }, + "fac2b85ab274055cf1415d57394e8aca4541857d": { + "balance": "289000000000000000000" + }, + "fb23a508ccdb4e91b252f5c06c465c55ed59b1db": { + "balance": "14698710175236000000000" + }, + "fb24d4e47ba70aa4b984372b4852ad3d082daa24": { + "balance": "4526648424830000000000" + }, + "fb27a7e8b8b4ae43c69ce025b46187e538608769": { + "balance": "121000000000000000000" + }, + "fb2cdb5e85872f52c99985f219b8fb4125c6a8b7": { + "balance": "8568367153000000000" + }, + "fb3d76c8165bcb3c93fd3b2b10c20588d0fa97aa": { + "balance": "500000000000000000000000" + }, + "fb5161b2cc9d48a53f47d66002905f0458e3cd9e": { + "balance": "225000000000000000000" + }, + "fb72756c4845f18ab35d29f632b662c0c0d4b94f": { + "balance": "883095068524000000000" + }, + "fb8b7efb02ea5292304c0f0abc8c555684653587": { + "balance": "10000000000000000000000" + }, + "fb9ee61e337a5c7b57c5140e84919101570e2cb7": { + "balance": "16000000000000000000" + }, + "fbae69f44b116c186a86cb0de79323ca3d6b99eb": { + "balance": "1359504686067000000000" + }, + "fbbd399eb9e5d3dd67efc48927973601dcd84321": { + "balance": "2049018637367000000000" + }, + "fbc9a3c3c429990cc306710b3dd44174dcc72ad4": { + "balance": "55507457947000000000" + }, + "fbce66a6898ecd70893db6b4b8c3d00afef8e20b": { + "balance": "20857164902458000000000" + }, + "fbe8fe04084fc93dff8228861fe100bfeeb057b6": { + "balance": "10000000000000000000000" + }, + "fbfb717f902ad79ef63565f9ab57f041ff5f7626": { + "balance": "16000000000000000000" + }, + "fc0b6c8c6be79bf0c9554f7855dc8c4a617d02c9": { + "balance": "17347593956000000000" + }, + "fc17518d05e605807847bbf6f407da89037bca00": { + "balance": "1796383702108000000000" + }, + "fc2793424c809cc80938a1be1292813adbc8ac8c": { + "balance": "10000000000000000000" + }, + "fc35930abb108ae6cae33fd065dfb799808ea326": { + "balance": "912737460000000000000" + }, + "fc5a9209799e563ae8d958774dc86345a3bc7ed2": { + "balance": "29049176573000000000" + }, + "fc8011850c09c9288e737ea58ca5c15cded6dc8d": { + "balance": "10000000000000000000000" + }, + "fc9183ed137be071ad183d025395a0ebe2674654": { + "balance": "500000000000000000000000" + }, + "fc98c9d88b1fbbb68dbdd6448aa6a32e8282800d": { + "balance": "900000000000000000000" + }, + "fc9f4b9da7a46c2bfcd50cafe1f892b9984be0ee": { + "balance": "21577116424370000000000" + }, + "fca525b732a673b953f1c23083c276cc8cbcb86c": { + "balance": "77653618624000000000" + }, + "fca57b6a4798f33478b6e23622173cda3fe1b9a0": { + "balance": "793368066098000000000" + }, + "fca79b446c513a7bed643603c42f35ff0fa89f49": { + "balance": "998082799053000000000" + }, + "fcab42f7f07735a7b09074c1f1769287069c88c8": { + "balance": "94824830574000000000" + }, + "fcacbbc6810c586522012ad32c3dfac80eb563b4": { + "balance": "10000000000000000000000" + }, + "fcb38809b63810b6673dcb4c947e01f7b49fb1b3": { + "balance": "725937240372000000000" + }, + "fcc0e531d9f6265672aa885af361534464a11015": { + "balance": "22121462657000000000" + }, + "fcc49c62d7738fa1b92aa6a69a12b671e4c7c8d9": { + "balance": "50000000000000000000000" + }, + "fcc95394fd796ca5bd8f3814883b1150d74dd9a5": { + "balance": "144000000000000000000" + }, + "fccdb068dfd599d7d5c290a6ae65eba9151d5b29": { + "balance": "5369426564000000000" + }, + "fcde41ae28bdf9084a28f47a9348d8aac5b3dd43": { + "balance": "409599263197000000000" + }, + "fce5816f066ca32d1fa02e9e8b5eb8a7fa3e4dea": { + "balance": "1193272309645000000000" + }, + "fcf9fb8996d6d9175ade6d6063be0742de20ea1f": { + "balance": "16852526239339000000000" + }, + "fd10488d55e6861cb67f7f50950d78892e7032ad": { + "balance": "165069902909000000000" + }, + "fd23e8263d89256add0dfe93da153d305ad917c7": { + "balance": "26633825496000000000" + }, + "fd3a98cc3b3f1439af35f806de2fb05fef98f279": { + "balance": "1043321187464000000000" + }, + "fd3d79185a91984a117ee6f9fd304725875094e2": { + "balance": "2349991833898000000000" + }, + "fd5e6ac22634f04ec4ace5da8996c2b7b70b22f4": { + "balance": "10000000000000000" + }, + "fd62ed1cf7a535c989fbd742b1660205a2f69dd0": { + "balance": "49000000000000000000" + }, + "fd645043bd4d7b71e63e30409b91e9fdda3a86c0": { + "balance": "362957768837969000000000" + }, + "fd7014fc1c70af482115247ff94ff6bdbd3d364d": { + "balance": "743383172317000000000" + }, + "fda0cfe95df9021497752b04863c3ec44d13e853": { + "balance": "15586809617955000000000" + }, + "fdb5b964808bcb974d3e888cbb45bcd57e57c907": { + "balance": "5549247772273000000000" + }, + "fdbaaa865ec38da13e80554b6d0abc437f60d8a5": { + "balance": "3736861227131000000000" + }, + "fdbb8693b3c20c0eac5fb585e2347d41debbffce": { + "balance": "100000000000000000" + }, + "fdbdaec57829f25ad48e18d94e0b8533f2801818": { + "balance": "6934630922926000000000" + }, + "fdc318ba5b1f8ad33e00528828b93a840592e2fb": { + "balance": "10000000000000000000000" + }, + "fdcf6a997bb10806e4d87eb4222e9f93b4202179": { + "balance": "1000000000000000000" + }, + "fde5a9911a10770d733db4d32ca9a5493478399c": { + "balance": "20000000000000000000000" + }, + "fe39185a6b84378820ee215f630533e658731ca9": { + "balance": "17022202932000000000" + }, + "fe3b1032e524674cba5f329f940c837850fa53ed": { + "balance": "50000000000000000000000" + }, + "fe3bc4ff2c3b66bc582558314b80030407e7de96": { + "balance": "1669870860988000000000" + }, + "fe668dbb1f3de744d16e13e0ed6f5708c2c15d1f": { + "balance": "39974355655263000000000" + }, + "fe95bfb97fa60341f8af2ad621e606b85e3c2e57": { + "balance": "528601649597478000000000" + }, + "fe99cf2a1fbbe7c46e4235b2d135a3a093fcf16c": { + "balance": "7271022106877000000000" + }, + "fec1f6ed4b3ff01e7ebe13fb53f60ee5a3b9e191": { + "balance": "1316316072034000000000" + }, + "fed9bec1b2145452ed5535e4ba29fafac6c35fbb": { + "balance": "10799354586000000000" + }, + "fedced7aa1cf3f3a7eec321cc0274759b154ea8e": { + "balance": "11740927210323000000000" + }, + "fef5063701a93ad02676fe0b99d0f4d2da0ccd67": { + "balance": "10178531012000000000" + }, + "fefd5627a408ca099587892ee2a46fa8cc89be19": { + "balance": "458504035686000000000" + }, + "ff1fc0f6f26188cbe18cf65d8a344d3775aecc6d": { + "balance": "81000000000000000000" + }, + "ff4fe483b3c04ebc8d6705c699ecee3e92071715": { + "balance": "1000000000000000000" + }, + "ff51bfe823394b2bce05947a6068bd5158d4af0e": { + "balance": "692533626783000000000" + }, + "ff6652e4e45f6b0f95ad4c9ec2bc80476e3f7fc6": { + "balance": "46457898024000000000" + }, + "ff68246ac7640091e5e58345736b249e036364fc": { + "balance": "2626125272000000000" + }, + "ff6d4b8a8393a503047ff829dbf2bf8e9172dc6d": { + "balance": "2865001878255000000000" + }, + "ff6fe19e056a7211b7e484c2c540d5aa5f1d83e5": { + "balance": "36000000000000000000" + }, + "ff7fa33529e1781c1b2951e57581780b229e3fda": { + "balance": "10000000000000000000" + }, + "ff82d1052538539d07cf3955476cc9a5027d8e4e": { + "balance": "83572023121000000000" + }, + "ff8acfe75afcc1efb1bc44be9f9bb242a94f73f7": { + "balance": "7556034521000000000" + }, + "ffa2b5f1685de9fcf1af4653cd3a584db1beed64": { + "balance": "114892199805000000000" + }, + "ffb1e9be68ae8be8d7d066c473589921e68825a2": { + "balance": "484660652980000000000" + }, + "ffbf91a9d1a6377b7435e3e734132e7b34188dac": { + "balance": "20000000000000000000000" + }, + "ffbff1fab9f2bc2f387d0cc9cc28f6aac533c813": { + "balance": "10000000000000000000000" + }, + "ffc4ff6433ea35544e7a07fda170e62c451301df": { + "balance": "29238210920000000000" + }, + "ffc7534b64a8fe8760e931a710883119d28ae106": { + "balance": "500000000000000000000000" + }, + "ffda6b8e3de72d7f7c18b892e6a8b80b886d5fa5": { + "balance": "214366938289000000000" + }, + "ffddb1fb7521c9772ea4886aaf022c4375ef904d": { + "balance": "554864446437000000000" + } + } } diff --git a/ethcore/res/ethereum/transition_test.json b/ethcore/res/ethereum/transition_test.json index 7c18fce4e54..9dc00fd5d8c 100644 --- a/ethcore/res/ethereum/transition_test.json +++ b/ethcore/res/ethereum/transition_test.json @@ -8,10 +8,6 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "homesteadTransition": "0", - "eip150Transition": "0", - "eip160Transition": "0", - "eip161abcTransition": "0", - "eip161dTransition": "0", "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": "5", "eip649Transition": "5" @@ -27,6 +23,10 @@ "networkID" : "0x1", "maxCodeSize": 24576, "maxCodeSizeTransition": "0", + "eip150Transition": "0", + "eip160Transition": "0", + "eip161abcTransition": "0", + "eip161dTransition": "0", "eip98Transition": "5", "eip140Transition": "5", "eip211Transition": "5", diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index 1bd3805ef3b..9c6db25cbca 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -46,14 +46,6 @@ pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]); pub struct EthashExtensions { /// Homestead transition block number. pub homestead_transition: BlockNumber, - /// EIP150 transition block number. - pub eip150_transition: BlockNumber, - /// Number of first block where EIP-160 rules begin. - pub eip160_transition: u64, - /// Number of first block where EIP-161.abc begin. - pub eip161abc_transition: u64, - /// Number of first block where EIP-161.d begins. - pub eip161d_transition: u64, /// DAO hard-fork transition block (X). pub dao_hardfork_transition: u64, /// DAO hard-fork refund contract address (C). @@ -66,10 +58,6 @@ impl From<::ethjson::spec::EthashParams> for EthashExtensions { fn from(p: ::ethjson::spec::EthashParams) -> Self { EthashExtensions { homestead_transition: p.homestead_transition.map_or(0, Into::into), - eip150_transition: p.eip150_transition.map_or(0, Into::into), - eip160_transition: p.eip160_transition.map_or(0, Into::into), - eip161abc_transition: p.eip161abc_transition.map_or(0, Into::into), - eip161d_transition: p.eip161d_transition.map_or(u64::max_value(), Into::into), dao_hardfork_transition: p.dao_hardfork_transition.map_or(u64::max_value(), Into::into), dao_hardfork_beneficiary: p.dao_hardfork_beneficiary.map_or_else(Address::new, Into::into), dao_hardfork_accounts: p.dao_hardfork_accounts.unwrap_or_else(Vec::new).into_iter().map(Into::into).collect(), @@ -267,19 +255,8 @@ impl EthereumMachine { Some(ref ext) => { if block_number < ext.homestead_transition { Schedule::new_frontier() - } else if block_number < ext.eip150_transition { - Schedule::new_homestead() } else { - let max_code_size = self.params.max_code_size(block_number); - let mut schedule = Schedule::new_post_eip150( - max_code_size as _, - block_number >= ext.eip160_transition, - block_number >= ext.eip161abc_transition, - block_number >= ext.eip161d_transition - ); - - self.params.update_schedule(block_number, &mut schedule); - schedule + self.params.schedule(block_number) } } }; @@ -503,10 +480,6 @@ mod tests { fn get_default_ethash_extensions() -> EthashExtensions { EthashExtensions { homestead_transition: 1150000, - eip150_transition: u64::max_value(), - eip160_transition: u64::max_value(), - eip161abc_transition: u64::max_value(), - eip161d_transition: u64::max_value(), dao_hardfork_transition: u64::max_value(), dao_hardfork_beneficiary: "0000000000000000000000000000000000000001".into(), dao_hardfork_accounts: Vec::new(), diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 1ee8cf70323..fa25c8894eb 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -78,6 +78,14 @@ pub struct CommonParams { pub min_gas_limit: U256, /// Fork block to check. pub fork_block: Option<(BlockNumber, H256)>, + /// EIP150 transition block number. + pub eip150_transition: BlockNumber, + /// Number of first block where EIP-160 rules begin. + pub eip160_transition: u64, + /// Number of first block where EIP-161.abc begin. + pub eip161abc_transition: u64, + /// Number of first block where EIP-161.d begins. + pub eip161d_transition: u64, /// Number of first block where EIP-98 rules begin. pub eip98_transition: BlockNumber, /// Number of first block where EIP-658 rules begin. @@ -134,9 +142,20 @@ pub struct CommonParams { impl CommonParams { /// Schedule for an EVM in the post-EIP-150-era of the Ethereum main net. pub fn schedule(&self, block_number: u64) -> ::vm::Schedule { - let mut schedule = ::vm::Schedule::new_post_eip150(self.max_code_size(block_number) as _, true, true, true); - self.update_schedule(block_number, &mut schedule); - schedule + if block_number < self.eip150_transition { + ::vm::Schedule::new_homestead() + } else { + let max_code_size = self.max_code_size(block_number); + let mut schedule = ::vm::Schedule::new_post_eip150( + max_code_size as _, + block_number >= self.eip160_transition, + block_number >= self.eip161abc_transition, + block_number >= self.eip161d_transition + ); + + self.update_schedule(block_number, &mut schedule); + schedule + } } /// Returns max code size at given block. @@ -197,6 +216,10 @@ impl From for CommonParams { } else { None }, + eip150_transition: p.eip150_transition.map_or(0, Into::into), + eip160_transition: p.eip160_transition.map_or(0, Into::into), + eip161abc_transition: p.eip161abc_transition.map_or(0, Into::into), + eip161d_transition: p.eip161d_transition.map_or(0, Into::into), eip98_transition: p.eip98_transition.map_or(0, Into::into), eip155_transition: p.eip155_transition.map_or(0, Into::into), validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into), diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index afa8b596823..66f6913e578 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -73,21 +73,6 @@ pub struct EthashParams { #[serde(rename="eip100bTransition")] pub eip100b_transition: Option, - /// See main EthashParams docs. - #[serde(rename="eip150Transition")] - pub eip150_transition: Option, - - /// See main EthashParams docs. - #[serde(rename="eip160Transition")] - pub eip160_transition: Option, - - /// See main EthashParams docs. - #[serde(rename="eip161abcTransition")] - pub eip161abc_transition: Option, - /// See main EthashParams docs. - #[serde(rename="eip161dTransition")] - pub eip161d_transition: Option, - /// See main EthashParams docs. #[serde(rename="ecip1010PauseTransition")] pub ecip1010_pause_transition: Option, @@ -190,11 +175,7 @@ mod tests { "difficultyHardforkTransition": "0x59d9", "difficultyHardforkBoundDivisor": "0x0200", "bombDefuseTransition": "0x41", - "eip100bTransition": "0x42", - "eip150Transition": "0x43", - "eip160Transition": "0x45", - "eip161abcTransition": "0x46", - "eip161dTransition": "0x47" + "eip100bTransition": "0x42" } }"#; @@ -237,10 +218,6 @@ mod tests { difficulty_hardfork_bound_divisor: Some(Uint(U256::from(0x0200))), bomb_defuse_transition: Some(Uint(U256::from(0x41))), eip100b_transition: Some(Uint(U256::from(0x42))), - eip150_transition: Some(Uint(U256::from(0x43))), - eip160_transition: Some(Uint(U256::from(0x45))), - eip161abc_transition: Some(Uint(U256::from(0x46))), - eip161d_transition: Some(Uint(U256::from(0x47))), ecip1010_pause_transition: None, ecip1010_continue_transition: None, ecip1017_era_rounds: None, @@ -285,10 +262,6 @@ mod tests { difficulty_hardfork_bound_divisor: None, bomb_defuse_transition: None, eip100b_transition: None, - eip150_transition: None, - eip160_transition: None, - eip161abc_transition: None, - eip161d_transition: None, ecip1010_pause_transition: None, ecip1010_continue_transition: None, ecip1017_era_rounds: None, diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 0addf52e4af..f171a881019 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -51,6 +51,21 @@ pub struct Params { #[serde(rename="forkCanonHash")] pub fork_hash: Option, + /// See main EthashParams docs. + #[serde(rename="eip150Transition")] + pub eip150_transition: Option, + + /// See main EthashParams docs. + #[serde(rename="eip160Transition")] + pub eip160_transition: Option, + + /// See main EthashParams docs. + #[serde(rename="eip161abcTransition")] + pub eip161abc_transition: Option, + /// See main EthashParams docs. + #[serde(rename="eip161dTransition")] + pub eip161d_transition: Option, + /// See `CommonParams` docs. #[serde(rename="eip98Transition")] pub eip98_transition: Option, From 84ecab0eaf96149be75ee127aef37d0cb0f2c4bb Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 22 May 2018 06:32:05 +0200 Subject: [PATCH 88/95] Remove HostInfo::client_version() and secret() (#8677) --- util/network-devp2p/src/handshake.rs | 3 ++- util/network-devp2p/src/host.rs | 14 +++++++------- util/network/src/lib.rs | 4 ---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/util/network-devp2p/src/handshake.rs b/util/network-devp2p/src/handshake.rs index a203af5b4b4..7aef4d4f0d7 100644 --- a/util/network-devp2p/src/handshake.rs +++ b/util/network-devp2p/src/handshake.rs @@ -26,7 +26,8 @@ use node_table::NodeId; use io::{IoContext, StreamToken}; use ethkey::{KeyPair, Public, Secret, recover, sign, Generator, Random}; use ethkey::crypto::{ecdh, ecies}; -use network::{Error, ErrorKind, HostInfo}; +use network::{Error, ErrorKind, HostInfo as HostInfoTrait}; +use host::HostInfo; #[derive(PartialEq, Eq, Debug)] enum HandshakeState { diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index f3446845fb1..5ccab2e4db2 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -215,19 +215,19 @@ impl HostInfo { self.nonce = keccak(&self.nonce); self.nonce } -} -impl HostInfoTrait for HostInfo { - fn id(&self) -> &NodeId { - self.keys.public() + pub(crate) fn client_version(&self) -> &str { + &self.config.client_version } - fn secret(&self) -> &Secret { + pub(crate) fn secret(&self) -> &Secret { self.keys.secret() } +} - fn client_version(&self) -> &str { - &self.config.client_version +impl HostInfoTrait for HostInfo { + fn id(&self) -> &NodeId { + self.keys.public() } } diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index 0137543fdd5..d16403cd34e 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -330,10 +330,6 @@ impl<'a, T> NetworkContext for &'a T where T: ?Sized + NetworkContext { pub trait HostInfo { /// Returns public key fn id(&self) -> &NodeId; - /// Returns secret key - fn secret(&self) -> &Secret; - /// Returns the client version. - fn client_version(&self) -> &str; } /// Network IO protocol handler. This needs to be implemented for each new subprotocol. From ee41fa6f30fe275977265c7e139b4841ab47c725 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 22 May 2018 06:34:01 +0200 Subject: [PATCH 89/95] Move connection_filter to the network crate (#8674) --- Cargo.lock | 1 + ethcore/node_filter/Cargo.toml | 1 + ethcore/node_filter/src/lib.rs | 6 ++++-- ethcore/sync/src/api.rs | 5 +++-- ethcore/sync/src/lib.rs | 4 ++-- util/network-devp2p/src/host.rs | 2 +- util/network-devp2p/src/lib.rs | 2 -- util/network-devp2p/src/service.rs | 2 +- util/{network-devp2p => network}/src/connection_filter.rs | 0 util/network/src/lib.rs | 2 ++ 10 files changed, 15 insertions(+), 10 deletions(-) rename util/{network-devp2p => network}/src/connection_filter.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index e2fa0a9db8f..646bc906456 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1805,6 +1805,7 @@ dependencies = [ "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-io 1.12.0", + "ethcore-network 1.12.0", "ethcore-network-devp2p 1.12.0", "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb-memorydb 0.1.0", diff --git a/ethcore/node_filter/Cargo.toml b/ethcore/node_filter/Cargo.toml index 25b5ec59f4e..0d204e29ff8 100644 --- a/ethcore/node_filter/Cargo.toml +++ b/ethcore/node_filter/Cargo.toml @@ -8,6 +8,7 @@ authors = ["Parity Technologies "] [dependencies] ethcore = { path = ".."} +ethcore-network = { path = "../../util/network" } ethcore-network-devp2p = { path = "../../util/network-devp2p" } ethereum-types = "0.3" log = "0.3" diff --git a/ethcore/node_filter/src/lib.rs b/ethcore/node_filter/src/lib.rs index 715b7ae3e98..c731ad356ad 100644 --- a/ethcore/node_filter/src/lib.rs +++ b/ethcore/node_filter/src/lib.rs @@ -18,7 +18,8 @@ extern crate ethabi; extern crate ethcore; -extern crate ethcore_network_devp2p as network; +extern crate ethcore_network as network; +extern crate ethcore_network_devp2p as devp2p; extern crate ethereum_types; extern crate lru_cache; extern crate parking_lot; @@ -43,7 +44,8 @@ use parking_lot::Mutex; use ethcore::client::{BlockChainClient, BlockId}; use ethereum_types::{H256, Address}; -use network::{NodeId, ConnectionFilter, ConnectionDirection}; +use network::{ConnectionFilter, ConnectionDirection}; +use devp2p::NodeId; use_contract!(peer_set, "PeerSet", "res/peer_set.json"); diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index e901528e411..56ea8526edf 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -19,9 +19,10 @@ use std::collections::{HashMap, BTreeMap}; use std::io; use std::time::Duration; use bytes::Bytes; -use devp2p::{NetworkService, ConnectionFilter}; +use devp2p::NetworkService; use network::{NetworkProtocolHandler, NetworkContext, HostInfo, PeerId, ProtocolId, - NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind}; + NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind, + ConnectionFilter}; use ethereum_types::{H256, H512, U256}; use io::{TimerToken}; use ethcore::ethstore::ethkey::Secret; diff --git a/ethcore/sync/src/lib.rs b/ethcore/sync/src/lib.rs index 3eb2e8332b4..c00ea5e4404 100644 --- a/ethcore/sync/src/lib.rs +++ b/ethcore/sync/src/lib.rs @@ -74,6 +74,6 @@ mod api; pub use api::*; pub use chain::{SyncStatus, SyncState}; -pub use devp2p::{validate_node_url, ConnectionFilter, ConnectionDirection}; -pub use network::{NonReservedPeerMode, Error, ErrorKind}; +pub use devp2p::validate_node_url; +pub use network::{NonReservedPeerMode, Error, ErrorKind, ConnectionFilter, ConnectionDirection}; pub use private_tx::{PrivateTxHandler, NoopPrivateTxHandler, SimplePrivateTxHandler}; diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index 5ccab2e4db2..3ab7b7f849c 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -45,7 +45,7 @@ use discovery::{Discovery, TableUpdates, NodeEntry}; use ip_utils::{map_external_address, select_public_address}; use path::restrict_permissions_owner; use parking_lot::{Mutex, RwLock}; -use connection_filter::{ConnectionFilter, ConnectionDirection}; +use network::{ConnectionFilter, ConnectionDirection}; type Slab = ::slab::Slab; diff --git a/util/network-devp2p/src/lib.rs b/util/network-devp2p/src/lib.rs index e5bb95f2207..244997a6545 100644 --- a/util/network-devp2p/src/lib.rs +++ b/util/network-devp2p/src/lib.rs @@ -106,10 +106,8 @@ mod discovery; mod service; mod node_table; mod ip_utils; -mod connection_filter; pub use service::NetworkService; -pub use connection_filter::{ConnectionFilter, ConnectionDirection}; pub use host::NetworkContext; pub use io::TimerToken; diff --git a/util/network-devp2p/src/service.rs b/util/network-devp2p/src/service.rs index 10a1e9abc85..3ac1ec7f717 100644 --- a/util/network-devp2p/src/service.rs +++ b/util/network-devp2p/src/service.rs @@ -21,7 +21,7 @@ use io::*; use parking_lot::RwLock; use std::sync::Arc; use ansi_term::Colour; -use connection_filter::ConnectionFilter; +use network::ConnectionFilter; struct HostHandler { public_url: RwLock> diff --git a/util/network-devp2p/src/connection_filter.rs b/util/network/src/connection_filter.rs similarity index 100% rename from util/network-devp2p/src/connection_filter.rs rename to util/network/src/connection_filter.rs diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index d16403cd34e..f3012e4c376 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -27,8 +27,10 @@ extern crate snappy; #[macro_use] extern crate error_chain; +mod connection_filter; mod error; +pub use connection_filter::{ConnectionFilter, ConnectionDirection}; pub use io::TimerToken; pub use error::{Error, ErrorKind, DisconnectReason}; From fe5f5b28d9be6b894545cfbbb42580068e14524b Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 22 May 2018 06:35:13 +0200 Subject: [PATCH 90/95] Remove the error when stopping the network (#8671) --- ethcore/sync/src/api.rs | 6 ++---- util/io/src/service_mio.rs | 10 ++++++---- util/network-devp2p/src/host.rs | 5 ++--- util/network-devp2p/src/service.rs | 7 +++---- util/network-devp2p/tests/tests.rs | 2 +- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/ethcore/sync/src/api.rs b/ethcore/sync/src/api.rs index 56ea8526edf..2f90e410aed 100644 --- a/ethcore/sync/src/api.rs +++ b/ethcore/sync/src/api.rs @@ -475,7 +475,7 @@ impl ChainNotify for EthSync { fn stop(&self) { self.eth_handler.snapshot_service.abort_restore(); - self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e)); + self.network.stop(); } fn broadcast(&self, message_type: ChainMessageType) { @@ -833,9 +833,7 @@ impl ManageNetwork for LightSync { fn stop_network(&self) { self.proto.abort(); - if let Err(e) = self.network.stop() { - warn!("Error stopping network: {}", e); - } + self.network.stop(); } fn network_config(&self) -> NetworkConfiguration { diff --git a/util/io/src/service_mio.rs b/util/io/src/service_mio.rs index f7c9f1976cf..2ae3d55e0ff 100644 --- a/util/io/src/service_mio.rs +++ b/util/io/src/service_mio.rs @@ -162,11 +162,13 @@ impl IoContext where Message: Send + Sync + 'static { } /// Unregister current IO handler. - pub fn unregister_handler(&self) -> Result<(), IoError> { - self.channel.send_io(IoMessage::RemoveHandler { + pub fn unregister_handler(&self) { + // `send_io` returns an error only if the channel is closed, which means that the + // background thread is no longer running. Therefore the handler is no longer active and + // can be considered as unregistered. + let _ = self.channel.send_io(IoMessage::RemoveHandler { handler_id: self.handler, - })?; - Ok(()) + }); } } diff --git a/util/network-devp2p/src/host.rs b/util/network-devp2p/src/host.rs index 3ab7b7f849c..fbbeb89ff8e 100644 --- a/util/network-devp2p/src/host.rs +++ b/util/network-devp2p/src/host.rs @@ -396,7 +396,7 @@ impl Host { format!("{}", Node::new(info.id().clone(), info.local_endpoint.clone())) } - pub fn stop(&self, io: &IoContext) -> Result<(), Error> { + pub fn stop(&self, io: &IoContext) { self.stopping.store(true, AtomicOrdering::Release); let mut to_kill = Vec::new(); for e in self.sessions.read().iter() { @@ -408,8 +408,7 @@ impl Host { trace!(target: "network", "Disconnecting on shutdown: {}", p); self.kill_connection(p, io, true); } - io.unregister_handler()?; - Ok(()) + io.unregister_handler(); } /// Get all connected peers. diff --git a/util/network-devp2p/src/service.rs b/util/network-devp2p/src/service.rs index 3ac1ec7f717..eb2e9685d42 100644 --- a/util/network-devp2p/src/service.rs +++ b/util/network-devp2p/src/service.rs @@ -125,15 +125,14 @@ impl NetworkService { Ok(()) } - /// Stop network IO - pub fn stop(&self) -> Result<(), Error> { + /// Stop network IO. + pub fn stop(&self) { let mut host = self.host.write(); if let Some(ref host) = *host { let io = IoContext::new(self.io_service.channel(), 0); //TODO: take token id from host - host.stop(&io)?; + host.stop(&io); } *host = None; - Ok(()) } /// Get a list of all connected peers by id. diff --git a/util/network-devp2p/tests/tests.rs b/util/network-devp2p/tests/tests.rs index e8c8eddde4b..a1d178d6544 100644 --- a/util/network-devp2p/tests/tests.rs +++ b/util/network-devp2p/tests/tests.rs @@ -112,7 +112,7 @@ fn net_start_stop() { let config = NetworkConfiguration::new_local(); let service = NetworkService::new(config, None).unwrap(); service.start().unwrap(); - service.stop().unwrap(); + service.stop(); service.start().unwrap(); } From bd1e3fc606c3bf6337cb5cabcc068a63c4e8a029 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Tue, 22 May 2018 19:07:27 +0200 Subject: [PATCH 91/95] Allow making direct RPC queries from the C API (#8588) --- parity-clib-example/main.cpp | 17 +++++++++++++++-- parity-clib/parity.h | 16 ++++++++++++++++ parity-clib/src/lib.rs | 31 ++++++++++++++++++++++++++++++ parity/rpc.rs | 2 +- parity/run.rs | 35 ++++++++++++++++++++++++++++++---- rpc/src/v1/types/provenance.rs | 4 ++++ 6 files changed, 98 insertions(+), 7 deletions(-) diff --git a/parity-clib-example/main.cpp b/parity-clib-example/main.cpp index 1fadf1b5b56..becce8598eb 100644 --- a/parity-clib-example/main.cpp +++ b/parity-clib-example/main.cpp @@ -1,4 +1,7 @@ #include +#include +#include +#include #include #include @@ -8,8 +11,8 @@ int main() { ParityParams cfg = { 0 }; cfg.on_client_restart_cb = on_restart; - const char* args[] = {"--light"}; - size_t str_lens[] = {7}; + const char* args[] = {"--no-ipc"}; + size_t str_lens[] = {8}; if (parity_config_from_cli(args, str_lens, 1, &cfg.configuration) != 0) { return 1; } @@ -19,6 +22,16 @@ int main() { return 1; } + const char* rpc = "{\"method\":\"parity_versionInfo\",\"params\":[],\"id\":1,\"jsonrpc\":\"2.0\"}"; + size_t out_len = 256; + char* out = (char*)malloc(out_len + 1); + if (parity_rpc(parity, rpc, strlen(rpc), out, &out_len)) { + return 1; + } + out[out_len] = '\0'; + printf("RPC output: %s", out); + free(out); + sleep(5); if (parity != NULL) { parity_destroy(parity); diff --git a/parity-clib/parity.h b/parity-clib/parity.h index b61da8e458b..f647395ce9a 100644 --- a/parity-clib/parity.h +++ b/parity-clib/parity.h @@ -86,6 +86,22 @@ int parity_start(const ParityParams* params, void** out); /// must not call this function. void parity_destroy(void* parity); +/// Performs an RPC request. +/// +/// Blocks the current thread until the request is finished. You are therefore encouraged to spawn +/// a new thread for each RPC request that requires accessing the blockchain. +/// +/// - `rpc` and `len` must contain the JSON string representing the RPC request. +/// - `out_str` and `out_len` point to a buffer where the output JSON result will be stored. If the +/// buffer is not large enough, the function fails. +/// - `out_len` will receive the final length of the string. +/// - On success, the function returns 0. On failure, it returns 1. +/// +/// **Important**: Keep in mind that this function doesn't write any null terminator on the output +/// string. +/// +int parity_rpc(void* parity, const char* rpc, size_t len, char* out_str, size_t* out_len); + #ifdef __cplusplus } #endif diff --git a/parity-clib/src/lib.rs b/parity-clib/src/lib.rs index b08d6487d1a..fe631ce8a83 100644 --- a/parity-clib/src/lib.rs +++ b/parity-clib/src/lib.rs @@ -23,6 +23,7 @@ use std::os::raw::{c_char, c_void, c_int}; use std::panic; use std::ptr; use std::slice; +use std::str; #[repr(C)] pub struct ParityParams { @@ -131,3 +132,33 @@ pub extern fn parity_destroy(client: *mut c_void) { }); } } + +#[no_mangle] +pub extern fn parity_rpc(client: *mut c_void, query: *const char, len: usize, out_str: *mut c_char, out_len: *mut usize) -> c_int { + unsafe { + panic::catch_unwind(|| { + let client: &mut parity::RunningClient = &mut *(client as *mut parity::RunningClient); + + let query_str = { + let string = slice::from_raw_parts(query as *const u8, len); + match str::from_utf8(string) { + Ok(a) => a, + Err(_) => return 1, + } + }; + + if let Some(output) = client.rpc_query_sync(query_str) { + let q_out_len = output.as_bytes().len(); + if *out_len < q_out_len { + return 1; + } + + ptr::copy_nonoverlapping(output.as_bytes().as_ptr(), out_str as *mut u8, q_out_len); + *out_len = q_out_len; + 0 + } else { + 1 + } + }).unwrap_or(1) + } +} diff --git a/parity/rpc.rs b/parity/rpc.rs index 66a2715d42b..21bc9a40969 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -355,7 +355,7 @@ fn with_domain(items: Option>, domain: &str, ui_address: &Option(apis: ApiSet, deps: &Dependencies) -> MetaIoHandler> +pub fn setup_apis(apis: ApiSet, deps: &Dependencies) -> MetaIoHandler> where D: rpc_apis::Dependencies { let mut handler = MetaIoHandler::with_middleware( diff --git a/parity/run.rs b/parity/run.rs index 73113055bbf..fd16085c46c 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -41,7 +41,7 @@ use miner::external::ExternalMiner; use node_filter::NodeFilter; use node_health; use parity_reactor::EventLoop; -use parity_rpc::{NetworkSettings, informant, is_major_importing}; +use parity_rpc::{Origin, Metadata, NetworkSettings, informant, is_major_importing}; use updater::{UpdatePolicy, Updater}; use parity_version::version; use ethcore_private_tx::{ProviderConfig, EncryptorConfig, SecretStoreEncryptor}; @@ -56,6 +56,7 @@ use cache::CacheConfig; use user_defaults::UserDefaults; use dapps; use ipfs; +use jsonrpc_core; use modules; use rpc; use rpc_apis; @@ -369,6 +370,7 @@ fn execute_light_impl(cmd: RunCmd, logger: Arc) -> Result) -> Result(cmd: RunCmd, logger: Arc, on_client_rq: }; // start rpc servers + let rpc_direct = rpc::setup_apis(rpc_apis::ApiSet::All, &dependencies); let ws_server = rpc::new_ws(cmd.ws_conf.clone(), &dependencies)?; let ipc_server = rpc::new_ipc(cmd.ipc_conf, &dependencies)?; let http_server = rpc::new_http("HTTP JSON-RPC", "jsonrpc", cmd.http_conf.clone(), &dependencies, dapps_middleware)?; @@ -878,6 +882,7 @@ fn execute_impl(cmd: RunCmd, logger: Arc, on_client_rq: Ok(RunningClient { inner: RunningClientInner::Full { + rpc: rpc_direct, informant, client, keep_alive: Box::new((watcher, service, updater, ws_server, http_server, ipc_server, ui_server, secretstore_key_server, ipfs_server, event_loop)), @@ -890,16 +895,18 @@ fn execute_impl(cmd: RunCmd, logger: Arc, on_client_rq: /// Should be destroyed by calling `shutdown()`, otherwise execution will continue in the /// background. pub struct RunningClient { - inner: RunningClientInner + inner: RunningClientInner, } enum RunningClientInner { Light { + rpc: jsonrpc_core::MetaIoHandler>, informant: Arc>, client: Arc, keep_alive: Box, }, Full { + rpc: jsonrpc_core::MetaIoHandler>, informant: Arc>, client: Arc, keep_alive: Box, @@ -907,25 +914,45 @@ enum RunningClientInner { } impl RunningClient { + /// Performs a synchronous RPC query. + /// Blocks execution until the result is ready. + pub fn rpc_query_sync(&self, request: &str) -> Option { + let metadata = Metadata { + origin: Origin::CApi, + session: None, + }; + + match self.inner { + RunningClientInner::Light { ref rpc, .. } => { + rpc.handle_request_sync(request, metadata) + }, + RunningClientInner::Full { ref rpc, .. } => { + rpc.handle_request_sync(request, metadata) + }, + } + } + /// Shuts down the client. pub fn shutdown(self) { match self.inner { - RunningClientInner::Light { informant, client, keep_alive } => { + RunningClientInner::Light { rpc, informant, client, keep_alive } => { // Create a weak reference to the client so that we can wait on shutdown // until it is dropped let weak_client = Arc::downgrade(&client); + drop(rpc); drop(keep_alive); informant.shutdown(); drop(informant); drop(client); wait_for_drop(weak_client); }, - RunningClientInner::Full { informant, client, keep_alive } => { + RunningClientInner::Full { rpc, informant, client, keep_alive } => { info!("Finishing work, please wait..."); // Create a weak reference to the client so that we can wait on shutdown // until it is dropped let weak_client = Arc::downgrade(&client); // drop this stuff as soon as exit detected. + drop(rpc); drop(keep_alive); // to make sure timer does not spawn requests while shutdown is in progress informant.shutdown(); diff --git a/rpc/src/v1/types/provenance.rs b/rpc/src/v1/types/provenance.rs index b52f0cb7746..6bcd43a21fa 100644 --- a/rpc/src/v1/types/provenance.rs +++ b/rpc/src/v1/types/provenance.rs @@ -49,6 +49,9 @@ pub enum Origin { /// Session id session: H256 }, + /// From the C API + #[serde(rename="c-api")] + CApi, /// Unknown #[serde(rename="unknown")] Unknown, @@ -68,6 +71,7 @@ impl fmt::Display for Origin { Origin::Ipc(ref session) => write!(f, "IPC (session: {})", session), Origin::Ws { ref session, ref dapp } => write!(f, "{} via WebSocket (session: {})", dapp, session), Origin::Signer { ref session, ref dapp } => write!(f, "{} via UI (session: {})", dapp, session), + Origin::CApi => write!(f, "C API"), Origin::Unknown => write!(f, "unknown origin"), } } From db9397890efbc551d8ba70c3887ddcb0f6b0e097 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 23 May 2018 10:27:45 +0100 Subject: [PATCH 92/95] Fix cli signer (#8682) * Update ethereum-types so `{:#x}` applies 0x prefix --- Cargo.lock | 102 +++++++++++++++++++-------------------- rpc/Cargo.toml | 2 +- rpc/src/v1/types/uint.rs | 8 +-- 3 files changed, 56 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 646bc906456..c0aae6664f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -248,7 +248,7 @@ name = "common-types" version = "0.1.0" dependencies = [ "ethcore-bytes 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2", @@ -385,7 +385,7 @@ name = "dir" version = "0.1.0" dependencies = [ "app_dirs 1.2.1 (git+https://github.com/paritytech/app-dirs-rs)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "journaldb 0.1.0", ] @@ -457,7 +457,7 @@ version = "5.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -530,7 +530,7 @@ dependencies = [ "ethcore-miner 1.12.0", "ethcore-stratum 1.12.0", "ethcore-transaction 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "ethkey 0.3.0", "ethstore 0.2.0", @@ -591,7 +591,7 @@ version = "0.1.0" name = "ethcore-crypto" version = "0.1.0" dependencies = [ - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.12.1 (git+https://github.com/paritytech/ring)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -628,7 +628,7 @@ dependencies = [ "ethcore-io 1.12.0", "ethcore-network 1.12.0", "ethcore-transaction 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -678,7 +678,7 @@ dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.12.0", "ethcore-transaction 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "fetch 0.1.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -706,7 +706,7 @@ dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-crypto 0.1.0", "ethcore-io 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.2.1", @@ -726,7 +726,7 @@ dependencies = [ "ethcore-io 1.12.0", "ethcore-logger 1.12.0", "ethcore-network 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "igd 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -764,7 +764,7 @@ dependencies = [ "ethcore-logger 1.12.0", "ethcore-miner 1.12.0", "ethcore-transaction 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "ethkey 0.3.0", "fetch 0.1.0", @@ -798,7 +798,7 @@ dependencies = [ "ethcore-logger 1.12.0", "ethcore-sync 1.12.0", "ethcore-transaction 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -847,7 +847,7 @@ version = "1.12.0" dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-logger 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", @@ -871,7 +871,7 @@ dependencies = [ "ethcore-network-devp2p 1.12.0", "ethcore-private-tx 1.0.0", "ethcore-transaction 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -895,7 +895,7 @@ dependencies = [ name = "ethcore-transaction" version = "0.1.0" dependencies = [ - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "ethkey 0.3.0", "evm 0.1.0", @@ -908,7 +908,7 @@ dependencies = [ [[package]] name = "ethereum-types" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -917,7 +917,7 @@ dependencies = [ "fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -932,7 +932,7 @@ dependencies = [ name = "ethjson" version = "0.1.0" dependencies = [ - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -947,7 +947,7 @@ dependencies = [ "edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", "ethcore-crypto 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mem 0.1.0", @@ -979,7 +979,7 @@ version = "0.2.0" dependencies = [ "dir 0.1.0", "ethcore-crypto 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1019,7 +1019,7 @@ name = "evm" version = "0.1.0" dependencies = [ "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1038,7 +1038,7 @@ dependencies = [ "ethcore 1.12.0", "ethcore-bytes 0.1.0", "ethcore-transaction 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "evm 0.1.0", "panic_hook 0.1.0", @@ -1178,7 +1178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "hardware-wallet" version = "1.12.0" dependencies = [ - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)", "libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)", @@ -1194,7 +1194,7 @@ name = "hashdb" version = "0.1.1" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1342,7 +1342,7 @@ version = "0.1.0" dependencies = [ "ethcore-bytes 0.1.0", "ethcore-logger 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2", @@ -1456,7 +1456,7 @@ dependencies = [ name = "keccak-hash" version = "0.1.2" dependencies = [ - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1492,7 +1492,7 @@ name = "kvdb-rocksdb" version = "0.1.0" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1644,7 +1644,7 @@ name = "memorydb" version = "0.1.1" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2", @@ -1807,7 +1807,7 @@ dependencies = [ "ethcore-io 1.12.0", "ethcore-network 1.12.0", "ethcore-network-devp2p 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb-memorydb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1866,7 +1866,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1978,7 +1978,7 @@ dependencies = [ "ethcore-service 0.1.0", "ethcore-sync 1.12.0", "ethcore-transaction 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "fake-fetch 0.0.1", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2044,7 +2044,7 @@ dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0", "ethcore-devtools 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fetch 0.1.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2109,7 +2109,7 @@ dependencies = [ "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fake-fetch 0.0.1", "fetch 0.1.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2133,7 +2133,7 @@ dependencies = [ "cid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-bytes 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", "multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2162,7 +2162,7 @@ dependencies = [ name = "parity-machine" version = "0.1.0" dependencies = [ - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2192,7 +2192,7 @@ dependencies = [ "ethcore-private-tx 1.0.0", "ethcore-sync 1.12.0", "ethcore-transaction 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "ethkey 0.3.0", "ethstore 0.2.0", @@ -2331,7 +2331,7 @@ dependencies = [ "ethcore 1.12.0", "ethcore-bytes 0.1.0", "ethcore-sync 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2376,7 +2376,7 @@ dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-crypto 0.1.0", "ethcore-network 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", @@ -2438,7 +2438,7 @@ dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0", "ethcore-logger 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.1", "keccak-hash 0.1.2", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2494,7 +2494,7 @@ name = "plain_hasher" version = "0.1.0" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2593,7 +2593,7 @@ version = "0.1.0" dependencies = [ "clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-logger 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2766,7 +2766,7 @@ version = "0.2.1" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2974,7 +2974,7 @@ name = "shell32-sys" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3444,7 +3444,7 @@ name = "transaction-pool" version = "1.12.0" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "trace-time 0.1.0", @@ -3471,7 +3471,7 @@ name = "trie-standardmap" version = "0.1.0" dependencies = [ "ethcore-bytes 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2", "rlp 0.2.1", ] @@ -3481,7 +3481,7 @@ name = "triehash" version = "0.1.0" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2", "rlp 0.2.1", "trie-standardmap 0.1.0", @@ -3489,7 +3489,7 @@ dependencies = [ [[package]] name = "uint" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3596,7 +3596,7 @@ name = "util-error" version = "0.1.0" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0", "rlp 0.2.1", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3628,7 +3628,7 @@ dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", "ethcore-bytes 0.1.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "keccak-hash 0.1.2", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3647,7 +3647,7 @@ version = "0.1.0" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-logger 1.12.0", - "ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3847,7 +3847,7 @@ dependencies = [ "checksum ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "210c9e21d164c15b6ef64fe601e0e12a3c84a031d5ef558e38463e53edbd22ed" "checksum ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2bc7099baa147187aedaecd9fe04a6c0541c82bc43ff317cb6900fe2b983d74" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" -"checksum ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3ae691a36ce5d25b433e63128ce5579f4a18457b6a9c849832b2c9e0fec92a" +"checksum ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c48729b8aea8aedb12cf4cb2e5cef439fdfe2dda4a89e47eeebd15778ef53b6" "checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002" "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" "checksum fixed-hash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18d6fd718fb4396e7a9c93ac59ba7143501467ca7a143c145b5555a571d5576" @@ -4045,7 +4045,7 @@ dependencies = [ "checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" "checksum transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "715254c8f0811be1a79ad3ea5e6fa3c8eddec2b03d7f5ba78cf093e56d79c24f" "checksum trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)" = "" -"checksum uint 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6477b2716357758c176c36719023e1f9726974d762150e4fc0a9c8c75488c343" +"checksum uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "38051a96565903d81c9a9210ce11076b2218f3b352926baa1f5f6abbdfce8273" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 731544a55f2..8fdb9ed5740 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -47,7 +47,7 @@ ethcore-miner = { path = "../miner" } ethcore-private-tx = { path = "../ethcore/private-tx" } ethcore-sync = { path = "../ethcore/sync" } ethcore-transaction = { path = "../ethcore/transaction" } -ethereum-types = "0.3" +ethereum-types = "0.3.2" ethjson = { path = "../json" } ethkey = { path = "../ethkey" } diff --git a/rpc/src/v1/types/uint.rs b/rpc/src/v1/types/uint.rs index e887322dbae..4e2a189a63f 100644 --- a/rpc/src/v1/types/uint.rs +++ b/rpc/src/v1/types/uint.rs @@ -55,7 +55,7 @@ macro_rules! impl_uint { impl fmt::LowerHex for $name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:#x}", self.0) + fmt::LowerHex::fmt(&self.0, f) } } @@ -102,19 +102,19 @@ impl_uint!(U64, u64, 1); impl serde::Serialize for U128 { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - serializer.serialize_str(&format!("0x{:x}", self.0)) + serializer.serialize_str(&format!("{:#x}", self)) } } impl serde::Serialize for U256 { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - serializer.serialize_str(&format!("0x{:x}", self.0)) + serializer.serialize_str(&format!("{:#x}", self)) } } impl serde::Serialize for U64 { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { - serializer.serialize_str(&format!("0x{:x}", self.0)) + serializer.serialize_str(&format!("{:#x}", self)) } } From 6563576ae9586288516cb614ae0787cb27a8f9f2 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 24 May 2018 04:39:52 +0200 Subject: [PATCH 93/95] Use impl Future in the light client RPC helpers (#8628) --- rpc/src/v1/helpers/light_fetch.rs | 69 +++++++++++++++---------------- rpc/src/v1/impls/eth_pubsub.rs | 2 +- rpc/src/v1/impls/light/eth.rs | 2 +- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index d8a157da21b..413670d5210 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -25,7 +25,7 @@ use ethcore::ids::BlockId; use ethcore::filter::Filter as EthcoreFilter; use ethcore::receipt::Receipt; -use jsonrpc_core::{BoxFuture, Result}; +use jsonrpc_core::{Result, Error}; use jsonrpc_core::futures::{future, Future}; use jsonrpc_core::futures::future::Either; use jsonrpc_macros::Trailing; @@ -139,58 +139,57 @@ impl LightFetch { } /// Get a block header from the on demand service or client, or error. - pub fn header(&self, id: BlockId) -> BoxFuture { + pub fn header(&self, id: BlockId) -> impl Future + Send { let mut reqs = Vec::new(); let header_ref = match self.make_header_requests(id, &mut reqs) { Ok(r) => r, - Err(e) => return Box::new(future::err(e)), + Err(e) => return Either::A(future::err(e)), }; - - self.send_requests(reqs, |res| + Either::B(self.send_requests(reqs, |res| extract_header(&res, header_ref) .expect("these responses correspond to requests that header_ref belongs to \ therefore it will not fail; qed") - ) + )) } /// Helper for getting contract code at a given block. - pub fn code(&self, address: Address, id: BlockId) -> BoxFuture> { + pub fn code(&self, address: Address, id: BlockId) -> impl Future, Error = Error> + Send { let mut reqs = Vec::new(); let header_ref = match self.make_header_requests(id, &mut reqs) { Ok(r) => r, - Err(e) => return Box::new(future::err(e)), + Err(e) => return Either::A(future::err(e)), }; reqs.push(request::Account { header: header_ref.clone(), address: address }.into()); let account_idx = reqs.len() - 1; reqs.push(request::Code { header: header_ref, code_hash: Field::back_ref(account_idx, 0) }.into()); - self.send_requests(reqs, |mut res| match res.pop() { + Either::B(self.send_requests(reqs, |mut res| match res.pop() { Some(OnDemandResponse::Code(code)) => code, _ => panic!("responses correspond directly with requests in amount and type; qed"), - }) + })) } /// Helper for getting account info at a given block. /// `None` indicates the account doesn't exist at the given block. - pub fn account(&self, address: Address, id: BlockId) -> BoxFuture> { + pub fn account(&self, address: Address, id: BlockId) -> impl Future, Error = Error> + Send { let mut reqs = Vec::new(); let header_ref = match self.make_header_requests(id, &mut reqs) { Ok(r) => r, - Err(e) => return Box::new(future::err(e)), + Err(e) => return Either::A(future::err(e)), }; reqs.push(request::Account { header: header_ref, address: address }.into()); - self.send_requests(reqs, |mut res|match res.pop() { + Either::B(self.send_requests(reqs, |mut res|match res.pop() { Some(OnDemandResponse::Account(acc)) => acc, _ => panic!("responses correspond directly with requests in amount and type; qed"), - }) + })) } /// Helper for getting proved execution. - pub fn proved_execution(&self, req: CallRequest, num: Trailing) -> BoxFuture { + pub fn proved_execution(&self, req: CallRequest, num: Trailing) -> impl Future + Send { const DEFAULT_GAS_PRICE: u64 = 21_000; // starting gas when gas not provided. const START_GAS: u64 = 50_000; @@ -280,39 +279,39 @@ impl LightFetch { } /// Get a block itself. Fails on unknown block ID. - pub fn block(&self, id: BlockId) -> BoxFuture { + pub fn block(&self, id: BlockId) -> impl Future + Send { let mut reqs = Vec::new(); let header_ref = match self.make_header_requests(id, &mut reqs) { Ok(r) => r, - Err(e) => return Box::new(future::err(e)), + Err(e) => return Either::A(future::err(e)), }; reqs.push(request::Body(header_ref).into()); - self.send_requests(reqs, |mut res| match res.pop() { + Either::B(self.send_requests(reqs, |mut res| match res.pop() { Some(OnDemandResponse::Body(b)) => b, _ => panic!("responses correspond directly with requests in amount and type; qed"), - }) + })) } /// Get the block receipts. Fails on unknown block ID. - pub fn receipts(&self, id: BlockId) -> BoxFuture> { + pub fn receipts(&self, id: BlockId) -> impl Future, Error = Error> + Send { let mut reqs = Vec::new(); let header_ref = match self.make_header_requests(id, &mut reqs) { Ok(r) => r, - Err(e) => return Box::new(future::err(e)), + Err(e) => return Either::A(future::err(e)), }; reqs.push(request::BlockReceipts(header_ref).into()); - self.send_requests(reqs, |mut res| match res.pop() { + Either::B(self.send_requests(reqs, |mut res| match res.pop() { Some(OnDemandResponse::Receipts(b)) => b, _ => panic!("responses correspond directly with requests in amount and type; qed"), - }) + })) } /// Get transaction logs - pub fn logs(&self, filter: EthcoreFilter) -> BoxFuture> { + pub fn logs(&self, filter: EthcoreFilter) -> impl Future, Error = Error> + Send { use std::collections::BTreeMap; use jsonrpc_core::futures::stream::{self, Stream}; @@ -326,9 +325,9 @@ impl LightFetch { }; match (block_number(filter.to_block), block_number(filter.from_block)) { - (Some(to), Some(from)) if to < from => return Box::new(future::ok(Vec::new())), + (Some(to), Some(from)) if to < from => return Either::A(future::ok(Vec::new())), (Some(_), Some(_)) => {}, - _ => return Box::new(future::err(errors::unknown_block())), + _ => return Either::A(future::err(errors::unknown_block())), } let maybe_future = self.sync.with_context(move |ctx| { @@ -362,15 +361,15 @@ impl LightFetch { }); match maybe_future { - Some(fut) => Box::new(fut), - None => Box::new(future::err(errors::network_disabled())), + Some(fut) => Either::B(Either::A(fut)), + None => Either::B(Either::B(future::err(errors::network_disabled()))), } } // Get a transaction by hash. also returns the index in the block. // Only returns transactions in the canonical chain. pub fn transaction_by_hash(&self, tx_hash: H256, eip86_transition: u64) - -> BoxFuture> + -> impl Future, Error = Error> + Send { let params = (self.sync.clone(), self.on_demand.clone()); let fetcher: Self = self.clone(); @@ -426,7 +425,7 @@ impl LightFetch { })) } - fn send_requests(&self, reqs: Vec, parse_response: F) -> BoxFuture where + fn send_requests(&self, reqs: Vec, parse_response: F) -> impl Future + Send where F: FnOnce(Vec) -> T + Send + 'static, T: Send + 'static, { @@ -439,7 +438,7 @@ impl LightFetch { match maybe_future { Some(recv) => recv, - None => Box::new(future::err(errors::network_disabled())) + None => Box::new(future::err(errors::network_disabled())) as Box + Send> } } } @@ -457,7 +456,7 @@ struct ExecuteParams { // has a peer execute the transaction with given params. If `gas_known` is false, // this will double the gas on each `OutOfGas` error. -fn execute_tx(gas_known: bool, params: ExecuteParams) -> BoxFuture { +fn execute_tx(gas_known: bool, params: ExecuteParams) -> impl Future + Send { if !gas_known { Box::new(future::loop_fn(params, |mut params| { execute_tx(true, params.clone()).and_then(move |res| { @@ -480,7 +479,7 @@ fn execute_tx(gas_known: bool, params: ExecuteParams) -> BoxFuture Ok(future::Loop::Break(failed)), } }) - })) + })) as Box + Send> } else { trace!(target: "light_fetch", "Placing execution request for {} gas in on_demand", params.tx.gas); @@ -501,8 +500,8 @@ fn execute_tx(gas_known: bool, params: ExecuteParams) -> BoxFuture Box::new(fut), - None => Box::new(future::err(errors::network_disabled())), + Some(fut) => Box::new(fut) as Box + Send>, + None => Box::new(future::err(errors::network_disabled())) as Box + Send>, } } } diff --git a/rpc/src/v1/impls/eth_pubsub.rs b/rpc/src/v1/impls/eth_pubsub.rs index 30459594466..c0789910c33 100644 --- a/rpc/src/v1/impls/eth_pubsub.rs +++ b/rpc/src/v1/impls/eth_pubsub.rs @@ -199,7 +199,7 @@ impl LightClient for LightFetch { } fn logs(&self, filter: EthFilter) -> BoxFuture> { - LightFetch::logs(self, filter) + Box::new(LightFetch::logs(self, filter)) as BoxFuture<_> } } diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index 35f7792b52c..10ad024f244 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -538,7 +538,7 @@ impl Filterable for EthClient { } fn logs(&self, filter: EthcoreFilter) -> BoxFuture> { - self.fetcher().logs(filter) + Box::new(self.fetcher().logs(filter)) as BoxFuture<_> } fn pending_logs(&self, _block_number: u64, _filter: &EthcoreFilter) -> Vec { From dc8da3743db3855ed86a52a2a36a2826d15917b7 Mon Sep 17 00:00:00 2001 From: Thibaut S <33178835+Tbaut@users.noreply.github.com> Date: Thu, 24 May 2018 10:53:37 +0200 Subject: [PATCH 94/95] Update mod.rs (#8695) - Update interfaces affected by unsafe-expose - replace `{{ }}` as this throws an error in Jekyll (wiki) --- parity/cli/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index 34e3bf03a11..a064baeac56 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -315,7 +315,7 @@ usage! { ["Convenience options"] FLAG flag_unsafe_expose: (bool) = false, or |c: &Config| c.misc.as_ref()?.unsafe_expose, "--unsafe-expose", - "All servers will listen on external interfaces and will be remotely accessible. It's equivalent with setting the following: --{{ws,jsonrpc,ui,ipfs,secret_store,stratum}}-interface=all --*-hosts=all This option is UNSAFE and should be used with great care!", + "All servers will listen on external interfaces and will be remotely accessible. It's equivalent with setting the following: --[ws,jsonrpc,ui,ipfs-api,secretstore,stratum,dapps,secretstore-http]-interface=all --*-hosts=all This option is UNSAFE and should be used with great care!", ARG arg_config: (String) = "$BASE/config.toml", or |_| None, "-c, --config=[CONFIG]", From e346f3058ef806ae397571beef5901f8723116d9 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Thu, 24 May 2018 13:06:48 +0200 Subject: [PATCH 95/95] remove empty file (#8705) --- ethstore/tests/cli.rs | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 ethstore/tests/cli.rs diff --git a/ethstore/tests/cli.rs b/ethstore/tests/cli.rs deleted file mode 100644 index f90ec463dc4..00000000000 --- a/ethstore/tests/cli.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . -