From 833dc160400322ec7e1b18fc1ab1873980bca967 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Sat, 11 Jun 2016 12:21:12 +0300 Subject: [PATCH 001/239] cargo dev config to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 3226ea5a2..02e321a1b 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ # Build artifacts out/ + +# Cargo local dev config +.cargo From 4ef4819bf9c90ba6600ced11e5ae72b08877e7ba Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 13 Jun 2016 09:51:14 -0700 Subject: [PATCH 002/239] removed try_seal from MinerClient interface (#1262) --- ethcore/src/client/client.rs | 4 ---- ethcore/src/client/mod.rs | 5 +---- ethcore/src/client/test_client.rs | 7 +------ ethcore/src/miner/miner.rs | 4 ++-- ethcore/src/tests/client.rs | 1 - 5 files changed, 4 insertions(+), 17 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 213ee9755..75a60204f 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -785,10 +785,6 @@ impl MiningBlockChainClient for Client where V: Verifier { open_block } - - fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result { - block.try_seal(self.engine.deref().deref(), seal) - } } impl MayPanic for Client { diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index eda850d9d..dbd09ea4a 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -36,7 +36,7 @@ use util::hash::{Address, H256, H2048}; use util::numbers::U256; use blockchain::TreeRoute; use block_queue::BlockQueueInfo; -use block::{LockedBlock, SealedBlock, OpenBlock}; +use block::OpenBlock; use header::{BlockNumber, Header}; use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; @@ -197,9 +197,6 @@ pub trait BlockChainClient : Sync + Send { /// Extended client interface used for mining pub trait MiningBlockChainClient : BlockChainClient { - /// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error. - fn try_seal(&self, block: LockedBlock, seal: Vec) -> Result; - /// Returns OpenBlock prepared for closing. fn prepare_open_block(&self, author: Address, gas_floor_target: U256, extra_data: Bytes) -> OpenBlock; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index d02afc0f7..f1a7a6674 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -31,7 +31,7 @@ use evm::Factory as EvmFactory; use miner::{Miner, MinerService}; use block_queue::BlockQueueInfo; -use block::{SealedBlock, LockedBlock, OpenBlock}; +use block::OpenBlock; use executive::Executed; use error::{ExecutionError}; use trace::LocalizedTrace; @@ -240,11 +240,6 @@ impl TestBlockChainClient { } impl MiningBlockChainClient for TestBlockChainClient { - fn try_seal(&self, block: LockedBlock, _seal: Vec) -> Result { - Err(block) - } - - fn prepare_open_block(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes) -> OpenBlock { unimplemented!(); } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index ceddb31bc..2df0c184b 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -181,7 +181,7 @@ impl Miner { }); if let Some(seal) = s { trace!(target: "miner", "prepare_sealing: managed internal seal. importing..."); - if let Ok(sealed) = chain.try_seal(block.lock(), seal) { + if let Ok(sealed) = block.lock().try_seal(self.engine(), seal) { if let Ok(_) = chain.import_block(sealed.rlp_bytes()) { trace!(target: "miner", "prepare_sealing: sealed internally and imported. leaving."); } else { @@ -510,7 +510,7 @@ impl MinerService for Miner { fn submit_seal(&self, chain: &MiningBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error> { if let Some(b) = self.sealing_work.lock().unwrap().take_used_if(|b| &b.hash() == &pow_hash) { - match chain.try_seal(b.lock(), seal) { + match b.lock().try_seal(self.engine(), seal) { Err(_) => { info!(target: "miner", "Mined block rejected, PoW was invalid."); Err(Error::PowInvalid) diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 789943942..d87b41b62 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -140,5 +140,4 @@ fn can_mine() { let b = client.prepare_open_block(Address::default(), 31415926.into(), vec![]).close(); assert_eq!(*b.block().header().parent_hash(), BlockView::new(&dummy_blocks[0]).header_view().sha3()); - assert!(client.try_seal(b.lock(), vec![]).is_ok()); } From 6b12334136ad416f628e8c3ed4a945451177dbb3 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 13 Jun 2016 18:55:24 +0200 Subject: [PATCH 003/239] Windows build (#1253) * Networking refactoring * Fixed typo * Trace logging * Updated dependencies for windows build * Windows fixes * use mio 0.5 * nix build * Windows build fix * style * removed unused import * ipc crate version bump * ipc config for named pipes * tweaks and fixes * tweaks and fixes * final version bump * Fixed tests * Disable color output on windows * Added missing doc --- Cargo.lock | 30 ++++++-- Cargo.toml | 4 +- parity/configuration.rs | 24 +++++- parity/main.rs | 33 +++++--- parity/rpc.rs | 26 +++++-- util/Cargo.toml | 2 +- util/src/io/service.rs | 2 +- util/src/keys/directory.rs | 8 ++ util/src/network/connection.rs | 134 ++++++++++++++++++++------------- util/src/network/handshake.rs | 54 +++++++------ util/src/network/host.rs | 121 +++++++++++++++-------------- util/src/network/session.rs | 53 +++++++------ 12 files changed, 293 insertions(+), 198 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52e053d66..c850940c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,7 +20,7 @@ dependencies = [ "ethsync 1.2.0", "fdlimit 0.1.0", "hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "json-ipc-server 0.1.0 (git+https://github.com/ethcore/json-ipc-server.git)", + "json-ipc-server 0.2.2 (git+https://github.com/ethcore/json-ipc-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -346,7 +346,7 @@ dependencies = [ "ethcore-util 1.2.0", "ethjson 0.1.0", "ethsync 1.2.0", - "json-ipc-server 0.1.0 (git+https://github.com/ethcore/json-ipc-server.git)", + "json-ipc-server 0.2.2 (git+https://github.com/ethcore/json-ipc-server.git)", "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -394,7 +394,7 @@ dependencies = [ "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", "nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb 0.4.5 (git+https://github.com/ethcore/rust-rocksdb)", @@ -570,12 +570,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "json-ipc-server" -version = "0.1.0" -source = "git+https://github.com/ethcore/json-ipc-server.git#4f9226c4f84dcce2385a188374e3b5fc66b63e68" +version = "0.2.2" +source = "git+https://github.com/ethcore/json-ipc-server.git#15ef25e5f859d2d27469c92cc13dd1ddea03e444" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -704,6 +708,22 @@ dependencies = [ "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mio" +version = "0.5.1" +source = "git+https://github.com/ethcore/mio?branch=v0.5.x#1fc881771fb8c2517317b4f805d7b88235be422b" +dependencies = [ + "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", + "nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index f7f805d30..ff624fa1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ docopt = "0.6" time = "0.1" ctrlc = { git = "https://github.com/ethcore/rust-ctrlc.git" } fdlimit = { path = "util/fdlimit" } -daemonize = "0.2" num_cpus = "0.2" number_prefix = "0.2" rpassword = "0.2.1" @@ -37,6 +36,9 @@ ethcore-ipc = { path = "ipc/rpc" } json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } ansi_term = "0.7" +[target.'cfg(not(windows))'.dependencies] +daemonize = "0.2" + [dependencies.hyper] version = "0.8" default-features = false diff --git a/parity/configuration.rs b/parity/configuration.rs index 3076e4e68..1e14cd1de 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -287,9 +287,14 @@ impl Configuration { } fn geth_ipc_path(&self) -> String { - if self.args.flag_testnet { path::ethereum::with_testnet("geth.ipc") } - else { path::ethereum::with_default("geth.ipc") } - .to_str().unwrap().to_owned() + if cfg!(windows) { + r"\\.\pipe\geth.ipc".to_owned() + } + else { + if self.args.flag_testnet { path::ethereum::with_testnet("geth.ipc") } + else { path::ethereum::with_default("geth.ipc") } + .to_str().unwrap().to_owned() + } } pub fn keys_iterations(&self) -> u32 { @@ -358,7 +363,18 @@ impl Configuration { fn ipc_path(&self) -> String { if self.args.flag_geth { self.geth_ipc_path() } - else { Configuration::replace_home(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone())) } + else { + if cfg!(windows) { + r"\\.\pipe\parity.jsonrpc".to_owned() + } + else { + Configuration::replace_home(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone())) + } + } + } + + pub fn have_color(&self) -> bool { + !self.args.flag_no_color && !cfg!(windows) } pub fn signer_port(&self) -> Option { diff --git a/parity/main.rs b/parity/main.rs index 0d536e28a..679bc012a 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -32,6 +32,7 @@ extern crate log as rlog; extern crate env_logger; extern crate ctrlc; extern crate fdlimit; +#[cfg(not(windows))] extern crate daemonize; extern crate time; extern crate number_prefix; @@ -86,7 +87,6 @@ use ethcore::service::ClientService; use ethcore::spec::Spec; use ethsync::EthSync; use ethcore::miner::{Miner, MinerService, ExternalMiner}; -use daemonize::Daemonize; use migration::migrate; use informant::Informant; @@ -115,11 +115,7 @@ fn execute(conf: Configuration) { execute_upgrades(&conf, &spec, &client_config); if conf.args.cmd_daemon { - Daemonize::new() - .pid_file(conf.args.arg_pid_file.clone()) - .chown_pid_file(true) - .start() - .unwrap_or_else(|e| die!("Couldn't daemonize; {}", e)); + daemonize(&conf); } if conf.args.cmd_account { @@ -145,6 +141,20 @@ fn execute(conf: Configuration) { execute_client(conf, spec, client_config); } +#[cfg(not(windows))] +fn daemonize(conf: &Configuration) { + use daemonize::Daemonize; + Daemonize::new() + .pid_file(conf.args.arg_pid_file.clone()) + .chown_pid_file(true) + .start() + .unwrap_or_else(|e| die!("Couldn't daemonize; {}", e)); +} + +#[cfg(windows)] +fn daemonize(_conf: &Configuration) { +} + fn execute_upgrades(conf: &Configuration, spec: &Spec, client_config: &ClientConfig) { match ::upgrade::upgrade(Some(&conf.path())) { Ok(upgrades_applied) if upgrades_applied > 0 => { @@ -228,6 +238,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // setup ipc rpc let _ipc_server = rpc::new_ipc(conf.ipc_settings(), &dependencies); + debug!("IPC: {}", conf.ipc_settings()); if conf.args.flag_webapp { println!("WARNING: Flag -w/--webapp is deprecated. Dapps server is now on by default. Ignoring."); } let dapps_server = dapps::new(dapps::Configuration { @@ -255,7 +266,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // Register IO handler let io_handler = Arc::new(ClientIoHandler { client: service.client(), - info: Informant::new(!conf.args.flag_no_color), + info: Informant::new(conf.have_color()), sync: sync.clone(), accounts: account_service.clone(), }); @@ -375,8 +386,8 @@ fn execute_import(conf: Configuration) { panic_handler.forward_from(&service); let client = service.client(); - let mut instream: Box = if let Some(f) = conf.args.arg_file { - let f = File::open(&f).unwrap_or_else(|_| die!("Cannot open the file given: {}", f)); + let mut instream: Box = if let Some(ref f) = conf.args.arg_file { + let f = File::open(f).unwrap_or_else(|_| die!("Cannot open the file given: {}", f)); Box::new(f) } else { Box::new(::std::io::stdin()) @@ -386,7 +397,7 @@ fn execute_import(conf: Configuration) { let mut first_read = 0; let format = match conf.args.flag_format { - Some(x) => match x.deref() { + Some(ref x) => match x.deref() { "binary" | "bin" => DataFormat::Binary, "hex" => DataFormat::Hex, x => die!("Invalid --format parameter given: {:?}", x), @@ -407,7 +418,7 @@ fn execute_import(conf: Configuration) { } }; - let informant = Informant::new(!conf.args.flag_no_color); + let informant = Informant::new(conf.have_color()); let do_import = |bytes| { while client.queue_info().is_full() { sleep(Duration::from_secs(1)); } diff --git a/parity/rpc.rs b/parity/rpc.rs index 66f504408..c10635889 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -22,6 +22,7 @@ use util::panics::PanicHandler; use die::*; use jsonipc; use rpc_apis; +use std::fmt; #[cfg(feature = "rpc")] pub use ethcore_rpc::Server as RpcServer; @@ -44,6 +45,17 @@ pub struct IpcConfiguration { pub apis: String, } +impl fmt::Display for IpcConfiguration { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.enabled { + write!(f, "endpoint address [{}], api list [{}]", self.socket_addr, self.apis) + } + else { + write!(f, "disabled") + } + } +} + pub struct Dependencies { pub panic_handler: Arc, pub apis: Arc, @@ -66,12 +78,6 @@ pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Option Option { - if !conf.enabled { return None; } - let apis = conf.apis.split(',').collect(); - Some(setup_ipc_rpc_server(deps, &conf.socket_addr, apis)) -} - fn setup_rpc_server(apis: Vec<&str>, deps: &Dependencies) -> Server { let apis = rpc_apis::from_str(apis); let server = Server::new(); @@ -109,10 +115,18 @@ pub fn setup_http_rpc_server( }, } } + #[cfg(not(feature = "rpc"))] pub fn setup_ipc_rpc_server(_dependencies: &Dependencies, _addr: &str, _apis: Vec<&str>) -> ! { die!("Your Parity version has been compiled without JSON-RPC support.") } + +pub fn new_ipc(conf: IpcConfiguration, deps: &Dependencies) -> Option { + if !conf.enabled { return None; } + let apis = conf.apis.split(',').collect(); + Some(setup_ipc_rpc_server(deps, &conf.socket_addr, apis)) +} + #[cfg(feature = "rpc")] pub fn setup_ipc_rpc_server(dependencies: &Dependencies, addr: &str, apis: Vec<&str>) -> jsonipc::Server { let server = setup_rpc_server(apis, dependencies); diff --git a/util/Cargo.toml b/util/Cargo.toml index 173acd528..05e05d4c1 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -12,7 +12,7 @@ log = "0.3" env_logger = "0.3" rustc-serialize = "0.3" arrayvec = "0.3" -mio = "0.5.1" +mio = { git = "https://github.com/ethcore/mio", branch = "v0.5.x" } nix ="0.5.0" rand = "0.3.12" time = "0.1.34" diff --git a/util/src/io/service.rs b/util/src/io/service.rs index d946463f5..409667c46 100644 --- a/util/src/io/service.rs +++ b/util/src/io/service.rs @@ -335,7 +335,7 @@ impl IoService where Message: Send + Sync + Clone + 'static { /// Starts IO event loop pub fn start() -> Result, UtilError> { let panic_handler = PanicHandler::new_in_arc(); - let mut event_loop = EventLoop::new().unwrap(); + let mut event_loop = EventLoop::new().unwrap(); let channel = event_loop.channel(); let panic = panic_handler.clone(); let thread = thread::spawn(move || { diff --git a/util/src/keys/directory.rs b/util/src/keys/directory.rs index 20be7df7b..d9d453409 100644 --- a/util/src/keys/directory.rs +++ b/util/src/keys/directory.rs @@ -466,6 +466,7 @@ pub struct KeyDirectory { } /// Restricts the permissions of given path only to the owner. +#[cfg(not(windows))] pub fn restrict_permissions_owner(file_path: &Path) -> Result<(), i32> { let cstr = ::std::ffi::CString::new(file_path.to_str().unwrap()).unwrap(); match unsafe { ::libc::chmod(cstr.as_ptr(), ::libc::S_IWUSR | ::libc::S_IRUSR) } { @@ -474,6 +475,13 @@ pub fn restrict_permissions_owner(file_path: &Path) -> Result<(), i32> { } } +/// Restricts the permissions of given path only to the owner. +#[cfg(windows)] +pub fn restrict_permissions_owner(_file_path: &Path) -> Result<(), i32> { + //TODO: implement me + Ok(()) +} + impl KeyDirectory { /// Initializes new cache directory context with a given `path` pub fn new(path: &Path) -> KeyDirectory { diff --git a/util/src/network/connection.rs b/util/src/network/connection.rs index 3f20b8f7b..ade06b469 100644 --- a/util/src/network/connection.rs +++ b/util/src/network/connection.rs @@ -17,6 +17,7 @@ use std::sync::Arc; use std::collections::VecDeque; use std::net::SocketAddr; +use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; use mio::{Handler, Token, EventSet, EventLoop, PollOpt, TryRead, TryWrite}; use mio::tcp::*; use hash::*; @@ -60,45 +61,57 @@ pub struct GenericConnection { interest: EventSet, /// Shared network statistics stats: Arc, + /// Registered flag + registered: AtomicBool, } impl GenericConnection { pub fn expect(&mut self, size: usize) { + trace!(target:"network", "Expect to read {} bytes", size); if self.rec_size != self.rec_buf.len() { - warn!(target:"net", "Unexpected connection read start"); + warn!(target:"network", "Unexpected connection read start"); } - unsafe { self.rec_buf.set_len(0) } self.rec_size = size; } /// Readable IO handler. Called when there is some data to be read. pub fn readable(&mut self) -> io::Result> { if self.rec_size == 0 || self.rec_buf.len() >= self.rec_size { - warn!(target:"net", "Unexpected connection read"); + warn!(target:"network", "Unexpected connection read"); } - let max = self.rec_size - self.rec_buf.len(); - // resolve "multiple applicable items in scope [E0034]" error let sock_ref = ::by_ref(&mut self.socket); - match sock_ref.take(max as u64).try_read_buf(&mut self.rec_buf) { - Ok(Some(size)) if size != 0 => { - self.stats.inc_recv(size); - if self.rec_size != 0 && self.rec_buf.len() == self.rec_size { - self.rec_size = 0; - Ok(Some(::std::mem::replace(&mut self.rec_buf, Bytes::new()))) - } else { Ok(None) } - }, - Ok(_) => Ok(None), - Err(e) => Err(e), - } - } + loop { + let max = self.rec_size - self.rec_buf.len(); + match sock_ref.take(max as u64).try_read_buf(&mut self.rec_buf) { + Ok(Some(size)) if size != 0 => { + self.stats.inc_recv(size); + trace!(target:"network", "{}: Read {} of {} bytes", self.token, self.rec_buf.len(), self.rec_size); + if self.rec_size != 0 && self.rec_buf.len() == self.rec_size { + self.rec_size = 0; + return Ok(Some(::std::mem::replace(&mut self.rec_buf, Bytes::new()))) + } + else if self.rec_buf.len() > self.rec_size { + warn!(target:"network", "Read past buffer {} bytes", self.rec_buf.len() - self.rec_size); + return Ok(Some(::std::mem::replace(&mut self.rec_buf, Bytes::new()))) + } + }, + Ok(_) => return Ok(None), + Err(e) => { + debug!(target:"network", "Read error {} ({})", self.token, e); + return Err(e) + } + } + } + } /// Add a packet to send queue. - pub fn send(&mut self, data: Bytes) { + pub fn send(&mut self, io: &IoContext, data: Bytes) where Message: Send + Clone { if !data.is_empty() { self.send_queue.push_back(Cursor::new(data)); } if !self.interest.is_writable() { self.interest.insert(EventSet::writable()); + io.update_registration(self.token).ok(); } } @@ -108,7 +121,7 @@ impl GenericConnection { } /// Writable IO handler. Called when the socket is ready to send. - pub fn writable(&mut self) -> io::Result { + pub fn writable(&mut self, io: &IoContext) -> Result where Message: Send + Clone { if self.send_queue.is_empty() { return Ok(WriteStatus::Complete) } @@ -121,7 +134,6 @@ impl GenericConnection { } match self.socket.try_write_buf(buf) { Ok(Some(size)) if (buf.position() as usize) < send_size => { - self.interest.insert(EventSet::writable()); self.stats.inc_send(size); Ok(WriteStatus::Ongoing) }, @@ -131,7 +143,7 @@ impl GenericConnection { }, Ok(Some(_)) => { panic!("Wrote past buffer");}, Ok(None) => Ok(WriteStatus::Ongoing), - Err(e) => Err(e) + Err(e) => try!(Err(e)) } }.and_then(|r| { if r == WriteStatus::Complete { @@ -139,9 +151,7 @@ impl GenericConnection { } if self.send_queue.is_empty() { self.interest.remove(EventSet::writable()); - } - else { - self.interest.insert(EventSet::writable()); + try!(io.update_registration(self.token)); } Ok(r) }) @@ -162,6 +172,7 @@ impl Connection { rec_size: 0, interest: EventSet::hup() | EventSet::readable(), stats: stats, + registered: AtomicBool::new(false), } } @@ -188,27 +199,36 @@ impl Connection { rec_buf: Vec::new(), rec_size: 0, send_queue: self.send_queue.clone(), - interest: EventSet::hup() | EventSet::readable(), + interest: EventSet::hup(), stats: self.stats.clone(), + registered: AtomicBool::new(false), }) } /// Register this connection with the IO event loop. pub fn register_socket(&self, reg: Token, event_loop: &mut EventLoop) -> io::Result<()> { + if self.registered.load(AtomicOrdering::SeqCst) { + return Ok(()); + } trace!(target: "network", "connection register; token={:?}", reg); if let Err(e) = event_loop.register(&self.socket, reg, self.interest, PollOpt::edge() /* | PollOpt::oneshot() */) { // TODO: oneshot is broken on windows trace!(target: "network", "Failed to register {:?}, {:?}", reg, e); } + self.registered.store(true, AtomicOrdering::SeqCst); Ok(()) } /// Update connection registration. Should be called at the end of the IO handler. pub fn update_socket(&self, reg: Token, event_loop: &mut EventLoop) -> io::Result<()> { trace!(target: "network", "connection reregister; token={:?}", reg); - event_loop.reregister( &self.socket, reg, self.interest, PollOpt::edge() /* | PollOpt::oneshot() */ ).or_else(|e| { // TODO: oneshot is broken on windows - trace!(target: "network", "Failed to reregister {:?}, {:?}", reg, e); + if !self.registered.load(AtomicOrdering::SeqCst) { + self.register_socket(reg, event_loop) + } else { + event_loop.reregister(&self.socket, reg, self.interest, PollOpt::edge() /* | PollOpt::oneshot() */ ).unwrap_or_else(|e| { // TODO: oneshot is broken on windows + trace!(target: "network", "Failed to reregister {:?}, {:?}", reg, e); + }); Ok(()) - }) + } } /// Delete connection registration. Should be called at the end of the IO handler. @@ -266,7 +286,7 @@ pub struct EncryptedConnection { } impl EncryptedConnection { - /// Create an encrypted connection out of the handshake. Consumes a handshake object. + /// Create an encrypted connection out of the handshake. pub fn new(handshake: &mut Handshake) -> Result { let shared = try!(crypto::ecdh::agree(handshake.ecdhe.secret(), &handshake.remote_ephemeral)); let mut nonce_material = H512::new(); @@ -320,7 +340,7 @@ impl EncryptedConnection { } /// Send a packet - pub fn send_packet(&mut self, payload: &[u8]) -> Result<(), UtilError> { + pub fn send_packet(&mut self, io: &IoContext, payload: &[u8]) -> Result<(), UtilError> where Message: Send + Clone { let mut header = RlpStream::new(); let len = payload.len() as usize; header.append_raw(&[(len >> 16) as u8, (len >> 8) as u8, len as u8], 1); @@ -342,7 +362,7 @@ impl EncryptedConnection { self.egress_mac.update(&packet[32..(32 + len + padding)]); EncryptedConnection::update_mac(&mut self.egress_mac, &mut self.mac_encoder, &[0u8; 0]); self.egress_mac.clone().finalize(&mut packet[(32 + len + padding)..]); - self.connection.send(packet); + self.connection.send(io, packet); Ok(()) } @@ -417,31 +437,29 @@ impl EncryptedConnection { /// Readable IO handler. Tracker receive status and returns decoded packet if avaialable. pub fn readable(&mut self, io: &IoContext) -> Result, UtilError> where Message: Send + Clone{ io.clear_timer(self.connection.token).unwrap(); - match self.read_state { - EncryptedConnectionState::Header => { - if let Some(data) = try!(self.connection.readable()) { - try!(self.read_header(&data)); - try!(io.register_timer(self.connection.token, RECIEVE_PAYLOAD_TIMEOUT)); - } - Ok(None) - }, - EncryptedConnectionState::Payload => { - match try!(self.connection.readable()) { - Some(data) => { - self.read_state = EncryptedConnectionState::Header; - self.connection.expect(ENCRYPTED_HEADER_LEN); - Ok(Some(try!(self.read_payload(&data)))) - }, - None => Ok(None) - } + if let EncryptedConnectionState::Header = self.read_state { + if let Some(data) = try!(self.connection.readable()) { + try!(self.read_header(&data)); + try!(io.register_timer(self.connection.token, RECIEVE_PAYLOAD_TIMEOUT)); } + }; + if let EncryptedConnectionState::Payload = self.read_state { + match try!(self.connection.readable()) { + Some(data) => { + self.read_state = EncryptedConnectionState::Header; + self.connection.expect(ENCRYPTED_HEADER_LEN); + Ok(Some(try!(self.read_payload(&data)))) + }, + None => Ok(None) + } + } else { + Ok(None) } } /// Writable IO handler. Processes send queeue. pub fn writable(&mut self, io: &IoContext) -> Result<(), UtilError> where Message: Send + Clone { - io.clear_timer(self.connection.token).unwrap(); - try!(self.connection.writable()); + try!(self.connection.writable(io)); Ok(()) } } @@ -472,12 +490,14 @@ pub fn test_encryption() { mod tests { use super::*; use std::sync::*; + use std::sync::atomic::AtomicBool; use super::super::stats::*; use std::io::{Read, Write, Error, Cursor, ErrorKind}; use mio::{EventSet}; use std::collections::VecDeque; use bytes::*; use devtools::*; + use io::*; impl GenericSocket for TestSocket {} @@ -521,6 +541,7 @@ mod tests { rec_size: 0, interest: EventSet::hup() | EventSet::readable(), stats: Arc::::new(NetworkStats::new()), + registered: AtomicBool::new(false), } } } @@ -543,10 +564,15 @@ mod tests { rec_size: 0, interest: EventSet::hup() | EventSet::readable(), stats: Arc::::new(NetworkStats::new()), + registered: AtomicBool::new(false), } } } + fn test_io() -> IoContext { + IoContext::new(IoChannel::disconnected(), 0) + } + #[test] fn connection_expect() { let mut connection = TestConnection::new(); @@ -557,7 +583,7 @@ mod tests { #[test] fn connection_write_empty() { let mut connection = TestConnection::new(); - let status = connection.writable(); + let status = connection.writable(&test_io()); assert!(status.is_ok()); assert!(WriteStatus::Complete == status.unwrap()); } @@ -568,7 +594,7 @@ mod tests { let data = Cursor::new(vec![0; 10240]); connection.send_queue.push_back(data); - let status = connection.writable(); + let status = connection.writable(&test_io()); assert!(status.is_ok()); assert!(WriteStatus::Complete == status.unwrap()); assert_eq!(10240, connection.socket.write_buffer.len()); @@ -581,7 +607,7 @@ mod tests { let data = Cursor::new(vec![0; 10240]); connection.send_queue.push_back(data); - let status = connection.writable(); + let status = connection.writable(&test_io()); assert!(status.is_ok()); assert!(WriteStatus::Ongoing == status.unwrap()); @@ -594,7 +620,7 @@ mod tests { let data = Cursor::new(vec![0; 10240]); connection.send_queue.push_back(data); - let status = connection.writable(); + let status = connection.writable(&test_io()); assert!(!status.is_ok()); assert_eq!(1, connection.send_queue.len()); diff --git a/util/src/network/handshake.rs b/util/src/network/handshake.rs index e02da3d4c..90e3bc67d 100644 --- a/util/src/network/handshake.rs +++ b/util/src/network/handshake.rs @@ -111,7 +111,7 @@ impl Handshake { self.originated = originated; io.register_timer(self.connection.token, HANDSHAKE_TIMEOUT).ok(); if originated { - try!(self.write_auth(host.secret(), host.id())); + try!(self.write_auth(io, host.secret(), host.id())); } else { self.state = HandshakeState::ReadingAuth; @@ -128,17 +128,17 @@ impl Handshake { /// Readable IO handler. Drives the state change. pub fn readable(&mut self, io: &IoContext, host: &HostInfo) -> Result<(), UtilError> where Message: Send + Clone { if !self.expired() { - io.clear_timer(self.connection.token).unwrap(); + io.clear_timer(self.connection.token).ok(); match self.state { HandshakeState::New => {} HandshakeState::ReadingAuth => { if let Some(data) = try!(self.connection.readable()) { - try!(self.read_auth(host.secret(), &data)); + try!(self.read_auth(io, host.secret(), &data)); }; }, HandshakeState::ReadingAuthEip8 => { if let Some(data) = try!(self.connection.readable()) { - try!(self.read_auth_eip8(host.secret(), &data)); + try!(self.read_auth_eip8(io, host.secret(), &data)); }; }, HandshakeState::ReadingAck => { @@ -153,9 +153,6 @@ impl Handshake { }, HandshakeState::StartSession => {}, } - if self.state != HandshakeState::StartSession { - try!(io.update_registration(self.connection.token)); - } } Ok(()) } @@ -163,11 +160,7 @@ impl Handshake { /// Writabe IO handler. pub fn writable(&mut self, io: &IoContext) -> Result<(), UtilError> where Message: Send + Clone { if !self.expired() { - io.clear_timer(self.connection.token).unwrap(); - try!(self.connection.writable()); - if self.state != HandshakeState::StartSession { - io.update_registration(self.connection.token).unwrap(); - } + try!(self.connection.writable(io)); } Ok(()) } @@ -183,7 +176,7 @@ impl Handshake { } /// Parse, validate and confirm auth message - fn read_auth(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { + fn read_auth(&mut self, io: &IoContext, secret: &Secret, data: &[u8]) -> Result<(), UtilError> where Message: Send + Clone { trace!(target:"network", "Received handshake auth from {:?}", self.connection.remote_addr_str()); if data.len() != V4_AUTH_PACKET_SIZE { debug!(target:"net", "Wrong auth packet size"); @@ -197,7 +190,7 @@ impl Handshake { let (pubk, rest) = rest.split_at(64); let (nonce, _) = rest.split_at(32); try!(self.set_auth(secret, sig, pubk, nonce, PROTOCOL_VERSION)); - try!(self.write_ack()); + try!(self.write_ack(io)); } Err(_) => { // Try to interpret as EIP-8 packet @@ -214,7 +207,7 @@ impl Handshake { Ok(()) } - fn read_auth_eip8(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { + fn read_auth_eip8(&mut self, io: &IoContext, secret: &Secret, data: &[u8]) -> Result<(), UtilError> where Message: Send + Clone { trace!(target:"network", "Received EIP8 handshake auth from {:?}", self.connection.remote_addr_str()); self.auth_cipher.extend_from_slice(data); let auth = try!(ecies::decrypt(secret, &self.auth_cipher[0..2], &self.auth_cipher[2..])); @@ -224,13 +217,13 @@ impl Handshake { let remote_nonce: H256 = try!(rlp.val_at(2)); let remote_version: u64 = try!(rlp.val_at(3)); try!(self.set_auth(secret, &signature, &remote_public, &remote_nonce, remote_version)); - try!(self.write_ack_eip8()); + try!(self.write_ack_eip8(io)); Ok(()) } /// Parse and validate ack message fn read_ack(&mut self, secret: &Secret, data: &[u8]) -> Result<(), UtilError> { - trace!(target:"network", "Received handshake auth to {:?}", self.connection.remote_addr_str()); + trace!(target:"network", "Received handshake ack from {:?}", self.connection.remote_addr_str()); if data.len() != V4_ACK_PACKET_SIZE { debug!(target:"net", "Wrong ack packet size"); return Err(From::from(NetworkError::BadProtocol)); @@ -270,7 +263,7 @@ impl Handshake { } /// Sends auth message - fn write_auth(&mut self, secret: &Secret, public: &Public) -> Result<(), UtilError> { + fn write_auth(&mut self, io: &IoContext, secret: &Secret, public: &Public) -> Result<(), UtilError> where Message: Send + Clone { trace!(target:"network", "Sending handshake auth to {:?}", self.connection.remote_addr_str()); let mut data = [0u8; /*Signature::SIZE*/ 65 + /*H256::SIZE*/ 32 + /*Public::SIZE*/ 64 + /*H256::SIZE*/ 32 + 1]; //TODO: use associated constants let len = data.len(); @@ -290,14 +283,14 @@ impl Handshake { } let message = try!(crypto::ecies::encrypt(&self.id, &[], &data)); self.auth_cipher = message.clone(); - self.connection.send(message); + self.connection.send(io, message); self.connection.expect(V4_ACK_PACKET_SIZE); self.state = HandshakeState::ReadingAck; Ok(()) } /// Sends ack message - fn write_ack(&mut self) -> Result<(), UtilError> { + fn write_ack(&mut self, io: &IoContext) -> Result<(), UtilError> where Message: Send + Clone { trace!(target:"network", "Sending handshake ack to {:?}", self.connection.remote_addr_str()); let mut data = [0u8; 1 + /*Public::SIZE*/ 64 + /*H256::SIZE*/ 32]; //TODO: use associated constants let len = data.len(); @@ -310,13 +303,13 @@ impl Handshake { } let message = try!(crypto::ecies::encrypt(&self.id, &[], &data)); self.ack_cipher = message.clone(); - self.connection.send(message); + self.connection.send(io, message); self.state = HandshakeState::StartSession; Ok(()) } /// Sends EIP8 ack message - fn write_ack_eip8(&mut self) -> Result<(), UtilError> { + fn write_ack_eip8(&mut self, io: &IoContext) -> Result<(), UtilError> where Message: Send + Clone { trace!(target:"network", "Sending EIP8 handshake ack to {:?}", self.connection.remote_addr_str()); let mut rlp = RlpStream::new_list(3); rlp.append(self.ecdhe.public()); @@ -333,7 +326,7 @@ impl Handshake { let message = try!(crypto::ecies::encrypt(&self.id, &prefix, &encoded)); self.ack_cipher.extend_from_slice(&prefix); self.ack_cipher.extend_from_slice(&message); - self.connection.send(self.ack_cipher.clone()); + self.connection.send(io, self.ack_cipher.clone()); self.state = HandshakeState::StartSession; Ok(()) } @@ -347,6 +340,7 @@ mod test { use super::*; use crypto::*; use hash::*; + use io::*; use std::net::SocketAddr; use mio::tcp::TcpStream; use network::stats::NetworkStats; @@ -371,6 +365,10 @@ mod test { Handshake::new(0, to, socket, &nonce, Arc::new(NetworkStats::new())).unwrap() } + fn test_io() -> IoContext { + IoContext::new(IoChannel::disconnected(), 0) + } + #[test] fn test_handshake_auth_plain() { let mut h = create_handshake(None); @@ -387,7 +385,7 @@ mod test { a4592ee77e2bd94d0be3691f3b406f9bba9b591fc63facc016bfa8\ ".from_hex().unwrap(); - h.read_auth(&secret, &auth).unwrap(); + h.read_auth(&test_io(), &secret, &auth).unwrap(); assert_eq!(h.state, super::HandshakeState::StartSession); check_auth(&h, 4); } @@ -411,9 +409,9 @@ mod test { 3bf7678318e2d5b5340c9e488eefea198576344afbdf66db5f51204a6961a63ce072c8926c\ ".from_hex().unwrap(); - h.read_auth(&secret, &auth[0..super::V4_AUTH_PACKET_SIZE]).unwrap(); + h.read_auth(&test_io(), &secret, &auth[0..super::V4_AUTH_PACKET_SIZE]).unwrap(); assert_eq!(h.state, super::HandshakeState::ReadingAuthEip8); - h.read_auth_eip8(&secret, &auth[super::V4_AUTH_PACKET_SIZE..]).unwrap(); + h.read_auth_eip8(&test_io(), &secret, &auth[super::V4_AUTH_PACKET_SIZE..]).unwrap(); assert_eq!(h.state, super::HandshakeState::StartSession); check_auth(&h, 4); } @@ -438,9 +436,9 @@ mod test { d490\ ".from_hex().unwrap(); - h.read_auth(&secret, &auth[0..super::V4_AUTH_PACKET_SIZE]).unwrap(); + h.read_auth(&test_io(), &secret, &auth[0..super::V4_AUTH_PACKET_SIZE]).unwrap(); assert_eq!(h.state, super::HandshakeState::ReadingAuthEip8); - h.read_auth_eip8(&secret, &auth[super::V4_AUTH_PACKET_SIZE..]).unwrap(); + h.read_auth_eip8(&test_io(), &secret, &auth[super::V4_AUTH_PACKET_SIZE..]).unwrap(); assert_eq!(h.state, super::HandshakeState::StartSession); check_auth(&h, 56); let ack = h.ack_cipher.clone(); diff --git a/util/src/network/host.rs b/util/src/network/host.rs index fe139e383..e5853b8db 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -215,8 +215,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone pub fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec) -> Result<(), UtilError> { let session = self.resolve_session(peer); if let Some(session) = session { - try!(session.lock().unwrap().deref_mut().send_packet(self.protocol, packet_id as u8, &data)); - try!(self.io.update_registration(peer)); + try!(session.lock().unwrap().deref_mut().send_packet(self.io, self.protocol, packet_id as u8, &data)); } else { trace!(target: "network", "Send: Peer no longer exist") } @@ -494,7 +493,7 @@ impl Host where Message: Send + Sync + Clone { for e in self.sessions.write().unwrap().iter_mut() { let mut s = e.lock().unwrap(); if !s.keep_alive(io) { - s.disconnect(DisconnectReason::PingTimeout); + s.disconnect(io, DisconnectReason::PingTimeout); to_kill.push(s.token()); } } @@ -616,10 +615,8 @@ impl Host where Message: Send + Sync + Clone { trace!(target: "network", "Session write error: {}: {:?}", token, e); } if s.done() { - io.deregister_stream(token).expect("Error deregistering stream"); - } else { - io.update_registration(token).unwrap_or_else(|e| debug!(target: "network", "Session registration error: {:?}", e)); - } + io.deregister_stream(token).unwrap_or_else(|e| debug!("Error deregistering stream: {:?}", e)); + } } } @@ -630,62 +627,65 @@ impl Host where Message: Send + Sync + Clone { fn session_readable(&self, token: StreamToken, io: &IoContext>) { let mut ready_data: Vec = Vec::new(); - let mut packet_data: Option<(ProtocolId, PacketId, Vec)> = None; + let mut packet_data: Vec<(ProtocolId, PacketId, Vec)> = Vec::new(); let mut kill = false; let session = { self.sessions.read().unwrap().get(token).cloned() }; if let Some(session) = session.clone() { let mut s = session.lock().unwrap(); - match s.readable(io, &self.info.read().unwrap()) { - Err(e) => { - trace!(target: "network", "Session read error: {}:{:?} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); - match e { - UtilError::Network(NetworkError::Disconnect(DisconnectReason::UselessPeer)) | - UtilError::Network(NetworkError::Disconnect(DisconnectReason::IncompatibleProtocol)) => { - if let Some(id) = s.id() { - self.nodes.write().unwrap().mark_as_useless(id); + loop { + match s.readable(io, &self.info.read().unwrap()) { + Err(e) => { + trace!(target: "network", "Session read error: {}:{:?} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); + match e { + UtilError::Network(NetworkError::Disconnect(DisconnectReason::UselessPeer)) | + UtilError::Network(NetworkError::Disconnect(DisconnectReason::IncompatibleProtocol)) => { + if let Some(id) = s.id() { + self.nodes.write().unwrap().mark_as_useless(id); + } + } + _ => (), + } + kill = true; + break; + }, + Ok(SessionData::Ready) => { + if !s.info.originated { + let session_count = self.session_count(); + let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; + if session_count >= ideal_peers as usize { + s.disconnect(io, DisconnectReason::TooManyPeers); + return; + } + // Add it no node table + if let Ok(address) = s.remote_addr() { + let entry = NodeEntry { id: s.id().unwrap().clone(), endpoint: NodeEndpoint { address: address, udp_port: address.port() } }; + self.nodes.write().unwrap().add_node(Node::new(entry.id.clone(), entry.endpoint.clone())); + let mut discovery = self.discovery.lock().unwrap(); + if let Some(ref mut discovery) = *discovery.deref_mut() { + discovery.add_node(entry); + } } } - _ => (), - } - kill = true; - }, - Ok(SessionData::Ready) => { - if !s.info.originated { - let session_count = self.session_count(); - let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; - if session_count >= ideal_peers as usize { - s.disconnect(DisconnectReason::TooManyPeers); - return; - } - // Add it no node table - if let Ok(address) = s.remote_addr() { - let entry = NodeEntry { id: s.id().unwrap().clone(), endpoint: NodeEndpoint { address: address, udp_port: address.port() } }; - self.nodes.write().unwrap().add_node(Node::new(entry.id.clone(), entry.endpoint.clone())); - let mut discovery = self.discovery.lock().unwrap(); - if let Some(ref mut discovery) = *discovery.deref_mut() { - discovery.add_node(entry); + self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); + for (p, _) in self.handlers.read().unwrap().iter() { + if s.have_capability(p) { + ready_data.push(p); } } - } - self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); - for (p, _) in self.handlers.read().unwrap().iter() { - if s.have_capability(p) { - ready_data.push(p); + }, + Ok(SessionData::Packet { + data, + protocol, + packet_id, + }) => { + match self.handlers.read().unwrap().get(protocol) { + None => { warn!(target: "network", "No handler found for protocol: {:?}", protocol) }, + Some(_) => packet_data.push((protocol, packet_id, data)), } - } - }, - Ok(SessionData::Packet { - data, - protocol, - packet_id, - }) => { - match self.handlers.read().unwrap().get(protocol) { - None => { warn!(target: "network", "No handler found for protocol: {:?}", protocol) }, - Some(_) => packet_data = Some((protocol, packet_id, data)), - } - }, - Ok(SessionData::None) => {}, - } + }, + Ok(SessionData::None) => break, + } + } } if kill { self.kill_connection(token, io, true); @@ -695,11 +695,10 @@ impl Host where Message: Send + Sync + Clone { self.stats.inc_sessions(); h.connected(&NetworkContext::new(io, p, session.clone(), self.sessions.clone()), &token); } - if let Some((p, packet_id, data)) = packet_data { + for (p, packet_id, data) in packet_data { let h = self.handlers.read().unwrap().get(p).unwrap().clone(); h.read(&NetworkContext::new(io, p, session.clone(), self.sessions.clone()), &token, packet_id, &data[1..]); } - io.update_registration(token).unwrap_or_else(|e| debug!(target: "network", "Token registration error: {:?}", e)); } fn connection_timeout(&self, token: StreamToken, io: &IoContext>) { @@ -742,10 +741,8 @@ impl Host where Message: Send + Sync + Clone { h.disconnected(&NetworkContext::new(io, p, expired_session.clone(), self.sessions.clone()), &token); } if deregister { - io.deregister_stream(token).expect("Error deregistering stream"); - } else if expired_session.is_some() { - io.update_registration(token).unwrap_or_else(|e| debug!(target: "network", "Connection registration error: {:?}", e)); - } + io.deregister_stream(token).unwrap_or_else(|e| debug!("Error deregistering stream: {:?}", e)); + } } fn update_nodes(&self, io: &IoContext>, node_changes: TableUpdates) { @@ -874,7 +871,7 @@ impl IoHandler> for Host where Messa NetworkIoMessage::Disconnect(ref peer) => { let session = { self.sessions.read().unwrap().get(*peer).cloned() }; if let Some(session) = session { - session.lock().unwrap().disconnect(DisconnectReason::DisconnectRequested); + session.lock().unwrap().disconnect(io, DisconnectReason::DisconnectRequested); } trace!(target: "network", "Disconnect requested {}", peer); self.kill_connection(*peer, io, false); @@ -882,7 +879,7 @@ impl IoHandler> for Host where Messa NetworkIoMessage::DisablePeer(ref peer) => { let session = { self.sessions.read().unwrap().get(*peer).cloned() }; if let Some(session) = session { - session.lock().unwrap().disconnect(DisconnectReason::DisconnectRequested); + session.lock().unwrap().disconnect(io, DisconnectReason::DisconnectRequested); if let Some(id) = session.lock().unwrap().id() { self.nodes.write().unwrap().mark_as_useless(id) } diff --git a/util/src/network/session.rs b/util/src/network/session.rs index 7b7f16c18..d5fd33813 100644 --- a/util/src/network/session.rs +++ b/util/src/network/session.rs @@ -145,7 +145,7 @@ impl Session { }) } - fn complete_handshake(&mut self, host: &HostInfo) -> Result<(), UtilError> { + fn complete_handshake(&mut self, io: &IoContext, host: &HostInfo) -> Result<(), UtilError> where Message: Send + Sync + Clone { let connection = if let State::Handshake(ref mut h) = self.state { self.info.id = Some(h.id.clone()); try!(EncryptedConnection::new(h)) @@ -153,8 +153,8 @@ impl Session { panic!("Unexpected state"); }; self.state = State::Session(connection); - try!(self.write_hello(host)); - try!(self.send_ping()); + try!(self.write_hello(io, host)); + try!(self.send_ping(io)); Ok(()) } @@ -220,10 +220,11 @@ impl Session { } } if let Some(data) = packet_data { - return Ok(try!(self.read_packet(data, host))); + return Ok(try!(self.read_packet(io, data, host))); } if create_session { - try!(self.complete_handshake(host)); + try!(self.complete_handshake(io, host)); + io.update_registration(self.token()).unwrap_or_else(|e| debug!(target: "network", "Token registration error: {:?}", e)); } Ok(SessionData::None) } @@ -263,7 +264,8 @@ impl Session { } /// Send a protocol packet to peer. - pub fn send_packet(&mut self, protocol: &str, packet_id: u8, data: &[u8]) -> Result<(), UtilError> { + pub fn send_packet(&mut self, io: &IoContext, protocol: &str, packet_id: u8, data: &[u8]) -> Result<(), UtilError> + where Message: Send + Sync + Clone { if self.info.capabilities.is_empty() || !self.had_hello { debug!(target: "network", "Sending to unconfirmed session {}, protocol: {}, packet: {}", self.token(), protocol, packet_id); return Err(From::from(NetworkError::BadProtocol)); @@ -283,7 +285,7 @@ impl Session { let mut rlp = RlpStream::new(); rlp.append(&(pid as u32)); rlp.append_raw(data, 1); - self.send(rlp) + self.send(io, rlp) } /// Keep this session alive. Returns false if ping timeout happened @@ -298,10 +300,9 @@ impl Session { }; if !timed_out && time::precise_time_ns() - self.ping_time_ns > PING_INTERVAL_SEC * 1000_000_000 { - if let Err(e) = self.send_ping() { + if let Err(e) = self.send_ping(io) { debug!("Error sending ping message: {:?}", e); } - io.update_registration(self.token()).unwrap_or_else(|e| debug!(target: "network", "Session registration error: {:?}", e)); } !timed_out } @@ -310,7 +311,8 @@ impl Session { self.connection().token() } - fn read_packet(&mut self, packet: Packet, host: &HostInfo) -> Result { + fn read_packet(&mut self, io: &IoContext, packet: Packet, host: &HostInfo) -> Result + where Message: Send + Sync + Clone { if packet.data.len() < 2 { return Err(From::from(NetworkError::BadProtocol)); } @@ -321,7 +323,7 @@ impl Session { match packet_id { PACKET_HELLO => { let rlp = UntrustedRlp::new(&packet.data[1..]); //TODO: validate rlp expected size - try!(self.read_hello(&rlp, host)); + try!(self.read_hello(io, &rlp, host)); Ok(SessionData::Ready) }, PACKET_DISCONNECT => { @@ -330,7 +332,7 @@ impl Session { Err(From::from(NetworkError::Disconnect(DisconnectReason::from_u8(reason)))) } PACKET_PING => { - try!(self.send_pong()); + try!(self.send_pong(io)); Ok(SessionData::None) }, PACKET_PONG => { @@ -362,7 +364,7 @@ impl Session { } } - fn write_hello(&mut self, host: &HostInfo) -> Result<(), UtilError> { + fn write_hello(&mut self, io: &IoContext, host: &HostInfo) -> Result<(), UtilError> where Message: Send + Sync + Clone { let mut rlp = RlpStream::new(); rlp.append_raw(&[PACKET_HELLO as u8], 0); rlp.begin_list(5) @@ -371,10 +373,11 @@ impl Session { .append(&host.capabilities) .append(&host.local_endpoint.address.port()) .append(host.id()); - self.send(rlp) + self.send(io, rlp) } - fn read_hello(&mut self, rlp: &UntrustedRlp, host: &HostInfo) -> Result<(), UtilError> { + fn read_hello(&mut self, io: &IoContext, rlp: &UntrustedRlp, host: &HostInfo) -> Result<(), UtilError> + where Message: Send + Sync + Clone { let protocol = try!(rlp.val_at::(0)); let client_version = try!(rlp.val_at::(1)); let peer_caps = try!(rlp.val_at::>(2)); @@ -417,36 +420,36 @@ impl Session { self.info.capabilities = caps; if self.info.capabilities.is_empty() { trace!(target: "network", "No common capabilities with peer."); - return Err(From::from(self.disconnect(DisconnectReason::UselessPeer))); + return Err(From::from(self.disconnect(io, DisconnectReason::UselessPeer))); } if protocol != host.protocol_version { trace!(target: "network", "Peer protocol version mismatch: {}", protocol); - return Err(From::from(self.disconnect(DisconnectReason::UselessPeer))); + return Err(From::from(self.disconnect(io, DisconnectReason::UselessPeer))); } self.had_hello = true; Ok(()) } /// Senf ping packet - pub fn send_ping(&mut self) -> Result<(), UtilError> { - try!(self.send(try!(Session::prepare(PACKET_PING)))); + pub fn send_ping(&mut self, io: &IoContext) -> Result<(), UtilError> where Message: Send + Sync + Clone { + try!(self.send(io, try!(Session::prepare(PACKET_PING)))); self.ping_time_ns = time::precise_time_ns(); self.pong_time_ns = None; Ok(()) } - fn send_pong(&mut self) -> Result<(), UtilError> { - self.send(try!(Session::prepare(PACKET_PONG))) + fn send_pong(&mut self, io: &IoContext) -> Result<(), UtilError> where Message: Send + Sync + Clone { + self.send(io, try!(Session::prepare(PACKET_PONG))) } /// Disconnect this session - pub fn disconnect(&mut self, reason: DisconnectReason) -> NetworkError { + pub fn disconnect(&mut self, io: &IoContext, reason: DisconnectReason) -> NetworkError where Message: Send + Sync + Clone { if let State::Session(_) = self.state { let mut rlp = RlpStream::new(); rlp.append(&(PACKET_DISCONNECT as u32)); rlp.begin_list(1); rlp.append(&(reason as u32)); - self.send(rlp).ok(); + self.send(io, rlp).ok(); } NetworkError::Disconnect(reason) } @@ -458,13 +461,13 @@ impl Session { Ok(rlp) } - fn send(&mut self, rlp: RlpStream) -> Result<(), UtilError> { + fn send(&mut self, io: &IoContext, rlp: RlpStream) -> Result<(), UtilError> where Message: Send + Sync + Clone { match self.state { State::Handshake(_) => { warn!(target:"network", "Unexpected send request"); }, State::Session(ref mut s) => { - try!(s.send_packet(&rlp.out())) + try!(s.send_packet(io, &rlp.out())) }, } Ok(()) From f5efd444f511a74e6c25bda5fbbf1948f74c6f9e Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 13 Jun 2016 19:22:54 +0200 Subject: [PATCH 004/239] rustup and windows instructions --- README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 193cbeb8f..dda44a0d1 100644 --- a/README.md +++ b/README.md @@ -42,16 +42,19 @@ Parity is fully compatible with Stable Rust. We recommend installing Rust through [multirust](https://github.com/brson/multirust). If you don't already have multirust, you can install it like this: -- Linux: +- Linux and OSX: ```bash -$ curl -sf https://raw.githubusercontent.com/brson/multirust/master/quick-install.sh | sh +$ curl https://sh.rustup.rs -sSf | sh ``` -- OSX with Homebrew: -```bash -$ brew update && brew install multirust -$ multirust default stable +- Windows + +Make sure you have Visual Studio 2015 with C++ support installed, download and run [rustup](https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe) and use the following command to setup msvc toolchain: + ``` +rustup default stable-x86_64-pc-windows-msvc +``` + Then, download and build Parity: @@ -72,4 +75,4 @@ To get started, just run $ parity ``` -and parity will begin syncing the Ethereum blockchain. \ No newline at end of file +and parity will begin syncing the Ethereum blockchain. From 4c812169d1367aaab7875e1bf781c6e4d90c28e6 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 13 Jun 2016 20:26:17 +0200 Subject: [PATCH 005/239] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dda44a0d1..f807be3a4 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ below to build from source. Parity is fully compatible with Stable Rust. -We recommend installing Rust through [multirust](https://github.com/brson/multirust). If you don't already have multirust, you can install it like this: +We recommend installing Rust through [rustup](https://www.rustup.rs/). If you don't already have rustup, you can install it like this: - Linux and OSX: ```bash From bee3669e9b840a3870184a4badc5a36eb88c9079 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 31 May 2016 15:34:25 +0200 Subject: [PATCH 006/239] Deactivate peers giving us invalid/empty headers --- sync/src/chain.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 277be7fea..569b6402d 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -319,6 +319,7 @@ impl ChainSync { /// Remove peer from active peer set fn deactivate_peer(&mut self, io: &mut SyncIo, peer_id: PeerId) { + trace!(target: "sync", "Deactivating peer {}", peer_id); self.active_peers.remove(&peer_id); if self.active_peers.is_empty() { trace!(target: "sync", "No more active peers"); @@ -456,6 +457,9 @@ impl ChainSync { } }, SyncState::Blocks | SyncState::NewBlocks | SyncState::Waiting => { + if headers.len() == 0 { + self.deactivate_peer(io, peer_id); // disable the peer for this syncing round if it gives invalid chain + } trace!(target: "sync", "Inserted {} headers", headers.len()); self.blocks.insert_headers(headers); }, From 925869d46251fe1ffeb8028282e67a2b44a8525a Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 10 Jun 2016 17:12:51 +0200 Subject: [PATCH 007/239] Fix returning non-canonical headers --- sync/src/chain.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 569b6402d..cd8f43aee 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -927,7 +927,16 @@ impl ChainSync { let hash: H256 = try!(r.val_at(0)); trace!(target: "sync", "-> GetBlockHeaders (hash: {}, max: {}, skip: {}, reverse:{})", hash, max_headers, skip, reverse); match io.chain().block_header(BlockID::Hash(hash)) { - Some(hdr) => From::from(HeaderView::new(&hdr).number()), + Some(hdr) => { + let number = From::from(HeaderView::new(&hdr).number()); + if io.chain().block_hash(BlockID::Number(number)) != Some(hash) { + // Non canonical header requested, return just a single header + let mut rlp = RlpStream::new_list(1); + rlp.append_raw(&hdr, 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 { From 8c7bcdafdbc7a50b85171ef4db216616d1cce6e0 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 13 Jun 2016 15:35:21 +0200 Subject: [PATCH 008/239] Continue reading session data in the same iteration if available --- util/src/network/connection.rs | 2 +- util/src/network/host.rs | 1 + util/src/network/session.rs | 13 +++++++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/util/src/network/connection.rs b/util/src/network/connection.rs index ade06b469..f4c4c2a8d 100644 --- a/util/src/network/connection.rs +++ b/util/src/network/connection.rs @@ -436,7 +436,7 @@ impl EncryptedConnection { /// Readable IO handler. Tracker receive status and returns decoded packet if avaialable. pub fn readable(&mut self, io: &IoContext) -> Result, UtilError> where Message: Send + Clone{ - io.clear_timer(self.connection.token).unwrap(); + try!(io.clear_timer(self.connection.token)); if let EncryptedConnectionState::Header = self.read_state { if let Some(data) = try!(self.connection.readable()) { try!(self.read_header(&data)); diff --git a/util/src/network/host.rs b/util/src/network/host.rs index e5853b8db..abace1983 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -683,6 +683,7 @@ impl Host where Message: Send + Sync + Clone { Some(_) => packet_data.push((protocol, packet_id, data)), } }, + Ok(SessionData::Continue) => (), Ok(SessionData::None) => break, } } diff --git a/util/src/network/session.rs b/util/src/network/session.rs index d5fd33813..c19dfbcf8 100644 --- a/util/src/network/session.rs +++ b/util/src/network/session.rs @@ -68,6 +68,8 @@ pub enum SessionData { /// Zero based packet ID packet_id: u8, }, + /// Session has more data to be read + Continue, } /// Shared session information @@ -329,16 +331,19 @@ impl Session { PACKET_DISCONNECT => { let rlp = UntrustedRlp::new(&packet.data[1..]); let reason: u8 = try!(rlp.val_at(0)); + if self.had_hello { + debug!("Disconnected: {}: {:?}", self.token(), DisconnectReason::from_u8(reason)); + } Err(From::from(NetworkError::Disconnect(DisconnectReason::from_u8(reason)))) } PACKET_PING => { try!(self.send_pong(io)); - Ok(SessionData::None) + Ok(SessionData::Continue) }, PACKET_PONG => { self.pong_time_ns = Some(time::precise_time_ns()); self.info.ping_ms = Some((self.pong_time_ns.unwrap() - self.ping_time_ns) / 1000_000); - Ok(SessionData::None) + Ok(SessionData::Continue) }, PACKET_GET_PEERS => Ok(SessionData::None), //TODO; PACKET_PEERS => Ok(SessionData::None), @@ -348,7 +353,7 @@ impl Session { i += 1; if i == self.info.capabilities.len() { debug!(target: "network", "Unknown packet: {:?}", packet_id); - return Ok(SessionData::None) + return Ok(SessionData::Continue) } } @@ -359,7 +364,7 @@ impl Session { }, _ => { debug!(target: "network", "Unknown packet: {:?}", packet_id); - Ok(SessionData::None) + Ok(SessionData::Continue) } } } From 1dac2e3b2378ce8f0b4543a493cf2159fa9ee0e9 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 13 Jun 2016 18:49:40 +0200 Subject: [PATCH 009/239] Fixed NewHashes response --- sync/src/chain.rs | 73 ++++++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index cd8f43aee..aff82f840 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -915,7 +915,7 @@ impl ChainSync { } /// Respond to GetBlockHeaders request - fn return_block_headers(io: &SyncIo, r: &UntrustedRlp) -> RlpResponseResult { + fn return_block_headers(io: &SyncIo, r: &UntrustedRlp, peer_id: PeerId) -> RlpResponseResult { // Packet layout: // [ block: { P , B_32 }, maxHeaders: P, skip: P, reverse: P in { 0 , 1 } ] let max_headers: usize = try!(r.val_at(1)); @@ -925,12 +925,14 @@ impl ChainSync { let number = if try!(r.at(0)).size() == 32 { // id is a hash let hash: H256 = try!(r.val_at(0)); - trace!(target: "sync", "-> GetBlockHeaders (hash: {}, max: {}, skip: {}, reverse:{})", hash, max_headers, skip, reverse); + 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 = From::from(HeaderView::new(&hdr).number()); - if io.chain().block_hash(BlockID::Number(number)) != Some(hash) { - // Non canonical header requested, return just a single header + assert_eq!(HeaderView::new(&hdr).sha3(), hash); + if max_headers == 1 || io.chain().block_hash(BlockID::Number(number)) != Some(hash) { + // Non canonical header or single header requested + trace!("Returning single header: {:?}", hash); let mut rlp = RlpStream::new_list(1); rlp.append_raw(&hdr, 1); return Ok(Some((BLOCK_HEADERS_PACKET, rlp))); @@ -940,7 +942,7 @@ impl ChainSync { 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:{})", try!(r.val_at::(0)), max_headers, skip, reverse); + trace!(target: "sync", "{} -> GetBlockHeaders (number: {}, max: {}, skip: {}, reverse:{})", peer_id, try!(r.val_at::(0)), max_headers, skip, reverse); try!(r.val_at(0)) }; @@ -975,13 +977,13 @@ impl ChainSync { } /// Respond to GetBlockBodies request - fn return_block_bodies(io: &SyncIo, r: &UntrustedRlp) -> RlpResponseResult { + fn return_block_bodies(io: &SyncIo, r: &UntrustedRlp, peer_id: PeerId) -> RlpResponseResult { let mut count = r.item_count(); if count == 0 { debug!(target: "sync", "Empty GetBlockBodies request, ignoring."); return Ok(None); } - trace!(target: "sync", "-> GetBlockBodies: {} entries", count); + trace!(target: "sync", "{} -> GetBlockBodies: {} entries", peer_id, count); count = min(count, MAX_BODIES_TO_SEND); let mut added = 0usize; let mut data = Bytes::new(); @@ -998,8 +1000,9 @@ impl ChainSync { } /// Respond to GetNodeData request - fn return_node_data(io: &SyncIo, r: &UntrustedRlp) -> RlpResponseResult { + fn return_node_data(io: &SyncIo, r: &UntrustedRlp, peer_id: PeerId) -> RlpResponseResult { let mut count = r.item_count(); + trace!(target: "sync", "{} -> GetNodeData: {} entries", peer_id, count); if count == 0 { debug!(target: "sync", "Empty GetNodeData request, ignoring."); return Ok(None); @@ -1013,13 +1016,15 @@ impl ChainSync { added += 1; } } + trace!(target: "sync", "{} -> GetNodeData: return {} entries", peer_id, added); let mut rlp = RlpStream::new_list(added); rlp.append_raw(&data, added); Ok(Some((NODE_DATA_PACKET, rlp))) } - fn return_receipts(io: &SyncIo, rlp: &UntrustedRlp) -> RlpResponseResult { + fn return_receipts(io: &SyncIo, rlp: &UntrustedRlp, peer_id: PeerId) -> RlpResponseResult { let mut count = rlp.item_count(); + trace!(target: "sync", "{} -> GetReceipts: {} entries", peer_id, count); if count == 0 { debug!(target: "sync", "Empty GetReceipts request, ignoring."); return Ok(None); @@ -1041,11 +1046,11 @@ impl ChainSync { Ok(Some((RECEIPTS_PACKET, rlp_result))) } - fn return_rlp(&self, io: &mut SyncIo, rlp: &UntrustedRlp, rlp_func: FRlp, error_func: FError) -> Result<(), PacketDecodeError> - where FRlp : Fn(&SyncIo, &UntrustedRlp) -> RlpResponseResult, + fn return_rlp(&self, io: &mut SyncIo, rlp: &UntrustedRlp, peer: PeerId, rlp_func: FRlp, error_func: FError) -> Result<(), PacketDecodeError> + where FRlp : Fn(&SyncIo, &UntrustedRlp, PeerId) -> RlpResponseResult, FError : FnOnce(UtilError) -> String { - let response = rlp_func(io, rlp); + let response = rlp_func(io, rlp, peer); match response { Err(e) => Err(e), Ok(Some((packet_id, rlp_stream))) => { @@ -1073,19 +1078,19 @@ impl ChainSync { NEW_BLOCK_PACKET => self.on_peer_new_block(io, peer, &rlp), NEW_BLOCK_HASHES_PACKET => self.on_peer_new_hashes(io, peer, &rlp), - GET_BLOCK_BODIES_PACKET => self.return_rlp(io, &rlp, + GET_BLOCK_BODIES_PACKET => self.return_rlp(io, &rlp, peer, ChainSync::return_block_bodies, |e| format!("Error sending block bodies: {:?}", e)), - GET_BLOCK_HEADERS_PACKET => self.return_rlp(io, &rlp, + GET_BLOCK_HEADERS_PACKET => self.return_rlp(io, &rlp, peer, ChainSync::return_block_headers, |e| format!("Error sending block headers: {:?}", e)), - GET_RECEIPTS_PACKET => self.return_rlp(io, &rlp, + GET_RECEIPTS_PACKET => self.return_rlp(io, &rlp, peer, ChainSync::return_receipts, |e| format!("Error sending receipts: {:?}", e)), - GET_NODE_DATA_PACKET => self.return_rlp(io, &rlp, + GET_NODE_DATA_PACKET => self.return_rlp(io, &rlp, peer, ChainSync::return_node_data, |e| format!("Error sending nodes: {:?}", e)), @@ -1103,7 +1108,7 @@ impl ChainSync { let tick = time::precise_time_s(); for (peer_id, peer) in &self.peers { if peer.asking != PeerAsking::Nothing && (tick - peer.ask_time) > CONNECTION_TIMEOUT_SEC { - trace!(target:"sync", "Timeouted {}", peer_id); + trace!(target:"sync", "Timeout {}", peer_id); io.disconnect_peer(*peer_id); } } @@ -1129,10 +1134,10 @@ impl ChainSync { let mut rlp_stream = RlpStream::new_list(blocks.len()); for block_hash in blocks { let mut hash_rlp = RlpStream::new_list(2); - let difficulty = chain.block_total_difficulty(BlockID::Hash(block_hash.clone())).expect("Malformed block without a difficulty on the chain!"); + let number = HeaderView::new(&chain.block_header(BlockID::Hash(block_hash.clone())).expect("Malformed block without a header on the chain!")).number(); hash_rlp.append(&block_hash); - hash_rlp.append(&difficulty); - rlp_stream.append_raw(&hash_rlp.out(), 1); + hash_rlp.append(&number); + rlp_stream.append_raw(&hash_rlp.as_raw(), 1); } Some(rlp_stream.out()) } @@ -1184,6 +1189,7 @@ impl ChainSync { /// propagates latest block to lagging peers fn propagate_blocks(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo) -> usize { let lucky_peers = self.select_lagging_peers(chain_info, io); + trace!("Sending NewBlocks to {:?}", lucky_peers); let mut sent = 0; for (peer_id, _) in lucky_peers { let rlp = ChainSync::create_latest_block_rlp(io.chain()); @@ -1198,6 +1204,7 @@ impl ChainSync { /// propagates new known hashes to all peers fn propagate_new_hashes(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo) -> usize { let lucky_peers = self.select_lagging_peers(chain_info, io); + trace!("Sending NewHashes to {:?}", lucky_peers); let mut sent = 0; let last_parent = HeaderView::new(&io.chain().block_header(BlockID::Hash(chain_info.best_block_hash.clone())).unwrap()).parent_hash(); for (peer_id, peer_number) in lucky_peers { @@ -1351,7 +1358,7 @@ mod tests { let mut queue = VecDeque::new(); let io = TestIo::new(&mut client, &mut queue, None); - let result = ChainSync::return_receipts(&io, &UntrustedRlp::new(&[0xc0])); + let result = ChainSync::return_receipts(&io, &UntrustedRlp::new(&[0xc0]), 0); assert!(result.is_ok()); } @@ -1371,7 +1378,7 @@ mod tests { let receipts_request = receipt_list.out(); // it returns rlp ONLY for hashes started with "f" - let result = ChainSync::return_receipts(&io, &UntrustedRlp::new(&receipts_request.clone())); + let result = ChainSync::return_receipts(&io, &UntrustedRlp::new(&receipts_request.clone()), 0); assert!(result.is_ok()); let rlp_result = result.unwrap(); @@ -1419,33 +1426,33 @@ mod tests { let io = TestIo::new(&mut client, &mut queue, None); let unknown: H256 = H256::new(); - let result = ChainSync::return_block_headers(&io, &UntrustedRlp::new(&make_hash_req(&unknown, 1, 0, false))); + let result = ChainSync::return_block_headers(&io, &UntrustedRlp::new(&make_hash_req(&unknown, 1, 0, false)), 0); assert!(to_header_vec(result).is_empty()); - let result = ChainSync::return_block_headers(&io, &UntrustedRlp::new(&make_hash_req(&unknown, 1, 0, true))); + let result = ChainSync::return_block_headers(&io, &UntrustedRlp::new(&make_hash_req(&unknown, 1, 0, true)), 0); assert!(to_header_vec(result).is_empty()); - let result = ChainSync::return_block_headers(&io, &UntrustedRlp::new(&make_hash_req(&hashes[2], 1, 0, true))); + let result = ChainSync::return_block_headers(&io, &UntrustedRlp::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, &UntrustedRlp::new(&make_hash_req(&hashes[2], 1, 0, false))); + let result = ChainSync::return_block_headers(&io, &UntrustedRlp::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, &UntrustedRlp::new(&make_hash_req(&hashes[50], 3, 5, false))); + let result = ChainSync::return_block_headers(&io, &UntrustedRlp::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, &UntrustedRlp::new(&make_hash_req(&hashes[50], 3, 5, true))); + let result = ChainSync::return_block_headers(&io, &UntrustedRlp::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, &UntrustedRlp::new(&make_num_req(2, 1, 0, true))); + let result = ChainSync::return_block_headers(&io, &UntrustedRlp::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, &UntrustedRlp::new(&make_num_req(2, 1, 0, false))); + let result = ChainSync::return_block_headers(&io, &UntrustedRlp::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, &UntrustedRlp::new(&make_num_req(50, 3, 5, false))); + let result = ChainSync::return_block_headers(&io, &UntrustedRlp::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, &UntrustedRlp::new(&make_num_req(50, 3, 5, true))); + let result = ChainSync::return_block_headers(&io, &UntrustedRlp::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()]); } @@ -1463,7 +1470,7 @@ mod tests { let node_request = node_list.out(); // it returns rlp ONLY for hashes started with "f" - let result = ChainSync::return_node_data(&io, &UntrustedRlp::new(&node_request.clone())); + let result = ChainSync::return_node_data(&io, &UntrustedRlp::new(&node_request.clone()), 0); assert!(result.is_ok()); let rlp_result = result.unwrap(); From 0b8710a2a172dd7fd3775134639ab68bb3558561 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 14 Jun 2016 03:04:06 +0200 Subject: [PATCH 010/239] removed redundant if condition --- ethcore/src/miner/miner.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 2df0c184b..ec232d238 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -492,7 +492,7 @@ impl MinerService for Miner { trace!(target: "miner", "Miner sleeping (current {}, last {})", current_no, last_request); self.sealing_enabled.store(false, atomic::Ordering::Relaxed); self.sealing_work.lock().unwrap().reset(); - } else if self.sealing_enabled.load(atomic::Ordering::Relaxed) { + } else { self.prepare_sealing(chain); } } From 5c019b74e40d91f17b860bae60b9ac4c27ec4675 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 14 Jun 2016 11:29:40 +0200 Subject: [PATCH 011/239] Validate header response --- sync/src/chain.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index aff82f840..0f7a138f8 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -384,6 +384,7 @@ impl ChainSync { /// 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: &UntrustedRlp) -> Result<(), PacketDecodeError> { self.clear_peer_download(peer_id); + let expected_hash = self.peers.get(&peer_id).and_then(|p| p.asking_hash); let expected_asking = if self.state == SyncState::ChainHead { PeerAsking::Heads } else { PeerAsking::BlockHeaders }; if !self.reset_peer_asking(peer_id, expected_asking) { trace!(target: "sync", "Ignored unexpected headers"); @@ -409,9 +410,15 @@ impl ChainSync { let mut headers = Vec::new(); let mut hashes = Vec::new(); + let mut valid_response = false; for i in 0..item_count { let info: BlockHeader = try!(r.val_at(i)); let number = BlockNumber::from(info.number); + if !valid_response { + if let Some(expected) = expected_hash { + valid_response = expected == info.hash() + } + } if self.blocks.contains(&info.hash()) { trace!(target: "sync", "Skipping existing block header {} ({:?})", number, info.hash()); continue; @@ -442,6 +449,10 @@ impl ChainSync { } } + if !valid_response { + trace!(target: "sync", "{} Disabled for invalid headers response", peer_id); + self.deactivate_peer(io, peer_id); // disable the peer for this syncing round if it gives invalid chain + } match self.state { SyncState::ChainHead => { if headers.is_empty() { @@ -457,9 +468,6 @@ impl ChainSync { } }, SyncState::Blocks | SyncState::NewBlocks | SyncState::Waiting => { - if headers.len() == 0 { - self.deactivate_peer(io, peer_id); // disable the peer for this syncing round if it gives invalid chain - } trace!(target: "sync", "Inserted {} headers", headers.len()); self.blocks.insert_headers(headers); }, @@ -835,6 +843,9 @@ impl ChainSync { rlp.append(&skip); rlp.append(&if reverse {1u32} else {0u32}); self.send_request(sync, peer_id, asking, GET_BLOCK_HEADERS_PACKET, rlp.out()); + if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { + peer.asking_hash = Some(h.clone()); + } } /// Request block bodies from a peer From 9ed2122ae2ccb7d3108a29566998f27fcd58694b Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 14 Jun 2016 12:18:20 +0200 Subject: [PATCH 012/239] Style + comments --- sync/src/chain.rs | 58 ++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 0f7a138f8..10d49edab 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -414,6 +414,7 @@ impl ChainSync { for i in 0..item_count { let info: BlockHeader = try!(r.val_at(i)); let number = BlockNumber::from(info.number); + // Check if any of the headers matches the hash we requested if !valid_response { if let Some(expected) = expected_hash { valid_response = expected == info.hash() @@ -449,29 +450,32 @@ impl ChainSync { } } + // Disable the peer for this syncing round if it gives invalid chain if !valid_response { trace!(target: "sync", "{} Disabled for invalid headers response", peer_id); - self.deactivate_peer(io, peer_id); // disable the peer for this syncing round if it gives invalid chain + self.deactivate_peer(io, peer_id); } - match self.state { - SyncState::ChainHead => { - if headers.is_empty() { - // peer is not on our chain - // track back and try again - self.imported_this_round = Some(0); - self.start_sync_round(io); - } else { - // TODO: validate heads better. E.g. check that there is enough distance between blocks. - trace!(target: "sync", "Received {} subchain heads, proceeding to download", headers.len()); - self.blocks.reset_to(hashes); - self.state = SyncState::Blocks; - } - }, - SyncState::Blocks | SyncState::NewBlocks | SyncState::Waiting => { - trace!(target: "sync", "Inserted {} headers", headers.len()); - self.blocks.insert_headers(headers); - }, - _ => trace!(target: "sync", "Unexpected headers({}) from {} ({}), state = {:?}", headers.len(), peer_id, io.peer_info(peer_id), self.state) + else { + match self.state { + SyncState::ChainHead => { + if headers.is_empty() { + // peer is not on our chain + // track back and try again + self.imported_this_round = Some(0); + self.start_sync_round(io); + } else { + // TODO: validate heads better. E.g. check that there is enough distance between blocks. + trace!(target: "sync", "Received {} subchain heads, proceeding to download", headers.len()); + self.blocks.reset_to(hashes); + self.state = SyncState::Blocks; + } + }, + SyncState::Blocks | SyncState::NewBlocks | SyncState::Waiting => { + trace!(target: "sync", "Inserted {} headers", headers.len()); + self.blocks.insert_headers(headers); + }, + _ => trace!(target: "sync", "Unexpected headers({}) from {} ({}), state = {:?}", headers.len(), peer_id, io.peer_info(peer_id), self.state) + } } self.collect_blocks(io); @@ -843,9 +847,9 @@ impl ChainSync { rlp.append(&skip); rlp.append(&if reverse {1u32} else {0u32}); self.send_request(sync, peer_id, asking, GET_BLOCK_HEADERS_PACKET, rlp.out()); - if let Some(ref mut peer) = self.peers.get_mut(&peer_id) { - peer.asking_hash = Some(h.clone()); - } + 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") + .asking_hash = Some(h.clone()); } /// Request block bodies from a peer @@ -940,10 +944,11 @@ impl ChainSync { match io.chain().block_header(BlockID::Hash(hash)) { Some(hdr) => { let number = From::from(HeaderView::new(&hdr).number()); - assert_eq!(HeaderView::new(&hdr).sha3(), hash); + debug_assert_eq!(HeaderView::new(&hdr).sha3(), hash); if max_headers == 1 || io.chain().block_hash(BlockID::Number(number)) != Some(hash) { // Non canonical header or single header requested - trace!("Returning single header: {:?}", hash); + // 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, 1); return Ok(Some((BLOCK_HEADERS_PACKET, rlp))); @@ -1145,7 +1150,8 @@ impl ChainSync { let mut rlp_stream = RlpStream::new_list(blocks.len()); for block_hash in blocks { let mut hash_rlp = RlpStream::new_list(2); - let number = HeaderView::new(&chain.block_header(BlockID::Hash(block_hash.clone())).expect("Malformed block without a header on the chain!")).number(); + let number = HeaderView::new(&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); From dbddb6a5667e0581941b7f33f76e1ff439b12ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 14 Jun 2016 12:23:01 +0200 Subject: [PATCH 013/239] Fixing generating new token while another parity instance is running. (#1272) --- parity/main.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 679bc012a..284dac673 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -109,6 +109,11 @@ fn execute(conf: Configuration) { return; } + if conf.args.cmd_signer { + execute_signer(conf); + return; + } + let spec = conf.spec(); let client_config = conf.client_config(&spec); @@ -133,11 +138,6 @@ fn execute(conf: Configuration) { return; } - if conf.args.cmd_signer { - execute_signer(conf); - return; - } - execute_client(conf, spec, client_config); } From 65d42d6a5a25a58f4bb2f31d1d1fc178bc0fe9ad Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 14 Jun 2016 13:25:06 +0200 Subject: [PATCH 014/239] Fixed valid response condition --- sync/src/chain.rs | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 10d49edab..90e18d8e8 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -410,7 +410,7 @@ impl ChainSync { let mut headers = Vec::new(); let mut hashes = Vec::new(); - let mut valid_response = false; + let mut valid_response = item_count == 0; //empty response is valid for i in 0..item_count { let info: BlockHeader = try!(r.val_at(i)); let number = BlockNumber::from(info.number); @@ -455,27 +455,25 @@ impl ChainSync { trace!(target: "sync", "{} Disabled for invalid headers response", peer_id); self.deactivate_peer(io, peer_id); } - else { - match self.state { - SyncState::ChainHead => { - if headers.is_empty() { - // peer is not on our chain - // track back and try again - self.imported_this_round = Some(0); - self.start_sync_round(io); - } else { - // TODO: validate heads better. E.g. check that there is enough distance between blocks. - trace!(target: "sync", "Received {} subchain heads, proceeding to download", headers.len()); - self.blocks.reset_to(hashes); - self.state = SyncState::Blocks; - } - }, - SyncState::Blocks | SyncState::NewBlocks | SyncState::Waiting => { - trace!(target: "sync", "Inserted {} headers", headers.len()); - self.blocks.insert_headers(headers); - }, - _ => trace!(target: "sync", "Unexpected headers({}) from {} ({}), state = {:?}", headers.len(), peer_id, io.peer_info(peer_id), self.state) - } + match self.state { + SyncState::ChainHead => { + if headers.is_empty() { + // peer is not on our chain + // track back and try again + self.imported_this_round = Some(0); + self.start_sync_round(io); + } else { + // TODO: validate heads better. E.g. check that there is enough distance between blocks. + trace!(target: "sync", "Received {} subchain heads, proceeding to download", headers.len()); + self.blocks.reset_to(hashes); + self.state = SyncState::Blocks; + } + }, + SyncState::Blocks | SyncState::NewBlocks | SyncState::Waiting => { + trace!(target: "sync", "Inserted {} headers", headers.len()); + self.blocks.insert_headers(headers); + }, + _ => trace!(target: "sync", "Unexpected headers({}) from {} ({}), state = {:?}", headers.len(), peer_id, io.peer_info(peer_id), self.state) } self.collect_blocks(io); From 7610d308e83056dce4e1d0961c1d8562d0f26637 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 14 Jun 2016 15:17:17 +0200 Subject: [PATCH 015/239] fixed #1255 --- rpc/src/v1/impls/eth.rs | 11 ++++++++++- rpc/src/v1/tests/mocked/eth.rs | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index b0d6abcf0..ac123c565 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -212,6 +212,7 @@ fn from_params_default_third(params: Params) -> Result<(F1, F2, BlockNum // must be in range [-32099, -32000] const UNSUPPORTED_REQUEST_CODE: i64 = -32000; +const NO_WORK_CODE: i64 = -32001; fn make_unsupported_err() -> Error { Error { @@ -221,6 +222,14 @@ fn make_unsupported_err() -> Error { } } +fn no_work_err() -> Error { + Error { + code: ErrorCode::ServerError(NO_WORK_CODE), + message: "Mining not ready.".into(), + data: None + } +} + impl Eth for EthClient where C: MiningBlockChainClient + 'static, S: SyncProvider + 'static, @@ -460,7 +469,7 @@ impl Eth for EthClient where //let sync = take_weak!(self.sync); if /*sync.status().state != SyncState::Idle ||*/ client.queue_info().total_queue_size() > MAX_QUEUE_SIZE_TO_MINE_ON { trace!(target: "miner", "Syncing. Cannot give any work."); - return to_value(&(String::new(), String::new(), String::new())); + return Err(no_work_err()); } } diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 34708e232..801a74f1d 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -732,7 +732,7 @@ fn returns_no_work_if_cant_mine() { eth_tester.client.set_queue_size(10); let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":["","",""],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32001,"message":"Mining not ready.","data":null},"id":1}"#; assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned())); } From 5920a7068f3dcfcc15d411d06f0c75d9de9dbb71 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 14 Jun 2016 17:12:46 +0300 Subject: [PATCH 016/239] installer initial, ui option for executable --- Cargo.lock | 1 + Cargo.toml | 3 ++ nsis/installer.nsi | 124 +++++++++++++++++++++++++++++++++++++++++++++ nsis/logo.ico | Bin 0 -> 99678 bytes parity/cli.rs | 2 + parity/main.rs | 5 ++ parity/url.rs | 57 +++++++++++++++++++++ 7 files changed, 192 insertions(+) create mode 100644 nsis/installer.nsi create mode 100644 nsis/logo.ico create mode 100644 parity/url.rs diff --git a/Cargo.lock b/Cargo.lock index c850940c9..e941d1042 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,6 +30,7 @@ dependencies = [ "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ff624fa1f..9f4c34c0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,9 @@ ethcore-ipc = { path = "ipc/rpc" } json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } ansi_term = "0.7" +[target.'cfg(windows)'.dependencies] +winapi = "0.2" + [target.'cfg(not(windows))'.dependencies] daemonize = "0.2" diff --git a/nsis/installer.nsi b/nsis/installer.nsi new file mode 100644 index 000000000..a245fbd31 --- /dev/null +++ b/nsis/installer.nsi @@ -0,0 +1,124 @@ +# This installs two files, app.exe and logo.ico, creates a start menu shortcut, builds an uninstaller, and +# adds uninstall information to the registry for Add/Remove Programs + +# To get started, put this script into a folder with the two files (app.exe, logo.ico, and license.rtf - +# You'll have to create these yourself) and run makensis on it + +# If you change the names "app.exe", "logo.ico", or "license.rtf" you should do a search and replace - they +# show up in a few places. +# All the other settings can be tweaked by editing the !defines at the top of this script +!define APPNAME "Parity" +!define COMPANYNAME "ETHCORE" +!define DESCRIPTION "Fast, light, robust Ethereum implementation" +# These three must be integers +!define VERSIONMAJOR 1 +!define VERSIONMINOR 2 +!define VERSIONBUILD 0 +# These will be displayed by the "Click here for support information" link in "Add/Remove Programs" +# It is possible to use "mailto:" links in here to open the email client +!define HELPURL "https://github.com/ethcore/parity/wiki" # "Support Information" link +!define UPDATEURL "https://github.com/ethcore/parity/releases" # "Product Updates" link +!define ABOUTURL "https://github.com/ethcore/parity" # "Publisher" link +# This is the size (in kB) of all the files copied into "Program Files" +!define INSTALLSIZE 26120 + +RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on) + +InstallDir "$PROGRAMFILES\${COMPANYNAME}\${APPNAME}" + +# rtf or txt file - remember if it is txt, it must be in the DOS text format (\r\n) +LicenseData "..\LICENSE" +# This will be in the installer/uninstaller's title bar +Name "${COMPANYNAME} ${APPNAME}" +Icon "logo.ico" +outFile "installer.exe" + +!include LogicLib.nsh + +# Just three pages - license agreement, install location, and installation +page license +page directory +Page instfiles + +!macro VerifyUserIsAdmin +UserInfo::GetAccountType +pop $0 +${If} $0 != "admin" ;Require admin rights on NT4+ + messageBox mb_iconstop "Administrator rights required!" + setErrorLevel 740 ;ERROR_ELEVATION_REQUIRED + quit +${EndIf} +!macroend + +function .onInit + setShellVarContext all + !insertmacro VerifyUserIsAdmin +functionEnd + +section "install" + # Files for the install directory - to build the installer, these should be in the same directory as the install script (this file) + setOutPath $INSTDIR + # Files added here should be removed by the uninstaller (see section "uninstall") + file /oname=parity.exe ..\target\release\parity.exe + file "logo.ico" + # Add any other files for the install directory (license files, app data, etc) here + + # Uninstaller - See function un.onInit and section "uninstall" for configuration + writeUninstaller "$INSTDIR\uninstall.exe" + + # Start Menu + createDirectory "$SMPROGRAMS\${COMPANYNAME}" + createShortCut "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" "$INSTDIR\parity.exe" "ui" "$INSTDIR\logo.ico" + + # Registry information for add/remove programs + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayName" "${COMPANYNAME} - ${APPNAME} - ${DESCRIPTION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "InstallLocation" "$\"$INSTDIR$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayIcon" "$\"$INSTDIR\logo.ico$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "Publisher" "$\"${COMPANYNAME}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "HelpLink" "$\"${HELPURL}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "URLUpdateInfo" "$\"${UPDATEURL}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "URLInfoAbout" "$\"${ABOUTURL}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayVersion" "$\"${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}$\"" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "VersionMajor" ${VERSIONMAJOR} + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "VersionMinor" ${VERSIONMINOR} + # There is no option for modifying or repairing the install + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "NoRepair" 1 + # Set the INSTALLSIZE constant (!defined at the top of this script) so Add/Remove Programs can accurately report the size + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "EstimatedSize" ${INSTALLSIZE} +sectionEnd + +# Uninstaller + +function un.onInit + SetShellVarContext all + + #Verify the uninstaller - last chance to back out + MessageBox MB_OKCANCEL "Permanantly remove ${APPNAME}?" IDOK next + Abort + next: + !insertmacro VerifyUserIsAdmin +functionEnd + +section "uninstall" + + # Remove Start Menu launcher + delete "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" + # Try to remove the Start Menu folder - this will only happen if it is empty + rmDir "$SMPROGRAMS\${COMPANYNAME}" + + # Remove files + delete $INSTDIR\parity.exe + delete $INSTDIR\logo.ico + + # Always delete uninstaller as the last action + delete $INSTDIR\uninstall.exe + + # Try to remove the install directory - this will only happen if it is empty + rmDir $INSTDIR + + # Remove uninstaller information from the registry + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" +sectionEnd diff --git a/nsis/logo.ico b/nsis/logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..4fbaa4d39cff498e1cba9deda57b3fd031e98ae4 GIT binary patch literal 99678 zcmeI5cd%APmcZXs?N;qyTl>#e?aaC(h@glfiWooyK|rE_WJwYQC1)^@Gm>-8Dme!O z8MC0`2*w#BVxAc%&-9+(dGu$$`)>H|_acu=)#HA*Z|6RJ`sB{a`bE~iXZ_cIWy!x% zSr7eNR#q#1mCAm9O447Dv`UpOzL(9)>ha%MSv6~Bzh7G`E9*b2Wo3;XeewN2evx(S zV_8|($}3ftlD}W*|58Tk@&5bu|NPPvx4&!4Ty2^*Y-IZOe%K7?)7La>)Y#l`ZTYnN zdCQHJOsi(i%}v)|Z(84fziE7LeRIbxRrFc2+MSVgw7$QE=4soqmAU4sGUmFg%bK<= zTWT8hUir&k1=ewI?R(7i*Ia9O-hBNHrd+Ag=IUQxsdY4O(!^YK#s8V+P44q8Pd>(3 zwMuqh%gY?tb>Vl7s?|)r+OdJkSGJsK-nfZ=qc82-v`u}pZIt=HUuzzo z*Ob0W=01BK`Oa_ZWj^ZFsvWqNe5)wyOg`4TVcmKYURi z^#DiSe8u5CE6bR?{DEgm$zM(Rvv_8-;xb8a{uPI@CVeP=xISu4z}-Uz3^e0Lk5=4K z`hTw|(0v4c2hTq7=%Z%*n6bL=S1es-rcRn9c%hFO^Z4Ut!q~BTwt$bK`XA>zV_PtH zuIb&QhpBX31wCs9_a9(t3hpl}IA!{jsoEar5;%U*{P}ve#c3lf@8AIg3LJ3+%<~Nh7KH*!l#^P(JmpQ0X=_WH`$dFWBWv?t{W=@}>@0@qHSH4Am z4;wt#RF`wij)Qa6?>w^K(|t~vI7!bPoBy$qBTbb`l?-cgQ-$kw%$$#m`N?V1bI<|6 z2K}{V<33w8zu&ZJkxgSzwyB&KT|0Hw`YPX0G1XS(iZ^N+Ys9+Pc7T<~M~zCo+w^pv zoXhmz=4Fh`1@D}>_Uz=n)Wx~r_rpDV>OQgM*c*4svfsY&~IoQ;EC^ybNuKrsd)$HsMD`3YeG8D zb!*n7`VXzprDG@GGTwT!`#;s(dFyTF@sXp<=*J$DdT!SJ#Q0cKZyEbuPUx!&<;p2O zs#mL)>EEZ1nK*Ww(kkFA=rx-+=-KIk2h5gDo3svhjoY+nVY*#}y`ZwBv)1epn}@k- z-=>Y=uX$$nlQUE4_Ph7lR^Yv7*RDEF=u`V0m}B3U5xBHze$UAQCsl;jcfUb<-&3Qe z;%+xR=r{NjTCGxr3g#BsTa1Ax^}74ZTON9@W4i~;4bonA`RkQ#1P4qSH(vLRw~XKW z%>qB8h7C`Rfwn7LT)RR2`kQJ38{Trv%e2XpHNCX-mpt}N1YdV(+b&lbZyoMC=S#JV zIG=R-#CiaOGp1&rH*S8;Vw>Ncf6agKd~)+g{id9IhOjT-;V9Rnego6#f%d8K+^T29 zP<;mvfV*t{?%8G2(tS2-EbHma8~cm3rM$bIQzuPU7@=L42Llg`8vgS-rrWNY54?A6 znKG&Iu>XO_N^vnWF1u-!pl_uZ|i%BGo>1*!3Or*yCpP ziWTNcfeZTM;ziCb%X4MYu3Kh+;4$zDFaiI>xS8{wUAvjq($3@w6O<-nt>C9v2fG*C zdNTbD+^<@`!o2X@bGpARAIiQ4E;*0bYw*Y5&b@o~2#s)4jycP;ZMPhA0REXEIGuBq zbA>eUC1=#wC!R2k>(|$P>Xs{r-{6B@-Fv9apoa8;c_@f>k~%Lv-Ym|VIii3f`H7qY z5o%}oOUWrjmg@Z%XG}@nk`1%T`X=jJl3<|rT{T3`&_Z~t{FPf3)Eq$v!Y8g=zTE8D zwcC90`RC@N4?i@|9Xx2ZZ{2DJ_3J16$_>Se9)T}G7qjWDdWbnQ zXPP=S?>5hDd`fx5E*(3n{NTX8{bu60afbCNsJTq1UgTPPckj{uyE24|<;$DrpM5q( z_m6q}3Dc)n?^Iu*3DLEzS+z>@U01g7bsY`r)K%J@aiT+lFNS7@k7F%rRlh6MU-B@{ z>bKva@>BBOdecqHcffNlU$P`e-gM?JuX%uJ%lo@^AqSW;aiYp);roz{(QkNygZmHo z@&NEK=n36=3i9``L4#EW{_3l9$bwl5#$&&C zY}d}roi#i4ZqwNVt5>efm2SW1-Ars0mM>YFN@p#QuY2>^cjVr#{05l{XPEtNpPc8etlOq% z`h0rB#$2`p$g^H}?)e-#DEb~XZ^&YSMcbEIGiI0vJ9J3B+w^^V_Nwg8zGwQxF2a@X zgGbPLy!_HjIq(hoLU3zTJCt|zdC1z{J9kd?8Lo`=?mMfS4eQoL))&^^RYFfP$F#xU zh#^DG;TK*oBZm!B{DR!i&UcNfx%X^P-N;Vu+0A*@t9y5qS3;w*udPmX-t0L-C;8j| z1l8@PPY~S>@<8UFvk4uc?JxNr?)i|yDY{a|=a!B7jeQaOYR|4+Im*?nR?Vzgxyo$Y zvQ>Ep+I8VAs$Tn@Ir#d*1@rXAjVjx<>E7p_ox2Qc?M;t*XS~cew2@z4U}@HjC(XOR zc~@k}V|?@Ym9uHkE=LX>5_<8LKzvAEbTChC*buvZ__8Gn7o})y+pc|PpLw^co*`3R z1A0bi0`wKE_l+JMBXb1pJa^VCgZ@lh0rFp3Pt~>5f-p%f@Wx^LU ztXD7N{!>46`;vtVbJW3^iS3(fBi32;Ug$f5=EA14uh2!mv27TPPe!ZUS1=(M3-PjGm zUqGjf7JG+%Lgyl+XLYf#lPfP*z}K!+Ar$9k!*BYHRF*?oHTGT1JB{Lx3|#~*$$$3#|y zuO4<6`K6mFE^~xT82LW7j_4_l9zJZAEnZ?qKl+&Hkbk2#d56Sy09`EdoRi0oi;vVw zvAyV+l8qOav83A%>}{JgXdp7pIp*}KQ|8!_qoRYHs5(nxvY-5FZRmFzL{J5y|_KuyJy~h+tk0Oj>=V$ zZDX^BjMeJY+DHtS69VI|T^r-T_ZWQ;V`h%fVIwEBdU|7ss z(((Pn|B*Gu9+CavXS>6?qRYTG2U{%ivrk-|5_T46-g;Z-)V5h%p4bY!{@QD)b@uDm z%4N$`4v%gd7~zR-@SYkqR5!wy!HKSp!CMbDbXzxXPVF7<_o8^mUIn`q*WS_F5AYi} z!A-{|5}mHa1AN2p`uNdfIczxGGVG&+V#Cl`@Qj;Yl)ted0AHh9^y>%k3~bbPZ0CV@ z_5->-@PsV~yko11Kdw73_B+o;5{v7_6DJDPrr2#S>^HiiH(q}|P|wIXw{6~%D^?bG z&FXCKzVpr;wqWSYPaZ#^@t*wJ20s$BB|m+Z{n|+<4ZB4Ah=cMD=-b!q6up{zZh_aZ z<+5eiKi)l0tSrt%dv4gg_6aWh%{%Ypu(Pq>3hRko1#2JFN6x;p@4l-x1GZ1VG&*AM zUa`7Jn~x{!i;Yy!KIr~n7oi#V)S()!xW#!vWr&$`mz;s_ zcVOl9S6|CvU+#Wq&R%)>L|6FPTjd%t?2Q#qS#j18Lyd}ZyoZJOVcF>)?4F8dw) z0&R@VwoP-N*zUak>Z`(M*7p7G=FRJGVsya6+Ox}B-@dvxh4{B`Cw!EXCOzv(~z3B(HX%Y(hiiziR!nw#5&&czWtzv&w`_XUXyA008mtXsV%SKH9?$aB8>>Z@FScdh(2)p?)Mv9=XGl?6$-D!I-c&xBCI!8QRg7 z!Ow)aO5oeoLMP!fq4-z!AU1V2UtXWYI74OuJ@%@cwb;4>^DeDo+hD!GkKhQ_-lk{z z#5NNiW7m$IzJ7Mp3vS_T!0!lp2;VL2+>t$G+O92!90oW$CvZ)CDCpEE*h0qh%1bZ% z+LYRQ(|ytw{3W<8Y9E1Xh#iNV><@qVL*RLtZrkL;hk*T!pE_~%{Adtweb9OMQa~em zzr}rrZh&`A2cDU$>#w;+=!_}~ukZ(P+w;p$ylQ+h;o~`%z(0Ox5M}8D_#QeISzumm zDd!4p2R!31<&_!QzOoOA-$37xp<}Zq<8*zm?0mor#no$JlT2IQKEYdYu6WxaAF(OUynQBzEXi9w zukXk(!Lfezur9!;J3pM^i{>v-|0Xxxue?oT|G>|9=|AW?Z<;MbEE@bbh>v2^3gU^( zhw~r^7a`m5+RVexz{B62#=QZ+68b^n^SS+JZxf?6Xby>iL7W)3OhNpnf6$)9(GIE~ z+2%D@<>XNY_U$L<^3K3Awl4e{*)RBg+cciwT9+1fzrib>QWRIg`Ob zes!`|;3oK9`<;11ZjY~@P4hk}2W)xcVA7uTP4$)m9`Gl{*Tnm+Am4$v?OV46w#hl< z%6RDuYX}V=gbRsbyK&w69Cbp|f$xIg9=Zsg8@i_;$Lp;dTz5q1{4jh2|K{>5)Pe6f zf8P3_EuojZ{i!Q=mUCmZ+(UF4&4E75ERz~++Sb(R_Leg54sKL6PK1@ZP%|^ zn=4i_XDYbUmi0d2d7$%xV8ffgAl``=Gjn>*IPPvc$TGo)ZW=Oi{KBj(^Z_}ukR!P3 z41Mj5HRaa983{dxkDi-e*uUXVUxVHZkv$>f=*}L#4rv!+kj{0!1e{1D7vd3#Qy7{ZrxLJ2fp;~7h8rW^&FP56UW(2FY4dG zEAnYSTnK)Gb|JYgvSHa4;^S0ac9AsVZ5m<5eyN+M>J9~oP>;d=; zxJ{?%lTh7*FIHx_TpHnL+7Ms&0KQ= zeuK`0CZ<00snE!N?G~prU>`p92|1rQ*H521t?|UTg8;sfwO4-TqW*&4&i zG4r6U@LztQb!%U|Qk=#d)EDLgy-Z(;O+YL@>|2p*U>8EHPh|MWDTx`%Tv=F$9te^# z2DNo5q!aTI-~OeG7OUMeHZJhR;B|P$AiRGmj4f^-xu=3N0y$>fvPu5pqr!3jPW_}>wCdc=?+8uy92B8jKN6WJetKfl5-SEj%`d+A!u(10Hg_z~pF3CMoDsu`_yYKEau4imxpNv{ z%&Bs}{f|HXsD8`%Hxl=WxM&L`<|jVc-^;zP=fC_?>)jeOv|RtQt?$-?@qFx ziNX5D>u)H{;FhBv=t1I9;>*gNH{6x}mp}hm&WS&2Ki)fcPUBnAKlfgEx1Qv8e4c`} zfd(U%1oYY8{`NP;$G?;Pw_nzvSN9$g7dL0DLce*2-y^>DpM}mNex)0ehWz*^6L$rE zfIAS#|ZM{LxYj+O@%^mv=dW^M#$A|ADHY;~GaK|8c zJ!uryv*vD{{00|&`st?{KaI1(`#pKj2@}jQ@dE$;_rIH= z0|#b2Ukm2WQ`%vJ(2wkA;;V5Uz`qmEyt&-T%N-oVuR~_QJL!BUP96E#zw6{2fNxkJ zGDLf}$5}J#LH__>xO~adv~XFR`b$z?)}H%PKNG%*Sc%;K6nA{A5qKY&J~E=9@~jK% z&b_AfMc&K1UtW7p1@dIzF_V~H;4t_?WXQzD%mj}7`c~4?xbJ8G-hJk~Z@}}*T#H<7l1knbpRoj*=l^@_&es>d*1K?n zV*Q7eFX`W)@g|HNr*agj0b(vA4R^1oI0p)QT3F>@2p3Qi*gt4J3wb2cbw3B!v+mD zUkaYyyL(S)EM4G)`-$zHXWYMmZntts%yIZjWV+`?jxa>d0k8Zxo&G}qalgX5a+h1P zMvaqm;37YOUWa{)jCYLO_mIil!mpwCCEhf2T+m)--ytV}*0<*{dC>uK2aR8xYt|Op z1briI5Wg0kL|lG=GiTfrqs_N+zHOF!w7hpHqys}GEe~@~e0Ao8yFl-B?#xbitlXur zNq7e62F0zOJ6ha&ID3H=?>ZyLVg2>aL0N0JjQtH zIwx{L_-b%IG8*nWjlHMDmJ@u8-i|vn!tRaW3})@Q^UK=~@5CwRd(a(7tTFN*&KJ&c z?hQ?M-Q9f11+hOuXKZnh`~7nIJ!RrVmGcoFKZphon-B0d`yQQ5GvVQb@-oldQw6PG zMqtJ-pQQz{6Ad~)D2IK}`|rJHelIpeHnzQAeL-m|SCIQ=|19aG^tn49dbdjrZhi_PU&TZrZLHC+@%idMBszC-E zg^#cqXAdu4urMQ<6&pj!a~Fo+y@%d@m85s>zkpBYZu3ld;r4CXs&18g1~>zP=7w_} z8@^_Z8>jAD3Ce5Jfh}x^t$m*d3yy;$BRfUecfF zPFXk3&rEP1djFHhPw4u0Zr>qv-q=^l+lSn@<~QHS2)Ms2iWhyTTQ`w8e5pEKbUl7` zg{8rBu>Qyv8CO`|lJJfB#FmG(pF3+-?D1Y#wyfG&qLZ07XHH~!^nK84nao|?TDA1t z2rCQjLe>cX!Tt1M_nZ0ELwS5t&{J~9Z*jT%%&)Kck%ry;dxA5Oqgb1sIQ8P!fi4Ey zkf`$5g>-1!E~E2>K5_nckaH&Nu150J5PdR!0>~c2Y*m8BiEbLX;JLGBL+{-TDu1b@ zV>^YM5Bo~&cEflqzcC@N$EFIqO715OBGq-Jc6lBx(t~U3Z{SDvPrDI2x zVc=urcQ=^L>-U7-7(8Hr;zaIa#~0Nv-=&_`xA()!t06msAB!^{_$B_}L7um?Abl*o-Y+xG=Wv8aU$~u^%tmyT#obamQ8I`O)cc zKQ4B-?58;Gvj)S2zsE-t+kECKtUNM0d~&b{3(J@8H~4#C>E;`52(1s8h9~@o*skDb z#J*0q4f5f8jIH|_(J#372*;_TIOavqF|o>02{gmbZQE2ogl;hG%x9d~b3rF~^*ec;1Ng`$A`_}6cEC|*3OYXQzR~l< z)$w76fS)1fKnsyq=C$8NT^@gF^m@?7_)tf!pSQo`MvoEwz)xZm__W&fdcV8x*yVE0 zz!$`A$F0ZjH*0>!Ew_lxki-KJSn$hZ)1XzhY}%}JE--7;(|vMwe04s1zvTBg((OZj z<%6z;H-@%hFUP4DxeYdR==7s}>6oXQA_oNTN6BsD^uf(by;hDKMV}$pIw$-bdcJmo z|J-__exrZf{LC{7Kgda=@)y_d70Q(}_-R7(K|{ysC-gh_Bct16KSY&9k4ziL?V|GL zFl+5|apfLFmCuY~bUxRZw}CFI}qsFUYr|_KWQULflnyoje=EV9G`vqnZ~B+(6()8TW-5W{TqInxI4gZ zQ?YaO>koVs`MOBFgq_>Bn}7V{A1eQ1-%lJjUTtjg1^BDf0S*X~zriCxCq(J${Q8iW zG+++>P!L{Ye9s=p)^9)Y=%ecYH&)_CoRatw=sp!ff zd{^NonOE=k!WwJ3?O@}KEfzjJRxi)|zz4%SVKaB+&|!_00dC(RFw$3iVz9yXYok^3 z=6a5tIDR};pUnrIjBEkFE}K@E&$0r`(Dq)w247+H6!?$gSLW9z&cr^wdz;;2Q_eiF zUydF=BJ(p+d01C&0E`o#4BQx0pI;k=orc_XrNl}D?#GQDt*{DD-cfXL#N2vaY^9KE z5I1R&$nuGm69v!Ucl4s*OzeHI8)970UeMtd#tM6^wmoc$SQ9%AWQEA?h%bg8i_I7G zytYgk(H(UX-SI;85&iLpAB9$YUCUbCC30+H4gpWg7B4oHDpZK9H>kaWN@tJvc(9B4 zKwx=`*tR2w>(Ql)`q7^gJ{WshY&MYpwrJWkQh($26P^Ir|BWO6)p-}1FX;Sr%NOKt z&O2_g5m>=~iskzWuK3EBmFY0kWQwQ8mIueW^IJ9}&Bz(E?fle)3HDhysftWWkE za9>$yLHJMjf%R+Gsy#FGN)SzF%lbWm1J)W^2!A8!#E)bi@rm9bb>n+LtUAsZzw$+q zcD1a}@WDfr&q25U-M8PVo|gV&4{@8=)w?uMCVeEP1Mm+W1b;w$hbaCjlXfyG!&$_7 z&@XI}k#*)(hY#$)KVl=gYsXHNp%Pz=`Gv0{ra@lkG?TIVl|dH5z9&`!{OwXXqgpm= zrnc5mG7`V~{LrWlbBlrMX7~LXtAUs2q{3*ZMkE#bej2-L`f}i&6+GXx**ig@B&P4R4nVf^( zHfaOB8vNF)FTbMvV_cnrx6b@{r(dlkP8s@5Y z99Cz3d_(WFQ(}{5`ydTbxg|R2bYhYQwa+}EXF`XFJcYHdCj1n7FwPg~i{gU&-7yd+ z1KSsPH7m2nW{UO4CI=lZbW&Wq7U&#kV*WS}@!Q|NWvk-bbaaDmAM^V+aYB(zYm*hc#pL!eZ>{AXaME~+Xd!HZJ1=d#JQ%=)c4}alj<`X*M2U)#~f52vYt62`@pY< z_)B(gGAGb5_&4D1!2UqLn~u*DXFjw)`@og+Q4hKm;H{|qCct^{xHi6=ofqJfcysCU z0MJX!hh2BZ!x>^}NaUQzl;C~vHE?Bvw$0-5#7+*`CwFXcUb+1O4p?*M4W0qHeFK5@ zFn?=k2hI?DhTOWC8)7%X55aT0-wNwDF(Q%E%$q$s7mWj+YbkQBu)bg)(MZlTod@9` zh%w0gxU>V~y#KyzJD6ifjw%ietFx%T(RcjuvG?O14Zr>{CS>R6|Inc@zQz()iL=z3 zpL2xoel#R!EcOxTR?#DR%NFE2_Qjm}$g=(DaA-4dfISD@zJSv?)6rQs6MXhV_ka=yW@`Z?AC8x--6X`5?{$_7FG@nlh@b;`V*~n6YZVK@9ge zG7)eBu{!#RzmOkp^^Oz$(EIPbpRFGioa+6apYPBj;C$i&r{lv!|9f`rrt-=-@>=+u zm2y`V@uQ*n@^cJ@RTs1X^f~8ql%KX=pO`z&geX1%T4Kb|p(-OM#wxV4UwwH^<1Ajg zYL&)=<*vY}^@RVS|LMSqw{PG;Y+qj$`!)JoGv4MI{VxzG4(IuqQzv7w) z+4vgSGsJhBFm`OLbAT~%R>J#7>C&MU(UY@2#MH=d{V4iv;YlJUvc`4Q)=T7r*D);zm9E0l>H<48Cz-OaT7%k zl`fqX)gS11;{GAmTDoXanCJ)mcyGV@qtdWjLGF$XzgMQ^EeqX79`J=L z$MNR#dxsBRv2>Zz{7;N}G?KpXtE0H4ai4Rw3&fRtLODBY{E7^M~d2ek1-RcST?uToPl1ca?jPuw&&u zC*tpV#~<~M+>CP|O7{i60oL#z>MpTmqv{R&j;)=QFGcYc&~3={{N$KnZSW2GKQteF zC4L1_`7g!qoTE$R{KT(kWQO)j=tkIIQL!EHJAqb1H1(6p9t^zq0~XVxv)8B zY{)Q)H5Zo8?;A8C=Oc1HVq+DS9Mi8a1)T;h&-u*#de}9@Z4dklKM0&Ri*Uc~D>J6ZZ+Q{&DGjmp(>s9u~tksQpVRoi&4&hQGl^IFr6Z zKO!HA(ywACd`@hr(b2|@r2w3w!#sWJbSN*$`k|l32Ow_jH^#2?h4=%~)_93^5G7N} zWWI`98EiuEXTx3&`B*0XLoa|lJ!-!pvq6SVY;bE!5!D{@Hf)#aA3hCX`Jpw~vzf{p zuor``oT*~QIzln|r zIe#W&;f!xDxP-kFR34wfiQ~qZzlp67{%1kFIWUQx6?ep|udTpWP@SC9$bmD#UDQb& zDP&6AOB_YV1ofdLq!SYo9I!)dXt9TiJ0{KnWC_UJ!uSE~(hfcUg6fCxx%bNEpyRqf z_@MHO*sq1jCn$>#BRqTD{*s@)j=c(dzki=T8P$f9$QLrvF;Z`Ke6RBwBg5_A<@lTV zz=n$TKQ3{SGCc?2DZl|?vL5V^h_8!&2w1bc7Bu`Qxq||kG563^u2?Z}Pr^fB*Ox9Y z;ayYw)`(q=zZ|km@Au2`9UOoSEi!iey6nAtapnTt&%SI>r%tGU0rrCUs-cgx`XOMB z7<14e*mVZAt2zjw_tEW!oi#z_ky#>(BGxAhl=XrOSc66L=c_zws`%aq(UH_wOX`Jx2%;ZtKZ2gbDgpM0X``}F zIZJ}_UT*2&V(#zce8$%uoqr~CV0A=cHmB&1h_%8#oH2E(^7_z*VKN+S(U1vdO7CL> z2A_u=%%J}LQ)f>mV=Sp6NFh+%s;Y;Kru_Nt$( z2RdUF?E5f;V&|QNBRj}!aZ@^_l7-W5S)dL>2mr;{0L+M zvqdhL>0D6`TYJs}c>hTfOA{Rb&DY;(oD%d;oW=NXq2uA5IF0CG&`nI9FhTb_@+Hb= z+7Eb(@nZLgpW0lZaWk#wa$0}RXW~aCGlsuXNa|BU9k-%7B4Xx z(C1sbYG^+A0_=N^ieC@;$p4evF~yw~*pw6R6CXtC527vo)(G22_!|6$GL;wk)mzfj z2KMcz^w|N?!G!tJvlhs5(8KhTxC7W1LffHJ!-n#V#Nk4>_V~zA5<8-m`XPtS9lR*8 zK>m}$k8tM%^*}2ipWu$KeiE;c_GmW@7N8qwn^*YNaoLbl z0b8_3yVz>0ErQVZUV0Nc|L>whR^L6*DSO*U-gB%(3I9etGjp3M&qKn8*C*rp*{fS&B#qldIJS^ZnF z4P$-j$Ik6LRCk0<2w5_;2l6E1ST`-A__Vg~m-2I__`X345;qzBEpj{jqL^Fs$Abq9 z(6b(yoV(`knDN~~CIk)7I=bJyztPRGUep)F>(LH6XJ`U!1=g-!qcA{hKKe&Lq4%Nr zkS}=KNZ!Nuy*oeH`Jj(?|Go9*TXMHTPn8jcoxg59oW?3;nfsQB)?le=r{h` z$f|k?ULfxAzvMo1`|p(Ct#oltQ2m#CI{Xs!Jif%x;^2Gs75WqKE-`kYvD29+&UAD{ zL3Vn`8?fI_SN4dknfR=nPxOaa_1KId-^G^iwupP`(&=-O=Vx5OUauqeImAZAz8_i- zT8#7IQxCC+u=nZNwX2>x*p*`& zjO^%(&%ey&6@k%K1<)rQ0DtcmSFYUj^%N^6~O?ZP%a(5iDdGV_uA9%j8Lkl7YVx7^^@SQs*vHv2z$8V)P zI0o4*`pIRBmze&K^ie!v;U}FwCV2`6M!?HmFZB4 ] [options] parity signer new-token [options] parity [options] + parity ui [options] Protocol Options: --chain CHAIN Specify the blockchain type. CHAIN may be either a @@ -211,6 +212,7 @@ pub struct Args { pub cmd_import: bool, pub cmd_signer: bool, pub cmd_new_token: bool, + pub cmd_ui: bool, pub arg_pid_file: String, pub arg_file: Option, pub arg_path: Vec, diff --git a/parity/main.rs b/parity/main.rs index 284dac673..1467eaa50 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -68,6 +68,7 @@ mod configuration; mod migration; mod signer; mod rpc_apis; +mod url; use std::io::{Write, Read, BufReader, BufRead}; use std::ops::Deref; @@ -272,6 +273,10 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) }); service.io().register_handler(io_handler).expect("Error registering IO handler"); + if conf.args.cmd_ui { + url::open("http://localhost:8080/") + } + // Handle exit wait_for_exit(panic_handler, rpc_server, dapps_server, signer_server); } diff --git a/parity/url.rs b/parity/url.rs new file mode 100644 index 000000000..672de4a7b --- /dev/null +++ b/parity/url.rs @@ -0,0 +1,57 @@ +// Copyright 2015, 2016 Ethcore (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 . + +//! Cross-platform open url in default browser + +#[cfg(windows)] +mod shell { + extern crate winapi; + + use self::winapi::*; + extern "system" { + pub fn ShellExecuteA( + hwnd: HWND, lpOperation: LPCSTR, lpFile: LPCSTR, lpParameters: LPCSTR, lpDirectory: LPCSTR, + nShowCmd: c_int + ) -> HINSTANCE; + } + + pub use self::winapi::SW_SHOWNORMAL as Normal; +} + +#[cfg(target_os = "windows")] +pub fn open(url: &str) { + use std::ffi::CString; + use std::ptr; + + unsafe { + shell::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(), + shell::Normal); + } +} + +#[cfg(target_os = "macos")] +pub fn open(url: &str) { + let _ = std::process::Command::new("open").arg(url).output(); +} + +#[cfg(target_os = "linux")] +pub fn open(url: &str) { + let _ = std::process::Command::new("xdg-open").arg(url).output(); +} From 39e2f6c8917dd7706b11b535f275c1c649c5844d Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 14 Jun 2016 17:37:01 +0300 Subject: [PATCH 017/239] cfg attrs --- nsis/installer.nsi | 2 ++ parity/url.rs | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/nsis/installer.nsi b/nsis/installer.nsi index a245fbd31..c853eeb5b 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -98,6 +98,7 @@ function un.onInit #Verify the uninstaller - last chance to back out MessageBox MB_OKCANCEL "Permanantly remove ${APPNAME}?" IDOK next Abort + next: !insertmacro VerifyUserIsAdmin functionEnd @@ -121,4 +122,5 @@ section "uninstall" # Remove uninstaller information from the registry DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" + sectionEnd diff --git a/parity/url.rs b/parity/url.rs index 672de4a7b..8e6f31222 100644 --- a/parity/url.rs +++ b/parity/url.rs @@ -31,7 +31,7 @@ mod shell { pub use self::winapi::SW_SHOWNORMAL as Normal; } -#[cfg(target_os = "windows")] +#[cfg(windows)] pub fn open(url: &str) { use std::ffi::CString; use std::ptr; @@ -46,12 +46,12 @@ pub fn open(url: &str) { } } -#[cfg(target_os = "macos")] +#[cfg(macos)] pub fn open(url: &str) { let _ = std::process::Command::new("open").arg(url).output(); } -#[cfg(target_os = "linux")] +#[cfg(linux)] pub fn open(url: &str) { let _ = std::process::Command::new("xdg-open").arg(url).output(); } From 8ced25b36c2e26ff4023d1f5cf56e9d242befba4 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 14 Jun 2016 18:12:41 +0300 Subject: [PATCH 018/239] remove some comments from sample --- nsis/installer.nsi | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/nsis/installer.nsi b/nsis/installer.nsi index c853eeb5b..2c17a2543 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -1,41 +1,27 @@ -# This installs two files, app.exe and logo.ico, creates a start menu shortcut, builds an uninstaller, and -# adds uninstall information to the registry for Add/Remove Programs -# To get started, put this script into a folder with the two files (app.exe, logo.ico, and license.rtf - -# You'll have to create these yourself) and run makensis on it - -# If you change the names "app.exe", "logo.ico", or "license.rtf" you should do a search and replace - they -# show up in a few places. -# All the other settings can be tweaked by editing the !defines at the top of this script !define APPNAME "Parity" !define COMPANYNAME "ETHCORE" !define DESCRIPTION "Fast, light, robust Ethereum implementation" -# These three must be integers !define VERSIONMAJOR 1 !define VERSIONMINOR 2 !define VERSIONBUILD 0 -# These will be displayed by the "Click here for support information" link in "Add/Remove Programs" -# It is possible to use "mailto:" links in here to open the email client + !define HELPURL "https://github.com/ethcore/parity/wiki" # "Support Information" link !define UPDATEURL "https://github.com/ethcore/parity/releases" # "Product Updates" link !define ABOUTURL "https://github.com/ethcore/parity" # "Publisher" link -# This is the size (in kB) of all the files copied into "Program Files" !define INSTALLSIZE 26120 RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on) InstallDir "$PROGRAMFILES\${COMPANYNAME}\${APPNAME}" -# rtf or txt file - remember if it is txt, it must be in the DOS text format (\r\n) LicenseData "..\LICENSE" -# This will be in the installer/uninstaller's title bar Name "${COMPANYNAME} ${APPNAME}" Icon "logo.ico" outFile "installer.exe" !include LogicLib.nsh -# Just three pages - license agreement, install location, and installation page license page directory Page instfiles From 37260d7cf5f6f85495221e7e16e5541db02b49c7 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 14 Jun 2016 18:16:41 +0300 Subject: [PATCH 019/239] fix build and remove .cargo regs --- .gitignore | 3 --- parity/url.rs | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 02e321a1b..3226ea5a2 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,3 @@ # Build artifacts out/ - -# Cargo local dev config -.cargo diff --git a/parity/url.rs b/parity/url.rs index 8e6f31222..8824704b0 100644 --- a/parity/url.rs +++ b/parity/url.rs @@ -46,12 +46,12 @@ pub fn open(url: &str) { } } -#[cfg(macos)] +#[cfg(target_os="macos")] pub fn open(url: &str) { let _ = std::process::Command::new("open").arg(url).output(); } -#[cfg(linux)] +#[cfg(target_os="linux")] pub fn open(url: &str) { let _ = std::process::Command::new("xdg-open").arg(url).output(); } From 91bb6c5d430fb94598c5f3752adffacfbb2b651c Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 14 Jun 2016 18:26:40 +0300 Subject: [PATCH 020/239] final fix --- parity/url.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/parity/url.rs b/parity/url.rs index 8824704b0..8ab6a2eda 100644 --- a/parity/url.rs +++ b/parity/url.rs @@ -48,10 +48,12 @@ pub fn open(url: &str) { #[cfg(target_os="macos")] pub fn open(url: &str) { + use std; let _ = std::process::Command::new("open").arg(url).output(); } #[cfg(target_os="linux")] pub fn open(url: &str) { + use std; let _ = std::process::Command::new("xdg-open").arg(url).output(); } From a26a4edc856873e84ead11493652f9d746989008 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 14 Jun 2016 18:37:04 +0300 Subject: [PATCH 021/239] version bump --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c850940c9..a3f22dded 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,7 +20,7 @@ dependencies = [ "ethsync 1.2.0", "fdlimit 0.1.0", "hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "json-ipc-server 0.2.2 (git+https://github.com/ethcore/json-ipc-server.git)", + "json-ipc-server 0.2.3 (git+https://github.com/ethcore/json-ipc-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -346,7 +346,7 @@ dependencies = [ "ethcore-util 1.2.0", "ethjson 0.1.0", "ethsync 1.2.0", - "json-ipc-server 0.2.2 (git+https://github.com/ethcore/json-ipc-server.git)", + "json-ipc-server 0.2.3 (git+https://github.com/ethcore/json-ipc-server.git)", "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -570,8 +570,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "json-ipc-server" -version = "0.2.2" -source = "git+https://github.com/ethcore/json-ipc-server.git#15ef25e5f859d2d27469c92cc13dd1ddea03e444" +version = "0.2.3" +source = "git+https://github.com/ethcore/json-ipc-server.git#66dfd4b1ec095f0df99e973d6ccb6ddd5168c698" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", From 7b89d6a26307a32c8f7dced7cbe9d86a776ccd3f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 14 Jun 2016 18:45:12 +0300 Subject: [PATCH 022/239] bump further --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index a3f22dded..ac06a8158 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -571,7 +571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "json-ipc-server" version = "0.2.3" -source = "git+https://github.com/ethcore/json-ipc-server.git#66dfd4b1ec095f0df99e973d6ccb6ddd5168c698" +source = "git+https://github.com/ethcore/json-ipc-server.git#d1438770cb3144f0846aaa8c75fcb0e9d7cd0e57" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", From f5cc3db4da429a3ff748f5db0bb5a963dcfe4926 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 14 Jun 2016 20:12:42 +0300 Subject: [PATCH 023/239] fixes with buffered writes --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index ac06a8158..28ab5bdaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -571,7 +571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "json-ipc-server" version = "0.2.3" -source = "git+https://github.com/ethcore/json-ipc-server.git#d1438770cb3144f0846aaa8c75fcb0e9d7cd0e57" +source = "git+https://github.com/ethcore/json-ipc-server.git#b224bdbcb53cab349c278484bd3e5e22390167c9" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", From 58948c53ff8f445b711e95f0684019d597ed9ace Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 14 Jun 2016 19:36:14 +0200 Subject: [PATCH 024/239] clarify windows instructions [ci skip] --- README.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f807be3a4..11f76acdd 100644 --- a/README.md +++ b/README.md @@ -49,14 +49,13 @@ $ curl https://sh.rustup.rs -sSf | sh - Windows -Make sure you have Visual Studio 2015 with C++ support installed, download and run [rustup](https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe) and use the following command to setup msvc toolchain: + Make sure you have Visual Studio 2015 with C++ support installed. Next, use the following commands to install and set up the msvc toolchain: + ``` + $ rustup toolchain install stable-x86_64-pc-windows-msvc + $ rustup default stable-x86_64-pc-windows-msvc + ``` -``` -rustup default stable-x86_64-pc-windows-msvc -``` - - -Then, download and build Parity: +Once you have rustup, download and build parity: ```bash # download Parity code @@ -68,11 +67,11 @@ $ cargo build --release ``` This will produce an executable in the `target/release` subdirectory. -Either run `cd target/release`, or copy `target/release/parity` to another location. +Either run `cd target/release` or copy `target/release/parity` to another location. To get started, just run ```bash $ parity ``` -and parity will begin syncing the Ethereum blockchain. +and parity will begin syncing the Ethereum blockchain. \ No newline at end of file From efa8f661e558d77fa3f0f3f528f3718c84abf474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 15 Jun 2016 00:17:23 +0200 Subject: [PATCH 025/239] More meaningful errors when sending transaction --- Cargo.lock | 42 +++++++++++----------- rpc/src/v1/helpers/signing_queue.rs | 30 +++++++++------- rpc/src/v1/impls/eth_signing.rs | 22 ++++++++---- rpc/src/v1/impls/mod.rs | 55 +++++++++++++++++++++++++++-- rpc/src/v1/impls/personal_signer.rs | 6 ++-- 5 files changed, 109 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c850940c9..5b8be3cc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -233,7 +233,7 @@ dependencies = [ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -279,7 +279,7 @@ dependencies = [ "ethcore-rpc 1.2.0", "ethcore-util 1.2.0", "hyper 0.9.3 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -290,8 +290,8 @@ dependencies = [ "parity-dapps-status 0.5.0 (git+https://github.com/ethcore/parity-dapps-status-rs.git)", "parity-dapps-wallet 0.6.1 (git+https://github.com/ethcore/parity-dapps-wallet-rs.git)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -330,7 +330,7 @@ name = "ethcore-ipc-nano" version = "1.2.0" dependencies = [ "ethcore-ipc 1.2.0", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)", ] @@ -347,12 +347,12 @@ dependencies = [ "ethjson 0.1.0", "ethsync 1.2.0", "json-ipc-server 0.2.2 (git+https://github.com/ethcore/json-ipc-server.git)", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -366,7 +366,7 @@ dependencies = [ "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-rpc 1.2.0", "ethcore-util 1.2.0", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-minimal-sysui 0.1.0 (git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -401,7 +401,7 @@ dependencies = [ "rust-crypto 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.1.0", "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -416,8 +416,8 @@ version = "0.1.0" dependencies = [ "ethcore-util 1.2.0", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -575,7 +575,7 @@ source = "git+https://github.com/ethcore/json-ipc-server.git#15ef25e5f859d2d2746 dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -593,11 +593,11 @@ dependencies = [ [[package]] name = "jsonrpc-core" -version = "2.0.5" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -608,7 +608,7 @@ version = "5.1.0" source = "git+https://github.com/ethcore/jsonrpc-http-server.git#6117b1d77b5a60d6fa2dc884f12aa7f5fd4585ca" dependencies = [ "hyper 0.9.3 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1185,12 +1185,12 @@ dependencies = [ [[package]] name = "serde" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_codegen" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1206,7 +1206,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/rpc/src/v1/helpers/signing_queue.rs b/rpc/src/v1/helpers/signing_queue.rs index 0ded8998c..dd59ce967 100644 --- a/rpc/src/v1/helpers/signing_queue.rs +++ b/rpc/src/v1/helpers/signing_queue.rs @@ -19,8 +19,11 @@ use std::time::{Instant, Duration}; use std::sync::{mpsc, Mutex, RwLock, Arc}; use std::collections::HashMap; use v1::types::{TransactionRequest, TransactionConfirmation}; -use util::{U256, H256}; +use util::U256; +use jsonrpc_core; +/// Result that can be returned from JSON RPC. +pub type RpcResult = Result; /// Possible events happening in the queue that can be listened to. #[derive(Debug, PartialEq)] @@ -59,7 +62,7 @@ pub trait SigningQueue: Send + Sync { /// Removes a request from the queue. /// Notifies possible token holders that transaction was confirmed and given hash was assigned. - fn request_confirmed(&self, id: U256, hash: H256) -> Option; + fn request_confirmed(&self, id: U256, result: RpcResult) -> Option; /// Returns a request if it is contained in the queue. fn peek(&self, id: &U256) -> Option; @@ -75,7 +78,7 @@ enum ConfirmationResult { /// The transaction has been rejected. Rejected, /// The transaction has been confirmed. - Confirmed(H256), + Confirmed(RpcResult), } /// Time you need to confirm the transaction in UI. @@ -100,7 +103,7 @@ pub struct ConfirmationPromise { impl ConfirmationToken { /// Submit solution to all listeners - fn resolve(&self, result: Option) { + fn resolve(&self, result: Option) { let mut res = self.result.lock().unwrap(); *res = result.map_or(ConfirmationResult::Rejected, |h| ConfirmationResult::Confirmed(h)); // Notify listener @@ -119,8 +122,8 @@ impl ConfirmationPromise { /// Blocks current thread and awaits for /// resolution of the transaction (rejected / confirmed) /// Returns `None` if transaction was rejected or timeout reached. - /// Returns `Some(hash)` if transaction was confirmed. - pub fn wait_with_timeout(&self) -> Option { + /// Returns `Some(result)` if transaction was confirmed. + pub fn wait_with_timeout(&self) -> Option { let timeout = Duration::from_secs(QUEUE_TIMEOUT_DURATION_SEC); let deadline = Instant::now() + timeout; @@ -137,7 +140,7 @@ impl ConfirmationPromise { // Check the result match *res { ConfirmationResult::Rejected => return None, - ConfirmationResult::Confirmed(h) => return Some(h), + ConfirmationResult::Confirmed(ref h) => return Some(h.clone()), ConfirmationResult::Waiting => continue, } } @@ -204,12 +207,12 @@ impl ConfirmationsQueue { /// Removes transaction from this queue and notifies `ConfirmationPromise` holders about the result. /// Notifies also a receiver about that event. - fn remove(&self, id: U256, result: Option) -> Option { + fn remove(&self, id: U256, result: Option) -> Option { let token = self.queue.write().unwrap().remove(&id); if let Some(token) = token { // notify receiver about the event - self.notify(result.map_or_else( + self.notify(result.clone().map_or_else( || QueueEvent::RequestRejected(id), |_| QueueEvent::RequestConfirmed(id) )); @@ -265,9 +268,9 @@ impl SigningQueue for ConfirmationsQueue { self.remove(id, None) } - fn request_confirmed(&self, id: U256, hash: H256) -> Option { + fn request_confirmed(&self, id: U256, result: RpcResult) -> Option { debug!(target: "own_tx", "Signer: Transaction confirmed ({:?}).", id); - self.remove(id, Some(hash)) + self.remove(id, Some(result)) } fn requests(&self) -> Vec { @@ -286,6 +289,7 @@ mod test { use util::numbers::{U256, H256}; use v1::types::TransactionRequest; use super::*; + use jsonrpc_core::to_value; fn request() -> TransactionRequest { TransactionRequest { @@ -317,10 +321,10 @@ mod test { // Just wait for the other thread to start thread::sleep(Duration::from_millis(100)); } - queue.request_confirmed(id, H256::from(1)); + queue.request_confirmed(id, to_value(&H256::from(1))); // then - assert_eq!(handle.join().expect("Thread should finish nicely"), H256::from(1)); + assert_eq!(handle.join().expect("Thread should finish nicely"), to_value(&H256::from(1))); } #[test] diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index f8c3c343d..591eae059 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -25,7 +25,7 @@ use util::keys::store::AccountProvider; use v1::helpers::{SigningQueue, ConfirmationsQueue}; use v1::traits::EthSigning; use v1::types::TransactionRequest; -use v1::impls::sign_and_dispatch; +use v1::impls::{sign_and_dispatch, error_codes}; /// Implementation of functions that require signing when no trusted signer is used. @@ -45,6 +45,7 @@ impl EthSigningQueueClient { impl EthSigning for EthSigningQueueClient { fn sign(&self, _params: Params) -> Result { + warn!("Invoking eth_sign is not yet supported with signer enabled."); // TODO [ToDr] Implement sign when rest of the signing queue is ready. rpc_unimplemented!() } @@ -55,7 +56,7 @@ impl EthSigning for EthSigningQueueClient { let queue = take_weak!(self.queue); let id = queue.add_request(request); let result = id.wait_with_timeout(); - to_value(&result.unwrap_or_else(H256::new)) + result.unwrap_or_else(|| to_value(&H256::new())) }) } } @@ -93,7 +94,9 @@ impl EthSigning for EthSigningUnsafeClient where fn sign(&self, params: Params) -> Result { from_params::<(Address, H256)>(params).and_then(|(addr, msg)| { - to_value(&take_weak!(self.accounts).sign(&addr, &msg).unwrap_or(H520::zero())) + take_weak!(self.accounts).sign(&addr, &msg) + .map(|v| to_value(&v)) + .unwrap_or_else(|e| Err(account_locked(format!("Error: {:?}", e)))) }) } @@ -102,10 +105,17 @@ impl EthSigning for EthSigningUnsafeClient where .and_then(|(request, )| { let accounts = take_weak!(self.accounts); match accounts.account_secret(&request.from) { - Ok(secret) => to_value(&sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, secret)), - Err(_) => to_value(&H256::zero()) + Ok(secret) => sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, secret), + Err(e) => Err(account_locked(format!("Error: {:?}", e))), } }) } - +} + +fn account_locked(data: String) -> Error { + Error { + code: ErrorCode::ServerError(error_codes::ACCOUNT_LOCKED), + message: "Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.".into(), + data: Some(Value::String(data)), + } } diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 7fdf57249..03f4b34ed 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -54,14 +54,16 @@ pub use self::traces::TracesClient; pub use self::rpc::RpcClient; use v1::types::TransactionRequest; +use ethcore::error::Error as EthcoreError; use ethcore::miner::{AccountDetails, MinerService}; use ethcore::client::MiningBlockChainClient; use ethcore::transaction::{Action, SignedTransaction, Transaction}; use util::numbers::*; use util::rlp::encode; use util::bytes::ToPretty; +use jsonrpc_core::{Error, ErrorCode, Value, to_value}; -fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> H256 +fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result where C: MiningBlockChainClient, M: MinerService { let hash = signed_transaction.hash(); @@ -72,10 +74,12 @@ fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedT } }); - import.map(|_| hash).unwrap_or(H256::zero()) + import + .map_err(transaction_error) + .and_then(|_| to_value(&hash)) } -fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, secret: H256) -> H256 +fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, secret: H256) -> Result where C: MiningBlockChainClient, M: MinerService { let signed_transaction = { @@ -97,3 +101,48 @@ fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, s trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty()); dispatch_transaction(&*client, &*miner, signed_transaction) } + +mod error_codes { + // NOTE [ToDr] Codes from -32000 to -32099 + pub const UNKNOWN_ERROR: i64 = -32002; + pub const TRANSACTION_ERROR: i64 = -32010; + pub const ACCOUNT_LOCKED: i64 = -32020; +} + +fn transaction_error(error: EthcoreError) -> Error { + use ethcore::error::TransactionError::*; + + if let EthcoreError::Transaction(e) = error { + let msg = match e { + AlreadyImported => "Transaction with the same hash was already imported.".into(), + Old => "Transaction nonce is too low. Try incrementing the nonce.".into(), + TooCheapToReplace => { + "Transaction fee is too low. There is another transaction with same nonce in the queue. Try increasing the fee or incrementing the nonce.".into() + }, + LimitReached => { + "There is too many transactions in the queue. Your transaction was dropped due to limit. Try increasing the fee.".into() + }, + InsufficientGasPrice { minimal, got } => { + format!("Transaction fee is to low. It does not satisfy your node's minimal fee (minimal: {}, got: {}). Try increasing the fee.", minimal, got) + }, + InsufficientBalance { balance, cost } => { + format!("Insufficient funds. Account you try to send transaction from does not have enough funds. Required {} and got: {}.", cost, balance) + }, + GasLimitExceeded { limit, got } => { + format!("Transaction cost exceeds current gas limit. Limit: {}, got: {}. Try decreasing supplied gas.", limit, got) + }, + InvalidGasLimit(_) => "Supplied gas is beyond limit.".into(), + }; + Error { + code: ErrorCode::ServerError(error_codes::TRANSACTION_ERROR), + message: msg, + data: None, + } + } else { + Error { + code: ErrorCode::ServerError(error_codes::UNKNOWN_ERROR), + message: "Unknown error when sending transaction.".into(), + data: Some(Value::String(format!("{:?}", error))), + } + } +} diff --git a/rpc/src/v1/impls/personal_signer.rs b/rpc/src/v1/impls/personal_signer.rs index 88bf9a5d1..0c1fcb7f1 100644 --- a/rpc/src/v1/impls/personal_signer.rs +++ b/rpc/src/v1/impls/personal_signer.rs @@ -73,9 +73,9 @@ impl PersonalSigner for SignerClient { - let hash = sign_and_dispatch(&*client, &*miner, request, secret); - queue.request_confirmed(id, hash); - Some(to_value(&hash)) + let res = sign_and_dispatch(&*client, &*miner, request, secret); + queue.request_confirmed(id, res.clone()); + Some(res) }, Err(_) => None } From b5624801737602655414062a01cc674139f60a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 15 Jun 2016 00:57:49 +0200 Subject: [PATCH 026/239] Fixing origin/host validation (#1273) --- parity/configuration.rs | 14 ++++++-------- signer/src/ws_server/session.rs | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index 1e14cd1de..3aff2ee27 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -362,14 +362,12 @@ impl Configuration { } fn ipc_path(&self) -> String { - if self.args.flag_geth { self.geth_ipc_path() } - else { - if cfg!(windows) { - r"\\.\pipe\parity.jsonrpc".to_owned() - } - else { - Configuration::replace_home(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone())) - } + if self.args.flag_geth { + self.geth_ipc_path() + } else if cfg!(windows) { + r"\\.\pipe\parity.jsonrpc".to_owned() + } else { + Configuration::replace_home(&self.args.flag_ipcpath.clone().unwrap_or(self.args.flag_ipc_path.clone())) } } diff --git a/signer/src/ws_server/session.rs b/signer/src/ws_server/session.rs index 8cc3f5d07..b635f1524 100644 --- a/signer/src/ws_server/session.rs +++ b/signer/src/ws_server/session.rs @@ -75,7 +75,7 @@ impl ws::Handler for Session { let host = req.header("host").or_else(|| req.header("Host")); // Check request origin and host header. - if !origin_is_allowed(&self.self_origin, origin) && !origin_is_allowed(&self.self_origin, host) { + if !origin_is_allowed(&self.self_origin, origin) && !(origin.is_none() && origin_is_allowed(&self.self_origin, host)) { warn!(target: "signer", "Blocked connection to Signer API from untrusted origin."); return Ok(ws::Response::forbidden(format!("You are not allowed to access system ui. Use: http://{}", self.self_origin))); } From 71131c41e557f1232624b7654362c8372d182dbd Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Wed, 15 Jun 2016 00:58:08 +0200 Subject: [PATCH 027/239] Security audit issues fixed (#1279) * Restrict network key file permissions * Check for overflow in str to bigint conversion * RLP decoder overflow check --- parity/signer.rs | 2 +- util/bigint/src/uint.rs | 35 +++++++++++++++++++++++------------ util/src/keys/directory.rs | 18 +----------------- util/src/network/host.rs | 7 ++++++- util/src/path.rs | 19 +++++++++++++++++++ util/src/rlp/tests.rs | 7 +++++++ util/src/rlp/untrusted_rlp.rs | 6 +++--- 7 files changed, 60 insertions(+), 34 deletions(-) diff --git a/parity/signer.rs b/parity/signer.rs index f8ff699df..3c8dceb6b 100644 --- a/parity/signer.rs +++ b/parity/signer.rs @@ -18,7 +18,7 @@ use std::io; use std::path::PathBuf; use std::sync::Arc; use util::panics::{PanicHandler, ForwardPanic}; -use util::keys::directory::restrict_permissions_owner; +use util::path::restrict_permissions_owner; use die::*; use rpc_apis; diff --git a/util/bigint/src/uint.rs b/util/bigint/src/uint.rs index 286f6a43f..efb9d63d9 100644 --- a/util/bigint/src/uint.rs +++ b/util/bigint/src/uint.rs @@ -50,6 +50,12 @@ use std::cmp::*; use serde; use rustc_serialize::hex::{FromHex, FromHexError, ToHex}; +/// Conversion from decimal string error +#[derive(Debug, PartialEq)] +pub enum FromDecStrErr { + /// Value does not fit into type + InvalidLength +} macro_rules! impl_map_from { ($thing:ident, $from:ty, $to:ty) => { @@ -493,10 +499,8 @@ pub trait Uint: Sized + Default + FromStr + From + fmt::Debug + fmt::Displa /// Returns the largest value that can be represented by this integer type. fn max_value() -> Self; - /// Error type for converting from a decimal string. - type FromDecStrErr; /// Convert from a decimal string. - fn from_dec_str(value: &str) -> Result; + fn from_dec_str(value: &str) -> Result; /// Conversion to u32 fn low_u32(&self) -> u32; @@ -553,17 +557,22 @@ macro_rules! construct_uint { pub struct $name(pub [u64; $n_words]); impl Uint for $name { - type FromDecStrErr = FromHexError; /// TODO: optimize, throw appropriate err - fn from_dec_str(value: &str) -> Result { - Ok(value.bytes() - .map(|b| b - 48) - .fold($name::from(0u64), | acc, c | - // fast multiplication by 10 - // (acc << 3) + (acc << 1) => acc * 10 - (acc << 3) + (acc << 1) + $name::from(c) - )) + fn from_dec_str(value: &str) -> Result { + let mut res = Self::default(); + for b in value.bytes().map(|b| b - 48) { + let (r, overflow) = res.overflowing_mul_u32(10); + if overflow { + return Err(FromDecStrErr::InvalidLength); + } + let (r, overflow) = r.overflowing_add(b.into()); + if overflow { + return Err(FromDecStrErr::InvalidLength); + } + res = r; + } + Ok(res) } #[inline] @@ -1433,6 +1442,7 @@ known_heap_size!(0, U128, U256); mod tests { use uint::{Uint, U128, U256, U512}; use std::str::FromStr; + use super::FromDecStrErr; #[test] pub fn uint256_from() { @@ -1802,6 +1812,7 @@ mod tests { fn uint256_from_dec_str() { assert_eq!(U256::from_dec_str("10").unwrap(), U256::from(10u64)); assert_eq!(U256::from_dec_str("1024").unwrap(), U256::from(1024u64)); + assert_eq!(U256::from_dec_str("115792089237316195423570985008687907853269984665640564039457584007913129639936"), Err(FromDecStrErr::InvalidLength)); } #[test] diff --git a/util/src/keys/directory.rs b/util/src/keys/directory.rs index d9d453409..32ac14b55 100644 --- a/util/src/keys/directory.rs +++ b/util/src/keys/directory.rs @@ -18,6 +18,7 @@ use common::*; use std::path::{PathBuf}; +use path::restrict_permissions_owner; const CURRENT_DECLARED_VERSION: u64 = 3; const MAX_KEY_FILE_LEN: u64 = 1024 * 80; @@ -465,23 +466,6 @@ pub struct KeyDirectory { cache_usage: RwLock>, } -/// Restricts the permissions of given path only to the owner. -#[cfg(not(windows))] -pub fn restrict_permissions_owner(file_path: &Path) -> Result<(), i32> { - let cstr = ::std::ffi::CString::new(file_path.to_str().unwrap()).unwrap(); - match unsafe { ::libc::chmod(cstr.as_ptr(), ::libc::S_IWUSR | ::libc::S_IRUSR) } { - 0 => Ok(()), - x => Err(x), - } -} - -/// Restricts the permissions of given path only to the owner. -#[cfg(windows)] -pub fn restrict_permissions_owner(_file_path: &Path) -> Result<(), i32> { - //TODO: implement me - Ok(()) -} - impl KeyDirectory { /// Initializes new cache directory context with a given `path` pub fn new(path: &Path) -> KeyDirectory { diff --git a/util/src/network/host.rs b/util/src/network/host.rs index abace1983..b37538c9c 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -41,6 +41,7 @@ use network::stats::NetworkStats; use network::error::{NetworkError, DisconnectReason}; use network::discovery::{Discovery, TableUpdates, NodeEntry}; use network::ip_utils::{map_external_address, select_public_address}; +use path::restrict_permissions_owner; type Slab = ::slab::Slab; @@ -946,13 +947,17 @@ fn save_key(path: &Path, key: &Secret) { return; }; path_buf.push("key"); - let mut file = match fs::File::create(path_buf.as_path()) { + let path = path_buf.as_path(); + let mut file = match fs::File::create(&path) { Ok(file) => file, Err(e) => { warn!("Error creating key file: {:?}", e); return; } }; + if let Err(e) = restrict_permissions_owner(&path) { + warn!(target: "network", "Failed to modify permissions of the file (chmod: {})", e); + } if let Err(e) = file.write(&key.hex().into_bytes()) { warn!("Error writing key file: {:?}", e); } diff --git a/util/src/path.rs b/util/src/path.rs index 899650149..023269a69 100644 --- a/util/src/path.rs +++ b/util/src/path.rs @@ -15,6 +15,7 @@ // along with Parity. If not, see . //! Path utilities +use std::path::Path; /// Default ethereum paths pub mod ethereum { @@ -62,3 +63,21 @@ pub mod ethereum { pth } } + +/// Restricts the permissions of given path only to the owner. +#[cfg(not(windows))] +pub fn restrict_permissions_owner(file_path: &Path) -> Result<(), i32> { + let cstr = ::std::ffi::CString::new(file_path.to_str().unwrap()).unwrap(); + match unsafe { ::libc::chmod(cstr.as_ptr(), ::libc::S_IWUSR | ::libc::S_IRUSR) } { + 0 => Ok(()), + x => Err(x), + } +} + +/// Restricts the permissions of given path only to the owner. +#[cfg(windows)] +pub fn restrict_permissions_owner(_file_path: &Path) -> Result<(), i32> { + //TODO: implement me + Ok(()) +} + diff --git a/util/src/rlp/tests.rs b/util/src/rlp/tests.rs index a92dd5c4a..3df2f2d97 100644 --- a/util/src/rlp/tests.rs +++ b/util/src/rlp/tests.rs @@ -429,3 +429,10 @@ fn test_rlp_nested_empty_list_encode() { assert_eq!(stream.drain()[..], [0xc2u8, 0xc0u8, 40u8][..]); } +#[test] +fn test_rlp_list_length_overflow() { + let data: Vec = vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00]; + let rlp = UntrustedRlp::new(&data); + let as_val: Result = rlp.val_at(0); + assert_eq!(Err(DecoderError::RlpIsTooShort), as_val); +} diff --git a/util/src/rlp/untrusted_rlp.rs b/util/src/rlp/untrusted_rlp.rs index 6109a643b..8e9b6d70e 100644 --- a/util/src/rlp/untrusted_rlp.rs +++ b/util/src/rlp/untrusted_rlp.rs @@ -334,9 +334,9 @@ impl<'a> BasicDecoder<'a> { /// Return first item info. fn payload_info(bytes: &[u8]) -> Result { let item = try!(PayloadInfo::from(bytes)); - match item.header_len + item.value_len <= bytes.len() { - true => Ok(item), - false => Err(DecoderError::RlpIsTooShort), + match item.header_len.checked_add(item.value_len) { + Some(x) if x <= bytes.len() => Ok(item), + _ => Err(DecoderError::RlpIsTooShort), } } } From dac387fac10c6c38035171ef0e30910e7fb115fb Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 15 Jun 2016 01:12:46 +0200 Subject: [PATCH 028/239] changed rpc error message to Still Syncing, when mining is not ready --- rpc/src/v1/impls/eth.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index ac123c565..2d337e73c 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -225,7 +225,7 @@ fn make_unsupported_err() -> Error { fn no_work_err() -> Error { Error { code: ErrorCode::ServerError(NO_WORK_CODE), - message: "Mining not ready.".into(), + message: "Still syncing.".into(), data: None } } From 44ed899fb388adce765c64064213a6fac855f424 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 15 Jun 2016 01:16:10 +0200 Subject: [PATCH 029/239] address comments [ci skip] --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 11f76acdd..ff729a3b7 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,9 @@ $ curl https://sh.rustup.rs -sSf | sh - Windows - Make sure you have Visual Studio 2015 with C++ support installed. Next, use the following commands to install and set up the msvc toolchain: + Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the rustup installer from + https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe and use the following command to install and set up the msvc toolchain: ``` - $ rustup toolchain install stable-x86_64-pc-windows-msvc $ rustup default stable-x86_64-pc-windows-msvc ``` From be6c572449e67a1b49abc78735d215d6015fee0a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 15 Jun 2016 01:26:58 +0200 Subject: [PATCH 030/239] Update eth.rs --- rpc/src/v1/tests/mocked/eth.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 801a74f1d..45f8bd366 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -732,7 +732,7 @@ fn returns_no_work_if_cant_mine() { eth_tester.client.set_queue_size(10); let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","error":{"code":-32001,"message":"Mining not ready.","data":null},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32001,"message":"Still syncing.","data":null},"id":1}"#; assert_eq!(eth_tester.io.handle_request(request), Some(response.to_owned())); } From 79bd168267467d9ca43570cbca8e2fc6104f8639 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 14 Jun 2016 16:27:47 -0700 Subject: [PATCH 031/239] bump rust-crypto (#1289) --- Cargo.lock | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b94238c82..b9749217a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -266,7 +266,7 @@ dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rust-crypto 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -399,7 +399,7 @@ dependencies = [ "nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb 0.4.5 (git+https://github.com/ethcore/rust-rocksdb)", - "rust-crypto 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -637,11 +637,6 @@ name = "lazy_static" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libc" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libc" version = "0.2.10" @@ -1140,11 +1135,11 @@ dependencies = [ [[package]] name = "rust-crypto" -version = "0.2.35" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", From 818b87e3118179a7ebf3784235565266d8ed82c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 15 Jun 2016 09:01:57 +0200 Subject: [PATCH 032/239] Fixing returned value --- rpc/src/v1/impls/eth.rs | 2 +- rpc/src/v1/impls/personal.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index b0d6abcf0..5c205c087 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -499,7 +499,7 @@ impl Eth for EthClient where .and_then(|(raw_transaction, )| { let raw_transaction = raw_transaction.to_vec(); match UntrustedRlp::new(&raw_transaction).as_val() { - Ok(signed_transaction) => to_value(&dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction)), + Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction), Err(_) => to_value(&H256::zero()), } }) diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index c62c71453..4f9e307cb 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -92,7 +92,7 @@ impl Personal for PersonalClient .and_then(|(request, password)| { let accounts = take_weak!(self.accounts); match accounts.locked_account_secret(&request.from, &password) { - Ok(secret) => to_value(&sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, secret)), + Ok(secret) => sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, secret), Err(_) => to_value(&H256::zero()), } }) From 3d86d099bbc084c2c8ffdfdb182f2605717ccd2f Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 15 Jun 2016 12:22:26 +0200 Subject: [PATCH 033/239] remove either/or commands, keep it simple [ci skip] --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ff729a3b7..27087b6a4 100644 --- a/README.md +++ b/README.md @@ -66,12 +66,11 @@ $ cd parity $ cargo build --release ``` -This will produce an executable in the `target/release` subdirectory. -Either run `cd target/release` or copy `target/release/parity` to another location. +This will produce an executable in the `./target/release` subdirectory. To get started, just run ```bash -$ parity +$ ./target/release/parity ``` and parity will begin syncing the Ethereum blockchain. \ No newline at end of file From 2527130831af4ca4d3dbce68c6de19f52035ce7f Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 15 Jun 2016 12:45:52 +0200 Subject: [PATCH 034/239] indentation (renders the same) [ci skip] --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 27087b6a4..acd873b74 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,9 @@ Parity is fully compatible with Stable Rust. We recommend installing Rust through [rustup](https://www.rustup.rs/). If you don't already have rustup, you can install it like this: - Linux and OSX: -```bash -$ curl https://sh.rustup.rs -sSf | sh -``` + ```bash + $ curl https://sh.rustup.rs -sSf | sh + ``` - Windows From 549647b6f25e94d458784a8eaa7125896f7ab9cd Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 15 Jun 2016 16:33:38 +0200 Subject: [PATCH 035/239] fixed #1261, overflow when calculating work (#1283) * fixed #1261, overflow when calculating work * tests for difficulty_to_boundary * return !U256::zer() for boundary <= 1 --- ethcore/src/ethereum/ethash.rs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 746da9069..c8b8d7b31 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -255,12 +255,21 @@ impl Ethash { /// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`. pub fn boundary_to_difficulty(boundary: &H256) -> U256 { - U256::from((U512::one() << 256) / U256::from(boundary.as_slice()).into()) + let d = U256::from(*boundary); + if d <= U256::one() { + U256::max_value() + } else { + ((U256::one() << 255) / d) << 1 + } } /// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`. pub fn difficulty_to_boundary(difficulty: &U256) -> H256 { - U256::from((U512::one() << 256) / difficulty.into()).into() + if *difficulty <= U256::one() { + U256::max_value().into() + } else { + (((U256::one() << 255) / *difficulty) << 1).into() + } } fn to_ethash(hash: H256) -> EH256 { @@ -291,12 +300,11 @@ impl Header { #[cfg(test)] mod tests { - extern crate ethash; - use common::*; use block::*; use tests::helpers::*; use super::super::new_morden; + use super::Ethash; #[test] fn on_close_block() { @@ -509,5 +517,15 @@ mod tests { } } + #[test] + fn test_difficulty_to_boundary() { + // result of f(0) is undefined, so do not assert the result + let _ = Ethash::difficulty_to_boundary(&U256::from(0)); + assert_eq!(Ethash::difficulty_to_boundary(&U256::from(1)), H256::from(U256::max_value())); + assert_eq!(Ethash::difficulty_to_boundary(&U256::from(2)), H256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap()); + assert_eq!(Ethash::difficulty_to_boundary(&U256::from(4)), H256::from_str("4000000000000000000000000000000000000000000000000000000000000000").unwrap()); + assert_eq!(Ethash::difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap()); + } + // TODO: difficulty test } From 680337530129b22e6a531a49fbf7a7a69f7e58c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 15 Jun 2016 18:32:21 +0200 Subject: [PATCH 036/239] Consolidating all RPC error codes --- rpc/src/v1/impls/eth.rs | 10 +++------- rpc/src/v1/impls/mod.rs | 16 +++++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 28ba1a7de..de68452e8 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -37,7 +37,7 @@ use ethcore::filter::Filter as EthcoreFilter; use self::ethash::SeedHashCompute; use v1::traits::Eth; use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, OptionalValue, Index, Filter, Log, Receipt}; -use v1::impls::dispatch_transaction; +use v1::impls::{dispatch_transaction, error_codes}; use serde; /// Eth rpc implementation. @@ -210,13 +210,9 @@ fn from_params_default_third(params: Params) -> Result<(F1, F2, BlockNum } } -// must be in range [-32099, -32000] -const UNSUPPORTED_REQUEST_CODE: i64 = -32000; -const NO_WORK_CODE: i64 = -32001; - fn make_unsupported_err() -> Error { Error { - code: ErrorCode::ServerError(UNSUPPORTED_REQUEST_CODE), + code: ErrorCode::ServerError(error_codes::UNSUPPORTED_REQUEST_CODE), message: "Unsupported request.".into(), data: None } @@ -224,7 +220,7 @@ fn make_unsupported_err() -> Error { fn no_work_err() -> Error { Error { - code: ErrorCode::ServerError(NO_WORK_CODE), + code: ErrorCode::ServerError(error_codes::NO_WORK_CODE), message: "Still syncing.".into(), data: None } diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 03f4b34ed..8ea02b8b3 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -63,6 +63,15 @@ use util::rlp::encode; use util::bytes::ToPretty; use jsonrpc_core::{Error, ErrorCode, Value, to_value}; +mod error_codes { + // NOTE [ToDr] Codes from [-32099, -32000] + pub const UNSUPPORTED_REQUEST_CODE: i64 = -32000; + pub const NO_WORK_CODE: i64 = -32001; + pub const UNKNOWN_ERROR: i64 = -32002; + pub const TRANSACTION_ERROR: i64 = -32010; + pub const ACCOUNT_LOCKED: i64 = -32020; +} + fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result where C: MiningBlockChainClient, M: MinerService { let hash = signed_transaction.hash(); @@ -102,13 +111,6 @@ fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, s dispatch_transaction(&*client, &*miner, signed_transaction) } -mod error_codes { - // NOTE [ToDr] Codes from -32000 to -32099 - pub const UNKNOWN_ERROR: i64 = -32002; - pub const TRANSACTION_ERROR: i64 = -32010; - pub const ACCOUNT_LOCKED: i64 = -32020; -} - fn transaction_error(error: EthcoreError) -> Error { use ethcore::error::TransactionError::*; From 7284df9bf5936646f2b057474f0308b61423991e Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Wed, 15 Jun 2016 19:01:58 +0200 Subject: [PATCH 037/239] Fixed loosing peers on incoming connections. (#1293) * Deactivate peer if it has no new data * Fixed node table timer registration * Fixed handshake timeout expiration * Extra trace * Fixed session count calculation * Only deactivate incapable peers in ChainHead state * Timer registration is not needed --- sync/src/chain.rs | 8 +++++++- util/src/network/handshake.rs | 5 +++-- util/src/network/host.rs | 7 +++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 90e18d8e8..611035b3d 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -405,6 +405,7 @@ impl ChainSync { } if item_count == 0 && (self.state == SyncState::Blocks || self.state == SyncState::NewBlocks) { self.deactivate_peer(io, peer_id); //TODO: is this too harsh? + self.continue_sync(io); return Ok(()); } @@ -452,7 +453,12 @@ impl ChainSync { // Disable the peer for this syncing round if it gives invalid chain if !valid_response { - trace!(target: "sync", "{} Disabled for invalid headers response", peer_id); + trace!(target: "sync", "{} Deactivated for invalid headers response", peer_id); + self.deactivate_peer(io, peer_id); + } + if headers.is_empty() && self.state == SyncState::ChainHead { + // Peer does not have any new subchain heads, deactivate it nd try with another + trace!(target: "sync", "{} Deactivated for no data", peer_id); self.deactivate_peer(io, peer_id); } match self.state { diff --git a/util/src/network/handshake.rs b/util/src/network/handshake.rs index 90e3bc67d..179309a6f 100644 --- a/util/src/network/handshake.rs +++ b/util/src/network/handshake.rs @@ -128,7 +128,6 @@ impl Handshake { /// Readable IO handler. Drives the state change. pub fn readable(&mut self, io: &IoContext, host: &HostInfo) -> Result<(), UtilError> where Message: Send + Clone { if !self.expired() { - io.clear_timer(self.connection.token).ok(); match self.state { HandshakeState::New => {} HandshakeState::ReadingAuth => { @@ -151,7 +150,9 @@ impl Handshake { try!(self.read_ack_eip8(host.secret(), &data)); }; }, - HandshakeState::StartSession => {}, + HandshakeState::StartSession => { + io.clear_timer(self.connection.token).ok(); + }, } } Ok(()) diff --git a/util/src/network/host.rs b/util/src/network/host.rs index b37538c9c..de6908200 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -523,11 +523,13 @@ impl Host where Message: Send + Sync + Clone { } let nodes = if pin { self.pinned_nodes.clone() } else { self.nodes.read().unwrap().nodes() }; + let mut started: usize = 0; for id in nodes.iter().filter(|ref id| !self.have_session(id) && !self.connecting_to(id)) .take(min(MAX_HANDSHAKES_PER_ROUND, handshake_limit - handshake_count)) { self.connect_peer(&id, io); + started += 1; } - debug!(target: "network", "Connecting peers: {} sessions, {} pending", self.session_count(), self.handshake_count()); + debug!(target: "network", "Connecting peers: {} sessions, {} pending, {} started", self.session_count(), self.handshake_count(), started); } #[cfg_attr(feature="dev", allow(single_match))] @@ -650,6 +652,7 @@ impl Host where Message: Send + Sync + Clone { break; }, Ok(SessionData::Ready) => { + self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); if !s.info.originated { let session_count = self.session_count(); let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; @@ -667,7 +670,6 @@ impl Host where Message: Send + Sync + Clone { } } } - self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); for (p, _) in self.handlers.read().unwrap().iter() { if s.have_capability(p) { ready_data.push(p); @@ -828,6 +830,7 @@ impl IoHandler> for Host where Messa io.update_registration(DISCOVERY).expect("Error updating discovery registration"); }, NODE_TABLE => { + trace!(target: "network", "Refreshing node table"); self.nodes.write().unwrap().clear_useless(); }, _ => match self.timers.read().unwrap().get(&token).cloned() { From 5538527016b9e1362096dda93192b6b9adae4159 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 15 Jun 2016 20:52:00 +0300 Subject: [PATCH 038/239] x64 path --- nsis/installer.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nsis/installer.nsi b/nsis/installer.nsi index 2c17a2543..f352e0b87 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -13,7 +13,7 @@ RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on) -InstallDir "$PROGRAMFILES\${COMPANYNAME}\${APPNAME}" +InstallDir "$PROGRAMFILES64\${COMPANYNAME}\${APPNAME}" LicenseData "..\LICENSE" Name "${COMPANYNAME} ${APPNAME}" From 7649037e51af1fdc885a5f09cce0b2c36518acae Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 15 Jun 2016 21:40:41 +0300 Subject: [PATCH 039/239] firewall rules --- nsis/installer.nsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/nsis/installer.nsi b/nsis/installer.nsi index f352e0b87..10143306a 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -56,6 +56,18 @@ section "install" createDirectory "$SMPROGRAMS\${COMPANYNAME}" createShortCut "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" "$INSTDIR\parity.exe" "ui" "$INSTDIR\logo.ico" + # Firewall remove rules if exists + SimpleFC::AdvRemoveRule "Parity incoming peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Parity outgoing peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Parity web queries (TCP:80)" + SimpleFC::AdvRemoveRule "Parity UDP discovery (UDP:30303)" + + # Firewall exception rules + SimpleFC::AdvAddRule "Parity incoming peers (TCP:30303)" "" 6 1 1 2147483647 1 "$INSTDIR\parity.exe" "" "" "Parity" 30303 "" "" "" + SimpleFC::AdvAddRule "Parity outgoing peers (TCP:30303)" "" 6 2 1 2147483647 1 "$INSTDIR\parity.exe" "" "" "Parity" "" 30303 "" "" + SimpleFC::AdvAddRule "Parity web queries (TCP:80)" "" 6 2 1 2147483647 1 "$INSTDIR\parity.exe" "" "" "Parity" "" 80 "" "" + SimpleFC::AdvAddRule "Parity UDP discovery (UDP:30303)" "" 17 2 1 2147483647 1 "$INSTDIR\parity.exe" "" "" "Parity" "" 30303 "" "" + # Registry information for add/remove programs WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayName" "${COMPANYNAME} - ${APPNAME} - ${DESCRIPTION}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" @@ -106,6 +118,12 @@ section "uninstall" # Try to remove the install directory - this will only happen if it is empty rmDir $INSTDIR + # Firewall exception rules + SimpleFC::AdvRemoveRule "Parity incoming peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Parity outgoing peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Parity web queries (TCP:80)" + SimpleFC::AdvRemoveRule "Parity UDP discovery (UDP:30303)" + # Remove uninstaller information from the registry DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" From 9603597da79ebcac99d4e018c960ce6c511c9880 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 15 Jun 2016 21:31:19 +0200 Subject: [PATCH 040/239] Fix read-ahead bug. Re-ahead 8 bytes rather than 3 to ensure large blocks import fine. --- parity/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 1467eaa50..e1890ff0f 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -398,7 +398,7 @@ fn execute_import(conf: Configuration) { Box::new(::std::io::stdin()) }; - let mut first_bytes: Bytes = vec![0; 3]; + let mut first_bytes: Bytes = vec![0; 8]; let mut first_read = 0; let format = match conf.args.flag_format { @@ -438,13 +438,13 @@ fn execute_import(conf: Configuration) { match format { DataFormat::Binary => { loop { - let mut bytes: Bytes = if first_read > 0 {first_bytes.clone()} else {vec![0; 3]}; + let mut bytes: Bytes = if first_read > 0 {first_bytes.clone()} else {vec![0; 8]}; let n = if first_read > 0 {first_read} else {instream.read(&mut(bytes[..])).unwrap_or_else(|_| die!("Error reading from the file/stream."))}; if n == 0 { break; } first_read = 0; let s = PayloadInfo::from(&(bytes[..])).unwrap_or_else(|e| die!("Invalid RLP in the file/stream: {:?}", e)).total(); bytes.resize(s, 0); - instream.read_exact(&mut(bytes[3..])).unwrap_or_else(|_| die!("Error reading from the file/stream.")); + instream.read_exact(&mut(bytes[8..])).unwrap_or_else(|_| die!("Error reading from the file/stream.")); do_import(bytes); } } From 80e56cb8d7c48bf6aa9236c1f48ba00c9896e82b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 15 Jun 2016 23:12:43 +0200 Subject: [PATCH 041/239] Refactor to use a const. --- parity/main.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index e1890ff0f..8b99f463b 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -398,7 +398,9 @@ fn execute_import(conf: Configuration) { Box::new(::std::io::stdin()) }; - let mut first_bytes: Bytes = vec![0; 8]; + const READAHEAD_BYTES: usize = 8; + + let mut first_bytes: Bytes = vec![0; READAHEAD_BYTES]; let mut first_read = 0; let format = match conf.args.flag_format { @@ -438,13 +440,13 @@ fn execute_import(conf: Configuration) { match format { DataFormat::Binary => { loop { - let mut bytes: Bytes = if first_read > 0 {first_bytes.clone()} else {vec![0; 8]}; + let mut bytes: Bytes = if first_read > 0 {first_bytes.clone()} else {vec![0; READAHEAD_BYTES]}; let n = if first_read > 0 {first_read} else {instream.read(&mut(bytes[..])).unwrap_or_else(|_| die!("Error reading from the file/stream."))}; if n == 0 { break; } first_read = 0; let s = PayloadInfo::from(&(bytes[..])).unwrap_or_else(|e| die!("Invalid RLP in the file/stream: {:?}", e)).total(); bytes.resize(s, 0); - instream.read_exact(&mut(bytes[8..])).unwrap_or_else(|_| die!("Error reading from the file/stream.")); + instream.read_exact(&mut(bytes[READAHEAD_BYTES..])).unwrap_or_else(|_| die!("Error reading from the file/stream.")); do_import(bytes); } } From 1e9da1e0fade195101eac0220590324bbc3d25ea Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Thu, 16 Jun 2016 11:21:35 +0200 Subject: [PATCH 042/239] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index acd873b74..e942943ec 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do - Windows Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the rustup installer from - https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe and use the following command to install and set up the msvc toolchain: + https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe, start "VS2015 x64 Native Tools Command Prompt", and use the following command to install and set up the msvc toolchain: ``` $ rustup default stable-x86_64-pc-windows-msvc ``` @@ -73,4 +73,4 @@ To get started, just run $ ./target/release/parity ``` -and parity will begin syncing the Ethereum blockchain. \ No newline at end of file +and parity will begin syncing the Ethereum blockchain. From 88b03580ff855749114ecbc42302016f5fc0763d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 16 Jun 2016 12:44:08 +0200 Subject: [PATCH 043/239] Gas price statistics. (#1291) * Gas price statistics. Affects eth_gasPrice. Added ethcore_gasPriceStatistics. Closes #1265 * Fix a bug in eth_gasPrice * Fix tests. * Revert minor alteration. * Tests for gas_price_statistics. - Tests; - Additional infrastructure for generating test blocks with transactions. --- ethcore/res/null.json | 33 +++++++++++ ethcore/src/client/client.rs | 3 +- ethcore/src/client/mod.rs | 28 +++++++++ ethcore/src/spec/spec.rs | 5 ++ ethcore/src/tests/client.rs | 12 ++++ ethcore/src/tests/helpers.rs | 75 +++++++++++++++++++----- ethcore/src/verification/verification.rs | 2 +- parity/rpc_apis.rs | 2 +- rpc/src/v1/impls/eth.rs | 14 ++++- rpc/src/v1/impls/ethcore.rs | 37 +++++++++--- rpc/src/v1/tests/mocked/ethcore.rs | 62 +++++++++++++------- rpc/src/v1/traits/ethcore.rs | 4 ++ 12 files changed, 225 insertions(+), 52 deletions(-) create mode 100644 ethcore/res/null.json diff --git a/ethcore/res/null.json b/ethcore/res/null.json new file mode 100644 index 000000000..b9b2b1260 --- /dev/null +++ b/ethcore/res/null.json @@ -0,0 +1,33 @@ +{ + "name": "Morden", + "engine": { + "Null": null + }, + "params": { + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x2" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x00006d6f7264656e", + "mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x2fefd8" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "0", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "0", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "0", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "0", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "0" } + } +} diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 75a60204f..85a3d693d 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -770,8 +770,7 @@ impl MiningBlockChainClient for Client where V: Verifier { author, gas_floor_target, extra_data, - ).expect("OpenBlock::new only fails if parent state root invalid. State root of best block's header is never invalid. \ - Therefore creating an OpenBlock with the best block's header will not fail."); + ).expect("OpenBlock::new only fails if parent state root invalid; state root of best block's header is never invalid; qed"); // Add uncles self.chain diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index dbd09ea4a..3fec68815 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -34,6 +34,7 @@ pub use env_info::{LastHashes, EnvInfo}; use util::bytes::Bytes; use util::hash::{Address, H256, H2048}; use util::numbers::U256; +use util::Itertools; use blockchain::TreeRoute; use block_queue::BlockQueueInfo; use block::OpenBlock; @@ -41,6 +42,7 @@ use header::{BlockNumber, Header}; use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; +use views::BlockView; use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; use trace::LocalizedTrace; @@ -193,6 +195,32 @@ pub trait BlockChainClient : Sync + Send { /// list all transactions fn all_transactions(&self) -> Vec; + + /// Get the gas price distribution. + fn gas_price_statistics(&self, sample_size: usize, distribution_size: usize) -> Result, ()> { + let mut h = self.chain_info().best_block_hash; + let mut corpus = Vec::new(); + for _ in 0..sample_size { + let block_bytes = self.block(BlockID::Hash(h)).expect("h is either the best_block_hash or an ancestor; qed"); + let block = BlockView::new(&block_bytes); + let header = block.header_view(); + if header.number() == 0 { + break; + } + block.transaction_views().iter().foreach(|t| corpus.push(t.gas_price())); + h = header.parent_hash().clone(); + } + corpus.sort(); + let n = corpus.len(); + if n > 0 { + Ok((0..(distribution_size + 1)) + .map(|i| corpus[i * (n - 1) / distribution_size]) + .collect::>() + ) + } else { + Err(()) + } + } } /// Extended client interface used for mining diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 743f1bd9b..02b311b24 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -244,6 +244,11 @@ impl Spec { pub fn new_test() -> Spec { Spec::load(include_bytes!("../../res/null_morden.json")) } + + /// Create a new Spec which is a NullEngine consensus with a premine of address whose secret is sha3(''). + pub fn new_null() -> Spec { + Spec::load(include_bytes!("../../res/null.json")) + } } #[cfg(test)] diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index d87b41b62..a5459035e 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -112,6 +112,18 @@ fn can_collect_garbage() { assert!(client.blockchain_cache_info().blocks < 100 * 1024); } +#[test] +fn can_generate_gas_price_statistics() { + let client_result = generate_dummy_client_with_data(16, 1, &vec_into![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + let client = client_result.reference(); + let s = client.gas_price_statistics(8, 8).unwrap(); + assert_eq!(s, vec_into![8, 8, 9, 10, 11, 12, 13, 14, 15]); + let s = client.gas_price_statistics(16, 8).unwrap(); + assert_eq!(s, vec_into![0, 1, 3, 5, 7, 9, 11, 13, 15]); + let s = client.gas_price_statistics(32, 8).unwrap(); + assert_eq!(s, vec_into![0, 1, 3, 5, 7, 9, 11, 13, 15]); +} + #[test] fn can_handle_long_fork() { let client_result = generate_dummy_client(1200); diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 3b27ef4a4..151d53bba 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -17,6 +17,7 @@ use client::{BlockChainClient, Client, ClientConfig}; use common::*; use spec::*; +use block::{OpenBlock}; use blockchain::{BlockChain, Config as BlockChainConfig}; use state::*; use evm::Schedule; @@ -85,6 +86,7 @@ impl Engine for TestEngine { } } +// TODO: move everything over to get_null_spec. pub fn get_test_spec() -> Spec { Spec::new_test() } @@ -126,7 +128,7 @@ fn create_unverifiable_block(order: u32, parent_hash: H256) -> Bytes { create_test_block(&create_unverifiable_block_header(order, parent_hash)) } -pub fn create_test_block_with_data(header: &Header, transactions: &[&SignedTransaction], uncles: &[Header]) -> Bytes { +pub fn create_test_block_with_data(header: &Header, transactions: &[SignedTransaction], uncles: &[Header]) -> Bytes { let mut rlp = RlpStream::new_list(3); rlp.append(header); rlp.begin_list(transactions.len()); @@ -138,33 +140,74 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[&SignedTrans } pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult> { + generate_dummy_client_with_spec_and_data(Spec::new_test, block_number, 0, &(vec![])) +} + +pub fn generate_dummy_client_with_data(block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> GuardedTempResult> { + generate_dummy_client_with_spec_and_data(Spec::new_null, block_number, txs_per_block, tx_gas_prices) +} + +pub fn generate_dummy_client_with_spec_and_data(get_test_spec: F, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> GuardedTempResult> where F: Fn()->Spec { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let test_spec = get_test_spec(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let test_engine = &test_spec.engine; - let state_root = test_spec.genesis_header().state_root; - let mut rolling_hash = test_spec.genesis_header().hash(); - let mut rolling_block_number = 1; + + let mut db_result = get_temp_journal_db(); + let mut db = db_result.take(); + test_spec.ensure_db_good(db.as_hashdb_mut()); + let vm_factory = Default::default(); + let genesis_header = test_spec.genesis_header(); + let mut rolling_timestamp = 40; + let mut last_hashes = vec![]; + let mut last_header = genesis_header.clone(); + let kp = KeyPair::from_secret("".sha3()).unwrap() ; + let author = kp.address(); + + let mut n = 0; for _ in 0..block_number { - let mut header = Header::new(); + last_hashes.push(last_header.hash()); - header.gas_limit = test_engine.params().min_gas_limit; - header.difficulty = U256::from(0x20000); - header.timestamp = rolling_timestamp; - header.number = rolling_block_number; - header.parent_hash = rolling_hash; - header.state_root = state_root.clone(); + // forge block. + let mut b = OpenBlock::new( + test_engine.deref(), + &vm_factory, + false, + db, + &last_header, + last_hashes.clone(), + author.clone(), + 3141562.into(), + vec![] + ).unwrap(); + b.set_difficulty(U256::from(0x20000)); + rolling_timestamp += 10; + b.set_timestamp(rolling_timestamp); - rolling_hash = header.hash(); - rolling_block_number = rolling_block_number + 1; - rolling_timestamp = rolling_timestamp + 10; + // first block we don't have any balance, so can't send any transactions. + for _ in 0..txs_per_block { + b.push_transaction(Transaction { + nonce: n.into(), + gas_price: tx_gas_prices[n % tx_gas_prices.len()], + gas: 100000.into(), + action: Action::Create, + data: vec![], + value: U256::zero(), + }.sign(kp.secret()), None).unwrap(); + n += 1; + } - if let Err(e) = client.import_block(create_test_block(&header)) { + let b = b.close_and_lock().seal(test_engine.deref(), vec![]).unwrap(); + + if let Err(e) = client.import_block(b.rlp_bytes()) { panic!("error importing block which is valid by definition: {:?}", e); } + + last_header = BlockView::new(&b.rlp_bytes()).header(); + db = b.drain(); } client.flush_queue(); client.import_verified_blocks(&IoChannel::disconnected()); diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 6511a8ddd..c6b75416b 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -361,7 +361,7 @@ mod tests { nonce: U256::from(2) }.sign(&keypair.secret()); - let good_transactions = [ &tr1, &tr2 ]; + let good_transactions = [ tr1.clone(), tr2.clone() ]; let diff_inc = U256::from(0x40); diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index d9085fc31..f4b2d067f 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -159,7 +159,7 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_queue).to_delegate()); }, Api::Ethcore => { - server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate()) + server.add_delegate(EthcoreClient::new(&deps.client, &deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate()) }, Api::EthcoreSet => { server.add_delegate(EthcoreSetClient::new(&deps.miner).to_delegate()) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 2d337e73c..80245708f 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -153,15 +153,23 @@ impl EthClient where } } + fn default_gas_price(&self) -> Result { + let miner = take_weak!(self.miner); + Ok(take_weak!(self.client) + .gas_price_statistics(100, 8) + .map(|x| x[4]) + .unwrap_or_else(|_| miner.sensible_gas_price()) + ) + } + fn sign_call(&self, request: CallRequest) -> Result { let client = take_weak!(self.client); - let miner = take_weak!(self.miner); let from = request.from.unwrap_or(Address::zero()); Ok(EthTransaction { nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)), action: request.to.map_or(Action::Create, Action::Call), gas: request.gas.unwrap_or(U256::from(50_000_000)), - gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), + gas_price: request.gas_price.unwrap_or_else(|| self.default_gas_price().expect("call only fails if client or miner are unavailable; client and miner are both available to be here; qed")), value: request.value.unwrap_or_else(U256::zero), data: request.data.map_or_else(Vec::new, |d| d.to_vec()) }.fake_sign(from)) @@ -293,7 +301,7 @@ impl Eth for EthClient where fn gas_price(&self, params: Params) -> Result { match params { - Params::None => to_value(&take_weak!(self.miner).sensible_gas_price()), + Params::None => to_value(&try!(self.default_gas_price())), _ => Err(Error::invalid_params()) } } diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/ethcore.rs index b3fe894c6..e77f46f5d 100644 --- a/rpc/src/v1/impls/ethcore.rs +++ b/rpc/src/v1/impls/ethcore.rs @@ -15,30 +15,34 @@ // along with Parity. If not, see . //! Ethcore-specific rpc implementation. -use util::RotatingLogger; +use util::{RotatingLogger}; use util::network_settings::NetworkSettings; use util::misc::version_data; use std::sync::{Arc, Weak}; use std::ops::Deref; -use std::collections::BTreeMap; +use std::collections::{BTreeMap}; +use ethcore::client::{MiningBlockChainClient}; use jsonrpc_core::*; use ethcore::miner::MinerService; use v1::traits::Ethcore; use v1::types::{Bytes}; /// Ethcore implementation. -pub struct EthcoreClient where +pub struct EthcoreClient where + C: MiningBlockChainClient, M: MinerService { + client: Weak, miner: Weak, logger: Arc, settings: Arc, } -impl EthcoreClient where M: MinerService { +impl EthcoreClient where C: MiningBlockChainClient, M: MinerService { /// Creates new `EthcoreClient`. - pub fn new(miner: &Arc, logger: Arc, settings: Arc) -> Self { + pub fn new(client: &Arc, miner: &Arc, logger: Arc, settings: Arc) -> Self { EthcoreClient { + client: Arc::downgrade(client), miner: Arc::downgrade(miner), logger: logger, settings: settings, @@ -46,7 +50,7 @@ impl EthcoreClient where M: MinerService { } } -impl Ethcore for EthcoreClient where M: MinerService + 'static { +impl Ethcore for EthcoreClient where M: MinerService + 'static, C: MiningBlockChainClient + 'static { fn transactions_limit(&self, _: Params) -> Result { to_value(&take_weak!(self.miner).transactions_limit()) @@ -97,8 +101,23 @@ impl Ethcore for EthcoreClient where M: MinerService + 'static { Ok(Value::Object(map)) } - fn default_extra_data(&self, _params: Params) -> Result { - let version = version_data(); - to_value(&Bytes::new(version)) + fn default_extra_data(&self, params: Params) -> Result { + match params { + Params::None => to_value(&Bytes::new(version_data())), + _ => Err(Error::invalid_params()), + } + } + + fn gas_price_statistics(&self, params: Params) -> Result { + match params { + Params::None => match take_weak!(self.client).gas_price_statistics(100, 8) { + Ok(stats) => to_value(&stats + .iter() + .map(|x| to_value(&x).expect("x must be U256; qed")) + .collect::>()), + _ => Err(Error::internal_error()), + }, + _ => Err(Error::invalid_params()), + } } } diff --git a/rpc/src/v1/tests/mocked/ethcore.rs b/rpc/src/v1/tests/mocked/ethcore.rs index 90103adef..68c33ecce 100644 --- a/rpc/src/v1/tests/mocked/ethcore.rs +++ b/rpc/src/v1/tests/mocked/ethcore.rs @@ -20,6 +20,7 @@ use jsonrpc_core::IoHandler; use v1::{Ethcore, EthcoreClient, EthcoreSet, EthcoreSetClient}; use ethcore::miner::MinerService; use v1::tests::helpers::TestMinerService; +use ethcore::client::{TestBlockChainClient}; use util::numbers::*; use rustc_serialize::hex::FromHex; use util::log::RotatingLogger; @@ -29,6 +30,10 @@ fn miner_service() -> Arc { Arc::new(TestMinerService::default()) } +fn client_service() -> Arc { + Arc::new(TestBlockChainClient::default()) +} + fn logger() -> Arc { Arc::new(RotatingLogger::new("rpc=trace".to_owned())) } @@ -45,19 +50,20 @@ fn settings() -> Arc { }) } -fn ethcore_client(miner: &Arc) -> EthcoreClient { - EthcoreClient::new(&miner, logger(), settings()) +fn ethcore_client(client: &Arc, miner: &Arc) -> EthcoreClient { + EthcoreClient::new(client, miner, logger(), settings()) } fn ethcore_set_client(miner: &Arc) -> EthcoreSetClient { - EthcoreSetClient::new(&miner) + EthcoreSetClient::new(miner) } #[test] fn rpc_ethcore_extra_data() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_extraData", "params": [], "id": 1}"#; @@ -72,8 +78,9 @@ fn rpc_ethcore_default_extra_data() { use util::ToPretty; let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_defaultExtraData", "params": [], "id": 1}"#; @@ -85,8 +92,9 @@ fn rpc_ethcore_default_extra_data() { #[test] fn rpc_ethcore_gas_floor_target() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_gasFloorTarget", "params": [], "id": 1}"#; @@ -98,8 +106,9 @@ fn rpc_ethcore_gas_floor_target() { #[test] fn rpc_ethcore_min_gas_price() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_minGasPrice", "params": [], "id": 1}"#; @@ -111,8 +120,9 @@ fn rpc_ethcore_min_gas_price() { #[test] fn rpc_ethcore_set_min_gas_price() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; @@ -125,8 +135,9 @@ fn rpc_ethcore_set_min_gas_price() { #[test] fn rpc_ethcore_set_gas_floor_target() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; @@ -139,8 +150,9 @@ fn rpc_ethcore_set_gas_floor_target() { #[test] fn rpc_ethcore_set_extra_data() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; @@ -153,8 +165,9 @@ fn rpc_ethcore_set_extra_data() { #[test] fn rpc_ethcore_set_author() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; @@ -167,10 +180,11 @@ fn rpc_ethcore_set_author() { #[test] fn rpc_ethcore_dev_logs() { let miner = miner_service(); + let client = client_service(); let logger = logger(); logger.append("a".to_owned()); logger.append("b".to_owned()); - let ethcore = EthcoreClient::new(&miner, logger.clone(), settings()).to_delegate(); + let ethcore = EthcoreClient::new(&client, &miner, logger.clone(), settings()).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); io.add_delegate(ethcore_set_client(&miner).to_delegate()); @@ -184,8 +198,9 @@ fn rpc_ethcore_dev_logs() { #[test] fn rpc_ethcore_dev_logs_levels() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogsLevels", "params":[], "id": 1}"#; @@ -196,8 +211,9 @@ fn rpc_ethcore_dev_logs_levels() { #[test] fn rpc_ethcore_set_transactions_limit() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setTransactionsLimit", "params":[10240240], "id": 1}"#; @@ -210,8 +226,9 @@ fn rpc_ethcore_set_transactions_limit() { #[test] fn rpc_ethcore_transactions_limit() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_transactionsLimit", "params":[], "id": 1}"#; @@ -223,8 +240,9 @@ fn rpc_ethcore_transactions_limit() { #[test] fn rpc_ethcore_net_chain() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netChain", "params":[], "id": 1}"#; @@ -236,8 +254,9 @@ fn rpc_ethcore_net_chain() { #[test] fn rpc_ethcore_net_max_peers() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netMaxPeers", "params":[], "id": 1}"#; @@ -249,8 +268,9 @@ fn rpc_ethcore_net_max_peers() { #[test] fn rpc_ethcore_net_port() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPort", "params":[], "id": 1}"#; @@ -262,8 +282,9 @@ fn rpc_ethcore_net_port() { #[test] fn rpc_ethcore_rpc_settings() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_rpcSettings", "params":[], "id": 1}"#; @@ -275,8 +296,9 @@ fn rpc_ethcore_rpc_settings() { #[test] fn rpc_ethcore_node_name() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_nodeName", "params":[], "id": 1}"#; diff --git a/rpc/src/v1/traits/ethcore.rs b/rpc/src/v1/traits/ethcore.rs index 4ce3eca59..1dd00ff73 100644 --- a/rpc/src/v1/traits/ethcore.rs +++ b/rpc/src/v1/traits/ethcore.rs @@ -57,6 +57,9 @@ pub trait Ethcore: Sized + Send + Sync + 'static { /// Returns default extra data fn default_extra_data(&self, _: Params) -> Result; + /// Returns distribution of gas price in latest blocks. + fn gas_price_statistics(&self, _: Params) -> Result; + /// Should be used to convert object to io delegate. fn to_delegate(self) -> IoDelegate { let mut delegate = IoDelegate::new(Arc::new(self)); @@ -73,6 +76,7 @@ pub trait Ethcore: Sized + Send + Sync + 'static { delegate.add_method("ethcore_rpcSettings", Ethcore::rpc_settings); delegate.add_method("ethcore_nodeName", Ethcore::node_name); delegate.add_method("ethcore_defaultExtraData", Ethcore::default_extra_data); + delegate.add_method("ethcore_gasPriceStatistics", Ethcore::gas_price_statistics); delegate } From 07641b8f0ac9e296973a3e22fec0052a623c7084 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 16 Jun 2016 16:14:22 +0400 Subject: [PATCH 044/239] Key load avoid warning (#1303) * avoid warning with key * fix intendations * more intendation fix * ok() instead of expect() --- util/src/keys/directory.rs | 11 +++++++---- util/src/keys/store.rs | 12 ++++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/util/src/keys/directory.rs b/util/src/keys/directory.rs index 32ac14b55..385a400c7 100644 --- a/util/src/keys/directory.rs +++ b/util/src/keys/directory.rs @@ -428,9 +428,9 @@ impl KeyFileContent { let crypto = match as_object.get("crypto") { None => { return Err(KeyFileParseError::NoCryptoSection); } Some(crypto_json) => match KeyFileCrypto::from_json(crypto_json) { - Ok(crypto) => crypto, - Err(crypto_error) => { return Err(KeyFileParseError::Crypto(crypto_error)); } - } + Ok(crypto) => crypto, + Err(crypto_error) => { return Err(KeyFileParseError::Crypto(crypto_error)); } + } }; Ok(KeyFileContent { @@ -627,7 +627,10 @@ impl KeyDirectory { } } - + /// Checks if key exists + pub fn exists(&self, id: &Uuid) -> bool { + KeyDirectory::load_key(&self.key_path(id)).is_ok() + } } diff --git a/util/src/keys/store.rs b/util/src/keys/store.rs index f6f41745f..b8a1de272 100644 --- a/util/src/keys/store.rs +++ b/util/src/keys/store.rs @@ -294,9 +294,9 @@ impl SecretStore { if let Some(unlock) = read_lock.get(account) { (unlock.relock_on_use, match crypto::KeyPair::from_secret(unlock.secret) { Ok(pair) => match pair.sign(message) { - Ok(signature) => Ok(signature), - Err(_) => Err(SigningError::InvalidSecret) - }, + Ok(signature) => Ok(signature), + Err(_) => Err(SigningError::InvalidSecret) + }, Err(_) => Err(SigningError::InvalidSecret) }) } else { @@ -348,6 +348,10 @@ impl SecretStore { garbage_lock.shrink_to_fit(); } + + fn exists(&self, key: &H128) -> bool { + self.directory.exists(key) + } } fn derive_key_iterations(password: &str, salt: &H256, c: u32) -> (Bytes, Bytes) { @@ -408,7 +412,7 @@ impl EncryptedHashMap for SecretStore { } fn insert(&mut self, key: H128, value: Value, password: &str) -> Option { - let previous = if let Ok(previous_value) = self.get(&key, password) { Some(previous_value) } else { None }; + let previous = if !self.exists(&key) { None } else { self.get(&key, password).ok() }; // crypto random initiators let salt = H256::random(); From 2a101baf1d4158487ad08a3ed773bdbf335a3d55 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 16 Jun 2016 19:02:55 +0400 Subject: [PATCH 045/239] Appveyor config for windows build+installer (#1302) * appveyor * proper dist name * quote * win-build config * proper build section * tests in release * plugin dir * cache binaries * quotes * escaped quotes * forces user dir * fixes * syntax * proper cahce dir * quotes? * root nsis instead of bin * submodules init * artifact path fix * no submodule * raw link here * another way to force cargo cache * include vc++ 2015 redist * fix name of the dist * ETHCORE -> Ethcore --- appveyor.yml | 29 +++++++++++++++++++++++++++++ nsis/installer.nsi | 7 ++++++- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..b980aba42 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,29 @@ +environment: + matrix: + - TARGET: x86_64-pc-windows-msvc +install: + - git submodule update --init --recursive + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.9.0-x86_64-pc-windows-msvc.exe" + - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -FileName nsis\SimpleFC.dll + - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -FileName nsis\vc_redist.x64.exe + - rust-1.9.0-x86_64-pc-windows-msvc.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin;C:\Program Files (x86)\NSIS + - rustc -V + - cargo -V + +build: off + +test_script: + - cargo test --verbose --release + +after_test: + - cargo build --verbose --release + - makensis.exe nsis\installer.nsi + +artifacts: + - path: nsis\installer.exe + name: Windows Installer (x86_64) + +cache: + - target + - C:\users\appveyor\.cargo -> appveyor.yml diff --git a/nsis/installer.nsi b/nsis/installer.nsi index 10143306a..fffcc1dd9 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -1,11 +1,13 @@ !define APPNAME "Parity" -!define COMPANYNAME "ETHCORE" +!define COMPANYNAME "Ethcore" !define DESCRIPTION "Fast, light, robust Ethereum implementation" !define VERSIONMAJOR 1 !define VERSIONMINOR 2 !define VERSIONBUILD 0 +!addplugindir .\ + !define HELPURL "https://github.com/ethcore/parity/wiki" # "Support Information" link !define UPDATEURL "https://github.com/ethcore/parity/releases" # "Product Updates" link !define ABOUTURL "https://github.com/ethcore/parity" # "Publisher" link @@ -47,6 +49,9 @@ section "install" # Files added here should be removed by the uninstaller (see section "uninstall") file /oname=parity.exe ..\target\release\parity.exe file "logo.ico" + file vc_redist.x64.exe + + ExecWait '"$INSTDIR\vc_redist.x64.exe" /passive /norestart' # Add any other files for the install directory (license files, app data, etc) here # Uninstaller - See function un.onInit and section "uninstall" for configuration From b38488dd0789a6ee817cf6ba87116c3ee83d53b9 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 17 Jun 2016 12:58:28 +0200 Subject: [PATCH 046/239] Network shutdown --- ethcore/src/service.rs | 23 +++++--- parity/cli.rs | 2 + parity/io_handler.rs | 19 ++++++- parity/main.rs | 11 ++-- rpc/src/v1/impls/net.rs | 10 ++++ rpc/src/v1/tests/helpers/sync_provider.rs | 6 +++ rpc/src/v1/traits/net.rs | 8 +++ sync/src/lib.rs | 24 +++++++-- util/src/io/service.rs | 65 +++++++++++++++-------- util/src/network/host.rs | 47 ++++++++++++---- util/src/network/service.rs | 55 +++++++++++++------ util/src/network/stats.rs | 2 +- 12 files changed, 205 insertions(+), 67 deletions(-) diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index 13f1c9f74..6adca7b52 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -41,6 +41,10 @@ pub enum SyncMessage { NewChainHead, /// A block is ready BlockVerified, + /// Start network command. + StartNetwork, + /// Stop network command. + StopNetwork, } /// IO Message type used for Network service @@ -48,17 +52,20 @@ pub type NetSyncMessage = NetworkIoMessage; /// Client service setup. Creates and registers client and network services with the IO subsystem. pub struct ClientService { - net_service: NetworkService, + net_service: Arc>, client: Arc, panic_handler: Arc } impl ClientService { /// Start the service in a separate thread. - pub fn start(config: ClientConfig, spec: Spec, net_config: NetworkConfiguration, db_path: &Path, miner: Arc) -> Result { + pub fn start(config: ClientConfig, spec: Spec, net_config: NetworkConfiguration, db_path: &Path, miner: Arc, enable_network: bool) -> Result { let panic_handler = PanicHandler::new_in_arc(); - let mut net_service = try!(NetworkService::start(net_config)); + let net_service = try!(NetworkService::new(net_config)); panic_handler.forward_from(&net_service); + if enable_network { + try!(net_service.start()); + } info!("Starting {}", net_service.host_info()); info!("Configured for {} using {:?} engine", spec.name, spec.engine.name()); @@ -70,7 +77,7 @@ impl ClientService { try!(net_service.io().register_handler(client_io)); Ok(ClientService { - net_service: net_service, + net_service: Arc::new(net_service), client: client, panic_handler: panic_handler, }) @@ -82,8 +89,8 @@ impl ClientService { } /// Get general IO interface - pub fn io(&mut self) -> &mut IoService { - self.net_service.io() + pub fn register_io_handler(&self, handler: Arc + Send>) -> Result<(), IoError> { + self.net_service.io().register_handler(handler) } /// Get client interface @@ -92,8 +99,8 @@ impl ClientService { } /// Get network service component - pub fn network(&mut self) -> &mut NetworkService { - &mut self.net_service + pub fn network(&mut self) -> Arc> { + self.net_service.clone() } } diff --git a/parity/cli.rs b/parity/cli.rs index b8aa88299..7e2a1d6a0 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -52,6 +52,7 @@ Account Options: --no-import-keys Do not import keys from legacy clients. Networking Options: + --no-network Disable p2p networking. --port PORT Override the port on which the node should listen [default: 30303]. --peers NUM Try to maintain that many peers [default: 25]. @@ -266,6 +267,7 @@ pub struct Args { pub flag_format: Option, pub flag_jitvm: bool, pub flag_no_color: bool, + pub flag_no_network: bool, // legacy... pub flag_geth: bool, pub flag_nodekey: Option, diff --git a/parity/io_handler.rs b/parity/io_handler.rs index d130d584c..569a11716 100644 --- a/parity/io_handler.rs +++ b/parity/io_handler.rs @@ -16,10 +16,10 @@ use std::sync::Arc; use ethcore::client::Client; -use ethcore::service::NetSyncMessage; +use ethcore::service::{NetSyncMessage, SyncMessage}; use ethsync::EthSync; use util::keys::store::AccountService; -use util::{TimerToken, IoHandler, IoContext}; +use util::{TimerToken, IoHandler, IoContext, NetworkService, NetworkIoMessage}; use informant::Informant; @@ -33,6 +33,7 @@ pub struct ClientIoHandler { pub sync: Arc, pub accounts: Arc, pub info: Informant, + pub network: Arc>, } impl IoHandler for ClientIoHandler { @@ -48,6 +49,20 @@ impl IoHandler for ClientIoHandler { _ => {} } } + + fn message(&self, _io: &IoContext, message: &NetSyncMessage) { + match *message { + NetworkIoMessage::User(SyncMessage::StartNetwork) => { + info!("Starting network"); + self.network.start().unwrap_or_else(|e| warn!("Error starting network: {:?}", e)); + }, + NetworkIoMessage::User(SyncMessage::StopNetwork) => { + info!("Stopping network"); + self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e)); + }, + _ => {/* Ignore other messages */}, + } + } } diff --git a/parity/main.rs b/parity/main.rs index 284dac673..80ea29576 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -198,7 +198,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // Build client let mut service = ClientService::start( - client_config, spec, net_settings, Path::new(&conf.path()), miner.clone() + client_config, spec, net_settings, Path::new(&conf.path()), miner.clone(), !conf.args.flag_no_network ).unwrap_or_else(|e| die_with_error("Client", e)); panic_handler.forward_from(&service); @@ -208,7 +208,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) let network_settings = Arc::new(conf.network_settings()); // Sync - let sync = EthSync::register(service.network(), sync_config, client.clone()); + let sync = EthSync::register(service.network().deref(), sync_config, client.clone()); let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies { signer_port: conf.signer_port(), @@ -269,8 +269,9 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) info: Informant::new(conf.have_color()), sync: sync.clone(), accounts: account_service.clone(), + network: service.network(), }); - service.io().register_handler(io_handler).expect("Error registering IO handler"); + service.register_io_handler(io_handler).expect("Error registering IO handler"); // Handle exit wait_for_exit(panic_handler, rpc_server, dapps_server, signer_server); @@ -309,7 +310,7 @@ fn execute_export(conf: Configuration) { // Build client let service = ClientService::start( - client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), + client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), false ).unwrap_or_else(|e| die_with_error("Client", e)); panic_handler.forward_from(&service); @@ -380,7 +381,7 @@ fn execute_import(conf: Configuration) { // Build client let service = ClientService::start( - client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), + client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), false ).unwrap_or_else(|e| die_with_error("Client", e)); panic_handler.forward_from(&service); diff --git a/rpc/src/v1/impls/net.rs b/rpc/src/v1/impls/net.rs index fb502e6cf..977561ede 100644 --- a/rpc/src/v1/impls/net.rs +++ b/rpc/src/v1/impls/net.rs @@ -47,4 +47,14 @@ impl Net for NetClient where S: SyncProvider + 'static { // right now (11 march 2016), we are always listening for incoming connections Ok(Value::Bool(true)) } + + fn start_network(&self, _: Params) -> Result { + take_weak!(self.sync).start_network(); + Ok(Value::Bool(true)) + } + + fn stop_network(&self, _: Params) -> Result { + take_weak!(self.sync).stop_network(); + Ok(Value::Bool(true)) + } } diff --git a/rpc/src/v1/tests/helpers/sync_provider.rs b/rpc/src/v1/tests/helpers/sync_provider.rs index 114b5b08f..11fa1cb9e 100644 --- a/rpc/src/v1/tests/helpers/sync_provider.rs +++ b/rpc/src/v1/tests/helpers/sync_provider.rs @@ -59,5 +59,11 @@ impl SyncProvider for TestSyncProvider { fn status(&self) -> SyncStatus { self.status.read().unwrap().clone() } + + fn start_network(&self) { + } + + fn stop_network(&self) { + } } diff --git a/rpc/src/v1/traits/net.rs b/rpc/src/v1/traits/net.rs index 56fba3e32..b65f53491 100644 --- a/rpc/src/v1/traits/net.rs +++ b/rpc/src/v1/traits/net.rs @@ -30,12 +30,20 @@ pub trait Net: Sized + Send + Sync + 'static { /// Otherwise false. fn is_listening(&self, _: Params) -> Result; + /// Start the network. + fn start_network(&self, _: Params) -> Result; + + /// Stop the network. + fn stop_network(&self, _: Params) -> Result; + /// Should be used to convert object to io delegate. fn to_delegate(self) -> IoDelegate { let mut delegate = IoDelegate::new(Arc::new(self)); delegate.add_method("net_version", Net::version); delegate.add_method("net_peerCount", Net::peer_count); delegate.add_method("net_listening", Net::is_listening); + delegate.add_method("net_start", Net::start_network); + delegate.add_method("net_stop", Net::stop_network); delegate } } diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 9c7da71ab..ca31ea020 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -66,8 +66,10 @@ use util::network::{NetworkProtocolHandler, NetworkService, NetworkContext, Peer use util::TimerToken; use util::{U256, ONE_U256}; use ethcore::client::Client; -use ethcore::service::SyncMessage; +use ethcore::service::{SyncMessage, NetSyncMessage}; use io::NetSyncIo; +use util::io::IoChannel; +use util::NetworkIoMessage; use chain::ChainSync; mod chain; @@ -98,6 +100,10 @@ impl Default for SyncConfig { pub trait SyncProvider: Send + Sync { /// Get sync status fn status(&self) -> SyncStatus; + /// Start the network + fn start_network(&self); + /// Stop the network + fn stop_network(&self); } /// Ethereum network protocol handler @@ -105,18 +111,21 @@ pub struct EthSync { /// Shared blockchain client. TODO: this should evetually become an IPC endpoint chain: Arc, /// Sync strategy - sync: RwLock + sync: RwLock, + /// IO communication chnnel. + io_channel: RwLock>, } pub use self::chain::{SyncStatus, SyncState}; impl EthSync { /// Creates and register protocol with the network service - pub fn register(service: &mut NetworkService, config: SyncConfig, chain: Arc) -> Arc { + pub fn register(service: &NetworkService, config: SyncConfig, chain: Arc) -> Arc { let sync = ChainSync::new(config, chain.deref()); let sync = Arc::new(EthSync { chain: chain, sync: RwLock::new(sync), + io_channel: RwLock::new(IoChannel::disconnected()), }); service.register_protocol(sync.clone(), "eth", &[62u8, 63u8]).expect("Error registering eth protocol handler"); sync @@ -138,11 +147,20 @@ impl SyncProvider for EthSync { fn status(&self) -> SyncStatus { self.sync.read().unwrap().status() } + + fn start_network(&self) { + self.io_channel.read().unwrap().send(NetworkIoMessage::User(SyncMessage::StartNetwork)).expect("Error sending IO notification"); + } + + fn stop_network(&self) { + self.io_channel.read().unwrap().send(NetworkIoMessage::User(SyncMessage::StopNetwork)).expect("Error sending IO notification"); + } } impl NetworkProtocolHandler for EthSync { fn initialize(&self, io: &NetworkContext) { io.register_timer(0, 1000).expect("Error registering sync timer"); + *self.io_channel.write().unwrap() = io.io_channel(); } fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) { diff --git a/util/src/io/service.rs b/util/src/io/service.rs index 409667c46..b924bbe44 100644 --- a/util/src/io/service.rs +++ b/util/src/io/service.rs @@ -17,10 +17,12 @@ use std::sync::*; use std::thread::{self, JoinHandle}; use std::collections::HashMap; +use std::ops::Deref; use mio::*; +use crossbeam::sync::chase_lev; +use slab::Slab; use error::*; use io::{IoError, IoHandler}; -use crossbeam::sync::chase_lev; use io::worker::{Worker, Work, WorkType}; use panics::*; @@ -33,6 +35,14 @@ pub type HandlerId = usize; /// Maximum number of tokens a handler can use pub const TOKENS_PER_HANDLER: usize = 16384; +const MAX_HANDLERS: usize = 8; + +fn compare_arcs(a: Arc, b: Arc) -> bool { + let p1 = &*a as *const T; + let p2 = &*b as *const T; + info!("{:p} == {:p} : {}", p1, p2 , p1 == p2); + p1 == p2 +} /// Messages used to communicate with the event loop from other threads. #[derive(Clone)] @@ -43,6 +53,9 @@ pub enum IoMessage where Message: Send + Clone + Sized { AddHandler { handler: Arc+Send>, }, + RemoveHandler { + handler_id: HandlerId, + }, AddTimer { handler_id: HandlerId, token: TimerToken, @@ -138,6 +151,15 @@ impl IoContext where Message: Send + Clone + 'static { pub fn channel(&self) -> IoChannel { self.channel.clone() } + + /// Unregister current IO handler. + pub fn unregister_handler(&self) -> Result<(), IoError> { + try!(self.channel.send_io(IoMessage::RemoveHandler { + handler_id: self.handler, + })); + Ok(()) + } + } #[derive(Clone)] @@ -149,7 +171,7 @@ struct UserTimer { /// Root IO handler. Manages user handlers, messages and IO timers. pub struct IoManager where Message: Send + Sync { timers: Arc>>, - handlers: Vec>>, + handlers: Slab>, HandlerId>, workers: Vec, worker_channel: chase_lev::Worker>, work_ready: Arc, @@ -175,7 +197,7 @@ impl IoManager where Message: Send + Sync + Clone + 'static { let mut io = IoManager { timers: Arc::new(RwLock::new(HashMap::new())), - handlers: Vec::new(), + handlers: Slab::new(MAX_HANDLERS), worker_channel: worker, workers: workers, work_ready: work_ready, @@ -192,10 +214,7 @@ impl Handler for IoManager where Message: Send + Clone + Sync fn ready(&mut self, _event_loop: &mut EventLoop, token: Token, events: EventSet) { let handler_index = token.as_usize() / TOKENS_PER_HANDLER; let token_id = token.as_usize() % TOKENS_PER_HANDLER; - if handler_index >= self.handlers.len() { - panic!("Unexpected stream token: {}", token.as_usize()); - } - let handler = self.handlers[handler_index].clone(); + let handler = self.handlers.get(handler_index).unwrap_or_else(|| panic!("Unexpected stream token: {}", token.as_usize())).clone(); if events.is_hup() { self.worker_channel.push(Work { work_type: WorkType::Hup, token: token_id, handler: handler.clone(), handler_id: handler_index }); @@ -214,12 +233,9 @@ impl Handler for IoManager where Message: Send + Clone + Sync fn timeout(&mut self, event_loop: &mut EventLoop, token: Token) { let handler_index = token.as_usize() / TOKENS_PER_HANDLER; let token_id = token.as_usize() % TOKENS_PER_HANDLER; - if handler_index >= self.handlers.len() { - panic!("Unexpected timer token: {}", token.as_usize()); - } + let handler = self.handlers.get(handler_index).unwrap_or_else(|| panic!("Unexpected stream token: {}", token.as_usize())).clone(); if let Some(timer) = self.timers.read().unwrap().get(&token.as_usize()) { event_loop.timeout_ms(token, timer.delay).expect("Error re-registering user timer"); - let handler = self.handlers[handler_index].clone(); self.worker_channel.push(Work { work_type: WorkType::Timeout, token: token_id, handler: handler, handler_id: handler_index }); self.work_ready.notify_all(); } @@ -232,12 +248,14 @@ impl Handler for IoManager where Message: Send + Clone + Sync event_loop.shutdown(); }, IoMessage::AddHandler { handler } => { - let handler_id = { - self.handlers.push(handler.clone()); - self.handlers.len() - 1 - }; + let handler_id = self.handlers.insert(handler.clone()).unwrap_or_else(|_| panic!("Too many handlers registered")); handler.initialize(&IoContext::new(IoChannel::new(event_loop.channel()), handler_id)); }, + IoMessage::RemoveHandler { handler_id } => { + // TODO: flush event loop + self.handlers.remove(handler_id); + info!("{} left", self.handlers.count()); + }, IoMessage::AddTimer { handler_id, token, delay } => { let timer_id = token + handler_id * TOKENS_PER_HANDLER; let timeout = event_loop.timeout_ms(Token(timer_id), delay).expect("Error registering user timer"); @@ -267,9 +285,12 @@ impl Handler for IoManager where Message: Send + Clone + Sync handler.update_stream(token, Token(token + handler_id * TOKENS_PER_HANDLER), event_loop); }, IoMessage::UserMessage(data) => { - for n in 0 .. self.handlers.len() { - let handler = self.handlers[n].clone(); - self.worker_channel.push(Work { work_type: WorkType::Message(data.clone()), token: 0, handler: handler, handler_id: n }); + //TODO: better way to iterate the slab + for id in 0 .. MAX_HANDLERS { + if let Some(h) = self.handlers.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.work_ready.notify_all(); } @@ -351,8 +372,8 @@ impl IoService where Message: Send + Sync + Clone + 'static { }) } - /// Regiter a IO hadnler with the event loop. - pub fn register_handler(&mut self, handler: Arc+Send>) -> Result<(), IoError> { + /// Regiter an IO handler with the event loop. + pub fn register_handler(&self, handler: Arc+Send>) -> Result<(), IoError> { try!(self.host_channel.send(IoMessage::AddHandler { handler: handler, })); @@ -360,13 +381,13 @@ 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(&mut self, message: Message) -> Result<(), IoError> { + pub fn send_message(&self, message: Message) -> Result<(), IoError> { try!(self.host_channel.send(IoMessage::UserMessage(message))); Ok(()) } /// Create a new message channel - pub fn channel(&mut self) -> IoChannel { + pub fn channel(&self) -> IoChannel { IoChannel { channel: Some(self.host_channel.clone()) } } } diff --git a/util/src/network/host.rs b/util/src/network/host.rs index abace1983..6001769fe 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -49,7 +49,7 @@ const MAX_HANDSHAKES: usize = 80; const MAX_HANDSHAKES_PER_ROUND: usize = 32; const MAINTENANCE_TIMEOUT: u64 = 1000; -#[derive(Debug)] +#[derive(Debug, Clone)] /// Network service configuration pub struct NetworkConfiguration { /// Directory path to store network configuration. None means nothing will be saved @@ -233,6 +233,11 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone self.io.message(NetworkIoMessage::User(msg)); } + /// Send an IO message + pub fn io_channel(&self) -> IoChannel> { + self.io.channel() + } + /// Disable current protocol capability for given peer. If no capabilities left peer gets disconnected. pub fn disable_peer(&self, peer: PeerId) { //TODO: remove capability, disconnect if no capabilities left @@ -327,7 +332,7 @@ pub struct Host where Message: Send + Sync + Clone { impl Host where Message: Send + Sync + Clone { /// Create a new instance - pub fn new(config: NetworkConfiguration) -> Result, UtilError> { + pub fn new(config: NetworkConfiguration, stats: Arc) -> Result, UtilError> { let mut listen_address = match config.listen_address { None => SocketAddr::from_str("0.0.0.0:30304").unwrap(), Some(addr) => addr, @@ -371,7 +376,7 @@ impl Host where Message: Send + Sync + Clone { handlers: RwLock::new(HashMap::new()), timers: RwLock::new(HashMap::new()), timer_counter: RwLock::new(USER_TIMER), - stats: Arc::new(NetworkStats::default()), + stats: stats, pinned_nodes: Vec::new(), num_sessions: AtomicUsize::new(0), }; @@ -383,10 +388,6 @@ impl Host where Message: Send + Sync + Clone { Ok(host) } - pub fn stats(&self) -> Arc { - self.stats.clone() - } - pub fn add_node(&mut self, id: &str) { match Node::from_str(id) { Err(e) => { debug!(target: "network", "Could not add node {}: {:?}", id, e); }, @@ -401,8 +402,8 @@ impl Host where Message: Send + Sync + Clone { } } - pub fn client_version(&self) -> String { - self.info.read().unwrap().client_version.clone() + pub fn client_version() -> String { + version() } pub fn external_url(&self) -> Option { @@ -415,6 +416,23 @@ impl Host where Message: Send + Sync + Clone { r } + pub fn stop(&self, io: &IoContext>) -> Result<(), UtilError> { + let mut to_kill = Vec::new(); + for e in self.sessions.write().unwrap().iter_mut() { + let mut s = e.lock().unwrap(); + if !s.keep_alive(io) { + s.disconnect(io, DisconnectReason::PingTimeout); + to_kill.push(s.token()); + } + } + for p in to_kill { + trace!(target: "network", "Ping timeout: {}", p); + self.kill_connection(p, io, true); + } + io.unregister_handler(); + Ok(()) + } + fn init_public_interface(&self, io: &IoContext>) -> Result<(), UtilError> { io.clear_timer(INIT_PUBLIC).unwrap(); if self.info.read().unwrap().public_endpoint.is_some() { @@ -767,6 +785,13 @@ impl Host where Message: Send + Sync + Clone { } } + +impl Drop for Host where Message: Send + Sync + Clone { + fn drop(&mut self) { + info!("Dropping host"); + } +} + impl IoHandler> for Host where Message: Send + Sync + Clone + 'static { /// Initialize networking fn initialize(&self, io: &IoContext>) { @@ -831,8 +856,8 @@ impl IoHandler> for Host where Messa }, _ => match self.timers.read().unwrap().get(&token).cloned() { Some(timer) => match self.handlers.read().unwrap().get(timer.protocol).cloned() { - None => { warn!(target: "network", "No handler found for protocol: {:?}", timer.protocol) }, - Some(h) => { h.timeout(&NetworkContext::new(io, timer.protocol, None, self.sessions.clone()), timer.token); } + None => { warn!(target: "network", "No handler found for protocol: {:?}", timer.protocol) }, + Some(h) => { h.timeout(&NetworkContext::new(io, timer.protocol, None, self.sessions.clone()), timer.token); } }, None => { warn!("Unknown timer token: {}", token); } // timer is not registerd through us } diff --git a/util/src/network/service.rs b/util/src/network/service.rs index 49957f7e7..406126425 100644 --- a/util/src/network/service.rs +++ b/util/src/network/service.rs @@ -28,33 +28,33 @@ use io::*; pub struct NetworkService where Message: Send + Sync + Clone + 'static { io_service: IoService>, host_info: String, - host: Arc>, + host: RwLock>>>, stats: Arc, - panic_handler: Arc + panic_handler: Arc, + config: NetworkConfiguration, } impl NetworkService where Message: Send + Sync + Clone + 'static { /// Starts IO event loop - pub fn start(config: NetworkConfiguration) -> Result, UtilError> { + pub fn new(config: NetworkConfiguration) -> Result, UtilError> { let panic_handler = PanicHandler::new_in_arc(); - let mut io_service = try!(IoService::>::start()); + let io_service = try!(IoService::>::start()); panic_handler.forward_from(&io_service); - let host = Arc::new(try!(Host::new(config))); - let stats = host.stats().clone(); - let host_info = host.client_version(); - try!(io_service.register_handler(host.clone())); + let stats = Arc::new(NetworkStats::new()); + let host_info = Host::::client_version(); Ok(NetworkService { io_service: io_service, host_info: host_info, stats: stats, panic_handler: panic_handler, - host: host, + host: RwLock::new(None), + config: config, }) } /// Regiter a new protocol handler with the event loop. - pub fn register_protocol(&mut self, handler: Arc+Send + Sync>, protocol: ProtocolId, versions: &[u8]) -> Result<(), NetworkError> { + pub fn register_protocol(&self, handler: Arc+Send + Sync>, protocol: ProtocolId, versions: &[u8]) -> Result<(), NetworkError> { try!(self.io_service.send_message(NetworkIoMessage::AddHandler { handler: handler, protocol: protocol, @@ -69,8 +69,8 @@ impl NetworkService where Message: Send + Sync + Clone + 'stat } /// Returns underlying io service. - pub fn io(&mut self) -> &mut IoService> { - &mut self.io_service + pub fn io(&self) -> &IoService> { + &self.io_service } /// Returns network statistics. @@ -80,12 +80,37 @@ impl NetworkService where Message: Send + Sync + Clone + 'stat /// Returns external url if available. pub fn external_url(&self) -> Option { - self.host.external_url() + let host = self.host.read().unwrap(); + host.as_ref().and_then(|h| h.external_url()) } /// Returns external url if available. - pub fn local_url(&self) -> String { - self.host.local_url() + pub fn local_url(&self) -> Option { + let host = self.host.read().unwrap(); + host.as_ref().map(|h| h.local_url()) + } + + /// Start network IO + pub fn start(&self) -> Result<(), UtilError> { + let mut host = self.host.write().unwrap(); + if host.is_none() { + let h = Arc::new(try!(Host::new(self.config.clone(), self.stats.clone()))); + try!(self.io_service.register_handler(h.clone())); + *host = Some(h); + } + Ok(()) + } + + /// Stop network IO + pub fn stop(&self) -> Result<(), UtilError> { + let mut host = self.host.write().unwrap(); + if let Some(ref host) = *host { + info!("Unregistering handler"); + let io = IoContext::new(self.io_service.channel(), 0); //TODO: take token id from host + host.stop(&io); + } + *host = None; + Ok(()) } } diff --git a/util/src/network/stats.rs b/util/src/network/stats.rs index 30e751a81..cc3b845da 100644 --- a/util/src/network/stats.rs +++ b/util/src/network/stats.rs @@ -65,7 +65,7 @@ impl NetworkStats { self.sessions.load(Ordering::Relaxed) } - #[cfg(test)] + /// Create a new empty instance. pub fn new() -> NetworkStats { NetworkStats { recv: AtomicUsize::new(0), From 67ffac1df932db92f416c83b0d81d9bb176159a0 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 17 Jun 2016 16:01:33 +0200 Subject: [PATCH 047/239] Check for session expiration on peer registration --- sync/src/chain.rs | 4 ++++ sync/src/io.rs | 6 ++++++ sync/src/tests/chain.rs | 10 ++++++++++ util/src/network/host.rs | 7 ++++++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 90e18d8e8..7e23601e4 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -356,6 +356,10 @@ impl ChainSync { }; trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{})", peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest_hash, peer.genesis); + if io.is_expired() { + info!("Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id)); + return Ok(()); + } if self.peers.contains_key(&peer_id) { warn!("Unexpected status packet from {}:{}", peer_id, io.peer_info(peer_id)); diff --git a/sync/src/io.rs b/sync/src/io.rs index 53a546e1c..5d4b32464 100644 --- a/sync/src/io.rs +++ b/sync/src/io.rs @@ -41,6 +41,8 @@ pub trait SyncIo { fn is_chain_queue_empty(&self) -> bool { self.chain().queue_info().is_empty() } + /// Check if the session is expired + fn is_expired(&self) -> bool; } /// Wraps `NetworkContext` and the blockchain client @@ -83,6 +85,10 @@ impl<'s, 'h> SyncIo for NetSyncIo<'s, 'h> { fn peer_info(&self, peer_id: PeerId) -> String { self.network.peer_info(peer_id) } + + fn is_expired(&self) -> bool { + self.network.is_expired() + } } diff --git a/sync/src/tests/chain.rs b/sync/src/tests/chain.rs index 09e83e358..7c7d70dde 100644 --- a/sync/src/tests/chain.rs +++ b/sync/src/tests/chain.rs @@ -192,3 +192,13 @@ fn restart_on_broken_chain() { assert_eq!(net.peer(0).chain.chain_info().best_block_number, 5); } + +#[test] +fn high_td_attach() { + let mut net = TestNet::new(2); + net.peer_mut(1).chain.add_blocks(10, EachBlockWith::Uncle); + net.peer_mut(1).chain.corrupt_block_parent(6); + net.sync_steps(20); + + assert_eq!(net.peer(0).chain.chain_info().best_block_number, 5); +} diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 6001769fe..e6e76c472 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -18,7 +18,7 @@ use std::net::{SocketAddr}; use std::collections::{HashMap}; use std::str::{FromStr}; use std::sync::*; -use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; +use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::ops::*; use std::cmp::min; use std::path::{Path, PathBuf}; @@ -249,6 +249,11 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone self.io.message(NetworkIoMessage::Disconnect(peer)); } + /// Sheck if the session is till active. + pub fn is_expired(&self) -> bool { + self.session.as_ref().map(|s| s.lock().unwrap().expired()).unwrap_or(false) + } + /// Register a new IO timer. 'IoHandler::timeout' will be called with the token. pub fn register_timer(&self, token: TimerToken, ms: u64) -> Result<(), UtilError> { self.io.message(NetworkIoMessage::AddTimer { From c340d8a34f2e500a87e79a150026fb18f235cfc9 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 17 Jun 2016 18:26:54 +0200 Subject: [PATCH 048/239] Tests --- ethcore/src/service.rs | 2 +- parity/io_handler.rs | 1 + parity/main.rs | 5 +-- sync/src/chain.rs | 2 +- sync/src/lib.rs | 16 ++++++--- sync/src/tests/helpers.rs | 4 +++ util/src/io/mod.rs | 2 +- util/src/io/service.rs | 65 +++++++++++++++++-------------------- util/src/network/host.rs | 34 +++++++++++-------- util/src/network/mod.rs | 3 +- util/src/network/service.rs | 2 +- util/src/network/tests.rs | 33 ++++++++++++++----- 12 files changed, 99 insertions(+), 70 deletions(-) diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index 6adca7b52..d9040113f 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -156,7 +156,7 @@ mod tests { fn it_can_be_started() { let spec = get_test_spec(); let temp_path = RandomTempPath::new(); - let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_local(), &temp_path.as_path(), Arc::new(Miner::default())); + let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_local(), &temp_path.as_path(), Arc::new(Miner::default()), false); assert!(service.is_ok()); } } diff --git a/parity/io_handler.rs b/parity/io_handler.rs index 569a11716..2460cfec7 100644 --- a/parity/io_handler.rs +++ b/parity/io_handler.rs @@ -55,6 +55,7 @@ impl IoHandler for ClientIoHandler { NetworkIoMessage::User(SyncMessage::StartNetwork) => { info!("Starting network"); self.network.start().unwrap_or_else(|e| warn!("Error starting network: {:?}", e)); + EthSync::register(&*self.network, self.sync.clone()).unwrap_or_else(|e| warn!("Error registering eth protocol handler: {}", e)); }, NetworkIoMessage::User(SyncMessage::StopNetwork) => { info!("Stopping network"); diff --git a/parity/main.rs b/parity/main.rs index 80ea29576..f600d4de0 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -79,7 +79,7 @@ use std::thread::sleep; use std::time::Duration; use rustc_serialize::hex::FromHex; use ctrlc::CtrlC; -use util::{H256, ToPretty, NetworkConfiguration, PayloadInfo, Bytes}; +use util::{H256, ToPretty, NetworkConfiguration, PayloadInfo, Bytes, UtilError}; use util::panics::{MayPanic, ForwardPanic, PanicHandler}; use ethcore::client::{BlockID, BlockChainClient, ClientConfig, get_db_path}; use ethcore::error::{Error, ImportError}; @@ -208,7 +208,8 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) let network_settings = Arc::new(conf.network_settings()); // Sync - let sync = EthSync::register(service.network().deref(), sync_config, client.clone()); + let sync = EthSync::new(sync_config, client.clone()); + EthSync::register(&*service.network(), sync.clone()).unwrap_or_else(|e| die_with_error("Error registering eth protocol handler", UtilError::from(e).into())); let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies { signer_port: conf.signer_port(), diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 7e23601e4..8b6aa9d7c 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -357,7 +357,7 @@ impl ChainSync { trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{})", peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest_hash, peer.genesis); if io.is_expired() { - info!("Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id)); + trace!("Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id)); return Ok(()); } diff --git a/sync/src/lib.rs b/sync/src/lib.rs index ca31ea020..cabc55ace 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -41,11 +41,13 @@ //! use ethcore::miner::Miner; //! //! fn main() { -//! let mut service = NetworkService::start(NetworkConfiguration::new()).unwrap(); +//! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap(); +//! service.start().unwrap(); //! let dir = env::temp_dir(); //! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, Arc::new(Miner::default()), service.io().channel()).unwrap(); //! let miner = Miner::new(false, ethereum::new_frontier()); -//! EthSync::register(&mut service, SyncConfig::default(), client); +//! let sync = EthSync::new(SyncConfig::default(), client); +//! EthSync::register(&mut service, sync); //! } //! ``` @@ -69,7 +71,7 @@ use ethcore::client::Client; use ethcore::service::{SyncMessage, NetSyncMessage}; use io::NetSyncIo; use util::io::IoChannel; -use util::NetworkIoMessage; +use util::{NetworkIoMessage, NetworkError}; use chain::ChainSync; mod chain; @@ -120,17 +122,21 @@ pub use self::chain::{SyncStatus, SyncState}; impl EthSync { /// Creates and register protocol with the network service - pub fn register(service: &NetworkService, config: SyncConfig, chain: Arc) -> Arc { + pub fn new(config: SyncConfig, chain: Arc) -> Arc { let sync = ChainSync::new(config, chain.deref()); let sync = Arc::new(EthSync { chain: chain, sync: RwLock::new(sync), io_channel: RwLock::new(IoChannel::disconnected()), }); - service.register_protocol(sync.clone(), "eth", &[62u8, 63u8]).expect("Error registering eth protocol handler"); sync } + /// Register protocol with the network service + pub fn register(service: &NetworkService, sync: Arc) -> Result<(), NetworkError> { + service.register_protocol(sync.clone(), "eth", &[62u8, 63u8]) + } + /// Stop sync pub fn stop(&mut self, io: &mut NetworkContext) { self.sync.write().unwrap().abort(&mut NetSyncIo::new(io, self.chain.deref())); diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index a9163b52e..6496a43d5 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -43,6 +43,10 @@ impl<'p> SyncIo for TestIo<'p> { fn disconnect_peer(&mut self, _peer_id: PeerId) { } + fn is_expired(&self) -> bool { + false + } + fn respond(&mut self, packet_id: PacketId, data: Vec) -> Result<(), UtilError> { self.queue.push_back(TestPacket { data: data, diff --git a/util/src/io/mod.rs b/util/src/io/mod.rs index 93805a46a..3229c95d5 100644 --- a/util/src/io/mod.rs +++ b/util/src/io/mod.rs @@ -142,7 +142,7 @@ mod tests { #[test] fn test_service_register_handler () { - let mut service = IoService::::start().expect("Error creating network service"); + let service = IoService::::start().expect("Error creating network service"); service.register_handler(Arc::new(MyHandler)).unwrap(); } diff --git a/util/src/io/service.rs b/util/src/io/service.rs index b924bbe44..65be55540 100644 --- a/util/src/io/service.rs +++ b/util/src/io/service.rs @@ -17,7 +17,6 @@ use std::sync::*; use std::thread::{self, JoinHandle}; use std::collections::HashMap; -use std::ops::Deref; use mio::*; use crossbeam::sync::chase_lev; use slab::Slab; @@ -37,13 +36,6 @@ pub type HandlerId = usize; pub const TOKENS_PER_HANDLER: usize = 16384; const MAX_HANDLERS: usize = 8; -fn compare_arcs(a: Arc, b: Arc) -> bool { - let p1 = &*a as *const T; - let p2 = &*b as *const T; - info!("{:p} == {:p} : {}", p1, p2 , p1 == p2); - p1 == p2 -} - /// Messages used to communicate with the event loop from other threads. #[derive(Clone)] pub enum IoMessage where Message: Send + Clone + Sized { @@ -214,30 +206,31 @@ impl Handler for IoManager where Message: Send + Clone + Sync fn ready(&mut self, _event_loop: &mut EventLoop, token: Token, events: EventSet) { let handler_index = token.as_usize() / TOKENS_PER_HANDLER; let token_id = token.as_usize() % TOKENS_PER_HANDLER; - let handler = self.handlers.get(handler_index).unwrap_or_else(|| panic!("Unexpected stream token: {}", token.as_usize())).clone(); - - if events.is_hup() { - self.worker_channel.push(Work { work_type: WorkType::Hup, token: token_id, handler: handler.clone(), handler_id: handler_index }); - } - else { - if events.is_readable() { - self.worker_channel.push(Work { work_type: WorkType::Readable, token: token_id, handler: handler.clone(), handler_id: handler_index }); + if let Some(handler) = self.handlers.get(handler_index) { + if events.is_hup() { + self.worker_channel.push(Work { work_type: WorkType::Hup, token: token_id, handler: handler.clone(), handler_id: handler_index }); } - if events.is_writable() { - self.worker_channel.push(Work { work_type: WorkType::Writable, token: token_id, handler: handler.clone(), handler_id: handler_index }); + else { + if events.is_readable() { + self.worker_channel.push(Work { work_type: WorkType::Readable, token: token_id, handler: handler.clone(), handler_id: handler_index }); + } + if events.is_writable() { + self.worker_channel.push(Work { work_type: WorkType::Writable, token: token_id, handler: handler.clone(), handler_id: handler_index }); + } } + self.work_ready.notify_all(); } - self.work_ready.notify_all(); } fn timeout(&mut self, event_loop: &mut EventLoop, token: Token) { let handler_index = token.as_usize() / TOKENS_PER_HANDLER; let token_id = token.as_usize() % TOKENS_PER_HANDLER; - let handler = self.handlers.get(handler_index).unwrap_or_else(|| panic!("Unexpected stream token: {}", token.as_usize())).clone(); - if let Some(timer) = self.timers.read().unwrap().get(&token.as_usize()) { - event_loop.timeout_ms(token, timer.delay).expect("Error re-registering user timer"); - self.worker_channel.push(Work { work_type: WorkType::Timeout, token: token_id, handler: handler, handler_id: handler_index }); - self.work_ready.notify_all(); + if let Some(handler) = self.handlers.get(handler_index) { + if let Some(timer) = self.timers.read().unwrap().get(&token.as_usize()) { + event_loop.timeout_ms(token, timer.delay).expect("Error re-registering user timer"); + self.worker_channel.push(Work { work_type: WorkType::Timeout, token: token_id, handler: handler.clone(), handler_id: handler_index }); + self.work_ready.notify_all(); + } } } @@ -254,7 +247,6 @@ impl Handler for IoManager where Message: Send + Clone + Sync IoMessage::RemoveHandler { handler_id } => { // TODO: flush event loop self.handlers.remove(handler_id); - info!("{} left", self.handlers.count()); }, IoMessage::AddTimer { handler_id, token, delay } => { let timer_id = token + handler_id * TOKENS_PER_HANDLER; @@ -268,21 +260,24 @@ impl Handler for IoManager where Message: Send + Clone + Sync } }, IoMessage::RegisterStream { handler_id, token } => { - let handler = self.handlers.get(handler_id).expect("Unknown handler id").clone(); - handler.register_stream(token, Token(token + handler_id * TOKENS_PER_HANDLER), event_loop); + if let Some(handler) = self.handlers.get(handler_id) { + handler.register_stream(token, Token(token + handler_id * TOKENS_PER_HANDLER), event_loop); + } }, IoMessage::DeregisterStream { handler_id, token } => { - let handler = self.handlers.get(handler_id).expect("Unknown handler id").clone(); - handler.deregister_stream(token, event_loop); - // unregister a timer associated with the token (if any) - let timer_id = token + handler_id * TOKENS_PER_HANDLER; - if let Some(timer) = self.timers.write().unwrap().remove(&timer_id) { - event_loop.clear_timeout(timer.timeout); + if let Some(handler) = self.handlers.get(handler_id) { + handler.deregister_stream(token, event_loop); + // unregister a timer associated with the token (if any) + let timer_id = token + handler_id * TOKENS_PER_HANDLER; + if let Some(timer) = self.timers.write().unwrap().remove(&timer_id) { + event_loop.clear_timeout(timer.timeout); + } } }, IoMessage::UpdateStreamRegistration { handler_id, token } => { - let handler = self.handlers.get(handler_id).expect("Unknown handler id").clone(); - handler.update_stream(token, Token(token + handler_id * TOKENS_PER_HANDLER), event_loop); + if let Some(handler) = self.handlers.get(handler_id) { + handler.update_stream(token, Token(token + handler_id * TOKENS_PER_HANDLER), event_loop); + } }, IoMessage::UserMessage(data) => { //TODO: better way to iterate the slab diff --git a/util/src/network/host.rs b/util/src/network/host.rs index e6e76c472..161fcfe3f 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -333,6 +333,7 @@ pub struct Host where Message: Send + Sync + Clone { stats: Arc, pinned_nodes: Vec, num_sessions: AtomicUsize, + stopping: AtomicBool, } impl Host where Message: Send + Sync + Clone { @@ -384,6 +385,7 @@ impl Host where Message: Send + Sync + Clone { stats: stats, pinned_nodes: Vec::new(), num_sessions: AtomicUsize::new(0), + stopping: AtomicBool::new(false), }; let boot_nodes = host.info.read().unwrap().config.boot_nodes.clone(); @@ -422,19 +424,18 @@ impl Host where Message: Send + Sync + Clone { } pub fn stop(&self, io: &IoContext>) -> Result<(), UtilError> { + self.stopping.store(true, AtomicOrdering::Release); let mut to_kill = Vec::new(); for e in self.sessions.write().unwrap().iter_mut() { let mut s = e.lock().unwrap(); - if !s.keep_alive(io) { - s.disconnect(io, DisconnectReason::PingTimeout); - to_kill.push(s.token()); - } + s.disconnect(io, DisconnectReason::ClientQuit); + to_kill.push(s.token()); } for p in to_kill { - trace!(target: "network", "Ping timeout: {}", p); + trace!(target: "network", "Disconnecting on shutdown: {}", p); self.kill_connection(p, io, true); } - io.unregister_handler(); + try!(io.unregister_handler()); Ok(()) } @@ -790,13 +791,6 @@ impl Host where Message: Send + Sync + Clone { } } - -impl Drop for Host where Message: Send + Sync + Clone { - fn drop(&mut self) { - info!("Dropping host"); - } -} - impl IoHandler> for Host where Message: Send + Sync + Clone + 'static { /// Initialize networking fn initialize(&self, io: &IoContext>) { @@ -814,6 +808,9 @@ impl IoHandler> for Host where Messa } fn stream_readable(&self, io: &IoContext>, stream: StreamToken) { + if self.stopping.load(AtomicOrdering::Acquire) { + return; + } match stream { FIRST_SESSION ... LAST_SESSION => self.session_readable(stream, io), DISCOVERY => { @@ -829,6 +826,9 @@ impl IoHandler> for Host where Messa } fn stream_writable(&self, io: &IoContext>, stream: StreamToken) { + if self.stopping.load(AtomicOrdering::Acquire) { + return; + } match stream { FIRST_SESSION ... LAST_SESSION => self.session_writable(stream, io), DISCOVERY => { @@ -840,6 +840,9 @@ impl IoHandler> for Host where Messa } fn timeout(&self, io: &IoContext>, token: TimerToken) { + if self.stopping.load(AtomicOrdering::Acquire) { + return; + } match token { IDLE => self.maintain_network(io), INIT_PUBLIC => self.init_public_interface(io).unwrap_or_else(|e| @@ -870,6 +873,9 @@ impl IoHandler> for Host where Messa } fn message(&self, io: &IoContext>, message: &NetworkIoMessage) { + if self.stopping.load(AtomicOrdering::Acquire) { + return; + } match *message { NetworkIoMessage::AddHandler { ref handler, @@ -1031,6 +1037,6 @@ fn host_client_url() { let mut config = NetworkConfiguration::new(); let key = h256_from_hex("6f7b0d801bc7b5ce7bbd930b84fd0369b3eb25d09be58d64ba811091046f3aa2"); config.use_secret = Some(key); - let host: Host = Host::new(config).unwrap(); + let host: Host = Host::new(config, Arc::new(NetworkStats::new())).unwrap(); assert!(host.local_url().starts_with("enode://101b3ef5a4ea7a1c7928e24c4c75fd053c235d7b80c22ae5c03d145d0ac7396e2a4ffff9adee3133a7b05044a5cee08115fd65145e5165d646bde371010d803c@")); } diff --git a/util/src/network/mod.rs b/util/src/network/mod.rs index 29f3d166c..d074e6631 100644 --- a/util/src/network/mod.rs +++ b/util/src/network/mod.rs @@ -56,8 +56,9 @@ //! } //! //! fn main () { -//! let mut service = NetworkService::::start(NetworkConfiguration::new_local()).expect("Error creating network service"); +//! let mut service = NetworkService::::new(NetworkConfiguration::new_local()).expect("Error creating network service"); //! service.register_protocol(Arc::new(MyHandler), "myproto", &[1u8]); +//! service.start().expect("Error starting service"); //! //! // Wait for quit condition //! // ... diff --git a/util/src/network/service.rs b/util/src/network/service.rs index 406126425..36f05d283 100644 --- a/util/src/network/service.rs +++ b/util/src/network/service.rs @@ -107,7 +107,7 @@ impl NetworkService where Message: Send + Sync + Clone + 'stat if let Some(ref host) = *host { info!("Unregistering handler"); let io = IoContext::new(self.io_service.channel(), 0); //TODO: take token id from host - host.stop(&io); + try!(host.stop(&io)); } *host = None; Ok(()) diff --git a/util/src/network/tests.rs b/util/src/network/tests.rs index b43da9320..861edc144 100644 --- a/util/src/network/tests.rs +++ b/util/src/network/tests.rs @@ -97,7 +97,8 @@ impl NetworkProtocolHandler for TestProtocol { #[test] fn net_service() { - let mut service = NetworkService::::start(NetworkConfiguration::new_local()).expect("Error creating network service"); + let service = NetworkService::::new(NetworkConfiguration::new_local()).expect("Error creating network service"); + service.start().unwrap(); service.register_protocol(Arc::new(TestProtocol::new(false)), "myproto", &[1u8]).unwrap(); } @@ -108,12 +109,14 @@ fn net_connect() { let mut config1 = NetworkConfiguration::new_local(); config1.use_secret = Some(key1.secret().clone()); config1.boot_nodes = vec![ ]; - let mut service1 = NetworkService::::start(config1).unwrap(); + let mut service1 = NetworkService::::new(config1).unwrap(); + service1.start().unwrap(); let handler1 = TestProtocol::register(&mut service1, false); let mut config2 = NetworkConfiguration::new_local(); - info!("net_connect: local URL: {}", service1.local_url()); - config2.boot_nodes = vec![ service1.local_url() ]; - let mut service2 = NetworkService::::start(config2).unwrap(); + info!("net_connect: local URL: {}", service1.local_url().unwrap()); + config2.boot_nodes = vec![ service1.local_url().unwrap() ]; + let mut service2 = NetworkService::::new(config2).unwrap(); + service2.start().unwrap(); let handler2 = TestProtocol::register(&mut service2, false); while !handler1.got_packet() && !handler2.got_packet() && (service1.stats().sessions() == 0 || service2.stats().sessions() == 0) { thread::sleep(Duration::from_millis(50)); @@ -122,17 +125,28 @@ fn net_connect() { assert!(service2.stats().sessions() >= 1); } +#[test] +fn net_start_stop() { + let config = NetworkConfiguration::new_local(); + let service = NetworkService::::new(config).unwrap(); + service.start().unwrap(); + service.stop().unwrap(); + service.start().unwrap(); +} + #[test] fn net_disconnect() { let key1 = KeyPair::create().unwrap(); let mut config1 = NetworkConfiguration::new_local(); config1.use_secret = Some(key1.secret().clone()); config1.boot_nodes = vec![ ]; - let mut service1 = NetworkService::::start(config1).unwrap(); + let mut service1 = NetworkService::::new(config1).unwrap(); + service1.start().unwrap(); let handler1 = TestProtocol::register(&mut service1, false); let mut config2 = NetworkConfiguration::new_local(); - config2.boot_nodes = vec![ service1.local_url() ]; - let mut service2 = NetworkService::::start(config2).unwrap(); + config2.boot_nodes = vec![ service1.local_url().unwrap() ]; + let mut service2 = NetworkService::::new(config2).unwrap(); + service2.start().unwrap(); let handler2 = TestProtocol::register(&mut service2, true); while !(handler1.got_disconnect() && handler2.got_disconnect()) { thread::sleep(Duration::from_millis(50)); @@ -144,7 +158,8 @@ fn net_disconnect() { #[test] fn net_timeout() { let config = NetworkConfiguration::new_local(); - let mut service = NetworkService::::start(config).unwrap(); + let mut service = NetworkService::::new(config).unwrap(); + service.start().unwrap(); let handler = TestProtocol::register(&mut service, false); while !handler.got_timeout() { thread::sleep(Duration::from_millis(50)); From fc60ed92e64aacfb9d56cc99da4706452645f9c6 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 17 Jun 2016 18:28:19 +0200 Subject: [PATCH 049/239] Removed info --- util/src/network/service.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/util/src/network/service.rs b/util/src/network/service.rs index 36f05d283..e8db354d4 100644 --- a/util/src/network/service.rs +++ b/util/src/network/service.rs @@ -105,7 +105,6 @@ impl NetworkService where Message: Send + Sync + Clone + 'stat pub fn stop(&self) -> Result<(), UtilError> { let mut host = self.host.write().unwrap(); if let Some(ref host) = *host { - info!("Unregistering handler"); let io = IoContext::new(self.io_service.channel(), 0); //TODO: take token id from host try!(host.stop(&io)); } From 16412eb0c96eb0abd4b4d73d2f68958f2fbefb1d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 17 Jun 2016 22:15:18 +0200 Subject: [PATCH 050/239] DAO Rescue soft fork (#1309) * DAO Rescue soft fork * Address minor issues. * Fix tests. --- ethcore/src/error.rs | 3 +++ ethcore/src/ethereum/ethash.rs | 5 ++++- ethcore/src/evm/schedule.rs | 3 +++ ethcore/src/state.rs | 18 ++++++++++++++++++ rpc/src/v1/impls/mod.rs | 1 + 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 98aec917a..9be800e13 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -58,6 +58,8 @@ pub enum TransactionError { }, /// Transaction's gas limit (aka gas) is invalid. InvalidGasLimit(OutOfBounds), + /// Transaction is invalid for some other reason. + DAORescue, } impl fmt::Display for TransactionError { @@ -76,6 +78,7 @@ impl fmt::Display for TransactionError { GasLimitExceeded { limit, got } => format!("Gas limit exceeded. Limit={}, Given={}", limit, got), InvalidGasLimit(ref err) => format!("Invalid gas limit. {}", err), + DAORescue => "Transaction is invalid due to the DAO rescue.".into(), }; f.write_fmt(format_args!("Transaction error ({})", msg)) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index c8b8d7b31..d89499872 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -101,7 +101,10 @@ impl Engine for Ethash { if env_info.number < self.ethash_params.frontier_compatibility_mode_limit { Schedule::new_frontier() } else { - Schedule::new_homestead() + let mut s = Schedule::new_homestead(); + // TODO: make dependent on gaslimit > 4000000 of block 1760000. + s.block_dao_transactions = env_info.number >= 1760000; + s } } diff --git a/ethcore/src/evm/schedule.rs b/ethcore/src/evm/schedule.rs index f82157239..59f30e7d3 100644 --- a/ethcore/src/evm/schedule.rs +++ b/ethcore/src/evm/schedule.rs @@ -80,6 +80,8 @@ pub struct Schedule { pub tx_data_non_zero_gas: usize, /// Gas price for copying memory pub copy_gas: usize, + /// DAO Rescue softfork block + pub block_dao_transactions: bool, } impl Schedule { @@ -126,6 +128,7 @@ impl Schedule { tx_data_zero_gas: 4, tx_data_non_zero_gas: 68, copy_gas: 3, + block_dao_transactions: false, } } } diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index 204cea618..dc9ca582c 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -222,6 +222,24 @@ impl State { let options = TransactOptions { tracing: tracing, vm_tracing: false, check_nonce: true }; let e = try!(Executive::new(self, env_info, engine, vm_factory).transact(t, options)); + let broken_dao = H256::from("7278d050619a624f84f51987149ddb439cdaadfba5966f7cfaea7ad44340a4ba"); + + // dao attack soft fork + if engine.schedule(&env_info).block_dao_transactions { + // collect all the addresses which have changed. + let addresses = self.cache.borrow().iter().map(|(addr, _)| addr.clone()).collect::>(); + + for a in addresses.iter() { + if self.code(a).map(|c| c.sha3() == broken_dao).unwrap_or(false) { + // Figure out if the balance has been reduced. + let maybe_original = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR).get(&a).map(Account::from_rlp); + if maybe_original.map(|original| *original.balance() > self.balance(a)).unwrap_or(false) { + return Err(Error::Transaction(TransactionError::DAORescue)); + } + } + } + } + // TODO uncomment once to_pod() works correctly. // trace!("Applied transaction. Diff:\n{}\n", state_diff::diff_pod(&old, &self.to_pod())); self.commit(); diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 8ea02b8b3..f69fa25ce 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -134,6 +134,7 @@ fn transaction_error(error: EthcoreError) -> Error { format!("Transaction cost exceeds current gas limit. Limit: {}, got: {}. Try decreasing supplied gas.", limit, got) }, InvalidGasLimit(_) => "Supplied gas is beyond limit.".into(), + DAORescue => "Transaction removes funds from a DAO.".into(), }; Error { code: ErrorCode::ServerError(error_codes::TRANSACTION_ERROR), From 3f77f7ce1f7a48069b63015259022cb9989d7072 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 18 Jun 2016 09:50:05 +0200 Subject: [PATCH 051/239] Removed RPC methods --- rpc/src/v1/traits/net.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/rpc/src/v1/traits/net.rs b/rpc/src/v1/traits/net.rs index b65f53491..2df8c8f9c 100644 --- a/rpc/src/v1/traits/net.rs +++ b/rpc/src/v1/traits/net.rs @@ -42,8 +42,6 @@ pub trait Net: Sized + Send + Sync + 'static { delegate.add_method("net_version", Net::version); delegate.add_method("net_peerCount", Net::peer_count); delegate.add_method("net_listening", Net::is_listening); - delegate.add_method("net_start", Net::start_network); - delegate.add_method("net_stop", Net::stop_network); delegate } } From 29e286572c772ff9f946b427909e7d99001d98d2 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Wed, 15 Jun 2016 19:01:58 +0200 Subject: [PATCH 052/239] Fixed loosing peers on incoming connections. (#1293) * Deactivate peer if it has no new data * Fixed node table timer registration * Fixed handshake timeout expiration * Extra trace * Fixed session count calculation * Only deactivate incapable peers in ChainHead state * Timer registration is not needed --- sync/src/chain.rs | 8 +++++++- util/src/network/handshake.rs | 5 +++-- util/src/network/host.rs | 7 +++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 90e18d8e8..ae58c4513 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -405,6 +405,7 @@ impl ChainSync { } if item_count == 0 && (self.state == SyncState::Blocks || self.state == SyncState::NewBlocks) { self.deactivate_peer(io, peer_id); //TODO: is this too harsh? + self.continue_sync(io); return Ok(()); } @@ -452,7 +453,12 @@ impl ChainSync { // Disable the peer for this syncing round if it gives invalid chain if !valid_response { - trace!(target: "sync", "{} Disabled for invalid headers response", peer_id); + trace!(target: "sync", "{} Deactivated for invalid headers response", peer_id); + self.deactivate_peer(io, peer_id); + } + if headers.is_empty() { + // Peer does not have any new subchain heads, deactivate it nd try with another + trace!(target: "sync", "{} Deactivated for no data", peer_id); self.deactivate_peer(io, peer_id); } match self.state { diff --git a/util/src/network/handshake.rs b/util/src/network/handshake.rs index 90e3bc67d..179309a6f 100644 --- a/util/src/network/handshake.rs +++ b/util/src/network/handshake.rs @@ -128,7 +128,6 @@ impl Handshake { /// Readable IO handler. Drives the state change. pub fn readable(&mut self, io: &IoContext, host: &HostInfo) -> Result<(), UtilError> where Message: Send + Clone { if !self.expired() { - io.clear_timer(self.connection.token).ok(); match self.state { HandshakeState::New => {} HandshakeState::ReadingAuth => { @@ -151,7 +150,9 @@ impl Handshake { try!(self.read_ack_eip8(host.secret(), &data)); }; }, - HandshakeState::StartSession => {}, + HandshakeState::StartSession => { + io.clear_timer(self.connection.token).ok(); + }, } } Ok(()) diff --git a/util/src/network/host.rs b/util/src/network/host.rs index b37538c9c..de6908200 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -523,11 +523,13 @@ impl Host where Message: Send + Sync + Clone { } let nodes = if pin { self.pinned_nodes.clone() } else { self.nodes.read().unwrap().nodes() }; + let mut started: usize = 0; for id in nodes.iter().filter(|ref id| !self.have_session(id) && !self.connecting_to(id)) .take(min(MAX_HANDSHAKES_PER_ROUND, handshake_limit - handshake_count)) { self.connect_peer(&id, io); + started += 1; } - debug!(target: "network", "Connecting peers: {} sessions, {} pending", self.session_count(), self.handshake_count()); + debug!(target: "network", "Connecting peers: {} sessions, {} pending, {} started", self.session_count(), self.handshake_count(), started); } #[cfg_attr(feature="dev", allow(single_match))] @@ -650,6 +652,7 @@ impl Host where Message: Send + Sync + Clone { break; }, Ok(SessionData::Ready) => { + self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); if !s.info.originated { let session_count = self.session_count(); let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; @@ -667,7 +670,6 @@ impl Host where Message: Send + Sync + Clone { } } } - self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); for (p, _) in self.handlers.read().unwrap().iter() { if s.have_capability(p) { ready_data.push(p); @@ -828,6 +830,7 @@ impl IoHandler> for Host where Messa io.update_registration(DISCOVERY).expect("Error updating discovery registration"); }, NODE_TABLE => { + trace!(target: "network", "Refreshing node table"); self.nodes.write().unwrap().clear_useless(); }, _ => match self.timers.read().unwrap().get(&token).cloned() { From 55fec2dcc3934273693ac888f3fbb7194c4b200c Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 15 Jun 2016 20:52:00 +0300 Subject: [PATCH 053/239] x64 path --- nsis/installer.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nsis/installer.nsi b/nsis/installer.nsi index 2c17a2543..f352e0b87 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -13,7 +13,7 @@ RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on) -InstallDir "$PROGRAMFILES\${COMPANYNAME}\${APPNAME}" +InstallDir "$PROGRAMFILES64\${COMPANYNAME}\${APPNAME}" LicenseData "..\LICENSE" Name "${COMPANYNAME} ${APPNAME}" From 232274546b2886305cc857ada7bd3512f5e5e433 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 15 Jun 2016 21:40:41 +0300 Subject: [PATCH 054/239] firewall rules --- nsis/installer.nsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/nsis/installer.nsi b/nsis/installer.nsi index f352e0b87..10143306a 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -56,6 +56,18 @@ section "install" createDirectory "$SMPROGRAMS\${COMPANYNAME}" createShortCut "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" "$INSTDIR\parity.exe" "ui" "$INSTDIR\logo.ico" + # Firewall remove rules if exists + SimpleFC::AdvRemoveRule "Parity incoming peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Parity outgoing peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Parity web queries (TCP:80)" + SimpleFC::AdvRemoveRule "Parity UDP discovery (UDP:30303)" + + # Firewall exception rules + SimpleFC::AdvAddRule "Parity incoming peers (TCP:30303)" "" 6 1 1 2147483647 1 "$INSTDIR\parity.exe" "" "" "Parity" 30303 "" "" "" + SimpleFC::AdvAddRule "Parity outgoing peers (TCP:30303)" "" 6 2 1 2147483647 1 "$INSTDIR\parity.exe" "" "" "Parity" "" 30303 "" "" + SimpleFC::AdvAddRule "Parity web queries (TCP:80)" "" 6 2 1 2147483647 1 "$INSTDIR\parity.exe" "" "" "Parity" "" 80 "" "" + SimpleFC::AdvAddRule "Parity UDP discovery (UDP:30303)" "" 17 2 1 2147483647 1 "$INSTDIR\parity.exe" "" "" "Parity" "" 30303 "" "" + # Registry information for add/remove programs WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayName" "${COMPANYNAME} - ${APPNAME} - ${DESCRIPTION}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" @@ -106,6 +118,12 @@ section "uninstall" # Try to remove the install directory - this will only happen if it is empty rmDir $INSTDIR + # Firewall exception rules + SimpleFC::AdvRemoveRule "Parity incoming peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Parity outgoing peers (TCP:30303)" + SimpleFC::AdvRemoveRule "Parity web queries (TCP:80)" + SimpleFC::AdvRemoveRule "Parity UDP discovery (UDP:30303)" + # Remove uninstaller information from the registry DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" From da058d0e86d47ddabe2f5fcc7dfe44a7c67ad4ed Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 15 Jun 2016 21:31:19 +0200 Subject: [PATCH 055/239] Fix read-ahead bug. Re-ahead 8 bytes rather than 3 to ensure large blocks import fine. --- parity/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index 1467eaa50..e1890ff0f 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -398,7 +398,7 @@ fn execute_import(conf: Configuration) { Box::new(::std::io::stdin()) }; - let mut first_bytes: Bytes = vec![0; 3]; + let mut first_bytes: Bytes = vec![0; 8]; let mut first_read = 0; let format = match conf.args.flag_format { @@ -438,13 +438,13 @@ fn execute_import(conf: Configuration) { match format { DataFormat::Binary => { loop { - let mut bytes: Bytes = if first_read > 0 {first_bytes.clone()} else {vec![0; 3]}; + let mut bytes: Bytes = if first_read > 0 {first_bytes.clone()} else {vec![0; 8]}; let n = if first_read > 0 {first_read} else {instream.read(&mut(bytes[..])).unwrap_or_else(|_| die!("Error reading from the file/stream."))}; if n == 0 { break; } first_read = 0; let s = PayloadInfo::from(&(bytes[..])).unwrap_or_else(|e| die!("Invalid RLP in the file/stream: {:?}", e)).total(); bytes.resize(s, 0); - instream.read_exact(&mut(bytes[3..])).unwrap_or_else(|_| die!("Error reading from the file/stream.")); + instream.read_exact(&mut(bytes[8..])).unwrap_or_else(|_| die!("Error reading from the file/stream.")); do_import(bytes); } } From d6701065eaa15b3de2c3cd01ae1e8642ec5281a7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 15 Jun 2016 23:12:43 +0200 Subject: [PATCH 056/239] Refactor to use a const. --- parity/main.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/parity/main.rs b/parity/main.rs index e1890ff0f..8b99f463b 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -398,7 +398,9 @@ fn execute_import(conf: Configuration) { Box::new(::std::io::stdin()) }; - let mut first_bytes: Bytes = vec![0; 8]; + const READAHEAD_BYTES: usize = 8; + + let mut first_bytes: Bytes = vec![0; READAHEAD_BYTES]; let mut first_read = 0; let format = match conf.args.flag_format { @@ -438,13 +440,13 @@ fn execute_import(conf: Configuration) { match format { DataFormat::Binary => { loop { - let mut bytes: Bytes = if first_read > 0 {first_bytes.clone()} else {vec![0; 8]}; + let mut bytes: Bytes = if first_read > 0 {first_bytes.clone()} else {vec![0; READAHEAD_BYTES]}; let n = if first_read > 0 {first_read} else {instream.read(&mut(bytes[..])).unwrap_or_else(|_| die!("Error reading from the file/stream."))}; if n == 0 { break; } first_read = 0; let s = PayloadInfo::from(&(bytes[..])).unwrap_or_else(|e| die!("Invalid RLP in the file/stream: {:?}", e)).total(); bytes.resize(s, 0); - instream.read_exact(&mut(bytes[8..])).unwrap_or_else(|_| die!("Error reading from the file/stream.")); + instream.read_exact(&mut(bytes[READAHEAD_BYTES..])).unwrap_or_else(|_| die!("Error reading from the file/stream.")); do_import(bytes); } } From 6026dd3657e72d309a646807f4e4022da29130bc Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Thu, 16 Jun 2016 11:21:35 +0200 Subject: [PATCH 057/239] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index acd873b74..e942943ec 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do - Windows Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the rustup installer from - https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe and use the following command to install and set up the msvc toolchain: + https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe, start "VS2015 x64 Native Tools Command Prompt", and use the following command to install and set up the msvc toolchain: ``` $ rustup default stable-x86_64-pc-windows-msvc ``` @@ -73,4 +73,4 @@ To get started, just run $ ./target/release/parity ``` -and parity will begin syncing the Ethereum blockchain. \ No newline at end of file +and parity will begin syncing the Ethereum blockchain. From 335bce85e86b0b966e02b47acf0b204d7437dd5a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 16 Jun 2016 12:44:08 +0200 Subject: [PATCH 058/239] Gas price statistics. (#1291) * Gas price statistics. Affects eth_gasPrice. Added ethcore_gasPriceStatistics. Closes #1265 * Fix a bug in eth_gasPrice * Fix tests. * Revert minor alteration. * Tests for gas_price_statistics. - Tests; - Additional infrastructure for generating test blocks with transactions. --- ethcore/res/null.json | 33 +++++++++++ ethcore/src/client/client.rs | 3 +- ethcore/src/client/mod.rs | 28 +++++++++ ethcore/src/spec/spec.rs | 5 ++ ethcore/src/tests/client.rs | 12 ++++ ethcore/src/tests/helpers.rs | 75 +++++++++++++++++++----- ethcore/src/verification/verification.rs | 2 +- parity/rpc_apis.rs | 2 +- rpc/src/v1/impls/eth.rs | 14 ++++- rpc/src/v1/impls/ethcore.rs | 37 +++++++++--- rpc/src/v1/tests/mocked/ethcore.rs | 62 +++++++++++++------- rpc/src/v1/traits/ethcore.rs | 4 ++ 12 files changed, 225 insertions(+), 52 deletions(-) create mode 100644 ethcore/res/null.json diff --git a/ethcore/res/null.json b/ethcore/res/null.json new file mode 100644 index 000000000..b9b2b1260 --- /dev/null +++ b/ethcore/res/null.json @@ -0,0 +1,33 @@ +{ + "name": "Morden", + "engine": { + "Null": null + }, + "params": { + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x2" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x00006d6f7264656e", + "mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x2fefd8" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "0", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "0", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "0", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "0", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "0" } + } +} diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 75a60204f..85a3d693d 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -770,8 +770,7 @@ impl MiningBlockChainClient for Client where V: Verifier { author, gas_floor_target, extra_data, - ).expect("OpenBlock::new only fails if parent state root invalid. State root of best block's header is never invalid. \ - Therefore creating an OpenBlock with the best block's header will not fail."); + ).expect("OpenBlock::new only fails if parent state root invalid; state root of best block's header is never invalid; qed"); // Add uncles self.chain diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index dbd09ea4a..3fec68815 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -34,6 +34,7 @@ pub use env_info::{LastHashes, EnvInfo}; use util::bytes::Bytes; use util::hash::{Address, H256, H2048}; use util::numbers::U256; +use util::Itertools; use blockchain::TreeRoute; use block_queue::BlockQueueInfo; use block::OpenBlock; @@ -41,6 +42,7 @@ use header::{BlockNumber, Header}; use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; +use views::BlockView; use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; use trace::LocalizedTrace; @@ -193,6 +195,32 @@ pub trait BlockChainClient : Sync + Send { /// list all transactions fn all_transactions(&self) -> Vec; + + /// Get the gas price distribution. + fn gas_price_statistics(&self, sample_size: usize, distribution_size: usize) -> Result, ()> { + let mut h = self.chain_info().best_block_hash; + let mut corpus = Vec::new(); + for _ in 0..sample_size { + let block_bytes = self.block(BlockID::Hash(h)).expect("h is either the best_block_hash or an ancestor; qed"); + let block = BlockView::new(&block_bytes); + let header = block.header_view(); + if header.number() == 0 { + break; + } + block.transaction_views().iter().foreach(|t| corpus.push(t.gas_price())); + h = header.parent_hash().clone(); + } + corpus.sort(); + let n = corpus.len(); + if n > 0 { + Ok((0..(distribution_size + 1)) + .map(|i| corpus[i * (n - 1) / distribution_size]) + .collect::>() + ) + } else { + Err(()) + } + } } /// Extended client interface used for mining diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 743f1bd9b..02b311b24 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -244,6 +244,11 @@ impl Spec { pub fn new_test() -> Spec { Spec::load(include_bytes!("../../res/null_morden.json")) } + + /// Create a new Spec which is a NullEngine consensus with a premine of address whose secret is sha3(''). + pub fn new_null() -> Spec { + Spec::load(include_bytes!("../../res/null.json")) + } } #[cfg(test)] diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index d87b41b62..a5459035e 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -112,6 +112,18 @@ fn can_collect_garbage() { assert!(client.blockchain_cache_info().blocks < 100 * 1024); } +#[test] +fn can_generate_gas_price_statistics() { + let client_result = generate_dummy_client_with_data(16, 1, &vec_into![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + let client = client_result.reference(); + let s = client.gas_price_statistics(8, 8).unwrap(); + assert_eq!(s, vec_into![8, 8, 9, 10, 11, 12, 13, 14, 15]); + let s = client.gas_price_statistics(16, 8).unwrap(); + assert_eq!(s, vec_into![0, 1, 3, 5, 7, 9, 11, 13, 15]); + let s = client.gas_price_statistics(32, 8).unwrap(); + assert_eq!(s, vec_into![0, 1, 3, 5, 7, 9, 11, 13, 15]); +} + #[test] fn can_handle_long_fork() { let client_result = generate_dummy_client(1200); diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 3b27ef4a4..151d53bba 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -17,6 +17,7 @@ use client::{BlockChainClient, Client, ClientConfig}; use common::*; use spec::*; +use block::{OpenBlock}; use blockchain::{BlockChain, Config as BlockChainConfig}; use state::*; use evm::Schedule; @@ -85,6 +86,7 @@ impl Engine for TestEngine { } } +// TODO: move everything over to get_null_spec. pub fn get_test_spec() -> Spec { Spec::new_test() } @@ -126,7 +128,7 @@ fn create_unverifiable_block(order: u32, parent_hash: H256) -> Bytes { create_test_block(&create_unverifiable_block_header(order, parent_hash)) } -pub fn create_test_block_with_data(header: &Header, transactions: &[&SignedTransaction], uncles: &[Header]) -> Bytes { +pub fn create_test_block_with_data(header: &Header, transactions: &[SignedTransaction], uncles: &[Header]) -> Bytes { let mut rlp = RlpStream::new_list(3); rlp.append(header); rlp.begin_list(transactions.len()); @@ -138,33 +140,74 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[&SignedTrans } pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult> { + generate_dummy_client_with_spec_and_data(Spec::new_test, block_number, 0, &(vec![])) +} + +pub fn generate_dummy_client_with_data(block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> GuardedTempResult> { + generate_dummy_client_with_spec_and_data(Spec::new_null, block_number, txs_per_block, tx_gas_prices) +} + +pub fn generate_dummy_client_with_spec_and_data(get_test_spec: F, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> GuardedTempResult> where F: Fn()->Spec { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let test_spec = get_test_spec(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); let test_engine = &test_spec.engine; - let state_root = test_spec.genesis_header().state_root; - let mut rolling_hash = test_spec.genesis_header().hash(); - let mut rolling_block_number = 1; + + let mut db_result = get_temp_journal_db(); + let mut db = db_result.take(); + test_spec.ensure_db_good(db.as_hashdb_mut()); + let vm_factory = Default::default(); + let genesis_header = test_spec.genesis_header(); + let mut rolling_timestamp = 40; + let mut last_hashes = vec![]; + let mut last_header = genesis_header.clone(); + let kp = KeyPair::from_secret("".sha3()).unwrap() ; + let author = kp.address(); + + let mut n = 0; for _ in 0..block_number { - let mut header = Header::new(); + last_hashes.push(last_header.hash()); - header.gas_limit = test_engine.params().min_gas_limit; - header.difficulty = U256::from(0x20000); - header.timestamp = rolling_timestamp; - header.number = rolling_block_number; - header.parent_hash = rolling_hash; - header.state_root = state_root.clone(); + // forge block. + let mut b = OpenBlock::new( + test_engine.deref(), + &vm_factory, + false, + db, + &last_header, + last_hashes.clone(), + author.clone(), + 3141562.into(), + vec![] + ).unwrap(); + b.set_difficulty(U256::from(0x20000)); + rolling_timestamp += 10; + b.set_timestamp(rolling_timestamp); - rolling_hash = header.hash(); - rolling_block_number = rolling_block_number + 1; - rolling_timestamp = rolling_timestamp + 10; + // first block we don't have any balance, so can't send any transactions. + for _ in 0..txs_per_block { + b.push_transaction(Transaction { + nonce: n.into(), + gas_price: tx_gas_prices[n % tx_gas_prices.len()], + gas: 100000.into(), + action: Action::Create, + data: vec![], + value: U256::zero(), + }.sign(kp.secret()), None).unwrap(); + n += 1; + } - if let Err(e) = client.import_block(create_test_block(&header)) { + let b = b.close_and_lock().seal(test_engine.deref(), vec![]).unwrap(); + + if let Err(e) = client.import_block(b.rlp_bytes()) { panic!("error importing block which is valid by definition: {:?}", e); } + + last_header = BlockView::new(&b.rlp_bytes()).header(); + db = b.drain(); } client.flush_queue(); client.import_verified_blocks(&IoChannel::disconnected()); diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 6511a8ddd..c6b75416b 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -361,7 +361,7 @@ mod tests { nonce: U256::from(2) }.sign(&keypair.secret()); - let good_transactions = [ &tr1, &tr2 ]; + let good_transactions = [ tr1.clone(), tr2.clone() ]; let diff_inc = U256::from(0x40); diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index d9085fc31..f4b2d067f 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -159,7 +159,7 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_queue).to_delegate()); }, Api::Ethcore => { - server.add_delegate(EthcoreClient::new(&deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate()) + server.add_delegate(EthcoreClient::new(&deps.client, &deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate()) }, Api::EthcoreSet => { server.add_delegate(EthcoreSetClient::new(&deps.miner).to_delegate()) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 2d337e73c..80245708f 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -153,15 +153,23 @@ impl EthClient where } } + fn default_gas_price(&self) -> Result { + let miner = take_weak!(self.miner); + Ok(take_weak!(self.client) + .gas_price_statistics(100, 8) + .map(|x| x[4]) + .unwrap_or_else(|_| miner.sensible_gas_price()) + ) + } + fn sign_call(&self, request: CallRequest) -> Result { let client = take_weak!(self.client); - let miner = take_weak!(self.miner); let from = request.from.unwrap_or(Address::zero()); Ok(EthTransaction { nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)), action: request.to.map_or(Action::Create, Action::Call), gas: request.gas.unwrap_or(U256::from(50_000_000)), - gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), + gas_price: request.gas_price.unwrap_or_else(|| self.default_gas_price().expect("call only fails if client or miner are unavailable; client and miner are both available to be here; qed")), value: request.value.unwrap_or_else(U256::zero), data: request.data.map_or_else(Vec::new, |d| d.to_vec()) }.fake_sign(from)) @@ -293,7 +301,7 @@ impl Eth for EthClient where fn gas_price(&self, params: Params) -> Result { match params { - Params::None => to_value(&take_weak!(self.miner).sensible_gas_price()), + Params::None => to_value(&try!(self.default_gas_price())), _ => Err(Error::invalid_params()) } } diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/ethcore.rs index b3fe894c6..e77f46f5d 100644 --- a/rpc/src/v1/impls/ethcore.rs +++ b/rpc/src/v1/impls/ethcore.rs @@ -15,30 +15,34 @@ // along with Parity. If not, see . //! Ethcore-specific rpc implementation. -use util::RotatingLogger; +use util::{RotatingLogger}; use util::network_settings::NetworkSettings; use util::misc::version_data; use std::sync::{Arc, Weak}; use std::ops::Deref; -use std::collections::BTreeMap; +use std::collections::{BTreeMap}; +use ethcore::client::{MiningBlockChainClient}; use jsonrpc_core::*; use ethcore::miner::MinerService; use v1::traits::Ethcore; use v1::types::{Bytes}; /// Ethcore implementation. -pub struct EthcoreClient where +pub struct EthcoreClient where + C: MiningBlockChainClient, M: MinerService { + client: Weak, miner: Weak, logger: Arc, settings: Arc, } -impl EthcoreClient where M: MinerService { +impl EthcoreClient where C: MiningBlockChainClient, M: MinerService { /// Creates new `EthcoreClient`. - pub fn new(miner: &Arc, logger: Arc, settings: Arc) -> Self { + pub fn new(client: &Arc, miner: &Arc, logger: Arc, settings: Arc) -> Self { EthcoreClient { + client: Arc::downgrade(client), miner: Arc::downgrade(miner), logger: logger, settings: settings, @@ -46,7 +50,7 @@ impl EthcoreClient where M: MinerService { } } -impl Ethcore for EthcoreClient where M: MinerService + 'static { +impl Ethcore for EthcoreClient where M: MinerService + 'static, C: MiningBlockChainClient + 'static { fn transactions_limit(&self, _: Params) -> Result { to_value(&take_weak!(self.miner).transactions_limit()) @@ -97,8 +101,23 @@ impl Ethcore for EthcoreClient where M: MinerService + 'static { Ok(Value::Object(map)) } - fn default_extra_data(&self, _params: Params) -> Result { - let version = version_data(); - to_value(&Bytes::new(version)) + fn default_extra_data(&self, params: Params) -> Result { + match params { + Params::None => to_value(&Bytes::new(version_data())), + _ => Err(Error::invalid_params()), + } + } + + fn gas_price_statistics(&self, params: Params) -> Result { + match params { + Params::None => match take_weak!(self.client).gas_price_statistics(100, 8) { + Ok(stats) => to_value(&stats + .iter() + .map(|x| to_value(&x).expect("x must be U256; qed")) + .collect::>()), + _ => Err(Error::internal_error()), + }, + _ => Err(Error::invalid_params()), + } } } diff --git a/rpc/src/v1/tests/mocked/ethcore.rs b/rpc/src/v1/tests/mocked/ethcore.rs index 90103adef..68c33ecce 100644 --- a/rpc/src/v1/tests/mocked/ethcore.rs +++ b/rpc/src/v1/tests/mocked/ethcore.rs @@ -20,6 +20,7 @@ use jsonrpc_core::IoHandler; use v1::{Ethcore, EthcoreClient, EthcoreSet, EthcoreSetClient}; use ethcore::miner::MinerService; use v1::tests::helpers::TestMinerService; +use ethcore::client::{TestBlockChainClient}; use util::numbers::*; use rustc_serialize::hex::FromHex; use util::log::RotatingLogger; @@ -29,6 +30,10 @@ fn miner_service() -> Arc { Arc::new(TestMinerService::default()) } +fn client_service() -> Arc { + Arc::new(TestBlockChainClient::default()) +} + fn logger() -> Arc { Arc::new(RotatingLogger::new("rpc=trace".to_owned())) } @@ -45,19 +50,20 @@ fn settings() -> Arc { }) } -fn ethcore_client(miner: &Arc) -> EthcoreClient { - EthcoreClient::new(&miner, logger(), settings()) +fn ethcore_client(client: &Arc, miner: &Arc) -> EthcoreClient { + EthcoreClient::new(client, miner, logger(), settings()) } fn ethcore_set_client(miner: &Arc) -> EthcoreSetClient { - EthcoreSetClient::new(&miner) + EthcoreSetClient::new(miner) } #[test] fn rpc_ethcore_extra_data() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_extraData", "params": [], "id": 1}"#; @@ -72,8 +78,9 @@ fn rpc_ethcore_default_extra_data() { use util::ToPretty; let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_defaultExtraData", "params": [], "id": 1}"#; @@ -85,8 +92,9 @@ fn rpc_ethcore_default_extra_data() { #[test] fn rpc_ethcore_gas_floor_target() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_gasFloorTarget", "params": [], "id": 1}"#; @@ -98,8 +106,9 @@ fn rpc_ethcore_gas_floor_target() { #[test] fn rpc_ethcore_min_gas_price() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_minGasPrice", "params": [], "id": 1}"#; @@ -111,8 +120,9 @@ fn rpc_ethcore_min_gas_price() { #[test] fn rpc_ethcore_set_min_gas_price() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; @@ -125,8 +135,9 @@ fn rpc_ethcore_set_min_gas_price() { #[test] fn rpc_ethcore_set_gas_floor_target() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; @@ -139,8 +150,9 @@ fn rpc_ethcore_set_gas_floor_target() { #[test] fn rpc_ethcore_set_extra_data() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; @@ -153,8 +165,9 @@ fn rpc_ethcore_set_extra_data() { #[test] fn rpc_ethcore_set_author() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; @@ -167,10 +180,11 @@ fn rpc_ethcore_set_author() { #[test] fn rpc_ethcore_dev_logs() { let miner = miner_service(); + let client = client_service(); let logger = logger(); logger.append("a".to_owned()); logger.append("b".to_owned()); - let ethcore = EthcoreClient::new(&miner, logger.clone(), settings()).to_delegate(); + let ethcore = EthcoreClient::new(&client, &miner, logger.clone(), settings()).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); io.add_delegate(ethcore_set_client(&miner).to_delegate()); @@ -184,8 +198,9 @@ fn rpc_ethcore_dev_logs() { #[test] fn rpc_ethcore_dev_logs_levels() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogsLevels", "params":[], "id": 1}"#; @@ -196,8 +211,9 @@ fn rpc_ethcore_dev_logs_levels() { #[test] fn rpc_ethcore_set_transactions_limit() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setTransactionsLimit", "params":[10240240], "id": 1}"#; @@ -210,8 +226,9 @@ fn rpc_ethcore_set_transactions_limit() { #[test] fn rpc_ethcore_transactions_limit() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_transactionsLimit", "params":[], "id": 1}"#; @@ -223,8 +240,9 @@ fn rpc_ethcore_transactions_limit() { #[test] fn rpc_ethcore_net_chain() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netChain", "params":[], "id": 1}"#; @@ -236,8 +254,9 @@ fn rpc_ethcore_net_chain() { #[test] fn rpc_ethcore_net_max_peers() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netMaxPeers", "params":[], "id": 1}"#; @@ -249,8 +268,9 @@ fn rpc_ethcore_net_max_peers() { #[test] fn rpc_ethcore_net_port() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPort", "params":[], "id": 1}"#; @@ -262,8 +282,9 @@ fn rpc_ethcore_net_port() { #[test] fn rpc_ethcore_rpc_settings() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_rpcSettings", "params":[], "id": 1}"#; @@ -275,8 +296,9 @@ fn rpc_ethcore_rpc_settings() { #[test] fn rpc_ethcore_node_name() { let miner = miner_service(); + let client = client_service(); let io = IoHandler::new(); - io.add_delegate(ethcore_client(&miner).to_delegate()); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_nodeName", "params":[], "id": 1}"#; diff --git a/rpc/src/v1/traits/ethcore.rs b/rpc/src/v1/traits/ethcore.rs index 4ce3eca59..1dd00ff73 100644 --- a/rpc/src/v1/traits/ethcore.rs +++ b/rpc/src/v1/traits/ethcore.rs @@ -57,6 +57,9 @@ pub trait Ethcore: Sized + Send + Sync + 'static { /// Returns default extra data fn default_extra_data(&self, _: Params) -> Result; + /// Returns distribution of gas price in latest blocks. + fn gas_price_statistics(&self, _: Params) -> Result; + /// Should be used to convert object to io delegate. fn to_delegate(self) -> IoDelegate { let mut delegate = IoDelegate::new(Arc::new(self)); @@ -73,6 +76,7 @@ pub trait Ethcore: Sized + Send + Sync + 'static { delegate.add_method("ethcore_rpcSettings", Ethcore::rpc_settings); delegate.add_method("ethcore_nodeName", Ethcore::node_name); delegate.add_method("ethcore_defaultExtraData", Ethcore::default_extra_data); + delegate.add_method("ethcore_gasPriceStatistics", Ethcore::gas_price_statistics); delegate } From 2c9a5fc0a99aa2795f0c6f78c02aaa88db04ebd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 15 Jun 2016 00:17:23 +0200 Subject: [PATCH 059/239] More meaningful errors when sending transaction --- Cargo.lock | 42 +++++++++++----------- rpc/src/v1/helpers/signing_queue.rs | 30 +++++++++------- rpc/src/v1/impls/eth_signing.rs | 22 ++++++++---- rpc/src/v1/impls/mod.rs | 55 +++++++++++++++++++++++++++-- rpc/src/v1/impls/personal_signer.rs | 6 ++-- 5 files changed, 109 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9749217a..b95500540 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,7 +72,7 @@ dependencies = [ "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -234,7 +234,7 @@ dependencies = [ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -280,7 +280,7 @@ dependencies = [ "ethcore-rpc 1.2.0", "ethcore-util 1.2.0", "hyper 0.9.3 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -291,8 +291,8 @@ dependencies = [ "parity-dapps-status 0.5.0 (git+https://github.com/ethcore/parity-dapps-status-rs.git)", "parity-dapps-wallet 0.6.1 (git+https://github.com/ethcore/parity-dapps-wallet-rs.git)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -331,7 +331,7 @@ name = "ethcore-ipc-nano" version = "1.2.0" dependencies = [ "ethcore-ipc 1.2.0", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)", ] @@ -348,12 +348,12 @@ dependencies = [ "ethjson 0.1.0", "ethsync 1.2.0", "json-ipc-server 0.2.3 (git+https://github.com/ethcore/json-ipc-server.git)", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -367,7 +367,7 @@ dependencies = [ "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-rpc 1.2.0", "ethcore-util 1.2.0", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-minimal-sysui 0.1.0 (git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -402,7 +402,7 @@ dependencies = [ "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.1.0", "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -417,8 +417,8 @@ version = "0.1.0" dependencies = [ "ethcore-util 1.2.0", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -576,7 +576,7 @@ source = "git+https://github.com/ethcore/json-ipc-server.git#b224bdbcb53cab349c2 dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -594,11 +594,11 @@ dependencies = [ [[package]] name = "jsonrpc-core" -version = "2.0.5" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -609,7 +609,7 @@ version = "5.1.0" source = "git+https://github.com/ethcore/jsonrpc-http-server.git#6117b1d77b5a60d6fa2dc884f12aa7f5fd4585ca" dependencies = [ "hyper 0.9.3 (git+https://github.com/ethcore/hyper)", - "jsonrpc-core 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1181,12 +1181,12 @@ dependencies = [ [[package]] name = "serde" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_codegen" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1202,7 +1202,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/rpc/src/v1/helpers/signing_queue.rs b/rpc/src/v1/helpers/signing_queue.rs index 0ded8998c..dd59ce967 100644 --- a/rpc/src/v1/helpers/signing_queue.rs +++ b/rpc/src/v1/helpers/signing_queue.rs @@ -19,8 +19,11 @@ use std::time::{Instant, Duration}; use std::sync::{mpsc, Mutex, RwLock, Arc}; use std::collections::HashMap; use v1::types::{TransactionRequest, TransactionConfirmation}; -use util::{U256, H256}; +use util::U256; +use jsonrpc_core; +/// Result that can be returned from JSON RPC. +pub type RpcResult = Result; /// Possible events happening in the queue that can be listened to. #[derive(Debug, PartialEq)] @@ -59,7 +62,7 @@ pub trait SigningQueue: Send + Sync { /// Removes a request from the queue. /// Notifies possible token holders that transaction was confirmed and given hash was assigned. - fn request_confirmed(&self, id: U256, hash: H256) -> Option; + fn request_confirmed(&self, id: U256, result: RpcResult) -> Option; /// Returns a request if it is contained in the queue. fn peek(&self, id: &U256) -> Option; @@ -75,7 +78,7 @@ enum ConfirmationResult { /// The transaction has been rejected. Rejected, /// The transaction has been confirmed. - Confirmed(H256), + Confirmed(RpcResult), } /// Time you need to confirm the transaction in UI. @@ -100,7 +103,7 @@ pub struct ConfirmationPromise { impl ConfirmationToken { /// Submit solution to all listeners - fn resolve(&self, result: Option) { + fn resolve(&self, result: Option) { let mut res = self.result.lock().unwrap(); *res = result.map_or(ConfirmationResult::Rejected, |h| ConfirmationResult::Confirmed(h)); // Notify listener @@ -119,8 +122,8 @@ impl ConfirmationPromise { /// Blocks current thread and awaits for /// resolution of the transaction (rejected / confirmed) /// Returns `None` if transaction was rejected or timeout reached. - /// Returns `Some(hash)` if transaction was confirmed. - pub fn wait_with_timeout(&self) -> Option { + /// Returns `Some(result)` if transaction was confirmed. + pub fn wait_with_timeout(&self) -> Option { let timeout = Duration::from_secs(QUEUE_TIMEOUT_DURATION_SEC); let deadline = Instant::now() + timeout; @@ -137,7 +140,7 @@ impl ConfirmationPromise { // Check the result match *res { ConfirmationResult::Rejected => return None, - ConfirmationResult::Confirmed(h) => return Some(h), + ConfirmationResult::Confirmed(ref h) => return Some(h.clone()), ConfirmationResult::Waiting => continue, } } @@ -204,12 +207,12 @@ impl ConfirmationsQueue { /// Removes transaction from this queue and notifies `ConfirmationPromise` holders about the result. /// Notifies also a receiver about that event. - fn remove(&self, id: U256, result: Option) -> Option { + fn remove(&self, id: U256, result: Option) -> Option { let token = self.queue.write().unwrap().remove(&id); if let Some(token) = token { // notify receiver about the event - self.notify(result.map_or_else( + self.notify(result.clone().map_or_else( || QueueEvent::RequestRejected(id), |_| QueueEvent::RequestConfirmed(id) )); @@ -265,9 +268,9 @@ impl SigningQueue for ConfirmationsQueue { self.remove(id, None) } - fn request_confirmed(&self, id: U256, hash: H256) -> Option { + fn request_confirmed(&self, id: U256, result: RpcResult) -> Option { debug!(target: "own_tx", "Signer: Transaction confirmed ({:?}).", id); - self.remove(id, Some(hash)) + self.remove(id, Some(result)) } fn requests(&self) -> Vec { @@ -286,6 +289,7 @@ mod test { use util::numbers::{U256, H256}; use v1::types::TransactionRequest; use super::*; + use jsonrpc_core::to_value; fn request() -> TransactionRequest { TransactionRequest { @@ -317,10 +321,10 @@ mod test { // Just wait for the other thread to start thread::sleep(Duration::from_millis(100)); } - queue.request_confirmed(id, H256::from(1)); + queue.request_confirmed(id, to_value(&H256::from(1))); // then - assert_eq!(handle.join().expect("Thread should finish nicely"), H256::from(1)); + assert_eq!(handle.join().expect("Thread should finish nicely"), to_value(&H256::from(1))); } #[test] diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index f8c3c343d..591eae059 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -25,7 +25,7 @@ use util::keys::store::AccountProvider; use v1::helpers::{SigningQueue, ConfirmationsQueue}; use v1::traits::EthSigning; use v1::types::TransactionRequest; -use v1::impls::sign_and_dispatch; +use v1::impls::{sign_and_dispatch, error_codes}; /// Implementation of functions that require signing when no trusted signer is used. @@ -45,6 +45,7 @@ impl EthSigningQueueClient { impl EthSigning for EthSigningQueueClient { fn sign(&self, _params: Params) -> Result { + warn!("Invoking eth_sign is not yet supported with signer enabled."); // TODO [ToDr] Implement sign when rest of the signing queue is ready. rpc_unimplemented!() } @@ -55,7 +56,7 @@ impl EthSigning for EthSigningQueueClient { let queue = take_weak!(self.queue); let id = queue.add_request(request); let result = id.wait_with_timeout(); - to_value(&result.unwrap_or_else(H256::new)) + result.unwrap_or_else(|| to_value(&H256::new())) }) } } @@ -93,7 +94,9 @@ impl EthSigning for EthSigningUnsafeClient where fn sign(&self, params: Params) -> Result { from_params::<(Address, H256)>(params).and_then(|(addr, msg)| { - to_value(&take_weak!(self.accounts).sign(&addr, &msg).unwrap_or(H520::zero())) + take_weak!(self.accounts).sign(&addr, &msg) + .map(|v| to_value(&v)) + .unwrap_or_else(|e| Err(account_locked(format!("Error: {:?}", e)))) }) } @@ -102,10 +105,17 @@ impl EthSigning for EthSigningUnsafeClient where .and_then(|(request, )| { let accounts = take_weak!(self.accounts); match accounts.account_secret(&request.from) { - Ok(secret) => to_value(&sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, secret)), - Err(_) => to_value(&H256::zero()) + Ok(secret) => sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, secret), + Err(e) => Err(account_locked(format!("Error: {:?}", e))), } }) } - +} + +fn account_locked(data: String) -> Error { + Error { + code: ErrorCode::ServerError(error_codes::ACCOUNT_LOCKED), + message: "Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.".into(), + data: Some(Value::String(data)), + } } diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 7fdf57249..03f4b34ed 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -54,14 +54,16 @@ pub use self::traces::TracesClient; pub use self::rpc::RpcClient; use v1::types::TransactionRequest; +use ethcore::error::Error as EthcoreError; use ethcore::miner::{AccountDetails, MinerService}; use ethcore::client::MiningBlockChainClient; use ethcore::transaction::{Action, SignedTransaction, Transaction}; use util::numbers::*; use util::rlp::encode; use util::bytes::ToPretty; +use jsonrpc_core::{Error, ErrorCode, Value, to_value}; -fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> H256 +fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result where C: MiningBlockChainClient, M: MinerService { let hash = signed_transaction.hash(); @@ -72,10 +74,12 @@ fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedT } }); - import.map(|_| hash).unwrap_or(H256::zero()) + import + .map_err(transaction_error) + .and_then(|_| to_value(&hash)) } -fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, secret: H256) -> H256 +fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, secret: H256) -> Result where C: MiningBlockChainClient, M: MinerService { let signed_transaction = { @@ -97,3 +101,48 @@ fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, s trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty()); dispatch_transaction(&*client, &*miner, signed_transaction) } + +mod error_codes { + // NOTE [ToDr] Codes from -32000 to -32099 + pub const UNKNOWN_ERROR: i64 = -32002; + pub const TRANSACTION_ERROR: i64 = -32010; + pub const ACCOUNT_LOCKED: i64 = -32020; +} + +fn transaction_error(error: EthcoreError) -> Error { + use ethcore::error::TransactionError::*; + + if let EthcoreError::Transaction(e) = error { + let msg = match e { + AlreadyImported => "Transaction with the same hash was already imported.".into(), + Old => "Transaction nonce is too low. Try incrementing the nonce.".into(), + TooCheapToReplace => { + "Transaction fee is too low. There is another transaction with same nonce in the queue. Try increasing the fee or incrementing the nonce.".into() + }, + LimitReached => { + "There is too many transactions in the queue. Your transaction was dropped due to limit. Try increasing the fee.".into() + }, + InsufficientGasPrice { minimal, got } => { + format!("Transaction fee is to low. It does not satisfy your node's minimal fee (minimal: {}, got: {}). Try increasing the fee.", minimal, got) + }, + InsufficientBalance { balance, cost } => { + format!("Insufficient funds. Account you try to send transaction from does not have enough funds. Required {} and got: {}.", cost, balance) + }, + GasLimitExceeded { limit, got } => { + format!("Transaction cost exceeds current gas limit. Limit: {}, got: {}. Try decreasing supplied gas.", limit, got) + }, + InvalidGasLimit(_) => "Supplied gas is beyond limit.".into(), + }; + Error { + code: ErrorCode::ServerError(error_codes::TRANSACTION_ERROR), + message: msg, + data: None, + } + } else { + Error { + code: ErrorCode::ServerError(error_codes::UNKNOWN_ERROR), + message: "Unknown error when sending transaction.".into(), + data: Some(Value::String(format!("{:?}", error))), + } + } +} diff --git a/rpc/src/v1/impls/personal_signer.rs b/rpc/src/v1/impls/personal_signer.rs index 88bf9a5d1..0c1fcb7f1 100644 --- a/rpc/src/v1/impls/personal_signer.rs +++ b/rpc/src/v1/impls/personal_signer.rs @@ -73,9 +73,9 @@ impl PersonalSigner for SignerClient { - let hash = sign_and_dispatch(&*client, &*miner, request, secret); - queue.request_confirmed(id, hash); - Some(to_value(&hash)) + let res = sign_and_dispatch(&*client, &*miner, request, secret); + queue.request_confirmed(id, res.clone()); + Some(res) }, Err(_) => None } From defe688797c31866f885f490d3908c899b78fbf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 15 Jun 2016 09:01:57 +0200 Subject: [PATCH 060/239] Fixing returned value --- rpc/src/v1/impls/eth.rs | 2 +- rpc/src/v1/impls/personal.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 80245708f..fb512d91a 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -516,7 +516,7 @@ impl Eth for EthClient where .and_then(|(raw_transaction, )| { let raw_transaction = raw_transaction.to_vec(); match UntrustedRlp::new(&raw_transaction).as_val() { - Ok(signed_transaction) => to_value(&dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction)), + Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction), Err(_) => to_value(&H256::zero()), } }) diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index c62c71453..4f9e307cb 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -92,7 +92,7 @@ impl Personal for PersonalClient .and_then(|(request, password)| { let accounts = take_weak!(self.accounts); match accounts.locked_account_secret(&request.from, &password) { - Ok(secret) => to_value(&sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, secret)), + Ok(secret) => sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, secret), Err(_) => to_value(&H256::zero()), } }) From 1baa15008674c29776e7a8067fd87e0fe6a4b97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 15 Jun 2016 18:32:21 +0200 Subject: [PATCH 061/239] Consolidating all RPC error codes --- rpc/src/v1/impls/eth.rs | 10 +++------- rpc/src/v1/impls/mod.rs | 16 +++++++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index fb512d91a..dc5d8c081 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -37,7 +37,7 @@ use ethcore::filter::Filter as EthcoreFilter; use self::ethash::SeedHashCompute; use v1::traits::Eth; use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, OptionalValue, Index, Filter, Log, Receipt}; -use v1::impls::dispatch_transaction; +use v1::impls::{dispatch_transaction, error_codes}; use serde; /// Eth rpc implementation. @@ -218,13 +218,9 @@ fn from_params_default_third(params: Params) -> Result<(F1, F2, BlockNum } } -// must be in range [-32099, -32000] -const UNSUPPORTED_REQUEST_CODE: i64 = -32000; -const NO_WORK_CODE: i64 = -32001; - fn make_unsupported_err() -> Error { Error { - code: ErrorCode::ServerError(UNSUPPORTED_REQUEST_CODE), + code: ErrorCode::ServerError(error_codes::UNSUPPORTED_REQUEST_CODE), message: "Unsupported request.".into(), data: None } @@ -232,7 +228,7 @@ fn make_unsupported_err() -> Error { fn no_work_err() -> Error { Error { - code: ErrorCode::ServerError(NO_WORK_CODE), + code: ErrorCode::ServerError(error_codes::NO_WORK_CODE), message: "Still syncing.".into(), data: None } diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 03f4b34ed..8ea02b8b3 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -63,6 +63,15 @@ use util::rlp::encode; use util::bytes::ToPretty; use jsonrpc_core::{Error, ErrorCode, Value, to_value}; +mod error_codes { + // NOTE [ToDr] Codes from [-32099, -32000] + pub const UNSUPPORTED_REQUEST_CODE: i64 = -32000; + pub const NO_WORK_CODE: i64 = -32001; + pub const UNKNOWN_ERROR: i64 = -32002; + pub const TRANSACTION_ERROR: i64 = -32010; + pub const ACCOUNT_LOCKED: i64 = -32020; +} + fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result where C: MiningBlockChainClient, M: MinerService { let hash = signed_transaction.hash(); @@ -102,13 +111,6 @@ fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, s dispatch_transaction(&*client, &*miner, signed_transaction) } -mod error_codes { - // NOTE [ToDr] Codes from -32000 to -32099 - pub const UNKNOWN_ERROR: i64 = -32002; - pub const TRANSACTION_ERROR: i64 = -32010; - pub const ACCOUNT_LOCKED: i64 = -32020; -} - fn transaction_error(error: EthcoreError) -> Error { use ethcore::error::TransactionError::*; From b4aae6bd9c7b4c88de12afabdabb3e38b71af392 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 16 Jun 2016 16:14:22 +0400 Subject: [PATCH 062/239] Key load avoid warning (#1303) * avoid warning with key * fix intendations * more intendation fix * ok() instead of expect() --- util/src/keys/directory.rs | 11 +++++++---- util/src/keys/store.rs | 12 ++++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/util/src/keys/directory.rs b/util/src/keys/directory.rs index 32ac14b55..385a400c7 100644 --- a/util/src/keys/directory.rs +++ b/util/src/keys/directory.rs @@ -428,9 +428,9 @@ impl KeyFileContent { let crypto = match as_object.get("crypto") { None => { return Err(KeyFileParseError::NoCryptoSection); } Some(crypto_json) => match KeyFileCrypto::from_json(crypto_json) { - Ok(crypto) => crypto, - Err(crypto_error) => { return Err(KeyFileParseError::Crypto(crypto_error)); } - } + Ok(crypto) => crypto, + Err(crypto_error) => { return Err(KeyFileParseError::Crypto(crypto_error)); } + } }; Ok(KeyFileContent { @@ -627,7 +627,10 @@ impl KeyDirectory { } } - + /// Checks if key exists + pub fn exists(&self, id: &Uuid) -> bool { + KeyDirectory::load_key(&self.key_path(id)).is_ok() + } } diff --git a/util/src/keys/store.rs b/util/src/keys/store.rs index f6f41745f..b8a1de272 100644 --- a/util/src/keys/store.rs +++ b/util/src/keys/store.rs @@ -294,9 +294,9 @@ impl SecretStore { if let Some(unlock) = read_lock.get(account) { (unlock.relock_on_use, match crypto::KeyPair::from_secret(unlock.secret) { Ok(pair) => match pair.sign(message) { - Ok(signature) => Ok(signature), - Err(_) => Err(SigningError::InvalidSecret) - }, + Ok(signature) => Ok(signature), + Err(_) => Err(SigningError::InvalidSecret) + }, Err(_) => Err(SigningError::InvalidSecret) }) } else { @@ -348,6 +348,10 @@ impl SecretStore { garbage_lock.shrink_to_fit(); } + + fn exists(&self, key: &H128) -> bool { + self.directory.exists(key) + } } fn derive_key_iterations(password: &str, salt: &H256, c: u32) -> (Bytes, Bytes) { @@ -408,7 +412,7 @@ impl EncryptedHashMap for SecretStore { } fn insert(&mut self, key: H128, value: Value, password: &str) -> Option { - let previous = if let Ok(previous_value) = self.get(&key, password) { Some(previous_value) } else { None }; + let previous = if !self.exists(&key) { None } else { self.get(&key, password).ok() }; // crypto random initiators let salt = H256::random(); From 76b413b5f7454cb2abdc0b45c187742cf0fc616d Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 16 Jun 2016 19:02:55 +0400 Subject: [PATCH 063/239] Appveyor config for windows build+installer (#1302) * appveyor * proper dist name * quote * win-build config * proper build section * tests in release * plugin dir * cache binaries * quotes * escaped quotes * forces user dir * fixes * syntax * proper cahce dir * quotes? * root nsis instead of bin * submodules init * artifact path fix * no submodule * raw link here * another way to force cargo cache * include vc++ 2015 redist * fix name of the dist * ETHCORE -> Ethcore --- appveyor.yml | 29 +++++++++++++++++++++++++++++ nsis/installer.nsi | 7 ++++++- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..b980aba42 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,29 @@ +environment: + matrix: + - TARGET: x86_64-pc-windows-msvc +install: + - git submodule update --init --recursive + - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.9.0-x86_64-pc-windows-msvc.exe" + - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -FileName nsis\SimpleFC.dll + - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -FileName nsis\vc_redist.x64.exe + - rust-1.9.0-x86_64-pc-windows-msvc.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" + - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin;C:\Program Files (x86)\NSIS + - rustc -V + - cargo -V + +build: off + +test_script: + - cargo test --verbose --release + +after_test: + - cargo build --verbose --release + - makensis.exe nsis\installer.nsi + +artifacts: + - path: nsis\installer.exe + name: Windows Installer (x86_64) + +cache: + - target + - C:\users\appveyor\.cargo -> appveyor.yml diff --git a/nsis/installer.nsi b/nsis/installer.nsi index 10143306a..fffcc1dd9 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -1,11 +1,13 @@ !define APPNAME "Parity" -!define COMPANYNAME "ETHCORE" +!define COMPANYNAME "Ethcore" !define DESCRIPTION "Fast, light, robust Ethereum implementation" !define VERSIONMAJOR 1 !define VERSIONMINOR 2 !define VERSIONBUILD 0 +!addplugindir .\ + !define HELPURL "https://github.com/ethcore/parity/wiki" # "Support Information" link !define UPDATEURL "https://github.com/ethcore/parity/releases" # "Product Updates" link !define ABOUTURL "https://github.com/ethcore/parity" # "Publisher" link @@ -47,6 +49,9 @@ section "install" # Files added here should be removed by the uninstaller (see section "uninstall") file /oname=parity.exe ..\target\release\parity.exe file "logo.ico" + file vc_redist.x64.exe + + ExecWait '"$INSTDIR\vc_redist.x64.exe" /passive /norestart' # Add any other files for the install directory (license files, app data, etc) here # Uninstaller - See function un.onInit and section "uninstall" for configuration From 42478add648f2f44670c3859044d725171a33068 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 17 Jun 2016 22:15:18 +0200 Subject: [PATCH 064/239] DAO Rescue soft fork (#1309) * DAO Rescue soft fork * Address minor issues. * Fix tests. --- ethcore/src/error.rs | 3 +++ ethcore/src/ethereum/ethash.rs | 5 ++++- ethcore/src/evm/schedule.rs | 3 +++ ethcore/src/state.rs | 18 ++++++++++++++++++ rpc/src/v1/impls/mod.rs | 1 + 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 98aec917a..9be800e13 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -58,6 +58,8 @@ pub enum TransactionError { }, /// Transaction's gas limit (aka gas) is invalid. InvalidGasLimit(OutOfBounds), + /// Transaction is invalid for some other reason. + DAORescue, } impl fmt::Display for TransactionError { @@ -76,6 +78,7 @@ impl fmt::Display for TransactionError { GasLimitExceeded { limit, got } => format!("Gas limit exceeded. Limit={}, Given={}", limit, got), InvalidGasLimit(ref err) => format!("Invalid gas limit. {}", err), + DAORescue => "Transaction is invalid due to the DAO rescue.".into(), }; f.write_fmt(format_args!("Transaction error ({})", msg)) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index c8b8d7b31..d89499872 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -101,7 +101,10 @@ impl Engine for Ethash { if env_info.number < self.ethash_params.frontier_compatibility_mode_limit { Schedule::new_frontier() } else { - Schedule::new_homestead() + let mut s = Schedule::new_homestead(); + // TODO: make dependent on gaslimit > 4000000 of block 1760000. + s.block_dao_transactions = env_info.number >= 1760000; + s } } diff --git a/ethcore/src/evm/schedule.rs b/ethcore/src/evm/schedule.rs index f82157239..59f30e7d3 100644 --- a/ethcore/src/evm/schedule.rs +++ b/ethcore/src/evm/schedule.rs @@ -80,6 +80,8 @@ pub struct Schedule { pub tx_data_non_zero_gas: usize, /// Gas price for copying memory pub copy_gas: usize, + /// DAO Rescue softfork block + pub block_dao_transactions: bool, } impl Schedule { @@ -126,6 +128,7 @@ impl Schedule { tx_data_zero_gas: 4, tx_data_non_zero_gas: 68, copy_gas: 3, + block_dao_transactions: false, } } } diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index 204cea618..dc9ca582c 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -222,6 +222,24 @@ impl State { let options = TransactOptions { tracing: tracing, vm_tracing: false, check_nonce: true }; let e = try!(Executive::new(self, env_info, engine, vm_factory).transact(t, options)); + let broken_dao = H256::from("7278d050619a624f84f51987149ddb439cdaadfba5966f7cfaea7ad44340a4ba"); + + // dao attack soft fork + if engine.schedule(&env_info).block_dao_transactions { + // collect all the addresses which have changed. + let addresses = self.cache.borrow().iter().map(|(addr, _)| addr.clone()).collect::>(); + + for a in addresses.iter() { + if self.code(a).map(|c| c.sha3() == broken_dao).unwrap_or(false) { + // Figure out if the balance has been reduced. + let maybe_original = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR).get(&a).map(Account::from_rlp); + if maybe_original.map(|original| *original.balance() > self.balance(a)).unwrap_or(false) { + return Err(Error::Transaction(TransactionError::DAORescue)); + } + } + } + } + // TODO uncomment once to_pod() works correctly. // trace!("Applied transaction. Diff:\n{}\n", state_diff::diff_pod(&old, &self.to_pod())); self.commit(); diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 8ea02b8b3..f69fa25ce 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -134,6 +134,7 @@ fn transaction_error(error: EthcoreError) -> Error { format!("Transaction cost exceeds current gas limit. Limit: {}, got: {}. Try decreasing supplied gas.", limit, got) }, InvalidGasLimit(_) => "Supplied gas is beyond limit.".into(), + DAORescue => "Transaction removes funds from a DAO.".into(), }; Error { code: ErrorCode::ServerError(error_codes::TRANSACTION_ERROR), From 75a7cf28604c8f8a03dbb5cd1940859c422bdf8e Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Sat, 18 Jun 2016 12:09:29 +0200 Subject: [PATCH 065/239] fixed #1180 (#1282) --- rpc/src/v1/impls/eth.rs | 12 ++++++++--- rpc/src/v1/types/receipt.rs | 41 +++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index dc5d8c081..bd9384dfe 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -421,9 +421,15 @@ impl Eth for EthClient where fn transaction_receipt(&self, params: Params) -> Result { from_params::<(H256,)>(params) .and_then(|(hash,)| { - let client = take_weak!(self.client); - let receipt = client.transaction_receipt(TransactionID::Hash(hash)); - to_value(&receipt.map(Receipt::from)) + let miner = take_weak!(self.miner); + match miner.pending_receipts().get(&hash) { + Some(receipt) => to_value(&Receipt::from(receipt.clone())), + None => { + let client = take_weak!(self.client); + let receipt = client.transaction_receipt(TransactionID::Hash(hash)); + to_value(&receipt.map(Receipt::from)) + } + } }) } diff --git a/rpc/src/v1/types/receipt.rs b/rpc/src/v1/types/receipt.rs index 32a7f5945..c56cdf3d3 100644 --- a/rpc/src/v1/types/receipt.rs +++ b/rpc/src/v1/types/receipt.rs @@ -17,23 +17,23 @@ use util::numbers::U256; use util::hash::{Address, H256}; use v1::types::Log; -use ethcore::receipt::LocalizedReceipt; +use ethcore::receipt::{Receipt as EthReceipt, LocalizedReceipt}; /// Receipt #[derive(Debug, Serialize)] pub struct Receipt { /// Transaction Hash #[serde(rename="transactionHash")] - pub transaction_hash: H256, + pub transaction_hash: Option, /// Transaction index #[serde(rename="transactionIndex")] - pub transaction_index: U256, + pub transaction_index: Option, /// Block hash #[serde(rename="blockHash")] - pub block_hash: H256, + pub block_hash: Option, /// Block number #[serde(rename="blockNumber")] - pub block_number: U256, + pub block_number: Option, /// Cumulative gas used #[serde(rename="cumulativeGasUsed")] pub cumulative_gas_used: U256, @@ -50,10 +50,10 @@ pub struct Receipt { impl From for Receipt { fn from(r: LocalizedReceipt) -> Self { Receipt { - transaction_hash: r.transaction_hash, - transaction_index: U256::from(r.transaction_index), - block_hash: r.block_hash, - block_number: U256::from(r.block_number), + transaction_hash: Some(r.transaction_hash), + transaction_index: Some(U256::from(r.transaction_index)), + block_hash: Some(r.block_hash), + block_number: Some(U256::from(r.block_number)), cumulative_gas_used: r.cumulative_gas_used, gas_used: r.gas_used, contract_address: r.contract_address, @@ -62,6 +62,21 @@ impl From for Receipt { } } +impl From for Receipt { + fn from(r: EthReceipt) -> Self { + Receipt { + transaction_hash: None, + transaction_index: None, + block_hash: None, + block_number: None, + cumulative_gas_used: r.gas_used, + gas_used: r.gas_used, + contract_address: None, + logs: r.logs.into_iter().map(From::from).collect(), + } + } +} + #[cfg(test)] mod tests { use serde_json; @@ -74,10 +89,10 @@ mod tests { let s = r#"{"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x00","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x04510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x04510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x00","logIndex":"0x01","type":"mined"}]}"#; let receipt = Receipt { - transaction_hash: H256::zero(), - transaction_index: U256::zero(), - block_hash: H256::from_str("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5").unwrap(), - block_number: U256::from(0x4510c), + transaction_hash: Some(H256::zero()), + transaction_index: Some(U256::zero()), + block_hash: Some(H256::from_str("ed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5").unwrap()), + block_number: Some(U256::from(0x4510c)), cumulative_gas_used: U256::from(0x20), gas_used: U256::from(0x10), contract_address: None, From e95756514404d425659f3fbeccaceb93808bc2a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 18 Jun 2016 12:33:45 +0200 Subject: [PATCH 066/239] Disabling ethcore_set* APIs by default (+ Status page update) (#1315) * More meaningful errors when sending transaction * Fixing returned value * Consolidating all RPC error codes * Fixed loosing peers on incoming connections. (#1293) * Deactivate peer if it has no new data * Fixed node table timer registration * Fixed handshake timeout expiration * Extra trace * Fixed session count calculation * Only deactivate incapable peers in ChainHead state * Timer registration is not needed * x64 path * firewall rules * Fix read-ahead bug. Re-ahead 8 bytes rather than 3 to ensure large blocks import fine. * Refactor to use a const. * Update README.md * Gas price statistics. (#1291) * Gas price statistics. Affects eth_gasPrice. Added ethcore_gasPriceStatistics. Closes #1265 * Fix a bug in eth_gasPrice * Fix tests. * Revert minor alteration. * Tests for gas_price_statistics. - Tests; - Additional infrastructure for generating test blocks with transactions. * Key load avoid warning (#1303) * avoid warning with key * fix intendations * more intendation fix * ok() instead of expect() * Appveyor config for windows build+installer (#1302) * appveyor * proper dist name * quote * win-build config * proper build section * tests in release * plugin dir * cache binaries * quotes * escaped quotes * forces user dir * fixes * syntax * proper cahce dir * quotes? * root nsis instead of bin * submodules init * artifact path fix * no submodule * raw link here * another way to force cargo cache * include vc++ 2015 redist * fix name of the dist * ETHCORE -> Ethcore * Disabling ethcore_set* APIs (+ Status page) --- Cargo.lock | 2 +- parity/rpc_apis.rs | 4 ++-- sync/src/chain.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b95500540..d6ac021ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "parity-dapps-status" version = "0.5.0" -source = "git+https://github.com/ethcore/parity-dapps-status-rs.git#53e159f52013be5d2e8ba7eca35f605ad6e3bfa9" +source = "git+https://github.com/ethcore/parity-dapps-status-rs.git#0cdd3512004e403aff7da3b8c16ba0bf5d6c911c" dependencies = [ "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", ] diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index f4b2d067f..8f8c7b27e 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -122,10 +122,10 @@ fn list_apis(apis: ApiSet) -> Vec { match apis { ApiSet::List(apis) => apis, ApiSet::UnsafeContext => { - vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc] + vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Ethcore, Api::Traces, Api::Rpc] }, _ => { - vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc] + vec![Api::Web3, Api::Net, Api::Eth, Api::Personal, Api::Signer, Api::Ethcore, Api::Traces, Api::Rpc] }, } } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 25f1eb6a3..db2ec339e 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -458,12 +458,12 @@ impl ChainSync { // Disable the peer for this syncing round if it gives invalid chain if !valid_response { trace!(target: "sync", "{} Deactivated for invalid headers response", peer_id); - self.deactivate_peer(io, peer_id); + self.deactivate_peer(io, peer_id); } if headers.is_empty() { // Peer does not have any new subchain heads, deactivate it nd try with another trace!(target: "sync", "{} Deactivated for no data", peer_id); - self.deactivate_peer(io, peer_id); + self.deactivate_peer(io, peer_id); } match self.state { SyncState::ChainHead => { From 91dc31fd705c3632db1b8dbce731a28fdb03e957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 18 Jun 2016 13:08:55 +0200 Subject: [PATCH 067/239] Removing Maker and DAO dapps (#1319) --- Cargo.lock | 18 ------------------ dapps/Cargo.toml | 2 +- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6ac021ea..52364e9d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -286,8 +286,6 @@ dependencies = [ "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", "parity-dapps-builtins 0.5.1 (git+https://github.com/ethcore/parity-dapps-builtins-rs.git)", - "parity-dapps-dao 0.4.0 (git+https://github.com/ethcore/parity-dapps-dao-rs.git)", - "parity-dapps-makerotc 0.3.0 (git+https://github.com/ethcore/parity-dapps-makerotc-rs.git)", "parity-dapps-status 0.5.0 (git+https://github.com/ethcore/parity-dapps-status-rs.git)", "parity-dapps-wallet 0.6.1 (git+https://github.com/ethcore/parity-dapps-wallet-rs.git)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -917,22 +915,6 @@ dependencies = [ "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", ] -[[package]] -name = "parity-dapps-dao" -version = "0.4.0" -source = "git+https://github.com/ethcore/parity-dapps-dao-rs.git#dd6b9ca7c18fbfa714183a4f570bd75b8391c13d" -dependencies = [ - "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", -] - -[[package]] -name = "parity-dapps-makerotc" -version = "0.3.0" -source = "git+https://github.com/ethcore/parity-dapps-makerotc-rs.git#33568ac7209aa765c498bb2322e848f552656303" -dependencies = [ - "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", -] - [[package]] name = "parity-dapps-status" version = "0.5.0" diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index 396ee4f2c..dc45085d5 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -36,6 +36,6 @@ syntex = "*" [features] default = ["serde_codegen", "extra-dapps"] -extra-dapps = ["parity-dapps-wallet", "parity-dapps-dao", "parity-dapps-makerotc"] +extra-dapps = ["parity-dapps-wallet"] nightly = ["serde_macros"] dev = ["clippy", "ethcore-rpc/dev", "ethcore-util/dev"] From 5e1e3ce85757434abdd0f12bfacd59bc5cb8936a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 18 Jun 2016 14:55:46 +0200 Subject: [PATCH 068/239] Filling-in optional fields of TransactionRequest... (#1305) * More meaningful errors when sending transaction * Fixing returned value * Consolidating all RPC error codes * Fixed loosing peers on incoming connections. (#1293) * Deactivate peer if it has no new data * Fixed node table timer registration * Fixed handshake timeout expiration * Extra trace * Fixed session count calculation * Only deactivate incapable peers in ChainHead state * Timer registration is not needed * x64 path * firewall rules * Fix read-ahead bug. Re-ahead 8 bytes rather than 3 to ensure large blocks import fine. * Refactor to use a const. * Update README.md * Gas price statistics. (#1291) * Gas price statistics. Affects eth_gasPrice. Added ethcore_gasPriceStatistics. Closes #1265 * Fix a bug in eth_gasPrice * Fix tests. * Revert minor alteration. * Tests for gas_price_statistics. - Tests; - Additional infrastructure for generating test blocks with transactions. * Key load avoid warning (#1303) * avoid warning with key * fix intendations * more intendation fix * ok() instead of expect() * Filling-in optional fields of TransactionRequest. * Adding reference to miner --- parity/rpc_apis.rs | 2 +- rpc/src/v1/impls/eth_signing.rs | 27 +++++++++++++++++++++----- rpc/src/v1/tests/mocked/eth_signing.rs | 6 +++++- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 8f8c7b27e..016f347aa 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -147,7 +147,7 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); if deps.signer_port.is_some() { - server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue).to_delegate()); + server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.miner).to_delegate()); } else { server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate()); } diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index 591eae059..9a045d7a1 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -24,25 +24,40 @@ use util::numbers::*; use util::keys::store::AccountProvider; use v1::helpers::{SigningQueue, ConfirmationsQueue}; use v1::traits::EthSigning; -use v1::types::TransactionRequest; +use v1::types::{TransactionRequest, Bytes}; use v1::impls::{sign_and_dispatch, error_codes}; /// Implementation of functions that require signing when no trusted signer is used. -pub struct EthSigningQueueClient { +pub struct EthSigningQueueClient { queue: Weak, + miner: Weak, } -impl EthSigningQueueClient { +impl EthSigningQueueClient { /// Creates a new signing queue client given shared signing queue. - pub fn new(queue: &Arc) -> Self { + pub fn new(queue: &Arc, miner: &Arc) -> Self { EthSigningQueueClient { queue: Arc::downgrade(queue), + miner: Arc::downgrade(miner), } } + + fn fill_optional_fields(&self, miner: Arc, mut request: TransactionRequest) -> TransactionRequest { + if let None = request.gas { + request.gas = Some(miner.sensible_gas_limit()); + } + if let None = request.gas_price { + request.gas_price = Some(miner.sensible_gas_price()); + } + if let None = request.data { + request.data = Some(Bytes::new(Vec::new())); + } + request + } } -impl EthSigning for EthSigningQueueClient { +impl EthSigning for EthSigningQueueClient { fn sign(&self, _params: Params) -> Result { warn!("Invoking eth_sign is not yet supported with signer enabled."); @@ -54,6 +69,8 @@ impl EthSigning for EthSigningQueueClient { from_params::<(TransactionRequest, )>(params) .and_then(|(request, )| { let queue = take_weak!(self.queue); + let miner = take_weak!(self.miner); + let request = self.fill_optional_fields(miner, request); let id = queue.add_request(request); let result = id.wait_with_timeout(); result.unwrap_or_else(|| to_value(&H256::new())) diff --git a/rpc/src/v1/tests/mocked/eth_signing.rs b/rpc/src/v1/tests/mocked/eth_signing.rs index 6eb6e3fd6..a70a4cdaf 100644 --- a/rpc/src/v1/tests/mocked/eth_signing.rs +++ b/rpc/src/v1/tests/mocked/eth_signing.rs @@ -19,21 +19,25 @@ use jsonrpc_core::IoHandler; use v1::impls::EthSigningQueueClient; use v1::traits::EthSigning; use v1::helpers::{ConfirmationsQueue, SigningQueue}; +use v1::tests::helpers::TestMinerService; use util::keys::TestAccount; struct EthSigningTester { pub queue: Arc, + pub miner: Arc, pub io: IoHandler, } impl Default for EthSigningTester { fn default() -> Self { let queue = Arc::new(ConfirmationsQueue::default()); + let miner = Arc::new(TestMinerService::default()); let io = IoHandler::new(); - io.add_delegate(EthSigningQueueClient::new(&queue).to_delegate()); + io.add_delegate(EthSigningQueueClient::new(&queue, &miner).to_delegate()); EthSigningTester { queue: queue, + miner: miner, io: io, } } From c9f8eff92df1291ac6cdce8788e6e9025e813c54 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 18 Jun 2016 14:59:52 +0200 Subject: [PATCH 069/239] Change CLI default for gas floor target. --- parity/cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/cli.rs b/parity/cli.rs index ba3cfc21a..0ec2bb094 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -120,7 +120,7 @@ Sealing/Mining Options: web service in turn and fallback on the last known good value [default: auto]. --gas-floor-target GAS Amount of gas per block to target when sealing a new - block [default: 4712388]. + block [default: 3141592]. --author ADDRESS Specify the block author (aka "coinbase") address for sending block rewards from sealed blocks [default: 0037a6b811ffeb6e072da21179d11b1406371c63]. From 22e390f92294465661d01c56769ebeb4a4e8a235 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 18 Jun 2016 15:00:12 +0200 Subject: [PATCH 070/239] Rename block_dao -> reject_dao. --- ethcore/src/ethereum/ethash.rs | 2 +- ethcore/src/evm/schedule.rs | 4 ++-- ethcore/src/state.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index d89499872..a4291796a 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -103,7 +103,7 @@ impl Engine for Ethash { } else { let mut s = Schedule::new_homestead(); // TODO: make dependent on gaslimit > 4000000 of block 1760000. - s.block_dao_transactions = env_info.number >= 1760000; + s.reject_dao_transactions = env_info.number >= 1760000; s } } diff --git a/ethcore/src/evm/schedule.rs b/ethcore/src/evm/schedule.rs index 59f30e7d3..188e72373 100644 --- a/ethcore/src/evm/schedule.rs +++ b/ethcore/src/evm/schedule.rs @@ -81,7 +81,7 @@ pub struct Schedule { /// Gas price for copying memory pub copy_gas: usize, /// DAO Rescue softfork block - pub block_dao_transactions: bool, + pub reject_dao_transactions: bool, } impl Schedule { @@ -128,7 +128,7 @@ impl Schedule { tx_data_zero_gas: 4, tx_data_non_zero_gas: 68, copy_gas: 3, - block_dao_transactions: false, + reject_dao_transactions: false, } } } diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index dc9ca582c..7d045b455 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -225,7 +225,7 @@ impl State { let broken_dao = H256::from("7278d050619a624f84f51987149ddb439cdaadfba5966f7cfaea7ad44340a4ba"); // dao attack soft fork - if engine.schedule(&env_info).block_dao_transactions { + if engine.schedule(&env_info).reject_dao_transactions { // collect all the addresses which have changed. let addresses = self.cache.borrow().iter().map(|(addr, _)| addr.clone()).collect::>(); From ec654feaf8f39dbc1cb53d1ba38fd6bcca55b616 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Sat, 18 Jun 2016 15:10:24 +0200 Subject: [PATCH 071/239] Syncing fix (#1320) * Fixed aborting peer for expired session * Don't ban for usesless --- sync/src/chain.rs | 14 +++++++++++--- util/src/network/connection.rs | 1 + util/src/network/host.rs | 3 +-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index db2ec339e..ef05ec9d1 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -396,7 +396,7 @@ impl ChainSync { return Ok(()); } let item_count = r.item_count(); - trace!(target: "sync", "{} -> BlockHeaders ({} entries)", peer_id, item_count); + trace!(target: "sync", "{} -> BlockHeaders ({} entries), state = {:?}", peer_id, item_count, self.state); if self.state == SyncState::Idle { trace!(target: "sync", "Ignored unexpected block headers"); self.continue_sync(io); @@ -655,6 +655,7 @@ impl ChainSync { fn continue_sync(&mut self, io: &mut SyncIo) { let mut peers: Vec<(PeerId, U256)> = self.peers.iter().map(|(k, p)| (*k, p.difficulty.unwrap_or_else(U256::zero))).collect(); peers.sort_by(|&(_, d1), &(_, d2)| d1.cmp(&d2).reverse()); //TODO: sort by rating + trace!(target: "sync", "Syncing with {}/{} peers", self.active_peers.len(), peers.len()); for (p, _) in peers { if self.active_peers.contains(&p) { self.sync_peer(io, p, false); @@ -737,6 +738,8 @@ impl ChainSync { None => { // TODO: get hash by number from the block queue trace!(target: "sync", "Could not revert to previous block, last: {} ({})", self.last_imported_block, self.last_imported_hash); + // just wait for full sync to complete + self.pause_sync(); } } } @@ -1128,14 +1131,19 @@ impl ChainSync { }) } - pub fn maintain_peers(&self, io: &mut SyncIo) { + pub fn maintain_peers(&mut self, io: &mut SyncIo) { let tick = time::precise_time_s(); + let mut aborting = Vec::new(); for (peer_id, peer) in &self.peers { if peer.asking != PeerAsking::Nothing && (tick - peer.ask_time) > CONNECTION_TIMEOUT_SEC { trace!(target:"sync", "Timeout {}", peer_id); io.disconnect_peer(*peer_id); + aborting.push(*peer_id); } } + for p in aborting { + self.on_peer_aborting(io, p); + } } fn check_resume(&mut self, io: &mut SyncIo) { @@ -1313,7 +1321,7 @@ impl ChainSync { self.check_resume(io); } - /// called when block is imported to chain, updates transactions queue and propagates the blocks + /// called when block is imported to chain, updates transactions queue and propagates the blocks pub fn chain_new_blocks(&mut self, io: &mut SyncIo, _imported: &[H256], invalid: &[H256], _enacted: &[H256], _retracted: &[H256]) { if io.is_chain_queue_empty() { // Propagate latests blocks diff --git a/util/src/network/connection.rs b/util/src/network/connection.rs index f4c4c2a8d..9ee045c87 100644 --- a/util/src/network/connection.rs +++ b/util/src/network/connection.rs @@ -139,6 +139,7 @@ impl GenericConnection { }, Ok(Some(size)) if (buf.position() as usize) == send_size => { self.stats.inc_send(size); + trace!(target:"network", "{}: Wrote {} bytes", self.token, send_size); Ok(WriteStatus::Complete) }, Ok(Some(_)) => { panic!("Wrote past buffer");}, diff --git a/util/src/network/host.rs b/util/src/network/host.rs index e2cf32aa0..d859db1c3 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -250,7 +250,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone self.io.message(NetworkIoMessage::Disconnect(peer)); } - /// Sheck if the session is till active. + /// Check if the session is still active. pub fn is_expired(&self) -> bool { self.session.as_ref().map(|s| s.lock().unwrap().expired()).unwrap_or(false) } @@ -664,7 +664,6 @@ impl Host where Message: Send + Sync + Clone { Err(e) => { trace!(target: "network", "Session read error: {}:{:?} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); match e { - UtilError::Network(NetworkError::Disconnect(DisconnectReason::UselessPeer)) | UtilError::Network(NetworkError::Disconnect(DisconnectReason::IncompatibleProtocol)) => { if let Some(id) = s.id() { self.nodes.write().unwrap().mark_as_useless(id); From c1c64bedc2b0c3801c39b2cc294489e4a8bb3168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 18 Jun 2016 15:10:36 +0200 Subject: [PATCH 072/239] Bumping topbar. Fixing ws server closing when suspending (#1312) * More meaningful errors when sending transaction * Fixing returned value * Consolidating all RPC error codes * Fixed loosing peers on incoming connections. (#1293) * Deactivate peer if it has no new data * Fixed node table timer registration * Fixed handshake timeout expiration * Extra trace * Fixed session count calculation * Only deactivate incapable peers in ChainHead state * Timer registration is not needed * x64 path * firewall rules * Fix read-ahead bug. Re-ahead 8 bytes rather than 3 to ensure large blocks import fine. * Refactor to use a const. * Update README.md * Gas price statistics. (#1291) * Gas price statistics. Affects eth_gasPrice. Added ethcore_gasPriceStatistics. Closes #1265 * Fix a bug in eth_gasPrice * Fix tests. * Revert minor alteration. * Tests for gas_price_statistics. - Tests; - Additional infrastructure for generating test blocks with transactions. * Key load avoid warning (#1303) * avoid warning with key * fix intendations * more intendation fix * ok() instead of expect() * Appveyor config for windows build+installer (#1302) * appveyor * proper dist name * quote * win-build config * proper build section * tests in release * plugin dir * cache binaries * quotes * escaped quotes * forces user dir * fixes * syntax * proper cahce dir * quotes? * root nsis instead of bin * submodules init * artifact path fix * no submodule * raw link here * another way to force cargo cache * include vc++ 2015 redist * fix name of the dist * ETHCORE -> Ethcore * Bumping topbar. Fixing ws server closing when suspending --- Cargo.lock | 8 ++++---- signer/src/ws_server/mod.rs | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52364e9d2..8bf4de9e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -370,7 +370,7 @@ dependencies = [ "parity-minimal-sysui 0.1.0 (git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.4.6 (git+https://github.com/ethcore/ws-rs.git)", + "ws 0.5.1 (git+https://github.com/ethcore/ws-rs.git)", ] [[package]] @@ -910,7 +910,7 @@ dependencies = [ [[package]] name = "parity-dapps-builtins" version = "0.5.1" -source = "git+https://github.com/ethcore/parity-dapps-builtins-rs.git#b3970ff4686a12321365cfafba6552bfaa2e7874" +source = "git+https://github.com/ethcore/parity-dapps-builtins-rs.git#413ef9a6f9c46d16d578a48e39adb44d5650d7d7" dependencies = [ "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", ] @@ -1446,8 +1446,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ws" -version = "0.4.6" -source = "git+https://github.com/ethcore/ws-rs.git#5b28de58421b017b01f4565b2c35a46679707789" +version = "0.5.1" +source = "git+https://github.com/ethcore/ws-rs.git#d5745df8ea1ab82cd2b844f15ca1ac759e7aa9f5" dependencies = [ "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/signer/src/ws_server/mod.rs b/signer/src/ws_server/mod.rs index 76c0fbb16..beffbd2f7 100644 --- a/signer/src/ws_server/mod.rs +++ b/signer/src/ws_server/mod.rs @@ -92,8 +92,11 @@ impl Server { fn start(addr: SocketAddr, handler: Arc, queue: Arc, authcodes_path: PathBuf) -> Result { let config = { let mut config = ws::Settings::default(); - config.max_connections = 10; + // It's also used for handling min-sysui requests (browser can make many of them in paralel) + config.max_connections = 15; config.method_strict = true; + // Was shutting down server when suspending on linux: + config.shutdown_on_interrupt = false; config }; From 81df97a737294f927162e2295a957118351caa85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sat, 18 Jun 2016 15:11:10 +0200 Subject: [PATCH 073/239] Fixing warnings (#1321) --- ethcore/src/state.rs | 6 +++--- ethcore/src/tests/client.rs | 1 + ethcore/src/tests/helpers.rs | 4 ++-- sync/src/chain.rs | 2 +- sync/src/lib.rs | 5 ++--- util/src/network/host.rs | 6 +++--- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index dc9ca582c..bdf754f3a 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -229,11 +229,11 @@ impl State { // collect all the addresses which have changed. let addresses = self.cache.borrow().iter().map(|(addr, _)| addr.clone()).collect::>(); - for a in addresses.iter() { - if self.code(a).map(|c| c.sha3() == broken_dao).unwrap_or(false) { + for a in &addresses { + if self.code(a).map_or(false, |c| c.sha3() == broken_dao) { // Figure out if the balance has been reduced. let maybe_original = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR).get(&a).map(Account::from_rlp); - if maybe_original.map(|original| *original.balance() > self.balance(a)).unwrap_or(false) { + if maybe_original.map_or(false, |original| *original.balance() > self.balance(a)) { return Err(Error::Transaction(TransactionError::DAORescue)); } } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index a5459035e..f2ab62840 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -113,6 +113,7 @@ fn can_collect_garbage() { } #[test] +#[cfg_attr(feature="dev", allow(useless_vec))] fn can_generate_gas_price_statistics() { let client_result = generate_dummy_client_with_data(16, 1, &vec_into![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); let client = client_result.reference(); diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 151d53bba..48ca14bbf 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -140,7 +140,7 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[SignedTransa } pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult> { - generate_dummy_client_with_spec_and_data(Spec::new_test, block_number, 0, &(vec![])) + generate_dummy_client_with_spec_and_data(Spec::new_test, block_number, 0, &[]) } pub fn generate_dummy_client_with_data(block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> GuardedTempResult> { @@ -205,7 +205,7 @@ pub fn generate_dummy_client_with_spec_and_data(get_test_spec: F, block_numbe if let Err(e) = client.import_block(b.rlp_bytes()) { panic!("error importing block which is valid by definition: {:?}", e); } - + last_header = BlockView::new(&b.rlp_bytes()).header(); db = b.drain(); } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index ef05ec9d1..54e4aa7a6 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1170,7 +1170,7 @@ impl ChainSync { .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); + rlp_stream.append_raw(hash_rlp.as_raw(), 1); } Some(rlp_stream.out()) } diff --git a/sync/src/lib.rs b/sync/src/lib.rs index cabc55ace..86f70ff0a 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -124,12 +124,11 @@ impl EthSync { /// Creates and register protocol with the network service pub fn new(config: SyncConfig, chain: Arc) -> Arc { let sync = ChainSync::new(config, chain.deref()); - let sync = Arc::new(EthSync { + Arc::new(EthSync { chain: chain, sync: RwLock::new(sync), io_channel: RwLock::new(IoChannel::disconnected()), - }); - sync + }) } /// Register protocol with the network service diff --git a/util/src/network/host.rs b/util/src/network/host.rs index d859db1c3..aef56fc09 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -252,7 +252,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone /// Check if the session is still active. pub fn is_expired(&self) -> bool { - self.session.as_ref().map(|s| s.lock().unwrap().expired()).unwrap_or(false) + self.session.as_ref().map_or(false, |s| s.lock().unwrap().expired()) } /// Register a new IO timer. 'IoHandler::timeout' will be called with the token. @@ -643,7 +643,7 @@ impl Host where Message: Send + Sync + Clone { } if s.done() { io.deregister_stream(token).unwrap_or_else(|e| debug!("Error deregistering stream: {:?}", e)); - } + } } } @@ -769,7 +769,7 @@ impl Host where Message: Send + Sync + Clone { } if deregister { io.deregister_stream(token).unwrap_or_else(|e| debug!("Error deregistering stream: {:?}", e)); - } + } } fn update_nodes(&self, io: &IoContext>, node_changes: TableUpdates) { From 7208f9f95c2f72ec2b8160d346333f82a9d49a84 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 18 Jun 2016 15:12:13 +0200 Subject: [PATCH 074/239] Unsaved file. Duh. --- sync/src/chain.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 021d8542a..3df478f9f 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -458,21 +458,12 @@ impl ChainSync { // Disable the peer for this syncing round if it gives invalid chain if !valid_response { trace!(target: "sync", "{} Deactivated for invalid headers response", peer_id); -<<<<<<< HEAD self.deactivate_peer(io, peer_id); } if headers.is_empty() && self.state == SyncState::ChainHead { // Peer does not have any new subchain heads, deactivate it nd try with another trace!(target: "sync", "{} Deactivated for no data", peer_id); self.deactivate_peer(io, peer_id); -======= - self.deactivate_peer(io, peer_id); - } - if headers.is_empty() { - // Peer does not have any new subchain heads, deactivate it nd try with another - trace!(target: "sync", "{} Deactivated for no data", peer_id); - self.deactivate_peer(io, peer_id); ->>>>>>> master } match self.state { SyncState::ChainHead => { From 47cd9ff34cdae38abb41b21cbf659a70f4c1cd20 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 18 Jun 2016 15:18:36 +0200 Subject: [PATCH 075/239] Remove code no longer in master :-S --- sync/src/chain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 3df478f9f..25f1eb6a3 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -460,7 +460,7 @@ impl ChainSync { trace!(target: "sync", "{} Deactivated for invalid headers response", peer_id); self.deactivate_peer(io, peer_id); } - if headers.is_empty() && self.state == SyncState::ChainHead { + if headers.is_empty() { // Peer does not have any new subchain heads, deactivate it nd try with another trace!(target: "sync", "{} Deactivated for no data", peer_id); self.deactivate_peer(io, peer_id); From 2b650117060dae9cea1a0573faf73dea6af8cef7 Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Sat, 18 Jun 2016 10:58:28 -0500 Subject: [PATCH 076/239] Use constants for DatabaseConfig (#1318) Closes #1157 --- util/src/journaldb/archivedb.rs | 8 +++----- util/src/journaldb/earlymergedb.rs | 8 +++----- util/src/journaldb/mod.rs | 5 +++++ util/src/journaldb/overlayrecentdb.rs | 8 +++----- util/src/journaldb/refcounteddb.rs | 7 +++---- 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index c6acc1280..e971711e0 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -20,6 +20,7 @@ use common::*; use rlp::*; use hashdb::*; use memorydb::*; +use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, VERSION_KEY}; use super::traits::JournalDB; use kvdb::{Database, DBTransaction, DatabaseConfig}; #[cfg(test)] @@ -38,17 +39,14 @@ pub struct ArchiveDB { latest_era: Option, } -// all keys must be at least 12 bytes -const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ]; -const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ]; const DB_VERSION : u32 = 0x103; impl ArchiveDB { /// Create a new instance from file pub fn new(path: &str) -> ArchiveDB { let opts = DatabaseConfig { - //use 12 bytes as prefix, this must match account_db prefix - prefix_size: Some(12), + // this must match account_db prefix + prefix_size: Some(DB_PREFIX_LEN), max_open_files: 256, }; let backing = Database::open(&opts, path).unwrap_or_else(|e| { diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs index 7cb117447..4d897e3db 100644 --- a/util/src/journaldb/earlymergedb.rs +++ b/util/src/journaldb/earlymergedb.rs @@ -20,6 +20,7 @@ use common::*; use rlp::*; use hashdb::*; use memorydb::*; +use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, VERSION_KEY}; use super::traits::JournalDB; use kvdb::{Database, DBTransaction, DatabaseConfig}; #[cfg(test)] @@ -67,9 +68,6 @@ pub struct EarlyMergeDB { latest_era: Option, } -// all keys must be at least 12 bytes -const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ]; -const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ]; const DB_VERSION : u32 = 0x003; const PADDING : [u8; 10] = [ 0u8; 10 ]; @@ -77,8 +75,8 @@ impl EarlyMergeDB { /// Create a new instance from file pub fn new(path: &str) -> EarlyMergeDB { let opts = DatabaseConfig { - //use 12 bytes as prefix, this must match account_db prefix - prefix_size: Some(12), + // this must match account_db prefix + prefix_size: Some(DB_PREFIX_LEN), max_open_files: 256, }; let backing = Database::open(&opts, path).unwrap_or_else(|e| { diff --git a/util/src/journaldb/mod.rs b/util/src/journaldb/mod.rs index 6e389b3c0..9f242e950 100644 --- a/util/src/journaldb/mod.rs +++ b/util/src/journaldb/mod.rs @@ -79,3 +79,8 @@ pub fn new(path: &str, algorithm: Algorithm) -> Box { Algorithm::RefCounted => Box::new(refcounteddb::RefCountedDB::new(path)), } } + +// all keys must be at least 12 bytes +const DB_PREFIX_LEN : usize = 12; +const LATEST_ERA_KEY : [u8; DB_PREFIX_LEN] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ]; +const VERSION_KEY : [u8; DB_PREFIX_LEN] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ]; diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs index 86d8d5c4d..435dd7880 100644 --- a/util/src/journaldb/overlayrecentdb.rs +++ b/util/src/journaldb/overlayrecentdb.rs @@ -20,6 +20,7 @@ use common::*; use rlp::*; use hashdb::*; use memorydb::*; +use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, VERSION_KEY}; use kvdb::{Database, DBTransaction, DatabaseConfig}; #[cfg(test)] use std::env; @@ -92,9 +93,6 @@ impl Clone for OverlayRecentDB { } } -// all keys must be at least 12 bytes -const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ]; -const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ]; const DB_VERSION : u32 = 0x203; const PADDING : [u8; 10] = [ 0u8; 10 ]; @@ -107,8 +105,8 @@ impl OverlayRecentDB { /// Create a new instance from file pub fn from_prefs(path: &str) -> OverlayRecentDB { let opts = DatabaseConfig { - //use 12 bytes as prefix, this must match account_db prefix - prefix_size: Some(12), + // this must match account_db prefix + prefix_size: Some(DB_PREFIX_LEN), max_open_files: 256, }; let backing = Database::open(&opts, path).unwrap_or_else(|e| { diff --git a/util/src/journaldb/refcounteddb.rs b/util/src/journaldb/refcounteddb.rs index 7f24a729c..3bcb0faaf 100644 --- a/util/src/journaldb/refcounteddb.rs +++ b/util/src/journaldb/refcounteddb.rs @@ -20,6 +20,7 @@ use common::*; use rlp::*; use hashdb::*; use overlaydb::*; +use super::{DB_PREFIX_LEN, LATEST_ERA_KEY, VERSION_KEY}; use super::traits::JournalDB; use kvdb::{Database, DBTransaction, DatabaseConfig}; #[cfg(test)] @@ -40,8 +41,6 @@ pub struct RefCountedDB { removes: Vec, } -const LATEST_ERA_KEY : [u8; 12] = [ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ]; -const VERSION_KEY : [u8; 12] = [ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ]; const DB_VERSION : u32 = 0x200; const PADDING : [u8; 10] = [ 0u8; 10 ]; @@ -49,8 +48,8 @@ impl RefCountedDB { /// Create a new instance given a `backing` database. pub fn new(path: &str) -> RefCountedDB { let opts = DatabaseConfig { - //use 12 bytes as prefix, this must match account_db prefix - prefix_size: Some(12), + // this must match account_db prefix + prefix_size: Some(DB_PREFIX_LEN), max_open_files: 256, }; let backing = Database::open(&opts, path).unwrap_or_else(|e| { From 2582253f95c5e33a51153604b43f4c207e0df7ff Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 18 Jun 2016 20:26:44 +0200 Subject: [PATCH 077/239] Install trigger for DAO-rescue soft-fork. Soft-fork should only be primed to trigger if the gas-limit of block #1760000 is at most 4,000,000. To accomplish this we pass in the gas limit of that block to EnvInfo so it can inform Schedule. This gets marshalled through `OpenBlock`/`ClosedBlock` and the `enact` functions much like `last_hashes`. `block.rs`'s `env_info()` takes care to ensure that if the current block happens to be #1760000, then we populate with the current `gas_limit`. --- ethcore/src/basic_authority.rs | 5 ++- ethcore/src/block.rs | 76 ++++++++++++++++++++++++++-------- ethcore/src/client/client.rs | 4 +- ethcore/src/client/mod.rs | 9 +++- ethcore/src/env_info.rs | 5 +++ ethcore/src/ethereum/ethash.rs | 12 +++--- ethcore/src/externalities.rs | 3 +- ethcore/src/miner/miner.rs | 1 + ethcore/src/tests/helpers.rs | 1 + 9 files changed, 89 insertions(+), 27 deletions(-) diff --git a/ethcore/src/basic_authority.rs b/ethcore/src/basic_authority.rs index c732ce711..c96179574 100644 --- a/ethcore/src/basic_authority.rs +++ b/ethcore/src/basic_authority.rs @@ -215,8 +215,9 @@ mod tests { timestamp: 0, difficulty: 0.into(), last_hashes: vec![], + dao_rescue_block_gas_limit: None, gas_used: 0.into(), - gas_limit: 0.into() + gas_limit: 0.into(), }); assert!(schedule.stack_limit > 0); @@ -278,7 +279,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, addr.clone(), 3141562.into(), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, addr.clone(), 3141562.into(), vec![]).unwrap(); let b = b.close_and_lock(); let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap(); diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 74f54a057..ff05b5af1 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -177,6 +177,7 @@ pub struct OpenBlock<'x> { engine: &'x Engine, vm_factory: &'x EvmFactory, last_hashes: LastHashes, + dao_rescue_block_gas_limit: Option, } /// Just like `OpenBlock`, except that we've applied `Engine::on_close_block`, finished up the non-seal header fields, @@ -188,6 +189,7 @@ pub struct ClosedBlock { block: ExecutedBlock, uncle_bytes: Bytes, last_hashes: LastHashes, + dao_rescue_block_gas_limit: Option, unclosed_state: State, } @@ -198,7 +200,6 @@ pub struct ClosedBlock { pub struct LockedBlock { block: ExecutedBlock, uncle_bytes: Bytes, - last_hashes: LastHashes, } /// A block that has a valid seal. @@ -219,9 +220,10 @@ impl<'x> OpenBlock<'x> { db: Box, parent: &Header, last_hashes: LastHashes, + dao_rescue_block_gas_limit: Option, author: Address, gas_floor_target: U256, - extra_data: Bytes + extra_data: Bytes, ) -> Result { let state = try!(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce())); let mut r = OpenBlock { @@ -229,6 +231,7 @@ impl<'x> OpenBlock<'x> { engine: engine, vm_factory: vm_factory, last_hashes: last_hashes, + dao_rescue_block_gas_limit: dao_rescue_block_gas_limit, }; r.block.base.header.parent_hash = parent.hash(); @@ -293,6 +296,7 @@ impl<'x> OpenBlock<'x> { last_hashes: self.last_hashes.clone(), // TODO: should be a reference. gas_used: self.block.receipts.last().map_or(U256::zero(), |r| r.gas_used), gas_limit: self.block.base.header.gas_limit.clone(), + dao_rescue_block_gas_limit: if self.block.base.header.number == 1760000 { Some(self.block.base.header.gas_limit) } else { self.dao_rescue_block_gas_limit }, } } @@ -339,6 +343,7 @@ impl<'x> OpenBlock<'x> { block: s.block, uncle_bytes: uncle_bytes, last_hashes: s.last_hashes, + dao_rescue_block_gas_limit: s.dao_rescue_block_gas_limit, unclosed_state: unclosed_state, } } @@ -360,7 +365,6 @@ impl<'x> OpenBlock<'x> { LockedBlock { block: s.block, uncle_bytes: uncle_bytes, - last_hashes: s.last_hashes, } } } @@ -386,7 +390,6 @@ impl ClosedBlock { LockedBlock { block: self.block, uncle_bytes: self.uncle_bytes, - last_hashes: self.last_hashes, } } @@ -400,6 +403,7 @@ impl ClosedBlock { engine: engine, vm_factory: vm_factory, last_hashes: self.last_hashes, + dao_rescue_block_gas_limit: self.dao_rescue_block_gas_limit, } } } @@ -456,7 +460,18 @@ impl IsBlock for SealedBlock { /// Enact the block given by block header, transactions and uncles #[cfg_attr(feature="dev", allow(too_many_arguments))] -pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes, vm_factory: &EvmFactory) -> Result { +pub fn enact( + header: &Header, + transactions: &[SignedTransaction], + uncles: &[Header], + engine: &Engine, + tracing: bool, + db: Box, + parent: &Header, + last_hashes: LastHashes, + dao_rescue_block_gas_limit: Option, + vm_factory: &EvmFactory +) -> Result { { if ::log::max_log_level() >= ::log::LogLevel::Trace { let s = try!(State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce())); @@ -464,7 +479,7 @@ pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Head } } - let mut b = try!(OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, header.author().clone(), 3141562.into(), header.extra_data().clone())); + let mut b = try!(OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, header.author().clone(), 3141562.into(), header.extra_data().clone())); b.set_difficulty(*header.difficulty()); b.set_gas_limit(*header.gas_limit()); b.set_timestamp(header.timestamp()); @@ -474,22 +489,49 @@ pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Head } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header -pub fn enact_bytes(block_bytes: &[u8], engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes, vm_factory: &EvmFactory) -> Result { +pub fn enact_bytes( + block_bytes: &[u8], + engine: &Engine, + tracing: bool, + db: Box, + parent: &Header, + last_hashes: LastHashes, + dao_rescue_block_gas_limit: Option, + vm_factory: &EvmFactory +) -> Result { let block = BlockView::new(block_bytes); let header = block.header(); - enact(&header, &block.transactions(), &block.uncles(), engine, tracing, db, parent, last_hashes, vm_factory) + enact(&header, &block.transactions(), &block.uncles(), engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory) } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header -pub fn enact_verified(block: &PreverifiedBlock, engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes, vm_factory: &EvmFactory) -> Result { +pub fn enact_verified( + block: &PreverifiedBlock, + engine: &Engine, + tracing: bool, + db: Box, + parent: &Header, + last_hashes: LastHashes, + dao_rescue_block_gas_limit: Option, + vm_factory: &EvmFactory +) -> Result { let view = BlockView::new(&block.bytes); - enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes, vm_factory) + enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory) } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards -pub fn enact_and_seal(block_bytes: &[u8], engine: &Engine, tracing: bool, db: Box, parent: &Header, last_hashes: LastHashes, vm_factory: &EvmFactory) -> Result { +pub fn enact_and_seal( + block_bytes: &[u8], + engine: &Engine, + tracing: bool, + db: Box, + parent: &Header, + last_hashes: LastHashes, + dao_rescue_block_gas_limit: Option, + vm_factory: &EvmFactory +) -> Result { let header = BlockView::new(block_bytes).header_view(); - Ok(try!(try!(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, vm_factory)).seal(engine, header.seal()))) + Ok(try!(try!(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, vm_factory)).seal(engine, header.seal()))) } #[cfg(test)] @@ -509,7 +551,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), 3141562.into(), vec![]).unwrap(); let b = b.close_and_lock(); let _ = b.seal(engine.deref(), vec![]); } @@ -525,7 +567,7 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), 3141562.into(), vec![]).unwrap() + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), 3141562.into(), vec![]).unwrap() .close_and_lock().seal(engine.deref(), vec![]).unwrap(); let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); @@ -533,7 +575,7 @@ mod tests { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); - let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], &Default::default()).unwrap(); + let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], None, &Default::default()).unwrap(); assert_eq!(e.rlp_bytes(), orig_bytes); @@ -553,7 +595,7 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let vm_factory = Default::default(); - let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), 3141562.into(), vec![]).unwrap(); + let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), 3141562.into(), vec![]).unwrap(); let mut uncle1_header = Header::new(); uncle1_header.extra_data = b"uncle1".to_vec(); let mut uncle2_header = Header::new(); @@ -568,7 +610,7 @@ mod tests { let mut db_result = get_temp_journal_db(); let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); - let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], &Default::default()).unwrap(); + let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], None, &Default::default()).unwrap(); let bytes = e.rlp_bytes(); assert_eq!(bytes, orig_bytes); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 85a3d693d..3264ce266 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -220,7 +220,7 @@ impl Client where V: Verifier { let last_hashes = self.build_last_hashes(header.parent_hash.clone()); let db = self.state_db.lock().unwrap().boxed_clone(); - let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, &self.vm_factory); + let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, self.dao_rescue_block_gas_limit(), &self.vm_factory); if let Err(e) = enact_result { warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); @@ -462,6 +462,7 @@ impl BlockChainClient for Client where V: Verifier { last_hashes: last_hashes, gas_used: U256::zero(), gas_limit: U256::max_value(), + dao_rescue_block_gas_limit: self.dao_rescue_block_gas_limit(), }; // that's just a copy of the state. let mut state = self.state(); @@ -767,6 +768,7 @@ impl MiningBlockChainClient for Client where V: Verifier { self.state_db.lock().unwrap().boxed_clone(), &self.chain.block_header(&h).expect("h is best block hash: so it's header must exist: qed"), self.build_last_hashes(h.clone()), + self.dao_rescue_block_gas_limit(), author, gas_floor_target, extra_data, diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 3fec68815..fd74f7c47 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -42,7 +42,7 @@ use header::{BlockNumber, Header}; use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; -use views::BlockView; +use views::{HeaderView, BlockView}; use error::{ImportResult, ExecutionError}; use receipt::LocalizedReceipt; use trace::LocalizedTrace; @@ -221,6 +221,13 @@ pub trait BlockChainClient : Sync + Send { Err(()) } } + + + /// Get `Some` gas limit of block 1_760_000, or `None` if chain is not yet that long. + fn dao_rescue_block_gas_limit(&self) -> Option { + self.block_header(BlockID::Number(1_760_000)) + .map(|header| HeaderView::new(&header).gas_limit()) + } } /// Extended client interface used for mining diff --git a/ethcore/src/env_info.rs b/ethcore/src/env_info.rs index e6d15cee6..a38a31ff7 100644 --- a/ethcore/src/env_info.rs +++ b/ethcore/src/env_info.rs @@ -39,6 +39,9 @@ pub struct EnvInfo { pub last_hashes: LastHashes, /// The gas used. pub gas_used: U256, + + /// Block gas limit at DAO rescue block #1760000 or None if not yet there. + pub dao_rescue_block_gas_limit: Option, } impl Default for EnvInfo { @@ -51,6 +54,7 @@ impl Default for EnvInfo { gas_limit: 0.into(), last_hashes: vec![], gas_used: 0.into(), + dao_rescue_block_gas_limit: None, } } } @@ -66,6 +70,7 @@ impl From for EnvInfo { timestamp: e.timestamp.into(), last_hashes: (1..cmp::min(number + 1, 257)).map(|i| format!("{}", number - i).as_bytes().sha3()).collect(), gas_used: U256::zero(), + dao_rescue_block_gas_limit: None, } } } diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index d89499872..f3cb95b09 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -103,7 +103,7 @@ impl Engine for Ethash { } else { let mut s = Schedule::new_homestead(); // TODO: make dependent on gaslimit > 4000000 of block 1760000. - s.block_dao_transactions = env_info.number >= 1760000; + s.block_dao_transactions = env_info.dao_rescue_block_gas_limit.map(|x| x <= 4_000_000.into()).unwrap_or(false); s } } @@ -319,7 +319,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), 3141562.into(), vec![]).unwrap(); let b = b.close(); assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap()); } @@ -334,7 +334,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, Address::zero(), 3141562.into(), vec![]).unwrap(); + let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), 3141562.into(), vec![]).unwrap(); let mut uncle = Header::new(); let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106"); uncle.author = uncle_author.clone(); @@ -362,7 +362,8 @@ mod tests { difficulty: 0.into(), last_hashes: vec![], gas_used: 0.into(), - gas_limit: 0.into() + gas_limit: 0.into(), + dao_rescue_block_gas_limit: None, }); assert!(schedule.stack_limit > 0); @@ -374,7 +375,8 @@ mod tests { difficulty: 0.into(), last_hashes: vec![], gas_used: 0.into(), - gas_limit: 0.into() + gas_limit: 0.into(), + dao_rescue_block_gas_limit: None, }); assert!(!schedule.have_delegate_call); diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index 66509440a..80941c4b4 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -318,7 +318,8 @@ mod tests { difficulty: 0.into(), last_hashes: vec![], gas_used: 0.into(), - gas_limit: 0.into() + gas_limit: 0.into(), + dao_rescue_block_gas_limit: None, } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index ec232d238..c488f9de1 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -266,6 +266,7 @@ impl MinerService for Miner { last_hashes: last_hashes, gas_used: U256::zero(), gas_limit: U256::max_value(), + dao_rescue_block_gas_limit: chain.dao_rescue_block_gas_limit(), }; // that's just a copy of the state. let mut state = block.state().clone(); diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 48ca14bbf..3384bb2ff 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -179,6 +179,7 @@ pub fn generate_dummy_client_with_spec_and_data(get_test_spec: F, block_numbe db, &last_header, last_hashes.clone(), + None, author.clone(), 3141562.into(), vec![] From d915eae7f7df4cd60b697a1d083b915d045a8e39 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 18 Jun 2016 20:54:44 +0200 Subject: [PATCH 078/239] Remove comment. --- ethcore/src/ethereum/ethash.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index f3cb95b09..ee021b2df 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -102,7 +102,7 @@ impl Engine for Ethash { Schedule::new_frontier() } else { let mut s = Schedule::new_homestead(); - // TODO: make dependent on gaslimit > 4000000 of block 1760000. + // TODO: make dependent on gaslimit > 4000000 of block 1760000. s.block_dao_transactions = env_info.dao_rescue_block_gas_limit.map(|x| x <= 4_000_000.into()).unwrap_or(false); s } From 026bfd6741bdca63ad14000f55c67086dad254d6 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 19 Jun 2016 02:09:17 +0200 Subject: [PATCH 079/239] fixed incomplete merge --- ethcore/src/ethereum/ethash.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 22df30399..4c92d1083 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -102,7 +102,7 @@ impl Engine for Ethash { Schedule::new_frontier() } else { let mut s = Schedule::new_homestead(); - s.block_dao_transactions = env_info.dao_rescue_block_gas_limit.map(|x| x <= 4_000_000.into()).unwrap_or(false); + s.reject_dao_transactions = env_info.dao_rescue_block_gas_limit.map(|x| x <= 4_000_000.into()).unwrap_or(false); s } } From 46d588dcaed45a537fca28150d0803b5e4d76e66 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 19 Jun 2016 12:28:24 +0200 Subject: [PATCH 080/239] CLI option and colour. --- parity/cli.rs | 3 +++ parity/main.rs | 7 +++++++ parity/signer.rs | 5 +++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 6fe38224a..94eaaed13 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -109,6 +109,8 @@ API and Console Options: [default: 8180]. --signer-path PATH Specify directory where Signer UIs tokens should be stored. [default: $HOME/.parity/signer] + --no-token By default a new system UI security token will be + output on start up. This will prevent it. Sealing/Mining Options: --force-sealing Force the node to author new blocks as if it were @@ -255,6 +257,7 @@ pub struct Args { pub flag_signer: bool, pub flag_signer_port: u16, pub flag_signer_path: String, + pub flag_no_token: bool, pub flag_force_sealing: bool, pub flag_author: String, pub flag_usd_per_tx: String, diff --git a/parity/main.rs b/parity/main.rs index 973b1174f..6ac07741c 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -186,6 +186,13 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) let net_settings = conf.net_settings(&spec); let sync_config = conf.sync_config(&spec); + // Create and display a new token for UIs. + if conf.args.flag_signer && !conf.args.flag_no_token { + new_token(conf.directories().signer).unwrap_or_else(|e| { + die!("Error generating token: {:?}", e) + }); + } + // Secret Store let account_service = Arc::new(conf.account_service()); diff --git a/parity/signer.rs b/parity/signer.rs index 3c8dceb6b..e280b0441 100644 --- a/parity/signer.rs +++ b/parity/signer.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +extern crate ansi_term; +use self::ansi_term::Colour::Red; use std::io; use std::path::PathBuf; use std::sync::Arc; @@ -65,8 +67,7 @@ pub fn new_token(path: String) -> io::Result<()> { let mut codes = try!(signer::AuthCodes::from_file(&path)); let code = try!(codes.generate_new()); try!(codes.to_file(&path)); - println!("New token has been generated. Copy the code below to your Signer UI:"); - println!("{}", code); + println!("This key code will authorise your System Signer UI: {}", White.bold().paint(code)); Ok(()) } From 7430cf72e27deca1eed047527475398e57e16c61 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 19 Jun 2016 12:29:39 +0200 Subject: [PATCH 081/239] Minor typo. --- parity/signer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/signer.rs b/parity/signer.rs index e280b0441..f15d8c97b 100644 --- a/parity/signer.rs +++ b/parity/signer.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . extern crate ansi_term; -use self::ansi_term::Colour::Red; +use self::ansi_term::Colour::White; use std::io; use std::path::PathBuf; use std::sync::Arc; From 8fad728e9b277899ee7895c834302c52151a1ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 19 Jun 2016 12:33:50 +0200 Subject: [PATCH 082/239] Fixing locks order (#1328) --- ethcore/src/miner/miner.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index ec232d238..ef59de1ec 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -31,13 +31,14 @@ use miner::{MinerService, MinerStatus, TransactionQueue, AccountDetails, Transac /// Keeps track of transactions using priority queue and holds currently mined block. pub struct Miner { + // NOTE [ToDr] When locking always lock in this order! transaction_queue: Mutex, + sealing_work: Mutex>, // for sealing... force_sealing: bool, sealing_enabled: AtomicBool, sealing_block_last_request: Mutex, - sealing_work: Mutex>, gas_floor_target: RwLock, author: RwLock
, extra_data: RwLock, @@ -424,20 +425,20 @@ impl MinerService for Miner { } fn pending_transactions_hashes(&self) -> Vec { + let queue = self.transaction_queue.lock().unwrap(); match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { (true, Some(pending)) => pending.transactions().iter().map(|t| t.hash()).collect(), _ => { - let queue = self.transaction_queue.lock().unwrap(); queue.pending_hashes() } } } fn transaction(&self, hash: &H256) -> Option { + let queue = self.transaction_queue.lock().unwrap(); match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { (true, Some(pending)) => pending.transactions().iter().find(|t| &t.hash() == hash).cloned(), _ => { - let queue = self.transaction_queue.lock().unwrap(); queue.find(hash) } } @@ -449,11 +450,11 @@ impl MinerService for Miner { } fn pending_transactions(&self) -> Vec { + let queue = self.transaction_queue.lock().unwrap(); // TODO: should only use the sealing_work when it's current (it could be an old block) match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { (true, Some(pending)) => pending.transactions().clone(), _ => { - let queue = self.transaction_queue.lock().unwrap(); queue.top_transactions() } } From 2245baaaab63f34b33720e78778f3a82c57ee880 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 19 Jun 2016 13:20:14 +0200 Subject: [PATCH 083/239] Provide CLI options to disable aspects of soft-fork. Soft-fork will remain default behaviour, but you can now disable either the whole mechanism (you'll lose money if you mine with this when the majority network doesn't) or just vote against it but otherwise go with the flow. --- ethcore/res/ethereum/frontier.json | 3 +- ethcore/res/ethereum/frontier_dao_rescue.json | 26729 ++++++++++++++++ ethcore/src/ethereum/ethash.rs | 7 +- ethcore/src/ethereum/mod.rs | 9 +- json/src/spec/ethash.rs | 8 +- parity/cli.rs | 12 +- parity/configuration.rs | 16 +- sync/src/lib.rs | 4 +- 8 files changed, 26774 insertions(+), 14 deletions(-) create mode 100644 ethcore/res/ethereum/frontier_dao_rescue.json diff --git a/ethcore/res/ethereum/frontier.json b/ethcore/res/ethereum/frontier.json index a57ad8ed8..159fe6d44 100644 --- a/ethcore/res/ethereum/frontier.json +++ b/ethcore/res/ethereum/frontier.json @@ -9,7 +9,8 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "frontierCompatibilityModeLimit": "0x118c30" + "frontierCompatibilityModeLimit": "0x118c30", + "daoRescueSoftFork": false } } }, diff --git a/ethcore/res/ethereum/frontier_dao_rescue.json b/ethcore/res/ethereum/frontier_dao_rescue.json new file mode 100644 index 000000000..4ceff14b7 --- /dev/null +++ b/ethcore/res/ethereum/frontier_dao_rescue.json @@ -0,0 +1,26729 @@ +{ + "name": "Frontier/Homestead", + "engine": { + "Ethash": { + "params": { + "gasLimitBoundDivisor": "0x0400", + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "frontierCompatibilityModeLimit": "0x118c30", + "daoRescueSoftFork": true + } + } + }, + "params": { + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x1" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388", + "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" + }, + "nodes": [ + "enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303", + "enode://de471bccee3d042261d52e9bff31458daecc406142b401d4cd848f677479f73104b9fdeb090af9583d3391b7f10cb2ba9e26865dd5fca4fcdc0fb1e3b723c786@54.94.239.50:30303", + "enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303", + "enode://248f12bc8b18d5289358085520ac78cd8076485211e6d96ab0bc93d6cd25442db0ce3a937dc404f64f207b0b9aed50e25e98ce32af5ac7cb321ff285b97de485@zero.parity.io: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 } } } }, + "3282791d6fd713f1e94f4bfd565eaa78b3a0599d": { + "balance": "1337000000000000000000" + }, + "17961d633bcf20a7b029a7d94b7df4da2ec5427f": { + "balance": "229427000000000000000" + }, + "493a67fe23decc63b10dda75f3287695a81bd5ab": { + "balance": "880000000000000000000" + }, + "01fb8ec12425a04f813e46c54c05748ca6b29aa9": { + "balance": "259800000000000000000" + }, + "d2a030ac8952325f9e1db378a71485a24e1b07b2": { + "balance": "2000000000000000000000" + }, + "77a34907f305a54c85db09c363fde3c47e6ae21f": { + "balance": "985000000000000000000" + }, + "391a77405c09a72b5e8436237aaaf95d68da1709": { + "balance": "49082000000000000000" + }, + "00aada25ea2286709abb422d41923fd380cd04c7": { + "balance": "650100000000000000000" + }, + "acc46a2a555c74ded4a2bd094e821b97843b40c0": { + "balance": "1940000000000000000000" + }, + "de07fb5b7a464e3ba7fbe09e9acb271af5338c58": { + "balance": "50000000000000000000" + }, + "4c696be99f3a690440c3436a59a7d7e937d6ba0d": { + "balance": "3460000000000000000000" + }, + "fa33553285a973719a0d5f956ff861b2d89ed304": { + "balance": "20000000000000000000" + }, + "67cfda6e70bf7657d39059b59790e5145afdbe61": { + "balance": "646000000000000000000" + }, + "a321091d3018064279db399d2b2a88a6f440ae24": { + "balance": "3200000000000000000000" + }, + "fb3fa1ac08aba9cc3bf0fe9d483820688f65b410": { + "balance": "30000000000000000000000" + }, + "6715c14035fb57bb3d667f7b707498c41074b855": { + "balance": "700000000000000000000" + }, + "d4344f7d5cad65d17e5c2d0e7323943d6f62fe92": { + "balance": "267400000000000000000" + }, + "a3294626ec2984c43b43da4d5d8e4669b11d4b59": { + "balance": "1008000000000000000000" + }, + "656018584130db83ab0591a8128d9381666a8d0e": { + "balance": "63960000000000000000" + }, + "0fa010ce0c731d3b628e36b91f571300e49dbeab": { + "balance": "999800000000000000000" + }, + "3098b65db93ecacaf7353c48808390a223d57684": { + "balance": "449965000000000000000" + }, + "ae635bf73831119d2d29c0d04ff8f8d8d0a57a46": { + "balance": "1337000000000000000000" + }, + "0f7515ff0e808f695e0c20485ff96ed2f7b79310": { + "balance": "1000169000000000000000" + }, + "8b30c04098d7a7e6420c357ea7bfa49bac9a8a18": { + "balance": "8000200000000000000000" + }, + "64dba2d6615b8bd7571836dc75bc79d314f5ecee": { + "balance": "10000000000000000000000" + }, + "e7912d4cf4562c573ddc5b71e37310e378ef86c9": { + "balance": "394000000000000000000" + }, + "a4da34450d22ec0ffcede0004b02f7872ee0b73a": { + "balance": "93342000000000000000" + }, + "34437d1465640b136cb5841c3f934f9ba0b7097d": { + "balance": "173000000000000000000" + }, + "c652871d192422c6bc235fa063b44a7e1d43e385": { + "balance": "155000000000000000000" + }, + "a8a708e84f82db86a35502193b4c6ee9a76ebe8f": { + "balance": "1015200000000000000000" + }, + "5c3f567faff7bad1b5120022e8cbcaa82b4917b3": { + "balance": "2000000000000000000000" + }, + "dbc1d0ee2bab531140de137722cd36bdb4e47194": { + "balance": "200000000000000000000" + }, + "f59dab1bf8df11327e61f9b7a14b563a96ec3554": { + "balance": "6000000000000000000000" + }, + "456f8d746682b224679349064d1b368c7c05b176": { + "balance": "3700000000000000000000" + }, + "5f13154631466dcb1353c890932a7c97e0878e90": { + "balance": "6000000000000000000000" + }, + "f4b1626e24f30bcad9273c527fcc714b5d007b8f": { + "balance": "200000000000000000000" + }, + "a8db0b9b201453333c757f6ad9bcb555c02da93b": { + "balance": "2199970000000000000000" + }, + "a0fc7e53c5ebd27a2abdac45261f84ab3b51aefb": { + "balance": "3008250000000000000000" + }, + "1b636b7a496f044d7359596e353a104616436f6b": { + "balance": "360354000000000000000" + }, + "74bce9ec38362d6c94ccac26d5c0e13a8b3b1d40": { + "balance": "999954000000000000000" + }, + "9834682180b982d166badb9d9d1d9bbf016d87ee": { + "balance": "2000000000000000000000" + }, + "1e6e0153fc161bc05e656bbb144c7187bf4fe84d": { + "balance": "2000000000000000000000" + }, + "989c0ccff654da03aeb11af701054561d6297e1d": { + "balance": "4000000000000000000000" + }, + "78a1e254409fb1b55a7cb4dd8eba3b30c8bad9ef": { + "balance": "100000000000000000000" + }, + "9ef1896b007c32a15114fb89d73dbd47f9122b69": { + "balance": "4000000000000000000000" + }, + "33320dd90f2baa110dd334872a998f148426453c": { + "balance": "999972000000000000000" + }, + "e72e1d335cc29a96b9b1c02f003a16d971e90b9d": { + "balance": "1580000000000000000000" + }, + "0921605f99164e3bcc28f31caece78973182561d": { + "balance": "793744000000000000000" + }, + "fc00a420a36107dfd5f495128a5fe5abb2db0f34": { + "balance": "5960000000000000000000" + }, + "dfcbdf09454e1a5e4a40d3eef7c5cf1cd3de9486": { + "balance": "4000000000000000000000" + }, + "646e043d0597a664948fbb0dc15475a3a4f3a6ed": { + "balance": "20000000000000000000" + }, + "79aeb34566b974c35a5881dec020927da7df5d25": { + "balance": "2000000000000000000000" + }, + "dbadc61ed5f0460a7f18e51b2fb2614d9264a0e0": { + "balance": "40000000000000000000" + }, + "97b91efe7350c2d57e7e406bab18f3617bcde14a": { + "balance": "9999980000000000000000" + }, + "8398e07ebcb4f75ff2116de77c1c2a99f303a4cf": { + "balance": "500000000000000000000" + }, + "f02796295101674288c1d93467053d042219b794": { + "balance": "740000000000000000000" + }, + "f4ed848ec961739c2c7e352f435ba70a7cd5db38": { + "balance": "1970000000000000000000" + }, + "82485728d0e281563758c75ab27ed9e882a0002d": { + "balance": "147000000000000000000" + }, + "427ec668ac9404e895cc861511d1620a4912be98": { + "balance": "40000000000000000000000" + }, + "1bbc199e586790be87afedc849c04726745c5d7b": { + "balance": "4000000000000000000000" + }, + "10d945334ecde47beb9ca3816c173dfbbd0b5333": { + "balance": "1400000000000000000000" + }, + "1dcebcb7656df5dcaa3368a055d22f9ed6cdd940": { + "balance": "499800000000000000000" + }, + "2ac1f8d7bf721f3cfe74d20fea9b87a28aaa982c": { + "balance": "161000000000000000000" + }, + "0a47ad9059a249fc936b2662353da6905f75c2b9": { + "balance": "2000000000000000000000" + }, + "768498934e37e905f1d0e77b44b574bcf3ec4ae8": { + "balance": "20000000000000000000000" + }, + "f46b6b9c7cb552829c1d3dfd8ffb11aabae782f6": { + "balance": "21000000000000000000" + }, + "7aea25d42b2612286e99c53697c6bc4100e2dbbf": { + "balance": "2000000000000000000000" + }, + "af3615c789d0b1152ad4db25fe5dcf222804cf62": { + "balance": "1000000000000000000000" + }, + "92e6581e1da1f9b846e09347333dc818e2d2ac66": { + "balance": "3640000000000000000000" + }, + "240305727313d01e73542c775ff59d11cd35f819": { + "balance": "5931229000000000000000" + }, + "b95cfda8465ba9c2661b249fc3ab661bdfa35ff0": { + "balance": "318949000000000000000" + }, + "1b0d076817e8d68ee2df4e1da1c1142d198c4435": { + "balance": "1550000000000000000000" + }, + "93c2e64e5de5589ed25006e843196ee9b1cf0b3e": { + "balance": "1670000000000000000000" + }, + "0e2e504a2d1122b5a9feee5cb1451bf4c2ace87b": { + "balance": "3940000000000000000000" + }, + "22b96ab2cad55db100b53001f9e4db378104c807": { + "balance": "10000000000000000000000" + }, + "a927d48bb6cb814bc609cbcaa9151f5d459a27e1": { + "balance": "271600000000000000000" + }, + "5cbd8daf27ddf704cdd0d909a789ba36ed4f37b2": { + "balance": "13400000000000000000" + }, + "9adbd3bc7b0afc05d1d2eda49ff863939c48db46": { + "balance": "199955000000000000000" + }, + "ac7e03702723cb16ee27e22dd0b815dc2d5cae9f": { + "balance": "16000000000000000000000" + }, + "1e210e7047886daa52aaf70f4b991dac68e3025e": { + "balance": "200000000000000000000" + }, + "c98048687f2bfcc9bd90ed18736c57edd352b65d": { + "balance": "1000000000000000000000" + }, + "81c18c2a238ddc4cba230a072dd7dc101e620273": { + "balance": "1337000000000000000000" + }, + "cb3d766c983f192bcecac70f4ee03dd9ff714d51": { + "balance": "100000000000000000000" + }, + "44a63d18424587b9b307bfc3c364ae10cd04c713": { + "balance": "20000000000000000000" + }, + "4ab2d34f04834fbf7479649cab923d2c4725c553": { + "balance": "3520000000000000000000" + }, + "b834acf3015322c58382eeb2b79638906e88b6de": { + "balance": "24000000000000000000000" + }, + "7d551397f79a2988b064afd0efebee802c7721bc": { + "balance": "39400000000000000000000" + }, + "b537d36a70eeb8d3e5c80de815225c1158cb92c4": { + "balance": "1500000000000000000000" + }, + "805ce51297a0793b812067f017b3e7b2df9bb1f9": { + "balance": "100000000000000000000" + }, + "085ba65febe23eefc2c802666ab1262382cfc494": { + "balance": "400000000000000000000" + }, + "b1c0d08b36e184f9952a4037e3e53a667d070a4e": { + "balance": "1000000000000000000000" + }, + "83fe5a1b328bae440711beaf6aad6026eda6d220": { + "balance": "20000000000000000000000" + }, + "7fd679e5fb0da2a5d116194dcb508318edc580f3": { + "balance": "6560000000000000000000" + }, + "41ad369f758fef38a19aa3149379832c818ef2a0": { + "balance": "1000060000000000000000" + }, + "6d846dc12657e91af25008519c3e857f51707dd6": { + "balance": "4590000000000000000000" + }, + "c02d6eadeacf1b78b3ca85035c637bb1ce01f490": { + "balance": "4000000000000000000000" + }, + "826eb7cd7319b82dd07a1f3b409071d96e39677f": { + "balance": "1000000000000000000000" + }, + "4ac9905a4cb6ab1cfd62546ee5917300b87c4fde": { + "balance": "1015200000000000000000" + }, + "cf6e52e6b77480b1867efec6446d9fc3cc3577e8": { + "balance": "222010000000000000000" + }, + "2476b2bb751ce748e1a4c4ff7b230be0c15d2245": { + "balance": "4000000000000000000000" + }, + "1a505e62a74e87e577473e4f3afa16bedd3cfa52": { + "balance": "500000000000000000000" + }, + "21d02705f3f64905d80ed9147913ea8c7307d695": { + "balance": "1363740000000000000000" + }, + "7b1daf14891b8a1e1bd429d8b36b9a4aa1d9afbf": { + "balance": "500000000000000000000" + }, + "5338ef70eac9dd9af5a0503b5efad1039e67e725": { + "balance": "2674000000000000000000" + }, + "50ca86b5eb1d01874df8e5f34945d49c6c1ab848": { + "balance": "1000000000000000000000" + }, + "f3cc8bcb559465f81bfe583bd7ab0a2306453b9e": { + "balance": "20000000000000000000000" + }, + "5c323457e187761a8276e359b7b7af3f3b6e3df6": { + "balance": "10000000000000000000000" + }, + "4d82d7700c123bb919419bbaf046799c6b0e2c66": { + "balance": "20000000000000000000000" + }, + "8a66abbc2d30ce21a833b0db8e561d5105e0a72c": { + "balance": "699958000000000000000" + }, + "2ae53866fc2d14d572ab73b4a065a1188267f527": { + "balance": "8000000000000000000000" + }, + "9af5c9894c33e42c2c518e3ac670ea9505d1b53e": { + "balance": "18200000000000000000" + }, + "cba25c7a503cc8e0d04971ca05c762f9b762b48b": { + "balance": "500000000000000000000" + }, + "fda3042819af3e662900e1b92b4358eda6e92590": { + "balance": "118200000000000000000000" + }, + "9bd7c38a4210304a4d653edeff1b3ce45fce7843": { + "balance": "282000000000000000000" + }, + "edc22fb92c638e1e21ff5cf039daa6e734dafb29": { + "balance": "298000000000000000000" + }, + "a1f193a0592f1feb9fdfc90aa813784eb80471c9": { + "balance": "1400000000000000000000" + }, + "e97fde0b67716325cf0ecce8a191a3761b2c791d": { + "balance": "1004700000000000000000" + }, + "110237cf9117e767922fc4a1b78d7964da82df20": { + "balance": "3940000000000000000000" + }, + "e32f95766d57b5cd4b173289d6876f9e64558194": { + "balance": "100000000000000000000" + }, + "f2d59c8923759073d6f415aaf8eb065ff2f3b685": { + "balance": "7880000000000000000000" + }, + "c53d79f7cb9b70952fd30fce58d54b9f0b59f647": { + "balance": "5089200000000000000000" + }, + "9eb281c32719c40fdb3e216db0f37fbc73a026b7": { + "balance": "20000000000000000000" + }, + "2d6511fd7a3800b26854c7ec39c0dcb5f4c4e8e8": { + "balance": "399910000000000000000" + }, + "61ba87c77e9b596de7ba0e326fddfeec2163ef66": { + "balance": "200000000000000000000" + }, + "de1121829c9a08284087a43fbd2fc1142a3233b4": { + "balance": "1000000000000000000000" + }, + "22a25812ab56dcc423175ed1d8adacce33cd1810": { + "balance": "1850000000000000000000" + }, + "518cef27b10582b6d14f69483ddaa0dd3c87bb5c": { + "balance": "600000000000000000000" + }, + "59161749fedcf1c721f2202d13ade2abcf460b3d": { + "balance": "2000000000000000000000" + }, + "3e36c17253c11cf38974ed0db1b759160da63783": { + "balance": "7000000000000000000000" + }, + "cbfa76db04ce38fb205d37b8d377cf1380da0317": { + "balance": "1430000000000000000000" + }, + "a7e83772bc200f9006aa2a260dbaa8483dc52b30": { + "balance": "207730000000000000000" + }, + "e87eac6d602b4109c9671bf57b950c2cfdb99d55": { + "balance": "49932000000000000000" + }, + "9b06ad841dffbe4ccf46f1039fc386f3c321446e": { + "balance": "2000000000000000000000" + }, + "e0f903c1e48ac421ab48528f3d4a2648080fe043": { + "balance": "1015200000000000000000" + }, + "5d872b122e994ef27c71d7deb457bf65429eca6c": { + "balance": "7999973000000000000000" + }, + "f34083ecea385017aa40bdd35ef7effb4ce7762d": { + "balance": "400000000000000000000" + }, + "7f3709391f3fbeba3592d175c740e87a09541d02": { + "balance": "480000000000000000000" + }, + "888e94917083d152202b53163939869d271175b4": { + "balance": "4000000000000000000000" + }, + "bed4c8f006a27c1e5f7ce205de75f516bfb9f764": { + "balance": "16000000000000000000000" + }, + "b3a6bd41f9d9c3201e050b87198fbda399342210": { + "balance": "3622615000000000000000" + }, + "550aadae1221b07afea39fba2ed62e05e5b7b5f9": { + "balance": "20000000000000000000" + }, + "bcedc4267ccb89b31bb764d7211171008d94d44d": { + "balance": "200000000000000000000" + }, + "6229dcc203b1edccfdf06e87910c452a1f4d7a72": { + "balance": "32500000000000000000000" + }, + "94be3ae54f62d663b0d4cc9e1ea8fe9556ea9ebf": { + "balance": "23280000000000000000" + }, + "0e0c9d005ea016c295cd795cc9213e87febc33eb": { + "balance": "198000000000000000000" + }, + "55d057bcc04bd0f4af9642513aa5090bb3ff93fe": { + "balance": "1106680000000000000000" + }, + "ed9e030ca75cb1d29ea01d0d4cdfdccd3844b6e4": { + "balance": "30895000000000000000" + }, + "86c4ce06d9ac185bb148d96f7b7abe73f441006d": { + "balance": "10000000000000000000000" + }, + "2c04115c3e52961b0dc0b0bf31fba4546f5966fd": { + "balance": "200000000000000000000" + }, + "b959dce02e91d9db02b1bd8b7d17a9c41a97af09": { + "balance": "8000000000000000000000" + }, + "e01547ba42fcafaf93938becf7699f74290af74f": { + "balance": "2000000000000000000000" + }, + "c593d6e37d14b566643ac4135f243caa0787c182": { + "balance": "12000000000000000000000" + }, + "2c0ee134d8b36145b47beee7af8d2738dbda08e8": { + "balance": "201000000000000000000" + }, + "0ef54ac7264d2254abbb5f8b41adde875157db7c": { + "balance": "40000000000000000000" + }, + "0349634dc2a9e80c3f7721ee2b5046aeaaedfbb5": { + "balance": "4000000000000000000000" + }, + "873e49135c3391991060290aa7f6ccb8f85a78db": { + "balance": "20000000000000000000" + }, + "05236d4c90d065f9e3938358aaffd777b86aec49": { + "balance": "500000000000000000000" + }, + "d2abd84a181093e5e229136f42d835e8235de109": { + "balance": "100007000000000000000" + }, + "b56a780028039c81caf37b6775c620e786954764": { + "balance": "2000000000000000000000" + }, + "86df73bd377f2c09de63c45d67f283eaefa0f4ab": { + "balance": "1000000000000000000000" + }, + "7670b02f2c3cf8fd4f4730f3381a71ea431c33c7": { + "balance": "267400000000000000000" + }, + "24aa1151bb765fa3a89ca50eb6e1b1c706417fd4": { + "balance": "3100000000000000000000" + }, + "43227d65334e691cf231b4a4e1d339b95d598afb": { + "balance": "10000000000000000000000" + }, + "695550656cbf90b75d92ad9122d90d23ca68ca4d": { + "balance": "1000000000000000000000" + }, + "5281733473e00d87f11e9955e589b59f4ac28e7a": { + "balance": "660360000000000000000000" + }, + "99a96bf2242ea1b39ece6fcc0d18aed00c0179f3": { + "balance": "300000000000000000000" + }, + "b1cf94f8091505055f010ab4bac696e0ca0f67a1": { + "balance": "1580000000000000000000" + }, + "54391b4d176d476cea164e5fb535c69700cb2535": { + "balance": "100076000000000000000" + }, + "152f2bd229ddf3cb0fdaf455c183209c0e1e39a2": { + "balance": "2000000000000000000000" + }, + "affc99d5ebb4a84fe7788d97dce274b038240438": { + "balance": "5000000000000000000000" + }, + "23df8f48ee009256ea797e1fa369beebcf6bc663": { + "balance": "2302671000000000000000" + }, + "3a72d635aadeee4382349db98a1813a4cfeb3df1": { + "balance": "200000000000000000000000" + }, + "ce26f9a5305f8381094354dbfc92664e84f902b5": { + "balance": "230200000000000000000" + }, + "d283b8edb10a25528a4404de1c65e7410dbcaa67": { + "balance": "12000000000000000000000" + }, + "a7859fc07f756ea7dcebbccd42f05817582d973f": { + "balance": "10000000000000000000000" + }, + "b28181a458a440f1c6bb1de8400281a3148f4c35": { + "balance": "376000000000000000000" + }, + "27b1694eafa165ebd7cc7bc99e74814a951419dc": { + "balance": "800000000000000000000" + }, + "66cc8ab23c00d1b82acd7d73f38c99e0d05a4fa6": { + "balance": "100000000000000000000" + }, + "926082cb7eed4b1993ad245a477267e1c33cd568": { + "balance": "374300000000000000000" + }, + "4a47fc3e177f567a1e3893e000e36bba23520ab8": { + "balance": "2000000000000000000000" + }, + "594a76f06935388dde5e234696a0668bc20d2ddc": { + "balance": "2800000000000000000000" + }, + "e91fa0badaddb9a97e88d3f4db7c55d6bb7430fe": { + "balance": "376000000000000000000" + }, + "574de1b3f38d915846ae3718564a5ada20c2f3ed": { + "balance": "4000000000000000000000" + }, + "5816c2687777b6d7d2a2432d59a41fa059e3a406": { + "balance": "133700000000000000000000" + }, + "b50955aa6e341571986608bdc891c2139f540cdf": { + "balance": "1970000000000000000000" + }, + "6d44974a31d187eda16ddd47b9c7ec5002d61fbe": { + "balance": "940000000000000000000" + }, + "80abec5aa36e5c9d098f1b942881bd5acac6963d": { + "balance": "2000000000000000000000" + }, + "294f494b3f2e143c2ffc9738cbfd9501850b874e": { + "balance": "2240000000000000000000" + }, + "bca3ffd4683fba0ad3bbc90734b611da9cfb457e": { + "balance": "200000000000000000000" + }, + "5992624c54cdec60a5ae938033af8be0c50cbb0a": { + "balance": "3621678000000000000000" + }, + "6560941328ff587cbc56c38c78238a7bb5f442f6": { + "balance": "744900000000000000000" + }, + "74b7e0228baed65957aebb4d916d333aae164f0e": { + "balance": "2000000000000000000000" + }, + "8516fcaf77c893970fcd1a958ba9a00e49044019": { + "balance": "196279000000000000000" + }, + "b992a967308c02b98af91ee760fd3b6b4824ab0e": { + "balance": "2000000000000000000000" + }, + "30bb4357cd6910c86d2238bf727cbe8156680e62": { + "balance": "100014000000000000000" + }, + "b8cc0f060aad92d4eb8b36b3b95ce9e90eb383d7": { + "balance": "150000000000000000000000" + }, + "28d4ebf41e3d3c451e943bdd7e1f175fae932a3d": { + "balance": "6000000000000000000000" + }, + "8c83d424a3cf24d51f01923dd54a18d6b6fede7b": { + "balance": "4000000000000000000000" + }, + "7efc90766a00bc52372cac97fabd8a3c831f8ecd": { + "balance": "158000000000000000000" + }, + "7c2b9603884a4f2e464eceb97d17938d828bc02c": { + "balance": "3000000000000000000000" + }, + "9d250ae4f110d71cafc7b0adb52e8d9acb6679b8": { + "balance": "9840000000000000000000" + }, + "61b3df2e9e9fd968131f1e88f0a0eb5bd765464d": { + "balance": "4000000000000000000000" + }, + "9ae13bd882f2576575921a94974cbea861ba0d35": { + "balance": "3160000000000000000000" + }, + "3d09688d93ad07f3abe68c722723cd680990435e": { + "balance": "29999948000000000000000" + }, + "5e58e255fc19870a04305ff2a04631f2ff294bb1": { + "balance": "17600000000000000000" + }, + "bcaed0acb6a76f113f7c613555a2c3b0f5bf34a5": { + "balance": "193600000000000000000" + }, + "159adce27aa10b47236429a34a5ac42cad5b6416": { + "balance": "31867951000000000000000" + }, + "e834c64318205ca7dd4a21abcb08266cb21ff02c": { + "balance": "999999000000000000000" + }, + "7b6a84718dd86e63338429ac811d7c8a860f21f1": { + "balance": "1790000000000000000000" + }, + "2118c116ab0cdf6fd11d54a4309307b477c3fc0f": { + "balance": "10000000000000000000000" + }, + "34a901a69f036bcf9f7843c0ba01b426e8c3dc2b": { + "balance": "4000000000000000000000" + }, + "c7d44fe32c7f8cd5f1a97427b6cd3afc9e45023e": { + "balance": "1580000000000000000000" + }, + "c6045b3c350b4ce9ca0c6b754fb41a69b97e9900": { + "balance": "925000000000000000000" + }, + "cf5a6f9df75579c644f794711215b30d77a0ce40": { + "balance": "2000000000000000000000" + }, + "e2904b1aefa056398b6234cb35811288d736db67": { + "balance": "40000000000000000000" + }, + "7101bd799e411cde14bdfac25b067ac890eab8e8": { + "balance": "1450054000000000000000" + }, + "cc45fb3a555bad807b388a0357c855205f7c75e8": { + "balance": "865000000000000000000" + }, + "ff0c3c7798e8733dd2668152891bab80a8be955c": { + "balance": "80220000000000000000" + }, + "3536453322c1466cb905af5c335ca8db74bff1e6": { + "balance": "447000000000000000000" + }, + "08cac8952641d8fc526ec1ab4f2df826a5e7710f": { + "balance": "300000000000000000000" + }, + "0d8aab8f74ea862cdf766805009d3f3e42d8d00b": { + "balance": "5820000000000000000000" + }, + "8908760cd39b9c1e8184e6a752ee888e3f0b7045": { + "balance": "6000000000000000000000" + }, + "8156360bbd370961ceca6b6691d75006ad204cf2": { + "balance": "40000000000000000000000" + }, + "a304588f0d850cd8d38f76e9e83c1bf63e333ede": { + "balance": "39800000000000000000" + }, + "14c63ba2dcb1dd4df33ddab11c4f0007fa96a62d": { + "balance": "15500000000000000000000" + }, + "a009bf076f1ba3fa57d2a7217218bed5565a7a7a": { + "balance": "1000000000000000000000" + }, + "1c89060f987c518fa079ec2c0a5ebfa30f5d20f7": { + "balance": "38000000000000000000000" + }, + "8895eb726226edc3f78cc6a515077b3296fdb95e": { + "balance": "3940000000000000000000" + }, + "7919e7627f9b7d54ea3b14bb4dd4649f4f39dee0": { + "balance": "1670000000000000000000" + }, + "b3c65b845aba6cd816fbaae983e0e46c82aa8622": { + "balance": "1000000000000000000000" + }, + "eff51d72adfae143edf3a42b1aec55a2ccdd0b90": { + "balance": "300000000000000000000" + }, + "05bb64a916be66f460f5e3b64332110d209e19ae": { + "balance": "4200000000000000000000" + }, + "d5b117ec116eb846418961eb7edb629cd0dd697f": { + "balance": "3000000000000000000000" + }, + "05e97b09492cd68f63b12b892ed1d11d152c0eca": { + "balance": "1015200000000000000000" + }, + "84cc7878da605fdb019fab9b4ccfc157709cdda5": { + "balance": "1336922000000000000000" + }, + "79cac6494f11ef2798748cb53285bd8e22f97cda": { + "balance": "2000000000000000000000" + }, + "bd5a8c94bd8be6470644f70c8f8a33a8a55c6341": { + "balance": "200000000000000000000" + }, + "b119e79aa9b916526581cbf521ef474ae84dcff4": { + "balance": "1470700000000000000000" + }, + "aff1045adf27a1aa329461b24de1bae9948a698b": { + "balance": "33400000000000000000" + }, + "4398628ea6632d393e929cbd928464c568aa4a0c": { + "balance": "1400000000000000000000" + }, + "99997668f7c1a4ff9e31f9977ae3224bcb887a85": { + "balance": "291200000000000000000" + }, + "bc0e8745c3a549445c2be900f52300804ab56289": { + "balance": "33104697000000000000000" + }, + "e5bab4f0afd8a9d1a381b45761aa18f3d3cce105": { + "balance": "1508010000000000000000" + }, + "be60037e90714a4b917e61f193d834906703b13a": { + "balance": "1700000000000000000000" + }, + "8ed4284c0f47449c15b8d9b3245de8beb6ce80bf": { + "balance": "800000000000000000000" + }, + "333ad1596401e05aea2d36ca47318ef4cd2cb3df": { + "balance": "2910000000000000000000" + }, + "22db559f2c3c1475a2e6ffe83a5979599196a7fa": { + "balance": "1000000000000000000000" + }, + "fdf449f108c6fb4f5a2b081eed7e45e6919e4d25": { + "balance": "2000000000000000000000" + }, + "0be1bcb90343fae5303173f461bd914a4839056c": { + "balance": "6000000000000000000000" + }, + "b981ad5e6b7793a23fc6c1e8692eb2965d18d0da": { + "balance": "9999924000000000000000" + }, + "c75d2259306aec7df022768c69899a652185dbc4": { + "balance": "4000000000000000000000" + }, + "6c2e9be6d4ab450fd12531f33f028c614674f197": { + "balance": "3580000000000000000000" + }, + "6dcc7e64fcafcbc2dc6c0e5e662cb347bffcd702": { + "balance": "20000000000000000000000" + }, + "aabdb35c1514984a039213793f3345a168e81ff1": { + "balance": "309760000000000000000" + }, + "d315deea1d8c1271f9d1311263ab47c007afb6f5": { + "balance": "69760000000000000000" + }, + "4faf90b76ecfb9631bf9022176032d8b2c207009": { + "balance": "1000032000000000000000" + }, + "3e7a966b5dc357ffb07e9fe067c45791fd8e3049": { + "balance": "59100000000000000000" + }, + "2e64a8d71111a22f4c5de1e039b336f68d398a7c": { + "balance": "2000000000000000000000" + }, + "181fbba852a7f50178b1c7f03ed9e58d54162929": { + "balance": "666000000000000000000" + }, + "4f7330096f79ed264ee0127f5d30d2f73c52b3d8": { + "balance": "499970000000000000000" + }, + "a8a8dbdd1a85d1beee2569e91ccc4d09ae7f6ea1": { + "balance": "5800000000000000000000" + }, + "1f9c3268458da301a2be5ab08257f77bb5a98aa4": { + "balance": "200000000000000000000" + }, + "fc372ff6927cb396d9cf29803500110da632bc52": { + "balance": "2000000000000000000000" + }, + "4fa554ab955c249217386a4d3263bbf72895434e": { + "balance": "19982000000000000000" + }, + "2a59e47ea5d8f0e7c028a3e8e093a49c1b50b9a3": { + "balance": "2000000000000000000000" + }, + "5e32c72191b8392c55f510d8e3326e3a60501d62": { + "balance": "44000000000000000000000" + }, + "1dfaee077212f1beaf0e6f2f1840537ae154ad86": { + "balance": "1000000000000000000000" + }, + "7eaba035e2af3793fd74674b102540cf190addb9": { + "balance": "1273000000000000000000" + }, + "d62edb96fce2969aaf6c545e967cf1c0bc805205": { + "balance": "85705000000000000000" + }, + "220dc68df019b6b0ccbffb784b5a5ab4b15d4060": { + "balance": "3940000000000000000000" + }, + "45bb829652d8bfb58b8527f0ecb621c29e212ec3": { + "balance": "2000000000000000000000" + }, + "79b120eb8806732321288f675a27a9225f1cd2eb": { + "balance": "2465000000000000000000" + }, + "740af1eefd3365d78ba7b12cb1a673e06a077246": { + "balance": "19700000000000000000000" + }, + "0f042c9c2fb18766f836bb59f735f27dc329fe3c": { + "balance": "10000000000000000000000" + }, + "6dda5f788a6c688ddf921fa3852eb6d6c6c62966": { + "balance": "40000000000000000000" + }, + "96ad579bbfa8db8ebec9d286a72e4661eed8e356": { + "balance": "1070750000000000000000" + }, + "0c2073ba44d3ddbdb639c04e191039a71716237f": { + "balance": "1430000000000000000000" + }, + "1a3520453582c718a21c42375bc50773255253e1": { + "balance": "790000000000000000000" + }, + "efcaae9ff64d2cd95b5249dcffe7faa0a0c0e44d": { + "balance": "401100000000000000000" + }, + "0a3de155d5ecd8e81c1ff9bbf0378301f8d4c623": { + "balance": "4000000000000000000000" + }, + "80f07ac09e7b2c3c0a3d1e9413a544c73a41becb": { + "balance": "20000000000000000000" + }, + "c3631c7698b6c5111989bf452727b3f9395a6dea": { + "balance": "10683500000000000000000" + }, + "4cc22c9bc9ad05d875a397dbe847ed221c920c67": { + "balance": "2000000000000000000000" + }, + "1a987e3f83de75a42f1bde7c997c19217b4a5f24": { + "balance": "2000000000000000000000" + }, + "5b2b64e9c058e382a8b299224eecaa16e09c8d92": { + "balance": "161000000000000000000" + }, + "86caafacf32aa0317c032ac36babed974791dc03": { + "balance": "40000000000000000000000" + }, + "1cd1f0a314cbb200de0a0cb1ef97e920709d97c2": { + "balance": "2000000000000000000000" + }, + "7d980f4b566bb045517e4c14c87750de9346744b": { + "balance": "1337000000000000000000" + }, + "8b5f29cc2faa262cdef30ef554f50eb488146eac": { + "balance": "5818250000000000000000" + }, + "5153a0c3c8912881bf1c3501bf64b45649e48222": { + "balance": "4000000000000000000000" + }, + "d21a7341eb84fd151054e5e387bb25d36e499c09": { + "balance": "14000000000000000000000" + }, + "9560e8ac6718a6a1cdcff189d603c9063e413da6": { + "balance": "4000000000000000000000" + }, + "e49ba0cd96816c4607773cf8a5970bb5bc16a1e6": { + "balance": "1670000000000000000000" + }, + "b8ac117d9f0dba80901445823c4c9d4fa3fedc6e": { + "balance": "15759015000000000000000" + }, + "af67fd3e127fd9dc36eb3fcd6a80c7be4f7532b2": { + "balance": "1670000000000000000000" + }, + "b43c27f7a0a122084b98f483922541c8836cee2c": { + "balance": "715000000000000000000" + }, + "4d9279962029a8bd45639737e98b511eff074c21": { + "balance": "1337000000000000000000" + }, + "c667441e7f29799aba616451d53b3f489f9e0f48": { + "balance": "13920000000000000000000" + }, + "275875ff4fbb0cf3a430213127487f7608d04cba": { + "balance": "500080000000000000000" + }, + "9a953b5bcc709379fcb559d7b916afdaa50cadcc": { + "balance": "100000000000000000000" + }, + "7ea791ebab0445a00efdfc4e4a8e9a7e7565136d": { + "balance": "18200000000000000000" + }, + "6ffe5cf82cc9ea5e36cad7c2974ce7249f3749e6": { + "balance": "1940000000000000000000" + }, + "f1b4ecc63525f7432c3d834ffe2b970fbeb87212": { + "balance": "3000064000000000000000" + }, + "6b72a8f061cfe6996ad447d3c72c28c0c08ab3a7": { + "balance": "4271316000000000000000" + }, + "bba3c68004248e489573abb2743677066b24c8a7": { + "balance": "2000000000000000000000" + }, + "b7c0d0cc0b4d342d4062bac624ccc3c70cc6da3f": { + "balance": "4000000000000000000000" + }, + "fe98c664c3e447a95e69bd582171b7176ea2a685": { + "balance": "4000000000000000000000" + }, + "ce71086d4c602554b82dcbfce88d20634d53cc4d": { + "balance": "43250000000000000000000" + }, + "1c601993789207f965bb865cbb4cd657cce76fc0": { + "balance": "98294000000000000000" + }, + "476b5599089a3fb6f29c6c72e49b2e4740ea808d": { + "balance": "2800000000000000000000" + }, + "3439998b247cb4bf8bc80a6d2b3527f1dfe9a6d2": { + "balance": "140000000000000000000" + }, + "c4f7d2e2e22084c44f70feaab6c32105f3da376f": { + "balance": "1970000000000000000000" + }, + "c1eba5684aa1b24cba63150263b7a9131aeec28d": { + "balance": "20000000000000000000" + }, + "94ad4bad824bd0eb9ea49c58cebcc0ff5e08346b": { + "balance": "1940000000000000000000" + }, + "ded877378407b94e781c4ef4af7cfc5bc220b516": { + "balance": "372500000000000000000" + }, + "699c9ee47195511f35f862ca4c22fd35ae8ffbf4": { + "balance": "80000000000000000000" + }, + "e3a89a1927cc4e2d43fbcda1e414d324a7d9e057": { + "balance": "205500000000000000000" + }, + "4d93696fa24859f5d2939aebfa54b4b51ae1dccc": { + "balance": "19100000000000000000" + }, + "0af65f14784e55a6f95667fd73252a1c94072d2a": { + "balance": "192987000000000000000" + }, + "5b70c49cc98b3df3fbe2b1597f5c1b6347a388b7": { + "balance": "970000000000000000000" + }, + "426f78f70db259ac8534145b2934f4ef1098b5d8": { + "balance": "360000000000000000000" + }, + "58b8ae8f63ef35ed0762f0b6233d4ac14e64b64d": { + "balance": "2000000000000000000000" + }, + "8eae29435598ba8f1c93428cdb3e2b4d31078e00": { + "balance": "2000000000000000000000" + }, + "17fd9b551a98cb61c2e07fbf41d3e8c9a530cba5": { + "balance": "26989000000000000000" + }, + "ab3e78294ba886a0cfd5d3487fb3a3078d338d6e": { + "balance": "1970000000000000000000" + }, + "bdf6e68c0cd7584080e847d72cbb23aad46aeb1d": { + "balance": "1970000000000000000000" + }, + "f989346772995ec1906faffeba2a7fe7de9c6bab": { + "balance": "6685000000000000000000" + }, + "dc5f5ad663a6f263327d64cac9cb133d2c960597": { + "balance": "2000000000000000000000" + }, + "68fe1357218d095849cd579842c4aa02ff888d93": { + "balance": "2000000000000000000000" + }, + "e09c68e61998d9c81b14e4ee802ba7adf6d74cdb": { + "balance": "4000000000000000000000" + }, + "890fe11f3c24db8732d6c2e772e2297c7e65f139": { + "balance": "62980000000000000000000" + }, + "a76929890a7b47fb859196016c6fdd8289ceb755": { + "balance": "5000000000000000000000" + }, + "2dc79d6e7f55bce2e2d0c02ad07ceca8bb529354": { + "balance": "1580000000000000000000" + }, + "19687daa39c368139b6e7be60dc1753a9f0cbea3": { + "balance": "8000000000000000000000" + }, + "c69be440134d6280980144a9f64d84748a37f349": { + "balance": "715000000000000000000" + }, + "3d8d0723721e73a6c0d860aa0557abd14c1ee362": { + "balance": "5000000000000000000000" + }, + "2b241f037337eb4acc61849bd272ac133f7cdf4b": { + "balance": "378000000000000000000000" + }, + "24b95ebef79500baa0eda72e77f877415df75c33": { + "balance": "910000000000000000000" + }, + "106ed5c719b5261477890425ae7551dc59bd255c": { + "balance": "11979600000000000000000" + }, + "5b2e2f1618552eab0db98add55637c2951f1fb19": { + "balance": "12000000000000000000000" + }, + "403145cb4ae7489fcc90cd985c6dc782b3cc4e44": { + "balance": "5999800000000000000000" + }, + "e8be24f289443ee473bc76822f55098d89b91cc5": { + "balance": "2000000000000000000000" + }, + "f6bc37b1d2a3788d589b6de212dc1713b2f6e78e": { + "balance": "5000000000000000000000" + }, + "67fc527dce1785f0fb8bc7e518b1c669f7ecdfb5": { + "balance": "240000000000000000000" + }, + "6580b1bc94390f04b397bd73e95d96ef11eaf3a8": { + "balance": "20000000000000000000" + }, + "98bf4af3810b842387db70c14d46099626003d10": { + "balance": "4000000000000000000000" + }, + "17993d312aa1106957868f6a55a5e8f12f77c843": { + "balance": "450065000000000000000" + }, + "0729b4b47c09eb16158464c8aa7fd9690b438839": { + "balance": "1999800000000000000000" + }, + "ae70e69d2c4a0af818807b1a2705f79fd0b5dbc4": { + "balance": "985000000000000000000" + }, + "38b50146e71916a5448de12a4d742135dcf39833": { + "balance": "32200000000000000000000" + }, + "38439aaa24e3636f3a18e020ea1da7e145160d86": { + "balance": "2600000000000000000000" + }, + "54b4429b182f0377be7e626939c5db6440f75d7a": { + "balance": "1970000000000000000000" + }, + "7179726f5c71ae1b6d16a68428174e6b34b23646": { + "balance": "7353500000000000000000" + }, + "c2ee91d3ef58c9d1a589844ea1ae3125d6c5ba69": { + "balance": "970000000000000000000" + }, + "912304118b80473d9e9fe3ee458fbe610ffda2bb": { + "balance": "200000000000000000000" + }, + "3308b03466c27a17dfe1aafceb81e16d2934566f": { + "balance": "17000000000000000000000" + }, + "10346414bec6d3dcc44e50e54d54c2b8c3734e3e": { + "balance": "4000000000000000000000" + }, + "4fee50c5f988206b09a573469fb1d0b42ebb6dce": { + "balance": "2009400000000000000000" + }, + "9ece1400800936c7c6485fcdd3626017d09afbf6": { + "balance": "310000000000000000000" + }, + "ddf3ad76353810be6a89d731b787f6f17188612b": { + "balance": "20000000000000000000000" + }, + "72402300e81d146c2e644e2bbda1da163ca3fb56": { + "balance": "7000000000000000000000" + }, + "bb4b4a4b548070ff41432c9e08a0ca6fa7bc9f76": { + "balance": "850000000000000000000" + }, + "c3dd58903886303b928625257ae1a013d71ae216": { + "balance": "2000000000000000000000" + }, + "ca6c818befd251361e02744068be99d8aa60b84a": { + "balance": "6000000000000000000000" + }, + "b8d2ddc66f308c0158ae3ccb7b869f7d199d7b32": { + "balance": "844800000000000000000" + }, + "8e486a0442d171c8605be348fee57eb5085eff0d": { + "balance": "4000000000000000000000" + }, + "a807104f2703d679f8deafc442befe849e42950b": { + "balance": "2000000000000000000000" + }, + "bb61a04bffd57c10470d45c39103f64650347616": { + "balance": "1000000000000000000000" + }, + "d1c45954a62b911ad701ff2e90131e8ceb89c95c": { + "balance": "1394000000000000000000" + }, + "5e65458be964ae449f71773704979766f8898761": { + "balance": "528600000000000000000" + }, + "f9b37825f03073d31e249378c30c795c33f83af2": { + "balance": "200152000000000000000" + }, + "e309974ce39d60aadf2e69673251bf0e04760a10": { + "balance": "254030000000000000000" + }, + "d541ac187ad7e090522de6da3213e9a7f4439673": { + "balance": "2000000000000000000000" + }, + "f33efc6397aa65fb53a8f07a0f893aae30e8bcee": { + "balance": "2304850000000000000000" + }, + "d2f1998e1cb1580cec4f6c047dcd3dcec54cf73c": { + "balance": "200000000000000000000" + }, + "0ed76c2c3b5d50ff8fb50b3eeacd681590be1c2d": { + "balance": "100000000000000000000" + }, + "637d67d87f586f0a5a479e20ee13ea310a10b647": { + "balance": "48300000000000000000000" + }, + "1a5ee533acbfb3a2d76d5b685277b796c56a052b": { + "balance": "2000000000000000000000" + }, + "323fca5ed77f699f9d9930f5ceeff8e56f59f03c": { + "balance": "1337000000000000000000" + }, + "a5fe2ce97f0e8c3856be0de5f4dcb2ce5d389a16": { + "balance": "22892000000000000000" + }, + "93258255b37c7f58f4b10673a932dd3afd90f4f2": { + "balance": "1000000000000000000000" + }, + "950fe9c6cad50c18f11a9ed9c45740a6180612d0": { + "balance": "8000000000000000000000" + }, + "ee31167f9cc93b3c6465609d79db0cde90e8484c": { + "balance": "2000000000000000000000" + }, + "6ebb5e6957aa821ef659b6018a393a504cae4450": { + "balance": "2000000000000000000000" + }, + "be305a796e33bbf7f9aeae6512959066efda1010": { + "balance": "10880000000000000000000" + }, + "537f9d4d31ef70839d84b0d9cdb72b9afedbdf35": { + "balance": "70000000000000000000000" + }, + "fe9e1197d7974a7648dcc7a03112a88edbc9045d": { + "balance": "4925000000000000000000" + }, + "99f77f998b20e0bcdcd9fc838641526cf25918ef": { + "balance": "1790000000000000000000" + }, + "76ffc157ad6bf8d56d9a1a7fddbc0fea010aabf4": { + "balance": "1000000000000000000000" + }, + "defe9141f4704599159d7b223de42bffd80496b3": { + "balance": "100000000000000000000" + }, + "7b1bf53a9cbe83a7dea434579fe72aac8d2a0cd0": { + "balance": "199800000000000000000" + }, + "23ccc3c6acd85c2e460c4ffdd82bc75dc849ea14": { + "balance": "4000000000000000000000" + }, + "9f86a066edb61fcb5856de93b75c8c791864b97b": { + "balance": "2000000000000000000000" + }, + "871b8a8b51dea1989a5921f13ec1a955a515ad47": { + "balance": "8000000000000000000000" + }, + "4efcd9c79fb4334ca6247b0a33bd9cc33208e272": { + "balance": "1337000000000000000000" + }, + "35ac1d3ed7464fa3db14e7729213ceaa378c095e": { + "balance": "1520000000000000000000" + }, + "c69d663c8d60908391c8d236191533fdf7775613": { + "balance": "485000000000000000000" + }, + "c2ed5ffdd1add855a2692fe062b5d618742360d4": { + "balance": "1200000000000000000000" + }, + "454f0141d721d33cbdc41018bd01119aa4784818": { + "balance": "6000000000000000000000" + }, + "6c8687e3417710bb8a93559021a1469e6a86bc77": { + "balance": "11126675000000000000000" + }, + "ec5b198a00cfb55a97b5d53644cffa8a04d2ab45": { + "balance": "2000000000000000000000" + }, + "cd59f3dde77e09940befb6ee58031965cae7a336": { + "balance": "10000000000000000000000" + }, + "8eebec1a62c08b05a7d1d59180af9ff0d18e3f36": { + "balance": "500000000000000000000" + }, + "92a971a739799f8cb48ea8475d72b2d2474172e6": { + "balance": "3940000000000000000000" + }, + "bed4649df646e2819229032d8868556fe1e053d3": { + "balance": "18200000000000000000" + }, + "c50fe415a641b0856c4e75bf960515441afa358d": { + "balance": "2000000000000000000000" + }, + "91f516146cda20281719978060c6be4149067c88": { + "balance": "2000000000000000000000" + }, + "54a1370116fe22099e015d07cd2669dd291cc9d1": { + "balance": "20000000000000000000" + }, + "80c04efd310f440483c73f744b5b9e64599ce3ec": { + "balance": "1200000000000000000000" + }, + "a8914c95b560ec13f140577338c32bcbb77d3a7a": { + "balance": "180000000000000000000" + }, + "e3c812737ac606baf7522ad817428a36050e7a34": { + "balance": "1940000000000000000000" + }, + "6d1456fff0104ee844a3314737843338d24cd66c": { + "balance": "141840000000000000000" + }, + "0e6ece99111cad1961c748ed3df51edd69d2a3b1": { + "balance": "100000000000000000000000" + }, + "019d709579ff4bc09fdcdde431dc1447d2c260bc": { + "balance": "20000000000000000000" + }, + "ebff84bbef423071e604c361bba677f5593def4e": { + "balance": "10000000000000000000000" + }, + "e10c540088113fa6ec00b4b2c8824f8796e96ec4": { + "balance": "236400000000000000000000" + }, + "e03220c697bcd28f26ef0b74404a8beb06b2ba7b": { + "balance": "8000000000000000000000" + }, + "e69a6cdb3a8a7db8e1f30c8b84cd73bae02bc0f8": { + "balance": "16915503000000000000000" + }, + "e5fb31a5caee6a96de393bdbf89fbe65fe125bb3": { + "balance": "1000000000000000000000" + }, + "030fb3401f72bd3418b7d1da75bf8c519dd707dc": { + "balance": "3000000000000000000000" + }, + "1c751e7f24df9d94a637a5dedeffc58277b5db19": { + "balance": "3220000000000000000000" + }, + "bded7e07d0711e684de65ac8b2ab57c55c1a8645": { + "balance": "591000000000000000000" + }, + "dd7ff441ba6ffe3671f3c0dabbff1823a5043370": { + "balance": "2000000000000000000000" + }, + "b55474ba58f0f2f40e6cbabed4ea176e011fcad6": { + "balance": "1970000000000000000000" + }, + "b92427ad7578b4bfe20a9f63a7c5506d5ca12dc8": { + "balance": "2000000000000000000000" + }, + "91a8baaed012ea2e63803b593d0d0c2aab4c5b0a": { + "balance": "1500000000000000000000" + }, + "a97e072144499fe5ebbd354acc7e7efb58985d08": { + "balance": "2674000000000000000000" + }, + "75c2ffa1bef54919d2097f7a142d2e14f9b04a58": { + "balance": "2673866000000000000000" + }, + "53faf165be031ec18330d9fce5bd1281a1af08db": { + "balance": "140000000000000000000" + }, + "055ab658c6f0ed4f875ed6742e4bc7292d1abbf0": { + "balance": "83500000000000000000" + }, + "6f18ec767e320508195f1374500e3f2e125689ff": { + "balance": "1000000000000000000000" + }, + "90fc537b210658660a83baa9ac4a8402f65746a8": { + "balance": "1880000000000000000000" + }, + "34664d220fa7f37958024a3332d684bcc6d4c8bd": { + "balance": "10000000000000000000000" + }, + "15acb61568ec4af7ea2819386181b116a6c5ee70": { + "balance": "31000000000000000000000" + }, + "69d98f38a3ba3dbc01fa5c2c1427d862832f2f70": { + "balance": "100000000000000000000000" + }, + "ece1152682b7598fe2d1e21ec15533885435ac85": { + "balance": "4000000000000000000000" + }, + "f618d9b104411480a863e623fc55232d1a4f48aa": { + "balance": "265793000000000000000" + }, + "f9debaecb5f339beea4894e5204bfa340d067f25": { + "balance": "1665000000000000000000" + }, + "5e731b55ced452bb3f3fe871ddc3ed7ee6510a8f": { + "balance": "3000000000000000000000" + }, + "67df242d240dd4b8071d72f8fcf35bb3809d71e8": { + "balance": "4000000000000000000000" + }, + "c4cf930e5d116ab8d13b9f9a7ec4ab5003a6abde": { + "balance": "320000000000000000000" + }, + "01a25a5f5af0169b30864c3be4d7563ccd44f09e": { + "balance": "1430000000000000000000" + }, + "7f6efb6f4318876d2ee624e27595f44446f68e93": { + "balance": "1550000000000000000000" + }, + "82249fe70f61c6b16f19a324840fdc020231bb02": { + "balance": "9504014000000000000000" + }, + "205237c4be146fba99478f3a7dad17b09138da95": { + "balance": "2000000000000000000000" + }, + "fd1fb5a89a89a721b8797068fbc47f3e9d52e149": { + "balance": "236400000000000000000" + }, + "e47fbaed99fc209962604ebd20e240f74f4591f1": { + "balance": "2000000000000000000000" + }, + "a24c3ab62181e9a15b78c4621e4c7c588127be26": { + "balance": "162410000000000000000" + }, + "b6cd7432d5161be79768ad45de3e447a07982063": { + "balance": "4000000000000000000000" + }, + "32a70691255c9fc9791a4f75c8b81f388e0a2503": { + "balance": "985000000000000000000" + }, + "562f16d79abfcec3943e34b20f05f97bdfcda605": { + "balance": "4000000000000000000000" + }, + "dbc66965e426ff1ac87ad6eb78c1d95271158f9f": { + "balance": "18200000000000000000" + }, + "7e87863ec43a481df04d017762edcb5caa629b5a": { + "balance": "39400000000000000000" + }, + "587d6849b168f6c3332b7abae7eb6c42c37f48bf": { + "balance": "880000000000000000000" + }, + "721158be5762b119cc9b2035e88ee4ee78f29b82": { + "balance": "10000000000000000000000" + }, + "84b91e2e2902d05e2b591b41083bd7beb2d52c74": { + "balance": "9848621000000000000000" + }, + "632cecb10cfcf38ec986b43b8770adece9200221": { + "balance": "20000000000000000000" + }, + "c34e3ba1322ed0571183a24f94204ee49c186641": { + "balance": "58200000000000000000" + }, + "ae78bb849139a6ba38ae92a09a69601cc4cb62d1": { + "balance": "500000000000000000000" + }, + "5ce0b6862cce9162e87e0849e387cb5df4f9118c": { + "balance": "1670000000000000000000" + }, + "f52c0a7877345fe0c233bb0f04fd6ab18b6f14ba": { + "balance": "400440000000000000000000" + }, + "e016dc138e25815b90be3fe9eee8ffb2e105624f": { + "balance": "500000000000000000000" + }, + "5789d01db12c816ac268e9af19dc0dd6d99f15df": { + "balance": "200000000000000000000" + }, + "d8b77db9b81bbe90427b62f702b201ffc29ff618": { + "balance": "930200000000000000000" + }, + "5dff811dad819ece3ba602c383fb5dc64c0a3a48": { + "balance": "186000000000000000000" + }, + "af3087e62e04bf900d5a54dc3e946274da92423b": { + "balance": "20000000000000000000" + }, + "8c1023fde1574db8bb54f1739670157ca47da652": { + "balance": "6969382000000000000000" + }, + "bb3b010b18e6e2be1135871026b7ba15ea0fde24": { + "balance": "10044000000000000000000" + }, + "cabdaf354f4720a466a764a528d60e3a482a393c": { + "balance": "1000000000000000000000" + }, + "94bbc67d13f89ebca594be94bc5170920c30d9f3": { + "balance": "80200000000000000000" + }, + "3275496fd4dd8931fd69fb0a0b04c4d1ff879ef5": { + "balance": "446000000000000000000" + }, + "281250a29121270a4ee5d78d24feafe82c70ba3a": { + "balance": "1000000000000000000000" + }, + "590ccb5911cf78f6f622f535c474375f4a12cfcf": { + "balance": "20000000000000000000000" + }, + "542e8096bafb88162606002e8c8a3ed19814aeac": { + "balance": "2000000000000000000000" + }, + "a65426cff378ed23253513b19f496de45fa7e18f": { + "balance": "7200000000000000000000" + }, + "4aa693b122f314482a47b11cc77c68a497876162": { + "balance": "1970000000000000000000" + }, + "d9b783d31d32adc50fa3eacaa15d92b568eaeb47": { + "balance": "34010000000000000000000" + }, + "068e655766b944fb263619658740b850c94afa31": { + "balance": "35200000000000000000" + }, + "9e23c5e4b782b00a5fadf1aead87dacf5b0367a1": { + "balance": "20000000000000000000" + }, + "bf17f397f8f46f1bae45d187148c06eeb959fa4d": { + "balance": "1001440000000000000000" + }, + "8578e10212ca14ff0732a8241e37467db85632a9": { + "balance": "6000000000000000000000" + }, + "2cb5495a505336c2465410d1cae095b8e1ba5cdd": { + "balance": "20000000000000000000000" + }, + "695b0f5242753701b264a67071a2dc880836b8db": { + "balance": "16400000000000000000" + }, + "f2edde37f9a8c39ddea24d79f4015757d06bf786": { + "balance": "100000000000000000000000" + }, + "480f31b989311e4124c6a7465f5a44094d36f9d0": { + "balance": "1025000000000000000000" + }, + "cf157612764e0fd696c8cb5fba85df4c0ddc3cb0": { + "balance": "30000000000000000000000" + }, + "27521deb3b6ef1416ea4c781a2e5d7b36ee81c61": { + "balance": "2000000000000000000000" + }, + "6efd90b535e00bbd889fda7e9c3184f879a151db": { + "balance": "10100000000000000000000" + }, + "b635a4bc71fb28fdd5d2c322983a56c284426e69": { + "balance": "170000000000000000000" + }, + "a17c9e4323069518189d5207a0728dcb92306a3f": { + "balance": "1000000000000000000000" + }, + "6af940f63ec9b8d876272aca96fef65cdacecdea": { + "balance": "3000000000000000000000" + }, + "469358709332c82b887e20bcddd0220f8edba7d0": { + "balance": "17300000000000000000000" + }, + "a257ad594bd88328a7d90fc0a907df95eecae316": { + "balance": "520510000000000000000" + }, + "6f051666cb4f7bd2b1907221b829b555d7a3db74": { + "balance": "1760000000000000000000" + }, + "46bfc5b207eb2013e2e60f775fecd71810c5990c": { + "balance": "1550000000000000000000" + }, + "62b9081e7710345e38e02e16449ace1b85bcfc4e": { + "balance": "910000000000000000000" + }, + "bc73f7b1ca3b773b34249ada2e2c8a9274cc17c2": { + "balance": "2000000000000000000000" + }, + "1adaf4abfa867db17f99af6abebf707a3cf55df6": { + "balance": "6000000000000000000000" + }, + "8d629c20608135491b5013f1002586a0383130e5": { + "balance": "1370000000000000000000" + }, + "38e46de4453c38e941e7930f43304f94bb7b2be8": { + "balance": "2005500000000000000000" + }, + "3485f621256433b98a4200dad857efe55937ec98": { + "balance": "2000000000000000000000" + }, + "775c10c93e0db7205b2643458233c64fc33fd75b": { + "balance": "2000000000000000000000" + }, + "7c4401ae98f12ef6de39ae24cf9fc51f80eba16b": { + "balance": "200000000000000000000" + }, + "17b807afa3ddd647e723542e7b52fee39527f306": { + "balance": "400010000000000000000" + }, + "0ab366e6e7d5abbce6b44a438d69a1cabb90d133": { + "balance": "320000000000000000000" + }, + "194ffe78bbf5d20dd18a1f01da552e00b7b11db1": { + "balance": "7000000000000000000000" + }, + "c45d47ab0c9aa98a5bd62d16223ea2471b121ca4": { + "balance": "593640000000000000000" + }, + "2487c3c4be86a2723d917c06b458550170c3edba": { + "balance": "1000000000000000000000" + }, + "ec4d08aa2e47496dca87225de33f2b40a8a5b36f": { + "balance": "158000000000000000000" + }, + "aaa8defe11e3613f11067fb983625a08995a8dfc": { + "balance": "200000000000000000000" + }, + "50bb67c8b8d8bd0f63c4760904f2d333f400aace": { + "balance": "2000000000000000000000" + }, + "1227e10a4dbf9caca31b1780239f557615fc35c1": { + "balance": "200000000000000000000" + }, + "44a8989e32308121f72466978db395d1f76c3a4b": { + "balance": "7236900000000000000000" + }, + "59569a21d28fba4bda37753405a081f2063da150": { + "balance": "4000000000000000000000" + }, + "c3756bcdcc7eec74ed896adfc335275930266e08": { + "balance": "6000000000000000000000" + }, + "ce3a61f0461b00935e85fa1ead82c45e5a64d488": { + "balance": "500000000000000000000" + }, + "012f396a2b5eb83559bac515e5210df2c8c362ba": { + "balance": "200000000000000000000" + }, + "93bc7d9a4abd44c8bbb8fe8ba804c61ad8d6576c": { + "balance": "3999922000000000000000" + }, + "e20bb9f3966419e14bbbaaaa6789e92496cfa479": { + "balance": "3465116000000000000000" + }, + "9eef442d291a447d74c5d253c49ef324eac1d8f0": { + "balance": "3420000000000000000000" + }, + "db6c2a73dac7424ab0d031b66761122566c01043": { + "balance": "3000000000000000000000" + }, + "704d243c2978e46c2c86adbecd246e3b295ff633": { + "balance": "2012000000000000000000" + }, + "d2ff672016f63b2f85398f4a6fedbb60a50d3cce": { + "balance": "342500000000000000000" + }, + "d2051cb3cb6704f0548cc890ab0a19db3415b42a": { + "balance": "334000000000000000000" + }, + "1111e5dbf45e6f906d62866f1708101788ddd571": { + "balance": "1300200000000000000000" + }, + "6a686bf220b593deb9b7324615fb9144ded3f39d": { + "balance": "1460000000000000000000" + }, + "911feea61fe0ed50c5b9e5a0d66071399d28bdc6": { + "balance": "60000000000000000000" + }, + "3881defae1c07b3ce04c78abe26b0cdc8d73f010": { + "balance": "200000000000000000000" + }, + "ea94f32808a2ef8a9bf0861d1d2404f7b7be258a": { + "balance": "20000000000000000000" + }, + "2eef6b1417d7b10ecfc19b123a8a89e73e526c58": { + "balance": "600000000000000000000" + }, + "dd8af9e7765223f4446f44d3d509819a3d3db411": { + "balance": "10000000000000000000000" + }, + "2efc4c647dac6acac35577ad221758fef6616faa": { + "balance": "8000000000000000000000" + }, + "1547b9bf7ad66274f3413827231ba405ee8c88c1": { + "balance": "17300000000000000000000" + }, + "250a40cef3202397f240469548beb5626af4f23c": { + "balance": "92500000000000000000" + }, + "c175be3194e669422d15fee81eb9f2c56c67d9c9": { + "balance": "200000000000000000000" + }, + "c9e02608066828848aeb28c73672a12925181f4d": { + "balance": "500038000000000000000" + }, + "8229ceb9f0d70839498d44e6abed93c5ca059f5d": { + "balance": "123300000000000000000000" + }, + "39f198331e4b21c1b760a3155f4ab2fe00a74619": { + "balance": "2000000000000000000000" + }, + "3ffcb870d4023d255d5167d8a507cefc366b68ba": { + "balance": "649400000000000000000" + }, + "00dae27b350bae20c5652124af5d8b5cba001ec1": { + "balance": "40000000000000000000" + }, + "fc5500825105cf712a318a5e9c3bfc69c89d0c12": { + "balance": "4000000000000000000000" + }, + "1ed8bb3f06778b039e9961d81cb71a73e6787c8e": { + "balance": "2000000000000000000000" + }, + "530ffac3bc3412e2ec0ea47b7981c770f5bb2f35": { + "balance": "133700000000000000000" + }, + "5f344b01c7191a32d0762ac188f0ec2dd460911d": { + "balance": "1000000000000000000000" + }, + "5cfa9877f719c79d9e494a08d1e41cf103fc87c9": { + "balance": "200000000000000000000" + }, + "f6eaac7032d492ef17fd6095afc11d634f56b382": { + "balance": "500038000000000000000" + }, + "962c0dec8a3d464bf39b1215eafd26480ae490cd": { + "balance": "2001680000000000000000" + }, + "262a8bfd7d9dc5dd3ad78161b6bb560824373655": { + "balance": "1169820000000000000000" + }, + "9b4824ff9fb2abda554dee4fb8cf549165570631": { + "balance": "20000000000000000000" + }, + "bb3b9005f46fd2ca3b30162599928c77d9f6b601": { + "balance": "8000014000000000000000" + }, + "f7dc251196fbcbb77c947d7c1946b0ff65021cea": { + "balance": "1000000000000000000000" + }, + "af1148ef6c8e103d7530efc91679c9ac27000993": { + "balance": "200000000000000000000" + }, + "0bb2650ea01aca755bc0c017b64b1ab5a66d82e3": { + "balance": "1337000000000000000000" + }, + "0cda12bf72d461bbc479eb92e6491d057e6b5ad1": { + "balance": "10000000000000000000000" + }, + "4e5b77f9066159e615933f2dda7477fa4e47d648": { + "balance": "200000000000000000000" + }, + "391161b0e43c302066e8a68d2ce7e199ecdb1d57": { + "balance": "4000000000000000000000" + }, + "c7e330cd0c890ac99fe771fcc7e7b009b7413d8a": { + "balance": "4000000000000000000000" + }, + "d4b38a5fdb63e01714e9801db47bc990bd509183": { + "balance": "5999000000000000000000" + }, + "bc0f98598f88056a26339620923b8f1eb074a9fd": { + "balance": "200000000000000000000" + }, + "dbc59ed88973dead310884223af49763c05030f1": { + "balance": "20000000000000000000" + }, + "0f85e42b1df321a4b3e835b50c00b06173968436": { + "balance": "985000000000000000000" + }, + "d7788ef28658aa06cc53e1f3f0de58e5c371be78": { + "balance": "6685000000000000000000" + }, + "ecd276af64c79d1bd9a92b86b5e88d9a95eb88f8": { + "balance": "20000000000000000000" + }, + "81c9e1aee2d3365d53bcfdcd96c7c538b0fd7eec": { + "balance": "1820000000000000000000" + }, + "5d39ef9ea6bdfff15d11fe91f561a6f9e31f5da5": { + "balance": "2000000000000000000000" + }, + "99878f9d6e0a7ed9aec78297b73879a80195afe0": { + "balance": "3980000000000000000000" + }, + "7294c918b1aefb4d25927ef9d799e71f93a28e85": { + "balance": "197000000000000000000" + }, + "a33f70da7275ef057104dfa7db64f472e9f5d553": { + "balance": "80220000000000000000" + }, + "255bdd6474cc8262f26a22c38f45940e1ceea69b": { + "balance": "4000000000000000000000" + }, + "52f8b509fee1a874ab6f9d87367fbeaf15ac137f": { + "balance": "1000000000000000000000" + }, + "e2728a3e8c2aaac983d05dc6877374a8f446eee9": { + "balance": "197600000000000000000" + }, + "ed0206cb23315128f8caff26f6a30b985467d022": { + "balance": "40000000000000000000000" + }, + "87cf36ad03c9eae9053abb5242de9117bb0f2a0b": { + "balance": "500000000000000000000" + }, + "a929c8bd71db0c308dac06080a1747f21b1465aa": { + "balance": "500000000000000000000" + }, + "9da6e075989c7419094cc9f6d2e49393bb199688": { + "balance": "11100000000000000000000" + }, + "763eece0b08ac89e32bfa4bece769514d8cb5b85": { + "balance": "4000000000000000000000" + }, + "5df3277ca85936c7a0d2c0795605ad25095e7159": { + "balance": "2000000000000000000000" + }, + "7163758cbb6c4c525e0414a40a049dcccce919bb": { + "balance": "200000000000000000000" + }, + "14cdddbc8b09e6675a9e9e05091cb92238c39e1e": { + "balance": "5100000000000000000000" + }, + "b3b7f493b44a2c8d80ec78b1cdc75a652b73b06c": { + "balance": "2000000000000000000000" + }, + "c69b855539ce1b04714728eec25a37f367951de7": { + "balance": "2000000000000000000000" + }, + "052eab1f61b6d45517283f41d1441824878749d0": { + "balance": "4000000000000000000000" + }, + "515651d6db4faf9ecd103a921bbbbe6ae970fdd4": { + "balance": "20000000000000000000000" + }, + "c7aff91929797489555a2ff1d14d5c695a108355": { + "balance": "1000000000000000000000" + }, + "d7ca7fdcfebe4588eff5421d1522b61328df7bf3": { + "balance": "4001070000000000000000" + }, + "eefba12dfc996742db790464ca7d273be6e81b3e": { + "balance": "1000000000000000000000" + }, + "ebaa216de9cc5a43031707d36fe6d5bedc05bdf0": { + "balance": "1969606000000000000000" + }, + "559194304f14b1b93afe444f0624e053c23a0009": { + "balance": "400000000000000000000" + }, + "4ecc19948dd9cd87b4c7201ab48e758f28e7cc76": { + "balance": "500200000000000000000" + }, + "f224eb900b37b4490eee6a0b6420d85c947d8733": { + "balance": "970000000000000000000" + }, + "97810bafc37e84306332aacb35e92ad911d23d24": { + "balance": "1000000000000000000000" + }, + "bd67d2e2f82da8861341bc96a2c0791fddf39e40": { + "balance": "200014000000000000000" + }, + "1b6495891240e64e594493c2662171db5e30ce13": { + "balance": "172400000000000000000" + }, + "00bdd4013aa31c04616c2bc9785f2788f915679b": { + "balance": "13400000000000000000" + }, + "c6ae287ddbe1149ba16ddcca4fe06aa2eaa988a9": { + "balance": "400000000000000000000" + }, + "b7c9f12b038e73436d17e1c12ffe1aeccdb3f58c": { + "balance": "540000000000000000000" + }, + "c1b500011cfba95d7cd636e95e6cbf6167464b25": { + "balance": "200000000000000000000" + }, + "39e0db4d60568c800b8c5500026c2594f5768960": { + "balance": "1000000000000000000000" + }, + "40e3c283f7e24de0410c121bee60a5607f3e29a6": { + "balance": "1000000000000000000000" + }, + "2f7d3290851be5c6b4b43f7d4574329f61a792c3": { + "balance": "100000000000000000000" + }, + "c33ece935a8f4ef938ea7e1bac87cb925d8490ca": { + "balance": "33122000000000000000000" + }, + "57bddf078834009c89d88e6282759dc45335b470": { + "balance": "2148000000000000000000" + }, + "50ad187ab21167c2b6e78be0153f44504a07945e": { + "balance": "100076000000000000000" + }, + "5bd24aac3612b20c609eb46779bf95698407c57c": { + "balance": "1970000000000000000000" + }, + "16526c9edf943efa4f6d0f0bae81e18b31c54079": { + "balance": "985000000000000000000" + }, + "4c6a9dc2cab10abb2e7c137006f08fecb5b779e1": { + "balance": "499000000000000000000" + }, + "02c9f7940a7b8b7a410bf83dc9c22333d4275dd3": { + "balance": "5000000000000000000000" + }, + "b9fd3833e88e7cf1fa9879bdf55af4b99cd5ce3f": { + "balance": "1000000000000000000000" + }, + "7e268f131ddf687cc325c412f78ba961205e9112": { + "balance": "16000600000000000000000" + }, + "180478a655d78d0f3b0c4f202b61485bc4002fd5": { + "balance": "2000000000000000000000" + }, + "ed4014538cee664a2fbcb6dc669f7ab16d0ba57c": { + "balance": "200000000000000000000" + }, + "f63a579bc3eac2a9490410128dbcebe6d9de8243": { + "balance": "1490000000000000000000" + }, + "5d822d9b3ef4b502627407da272f67814a6becd4": { + "balance": "20000000000000000000" + }, + "eb52ab10553492329c1c54833ae610f398a65b9d": { + "balance": "152000000000000000000" + }, + "63340a57716bfa63eb6cd133721202575bf796f0": { + "balance": "209967000000000000000" + }, + "933bf33f8299702b3a902642c33e0bfaea5c1ca3": { + "balance": "15200000000000000000" + }, + "25bc49ef288cd165e525c661a812cf84fbec8f33": { + "balance": "338464000000000000000" + }, + "c8231ba5a411a13e222b29bfc1083f763158f226": { + "balance": "1000090000000000000000" + }, + "6c15ec3520bf8ebbc820bd0ff19778375494cf9d": { + "balance": "2005500000000000000000" + }, + "aaced8a9563b1bc311dbdffc1ae7f57519c4440c": { + "balance": "2000000000000000000000" + }, + "d90f3009db437e4e11c780bec8896f738d65ef0d": { + "balance": "4000000000000000000000" + }, + "5603241eb8f08f721e348c9d9ad92f48e390aa24": { + "balance": "200000000000000000000" + }, + "53cec6c88092f756efe56f7db11228a2db45b122": { + "balance": "4000000000000000000000" + }, + "194cebb4929882bf3b4bf9864c2b1b0f62c283f9": { + "balance": "571300000000000000000" + }, + "4be8628a8154874e048d80c142181022b180bcc1": { + "balance": "60000000000000000000" + }, + "5fd973af366aa5157c54659bcfb27cbfa5ac15d6": { + "balance": "4000000000000000000000" + }, + "303139bc596403d5d3931f774c66c4ba467454db": { + "balance": "1699830000000000000000" + }, + "87584a3f613bd4fac74c1e780b86d6caeb890cb2": { + "balance": "1700000000000000000000" + }, + "77f4e3bdf056883cc87280dbe640a18a0d02a207": { + "balance": "193806000000000000000" + }, + "4de3fe34a6fbf634c051997f47cc7f48791f5824": { + "balance": "1999000000000000000000" + }, + "c45a1ca1036b95004187cdac44a36e33a94ab5c3": { + "balance": "254800000000000000000" + }, + "65d33eb39cda6453b19e61c1fe4db93170ef9d34": { + "balance": "13370000000000000000" + }, + "f65616be9c8b797e7415227c9138faa0891742d7": { + "balance": "790000000000000000000" + }, + "e17812f66c5e65941e186c46922b6e7b2f0eeb46": { + "balance": "1820000000000000000000" + }, + "d47f50df89a1cff96513bef1b2ae3a2971accf2c": { + "balance": "840000000000000000000" + }, + "8ed1528b447ed4297902f639c514d0944a88f8c8": { + "balance": "198800000000000000000" + }, + "a4fb14409a67b45688a8593e5cc2cf596ced6f11": { + "balance": "1790000000000000000000" + }, + "855d9aef2c39c6230d09c99ef6494989abe68785": { + "balance": "161000000000000000000" + }, + "778c43d11afe3b586ff374192d96a7f23d2b9b7f": { + "balance": "2577139000000000000000" + }, + "e3ece1f632711d13bfffa1f8f6840871ee58fb27": { + "balance": "4000000000000000000000" + }, + "beb3358c50cf9f75ffc76d443c2c7f55075a0589": { + "balance": "2674000000000000000000" + }, + "f156dc0b2a981e5b55d3f2f03b8134e331dbadb7": { + "balance": "100000000000000000000" + }, + "eb9cc9fe0869d2dab52cc7aae8fd57adb35f9feb": { + "balance": "1966000000000000000000" + }, + "2467c6a5c696ede9a1e542bf1ad06bcc4b06aca0": { + "balance": "18500000000000000000" + }, + "ec75b4a47513120ba5f86039814f1998e3817ac3": { + "balance": "178756000000000000000" + }, + "9c3d0692ceeef80aa4965ceed262ffc7f069f2dc": { + "balance": "200000000000000000000" + }, + "e05029aceb0778675bef1741ab2cd2931ef7c84b": { + "balance": "5000057000000000000000" + }, + "41d3b731a326e76858baa5f4bd89b57b36932343": { + "balance": "394000000000000000000" + }, + "c346cb1fbce2ab285d8e5401f42dd7234d37e86d": { + "balance": "83500000000000000000" + }, + "45f4fc60f08eaca10598f0336329801e3c92cb46": { + "balance": "200000000000000000000" + }, + "f04a6a379708b9428d722aa2b06b77e88935cf89": { + "balance": "300000000000000000000" + }, + "232832cd5977e00a4c30d0163f2e24f088a6cb09": { + "balance": "3000000000000000000000" + }, + "d2ac0d3a58605e1d0f0eb3de25b2cad129ed6058": { + "balance": "4000000000000000000000" + }, + "a356551bb77d4f45a6d7e09f0a089e79cca249cb": { + "balance": "340000000000000000000" + }, + "b50c9f5789ae44e2dce017c714caf00c830084c2": { + "balance": "394000000000000000000" + }, + "21fd6c5d97f9c600b76821ddd4e776350fce2be0": { + "balance": "1999946000000000000000" + }, + "f0d5c31ccb6cbe30c7c9ea19f268d159851f8c9c": { + "balance": "16700000000000000000000" + }, + "ab7091932e4bc39dbb552380ca934fd7166d1e6e": { + "balance": "3340000000000000000000" + }, + "acd8dd91f714764c45677c63d852e56eb9eece2e": { + "balance": "2000000000000000000000" + }, + "57d032a43d164e71aa2ef3ffd8491b0a4ef1ea5b": { + "balance": "2000000000000000000000" + }, + "5af46a25ac09cb73616b53b14fb42ff0a51cddb2": { + "balance": "4000000000000000000000" + }, + "1ea6bf2f15ae9c1dbc64daa7f8ea4d0d81aad3eb": { + "balance": "4200000000000000000000" + }, + "03337012ae1d7ff3ee7f697c403e7780188bf0ef": { + "balance": "200000000000000000000" + }, + "32eb64be1b5dede408c6bdefbe6e405c16b7ed02": { + "balance": "1970000000000000000000" + }, + "22e2488e2da26a49ae84c01bd54b21f2947891c6": { + "balance": "1730000000000000000000" + }, + "be98a77fd41097b34f59d7589baad021659ff712": { + "balance": "900000000000000000000" + }, + "dda4ed2a58a8dd20a73275347b580d71b95bf99a": { + "balance": "399000000000000000000" + }, + "671110d96aaff11523cc546bf9940eedffb2faf7": { + "balance": "4000000000000000000000" + }, + "5d71799c8df3bccb7ee446df50b8312bc4eb71c5": { + "balance": "200000000000000000000" + }, + "ae179a460db66326743d24e67523a57b246daf7f": { + "balance": "4722920000000000000000" + }, + "198bfcf1b07ae308fa2c02069ac9dafe7135fb47": { + "balance": "20000000000000000000" + }, + "4662a1765ee921842ddc88898d1dc8627597bd7e": { + "balance": "10000000000000000000000" + }, + "783eec8aa5dac77b2e6623ed5198a431abbaee07": { + "balance": "440000000000000000000" + }, + "ed6643c0e8884b2d3211853785a08bf8f33ed29f": { + "balance": "1337000000000000000000" + }, + "5cc7d3066d45d27621f78bb4b339473e442a860f": { + "balance": "9999908000000000000000" + }, + "94ef8be45077c7d4c5652740de946a62624f713f": { + "balance": "100085000000000000000" + }, + "2f853817afd3b8f3b86e9f60ee77b5d97773c0e3": { + "balance": "1451450000000000000000" + }, + "3e0b8ed86ed669e12723af7572fbacfe829b1e16": { + "balance": "1499800000000000000000" + }, + "fa68e0cb3edf51f0a6f211c9b2cb5e073c9bffe6": { + "balance": "291200000000000000000" + }, + "2c234f505ca8dcc77d9b7e01d257c318cc19396d": { + "balance": "100000000000000000000" + }, + "f3f24fc29e20403fc0e8f5ebbb553426f78270a2": { + "balance": "100000000000000000000" + }, + "91546b79ecf69f936b5a561508b0d7e50cc5992f": { + "balance": "267400000000000000000" + }, + "435443b81dfdb9bd8c6787bc2518e2d47e57c15f": { + "balance": "5968500000000000000000" + }, + "3a06e3bb1edcfd0c44c3074de0bb606b049894a2": { + "balance": "10000000000000000000000" + }, + "3a3108c1e680a33b336c21131334409d97e5adec": { + "balance": "20000000000000000000" + }, + "2caf6bf4ec7d5a19c5e0897a5eeb011dcece4210": { + "balance": "139740000000000000000" + }, + "f44f8551ace933720712c5c491cdb6f2f951736c": { + "balance": "4000000000000000000000" + }, + "5bc1f95507b1018642e45cd9c0e22733b9b1a326": { + "balance": "100000000000000000000" + }, + "94ca56de777fd453177f5e0694c478e66aff8a84": { + "balance": "500000000000000000000" + }, + "afdd1b786162b8317e20f0e979f4b2ce486d765d": { + "balance": "20000000000000000000" + }, + "3a805fa0f7387f73055b7858ca8519edd93d634f": { + "balance": "1850000000000000000000" + }, + "8b36224c7356e751f0c066c35e3b44860364bfc2": { + "balance": "998987000000000000000" + }, + "cfecbea07c27002f65fe534bb8842d0925c78402": { + "balance": "4000000000000000000000" + }, + "482982ac1f1c6d1721feecd9b9c96cd949805055": { + "balance": "10000000000000000000000" + }, + "af880fc7567d5595cacce15c3fc14c8742c26c9e": { + "balance": "133700000000000000000" + }, + "acc1c78786ab4d2b3b277135b5ba123e0400486b": { + "balance": "78800000000000000000" + }, + "41f27e744bd29de2b0598f02a0bb9f98e681eaa4": { + "balance": "7760000000000000000000" + }, + "09a025316f967fa8b9a1d60700063f5a68001caa": { + "balance": "38200000000000000000" + }, + "391f20176d12360d724d51470a90703675594a4d": { + "balance": "1600000000000000000000" + }, + "fe4d8403216fd571572bf1bdb01d00578978d688": { + "balance": "9850000000000000000000" + }, + "900f0b8e35b668f81ef252b13855aa5007d012e7": { + "balance": "425000000000000000000" + }, + "c35b95a2a3737cb8f0f596b34524872bd30da234": { + "balance": "7540000000000000000000" + }, + "412a68f6c645559cc977fc4964047a201d1bb0e2": { + "balance": "50000000000000000000000" + }, + "d3dad1b6d08d4581ccae65a8732db6ac69f0c69e": { + "balance": "6000000000000000000000" + }, + "35855ec641ab9e081ed0c2a6dcd81354d0244a87": { + "balance": "1201897000000000000000" + }, + "88015d7203c5e0224aeda286ed12f1a51b789333": { + "balance": "4999711000000000000000" + }, + "251c12722c6879227992a304eb3576cd18434ea5": { + "balance": "2000000000000000000000" + }, + "1f6f0030349752061c96072bc3d6eb3549208d6b": { + "balance": "23891000000000000000" + }, + "86153063a1ae7f02f1a88136d4d69c7c5e3e4327": { + "balance": "1000000000000000000000" + }, + "78355df0a230f83d032c703154414de3eedab557": { + "balance": "2000000000000000000000" + }, + "c5b56cd234267c28e89c6f6b2266b086a12f970c": { + "balance": "4000000000000000000000" + }, + "3e3cd3bec06591d6346f254b621eb41c89008d31": { + "balance": "993800000000000000000" + }, + "378ea1dc8edc19bae82638029ea8752ce98bcfcd": { + "balance": "2000000000000000000000" + }, + "67632046dcb25a54936928a96f423f3320cbed92": { + "balance": "2000000000000000000000" + }, + "ddbee6f094eae63420b003fb4757142aea6cd0fd": { + "balance": "2000000000000000000000" + }, + "b555d00f9190cc3677aef314acd73fdc39399259": { + "balance": "2000000000000000000000" + }, + "e230fe1bff03186d0219f15d4c481b7d59be286a": { + "balance": "36710000000000000000" + }, + "3e4e9265223c9738324cf20bd06006d0073edb8c": { + "balance": "133700000000000000000" + }, + "7450ff7f99eaa9116275deac68e428df5bbcd8b9": { + "balance": "2000000000000000000000" + }, + "021f69043de88c4917ca10f1842897eec0589c7c": { + "balance": "1978760000000000000000" + }, + "351787843505f8e4eff46566cce6a59f4d1c5fe7": { + "balance": "9250000000000000000000" + }, + "ebd37b256563e30c6f9289a8e2702f0852880833": { + "balance": "1999944000000000000000" + }, + "ed41e1a28f5caa843880ef4e8b08bd6c33141edf": { + "balance": "790174000000000000000" + }, + "8d238e036596987643d73173c37b0ad06055b96c": { + "balance": "2089724000000000000000" + }, + "478e524ef2a381d70c82588a93ca7a5fa9d51cbf": { + "balance": "254908000000000000000000" + }, + "4419ac618d5dea7cdc6077206fb07dbdd71c1702": { + "balance": "4000000000000000000000" + }, + "ca25ff34934c1942e22a4e7bd56f14021a1af088": { + "balance": "197000000000000000000" + }, + "5552f4b3ed3e1da79a2f78bb13e8ae5a68a9df3b": { + "balance": "1000000000000000000000" + }, + "4354221e62dc09e6406436163a185ef06d114a81": { + "balance": "2000000000000000000000" + }, + "ca0432cb157b5179f02ebba5c9d1b54fec4d88ca": { + "balance": "1000000000000000000000" + }, + "8a780ab87a9145fe10ed60fa476a740af4cab1d2": { + "balance": "334000000000000000000" + }, + "4ff676e27f681a982d8fd9d20e648b3dce05e945": { + "balance": "2800000000000000000000" + }, + "6c63fc85029a2654d79b2bea4de349e4524577c5": { + "balance": "660000000000000000000" + }, + "1ac089c3bc4d82f06a20051a9d732dc0e734cb61": { + "balance": "700300000000000000000" + }, + "4bf4479799ef82eea20943374f56a1bf54001e5e": { + "balance": "3940000000000000000000" + }, + "08411652c871713609af0062a8a1281bf1bbcfd9": { + "balance": "1400000000000000000000" + }, + "e1bfaa5a45c504428923c4a61192a55b1400b45d": { + "balance": "2674000000000000000000" + }, + "5e1fbd4e58e2312b3c78d7aaaafa10bf9c3189e3": { + "balance": "40000000000000000000000" + }, + "bb27c6a7f91075475ab229619040f804c8ec7a6a": { + "balance": "10000000000000000000000" + }, + "5d8d31faa864e22159cd6f5175ccecc53fa54d72": { + "balance": "26980000000000000000000" + }, + "2dd8eeef87194abc2ce7585da1e35b7cea780cb7": { + "balance": "999999000000000000000" + }, + "0e1801e70b6262861b1134ccbc391f568afc92f7": { + "balance": "4000000000000000000000" + }, + "61042b80fd6095d1b87be2f00f109fabafd157a6": { + "balance": "100000000000000000000" + }, + "fb5518714cefc36d04865de5915ef0ff47dfe743": { + "balance": "2000000000000000000000" + }, + "b5add1e7809f7d03069bfe883b0a932210be8712": { + "balance": "1000000000000000000000" + }, + "c2e2d498f70dcd0859e50b023a710a6d4b2133bd": { + "balance": "1037130000000000000000" + }, + "4ad047fae67ef162fe68fedbc27d3b65caf10c36": { + "balance": "1970000000000000000000" + }, + "69cb3e2153998d86e5ee20c1fcd1a6baeeb2863f": { + "balance": "4000000000000000000000" + }, + "683633010a88686bea5a98ea53e87997cbf73e69": { + "balance": "99960000000000000000" + }, + "6cb11ecb32d3ce829601310636f5a10cf7cf9b5f": { + "balance": "20068370000000000000000" + }, + "a613456996408af1c2e93e177788ab55895e2b32": { + "balance": "6366000000000000000000" + }, + "8308ed0af7f8a3c1751fafc877b5a42af7d35882": { + "balance": "1000000000000000000000" + }, + "e5edf8123f2403ce1a0299becf7aac744d075f23": { + "balance": "200200000000000000000" + }, + "05665155cc49cbf6aabdd5ae92cbfaad82b8c0c1": { + "balance": "400000000000000000000" + }, + "00b277b099a8e866ca0ec65bcb87284fd142a582": { + "balance": "1970000000000000000000" + }, + "4b9e068fc4680976e61504912985fd5ce94bab0d": { + "balance": "668500000000000000000" + }, + "12134e7f6b017bf48e855a399ca58e2e892fa5c8": { + "balance": "1000000000000000000000" + }, + "dffcea5421ec15900c6ecfc777184e140e209e24": { + "balance": "19980000000000000000" + }, + "2132c0516a2e17174ac547c43b7b0020d1eb4c59": { + "balance": "985000000000000000000" + }, + "d39a5da460392b940b3c69bc03757bf3f2e82489": { + "balance": "7019250000000000000000" + }, + "66c8331efe7198e98b2d32b938688e3241d0e24f": { + "balance": "9620000000000000000000" + }, + "bdca2a0ff34588af625fa8e28fc3015ab5a3aa00": { + "balance": "2339800000000000000000" + }, + "7dfc342dffcf45dfee74f84c0995397bd1a63172": { + "balance": "250000000000000000000" + }, + "a202547242806f6e70e74058d6e5292defc8c8d4": { + "balance": "2002000000000000000000" + }, + "3bbc13d04accc0707aebdcaef087d0b87e0b5ee3": { + "balance": "3520000000000000000000" + }, + "be5cba8d37427986e8ca2600e858bb03c359520f": { + "balance": "2955000000000000000000" + }, + "4174fa1bc12a3b7183cbabb77a0b59557ba5f1db": { + "balance": "2000000000000000000000" + }, + "9eb3a7cb5e6726427a3a361cfa8d6164dbd0ba16": { + "balance": "804000000000000000000" + }, + "25e661c939863acc044e6f17b5698cce379ec3cc": { + "balance": "1370000000000000000000" + }, + "24bd5904059091d2f9e12d6a26a010ca22ab14e8": { + "balance": "1880000000000000000000" + }, + "c96626728aaa4c4fb3d31c26df3af310081710d1": { + "balance": "3340000000000000000000" + }, + "0fb5d2c673bfb1ddca141b9894fd6d3f05da6720": { + "balance": "100000000000000000000" + }, + "2de31afd189a13a76ff6fe73ead9f74bb5c4a629": { + "balance": "6000000000000000000000" + }, + "bd09126c891c4a83068059fe0e15796c4661a9f4": { + "balance": "800000000000000000000" + }, + "496f5843f6d24cd98d255e4c23d1e1f023227545": { + "balance": "1754143000000000000000" + }, + "540cf23dd95c4d558a279d778d2b3735b3164191": { + "balance": "10000000000000000000000" + }, + "9b5ec18e8313887df461d2902e81e67a8f113bb1": { + "balance": "100000000000000000000" + }, + "b7a7f77c348f92a9f1100c6bd829a8ac6d7fcf91": { + "balance": "1820000000000000000000" + }, + "2590126870e0bde8a663ab040a72a5573d8d41c2": { + "balance": "5000000000000000000000" + }, + "090fa9367bda57d0d3253a0a8ff76ce0b8e19a73": { + "balance": "1000000000000000000000" + }, + "2a5ba9e34cd58da54c9a2712663a3be274c8e47b": { + "balance": "197000000000000000000" + }, + "3e8641d43c42003f0a33c929f711079deb2b9e46": { + "balance": "500000000000000000000" + }, + "f4d97664cc4eec9edbe7fa09f4750a663b507d79": { + "balance": "4000000000000000000000" + }, + "b1540e94cff3465cc3d187e7c8e3bdaf984659e2": { + "balance": "2989950000000000000000" + }, + "f96883582459908c827627e86f28e646f9c7fc7a": { + "balance": "8350000000000000000000" + }, + "d4feed99e8917c5c5458635f3603ecb7e817a7d0": { + "balance": "300031000000000000000" + }, + "14b1603ec62b20022033eec4d6d6655ac24a015a": { + "balance": "50000000000000000000" + }, + "af8e1dcb314c950d3687434d309858e1a8739cd4": { + "balance": "267400000000000000000" + }, + "4b9206ba6b549a1a7f969e1d5dba867539d1fa67": { + "balance": "7880000000000000000000" + }, + "471010da492f4018833b088d9872901e06129174": { + "balance": "500000000000000000000" + }, + "d243184c801e5d79d2063f3578dbae81e7b3a9cb": { + "balance": "1989700000000000000000" + }, + "3eada8c92f56067e1bb73ce378da56dc2cdfd365": { + "balance": "2210000000000000000000" + }, + "33ea6b7855e05b07ab80dab1e14de9b649e99b6c": { + "balance": "532000000000000000000" + }, + "700711e311bb947355f755b579250ca7fd765a3e": { + "balance": "1790000000000000000000" + }, + "87fb26c31e48644d693134205cae43b21f18614b": { + "balance": "1370000000000000000000" + }, + "001d14804b399c6ef80e64576f657660804fec0b": { + "balance": "4200000000000000000000" + }, + "f9642086b1fbae61a6804dbe5fb15ec2d2b537f4": { + "balance": "2000000000000000000000" + }, + "6919dd5e5dfb1afa404703b9faea8cee35d00d70": { + "balance": "5910000000000000000000" + }, + "9ac4da51d27822d1e208c96ea64a1e5b55299723": { + "balance": "100040000000000000000" + }, + "1bd8ebaa7674bb18e19198db244f570313075f43": { + "balance": "150000000000000000000" + }, + "e64ef012658d54f8e8609c4e9023c09fe865c83b": { + "balance": "28000000000000000000" + }, + "43b079baf0727999e66bf743d5bcbf776c3b0922": { + "balance": "2000000000000000000000" + }, + "06ac26ad92cb859bd5905ddce4266aa0ec50a9c5": { + "balance": "775000000000000000000" + }, + "99c1d9f40c6ab7f8a92fce2fdce47a54a586c53f": { + "balance": "985000000000000000000" + }, + "4ae93082e45187c26160e66792f57fad3551c73a": { + "balance": "21658000000000000000000" + }, + "7da7613445a21299aa74f0ad71431ec43fbb1be9": { + "balance": "68000000000000000000" + }, + "4a9a26fd0a8ba10f977da4f77c31908dab4a8016": { + "balance": "1790000000000000000000" + }, + "972c2f96aa00cf8a2f205abcf8937c0c75f5d8d9": { + "balance": "200000000000000000000" + }, + "b5046cb3dc1dedbd364514a2848e44c1de4ed147": { + "balance": "16445100000000000000000" + }, + "48c2ee91a50756d8ce9abeeb7589d22c6fee5dfb": { + "balance": "3220000000000000000000" + }, + "46c1aa2244b9c8a957ca8fac431b0595a3b86824": { + "balance": "4000000000000000000000" + }, + "21fd0bade5f4ef7474d058b7f3d854cb1300524e": { + "balance": "20000000000000000000" + }, + "1864a3c7b48155448c54c88c708f166709736d31": { + "balance": "133700000000000000000" + }, + "5dd53ae897526b167d39f1744ef7c3da5b37a293": { + "balance": "8000000000000000000000" + }, + "ece111670b563ccdbebca52384290ecd68fe5c92": { + "balance": "20000000000000000000" + }, + "74d671d99cbea1ab57906375b63ff42b50451d17": { + "balance": "1000000000000000000000" + }, + "5717cc9301511d4a81b9f583148beed3d3cc8309": { + "balance": "2600000000000000000000" + }, + "8f92844f282a92999ee5b4a8d773d06b694dbd9f": { + "balance": "1940000000000000000000" + }, + "b5a606f4ddcbb9471ec67f658caf2b00ee73025e": { + "balance": "4325000000000000000000" + }, + "bdb60b823a1173d45a0792245fb496f1fd3301cf": { + "balance": "2000000000000000000000" + }, + "1d2615f8b6ca5012b663bdd094b0c5137c778ddf": { + "balance": "10000000000000000000000" + }, + "82ff716fdf033ec7e942c909d9831867b8b6e2ef": { + "balance": "1790000000000000000000" + }, + "44c14765127cde11fab46c5d2cf4d4b2890023fd": { + "balance": "2000000000000000000000" + }, + "c72cb301258e91bc08998a805dd192f25c2f9a35": { + "balance": "591000000000000000000" + }, + "ad732c976593eec4783b4e2ecd793979780bfedb": { + "balance": "2000000000000000000000" + }, + "d8f62036f03b7635b858f1103f8a1d9019a892b6": { + "balance": "50000000000000000000" + }, + "0a06fad7dcd7a492cbc053eeabde6934b39d8637": { + "balance": "20000000000000000000" + }, + "67f2bb78b8d3e11f7c458a10b5c8e0a1d374467d": { + "balance": "1790000000000000000000" + }, + "4b5cdb1e428c91dd7cb54a6aed4571da054bfe52": { + "balance": "88000000000000000000" + }, + "b3557d39b5411b84445f5f54f38f62d2714d0087": { + "balance": "600000000000000000000" + }, + "0b0e055b28cbd03dc5ff44aa64f3dce04f5e63fb": { + "balance": "2000000000000000000000" + }, + "9b2be7f56754f505e3441a10f7f0e20fd3ddf849": { + "balance": "340000000000000000000" + }, + "0b93fca4a4f09cac20db60e065edcccc11e0a5b6": { + "balance": "200000000000000000000" + }, + "3bc85d6c735b9cda4bba5f48b24b13e70630307b": { + "balance": "1970000000000000000000" + }, + "52102354a6aca95d8a2e86d5debda6de69346076": { + "balance": "2000000000000000000000" + }, + "cda4530f4b9bc50905b79d17c28fc46f95349bdf": { + "balance": "942000000000000000000" + }, + "ff545bbb66fbd00eb5e6373ff4e326f5feb5fe12": { + "balance": "20000000000000000000" + }, + "4030a925706b2c101c8c5cb9bd05fbb4f6759b18": { + "balance": "4000000000000000000000" + }, + "f11e01c7a9d12499005f4dae7716095a34176277": { + "balance": "400000000000000000000" + }, + "a4826b6c3882fad0ed5c8fbb25cc40cc4f33759f": { + "balance": "2068000000000000000000" + }, + "28510e6eff1fc829b6576f4328bc3938ec7a6580": { + "balance": "10000000000000000000000" + }, + "9ce5363b13e8238aa4dd15acd0b2e8afe0873247": { + "balance": "200000000000000000000" + }, + "d97bc84abd47c05bbf457b2ef659d61ca5e5e48f": { + "balance": "122000000000000000000" + }, + "4a719061f5285495b37b9d7ef8a51b07d6e6acac": { + "balance": "199800000000000000000" + }, + "8b714522fa2839620470edcf0c4401b713663df1": { + "balance": "200000000000000000000" + }, + "b6decf82969819ba02de29b9b593f21b64eeda0f": { + "balance": "740000000000000000000" + }, + "c87d3ae3d88704d9ab0009dcc1a0067131f8ba3c": { + "balance": "1969606000000000000000" + }, + "dccb370ed68aa922283043ef7cad1b9d403fc34a": { + "balance": "4000000000000000000000" + }, + "2d532df4c63911d1ce91f6d1fcbff7960f78a885": { + "balance": "1669833000000000000000" + }, + "1fcfd1d57f872290560cb62d600e1defbefccc1c": { + "balance": "1490000000000000000000" + }, + "d9e27eb07dfc71a706060c7f079238ca93e88539": { + "balance": "1000000000000000000000" + }, + "da7732f02f2e272eaf28df972ecc0ddeed9cf498": { + "balance": "205274000000000000000" + }, + "bf09d77048e270b662330e9486b38b43cd781495": { + "balance": "436000000000000000000000" + }, + "619f171445d42b02e2e07004ad8afe694fa53d6a": { + "balance": "20000000000000000000" + }, + "2bdd03bebbee273b6ca1059b34999a5bbd61bb79": { + "balance": "20000000000000000000" + }, + "8da1d359ba6cb4bcc57d7a437720d55db2f01c72": { + "balance": "80000000000000000000" + }, + "be935793f45b70d8045d2654d8dd3ad24b5b6137": { + "balance": "880000000000000000000" + }, + "ee71793e3acf12a7274f563961f537529d89c7de": { + "balance": "2000000000000000000000" + }, + "86f05d19063e9369c6004eb3f123943a7cff4eab": { + "balance": "1999944000000000000000" + }, + "87b10f9c280098179a2b76e9ce90be61fc844d0d": { + "balance": "1337000000000000000000" + }, + "243c84d12420570cc4ef3baba1c959c283249520": { + "balance": "2345000000000000000000" + }, + "6bc85acd5928722ef5095331ee88f484b8cf8357": { + "balance": "180000000000000000000" + }, + "2561a138dcf83bd813e0e7f108642be3de3d6f05": { + "balance": "999940000000000000000" + }, + "7d0350e40b338dda736661872be33f1f9752d755": { + "balance": "49933000000000000000" + }, + "e5dc9349cb52e161196122cf87a38936e2c57f34": { + "balance": "2000000000000000000000" + }, + "543a8c0efb8bcd15c543e2a6a4f807597631adef": { + "balance": "5893800000000000000000" + }, + "0413d0cf78c001898a378b918cd6e498ea773c4d": { + "balance": "280000000000000000000" + }, + "3708e59de6b4055088782902e0579c7201a8bf50": { + "balance": "200000000000000000000000" + }, + "699fc6d68a4775573c1dcdaec830fefd50397c4e": { + "balance": "60000000000000000000" + }, + "379a7f755a81a17edb7daaa28afc665dfa6be63a": { + "balance": "25000000000000000000" + }, + "260a230e4465077e0b14ee4442a482d5b0c914bf": { + "balance": "1677935000000000000000" + }, + "3daa01ceb70eaf9591fa521ba4a27ea9fb8ede4a": { + "balance": "1667400000000000000000" + }, + "7f3a1e45f67e92c880e573b43379d71ee089db54": { + "balance": "100000000000000000000000" + }, + "38643babea6011316cc797d9b093c897a17bdae7": { + "balance": "334400000000000000000" + }, + "84675e9177726d45eaa46b3992a340ba7f710c95": { + "balance": "1000000000000000000000" + }, + "0f83461ba224bb1e8fdd9dae535172b735acb4e0": { + "balance": "200000000000000000000" + }, + "31aa3b1ebe8c4dbcb6a708b1d74831e60e497660": { + "balance": "400000000000000000000" + }, + "a32cf7dde20c3dd5679ff5e325845c70c5962662": { + "balance": "20000000000000000000" + }, + "c007f0bdb6e7009202b7af3ea90902697c721413": { + "balance": "2999966000000000000000" + }, + "05c64004a9a826e94e5e4ee267fa2a7632dd4e6f": { + "balance": "16191931000000000000000" + }, + "f622e584a6623eaaf99f2be49e5380c5cbcf5cd8": { + "balance": "200000000000000000000" + }, + "9dc10fa38f9fb06810e11f60173ec3d2fd6a751e": { + "balance": "1970000000000000000000" + }, + "423c3107f4bace414e499c64390a51f74615ca5e": { + "balance": "2000000000000000000000" + }, + "92438e5203b6346ff886d7c36288aacccc78ceca": { + "balance": "1000000000000000000000" + }, + "bef07d97c3481f9d6aee1c98f9d91a180a32442b": { + "balance": "100000000000000000000000" + }, + "55aa5d313ebb084da0e7801091e29e92c5dec3aa": { + "balance": "2000000000000000000000" + }, + "89c433d601fad714da6369308fd26c1dc9942bbf": { + "balance": "2000000000000000000000" + }, + "25106ab6755df86d6b63a187703b0cfea0e594a0": { + "balance": "27400000000000000000" + }, + "494256e99b0f9cd6e5ebca3899863252900165c8": { + "balance": "14000000000000000000000" + }, + "5f4ace4c1cc13391e01f00b198e1f20b5f91cbf5": { + "balance": "5000196000000000000000" + }, + "135cecd955e5798370769230159303d9b1839f66": { + "balance": "5000000000000000000000" + }, + "ced81ec3533ff1bfebf3e3843ee740ad11758d3e": { + "balance": "1970000000000000000000" + }, + "688eb3853bbcc50ecfee0fa87f0ab693cabdef02": { + "balance": "31600000000000000000000" + }, + "2159240813a73095a7ebf7c3b3743e8028ae5f09": { + "balance": "2000000000000000000000" + }, + "99d1579cd42682b7644e1d4f7128441eeffe339d": { + "balance": "20000000000000000000000" + }, + "8a243a0a9fea49b839547745ff2d11af3f4b0522": { + "balance": "985000000000000000000" + }, + "c1a41a5a27199226e4c7eb198b031b59196f9842": { + "balance": "191000000000000000000" + }, + "7514adbdc63f483f304d8e94b67ff3309f180b82": { + "balance": "622911000000000000000" + }, + "74aeec915de01cc69b2cb5a6356feea14658c6c5": { + "balance": "232500000000000000000" + }, + "76f9ad3d9bbd04ae055c1477c0c35e7592cb2a20": { + "balance": "40200000000000000000000" + }, + "a8a7b68adab4e3eadff19ffa58e34a3fcec0d96a": { + "balance": "6000000000000000000000" + }, + "60de22a1507432a47b01cc68c52a0bf8a2e0d098": { + "balance": "19100000000000000000" + }, + "ceb33d78e7547a9da2e87d51aec5f3441c87923a": { + "balance": "20000000000000000000" + }, + "432809a2390f07c665921ff37d547d12f1c9966a": { + "balance": "30000000000000000000000" + }, + "d5e656a1b916f9bf45afb07dd8afaf73b4c56f41": { + "balance": "97000000000000000000" + }, + "e3410bb7557cf91d79fa69d0dfea0aa075402651": { + "balance": "2000000000000000000000" + }, + "dee942d5caf5fac11421d86b010b458e5c392990": { + "balance": "4000000000000000000000" + }, + "a98f109835f5eacd0543647c34a6b269e3802fac": { + "balance": "400000000000000000000" + }, + "932b9c04d40d2ac83083d94298169dae81ab2ed0": { + "balance": "2000000000000000000000" + }, + "ba10f2764290f875434372f79dbf713801caac01": { + "balance": "955000000000000000000" + }, + "a2c7eaffdc2c9d937345206c909a52dfb14c478f": { + "balance": "143000000000000000000" + }, + "6c67e0d7b62e2a08506945a5dfe38263339f1f22": { + "balance": "1970000000000000000000" + }, + "60c3714fdddb634659e4a2b1ea42c4728cc7b8ba": { + "balance": "13370000000000000000" + }, + "73b4d499de3f38bf35aaf769a6e318bc6d123692": { + "balance": "2000000000000000000000" + }, + "3b22dea3c25f1b59c7bd27bb91d3a3eaecef3984": { + "balance": "100000000000000000000" + }, + "1e3badb1b6e1380e27039c576ae6222e963a5b53": { + "balance": "20000000000000000000000" + }, + "abd4d6c1666358c0406fdf3af248f78ece830104": { + "balance": "2112000000000000000000" + }, + "0c925ad5eb352c8ef76d0c222d115b0791b962a1": { + "balance": "3180000000000000000000" + }, + "be9186c34a52514abb9107860f674f97b821bd5b": { + "balance": "509600000000000000000" + }, + "b7f67314cb832e32e63b15a40ce0d7ffbdb26985": { + "balance": "1060866000000000000000" + }, + "3f30d3bc9f602232bc724288ca46cd0b0788f715": { + "balance": "4000000000000000000000" + }, + "970abd53a54fca4a6429207c182d4d57bb39d4a0": { + "balance": "2000000000000000000000" + }, + "36d85dc3683156e63bf880a9fab7788cf8143a27": { + "balance": "20000000000000000000000" + }, + "2836123046b284e5ef102bfd22b1765e508116ad": { + "balance": "411880000000000000000" + }, + "de06d5ea777a4eb1475e605dbcbf43444e8037ea": { + "balance": "50000000000000000000000" + }, + "9af11399511c213181bfda3a8b264c05fc81b3ce": { + "balance": "14000000000000000000000" + }, + "e2191215983f33fd33e22cd4a2490054da53fddc": { + "balance": "15800000000000000000" + }, + "2eebf59432b52892f9380bd140aa99dcf8ad0c0f": { + "balance": "152000000000000000000" + }, + "dc087f9390fb9e976ac23ab689544a0942ec2021": { + "balance": "1820000000000000000000" + }, + "fd4b989558ae11be0c3b36e2d6f2a54a9343ca2e": { + "balance": "2000000000000000000000" + }, + "770c2fb2c4a81753ac0182ea460ec09c90a516f8": { + "balance": "20000000000000000000" + }, + "b28dbfc6499894f73a71faa00abe0f4bc9d19f2a": { + "balance": "100000000000000000000" + }, + "b0cef8e8fb8984a6019f01c679f272bbe68f5c77": { + "balance": "152000000000000000000" + }, + "f400f93d5f5c7e3fc303129ac8fb0c2f786407fa": { + "balance": "2000000000000000000000" + }, + "f2133431d1d9a37ba2f0762bc40c5acc8aa6978e": { + "balance": "2000000000000000000000" + }, + "9003d270891ba2df643da8341583193545e3e000": { + "balance": "4000000000000000000000" + }, + "8938d1b4daee55a54d738cf17e4477f6794e46f7": { + "balance": "18200000000000000000" + }, + "98e6f547db88e75f1f9c8ac2c5cf1627ba580b3e": { + "balance": "1000000000000000000000" + }, + "009fdbf44e1f4a6362b769c39a475f95a96c2bc7": { + "balance": "564000000000000000000" + }, + "d0f9597811b0b992bb7d3757aa25b4c2561d32e2": { + "balance": "500000000000000000000" + }, + "dcd10c55bb854f754434f1219c2c9a98ace79f03": { + "balance": "4000086000000000000000" + }, + "67048f3a12a4dd1f626c64264cb1d7971de2ca38": { + "balance": "180000000000000000000" + }, + "d33cf82bf14c592640a08608914c237079d5be34": { + "balance": "2000000000000000000000" + }, + "f5b068989df29c253577d0405ade6e0e7528f89e": { + "balance": "1610000000000000000000" + }, + "a9a8eca11a23d64689a2aa3e417dbb3d336bb59a": { + "balance": "262025000000000000000" + }, + "99413704b1a32e70f3bc0d69dd881c38566b54cb": { + "balance": "27382708000000000000000" + }, + "2a085e25b64862f5e68d768e2b0f7a8529858eee": { + "balance": "1983618000000000000000" + }, + "833d3fae542ad5f8b50ce19bde2bec579180c88c": { + "balance": "346000000000000000000" + }, + "c3483d6e88ac1f4ae73cc4408d6c03abe0e49dca": { + "balance": "17000000000000000000000" + }, + "fde395bc0b6d5cbb4c1d8fea3e0b4bff635e9db7": { + "balance": "2000000000000000000000" + }, + "eddacd94ec89a2ef968fcf977a08f1fae2757869": { + "balance": "8000000000000000000000" + }, + "dc29119745d2337320da51e19100c948d980b915": { + "balance": "160000000000000000000" + }, + "640bf87415e0cf407301e5599a68366da09bbac8": { + "balance": "493207000000000000000" + }, + "afcc7dbb8356d842d43ae7e23c8422b022a30803": { + "balance": "30400000000000000000000" + }, + "9120e71173e1ba19ba8f9f4fdbdcaa34e1d6bb78": { + "balance": "2000000000000000000000" + }, + "9092918707c621fdbd1d90fb80eb787fd26f7350": { + "balance": "2460000000000000000000" + }, + "263e57dacbe0149f82fe65a2664898866ff5b463": { + "balance": "38000000000000000000000" + }, + "315db7439fa1d5b423afa7dd7198c1cf74c918bc": { + "balance": "600000000000000000000" + }, + "09b4668696f86a080f8bebb91db8e6f87015915a": { + "balance": "656010000000000000000" + }, + "5c31996dcac015f9be985b611f468730ef244d90": { + "balance": "200000000000000000000" + }, + "b1179589e19db9d41557bbec1cb24ccc2dec1c7f": { + "balance": "100000000000000000000000" + }, + "3b1937d5e793b89b63fb8eb5f1b1c9ca6ba0fa8e": { + "balance": "2000000000000000000000" + }, + "c9127b7f6629ee13fc3f60bc2f4467a20745a762": { + "balance": "16465639000000000000000" + }, + "7306de0e288b56cfdf987ef0d3cc29660793f6dd": { + "balance": "508060000000000000000" + }, + "2aa192777ca5b978b6b2c2ff800ac1860f753f47": { + "balance": "335000000000000000000" + }, + "55da9dcdca61cbfe1f133c7bcefc867b9c8122f9": { + "balance": "880000000000000000000" + }, + "cdd9efac4d6d60bd71d95585dce5d59705c13564": { + "balance": "100000000000000000000" + }, + "ad8e48a377695de014363a523a28b1a40c78f208": { + "balance": "1000000000000000000000" + }, + "252b6555afdc80f2d96d972d17db84ea5ad521ac": { + "balance": "7880000000000000000000" + }, + "60ab71cd26ea6d6e59a7a0f627ee079c885ebbf6": { + "balance": "26740000000000000000" + }, + "f40b134fea22c6b29c8457f49f000f9cda789adb": { + "balance": "600000000000000000000" + }, + "85a2f6ea94d05e8c1d9ae2f4910338a358e98ded": { + "balance": "2000000000000000000000" + }, + "ae13a08511110f32e53be4127845c843a1a57c7b": { + "balance": "500000000000000000000" + }, + "40db1ba585ce34531edec5494849391381e6ccd3": { + "balance": "1790000000000000000000" + }, + "0c5589a7a89b9ad15b02751930415948a875fbef": { + "balance": "126000000000000000000" + }, + "89054430dcdc28ac15fa635ef87c105e602bf70c": { + "balance": "108000000000000000000" + }, + "6c882c27732cef5c7c13a686f0a2ea77555ac289": { + "balance": "100000000000000000000000" + }, + "de374299c1d07d79537385190f442ef9ca24061f": { + "balance": "133700000000000000000" + }, + "b146a0b925553cf06fcaf54a1b4dfea621290757": { + "balance": "2000200000000000000000" + }, + "09ae49e37f121df5dc158cfde806f173a06b0c7f": { + "balance": "3988000000000000000000" + }, + "b758896f1baa864f17ebed16d953886fee68aae6": { + "balance": "1000000000000000000000" + }, + "30730466b8eb6dc90d5496aa76a3472d7dbe0bbe": { + "balance": "1999800000000000000000" + }, + "fc02734033e57f70517e0afc7ee62461f06fad8e": { + "balance": "394000000000000000000" + }, + "a9b2d2e0494eab18e07d37bbb856d80e80f84cd3": { + "balance": "10000000000000000000000" + }, + "95278b08dee7c0f2c8c0f722f9fcbbb9a5241fda": { + "balance": "2408672000000000000000" + }, + "dab6bcdb83cf24a0ae1cb21b3b5b83c2f3824927": { + "balance": "50000000000000000000000" + }, + "94439ca9cc169a79d4a09cae5e67764a6f871a21": { + "balance": "240000000000000000000" + }, + "e06c29a81517e0d487b67fb0b6aabc4f57368388": { + "balance": "401100000000000000000" + }, + "458e3cc99e947844a18e6a42918fef7e7f5f5eb3": { + "balance": "36400000000000000000000" + }, + "0a9804137803ba6868d93a55f9985fcd540451e4": { + "balance": "13370000000000000000" + }, + "40630024bd2c58d248edd8465617b2bf1647da0e": { + "balance": "1000000000000000000000" + }, + "15224ad1c0face46f9f556e4774a3025ad06bd52": { + "balance": "13370000000000000000" + }, + "2e2810dee44ae4dff3d86342ab126657d653c336": { + "balance": "200000000000000000000" + }, + "48a30de1c919d3fd3180e97d5f2b2a9dbd964d2d": { + "balance": "44000000000000000000" + }, + "46a30b8a808931217445c3f5a93e882c0345b426": { + "balance": "250019000000000000000" + }, + "455396a4bbd9bae8af9fb7c4d64d471db9c24505": { + "balance": "161000000000000000000" + }, + "edfda2d5db98f9380714664d54b4ee971a1cae03": { + "balance": "40044000000000000000" + }, + "f5eadcd2d1b8657a121f33c458a8b13e76b65526": { + "balance": "249828000000000000000" + }, + "90e7070f4d033fe6910c9efe5a278e1fc6234def": { + "balance": "100392000000000000000" + }, + "d55508adbbbe9be81b80f97a6ea89add68da674f": { + "balance": "2000000000000000000000" + }, + "66925de3e43f4b41bf9dadde27d5488ef569ea0d": { + "balance": "39400000000000000000" + }, + "b7c077946674ba9341fb4c747a5d50f5d2da6415": { + "balance": "1000000000000000000000" + }, + "c52d1a0c73c2a1be84915185f8b34faa0adf1de3": { + "balance": "1400001000000000000000" + }, + "79b8aad879dd30567e8778d2d231c8f37ab8734e": { + "balance": "2000000000000000000000" + }, + "3aae4872fd9093cbcad1406f1e8078bab50359e2": { + "balance": "39400000000000000000" + }, + "b2e9d76bf50fc36bf7d3944b63e9ca889b699968": { + "balance": "2660000000000000000000" + }, + "405f596b94b947344c033ce2dcbff12e25b79784": { + "balance": "2000000000000000000000" + }, + "232cb1cd49993c144a3f88b3611e233569a86bd6": { + "balance": "15576000000000000000000" + }, + "9e232c08c14dc1a6ed0b8a3b2868977ba5c17d10": { + "balance": "20000000000000000000" + }, + "095270cc42141dd998ad2862dbd1fe9b44e7e650": { + "balance": "1200000000000000000000" + }, + "15d99468507aa0413fb60dca2adc7f569cb36b54": { + "balance": "2000000000000000000000" + }, + "04852732b4c652f6c2e58eb36587e60a62da14db": { + "balance": "20000000000000000000000" + }, + "ecf24cdd7c22928c441e694de4aa31b0fab59778": { + "balance": "600000000000000000000" + }, + "512b91bbfaa9e581ef683fc90d9db22a8f49f48b": { + "balance": "310000000000000000000000" + }, + "a88577a073fbaf33c4cd202e00ea70ef711b4006": { + "balance": "2000000000000000000000" + }, + "00acc6f082a442828764d11f58d6894ae408f073": { + "balance": "60000000000000000000000" + }, + "0355bcacbd21441e95adeedc30c17218c8a408ce": { + "balance": "400000000000000000000" + }, + "4e73cf2379f124860f73d6d91bf59acc5cfc845b": { + "balance": "40110000000000000000" + }, + "2a742b8910941e0932830a1d9692cfd28494cf40": { + "balance": "499986000000000000000" + }, + "41a8c2830081b102df6e0131657c07ab635b54ce": { + "balance": "1999944000000000000000" + }, + "b63064bd3355e6e07e2d377024125a33776c4afa": { + "balance": "38800000000000000000000" + }, + "1a25e1c5bc7e5f50ec16f8885f210ea1b938800e": { + "balance": "4000000000000000000000" + }, + "09b59b8698a7fbd3d2f8c73a008988de3e406b2b": { + "balance": "40000000000000000000000" + }, + "c555b93156f09101233c6f7cf6eb3c4f196d3346": { + "balance": "3000000000000000000000" + }, + "12f32c0a1f2daab676fe69abd9e018352d4ccd45": { + "balance": "50000000000000000000" + }, + "5956b28ec7890b76fc061a1feb52d82ae81fb635": { + "balance": "2000000000000000000000" + }, + "c739259e7f85f2659bef5f609ed86b3d596c201e": { + "balance": "200000000000000000000" + }, + "fae92c1370e9e1859a5df83b56d0f586aa3b404c": { + "balance": "106480000000000000000" + }, + "d5a7bec332adde18b3104b5792546aa59b879b52": { + "balance": "2000000000000000000000" + }, + "4f88dfd01091a45a9e2676021e64286cd36b8d34": { + "balance": "1000000000000000000000" + }, + "102c477d69aadba9a0b0f62b7459e17fbb1c1561": { + "balance": "2000000000000000000000" + }, + "34272d5e7574315dcae9abbd317bac90289d4765": { + "balance": "1820000000000000000000" + }, + "fe615d975c0887e0c9113ec7298420a793af8b96": { + "balance": "8000000000000000000000" + }, + "487adf7d70a6740f8d51cbdd68bb3f91c4a5ce68": { + "balance": "66850000000000000000" + }, + "7e5d9993104e4cb545e179a2a3f971f744f98482": { + "balance": "2000000000000000000000" + }, + "5529830a61c1f13c197e550beddfd6bd195c9d02": { + "balance": "10000000000000000000000" + }, + "2f282abbb6d4a3c3cd3b5ca812f7643e80305f06": { + "balance": "1850000000000000000000" + }, + "7352586d021ad0cf77e0e928404a59f374ff4582": { + "balance": "3400000000000000000000" + }, + "03f7b92008813ae0a676eb212814afab35221069": { + "balance": "2000000000000000000000" + }, + "056686078fb6bcf9ba0a8a8dc63a906f5feac0ea": { + "balance": "499800000000000000000" + }, + "8063379a7bf2cb923a84c5093e68dac7f75481c5": { + "balance": "322102000000000000000" + }, + "200264a09f8c68e3e6629795280f56254f8640d0": { + "balance": "20000000000000000000" + }, + "5a891155f50e42074374c739baadf7df2651153a": { + "balance": "4775000000000000000000" + }, + "80022a1207e910911fc92849b069ab0cdad043d3": { + "balance": "13370000000000000000" + }, + "e781ec732d401202bb9bd13860910dd6c29ac0b6": { + "balance": "1240000000000000000000" + }, + "4c2f1afef7c5868c44832fc77cb03b55f89e6d6e": { + "balance": "20000000000000000000000" + }, + "34ff582952ff24458f7b13d51f0b4f987022c1fe": { + "balance": "2804400000000000000000" + }, + "73914b22fc2f131584247d82be4fecbf978ad4ba": { + "balance": "2000000000000000000000" + }, + "562be95aba17c5371fe2ba828799b1f55d2177d6": { + "balance": "38200000000000000000000" + }, + "648f5bd2a2ae8902db37847d1cb0db9390b06248": { + "balance": "7769965000000000000000" + }, + "6a9758743b603eea3aa0524b42889723c4153948": { + "balance": "10100000000000000000000" + }, + "5985c59a449dfc5da787d8244e746c6d70caa55f": { + "balance": "100000000000000000000" + }, + "56ee197f4bbf9f1b0662e41c2bbd9aa1f799e846": { + "balance": "1000000000000000000000" + }, + "d47c242edffea091bc54d57df5d1fdb93101476c": { + "balance": "2914000000000000000000" + }, + "d482e7f68e41f238fe517829de15477fe0f6dd1d": { + "balance": "500000000000000000000" + }, + "05bf4fcfe772e45b826443852e6c351350ce72a2": { + "balance": "8000000000000000000000" + }, + "f10462e58fcc07f39584a187639451167e859201": { + "balance": "169830000000000000000" + }, + "1aa27699cada8dc3a76f7933aa66c71919040e88": { + "balance": "400000000000000000000" + }, + "24046b91da9b61b629cb8b8ec0c351a07e0703e4": { + "balance": "2000000000000000000000" + }, + "41033c1b6d05e1ca89b0948fc64453fbe87ab25e": { + "balance": "1337000000000000000000" + }, + "369822f5578b40dd1f4471706b22cd971352da6b": { + "balance": "346000000000000000000" + }, + "044e853144e3364495e7a69fa1d46abea3ac0964": { + "balance": "49225000000000000000" + }, + "abf728cf9312f22128024e7046c251f5dc5901ed": { + "balance": "29550000000000000000000" + }, + "d781f7fc09184611568570b4986e2c72872b7ed0": { + "balance": "20002000000000000000" + }, + "6bb4a661a33a71d424d49bb5df28622ed4dffcf4": { + "balance": "630400000000000000000" + }, + "fef3b3dead1a6926d49aa32b12c22af54d9ff985": { + "balance": "1000000000000000000000" + }, + "fa410971ad229c3036f41acf852f2ac999281950": { + "balance": "3997400000000000000000" + }, + "de176b5284bcee3a838ba24f67fc7cbf67d78ef6": { + "balance": "37600000000000000000" + }, + "23120046f6832102a752a76656691c863e17e59c": { + "balance": "329800000000000000000" + }, + "a2f472fe4f22b77db489219ea4023d11582a9329": { + "balance": "40000000000000000000000" + }, + "f0d64cf9df09741133d170485fd24b005011d520": { + "balance": "498680000000000000000" + }, + "8b505e2871f7deb7a63895208e8227dcaa1bff05": { + "balance": "61216600000000000000000" + }, + "481e3a91bfdc2f1c8428a0119d03a41601417e1c": { + "balance": "1000000000000000000000" + }, + "bc69a0d2a31c3dbf7a9122116901b2bdfe9802a0": { + "balance": "3000000000000000000000" + }, + "20a81680e465f88790f0074f60b4f35f5d1e6aa5": { + "balance": "1279851000000000000000" + }, + "194a6bb302b8aba7a5b579df93e0df1574967625": { + "balance": "500000000000000000000" + }, + "264cc8086a8710f91b21720905912cd7964ae868": { + "balance": "26740000000000000000" + }, + "24aca08d5be85ebb9f3132dfc1b620824edfedf9": { + "balance": "18200000000000000000" + }, + "1851a063ccdb30549077f1d139e72de7971197d5": { + "balance": "2000000000000000000000" + }, + "f64a4ac8d540a9289c68d960d5fb7cc45a77831c": { + "balance": "2000000000000000000000" + }, + "c3db5657bb72f10d58f231fddf11980aff678693": { + "balance": "5910000000000000000000" + }, + "b46ace865e2c50ea4698d216ab455dff5a11cd72": { + "balance": "1000000000000000000000" + }, + "9faea13c733412dc4b490402bfef27a0397a9bc3": { + "balance": "310000000000000000000" + }, + "b40594c4f3664ef849cca6227b8a25aa690925ee": { + "balance": "4000000000000000000000" + }, + "672fa0a019088db3166f6119438d07a99f8ba224": { + "balance": "13370000000000000000000" + }, + "c1ffad07db96138c4b2a530ec1c7de29b8a0592c": { + "balance": "17600000000000000000" + }, + "87af25d3f6f8eea15313d5fe4557e810c524c083": { + "balance": "19700000000000000000000" + }, + "d6a22e598dabd38ea6e958bd79d48ddd9604f4df": { + "balance": "1000000000000000000000" + }, + "a2a435de44a01bd0ecb29e44e47644e46a0cdffb": { + "balance": "500171000000000000000" + }, + "549b47649cfad993e4064d2636a4baa0623305cc": { + "balance": "601650000000000000000" + }, + "1321b605026f4ffb296a3e0edcb390c9c85608b7": { + "balance": "2000000000000000000000" + }, + "b4bf24cb83686bc469869fefb044b909716993e2": { + "balance": "2000000000000000000000" + }, + "12d91a92d74fc861a729646db192a125b79f5374": { + "balance": "18200000000000000000" + }, + "7f0662b410298c99f311d3a1454a1eedba2fea76": { + "balance": "200000000000000000000" + }, + "83908aa7478a6d1c9b9b0281148f8f9f242b9fdc": { + "balance": "2000000000000000000000" + }, + "c1438c99dd51ef1ca8386af0a317e9b041457888": { + "balance": "223500000000000000000" + }, + "545bb070e781172eb1608af7fc2895d6cb87197e": { + "balance": "2244000000000000000000" + }, + "161d26ef6759ba5b9f20fdcd66f16132c352415e": { + "balance": "2000000000000000000000" + }, + "d7f370d4bed9d57c6f49c999de729ee569d3f4e4": { + "balance": "200000000000000000000" + }, + "90e35aabb2deef408bb9b5acef714457dfde6272": { + "balance": "100076000000000000000" + }, + "0fcfc4065008cfd323305f6286b57a4dd7eee23b": { + "balance": "20000000000000000000000" + }, + "cd725d70be97e677e3c8e85c0b26ef31e9955045": { + "balance": "1337000000000000000000" + }, + "dcf6b657266e91a4dae6033ddac15332dd8d2b34": { + "balance": "1760000000000000000000" + }, + "31f006f3494ed6c16eb92aaf9044fa8abb5fd5a3": { + "balance": "500000000000000000000" + }, + "cdea386f9d0fd804d02818f237b7d9fa7646d35e": { + "balance": "3012139000000000000000" + }, + "d45b3341e8f15c80329320c3977e3b90e7826a7e": { + "balance": "500000000000000000000" + }, + "0b649da3b96a102cdc6db652a0c07d65b1e443e6": { + "balance": "2000000000000000000000" + }, + "0a58fddd71898de773a74fdae45e7bd84ef43646": { + "balance": "20000000000000000000" + }, + "0256149f5b5063bea14e15661ffb58f9b459a957": { + "balance": "704000000000000000000" + }, + "4438e880cb2766b0c1ceaec9d2418fceb952a044": { + "balance": "133712000000000000000" + }, + "9ed80eda7f55054db9fb5282451688f26bb374c1": { + "balance": "300000000000000000000" + }, + "8dab948ae81da301d972e3f617a912e5a753712e": { + "balance": "400000000000000000000" + }, + "5b5d8c8eed6c85ac215661de026676823faa0a0c": { + "balance": "20000000000000000000000" + }, + "46722a36a01e841d03f780935e917d85d5a67abd": { + "balance": "14900000000000000000" + }, + "d4b8bdf3df9a51b0b91d16abbea05bb4783c8661": { + "balance": "1000000000000000000000" + }, + "98f6b8e6213dbc9a5581f4cce6655f95252bdb07": { + "balance": "319968000000000000000" + }, + "3599493ce65772cf93e98af1195ec0955dc98002": { + "balance": "1500048000000000000000" + }, + "ecab5aba5b828de1705381f38bc744b32ba1b437": { + "balance": "940000000000000000000" + }, + "9a82826d3c29481dcc2bd2950047e8b60486c338": { + "balance": "20000000000000000000000" + }, + "6c474bc66a54780066aa4f512eefa773abf919c7": { + "balance": "94000000000000000000" + }, + "d5903e9978ee20a38c3f498d63d57f31a39f6a06": { + "balance": "10380000000000000000000" + }, + "341480cc8cb476f8d01ff30812e7c70e05afaf5d": { + "balance": "2000000000000000000000" + }, + "af771039345a343001bc0f8a5923b126b60d509c": { + "balance": "985000000000000000000" + }, + "b5a4679685fa14196c2e9230c8c4e33bffbc10e2": { + "balance": "1400000000000000000000" + }, + "2a400dff8594de7228b4fd15c32322b75bb87da8": { + "balance": "95810000000000000000" + }, + "a1336dfb96b6bcbe4b3edf3205be5723c90fad52": { + "balance": "5000000000000000000000" + }, + "e9b1f1fca3fa47269f21b061c353b7f5e96d905a": { + "balance": "500000000000000000000" + }, + "0ee414940487fd24e390378285c5d7b9334d8b65": { + "balance": "2680000000000000000000" + }, + "6ab5b4c41cddb829690c2fda7f20c85e629dd5d5": { + "balance": "1860000000000000000000" + }, + "dd63042f25ed32884ad26e3ad959eb94ea36bf67": { + "balance": "21340000000000000000000" + }, + "c0b3f244bca7b7de5b48a53edb9cbeab0b6d88c0": { + "balance": "5820000000000000000000" + }, + "ed1a5c43c574d4e934299b24f1472cdc9fd6f010": { + "balance": "200000000000000000000" + }, + "b2d9ab9664bcf6df203c346fc692fd9cbab9205e": { + "balance": "438000000000000000000" + }, + "ede8c2cb876fbe8a4cca8290361a7ea01a69fdf8": { + "balance": "7813091000000000000000" + }, + "6a7c252042e7468a3ff773d6450bba85efa26391": { + "balance": "500000000000000000000" + }, + "a106e6923edd53ca8ed650968a9108d6ccfd9670": { + "balance": "9499935000000000000000" + }, + "031e25db516b0f099faebfd94f890cf96660836b": { + "balance": "2000000000000000000000" + }, + "7fdbc3a844e40d96b2f3a635322e6065f4ca0e84": { + "balance": "2000000000000000000000" + }, + "df47a61b72535193c561cccc75c3f3ce0804a20e": { + "balance": "398000000000000000000" + }, + "ed31305c319f9273d3936d8f5b2f71e9b1b22963": { + "balance": "100000000000000000000" + }, + "a6b2d573297360102c07a18fc21df2e7499ff4eb": { + "balance": "4011000000000000000000" + }, + "f68464bf64f2411356e4d3250efefe5c50a5f65b": { + "balance": "20000000000000000000" + }, + "927cc2bfda0e088d02eff70b38b08aa53cc30941": { + "balance": "1852700000000000000000" + }, + "41cb9896445f70a10a14215296daf614e32cf4d5": { + "balance": "1910000000000000000000" + }, + "3ad70243d88bf0400f57c8c1fd57811848af162a": { + "balance": "860000000000000000000" + }, + "63b9754d75d12d384039ec69063c0be210d5e0e3": { + "balance": "2694055000000000000000" + }, + "ad1799aad7602b4540cd832f9db5f11150f1687a": { + "balance": "2000000000000000000000" + }, + "a8b65ba3171a3f77a6350b9daf1f8d55b4d201eb": { + "balance": "745000000000000000000" + }, + "ad0a4ae478e9636e88c604f242cf5439c6d45639": { + "balance": "3520000000000000000000" + }, + "4cd0b0a6436362595ceade052ebc9b929fb6c6c0": { + "balance": "2000000000000000000000" + }, + "c1d4af38e9ba799040894849b8a8219375f1ac78": { + "balance": "20000000000000000000000" + }, + "49ddee902e1d0c99d1b11af3cc8a96f78e4dcf1a": { + "balance": "199358000000000000000" + }, + "ae842210f44d14c4a4db91fc9d3b3b50014f7bf7": { + "balance": "4000000000000000000000" + }, + "10a1c42dc1ba746986b985a522a73c93eae64c63": { + "balance": "1000000000000000000000" + }, + "5103bc09933e9921fd53dc536f11f05d0d47107d": { + "balance": "4000000000000000000000" + }, + "c88eec54d305c928cc2848c2fee23531acb96d49": { + "balance": "1999946000000000000000" + }, + "9a2ce43b5d89d6936b8e8c354791b8afff962425": { + "balance": "2000000000000000000000" + }, + "562020e3ed792d2f1835fe5f55417d5111460c6a": { + "balance": "20000000000000000000000" + }, + "ed16ce39feef3bd7f5d162045e0f67c0f00046bb": { + "balance": "20000000000000000000" + }, + "ab948a4ae3795cbca13126e19253bdc21d3a8514": { + "balance": "200000000000000000000" + }, + "c12b7f40df9a2f7bf983661422ab84c9c1f50858": { + "balance": "8000000000000000000000" + }, + "62e6b2f5eb94fa7a43831fc87e254a3fe3bf8f89": { + "balance": "250000000000000000000" + }, + "423bca47abc00c7057e3ad34fca63e375fbd8b4a": { + "balance": "18000000000000000000000" + }, + "5ff326cd60fd136b245e29e9087a6ad3a6527f0d": { + "balance": "1880000000000000000000" + }, + "79ffb4ac13812a0b78c4a37b8275223e176bfda5": { + "balance": "17300000000000000000" + }, + "f757fc8720d3c4fa5277075e60bd5c411aebd977": { + "balance": "2000000000000000000000" + }, + "0bdbc54cc8bdbbb402a08911e2232a5460ce866b": { + "balance": "3000000000000000000000" + }, + "9ee9760cc273d4706aa08375c3e46fa230aff3d5": { + "balance": "8950000000000000000000" + }, + "d23a24d7f9468343c143a41d73b88f7cbe63be5e": { + "balance": "200000000000000000000" + }, + "46d80631284203f6288ecd4e5758bb9d41d05dbe": { + "balance": "2000000000000000000000" + }, + "3f4cd1399f8a34eddb9a17a471fc922b5870aafc": { + "balance": "200000000000000000000" + }, + "44c54eaa8ac940f9e80f1e74e82fc14f1676856a": { + "balance": "7880000000000000000000" + }, + "aec27ff5d7f9ddda91183f46f9d52543b6cd2b2f": { + "balance": "450000000000000000000" + }, + "203c6283f20df7bc86542fdfb4e763ecdbbbeef5": { + "balance": "25000000000000000000000" + }, + "bcaf347918efb2d63dde03e39275bbe97d26df50": { + "balance": "100000000000000000000" + }, + "974d0541ab4a47ec7f75369c0069b64a1b817710": { + "balance": "400000000000000000000" + }, + "5da54785c9bd30575c89deb59d2041d20a39e17b": { + "balance": "1967031000000000000000" + }, + "1fb463a0389983df7d593f7bdd6d78497fed8879": { + "balance": "20000000000000000000" + }, + "6e1ea4b183e252c9bb7767a006d4b43696cb8ae9": { + "balance": "294245000000000000000" + }, + "c2aa74847e86edfdd3f3db22f8a2152feee5b7f7": { + "balance": "2048852000000000000000" + }, + "a13b9d82a99b3c9bba5ae72ef2199edc7d3bb36c": { + "balance": "1999944000000000000000" + }, + "5135fb8757600cf474546252f74dc0746d06262c": { + "balance": "2000000000000000000000" + }, + "43e7ec846358d7d0f937ad1c350ba069d7bf72bf": { + "balance": "118800000000000000000" + }, + "f2ed3e77254acb83231dc0860e1a11242ba627db": { + "balance": "1980000000000000000000" + }, + "c0a02ab94ebe56d045b41b629b98462e3a024a93": { + "balance": "100000000000000000000" + }, + "f21549bdd1487912f900a7523db5f7626121bba3": { + "balance": "10000000000000000000000" + }, + "886d0a9e17c9c095af2ea2358b89ec705212ee94": { + "balance": "28000000000000000000" + }, + "211b29cefc79ae976744fdebcebd3cbb32c51303": { + "balance": "14000000000000000000000" + }, + "b8c2703d8c3f2f44c584bc10e7c0a6b64c1c097e": { + "balance": "5550000000000000000000" + }, + "ec30addd895b82ee319e54fb04cb2bb03971f36b": { + "balance": "2000000000000000000000" + }, + "b71b62f4b448c02b1201cb5e394ae627b0a560ee": { + "balance": "500000000000000000000" + }, + "e1334e998379dfe983177062791b90f80ee22d8d": { + "balance": "500000000000000000000" + }, + "1d633097a85225a1ff4321b12988fdd55c2b3844": { + "balance": "4000000000000000000000" + }, + "8bd8d4c4e943f6c8073921dc17e3e8d7a0761627": { + "balance": "2933330000000000000000" + }, + "a5d96e697d46358d119af7819dc7087f6ae47fef": { + "balance": "14605131000000000000000" + }, + "d0809498c548047a1e2a2aa6a29cd61a0ee268bd": { + "balance": "2000000000000000000000" + }, + "3cd6b7593cbee77830a8b19d0801958fcd4bc57a": { + "balance": "500000000000000000000" + }, + "ead4d2eefb76abae5533961edd11400406b298fc": { + "balance": "3880000000000000000000" + }, + "6331028cbb5a21485bc51b565142993bdb2582a9": { + "balance": "534800000000000000000" + }, + "163bad4a122b457d64e8150a413eae4d07023e6b": { + "balance": "18800000000000000000" + }, + "c522e20fbf04ed7f6b05a37b4718d6fce0142e1a": { + "balance": "4000000000000000000000" + }, + "2d9bad6f1ee02a70f1f13def5cccb27a9a274031": { + "balance": "1790000000000000000000" + }, + "5ed0d6338559ef44dc7a61edeb893fa5d83fa1b5": { + "balance": "220000000000000000000" + }, + "ec8c1d7b6aaccd429db3a91ee4c9eb1ca4f6f73c": { + "balance": "4250000000000000000000" + }, + "3896ad743579d38e2302454d1fb6e2ab69e01bfd": { + "balance": "1880000000000000000000" + }, + "e73ccf436725c151e255ccf5210cfce5a43f13e3": { + "balance": "19982000000000000000" + }, + "9483d98f14a33fdc118d403955c29935edfc5f70": { + "balance": "459600000000000000000" + }, + "1cfcf7517f0c08459720942b647ad192aa9c8828": { + "balance": "800000000000000000000" + }, + "8d378f0edc0bb0f0686d6a20be6a7692c4fa24b8": { + "balance": "100000000000000000000" + }, + "06f68de3d739db41121eacf779aada3de8762107": { + "balance": "28000000000000000000" + }, + "9909650dd5b1397b8b8b0eb69499b291b0ad1213": { + "balance": "200000000000000000000" + }, + "b66675142e3111a1c2ea1eb2419cfa42aaf7a234": { + "balance": "1000000000000000000000" + }, + "7836f7ef6bc7bd0ff3acaf449c84dd6b1e2c939f": { + "balance": "4142296000000000000000" + }, + "3ddedbe48923fbf9e536bf9ffb0747c9cdd39eef": { + "balance": "16100000000000000000000" + }, + "c47d610b399250f70ecf1389bab6292c91264f23": { + "balance": "288800000000000000000" + }, + "51a6d627f66a8923d88d6094c4715380d3057cb6": { + "balance": "1152044000000000000000" + }, + "6c0cc917cbee7d7c099763f14e64df7d34e2bf09": { + "balance": "250000000000000000000" + }, + "aaaae68b321402c8ebc13468f341c63c0cf03fce": { + "balance": "1520000000000000000000" + }, + "819cdaa5303678ef7cec59d48c82163acc60b952": { + "balance": "14523448000000000000000" + }, + "d071192966eb69c3520fca3aa4dd04297ea04b4e": { + "balance": "110000000000000000000" + }, + "e53425d8df1f11c341ff58ae5f1438abf1ca53cf": { + "balance": "322000000000000000000" + }, + "8ffe322997b8e404422d19c54aadb18f5bc8e9b7": { + "balance": "3940000000000000000000" + }, + "305f78d618b990b4295bac8a2dfa262884f804ea": { + "balance": "4000000000000000000000" + }, + "274d69170fe7141401882b886ac4618c6ae40edb": { + "balance": "955000000000000000000" + }, + "69c94e07c4a9be3384d95dfa3cb9290051873b7b": { + "balance": "70000000000000000000" + }, + "859c600cf13d1d0273d5d1da3cd789e495899f27": { + "balance": "2674000000000000000000" + }, + "c06cebbbf7f5149a66f7eb976b3e47d56516da2f": { + "balance": "2000000000000000000000" + }, + "37bbc47212d82fcb5ee08f5225ecc2041ad2da7d": { + "balance": "3280000000000000000000" + }, + "11e7997edd904503d77da6038ab0a4c834bbd563": { + "balance": "388000000000000000000" + }, + "d333627445f2d787901ef33bb2a8a3675e27ffec": { + "balance": "400000000000000000000" + }, + "16a58e985dccd707a594d193e7cca78b5d027849": { + "balance": "1360000000000000000000" + }, + "f8ae857b67a4a2893a3fbe7c7a87ff1c01c6a6e7": { + "balance": "4000000000000000000000" + }, + "491561db8b6fafb9007e62d050c282e92c4b6bc8": { + "balance": "30000000000000000000000" + }, + "21df1ec24b4e4bfe79b0c095cebae198f291fbd1": { + "balance": "20000000000000000000000" + }, + "e208812a684098f3da4efe6aba256256adfe3fe6": { + "balance": "2000000000000000000000" + }, + "f4ec8e97a20aa5f8dd206f55207e06b813df2cc0": { + "balance": "200000000000000000000" + }, + "29eb7eefdae9feb449c63ff5f279d67510eb1422": { + "balance": "19400000000000000000" + }, + "0d678706d037187f3e22e6f69b99a592d11ebc59": { + "balance": "1580000000000000000000" + }, + "de6d363106cc6238d2f092f0f0372136d1cd50c6": { + "balance": "5348000000000000000000" + }, + "c8710d7e8b5a3bd69a42fe0fa8b87c357fddcdc8": { + "balance": "4000000000000000000000" + }, + "5267f4d41292f370863c90d793296903843625c7": { + "balance": "1400000000000000000000" + }, + "4cda41dd533991290794e22ae324143e309b3d3d": { + "balance": "2400000000000000000000" + }, + "f8a50cee2e688ceee3aca4d4a29725d4072cc483": { + "balance": "2000000000000000000000" + }, + "5ed3bbc05240e0d399eb6ddfe60f62de4d9509af": { + "balance": "193999806000000000000000" + }, + "0befb54707f61b2c9fb04715ab026e1bb72042bd": { + "balance": "4000000000000000000000" + }, + "cab9a301e6bd46e940355028eccd40ce4d5a1ac3": { + "balance": "400000000000000000000" + }, + "64672da3ab052821a0243d1ce4b6e0a36517b8eb": { + "balance": "200000000000000000000" + }, + "eac0827eff0c6e3ff28a7d4a54f65cb7689d7b99": { + "balance": "2856500000000000000000" + }, + "f4b6cdcfcb24230b337d770df6034dfbd4e1503f": { + "balance": "19000000000000000000000" + }, + "7be2f7680c802da6154c92c0194ae732517a7169": { + "balance": "18200000000000000000" + }, + "869f1aa30e4455beb1822091de5cadec79a8f946": { + "balance": "8000000000000000000000" + }, + "c4681e73bb0e32f6b726204831ff69baa4877e32": { + "balance": "1820000000000000000000" + }, + "962cd22a8edf1e4f4e55b4b15ddbfb5d9d541971": { + "balance": "2000000000000000000000" + }, + "131df8d330eb7cc7147d0a55576f05de8d26a8b7": { + "balance": "188000000000000000000" + }, + "19f99f2c0b46ce8906875dc9f90ae104dae35594": { + "balance": "4507300000000000000000" + }, + "91bb3f79022bf3c453f4ff256e269b15cf2c9cbd": { + "balance": "1519000000000000000000" + }, + "7301dc4cf26d7186f2a11bf8b08bf229463f64a3": { + "balance": "2000000000000000000000" + }, + "7cbca88fca6a0060b960985c9aa1b02534dc2208": { + "balance": "462500000000000000000" + }, + "f3c1abd29dc57b41dc192d0e384d021df0b4f6d4": { + "balance": "2798000000000000000000" + }, + "5d32f6f86e787ff78e63d78b0ef95fe6071852b8": { + "balance": "401100000000000000000" + }, + "1678c5f2a522393225196361894f53cc752fe2f3": { + "balance": "1936000000000000000000" + }, + "1cf04cb14380059efd3f238b65d5beb86afa14d8": { + "balance": "20000000000000000000" + }, + "52e1731350f983cc2c4189842fde0613fad50ce1": { + "balance": "11640000000000000000000" + }, + "d0b11d6f2bce945e0c6a5020c3b52753f803f9d1": { + "balance": "200000000000000000000" + }, + "409bd75085821c1de70cdc3b11ffc3d923c74010": { + "balance": "4000000000000000000000" + }, + "0bb7160aba293762f8734f3e0326ffc9a4cac190": { + "balance": "1000000000000000000000" + }, + "7aad4dbcd3acf997df93586956f72b64d8ad94ee": { + "balance": "4000000000000000000000" + }, + "2dec98329d1f96c3a59caa7981755452d4da49d5": { + "balance": "200000000000000000000" + }, + "c18ab467feb5a0aadfff91230ff056464d78d800": { + "balance": "2000000000000000000000" + }, + "c90c3765156bca8e4897ab802419153cbe5225a9": { + "balance": "200000000000000000000" + }, + "85c8f3cc7a354feac99a5e7bfe7cdfa351cfe355": { + "balance": "400000000000000000000" + }, + "f4fc4d39bc0c2c4068a36de50e4ab4d4db7e340a": { + "balance": "25380000000000000000" + }, + "f50abbd4aa45d3eb88515465a8ba0b310fd9b521": { + "balance": "6685000000000000000000" + }, + "4d200110124008d56f76981256420c946a6ff45c": { + "balance": "199955000000000000000" + }, + "f4ba6a46d55140c439cbcf076cc657136262f4f8": { + "balance": "2000000000000000000000" + }, + "fa7adf660b8d99ce15933d7c5f072f3cbeb99d33": { + "balance": "5910000000000000000000" + }, + "84503334630d77f74147f68b2e086613c8f1ade9": { + "balance": "1600000000000000000000" + }, + "31ed858788bda4d5270992221cc04206ec62610d": { + "balance": "1176000000000000000000" + }, + "bfbca418d3529cb393081062032a6e1183c6b2dc": { + "balance": "8000000000000000000000" + }, + "8263ece5d709e0d7ae71cca868ed37cd2fef807b": { + "balance": "990000000000000000000" + }, + "23ba3864da583dab56f420873c37679690e02f00": { + "balance": "9800000000000000000000" + }, + "cedcb3a1d6843fb6bef643617deaf38f8e98dd5f": { + "balance": "477500000000000000000" + }, + "8fac748f784a0fed68dba43319b42a75b4649c6e": { + "balance": "910000000000000000000" + }, + "18b8bcf98321da61fb4e3eacc1ec5417272dc27e": { + "balance": "880000000000000000000" + }, + "776943ffb2ef5cdd35b83c28bc046bd4f4677098": { + "balance": "3000000000000000000000" + }, + "fb8113f94d9173eefd5a3073f516803a10b286ae": { + "balance": "80000000000000000000" + }, + "3e8349b67f5745449f659367d9ad4712db5b895a": { + "balance": "1820000000000000000000" + }, + "79cfa9780ae6d87b2c31883f09276986c89a6735": { + "balance": "1000000000000000000000" + }, + "5006fe4c22173980f00c74342b39cd231c653129": { + "balance": "2000000000000000000000" + }, + "13848b46ea75beb7eaa85f59d866d77fd24cf21a": { + "balance": "50000000000000000000000" + }, + "d64a2d50f8858537188a24e0f50df1681ab07ed7": { + "balance": "38800000000000000000000" + }, + "4f9ce2af9b8c5e42c6808a3870ec576f313545d1": { + "balance": "10000000000000000000000" + }, + "8764d02722000996ecd475b433298e9f540b05bf": { + "balance": "200000000000000000000" + }, + "3b7c77dbe95dc2602ce3269a9545d04965fefdbd": { + "balance": "2000000000000000000000" + }, + "c9dcbb056f4db7d9da39936202c5bd8230b3b477": { + "balance": "20000000000000000000000" + }, + "9ecbabb0b22782b3754429e1757aaba04b81189f": { + "balance": "823743000000000000000" + }, + "831c44b3084047184b2ad218680640903750c45d": { + "balance": "1970000000000000000000" + }, + "ff8eb07de3d49d9d52bbe8e5b26dbe1d160fa834": { + "balance": "3986000000000000000000" + }, + "8ccf3aa21ab742576ad8c422f71bb188591dea8a": { + "balance": "1000000000000000000000" + }, + "ddac312a9655426a9c0c9efa3fd82559ef4505bf": { + "balance": "401100000000000000000" + }, + "9a3e2b1bf346dd070b027357feac44a4b2c97db8": { + "balance": "10000000000000000000000" + }, + "69d39d510889e552a396135bfcdb06e37e387633": { + "balance": "4000000000000000000000" + }, + "83a3148833d9644984f7c475a7850716efb480ff": { + "balance": "3400000000000000000000" + }, + "62b4a9226e61683c72c183254690daf511b4117a": { + "balance": "260000000000000000000" + }, + "50763add868fd7361178342fc055eaa2b95f6846": { + "balance": "66838000000000000000" + }, + "91898eab8c05c0222883cd4db23b7795e1a24ad7": { + "balance": "2000000000000000000000" + }, + "066647cfc85d23d37605573d208ca154b244d76c": { + "balance": "10000000000000000000000" + }, + "aaf9ee4b886c6d1e95496fd274235bf4ecfcb07d": { + "balance": "1400000000000000000000" + }, + "06860a93525955ff624940fadcffb8e149fd599c": { + "balance": "1999800000000000000000" + }, + "e81c2d346c0adf4cc56708f6394ba6c8c8a64a1e": { + "balance": "2000000000000000000000" + }, + "41a8e236a30e6d63c1ff644d132aa25c89537e01": { + "balance": "20000000000000000000" + }, + "6a679e378fdce6bfd97fe62f043c6f6405d79e99": { + "balance": "4000000000000000000000" + }, + "933436c8472655f64c3afaaf7c4c621c83a62b38": { + "balance": "1000000000000000000000" + }, + "abe07ced6ac5ddf991eff6c3da226a741bd243fe": { + "balance": "10000000000000000000000" + }, + "bb56a404723cff20d0685488b05a02cdc35aacaa": { + "balance": "20000000000000000000" + }, + "0d551ec1a2133c981d5fc6a8c8173f9e7c4f47af": { + "balance": "2000000000000000000000" + }, + "23376ecabf746ce53321cf42c86649b92b67b2ff": { + "balance": "2000000000000000000000" + }, + "644ba6c61082e989109f5c11d4b40e991660d403": { + "balance": "4000000000000000000000" + }, + "680d5911ed8dd9eec45c060c223f89a7f620bbd5": { + "balance": "20000000000000000000000" + }, + "cb1bb6f1da5eb10d4899f7e61d06c1b00fdfb52d": { + "balance": "1038000000000000000000" + }, + "303a30ac4286ae17cf483dad7b870c6bd64d7b4a": { + "balance": "500000000000000000000" + }, + "7b0b31ff6e24745ead8ed9bb85fc0bf2fe1d55d4": { + "balance": "800000000000000000000" + }, + "854691ce714f325ced55ce5928ce9ba12facd1b8": { + "balance": "4380000000000000000000" + }, + "a13cfe826d6d1841dcae443be8c387518136b5e8": { + "balance": "140000000000000000000000" + }, + "5fcd84546896dd081db1a320bd4d8c1dd1528c4c": { + "balance": "20000000000000000000" + }, + "3db5fe6a68bd3612ac15a99a61e555928eeceaf3": { + "balance": "1580000000000000000000" + }, + "7a79e30ff057f70a3d0191f7f53f761537af7dff": { + "balance": "400000000000000000000" + }, + "3d3fad49c9e5d2759c8e8e5a7a4d60a0dd135692": { + "balance": "20000000000000000000" + }, + "05a830724302bc0f6ebdaa1ebeeeb46e6ce00b39": { + "balance": "98500000000000000000" + }, + "e4b6ae22c7735f5b89f34dd77ad0975f0acc9181": { + "balance": "1000000000000000000000" + }, + "3f2dd55db7eab0ebee65b33ed8202c1e992e958b": { + "balance": "820000000000000000000" + }, + "395d6d255520a8db29abc47d83a5db8a1a7df087": { + "balance": "100000000000000000000" + }, + "1cc90876004109cd79a3dea866cb840ac364ba1b": { + "balance": "2000000000000000000000" + }, + "c83e9d6a58253beebeb793e6f28b054a58491b74": { + "balance": "281800000000000000000" + }, + "901d99b699e5c6911519cb2076b4c76330c54d22": { + "balance": "2000000000000000000000" + }, + "3a9132b7093d3ec42e1e4fb8cb31ecdd43ae773c": { + "balance": "2000000000000000000000" + }, + "b41eaf5d51a5ba1ba39bb418dbb54fab750efb1f": { + "balance": "1000000000000000000000" + }, + "aa493d3f4fb866491cf8f800efb7e2324ed7cfe5": { + "balance": "1700000000000000000000" + }, + "509982f56237ee458951047e0a2230f804e2e895": { + "balance": "17500000000000000000000" + }, + "316e92a91bbda68b9e2f98b3c048934e3cc0b416": { + "balance": "2000000000000000000000" + }, + "a3430e1f647f321ed34739562323c7d623410b56": { + "balance": "999942000000000000000" + }, + "fca43bbc23a0d321ba9e46b929735ce7d8ef0c18": { + "balance": "20000000000000000000" + }, + "ff45cb34c928364d9cc9d8bb00373474618f06f3": { + "balance": "100000000000000000000" + }, + "8c999591fd72ef7111efca7a9e97a2356b3b000a": { + "balance": "4084000000000000000000" + }, + "8579dadf1a395a3471e20b6f763d9a0ff19a3f6f": { + "balance": "4000000000000000000000" + }, + "c8d4e1599d03b79809e0130a8dc38408f05e8cd3": { + "balance": "2945500000000000000000" + }, + "2abce1808940cd4ef5b5e05285f82df7a9ab5e03": { + "balance": "9800000000000000000000" + }, + "0bb0c12682a2f15c9b5741b2385cbe41f034068e": { + "balance": "1500000000000000000000" + }, + "08b7bdcf944d5570838be70460243a8694485858": { + "balance": "2000000000000000000000" + }, + "c452e0e4b3d6ae06b836f032ca09db409ddfe0fb": { + "balance": "800000000000000000000" + }, + "48d4f2468f963fd79a006198bb67895d2d5aa4d3": { + "balance": "1400000000000000000000" + }, + "f9e7222faaf0f4da40c1c4a40630373a09bed7b6": { + "balance": "2865000000000000000000" + }, + "bf59aee281fa43fe97194351a9857e01a3b897b2": { + "balance": "600000000000000000000" + }, + "da0d4b7ef91fb55ad265f251142067f10376ced6": { + "balance": "20000000000000000000000" + }, + "2c6f5c124cc789f8bb398e3f889751bc4b602d9e": { + "balance": "24928000000000000000" + }, + "c85ef27d820403805fc9ed259fff64acb8d6346a": { + "balance": "2000000000000000000000" + }, + "9aa8308f42910e5ade09c1a5e282d6d91710bdbf": { + "balance": "200000000000000000000" + }, + "9e4cec353ac3e381835e3c0991f8faa5b7d0a8e6": { + "balance": "9999917000000000000000" + }, + "137cf341e8516c815814ebcd73e6569af14cf7bc": { + "balance": "1000000000000000000000" + }, + "889da662eb4a0a2a069d2bc24b05b4ee2e92c41b": { + "balance": "1663417000000000000000" + }, + "0998d8273115b56af43c505e087aff0676ed3659": { + "balance": "3999984000000000000000" + }, + "3e4d13c55a84e46ed7e9cb90fd355e8ad991e38f": { + "balance": "1000000000000000000000" + }, + "abc068b4979b0ea64a62d3b7aa897d73810dc533": { + "balance": "1970000000000000000000" + }, + "d8fdf546674738c984d8fab857880b3e4280c09e": { + "balance": "20000000000000000000" + }, + "aff161740a6d909fe99c59a9b77945c91cc91448": { + "balance": "60000000000000000000" + }, + "92ad1b3d75fba67d54663da9fc848a8ade10fa67": { + "balance": "2000000000000000000000" + }, + "819eb4990b5aba5547093da12b6b3c1093df6d46": { + "balance": "1000000000000000000000" + }, + "643d9aeed4b180947ed2b9207cce4c3ddc55e1f7": { + "balance": "200000000000000000000" + }, + "ab3e62e77a8b225e411592b1af300752fe412463": { + "balance": "9850000000000000000000" + }, + "650b425555e4e4c51718146836a2c1ee77a5b421": { + "balance": "20000000000000000000000" + }, + "ba8e46d69d2e2343d86c60d82cf42c2041a0c1c2": { + "balance": "100000000000000000000" + }, + "f9570e924c95debb7061369792cf2efec2a82d5e": { + "balance": "20000000000000000000" + }, + "4dc4bf5e7589c47b28378d7503cf96488061dbbd": { + "balance": "1760000000000000000000" + }, + "3d7ea5bf03528100ed8af8aed2653e921b6e6725": { + "balance": "1000000000000000000000" + }, + "a02bde6461686e19ac650c970d0672e76dcb4fc2": { + "balance": "8865000000000000000000" + }, + "b0e760bb07c081777345e0578e8bc898226d4e3b": { + "balance": "2000000000000000000000" + }, + "979cbf21dfec8ace3f1c196d82df962534df394f": { + "balance": "2832860000000000000000" + }, + "9f8245c3ab7d173164861cd3991b94f1ba40a93a": { + "balance": "2860000000000000000000" + }, + "c25cf826550c8eaf10af2234fef904ddb95213be": { + "balance": "1000000000000000000000" + }, + "967bfaf76243cdb9403c67d2ceefdee90a3feb73": { + "balance": "970582000000000000000" + }, + "0b2113504534642a1daf102eee10b9ebde76e261": { + "balance": "2733351000000000000000" + }, + "74bc4a5e2045f4ff8db184cf3a9b0c065ad807d2": { + "balance": "2000000000000000000000" + }, + "f1da40736f99d5df3b068a5d745fafc6463fc9b1": { + "balance": "121546000000000000000" + }, + "0fa6c7b0973d0bae2940540e247d3627e37ca347": { + "balance": "1000000000000000000000" + }, + "72b05962fb2ad589d65ad16a22559eba1458f387": { + "balance": "133700000000000000000" + }, + "6ceae3733d8fa43d6cd80c1a96e8eb93109c83b7": { + "balance": "298000000000000000000" + }, + "28eaea78cd4d95faecfb68836eafe83520f3bbb7": { + "balance": "200000000000000000000" + }, + "f49f6f9baabc018c8f8e119e0115f491fc92a8a4": { + "balance": "10000000000000000000000" + }, + "833316985d47742bfed410604a91953c05fb12b0": { + "balance": "2000000000000000000000" + }, + "ead75016e3a0815072b6b108bcc1b799acf0383e": { + "balance": "2000000000000000000000" + }, + "0032403587947b9f15622a68d104d54d33dbd1cd": { + "balance": "77500000000000000000" + }, + "8f64b9c1246d857831643107d355b5c75fef5d4f": { + "balance": "1999944000000000000000" + }, + "15dcafcc2bace7b55b54c01a1c514626bf61ebd8": { + "balance": "9400000000000000000000" + }, + "6886ada7bbb0617bda842191c68c922ea3a8ac82": { + "balance": "1160000000000000000000" + }, + "f736dc96760012388fe88b66c06efe57e0d7cf0a": { + "balance": "2100000000000000000000" + }, + "0b288a5a8b75f3dc4191eb0457e1c83dbd204d25": { + "balance": "4853000000000000000000" + }, + "56b6c23dd2ec90b4728f3bb2e764c3c50c85f144": { + "balance": "1000000000000000000000" + }, + "6310b020fd98044957995092090f17f04e52cdfd": { + "balance": "1580000000000000000000" + }, + "b0baeb30e313776c4c6d247402ba4167afcda1cc": { + "balance": "1970000000000000000000" + }, + "7641f7d26a86cddb2be13081810e01c9c83c4b20": { + "balance": "13370000000000000000" + }, + "07a8dadec142571a7d53a4297051786d072cba55": { + "balance": "22729000000000000000" + }, + "cc73dd356b4979b579b401d4cc7a31a268ddce5a": { + "balance": "500000000000000000000" + }, + "adf1acfe99bc8c14b304c8d905ba27657b8a7bc4": { + "balance": "20000000000000000000000" + }, + "72dabb5b6eed9e99be915888f6568056381608f8": { + "balance": "208433000000000000000" + }, + "9de20ae76aa08263b205d5142461961e2408d266": { + "balance": "252000000000000000000" + }, + "9d4ff989b7bed9ab109d10c8c7e55f02d76734ad": { + "balance": "1000000000000000000000" + }, + "e58dd23238ee6ea7c2138d385df500c325f376be": { + "balance": "1820000000000000000000" + }, + "4bd6dd0cff23400e1730ba7b894504577d14e74a": { + "balance": "206028000000000000000000" + }, + "35147430c3106500e79fa2f502462e94703c23b1": { + "balance": "1999944000000000000000" + }, + "c0ae14d724832e2fce2778de7f7b8daf7b12a93e": { + "balance": "20000000000000000000" + }, + "b57413060af3f14eb479065f1e9d19b3757ae8cc": { + "balance": "40000000000000000000" + }, + "7d04d2edc058a1afc761d9c99ae4fc5c85d4c8a6": { + "balance": "314807840000000000000000" + }, + "1c94d636e684eb155895ce6db4a2588fba1d001b": { + "balance": "2000000000000000000000" + }, + "c721b2a7aa44c21298e85039d00e2e460e670b9c": { + "balance": "140800000000000000000" + }, + "2d89a8006a4f137a20dc2bec46fe2eb312ea9654": { + "balance": "200000000000000000000" + }, + "646afba71d849e80c0ed59cac519b278e7f7abe4": { + "balance": "1000000000000000000000" + }, + "71f2cdd1b046e2da2fbb5a26723422b8325e25a3": { + "balance": "99960000000000000000" + }, + "2c9fa72c95f37d08e9a36009e7a4b07f29bad41a": { + "balance": "16100000000000000000" + }, + "848fbd29d67cf4a013cb02a4b176ef244e9ee68d": { + "balance": "20116000000000000000" + }, + "68190ca885da4231874c1cfb42b1580a21737f38": { + "balance": "3820000000000000000000" + }, + "9adf458bff3599eee1a26398853c575bc38c6313": { + "balance": "280000000000000000000" + }, + "b72220ade364d0369f2d2da783ca474d7b9b34ce": { + "balance": "499986000000000000000" + }, + "38e2af73393ea98a1d993a74df5cd754b98d529a": { + "balance": "1790000000000000000000" + }, + "4d38d90f83f4515c03cc78326a154d358bd882b7": { + "balance": "185000000000000000000" + }, + "aa8eb0823b07b0e6d20aadda0e95cf3835be192e": { + "balance": "32000000000000000000" + }, + "008639dabbe3aeac887b5dc0e43e13bcd287d76c": { + "balance": "310200000000000000000" + }, + "fa3a0c4b903f6ea52ea7ab7b8863b6a616ad6650": { + "balance": "20000000000000000000" + }, + "e26bf322774e18288769d67e3107deb7447707b8": { + "balance": "2000000000000000000000" + }, + "e061a4f2fc77b296d19ada238e49a5cb8ecbfa70": { + "balance": "4000000000000000000000" + }, + "b320834836d1dbfda9e7a3184d1ad1fd4320ccc0": { + "balance": "1000000000000000000000" + }, + "0ed3bb3a4eb554cfca97947d575507cdfd6d21d8": { + "balance": "547863000000000000000" + }, + "32fa0e86cd087dd68d693190f32d93310909ed53": { + "balance": "4000000000000000000000" + }, + "5b759fa110a31c88469f54d44ba303d57dd3e10f": { + "balance": "1683760000000000000000" + }, + "136f4907cab41e27084b9845069ff2fd0c9ade79": { + "balance": "4000000000000000000000" + }, + "3d89e505cb46e211a53f32f167a877bec87f4b0a": { + "balance": "25019000000000000000" + }, + "57a852fdb9b1405bf53ccf9508f83299d3206c52": { + "balance": "2000000000000000000000" + }, + "747abc9649056d3926044d28c3ad09ed17b67d70": { + "balance": "5000057000000000000000" + }, + "5c29f9e9a523c1f8669448b55c48cbd47c25e610": { + "balance": "964320000000000000000" + }, + "30a9da72574c51e7ee0904ba1f73a6b7b83b9b9d": { + "balance": "20200000000000000000" + }, + "220e2b92c0f6c902b513d9f1e6fab6a8b0def3d7": { + "balance": "800000000000000000000" + }, + "5af7c072b2c5acd71c76addcce535cf7f8f93585": { + "balance": "20000000000000000000" + }, + "81556db27349ab8b27004944ed50a46e941a0f5f": { + "balance": "3998000000000000000000" + }, + "987618c85656207c7bac1507c0ffefa2fb64b092": { + "balance": "64419000000000000000" + }, + "e0f372347c96b55f7d4306034beb83266fd90966": { + "balance": "400000000000000000000" + }, + "71784c105117c1f68935797fe159abc74e43d16a": { + "balance": "2001600000000000000000" + }, + "9284f96ddb47b5186ee558aa31324df5361c0f73": { + "balance": "16000000000000000000000" + }, + "a60c1209754f5d87b181da4f0817a81859ef9fd8": { + "balance": "50000000000000000000" + }, + "5afda9405c8e9736514574da928de67456010918": { + "balance": "6008500000000000000000" + }, + "6978696d5150a9a263513f8f74c696f8b1397cab": { + "balance": "6640000000000000000000" + }, + "a9ad1926bc66bdb331588ea8193788534d982c98": { + "balance": "30000000000000000000000" + }, + "e3f80b40fb83fb97bb0d5230af4f6ed59b1c7cc8": { + "balance": "1337000000000000000000" + }, + "e207578e1f4ddb8ff6d5867b39582d71b9812ac5": { + "balance": "3880000000000000000000" + }, + "86883d54cd3915e549095530f9ab1805e8c5432d": { + "balance": "4000000000000000000000" + }, + "6974c8a414ceaefd3c2e4dfdbef430568d9a960b": { + "balance": "334250000000000000000" + }, + "532d32b00f305bcc24dcef56817d622f34fb2c24": { + "balance": "1800000000000000000000" + }, + "761f8a3a2af0a8bdbe1da009321fb29764eb62a1": { + "balance": "10000000000000000000000" + }, + "4677b04e0343a32131fd6abb39b1b6156bba3d5b": { + "balance": "200000000000000000000" + }, + "ef69781f32ffce33346f2c9ae3f08493f3e82f89": { + "balance": "18200000000000000000" + }, + "e3b3d2c9bf570be6a2f72adca1862c310936a43c": { + "balance": "100100000000000000000" + }, + "d19caf39bb377fdf2cf19bd4fb52591c2631a63c": { + "balance": "1000000000000000000000" + }, + "5d68324bcb776d3ffd0bf9fea91d9f037fd6ab0f": { + "balance": "2000000000000000000000" + }, + "1c99fe9bb6c6d1066d912099547fd1f4809eacd9": { + "balance": "2000000000000000000000" + }, + "bbfe0a830cace87b7293993a7e9496ce64f8e394": { + "balance": "6000000000000000000000" + }, + "26c0054b700d3a7c2dcbe275689d4f4cad16a335": { + "balance": "2000000000000000000000" + }, + "7d7e7c61779adb7706c94d32409a2bb4e994bf60": { + "balance": "865992000000000000000" + }, + "d037d215d11d1df3d54fbd321cd295c5465e273b": { + "balance": "1400000000000000000000" + }, + "08166f02313feae18bb044e7877c808b55b5bf58": { + "balance": "1970000000000000000000" + }, + "781b1501647a2e06c0ed43ff197fccec35e1700b": { + "balance": "3000000000000000000000" + }, + "74316adf25378c10f576d5b41a6f47fa98fce33d": { + "balance": "336082000000000000000" + }, + "44e2fdc679e6bee01e93ef4a3ab1bcce012abc7c": { + "balance": "410231000000000000000" + }, + "178eaf6b8554c45dfde16b78ce0c157f2ee31351": { + "balance": "320000000000000000000" + }, + "cf923a5d8fbc3d01aa079d1cfe4b43ce071b1611": { + "balance": "2000000000000000000000" + }, + "0c28847e4f09dfce5f9b25af7c4e530f59c880fe": { + "balance": "1000000000000000000000" + }, + "54ce88275956def5f9458e3b95decacd484021a0": { + "balance": "2000000000000000000000" + }, + "9d4213339a01551861764c87a93ce8f85f87959a": { + "balance": "200000000000000000000" + }, + "e559b5fd337b9c5572a9bf9e0f2521f7d446dbe4": { + "balance": "200000000000000000000" + }, + "dcb03bfa6c1131234e56b7ea7c4f721487546b7a": { + "balance": "1337000000000000000000" + }, + "db6ff71b3db0928f839e05a7323bfb57d29c87aa": { + "balance": "910000000000000000000" + }, + "eb7c202b462b7cc5855d7484755f6e26ef43a115": { + "balance": "2000000000000000000000" + }, + "323486ca64b375474fb2b759a9e7a135859bd9f6": { + "balance": "400000000000000000000" + }, + "2c1df8a76f48f6b54bcf9caf56f0ee1cf57ab33d": { + "balance": "10118000000000000000000" + }, + "2cd87866568dd81ad47d9d3ad0846e5a65507373": { + "balance": "400000000000000000000" + }, + "8566610901aace38b83244f3a9c831306a67b9dc": { + "balance": "3256000000000000000000" + }, + "1c257ad4a55105ea3b58ed374b198da266c85f63": { + "balance": "10000000000000000000000" + }, + "cf4f1138f1bd6bf5b6d485cce4c1017fcb85f07d": { + "balance": "882038000000000000000" + }, + "c934becaf71f225f8b4a4bf7b197f4ac9630345c": { + "balance": "20000000000000000000000" + }, + "1e2bf4ba8e5ef18d37de6d6ad636c4cae489d0cc": { + "balance": "2000000000000000000000" + }, + "9d78a975b7db5e4d8e28845cfbe7e31401be0dd9": { + "balance": "1340000000000000000000" + }, + "16aa52cb0b554723e7060f21f327b0a68315fea3": { + "balance": "250000000000000000000" + }, + "97e28973b860c567402800fbb63ce39a048a3d79": { + "balance": "97000000000000000000" + }, + "4ac5acad000b8877214cb1ae00eac9a37d59a0fd": { + "balance": "4000000000000000000000" + }, + "01226e0ad8d62277b162621c62c928e96e0b9a8c": { + "balance": "2000000000000000000000" + }, + "479abf2da4d58716fd973a0d13a75f530150260a": { + "balance": "20000000000000000000" + }, + "31d81d526c195e3f10b5c6db52b5e59afbe0a995": { + "balance": "264000000000000000000" + }, + "749087ac0f5a97c6fad021538bf1d6cda18e0daa": { + "balance": "1000000000000000000000" + }, + "1565af837ef3b0bd4e2b23568d5023cd34b16498": { + "balance": "393284000000000000000" + }, + "997d6592a31589acc31b9901fbeb3cc3d65b3215": { + "balance": "2000000000000000000000" + }, + "9d207517422cc0d60de7c237097a4d4fce20940c": { + "balance": "500000000000000000000" + }, + "24b8b446debd1947955dd084f2c544933346d3ad": { + "balance": "4324135000000000000000" + }, + "107a03cf0842dbdeb0618fb587ca69189ec92ff5": { + "balance": "1970000000000000000000" + }, + "7f603aec1759ea5f07c7f8d41a1428fbbaf9e762": { + "balance": "20000000000000000000" + }, + "53a244672895480f4a2b1cdf7da5e5a242ec4dbc": { + "balance": "1000000000000000000000" + }, + "7db4c7d5b797e9296e6382f203693db409449d62": { + "balance": "400000000000000000000" + }, + "2ae82dab92a66389eea1abb901d1d57f5a7cca0b": { + "balance": "2000000000000000000000" + }, + "16bc40215abbd9ae5d280b95b8010b4514ff1292": { + "balance": "200000000000000000000" + }, + "bba4fac3c42039d828e742cde0efffe774941b39": { + "balance": "1999946000000000000000" + }, + "5431ca427e6165a644bae326bd09750a178c650d": { + "balance": "2000000000000000000000" + }, + "dcf33965531380163168fc11f67e89c6f1bc178a": { + "balance": "334885000000000000000" + }, + "65fd02d704a12a4dace9471b0645f962a89671c8": { + "balance": "28615000000000000000" + }, + "135d1719bf03e3f866312479fe338118cd387e70": { + "balance": "2000000000000000000000" + }, + "f3159866c2bc86bba40f9d73bb99f1eee57bb9d7": { + "balance": "1000000000000000000000" + }, + "e3a4621b66004588e31206f718cb00a319889cf0": { + "balance": "2000000000000000000000" + }, + "abcdbc8f1dd13af578d4a4774a62182bedf9f9be": { + "balance": "36660000000000000000" + }, + "9fbe066de57236dc830725d32a02aef9246c6c5e": { + "balance": "2000000000000000000000" + }, + "81cfad760913d3c322fcc77b49c2ae3907e74f6e": { + "balance": "197000000000000000000" + }, + "0ab59d390702c9c059db148eb4f3fcfa7d04c7e7": { + "balance": "18200000000000000000" + }, + "2c2db28c3309375eea3c6d72cd6d0eec145afcc0": { + "balance": "2000000000000000000000" + }, + "08306de51981e7aca1856859b7c778696a6b69f9": { + "balance": "3200000000000000000000" + }, + "f814799f6ddf4dcb29c7ee870e75f9cc2d35326d": { + "balance": "1000000000000000000000" + }, + "ee867d20916bd2e9c9ece08aa04385db667c912e": { + "balance": "50000000000000000000000" + }, + "97a86f01ce3f7cfd4441330e1c9b19e1b10606ef": { + "balance": "2000000000000000000000" + }, + "4c759813ad1386bed27ffae9e4815e3630cca312": { + "balance": "2000000000000000000000" + }, + "8f226096c184ebb40105e08dac4d22e1c2d54d30": { + "balance": "306552000000000000000" + }, + "13acada8980affc7504921be84eb4944c8fbb2bd": { + "balance": "1601600000000000000000" + }, + "122dcfd81addb97d1a0e4925c4b549806e9f3beb": { + "balance": "1514954000000000000000" + }, + "232f525d55859b7d4e608d20487faadb00293135": { + "balance": "4000000000000000000000" + }, + "6f7ac681d45e418fce8b3a1db5bc3be6f06c9849": { + "balance": "2000000000000000000000" + }, + "0c8692eeff2a53d6d1688ed56a9ddbbd68dabba1": { + "balance": "2000000000000000000000" + }, + "6a6337833f8f6a6bf10ca7ec21aa810ed444f4cb": { + "balance": "1028200000000000000000" + }, + "209377b6ad3fe101c9685b3576545c6b1684e73c": { + "balance": "1820000000000000000000" + }, + "560fc08d079f047ed8d7df75551aa53501f57013": { + "balance": "7600000000000000000000" + }, + "8e78f351457d016f4ad2755ec7424e5c21ba6d51": { + "balance": "146000000000000000000" + }, + "2ce11a92fad024ff2b3e87e3b542e6c60dcbd996": { + "balance": "4000000000000000000000" + }, + "8ab839aeaf2ad37cb78bacbbb633bcc5c099dc46": { + "balance": "2000000000000000000000" + }, + "673144f0ec142e770f4834fee0ee311832f3087b": { + "balance": "500038000000000000000" + }, + "ba8a63f3f40de4a88388bc50212fea8e064fbb86": { + "balance": "2000000000000000000000" + }, + "ee899b02cbcb3939cd61de1342d50482abb68532": { + "balance": "1760000000000000000000" + }, + "c2d9eedbc9019263d9d16cc5ae072d1d3dd9db03": { + "balance": "20000000000000000000000" + }, + "355c0c39f5d5700b41d375b3f17851dcd52401f9": { + "balance": "3979000000000000000000" + }, + "8179c80970182cc5b7d82a4df06ea94db63a25f3": { + "balance": "727432000000000000000" + }, + "b388b5dfecd2c5e4b596577c642556dbfe277855": { + "balance": "20000000000000000000" + }, + "a9e28337e6357193d9e2cb236b01be44b81427df": { + "balance": "2200000000000000000000" + }, + "04ba4bb87140022c214a6fac42db5a16dd954045": { + "balance": "1000000000000000000000" + }, + "67c926093e9b8927933810d98222d62e2b8206bb": { + "balance": "1910000000000000000000" + }, + "ed7346766e1a676d0d06ec821867a276a083bf31": { + "balance": "4012890000000000000000" + }, + "92558226b384626cad48e09d966bf1395ee7ea5d": { + "balance": "334250000000000000000" + }, + "bdf693f833c3fe471753184788eb4bfe4adc3f96": { + "balance": "1970000000000000000000" + }, + "4474299d0ee090dc90789a1486489c3d0d645e6d": { + "balance": "1000000000000000000000" + }, + "b1178ad47383c31c8134a1941cbcd474d06244e2": { + "balance": "1000000000000000000000" + }, + "979d681c617da16f21bcaca101ed16ed015ab696": { + "balance": "1880000000000000000000" + }, + "6b20c080606a79c73bd8e75b11717a4e8db3f1c3": { + "balance": "299720000000000000000" + }, + "b85218f342f8012eda9f274e63ce2152b2dcfdab": { + "balance": "3100000000000000000000" + }, + "530b61e42f39426d2408d40852b9e34ab5ebebc5": { + "balance": "267400000000000000000" + }, + "76afc225f4fa307de484552bbe1d9d3f15074c4a": { + "balance": "2998800000000000000000" + }, + "1e783e522ab7df0acaac9eeed3593039e5ac7579": { + "balance": "203435800000000000000000" + }, + "0f7bf6373f771a4601762c4dae5fbbf4fedd9cc9": { + "balance": "2000000000000000000000" + }, + "7a8797690ab77b5470bf7c0c1bba612508e1ac7d": { + "balance": "8865000000000000000000" + }, + "2a2ab6b74c7af1d9476bb5bcb4524797bedc3552": { + "balance": "1000000000000000000000" + }, + "523e140dc811b186dee5d6c88bf68e90b8e096fd": { + "balance": "2000000000000000000000" + }, + "ea8168fbf225e786459ca6bb18d963d26b505309": { + "balance": "500000000000000000000" + }, + "20ff3ede8cadb5c37b48cb14580fb65e23090a7b": { + "balance": "42000000000000000000000" + }, + "e482d255ede56b04c3e8df151f56e9ca62aaa8c2": { + "balance": "500000000000000000000" + }, + "2e0880a34596230720f05ac8f065af8681dcb6c2": { + "balance": "100000000000000000000000" + }, + "c674f28c8afd073f8b799691b2f0584df942e844": { + "balance": "2000000000000000000000" + }, + "b646df98b49442746b61525c81a3b04ba3106250": { + "balance": "1970000000000000000000" + }, + "d55c1c8dfbe1e02cacbca60fdbdd405b09f0b75f": { + "balance": "2000000000000000000000" + }, + "65ebaed27edb9dcc1957aee5f452ac2105a65c0e": { + "balance": "43531987000000000000000" + }, + "f079e1b1265f50e8c8a98ec0c7815eb3aeac9eb4": { + "balance": "20094000000000000000" + }, + "867eba56748a5904350d2ca2a5ce9ca00b670a9b": { + "balance": "20000000000000000000000" + }, + "51ee0cca3bcb10cd3e983722ced8493d926c0866": { + "balance": "999972000000000000000" + }, + "88d541c840ce43cefbaf6d19af6b9859b573c145": { + "balance": "170000000000000000000" + }, + "f851b010f633c40af1a8f06a73ebbaab65077ab5": { + "balance": "4400000000000000000000" + }, + "e0aa69365555b73f282333d1e30c1bbd072854e8": { + "balance": "7000000000000000000000" + }, + "c7b1c83e63203f9547263ef6282e7da33b6ed659": { + "balance": "18200000000000000000" + }, + "af06f5fa6d1214ec43967d1bd4dde74ab814a938": { + "balance": "88000000000000000000" + }, + "991173601947c2084a62d639527e961512579af9": { + "balance": "600000000000000000000" + }, + "7a381122bada791a7ab1f6037dac80432753baad": { + "balance": "10000000000000000000000" + }, + "e766f34ff16f3cfcc97321721f43ddf5a38b0cf4": { + "balance": "1550000000000000000000" + }, + "d785a8f18c38b9bc4ffb9b8fa8c7727bd642ee1c": { + "balance": "1000000000000000000000" + }, + "aebd4f205de799b64b3564b256d42a711d37ef99": { + "balance": "1177100000000000000000" + }, + "a2fa17c0fb506ce494008b9557841c3f641b8cae": { + "balance": "20000000000000000000" + }, + "a8aca748f9d312ec747f8b6578142694c7e9f399": { + "balance": "2000000000000000000000" + }, + "950c68a40988154d2393fff8da7ccda99614f72c": { + "balance": "4597943000000000000000" + }, + "075d15e2d33d8b4fa7dba8b9e607f04a261e340b": { + "balance": "1910000000000000000000" + }, + "3616d448985f5d32aefa8b93a993e094bd854986": { + "balance": "205400000000000000000" + }, + "4bb9655cfb2a36ea7c637a7b859b4a3154e26ebe": { + "balance": "16000000000000000000000" + }, + "84949dba559a63bfc845ded06e9f2d9b7f11ef24": { + "balance": "2000000000000000000000" + }, + "937563d8a80fd5a537b0e66d20a02525d5d88660": { + "balance": "2500000000000000000000" + }, + "b183ebee4fcb42c220e47774f59d6c54d5e32ab1": { + "balance": "1604266000000000000000" + }, + "21e5d77320304c201c1e53b261a123d0a1063e81": { + "balance": "86972000000000000000" + }, + "fa14b566234abee73042c31d21717182cba14aa1": { + "balance": "328000000000000000000" + }, + "2da617695009cc57d26ad490b32a5dfbeb934e5e": { + "balance": "20000000000000000000000" + }, + "3326b88de806184454c40b27f309d9dd6dcfb978": { + "balance": "17900000000000000000000" + }, + "95e6a54b2d5f67a24a4875af75107ca7ea9fd2fa": { + "balance": "1337000000000000000000" + }, + "8db58e406e202df9bc703c480bd8ed248d52a032": { + "balance": "2000000000000000000000" + }, + "f777361a3dd8ab62e5f1b9b047568cc0b555704c": { + "balance": "1000000000000000000000" + }, + "83a93b5ba41bf88720e415790cdc0b67b4af34c4": { + "balance": "200000000000000000000" + }, + "8a1cc5ac111c49bfcfd848f37dd768aa65c88802": { + "balance": "10000000000000000000000" + }, + "52214378b54004056a7cc08c891327798ac6b248": { + "balance": "15200000000000000000000" + }, + "ad80d865b85c34d2e6494b2e7aefea6b9af184db": { + "balance": "4000000000000000000000" + }, + "e7d6240620f42c5edbb2ede6aec43da4ed9b5757": { + "balance": "1000000000000000000000" + }, + "d0e35e047646e759f4517093d6408642517f084d": { + "balance": "3939507000000000000000" + }, + "9340345ca6a3eabdb77363f2586043f29438ce0b": { + "balance": "530922000000000000000" + }, + "6640ccf053555c130ae2b656647ea6e31637b9ab": { + "balance": "1970000000000000000000" + }, + "184d86f3466ae6683b19729982e7a7e1a48347b2": { + "balance": "10000000000000000000000" + }, + "84ec06f24700fe42414cb9897c154c88de2f6132": { + "balance": "1337000000000000000000" + }, + "d1e5e234a9f44266a4a6241a84d7a1a55ad5a7fe": { + "balance": "20000000000000000000000" + }, + "e8a9a41740f44f54c3688b53e1ddd42e43c9fe94": { + "balance": "4000000000000000000000" + }, + "6e3a51db743d334d2fe88224b5fe7c008e80e624": { + "balance": "106000000000000000000" + }, + "3e94df5313fa520570ef232bc3311d5f622ff183": { + "balance": "2000000000000000000000" + }, + "8957727e72cf629020f4e05edf799aa7458062d0": { + "balance": "2200000000000000000000" + }, + "cf5e0eacd1b39d0655f2f77535ef6608eb950ba0": { + "balance": "2000000000000000000000" + }, + "f4aaa3a6163e3706577b49c0767e948a681e16ee": { + "balance": "2000000000000000000000" + }, + "97f1fe4c8083e596212a187728dd5cf80a31bec5": { + "balance": "20000000000000000000" + }, + "57d5fd0e3d3049330ffcdcd020456917657ba2da": { + "balance": "1991240000000000000000" + }, + "49bdbc7ba5abebb6389e91a3285220d3451bd253": { + "balance": "1000000000000000000000" + }, + "ae126b382cf257fad7f0bc7d16297e54cc7267da": { + "balance": "300000000000000000000" + }, + "bbf8616d97724af3def165d0e28cda89b800009a": { + "balance": "114063000000000000000" + }, + "adb948b1b6fefe207de65e9bbc2de98e605d0b57": { + "balance": "2000000000000000000000" + }, + "8a217db38bc35f215fd92906be42436fe7e6ed19": { + "balance": "6000000000000000000000" + }, + "e28b062259e96eeb3c8d4104943f9eb325893cf5": { + "balance": "1337000000000000000000" + }, + "6a6b18a45a76467e2e5d5a2ef911c3e12929857b": { + "balance": "82000000000000000000000" + }, + "cb68ae5abe02dcf8cbc5aa719c25814651af8b85": { + "balance": "500000000000000000000" + }, + "4c7e2e2b77ad0cd6f44acb2861f0fb8b28750ef9": { + "balance": "20000000000000000000" + }, + "58ba1569650e5bbbb21d35d3e175c0d6b0c651a9": { + "balance": "500000000000000000000" + }, + "1eb4bf73156a82a0a6822080c6edf49c469af8b9": { + "balance": "1910000000000000000000" + }, + "4103299671d46763978fa4aa19ee34b1fc952784": { + "balance": "200000000000000000000" + }, + "e321bb4a946adafdade4571fb15c0043d39ee35f": { + "balance": "1575212000000000000000" + }, + "893608751d68d046e85802926673cdf2f57f7cb8": { + "balance": "19700000000000000000" + }, + "70fee08b00c6c2c04a3c625c1ff77caf1c32df01": { + "balance": "200000000000000000000" + }, + "7b0fea1176d52159333a143c294943da36bbddb4": { + "balance": "9380000000000000000000" + }, + "d331c823825a9e5263d052d8915d4dcde07a5c37": { + "balance": "564000000000000000000" + }, + "a45432a6f2ac9d56577b938a37fabac8cc7c461c": { + "balance": "1000000000000000000000" + }, + "764fc46d428b6dbc228a0f5f55c9508c772eab9f": { + "balance": "26000000000000000000000" + }, + "1a95a8a8082e4652e4170df9271cb4bb4305f0b2": { + "balance": "50000000000000000000" + }, + "08c9f1bfb689fdf804d769f82123360215aff93b": { + "balance": "1970000000000000000000" + }, + "1572cdfab72a01ce968e78f5b5448da29853fbdd": { + "balance": "5061500000000000000000" + }, + "379c7166849bc24a02d6535e2def13daeef8aa8d": { + "balance": "100000000000000000000" + }, + "e0a254ac09b9725bebc8e460431dd0732ebcabbf": { + "balance": "6000000000000000000000" + }, + "3225c1ca5f2a9c88156bb7d9cdc44a326653c214": { + "balance": "400000000000000000000" + }, + "84686c7bad762c54b667d59f90943cd14d117a26": { + "balance": "20000000000000000000" + }, + "3d5a8b2b80be8b35d8ecf789b5ed7a0775c5076c": { + "balance": "20000000000000000000" + }, + "2ccf80e21898125eb4e807cd82e09b9d28592f6e": { + "balance": "2000000000000000000000" + }, + "dde969aef34ea87ac299b7597e292b4a0155cc8a": { + "balance": "298819000000000000000" + }, + "19e94e620050aad766b9e1bad931238312d4bf49": { + "balance": "2396000000000000000000" + }, + "959f57fded6ae37913d900b81e5f48a79322c627": { + "balance": "255599000000000000000" + }, + "b9b0a3219a3288d9b35b091b14650b8fe23dce2b": { + "balance": "14000000000000000000000" + }, + "3575c770668a9d179f1ef768c293f80166e2aa3d": { + "balance": "474000000000000000000" + }, + "58f05b262560503ca761c61890a4035f4c737280": { + "balance": "8000000000000000000000" + }, + "3286d1bc657a312c8847d93cb3cb7950f2b0c6e3": { + "balance": "20000000000000000000000" + }, + "1d9e6aaf8019a05f230e5def05af5d889bd4d0f2": { + "balance": "133700000000000000000" + }, + "a375b4bc24a24e1f797593cc302b2f331063fa5c": { + "balance": "200000000000000000000" + }, + "108ba7c2895c50e072dc6f964932d50c282d3034": { + "balance": "500000000000000000000" + }, + "b6b34a263f10c3d2eceb0acc559a7b2ab85ce565": { + "balance": "4000000000000000000000" + }, + "a4d2b429f1ad5349e31704969edc5f25ee8aca10": { + "balance": "10000000000000000000000" + }, + "674adb21df4c98c7a347ac4c3c24266757dd7039": { + "balance": "2000000000000000000000" + }, + "33565ba9da2c03e778ce12294f081dfe81064d24": { + "balance": "16000000000000000000000" + }, + "4ddda7586b2237b053a7f3289cf460dc57d37a09": { + "balance": "10000000000000000000000" + }, + "cc4faac00be6628f92ef6b8cb1b1e76aac81fa18": { + "balance": "205410000000000000000" + }, + "5f99dc8e49e61d57daef606acdd91b4d7007326a": { + "balance": "3000000000000000000000" + }, + "b8a979352759ba09e35aa5935df175bff678a108": { + "balance": "20000000000000000000" + }, + "86fff220e59305c09f483860d6f94e96fbe32f57": { + "balance": "42900000000000000000" + }, + "03e8b084537557e709eae2e1e1a5a6bce1ef8314": { + "balance": "20000000000000000000" + }, + "dda4ff7de491c687df4574dd1b17ff8f246ba3d1": { + "balance": "19600000000000000000000" + }, + "2538532936813c91e653284f017c80c3b8f8a36f": { + "balance": "2002000000000000000000" + }, + "5a82f96cd4b7e2d93d10f3185dc8f43d4b75aa69": { + "balance": "1999400000000000000000" + }, + "86740a46648e845a5d96461b18091ff57be8a16f": { + "balance": "98000000000000000000000" + }, + "7e3f63e13129a221ba1ab06326342cd98b5126ae": { + "balance": "1597960000000000000000" + }, + "1f5f3b34bd134b2781afe5a0424ac5846cdefd11": { + "balance": "99000000000000000000" + }, + "39936c2719450b9420cc2522cf91db01f227c1c1": { + "balance": "500000000000000000000" + }, + "967076a877b18ec15a415bb116f06ef32645dba3": { + "balance": "2000000000000000000000" + }, + "a42908e7fe53980a9abf4044e957a54b70e99cbe": { + "balance": "2000000000000000000000" + }, + "5eb371c407406c427b3b7de271ad3c1e04269579": { + "balance": "3000000000000000000000" + }, + "a570223ae3caa851418a9843a1ac55db4824f4fd": { + "balance": "200000000000000000000" + }, + "764692cccb33405dd0ab0c3379b49caf8e6221ba": { + "balance": "20000000000000000000" + }, + "a365918bfe3f2627b9f3a86775d8756e0fd8a94b": { + "balance": "400000000000000000000" + }, + "069ed0ab7aa77de571f16106051d92afe195f2d0": { + "balance": "200000000000000000000" + }, + "bd432a3916249b4724293af9146e49b8280a7f2a": { + "balance": "4000000000000000000000" + }, + "61c9dce8b2981cb40e98b0402bc3eb28348f03ac": { + "balance": "196910000000000000000" + }, + "8f1fcc3c51e252b693bc5b0ec3f63529fe69281e": { + "balance": "6000000000000000000000" + }, + "55fd08d18064bd202c0ec3d2cce0ce0b9d169c4d": { + "balance": "1970000000000000000000" + }, + "383a7c899ee18bc214969870bc7482f6d8f3570e": { + "balance": "10000000000000000000000" + }, + "b14cc8de33d6338236539a489020ce4655a32bc6": { + "balance": "8000000000000000000000" + }, + "448bf410ad9bbc2fecc4508d87a7fc2e4b8561ad": { + "balance": "199955000000000000000" + }, + "06f7dc8d1b9462cef6feb13368a7e3974b097f9f": { + "balance": "2000000000000000000000" + }, + "9c9f89a3910f6a2ae8a91047a17ab788bddec170": { + "balance": "10000000000000000000000" + }, + "5de598aba344378cab4431555b4f79992dc290c6": { + "balance": "1337000000000000000000" + }, + "87e6034ecf23f8b5639d5f0ea70a22538a920423": { + "balance": "328000000000000000000" + }, + "8b27392206b958cd375d7ef8af2cf8ef0598c0bc": { + "balance": "1000000000000000000000" + }, + "49136fe6e28b7453fcb16b6bbbe9aaacba8337fd": { + "balance": "2000000000000000000000" + }, + "6982fe8a867e93eb4a0bd051589399f2ec9a5292": { + "balance": "2000000000000000000000" + }, + "9fd1052a60506bd1a9ef003afd9d033c267d8e99": { + "balance": "1000000000000000000000" + }, + "d38fa2c4cc147ad06ad5a2f75579281f22a7cc1f": { + "balance": "20000000000000000000000" + }, + "6f794dbdf623daa6e0d00774ad6962737c921ea4": { + "balance": "2000000000000000000000" + }, + "e96b184e1f0f54924ac874f60bbf44707446b72b": { + "balance": "2910840000000000000000" + }, + "b5ba29917c78a1d9e5c5c713666c1e411d7f693a": { + "balance": "3100000000000000000000" + }, + "81d619ff5726f2405f12904c72eb1e24a0aaee4f": { + "balance": "20000000000000000000000" + }, + "b02fa29387ec12e37f6922ac4ce98c5b09e0b00f": { + "balance": "2000000000000000000000" + }, + "b7230d1d1ff2aca366963914a79df9f7c5ea2c98": { + "balance": "8000000000000000000000" + }, + "7b4007c45e5a573fdbb6f8bd746bf94ad04a3c26": { + "balance": "15202564000000000000000" + }, + "8d9a0c70d2262042df1017d6c303132024772712": { + "balance": "2000000000000000000000" + }, + "323aad41df4b6fc8fece8c93958aa901fa680843": { + "balance": "970000000000000000000" + }, + "db04fad9c49f9e880beb8fcf1d3a3890e4b3846f": { + "balance": "1242482000000000000000" + }, + "27824666d278d70423f03dfe1dc7a3f02f43e2b5": { + "balance": "1000070000000000000000" + }, + "e04920dc6ecc1d6ecc084f88aa0af5db97bf893a": { + "balance": "182000000000000000000" + }, + "b0c1b177a220e41f7c74d07cde8569c21c75c2f9": { + "balance": "5600000000000000000000" + }, + "7864dc999fe4f8e003c0f43decc39aae1522dc0f": { + "balance": "94400000000000000000" + }, + "c75c37ce2da06bbc40081159c6ba0f976e3993b1": { + "balance": "1078640000000000000000" + }, + "179a825e0f1f6e985309668465cffed436f6aea9": { + "balance": "20000000000000000000" + }, + "2c6b699d9ead349f067f45711a074a641db6a897": { + "balance": "20000000000000000000" + }, + "068ce8bd6e902a45cb83b51541b40f39c4469712": { + "balance": "5240000000000000000000" + }, + "767ac690791c2e23451089fe6c7083fe55deb62b": { + "balance": "820000000000000000000" + }, + "b34f04b8db65bba9c26efc4ce6efc50481f3d65d": { + "balance": "20000000000000000000000" + }, + "29aef48de8c9fbad4b9e4ca970797a5533eb722d": { + "balance": "10000000000000000000000" + }, + "0a0ecda6636f7716ef1973614687fd89a820a706": { + "balance": "394000000000000000000" + }, + "b32825d5f3db249ef4e85cc4f33153958976e8bc": { + "balance": "501375000000000000000" + }, + "7ef16fd8d15b378a0fba306b8d03dd98fc92619f": { + "balance": "700000000000000000000" + }, + "b58b52865ea55d8036f2fab26098b352ca837e18": { + "balance": "18200000000000000000" + }, + "9b658fb361e046d4fcaa8aef6d02a99111223625": { + "balance": "2000000000000000000000" + }, + "b2a498f03bd7178bd8a789a00f5237af79a3e3f8": { + "balance": "19400000000000000000000" + }, + "cb48fe8265d9af55eb7006bc335645b0a3a183be": { + "balance": "3000000000000000000000" + }, + "3cf9a1d465e78b7039e3694478e2627b36fcd141": { + "balance": "1372000000000000000000" + }, + "5db84400570069a9573cab04b4e6b69535e202b8": { + "balance": "9700000000000000000000" + }, + "214c89c5bd8e7d22bc574bb35e48950211c6f776": { + "balance": "18903000000000000000" + }, + "53396f4a26c2b4604496306c5442e7fcba272e36": { + "balance": "20055000000000000000000" + }, + "720994dbe56a3a95929774e20e1fe525cf3704e4": { + "balance": "8000000000000000000000" + }, + "3571cf7ad304ecaee595792f4bbfa484418549d6": { + "balance": "5825500000000000000000" + }, + "6042c644bae2b96f25f94d31f678c90dc96690db": { + "balance": "2000000000000000000000" + }, + "2e24b597873bb141bdb237ea8a5ab747799af02d": { + "balance": "20000000000000000000000" + }, + "08c802f87758349fa03e6bc2e2fd0791197eea9a": { + "balance": "2000000000000000000000" + }, + "297a88921b5fca10e5bb9ded60025437ae221694": { + "balance": "200000000000000000000" + }, + "aee49d68adedb081fd43705a5f78c778fb90de48": { + "balance": "20000000000000000000" + }, + "4cee901b4ac8b156c5e2f8a6f1bef572a7dceb7e": { + "balance": "1000000000000000000000" + }, + "dfaf31e622c03d9e18a0ddb8be60fbe3e661be0a": { + "balance": "9999800000000000000000" + }, + "00aa5381b2138ebeffc191d5d8c391753b7098d2": { + "balance": "990049000000000000000" + }, + "5b4c0c60f10ed2894bdb42d9dd1d210587810a0d": { + "balance": "500000000000000000000" + }, + "c44f4ab5bc60397c737eb0683391b633f83c48fa": { + "balance": "1000000000000000000000" + }, + "50bef2756248f9a7a380f91b051ba3be28a649ed": { + "balance": "1999884000000000000000" + }, + "1bd909ac0d4a1102ec98dcf2cca96a0adcd7a951": { + "balance": "20055000000000000000" + }, + "9ec03e02e587b7769def538413e97f7e55be71d8": { + "balance": "19700000000000000000000" + }, + "9874803fe1f3a0365e7922b14270eaeb032cc1b5": { + "balance": "1124500000000000000000" + }, + "4e2310191ead8d3bc6489873a5f0c2ec6b87e1be": { + "balance": "1000000000000000000000" + }, + "93678a3c57151aeb68efdc43ef4d36cb59a009f3": { + "balance": "30060000000000000000" + }, + "f483f607a21fcc28100a018c568ffbe140380410": { + "balance": "1000000000000000000000" + }, + "2a91a9fed41b7d0e5cd2d83158d3e8a41a9a2d71": { + "balance": "1940000000000000000000" + }, + "240e559e274aaef0c258998c979f671d1173b88b": { + "balance": "4000000000000000000000" + }, + "108a2b7c336f784779d8b54d02a8d31d9a139c0a": { + "balance": "10000000000000000000000" + }, + "9c98fdf1fdcd8ba8f4c5b04c3ae8587efdf0f6e6": { + "balance": "6000000000000000000000" + }, + "194ff44aefc17bd20efd7a204c47d1620c86db5d": { + "balance": "2999400000000000000000" + }, + "1f8116bd0af5570eaf0c56c49c7ab5e37a580458": { + "balance": "2000000000000000000000" + }, + "d79835e404fb86bf845fba090d6ba25e0c8866a6": { + "balance": "2400000000000000000000" + }, + "a8e7201ff619faffc332e6ad37ed41e301bf014a": { + "balance": "600000000000000000000" + }, + "286906b6bd4972e3c71655e04baf36260c7cb153": { + "balance": "340000000000000000000" + }, + "db4bc83b0e6baadb1156c5cf06e0f721808c52c7": { + "balance": "880000000000000000000" + }, + "a158148a2e0f3e92dc2ce38febc20107e3253c96": { + "balance": "2000000000000000000000" + }, + "9f6a322a6d469981426ae844865d7ee0bb15c7b3": { + "balance": "50003000000000000000" + }, + "32f29e8727a74c6b4301e3ffff0687c1b870dae9": { + "balance": "1000000000000000000000" + }, + "19918aa09e7d494e98ffa5db50350892f7156ac6": { + "balance": "10000000000000000000000" + }, + "5a5f8508da0ebebb90be9033bd4d9e274105ae00": { + "balance": "6685000000000000000000" + }, + "6fc25e7e00ca4f60a9fe6f28d1fde3542e2d1079": { + "balance": "792000000000000000000" + }, + "72094f3951ffc9771dced23ada080bcaf9c7cca7": { + "balance": "6000000000000000000000" + }, + "43f7e86e381ec51ec4906d1476cba97a3db584e4": { + "balance": "1000000000000000000000" + }, + "05696b73916bd3033e05521e3211dfec026e98e4": { + "balance": "2000000000000000000000" + }, + "5e7f70378775589fc66a81d3f653e954f55560eb": { + "balance": "2434000000000000000000" + }, + "895613236f3584216ad75c5d3e07e3fa6863a778": { + "balance": "2000000000000000000000" + }, + "4eb1454b573805c8aca37edec7149a41f61202f4": { + "balance": "300000000000000000000" + }, + "d99999a2490d9494a530cae4daf38554f4dd633e": { + "balance": "120000000000000000000" + }, + "1704cefcfb1331ec7a78388b29393e85c1af7916": { + "balance": "400000000000000000000" + }, + "ac4acfc36ed6094a27e118ecc911cd473e8fb91f": { + "balance": "1799800000000000000000" + }, + "a975b077fcb4cc8efcbf838459b6fa243a4159d6": { + "balance": "40000000000000000000" + }, + "9c405cf697956138065e11c5f7559e67245bd1a5": { + "balance": "200000000000000000000" + }, + "cafde855864c2598da3cafc05ad98df2898e8048": { + "balance": "14179272000000000000000" + }, + "8ef711e43a13918f1303e81d0ea78c9eefd67eb2": { + "balance": "4000000000000000000000" + }, + "0b14891999a65c9ef73308efe3100ca1b20e8192": { + "balance": "800000000000000000000" + }, + "47cf9cdaf92fc999cc5efbb7203c61e4f1cdd4c3": { + "balance": "131400000000000000000" + }, + "04ba8a3f03f08b895095994dda619edaacee3e7a": { + "balance": "2000000000000000000000" + }, + "02b6d65cb00b7b36e1fb5ed3632c4cb20a894130": { + "balance": "20000000000000000000000" + }, + "f99aee444b5783c093cfffd1c4632cf93c6f050c": { + "balance": "400000000000000000000" + }, + "2541314a0b408e95a694444977712a50713591ab": { + "balance": "1634706000000000000000" + }, + "3096dca34108085bcf04ae72b94574a13e1a3e1d": { + "balance": "200000000000000000000" + }, + "56df05bad46c3f00ae476ecf017bb8c877383ff1": { + "balance": "197248000000000000000" + }, + "6d59b21cd0e2748804d9abe064eac2bef0c95f27": { + "balance": "2000000000000000000000" + }, + "b29f5b7c1930d9f97a115e067066f0b54db44b3b": { + "balance": "1000000000000000000000" + }, + "888c16144933197cac26504dd76e06fd6600c789": { + "balance": "100000000000000000000" + }, + "dfe3c52a92c30396a4e33a50170dc900fcf8c9cf": { + "balance": "50000000000000000000" + }, + "f76f69cee4faa0a63b30ae1e7881f4f715657010": { + "balance": "200000000000000000000" + }, + "ee0007b0960d00908a94432a737557876aac7c31": { + "balance": "53053000000000000000" + }, + "effc15e487b1beda0a8d1325bdb4172240dc540a": { + "balance": "64940000000000000000" + }, + "40ab0a3e83d0c8ac9366910520eab1772bac3b1a": { + "balance": "976600000000000000000" + }, + "1895a0eb4a4372722fcbc5afe6936f289c88a419": { + "balance": "910000000000000000000" + }, + "81efe296ae76c860d1c5fbd33d47e8ce9996d157": { + "balance": "1000000000000000000000" + }, + "9ddd355e634ee9927e4b7f6c97e7bf3a2f1e687a": { + "balance": "50000000000000000000" + }, + "f2b4ab2c9427a9015ef6eefff5edb60139b719d1": { + "balance": "716800000000000000000" + }, + "765be2e12f629e6349b97d21b62a17b7c830edab": { + "balance": "6000000000000000000000" + }, + "ff61c9c1b7a3d8b53bba20b34466544b7b216644": { + "balance": "2000000000000000000000" + }, + "36a08fd6fd1ac17ce15ed57eefb12a2be28188bf": { + "balance": "1337000000000000000000" + }, + "17049311101d817efb1d65910f663662a699c98c": { + "balance": "1999800000000000000000" + }, + "30511832918d8034a7bee72ef2bfee440ecbbcf6": { + "balance": "16100000000000000000000" + }, + "d27c234ff7accace3d996708f8f9b04970f97d36": { + "balance": "1337000000000000000000" + }, + "a961171f5342b173dd70e7bfe5b5ca238b13bcdd": { + "balance": "3397053000000000000000" + }, + "30bf61b2d877fe10635126326fa189e4b0b1c3b0": { + "balance": "1027580000000000000000" + }, + "4bb6d86b8314c22d8d37ea516d0019f156aae12d": { + "balance": "1000000000000000000000" + }, + "5f363e0ab747e02d1b3b66abb69ea53c7baf523a": { + "balance": "11640000000000000000000" + }, + "283e11203749b1fa4f32febb71e49d135919382a": { + "balance": "1000000000000000000000" + }, + "ac5999a89d2dd286d5a80c6dee7e86aad40f9e12": { + "balance": "3880000000000000000000" + }, + "3f6dd3650ee428dcb7759553b017a96a94286ac9": { + "balance": "1337000000000000000000" + }, + "b3fc1d6881abfcb8becc0bb021b8b73b7233dd91": { + "balance": "50000000000000000000" + }, + "f0832a6bb25503eeca435be31b0bf905ca1fcf57": { + "balance": "6685000000000000000000" + }, + "9d7fda7070bf3ee9bbd9a41f55cad4854ae6c22c": { + "balance": "11027380000000000000000" + }, + "4b0bd8acfcbc53a6010b40d4d08ddd2d9d69622d": { + "balance": "668500000000000000000" + }, + "f3b668b3f14d920ebc379092db98031b67b219b3": { + "balance": "199955000000000000000" + }, + "d91d889164479ce436ece51763e22cda19b22d6b": { + "balance": "3365200000000000000000" + }, + "ffe28db53c9044b4ecd4053fd1b4b10d7056c688": { + "balance": "100000000000000000000" + }, + "c77b01a6e911fa988d01a3ab33646beef9c138f3": { + "balance": "721400000000000000000" + }, + "c0064f1d9474ab915d56906c9fb320a2c7098c9b": { + "balance": "358000000000000000000" + }, + "4e3edad4864dab64cae4c5417a76774053dc6432": { + "balance": "590943000000000000000" + }, + "71d2cc6d02578c65f73c575e76ce8fbcfadcf356": { + "balance": "72400000000000000000" + }, + "9971df60f0ae66dce9e8c84e17149f09f9c52f64": { + "balance": "200000000000000000000" + }, + "58e661d0ba73d6cf24099a5562b808f7b3673b68": { + "balance": "2000000000000000000000" + }, + "84b0ee6bb837d3a4c4c5011c3a228c0edab4634a": { + "balance": "20000000000000000000" + }, + "84375afbf59b3a1d61a1be32d075e0e15a4fbca5": { + "balance": "200000000000000000000" + }, + "9ae9476bfecd3591964dd325cf8c2a24faed82c1": { + "balance": "4000000000000000000000" + }, + "6a4c8907b600248057b1e46354b19bdc859c991a": { + "balance": "20000000000000000000" + }, + "1c045649cd53dc23541f8ed4d341812808d5dd9c": { + "balance": "7000000000000000000000" + }, + "c5e488cf2b5677933971f64cb8202dd05752a2c0": { + "balance": "1000000000000000000000" + }, + "eb25481fcd9c221f1ac7e5fd1ecd9307a16215b8": { + "balance": "197000000000000000000" + }, + "a61887818f914a20e31077290b83715a6b2d6ef9": { + "balance": "1880000000000000000000" + }, + "679437eacf437878dc293d48a39c87b7421a216c": { + "balance": "64528000000000000000" + }, + "331a1c26cc6994cdd3c14bece276ffff4b9df77c": { + "balance": "18049000000000000000" + }, + "75b95696e8ec4510d56868a7c1a735c68b244890": { + "balance": "6400000000000000000000" + }, + "a77f3ee19e9388bbbb2215c62397b96560132360": { + "balance": "200000000000000000000" + }, + "bc7afc8477412274fc265df13c054473427d43c6": { + "balance": "130034000000000000000" + }, + "91050a5cffadedb4bb6eaafbc9e5013428e96c80": { + "balance": "1700000000000000000000" + }, + "24586ec5451735eeaaeb470dc8736aae752f82e5": { + "balance": "17600000000000000000" + }, + "51039377eed0c573f986c5e8a95fb99a59e9330f": { + "balance": "1970000000000000000000" + }, + "fbb161fe875f09290a4b262bc60110848f0d2226": { + "balance": "2000000000000000000000" + }, + "ed52a2cc0869dc9e9f842bd0957c47a8e9b0c9ff": { + "balance": "9550000000000000000000" + }, + "bad235d5085dc7b068a67c412677b03e1836884c": { + "balance": "2000000000000000000000" + }, + "055eac4f1ad3f58f0bd024d68ea60dbe01c6afb3": { + "balance": "100000000000000000000" + }, + "4058808816fdaa3a5fc98ed47cfae6c18315422e": { + "balance": "199800000000000000000" + }, + "3540c7bd7a8442d5bee21a2180a1c4edff1649e0": { + "balance": "1239295000000000000000" + }, + "c5edbbd2ca0357654ad0ea4793f8c5cecd30e254": { + "balance": "6000000000000000000000" + }, + "b5906b0ae9a28158e8ac550e39da086ee3157623": { + "balance": "200000000000000000000" + }, + "4d801093c19ca9b8f342e33cc9c77bbd4c8312cf": { + "balance": "345005000000000000000" + }, + "206482ee6f138a778fe1ad62b180ce856fbb23e6": { + "balance": "2000000000000000000000" + }, + "c0ed0d4ad10de03435b153a0fc25de3b93f45204": { + "balance": "3160000000000000000000" + }, + "29e67990e1b6d52e1055ffe049c53195a81542cf": { + "balance": "20000000000000000000000" + }, + "e6d22209ffd0b87509ade3a8e2ef429879cb89b5": { + "balance": "17260000000000000000000" + }, + "d6644d40e90bc97fe7dfe7cabd3269fd579ba4b3": { + "balance": "159000000000000000000" + }, + "ece1290877b583e361a2d41b009346e6274e2538": { + "balance": "300000000000000000000" + }, + "ab3861226ffec1289187fb84a08ec3ed043264e8": { + "balance": "1000000000000000000000" + }, + "60e0bdd0a259bb9cb09d3f37e5cd8b9daceabf8a": { + "balance": "1370000000000000000000" + }, + "28b77585cb3d55a199ab291d3a18c68fe89a848a": { + "balance": "1960000000000000000000" + }, + "73128173489528012e76b41a5e28c68ba4e3a9d4": { + "balance": "1000000000000000000000" + }, + "018492488ba1a292342247b31855a55905fef269": { + "balance": "140000000000000000000" + }, + "0bb54c72fd6610bfa4363397e020384b022b0c49": { + "balance": "1337000000000000000000" + }, + "520f66a0e2657ff0ac4195f2f064cf2fa4b24250": { + "balance": "40000000000000000000" + }, + "a1432ed2c6b7777a88e8d46d388e70477f208ca5": { + "balance": "7999538000000000000000" + }, + "149ba10f0da2725dc704733e87f5a524ca88515e": { + "balance": "7880000000000000000000" + }, + "b287f7f8d8c3872c1b586bcd7d0aedbf7e732732": { + "balance": "20000000000000000000" + }, + "c46bbdef76d4ca60d316c07f5d1a780e3b165f7e": { + "balance": "2000000000000000000000" + }, + "b5a589dd9f4071dbb6fba89b3f5d5dae7d96c163": { + "balance": "2000000000000000000000" + }, + "d218efb4db981cdd6a797f4bd48c7c26293ceb40": { + "balance": "2975000000000000000000" + }, + "af87d2371ef378957fbd05ba2f1d66931b01e2b8": { + "balance": "700000000000000000000" + }, + "86ef6426211949cc37f4c75e7850369d0cf5f479": { + "balance": "13399196000000000000000" + }, + "fb3a0b0d6b6a718f6fc0292a825dc9247a90a5d0": { + "balance": "199950000000000000000" + }, + "da16dd5c3d1a2714358fe3752cae53dbab2be98c": { + "balance": "19400000000000000000000" + }, + "9eb7834e171d41e069a77947fca87622f0ba4e48": { + "balance": "100000000000000000000" + }, + "e1d91b0954cede221d6f24c7985fc59965fb98b8": { + "balance": "2000000000000000000000" + }, + "85d0d88754ac84b8b21ba93dd2bfec72626faba8": { + "balance": "1000000000000000000000" + }, + "695b4cce085856d9e1f9ff3e79942023359e5fbc": { + "balance": "5000000000000000000000" + }, + "9156d18029350e470408f15f1aa3be9f040a67c6": { + "balance": "1000000000000000000000" + }, + "a9d64b4f3bb7850722b58b478ba691375e224e42": { + "balance": "6000000000000000000000" + }, + "17e4a0e52bac3ee44efe0954e753d4b85d644e05": { + "balance": "2000000000000000000000" + }, + "b8a79c84945e47a9c3438683d6b5842cff7684b1": { + "balance": "2000000000000000000000" + }, + "cfac2e1bf33205b05533691a02267ee19cd81836": { + "balance": "1000000000000000000000" + }, + "6b992521ec852370848ad697cc2df64e63cc06ff": { + "balance": "1000000000000000000000" + }, + "60af0ee118443c9b37d2fead77f5e521debe1573": { + "balance": "1910000000000000000000" + }, + "c6dbdb9efd5ec1b3786e0671eb2279b253f215ed": { + "balance": "1000000000000000000000" + }, + "659c0a72c767a3a65ced0e1ca885a4c51fd9b779": { + "balance": "2000000000000000000000" + }, + "ed1276513b6fc68628a74185c2e20cbbca7817bf": { + "balance": "191000000000000000000" + }, + "5ad12c5ed4fa827e2150cfa0d68c0aa37b1769b8": { + "balance": "800000000000000000000" + }, + "17c0fef6986cfb2e4041f9979d9940b69dff3de2": { + "balance": "4000000000000000000000" + }, + "ca98c7988efa08e925ef9c9945520326e9f43b99": { + "balance": "4000000000000000000000" + }, + "fe8f1fdcab7fbec9a6a3fcc507619600505c36a3": { + "balance": "19700000000000000000" + }, + "4420aa35465be617ad2498f370de0a3cc4d230af": { + "balance": "2000000000000000000000" + }, + "8232d1f9742edf8dd927da353b2ae7b4cbce7592": { + "balance": "668500000000000000000" + }, + "eca5f58792b8c62d2af556717ee3ee3028be4dce": { + "balance": "2000000000000000000000" + }, + "6bf86f1e2f2b8032a95c4d7738a109d3d0ed8104": { + "balance": "1820000000000000000000" + }, + "3ac2f0ff1612e4a1c346d53382abf6d8a25baa53": { + "balance": "2000000000000000000000" + }, + "daa1bd7a9148fb865cd612dd35f162861d0f3bdc": { + "balance": "3066243000000000000000" + }, + "5169c60aee4ceed1849ab36d664cff97061e8ea8": { + "balance": "3000000000000000000000" + }, + "2a5e3a40d2cd0325766de73a3d671896b362c73b": { + "balance": "100000000000000000000000" + }, + "a83382b6e15267974a8550b98f7176c1a353f9be": { + "balance": "3541608000000000000000" + }, + "b50c149a1906fad2786ffb135aab501737e9e56f": { + "balance": "388000000000000000000" + }, + "d9775965b716476675a8d513eb14bbf7b07cd14a": { + "balance": "5076200000000000000000" + }, + "66662006015c1f8e3ccfcaebc8ee6807ee196303": { + "balance": "500024000000000000000" + }, + "78746a958dced4c764f876508c414a68342cecb9": { + "balance": "50600000000000000000" + }, + "e982e6f28c548f5f96f45e63f7ab708724f53fa1": { + "balance": "396238000000000000000" + }, + "740bfd52e01667a3419b029a1b8e45576a86a2db": { + "balance": "16800000000000000000000" + }, + "2bd252e0d732ff1d7c78f0a02e6cb25423cf1b1a": { + "balance": "2674000000000000000000" + }, + "2e2d7ea66b9f47d8cc52c01c52b6e191bc7d4786": { + "balance": "3999800000000000000000" + }, + "3e3161f1ea2fbf126e79da1801da9512b37988c9": { + "balance": "49250000000000000000000" + }, + "7e2ba86da52e785d8625334f3397ba1c4bf2e8d1": { + "balance": "197000000000000000000" + }, + "7608f437b31f18bc0b64d381ae86fd978ed7b31f": { + "balance": "50000000000000000000" + }, + "25a5a44d38a2f44c6a9db9cdbc6b1e2e97abb509": { + "balance": "17000000000000000000000" + }, + "745ad3abc6eeeb2471689b539e789ce2b8268306": { + "balance": "1129977000000000000000" + }, + "09e437d448861228a232b62ee8d37965a904ed9c": { + "balance": "21708305000000000000000" + }, + "be53322f43fbb58494d7cce19dda272b2450e827": { + "balance": "200018000000000000000" + }, + "4166fc08ca85f766fde831460e9dc93c0e21aa6c": { + "balance": "1000000000000000000000" + }, + "99c0174cf84e0783c220b4eb6ae18fe703854ad3": { + "balance": "2074800000000000000000" + }, + "3cf484524fbdfadae26dc185e32b2b630fd2e726": { + "balance": "448798000000000000000" + }, + "fdcd5d80b105897a57abc47865768b2900524295": { + "balance": "6400000000000000000000" + }, + "f22f4078febbbaa8b0e78e642c8a42f35d433905": { + "balance": "1999944000000000000000" + }, + "eac768bf14b8f9432e69eaa82a99fbeb94cd0c9c": { + "balance": "98500000000000000000000" + }, + "2639eee9873ceec26fcc9454b548b9e7c54aa65c": { + "balance": "1000000000000000000000" + }, + "c3c3c2510d678020485a63735d1307ec4ca6302b": { + "balance": "1000000000000000000000" + }, + "b73d6a77559c86cf6574242903394bacf96e3570": { + "balance": "91200000000000000000" + }, + "5ce2e7ceaaa18af0f8aafa7fbad74cc89e3cd436": { + "balance": "20000000000000000000000" + }, + "03377c0e556b640103289a6189e1aeae63493467": { + "balance": "20000000000000000000000" + }, + "6eb0a5a9ae96d22cf01d8fd6483b9f38f08c2c8b": { + "balance": "4000000000000000000000" + }, + "fc8215a0a69913f62a43bf1c8590b9ddcd0d8ddb": { + "balance": "2000000000000000000000" + }, + "4a835c25824c47ecbfc79439bf3f5c3481aa75cd": { + "balance": "1400000000000000000000" + }, + "b5493ef173724445cf345c035d279ba759f28d51": { + "balance": "20000000000000000000" + }, + "b9e90c1192b3d5d3e3ab0700f1bf655f5dd4347a": { + "balance": "499928000000000000000" + }, + "419bde7316cc1ed295c885ace342c79bf7ee33ea": { + "balance": "6000000000000000000000" + }, + "e4625501f52b7af52b19ed612e9d54fdd006b492": { + "balance": "209440000000000000000" + }, + "e9d599456b2543e6db80ea9b210e908026e2146e": { + "balance": "200000000000000000000" + }, + "2c06dd922b61514aafedd84488c0c28e6dcf0e99": { + "balance": "100000000000000000000000" + }, + "06b5ede6fdf1d6e9a34721379aeaa17c713dd82a": { + "balance": "2000000000000000000000" + }, + "d8930a39c77357c30ad3a060f00b06046331fd62": { + "balance": "820000000000000000000" + }, + "b2a2c2111612fb8bbb8e7dd9378d67f1a384f050": { + "balance": "20000000000000000000" + }, + "1f174f40a0447234e66653914d75bc003e5690dc": { + "balance": "160000000000000000000" + }, + "e06cb6294704eea7437c2fc3d30773b7bf38889a": { + "balance": "20094000000000000000" + }, + "cd06f8c1b5cdbd28e2d96b6346c3e85a0483ba24": { + "balance": "1000000000000000000000" + }, + "f316ef1df2ff4d6c1808dba663ec8093697968e0": { + "balance": "1794400000000000000000" + }, + "1e6915ebd9a19c81b692ad99b1218a592c1ac7b1": { + "balance": "4000000000000000000000" + }, + "885493bda36a0432976546c1ddce71c3f4570021": { + "balance": "216700000000000000000" + }, + "18b0407cdad4ce52600623bd5e1f6a81ab61f026": { + "balance": "319489000000000000000" + }, + "187d9f0c07f8eb74faaad15ebc7b80447417f782": { + "balance": "20000000000000000000" + }, + "5d6ccf806738091042ad97a6e095fe8c36aa79c5": { + "balance": "188000000000000000000" + }, + "53437fecf34ab9d435f4deb8ca181519e2592035": { + "balance": "188000000000000000000" + }, + "fd1faa347b0fcc804c2da86c36d5f1d18b7087bb": { + "balance": "52380000000000000000" + }, + "650cf67db060cce17568d5f2a423687c49647609": { + "balance": "100000000000000000000" + }, + "bcd95ef962462b6edfa10fda87d72242fe3edb5c": { + "balance": "334133000000000000000" + }, + "3b5e8b3c77f792decb7a8985df916efb490aac23": { + "balance": "2000000000000000000000" + }, + "f13b083093ba564e2dc631568cf7540d9a0ec719": { + "balance": "1999944000000000000000" + }, + "373c547e0cb5ce632e1c5ad66155720c01c40995": { + "balance": "4691588000000000000000" + }, + "7313461208455455465445a459b06c3773b0eb30": { + "balance": "2000000000000000000000" + }, + "441f37e8a029fd02482f289c49b5d06d00e408a4": { + "balance": "333333000000000000000" + }, + "d30d4c43adcf55b2cb53d68323264134498d89ce": { + "balance": "1000000000000000000000" + }, + "f648ea89c27525710172944e79edff847803b775": { + "balance": "100000000000000000000000" + }, + "0c7f869f8e90d53fdc03e8b2819b016b9d18eb26": { + "balance": "20000000000000000000000" + }, + "c71f92a3a54a7b8c2f5ea44305fccb84eee23148": { + "balance": "49980000000000000000" + }, + "7988901331e387f713faceb9005cb9b65136eb14": { + "balance": "1970000000000000000000" + }, + "e9a39a8bac0f01c349c64cedb69897f633234ed2": { + "balance": "3980000000000000000000" + }, + "ad2a5c00f923aaf21ab9f3fb066efa0a03de2fb2": { + "balance": "999996000000000000000" + }, + "f25259a5c939cd25966c9b6303d3731c53ddbc4c": { + "balance": "200000000000000000000" + }, + "d1682c2159018dc3d07f08240a8c606daf65f8e1": { + "balance": "200000000000000000000000" + }, + "a99991cebd98d9c838c25f7a7416d9e244ca250d": { + "balance": "1000000000000000000000" + }, + "5a285755391e914e58025faa48cc685f4fd4f5b8": { + "balance": "26000000000000000000000" + }, + "4d24b7ac47d2f27de90974ba3de5ead203544bcd": { + "balance": "100000000000000000000" + }, + "21b182f2da2b384493cf5f35f83d9d1ee14f2a21": { + "balance": "2000000000000000000000" + }, + "31ab088966ecc7229258f6098fce68cf39b38485": { + "balance": "1000000000000000000000" + }, + "4977a7939d0939689455ce2639d0ee5a4cd910ed": { + "balance": "1820000000000000000000" + }, + "07af938c1237a27c9030094dcf240750246e3d2c": { + "balance": "500000000000000000000" + }, + "4e2bfa4a466f82671b800eee426ad00c071ba170": { + "balance": "4000000000000000000000" + }, + "107379d4c467464f235bc18e55938aad3e688ad7": { + "balance": "50000000000000000000" + }, + "f7b29b82195c882dab7897c2ae95e77710f57875": { + "balance": "2199000000000000000000" + }, + "56586391040c57eec6f5affd8cd4abde10b50acc": { + "balance": "4000000000000000000000" + }, + "ac608e2bac9dd20728d2947effbbbf900a9ce94b": { + "balance": "6000600000000000000000" + }, + "48548b4ba62bcb2f0d34a88dc69a680e539cf046": { + "balance": "100084000000000000000" + }, + "1665ab1739d71119ee6132abbd926a279fe67948": { + "balance": "100000000000000000000" + }, + "af4493e8521ca89d95f5267c1ab63f9f45411e1b": { + "balance": "200000000000000000000" + }, + "bf6925c00751008440a6739a02bf2b6cdaab5e3a": { + "balance": "1000000000000000000000" + }, + "3fe40fbd919aad2818df01ee4df46c46842ac539": { + "balance": "6000000000000000000000" + }, + "455b9296921a74d1fc41617f43b8303e6f3ed76c": { + "balance": "4200000000000000000000" + }, + "7086b4bde3e35d4aeb24b825f1a215f99d85f745": { + "balance": "1999800000000000000000" + }, + "d4ee4919fb37f2bb970c3fff54aaf1f3dda6c03f": { + "balance": "40000000000000000000000" + }, + "a4489a50ead5d5445a7bee4d2d5536c2a76c41f8": { + "balance": "200000000000000000000" + }, + "505e4f7c275588c533a20ebd2ac13b409bbdea3c": { + "balance": "17600000000000000000" + }, + "3bb53598cc20e2055dc553b049404ac9b7dd1e83": { + "balance": "615020000000000000000" + }, + "52cd20403ba7eda6bc307a3d63b5911b817c1263": { + "balance": "20000000000000000000" + }, + "a211da03cc0e31ecce5309998718515528a090df": { + "balance": "200000000000000000000" + }, + "bcb422dc4dd2aae94abae95ea45dd1731bb6b0ba": { + "balance": "447500000000000000000" + }, + "cbde9734b8e6aa538c291d6d7facedb0f338f857": { + "balance": "2000000000000000000000" + }, + "171ca02a8b6d62bf4ca47e906914079861972cb2": { + "balance": "200000000000000000000" + }, + "d40d0055fd9a38488aff923fd03d35ec46d711b3": { + "balance": "4999711000000000000000" + }, + "3887192c7f705006b630091276b39ac680448d6b": { + "balance": "60000000000000000000" + }, + "3f3c8e61e5604cef0605d436dd22accd862217fc": { + "balance": "1337000000000000000000" + }, + "4258fd662fc4ce3295f0d4ed8f7bb1449600a0a9": { + "balance": "6719600000000000000000" + }, + "4571de672b9904bad8743692c21c4fdcea4c2e01": { + "balance": "4000000000000000000000" + }, + "5be045512a026e3f1cebfd5a7ec0cfc36f2dc16b": { + "balance": "120000000000000000000" + }, + "d6300b3215b11de762ecde4b70b7927d01291582": { + "balance": "2000000000000000000000" + }, + "f9e37447406c412197b2e2aebc001d6e30c98c60": { + "balance": "8346700000000000000000" + }, + "bd047ff1e69cc6b29ad26497a9a6f27a903fc4dd": { + "balance": "865000000000000000000" + }, + "23fa7eb51a48229598f97e762be0869652dffc66": { + "balance": "1000000000000000000000" + }, + "6679aeecd87a57a73f3356811d2cf49d0c4d96dc": { + "balance": "600000000000000000000" + }, + "23c55aeb5739876f0ac8d7ebea13be729685f000": { + "balance": "1337000000000000000000" + }, + "757b65876dbf29bf911d4f0692a2c9beb1139808": { + "balance": "4124263000000000000000" + }, + "e8fc36b0131ec120ac9e85afc10ce70b56d8b6ba": { + "balance": "200000000000000000000" + }, + "1a89899cbebdbb64bb26a195a63c08491fcd9eee": { + "balance": "2000000000000000000000" + }, + "6edf7f5283725c953ee64317f66188af1184b033": { + "balance": "8050000000000000000000" + }, + "297385e88634465685c231a314a0d5dcd146af01": { + "balance": "1550000000000000000000" + }, + "018f20a27b27ec441af723fd9099f2cbb79d6263": { + "balance": "2167000000000000000000" + }, + "a5a4227f6cf98825c0d5baff5315752ccc1a1391": { + "balance": "10000000000000000000000" + }, + "69517083e303d4fbb6c2114514215d69bc46a299": { + "balance": "100000000000000000000" + }, + "1dab172effa6fbee534c94b17e794edac54f55f8": { + "balance": "1970000000000000000000" + }, + "c6ee35934229693529dc41d9bb71a2496658b88e": { + "balance": "19700000000000000000000" + }, + "a8ee1df5d44b128469e913569ef6ac81eeda4fc8": { + "balance": "500000000000000000000" + }, + "35bd246865fab490ac087ac1f1d4f2c10d0cda03": { + "balance": "400000000000000000000" + }, + "4bf8bf1d35a231315764fc8001809a949294fc49": { + "balance": "66850000000000000000" + }, + "c70fa45576bf9c865f983893002c414926f61029": { + "balance": "400400000000000000000" + }, + "fdeaac2acf1d138e19f2fc3f9fb74592e3ed818a": { + "balance": "668500000000000000000" + }, + "bfbfbcb656c2992be8fcde8219fbc54aadd59f29": { + "balance": "9999924000000000000000" + }, + "1722c4cbe70a94b6559d425084caeed4d6e66e21": { + "balance": "4000000000000000000000" + }, + "00e681bc2d10db62de85848324492250348e90bf": { + "balance": "20000000000000000000000" + }, + "5c308bac4857d33baea074f3956d3621d9fa28e1": { + "balance": "4999711000000000000000" + }, + "68c08490c89bf0d6b6f320b1aca95c8312c00608": { + "balance": "4000000000000000000000" + }, + "ce1884ddbbb8e10e4dba6e44feeec2a7e5f92f05": { + "balance": "4000000000000000000000" + }, + "427417bd16b1b3d22dbb902d8f9657016f24a61c": { + "balance": "2000000000000000000000" + }, + "5ff93de6ee054cad459b2d5eb0f6870389dfcb74": { + "balance": "220000000000000000000" + }, + "71946b7117fc915ed107385f42d99ddac63249c2": { + "balance": "2000000000000000000000" + }, + "11ec00f849b6319cf51aa8dd8f66b35529c0be77": { + "balance": "2000000000000000000000" + }, + "610fd6ee4eebab10a8c55d0b4bd2e7d6ef817156": { + "balance": "20002000000000000000" + }, + "a422e4bf0bf74147cc895bed8f16d3cef3426154": { + "balance": "349281000000000000000" + }, + "745aecbaf9bb39b74a67ea1ce623de368481baa6": { + "balance": "10000000000000000000000" + }, + "9f496cb2069563144d0811677ba0e4713a0a4143": { + "balance": "1122000000000000000000" + }, + "c500b720734ed22938d78c5e48b2ba9367a575ba": { + "balance": "33400000000000000000000" + }, + "cd072e6e1833137995196d7bb1725fef8761f655": { + "balance": "6000000000000000000000" + }, + "94644ad116a41ce2ca7fbec609bdef738a2ac7c7": { + "balance": "5000000000000000000000" + }, + "e8d942d82f175ecb1c16a405b10143b3f46b963a": { + "balance": "568600000000000000000" + }, + "f73dd9c142b71bce11d06e30e7e7d032f2ec9c9e": { + "balance": "1970000000000000000000" + }, + "1327d759d56e0ab87af37ecf63fe01f310be100a": { + "balance": "659200000000000000000" + }, + "28fa2580f9ebe420f3e5eefdd371638e3b7af499": { + "balance": "6000000000000000000000" + }, + "024bdd2c7bfd500ee7404f7fb3e9fb31dd20fbd1": { + "balance": "180000000000000000000" + }, + "b4b14bf45455d0ab0803358b7524a72be1a2045b": { + "balance": "500000000000000000000" + }, + "b1e2dd95e39ae9775c55aeb13f12c2fa233053ba": { + "balance": "2000000000000000000000" + }, + "35b03ea4245736f57b85d2eb79628f036ddcd705": { + "balance": "4000000000000000000000" + }, + "eb2ef3d38fe652403cd4c9d85ed7f0682cd7c2de": { + "balance": "42784000000000000000000" + }, + "690594d306613cd3e2fd24bca9994ad98a3d73f8": { + "balance": "2000000000000000000000" + }, + "8397a1bc47acd647418159b99cea57e1e6532d6e": { + "balance": "9169160000000000000000" + }, + "b44815a0f28e569d0e921a4ade8fb2642526497a": { + "balance": "55500000000000000000" + }, + "e24109be2f513d87498e926a286499754f9ed49e": { + "balance": "886500000000000000000" + }, + "37ac29bda93f497bc4aeaab935452c431510341e": { + "balance": "985000000000000000000" + }, + "4a81abe4984c7c6bef63d69820e55743c61f201c": { + "balance": "16011846000000000000000" + }, + "66dcc5fb4ee7fee046e141819aa968799d644491": { + "balance": "1337000000000000000000" + }, + "43ff38743ed0cd43308c066509cc8e7e72c862aa": { + "balance": "1940000000000000000000" + }, + "b8f20005b61352ffa7699a1b52f01f5ab39167f1": { + "balance": "10000000000000000000000" + }, + "1cda411bd5163baeca1e558563601ce720e24ee1": { + "balance": "18200000000000000000" + }, + "86245f596691093ece3f3d3ca2263eace81941d9": { + "balance": "188000000000000000000" + }, + "f52a5882e8927d944b359b26366ba2b9cacfbae8": { + "balance": "25000080000000000000000" + }, + "118c18b2dce170e8f445753ba5d7513cb7636d2d": { + "balance": "8800000000000000000000" + }, + "7168b3bb8c167321d9bdb023a6e9fd11afc9afd9": { + "balance": "1790000000000000000000" + }, + "d9103bb6b67a55a7fece2d1af62d457c2178946d": { + "balance": "1000000000000000000000" + }, + "8b9fda7d981fe9d64287f85c94d83f9074849fcc": { + "balance": "14000000000000000000000" + }, + "91211712719f2b084d3b3875a85069f466363141": { + "balance": "1000000000000000000000" + }, + "4863849739265a63b0a2bf236a5913e6f959ce15": { + "balance": "1520000000000000000000" + }, + "c2d1778ef6ee5fe488c145f3586b6ebbe3fbb445": { + "balance": "1146000000000000000000" + }, + "2b77a4d88c0d56a3dbe3bae04a05f4fcd1b757e1": { + "balance": "300000000000000000000" + }, + "fe9c0fffefb803081256c0cf4d6659e6d33eb4fb": { + "balance": "1528000000000000000000" + }, + "893017ff1adad499aa065401b4236ce6e92b625a": { + "balance": "1999944000000000000000" + }, + "073c67e09b5c713c5221c8a0c7f3f74466c347b0": { + "balance": "19400000000000000000000" + }, + "93e303411afaf6c107a44101c9ac5b36e9d6538b": { + "balance": "66000000000000000000000" + }, + "0ec50aa823f465b9464b0bc0c4a57724a555f5d6": { + "balance": "59100000000000000000000" + }, + "a3e3a6ea509573e21bd0239ece0523a7b7d89b2f": { + "balance": "1970000000000000000000" + }, + "c069ef0eb34299abd2e32dabc47944b272334824": { + "balance": "120000000000000000000" + }, + "28a3da09a8194819ae199f2e6d9d1304817e28a5": { + "balance": "2000000000000000000000" + }, + "e9495ba5842728c0ed97be37d0e422b98d69202c": { + "balance": "2000000000000000000000" + }, + "bba976f1a1215f7512871892d45f7048acd356c8": { + "balance": "2000000000000000000000" + }, + "887cac41cd706f3345f2d34ac34e01752a6e5909": { + "balance": "595366000000000000000" + }, + "e0e0b2e29dde73af75987ee4446c829a189c95bc": { + "balance": "149000000000000000000" + }, + "4a5fae3b0372c230c125d6d470140337ab915656": { + "balance": "1600000000000000000000" + }, + "425177eb74ad0a9d9a5752228147ee6d6356a6e6": { + "balance": "13370000000000000000" + }, + "5db7bba1f9573f24115d8c8c62e9ce8895068e9f": { + "balance": "49984000000000000000" + }, + "fa6a37f018e97967937fc5e8617ba1d786dd5f77": { + "balance": "19999800000000000000000" + }, + "45e3a93e72144ada860cbc56ff85145ada38c6da": { + "balance": "1610000000000000000000" + }, + "67da922effa472a6b124e84ea8f86b24e0f515aa": { + "balance": "20000000000000000000" + }, + "aa9bd4589535db27fa2bc903ca17d679dd654806": { + "balance": "2000000000000000000000" + }, + "16a9e9b73ae98b864d1728798b8766dbc6ea8d12": { + "balance": "957480000000000000000" + }, + "d6580ab5ed4c7dfa506fa6fe64ad5ce129707732": { + "balance": "4000000000000000000000" + }, + "984a7985e3cc7eb5c93691f6f8cc7b8f245d01b2": { + "balance": "6000000000000000000000" + }, + "7746b6c6699c8f34ca2768a820f1ffa4c207fe05": { + "balance": "4000086000000000000000" + }, + "2fa491fb5920a6574ebd289f39c1b2430d2d9a6a": { + "balance": "2000000000000000000000" + }, + "fae76719d97eac41870428e940279d97dd57b2f6": { + "balance": "98500000000000000000000" + }, + "41b2dbd79dda9b864f6a7030275419c39d3efd3b": { + "balance": "3200000000000000000000" + }, + "dd8254121a6e942fc90828f2431f511dad7f32e6": { + "balance": "3018000000000000000000" + }, + "37fac1e6bc122e936dfb84de0c4bef6e0d60c2d7": { + "balance": "2000000000000000000000" + }, + "3a10888b7e149cae272c01302c327d0af01a0b24": { + "balance": "17000000000000000000" + }, + "401354a297952fa972ad383ca07a0a2811d74a71": { + "balance": "14000000000000000000" + }, + "51865db148881951f51251710e82b9be0d7eadb2": { + "balance": "2000000000000000000000" + }, + "bbbd6ecbb5752891b4ceb3cce73a8f477059376f": { + "balance": "36000000000000000000" + }, + "3f236108eec72289bac3a65cd283f95e041d144c": { + "balance": "999925000000000000000" + }, + "dc83b6fd0d512131204707eaf72ea0c8c9bef976": { + "balance": "2000000000000000000000" + }, + "036eeff5ba90a6879a14dff4c5043b18ca0460c9": { + "balance": "100000000000000000000" + }, + "fac5ca94758078fbfccd19db3558da7ee8a0a768": { + "balance": "1017500000000000000000" + }, + "d0d62c47ea60fb90a3639209bbfdd4d933991cc6": { + "balance": "194000000000000000000" + }, + "891cb8238c88e93a1bcf61db49bd82b47a7f4f84": { + "balance": "2680000000000000000000" + }, + "df53003346d65c5e7a646bc034f2b7d32fcbe56a": { + "balance": "2000000000000000000000" + }, + "6e89c51ea6de13e06cdc748b67c4410fe9bcab03": { + "balance": "4000000000000000000000" + }, + "a61cdbadf04b1e54c883de6005fcdf16beb8eb2f": { + "balance": "2000000000000000000000" + }, + "e3951de5aefaf0458768d774c254f7157735e505": { + "balance": "1600930000000000000000" + }, + "f2732cf2c13b8bb8e7492a988f5f89e38273ddc8": { + "balance": "600000000000000000000" + }, + "4752218e54de423f86c0501933917aea08c8fed5": { + "balance": "20000000000000000000000" + }, + "152f4e860ef3ee806a502777a1b8dbc91a907668": { + "balance": "600000000000000000000" + }, + "15b96f30c23b8664e7490651066b00c4391fbf84": { + "balance": "410650000000000000000" + }, + "8693e9b8be94425eef7969bc69f9d42f7cad671e": { + "balance": "1000090000000000000000" + }, + "f41557dfdfb1a1bdcefefe2eba1e21fe0a4a9942": { + "balance": "1970000000000000000000" + }, + "38458e0685573cb4d28f53098829904570179266": { + "balance": "40000000000000000000" + }, + "53e4d9696dcb3f4d7b3f70dcaa4eecb71782ff5c": { + "balance": "200000000000000000000" + }, + "2dca0e449ab646dbdfd393a96662960bcab5ae1e": { + "balance": "40000000000000000000000" + }, + "87d7ac0653ccc67aa9c3469eef4352193f7dbb86": { + "balance": "200000000000000000000000" + }, + "ae9f5c3fbbe0c9bcbf1af8ff74ea280b3a5d8b08": { + "balance": "1730000000000000000000" + }, + "7751f363a0a7fd0533190809ddaf9340d8d11291": { + "balance": "20000000000000000000" + }, + "708a2af425ceb01e87ffc1be54c0f532b20eacd6": { + "balance": "134159000000000000000" + }, + "ac122a03cd058c122e5fe17b872f4877f9df9572": { + "balance": "1969606000000000000000" + }, + "5da4ca88935c27f55c311048840e589e04a8a049": { + "balance": "80000000000000000000" + }, + "e67c2c1665c88338688187629f49e99b60b2d3ba": { + "balance": "200000000000000000000" + }, + "dec82373ade8ebcf2acb6f8bc2414dd7abb70d77": { + "balance": "200000000000000000000" + }, + "47c247f53b9fbeb17bba0703a00c009fdb0f6eae": { + "balance": "20000000000000000000000" + }, + "9a522e52c195bfb7cf5ffaaedb91a3ba7468161d": { + "balance": "1000000000000000000000" + }, + "3159e90c48a915904adfe292b22fa5fd5e72796b": { + "balance": "1008800000000000000000" + }, + "defddfd59b8d2c154eecf5c7c167bf0ba2905d3e": { + "balance": "93588000000000000000" + }, + "ad1d68a038fd2586067ef6d135d9628e79c2c924": { + "balance": "4686168000000000000000" + }, + "038e45eadd3d88b87fe4dab066680522f0dfc8f9": { + "balance": "10000000000000000000000" + }, + "2561ec0f379218fe5ed4e028a3f744aa41754c72": { + "balance": "13370000000000000000" + }, + "b95396daaa490df2569324fcc6623be052f132ca": { + "balance": "2000000000000000000000" + }, + "2376ada90333b1d181084c97e645e810aa5b76f1": { + "balance": "750000000000000000000" + }, + "07800d2f8068e448c79a4f69b1f15ef682aae5f6": { + "balance": "19400000000000000000000" + }, + "adeb204aa0c38e179e81a94ed8b3e7d53047c26b": { + "balance": "608000000000000000000" + }, + "0dc100b107011c7fc0a1339612a16ccec3285208": { + "balance": "2000000000000000000000" + }, + "f0b1340b996f6f0bf0d9561c849caf7f4430befa": { + "balance": "100000000000000000000" + }, + "e1443dbd95cc41237f613a48456988a04f683282": { + "balance": "4000086000000000000000" + }, + "d3c6f1e0f50ec3d2a67e6bcd193ec7ae38f1657f": { + "balance": "6618150000000000000000" + }, + "b68899e7610d4c93a23535bcc448945ba1666f1c": { + "balance": "200000000000000000000" + }, + "a7253763cf4a75df92ca1e766dc4ee8a2745147b": { + "balance": "10740000000000000000000" + }, + "75d67ce14e8d29e8c2ffe381917b930b1aff1a87": { + "balance": "3000000000000000000000" + }, + "493d48bda015a9bfcf1603936eab68024ce551e0": { + "balance": "22528000000000000000" + }, + "7ddd57165c87a2707f025dcfc2508c09834759bc": { + "balance": "1400000000000000000000" + }, + "cff7f89a4d4219a38295251331568210ffc1c134": { + "balance": "1760000000000000000000" + }, + "168d30e53fa681092b52e9bae15a0dcb41a8c9bb": { + "balance": "100000000000000000000" + }, + "99b743d1d9eff90d9a1934b4db21d519d89b4a38": { + "balance": "100000000000000000000" + }, + "a3d0b03cffbb269f796ac29d80bfb07dc7c6ad06": { + "balance": "2000000000000000000000" + }, + "816d9772cf11399116cc1e72c26c6774c9edd739": { + "balance": "200000000000000000000" + }, + "a880e2a8bf88a1a82648b4013c49c4594c433cc8": { + "balance": "4728000000000000000000" + }, + "2a44a7218fe44d65a1b4b7a7d9b1c2c52c8c3e34": { + "balance": "62221355000000000000000" + }, + "cb86edbc8bbb1f9131022be649565ebdb09e32a1": { + "balance": "2000000000000000000000" + }, + "3915eab5ab2e5977d075dec47d96b68b4b5cf515": { + "balance": "61520000000000000000000" + }, + "8165cab0eafb5a328fc41ac64dae715b2eef2c65": { + "balance": "1000000000000000000000" + }, + "416c86b72083d1f8907d84efd2d2d783dffa3efb": { + "balance": "1999944000000000000000" + }, + "c524086d46c8112b128b2faf6f7c7d8160a8386c": { + "balance": "400000000000000000000" + }, + "902d74a157f7d2b9a3378b1f56703730e03a1719": { + "balance": "4000000000000000000000" + }, + "74ef2869cbe608856045d8c2041118579f2236ea": { + "balance": "59724000000000000000" + }, + "af992dd669c0883e5515d3f3112a13f617a4c367": { + "balance": "2000000000000000000000" + }, + "4c6a248fc97d705def495ca20759169ef0d36471": { + "balance": "760000000000000000000" + }, + "974d2f17895f2902049deaaecf09c3046507402d": { + "balance": "14707000000000000000" + }, + "0239b4f21f8e05cd01512b2be7a0e18a6d974607": { + "balance": "1000000000000000000000" + }, + "b97a6733cd5fe99864b3b33460d1672434d5cafd": { + "balance": "1999579000000000000000" + }, + "f558a2b2dd26dd9593aae04531fd3c3cc3854b67": { + "balance": "198000000000000000000" + }, + "b577b6befa054e9c040461855094b002d7f57bd7": { + "balance": "114000000000000000000000" + }, + "73bfe7710f31cab949b7a2604fbf5239cee79015": { + "balance": "2000000000000000000000" + }, + "5717f2d8f18ffcc0e5fe247d3a4219037c3a649c": { + "balance": "3998000000000000000000" + }, + "20707e425d2a11d2c89f391b2b809f556c592421": { + "balance": "2000000000000000000000" + }, + "9a6708ddb8903c289f83fe889c1edcd61f854423": { + "balance": "1000000000000000000000" + }, + "fa27cc49d00b6c987336a875ae39da58fb041b2e": { + "balance": "10000000000000000000000" + }, + "d688e785c98f00f84b3aa1533355c7a258e87948": { + "balance": "500000000000000000000" + }, + "927cb7dc187036b5427bc7e200c5ec450c1d27d4": { + "balance": "216000000000000000000" + }, + "b2bfaa58b5196c5cb7f89de15f479d1838de713d": { + "balance": "21000000000000000000" + }, + "e180de9e86f57bafacd7904f9826b6b4b26337a3": { + "balance": "830400000000000000000" + }, + "a1204dad5f560728a35c0d8fc79481057bf77386": { + "balance": "1000000000000000000000" + }, + "6b0da25af267d7836c226bcae8d872d2ce52c941": { + "balance": "6000000000000000000000" + }, + "0517448dada761cc5ba4033ee881c83037036400": { + "balance": "1998000000000000000000" + }, + "7ed0a5a847bef9a9da7cba1d6411f5c316312619": { + "balance": "39842000000000000000" + }, + "5b5d517029321562111b43086d0b043591109a70": { + "balance": "2600000000000000000000" + }, + "56fc1a7bad4047237ce116146296238e078f93ad": { + "balance": "178000000000000000000" + }, + "6c5422fb4b14e6d98b6091fdec71f1f08640419d": { + "balance": "400000000000000000000" + }, + "108fe8ee2a13da487b22c6ab6d582ea71064d98c": { + "balance": "399800000000000000000" + }, + "0ad3e44d3c001fa290b393617030544108ac6eb9": { + "balance": "1969019000000000000000" + }, + "25aee68d09afb71d8817f3f184ec562f7897b734": { + "balance": "2000000000000000000000" + }, + "c2340a4ca94c9678b7494c3c852528ede5ee529f": { + "balance": "48669000000000000000" + }, + "44901e0d0e08ac3d5e95b8ec9d5e0ff5f12e0393": { + "balance": "417500000000000000000" + }, + "8775a610c502b9f1e6ad4cdadb8ce29bff75f6e4": { + "balance": "600000000000000000000" + }, + "682897bc4f8e89029120fcffb787c01a93e64184": { + "balance": "10000000000000000000000" + }, + "f7acff934b84da0969dc37a8fcf643b7d7fbed41": { + "balance": "1999944000000000000000" + }, + "f05fcd4c0d73aa167e5553c8c0d6d4f2faa39757": { + "balance": "13334000000000000000000" + }, + "c981d312d287d558871edd973abb76b979e5c35e": { + "balance": "1970000000000000000000" + }, + "9da61ccd62bf860656e0325d7157e2f160d93bb5": { + "balance": "4999980000000000000000" + }, + "d284a50382f83a616d39b8a9c0f396e0ebbfa95d": { + "balance": "1000070000000000000000" + }, + "d6cf5c1bcf9da662bcea2255905099f9d6e84dcc": { + "balance": "8349332000000000000000" + }, + "c71b2a3d7135d2a85fb5a571dcbe695e13fc43cd": { + "balance": "1000000000000000000000" + }, + "b22dadd7e1e05232a93237baed98e0df92b1869e": { + "balance": "2000000000000000000000" + }, + "b09fe6d4349b99bc37938054022d54fca366f7af": { + "balance": "200000000000000000000000" + }, + "427e4751c3babe78cff8830886febc10f9908d74": { + "balance": "1970000000000000000000" + }, + "60b358cb3dbefa37f47df2d7365840da8e3bc98c": { + "balance": "20000000000000000000" + }, + "dcd5bca2005395b675fde5035659b26bfefc49ee": { + "balance": "197000000000000000000" + }, + "81186931184137d1192ac88cd3e1e5d0fdb86a74": { + "balance": "2900000000000000000000" + }, + "de212293f8f1d231fa10e609470d512cb8ffc512": { + "balance": "2000000000000000000000" + }, + "1937c5c515057553ccbd46d5866455ce66290284": { + "balance": "1000000000000000000000000" + }, + "592777261e3bd852c48eca95b3a44c5b7f2d422c": { + "balance": "20000000000000000000000" + }, + "bbf84292d954acd9e4072fb860b1504106e077ae": { + "balance": "1500000000000000000000" + }, + "3b4100e30a73b0c734b18ffa8426d19b19312f1a": { + "balance": "55300000000000000000000" + }, + "a03a3dc7c533d1744295be955d61af3f52b51af5": { + "balance": "40000000000000000000" + }, + "4aa148c2c33401e66a2b586e6577c4b292d3f240": { + "balance": "216200000000000000000" + }, + "ff850e3be1eb6a4d726c08fa73aad358f39706da": { + "balance": "1940000000000000000000" + }, + "743651b55ef8429df50cf81938c2508de5c8870f": { + "balance": "2000000000000000000000" + }, + "3700e3027424d939dbde5d42fb78f6c4dbec1a8f": { + "balance": "40000000000000000000" + }, + "c1cbd2e2332a524cf219b10d871ccc20af1fb0fa": { + "balance": "1000000000000000000000" + }, + "e25b9f76b8ad023f057eb11ad94257a0862e4e8c": { + "balance": "2000000000000000000000" + }, + "719e891fbcc0a33e19c12dc0f02039ca05b801df": { + "balance": "6185800000000000000000" + }, + "39636b25811b176abfcfeeca64bc87452f1fdff4": { + "balance": "400000000000000000000" + }, + "631030a5b27b07288a45696f189e1114f12a81c0": { + "balance": "499970000000000000000" + }, + "bcc84597b91e73d5c5b4d69c80ecf146860f779a": { + "balance": "4380000000000000000000" + }, + "095e0174829f34c3781be1a5e38d1541ea439b7f": { + "balance": "6000000000000000000000" + }, + "2e7e05e29edda7e4ae25c5173543efd71f6d3d80": { + "balance": "6000000000000000000000" + }, + "dbb6ac484027041642bbfd8d80f9d0c1cf33c1eb": { + "balance": "2000000000000000000000" + }, + "153c08aa8b96a611ef63c0253e2a4334829e579d": { + "balance": "394000000000000000000" + }, + "10f4bff0caa5027c0a6a2dcfc952824de2940909": { + "balance": "2000000000000000000000" + }, + "2ef869f0350b57d53478d701e3fee529bc911c75": { + "balance": "50000000000000000000" + }, + "70ab34bc17b66f9c3b63f151274f2a727c539263": { + "balance": "2000000000000000000000" + }, + "3201259caf734ad7581c561051ba0bca7fd6946b": { + "balance": "180000000000000000000000" + }, + "84e9cf8166c36abfa49053b7a1ad4036202681ef": { + "balance": "2000000000000000000000" + }, + "4ebc5629f9a6a66b2cf3363ac4895c0348e8bf87": { + "balance": "1000090000000000000000" + }, + "e50b464ac9de35a5618b7cbf254674182b81b97e": { + "balance": "4100000000000000000000" + }, + "2abdf1a637ef6c42a7e2fe217773d677e804ebdd": { + "balance": "5000000000000000000000" + }, + "7a0a78a9cc393f91c3d9e39a6b8c069f075e6bf5": { + "balance": "1337000000000000000000" + }, + "2d9c5fecd2b44fbb6a1ec732ea059f4f1f9d2b5c": { + "balance": "1010694000000000000000" + }, + "7b712c7af11676006a66d2fc5c1ab4c479ce6037": { + "balance": "8000000000000000000000" + }, + "3466f67e39636c01f43b3a21a0e8529325c08624": { + "balance": "842864000000000000000" + }, + "fdd502a74e813bcfa355ceda3c176f6a6871af7f": { + "balance": "400000000000000000000" + }, + "26475419c06d5f147aa597248eb46cf7befa64a5": { + "balance": "1640000000000000000000" + }, + "9243d7762d77287b12638688b9854e88a769b271": { + "balance": "1000000000000000000000" + }, + "723d8baa2551d2addc43c21b45e8af4ca2bfb2c2": { + "balance": "1760000000000000000000" + }, + "f2fbb6d887f8b8cc3a869aba847f3d1f643c53d6": { + "balance": "3999000000000000000000" + }, + "2cdb3944650616e47cb182e060322fa1487978ce": { + "balance": "1820000000000000000000" + }, + "f0d21663d8b0176e05fde1b90ef31f8530fda95f": { + "balance": "1999944000000000000000" + }, + "77cc02f623a9cf98530997ea67d95c3b491859ae": { + "balance": "1354900000000000000000" + }, + "d1b5a454ac3405bb4179208c6c84de006bcb9be9": { + "balance": "500000000000000000000" + }, + "b9920fd0e2c735c256463caa240fb7ac86a93dfa": { + "balance": "1760000000000000000000" + }, + "ed1f1e115a0d60ce02fb25df014d289e3a0cbe7d": { + "balance": "500000000000000000000" + }, + "23e2c6a8be8e0acfa5c4df5e36058bb7cbac5a81": { + "balance": "2000000000000000000000" + }, + "f0be0faf4d7923fc444622d1980cf2d990aab307": { + "balance": "2000000000000000000000" + }, + "0829d0f7bb7c446cfbb0deadb2394d9db7249a87": { + "balance": "40110000000000000000" + }, + "2ecac504b233866eb5a4a99e7bd2901359e43b3d": { + "balance": "20000000000000000000000" + }, + "06d6cb308481c336a6e1a225a912f6e6355940a1": { + "balance": "1760000000000000000000" + }, + "d4879fd12b1f3a27f7e109761b23ca343c48e3d8": { + "balance": "666000000000000000000" + }, + "857f100b1a5930225efc7e9020d78327b41c02cb": { + "balance": "2000000000000000000000" + }, + "3aa42c21b9b31c3e27ccd17e099af679cdf56907": { + "balance": "8000000000000000000000" + }, + "764d5212263aff4a2a14f031f04ec749dc883e45": { + "balance": "1850000000000000000000" + }, + "d03a2da41e868ed3fef5745b96f5eca462ff6fda": { + "balance": "3000000000000000000000" + }, + "4f26690c992b7a312ab12e1385d94acd58288e7b": { + "balance": "14000000000000000000000" + }, + "7b122162c913e7146cad0b7ed37affc92a0bf27f": { + "balance": "1506799000000000000000" + }, + "c87352dba582ee2066b9c002a962e003134f78b1": { + "balance": "500000000000000000000" + }, + "9f4ac9c9e7e24cb2444a0454fa5b9ad9d92d3853": { + "balance": "835000000000000000000" + }, + "ccf62a663f1353ba2ef8e6521dc1ecb673ec8ef7": { + "balance": "152000000000000000000" + }, + "557f5e65e0da33998219ad4e99570545b2a9d511": { + "balance": "11024000000000000000000" + }, + "a5f0077b351f6c505cd515dfa6d2fa7f5c4cd287": { + "balance": "40000000000000000000000" + }, + "79c6002f8452ca157f1317e80a2faf24475559b7": { + "balance": "20000000000000000000" + }, + "3aa07a34a1afc8967d3d1383b96b62cf96d5fa90": { + "balance": "20000000000000000000000" + }, + "7f389c12f3c6164f6446566c77669503c2792527": { + "balance": "98500000000000000000" + }, + "ac4cc256ae74d624ace80db078b2207f57198f6b": { + "balance": "2001000000000000000000" + }, + "823ba7647238d113bce9964a43d0a098118bfe4d": { + "balance": "200000000000000000000" + }, + "f5a7676ad148ae9c1ef8b6f5e5a0c2c473be850b": { + "balance": "200000000000000000000" + }, + "7d34803569e00bd6b59fff081dfa5c0ab4197a62": { + "balance": "1712700000000000000000" + }, + "061ea4877cd08944eb64c2966e9db8dedcfec06b": { + "balance": "1000000000000000000000" + }, + "df37c22e603aedb60a627253c47d8ba866f6d972": { + "balance": "24000000000000000000000" + }, + "529aa002c6962a3a8545027fd8b05f22b5bf9564": { + "balance": "1670000000000000000000" + }, + "eb89a882670909cf377e9e78286ee97ba78d46c2": { + "balance": "802200000000000000000" + }, + "9ac85397792a69d78f286b86432a07aeceb60e64": { + "balance": "14300000000000000000" + }, + "9610592202c282ab9bd8a884518b3e0bd4758137": { + "balance": "268000000000000000000" + }, + "73932709a97f02c98e51b091312865122385ae8e": { + "balance": "1430000000000000000000" + }, + "5ef8c96186b37984cbfe04c598406e3b0ac3171f": { + "balance": "9400000000000000000000" + }, + "b6f78da4f4d041b3bc14bc5ba519a5ba0c32f128": { + "balance": "172326253000000000000000" + }, + "6f0edd23bcd85f6015f9289c28841fe04c83efeb": { + "balance": "19100000000000000000" + }, + "a8a43c009100616cb4ae4e033f1fc5d7e0b6f152": { + "balance": "3939015000000000000000" + }, + "7081fa6baad6cfb7f51b2cca16fb8970991a64ba": { + "balance": "233953000000000000000" + }, + "9de7386dde401ce4c67b71b6553f8aa34ea5a17d": { + "balance": "60000000000000000000" + }, + "54ec7300b81ac84333ed1b033cd5d7a33972e234": { + "balance": "200000000000000000000" + }, + "67a80e0190721f94390d6802729dd12c31a895ad": { + "balance": "1999964000000000000000" + }, + "3a4297da3c555e46c073669d0478fce75f2f790e": { + "balance": "1969606000000000000000" + }, + "c2e0584a71348cc314b73b2029b6230b92dbb116": { + "balance": "2000000000000000000000" + }, + "0a2ade95b2e8c66d8ae6f0ba64ca57d783be6d44": { + "balance": "4000000000000000000000" + }, + "544b5b351d1bc82e9297439948cf4861dac9ae11": { + "balance": "22000000000000000000000" + }, + "3ae62bd271a760637fad79c31c94ff62b4cd12f7": { + "balance": "2000000000000000000000" + }, + "0d8023929d917234ae40512b1aabb5e8a4512771": { + "balance": "148000000000000000000" + }, + "2858acacaf21ea81cab7598fdbd86b452e9e8e15": { + "balance": "666000000000000000000" + }, + "c033b1325a0af45472c25527853b1f1c21fa35de": { + "balance": "2000000000000000000000" + }, + "bbf85aaaa683738f073baef44ac9dc34c4c779ea": { + "balance": "2000000000000000000000" + }, + "6ae57f27917c562a132a4d1bf7ec0ac785832926": { + "balance": "6000000000000000000000" + }, + "88e6f9b247f988f6c0fc14c56f1de53ec69d43cc": { + "balance": "100000000000000000000" + }, + "b72c2a011c0df50fbb6e28b20ae1aad217886790": { + "balance": "4000000000000000000000" + }, + "161caf5a972ace8379a6d0a04ae6e163fe21df2b": { + "balance": "100000000000000000000000" + }, + "2a63590efe9986c3fee09b0a0a338b15bed91f21": { + "balance": "6458400000000000000000" + }, + "50e1c8ec98415bef442618708799437b86e6c205": { + "balance": "6000000000000000000000" + }, + "33f4a6471eb1bca6a9f85b3b4872e10755c82be1": { + "balance": "2000000000000000000000" + }, + "9c49deff47085fc09704caa2dca8c287a9a137da": { + "balance": "8000000000000000000000" + }, + "e1173a247d29d8238df0922f4df25a05f2af77c3": { + "balance": "40007051000000000000000" + }, + "51891b2ccdd2f5a44b2a8bc49a5d9bca6477251c": { + "balance": "310000000000000000000" + }, + "ecaf3350b7ce144d068b186010852c84dd0ce0f0": { + "balance": "2000000000000000000000" + }, + "72393d37b451effb9e1ff3b8552712e2a970d8c2": { + "balance": "985000000000000000000" + }, + "1bbc60bcc80e5cdc35c5416a1f0a40a83dae867b": { + "balance": "2000000000000000000000" + }, + "b8ab39805bd821184f6cbd3d2473347b12bf175c": { + "balance": "118200000000000000000" + }, + "c55a6b4761fd11e8c85f15174d74767cd8bd9a68": { + "balance": "133700000000000000000" + }, + "99d1b585965f406a42a49a1ca70f769e765a3f98": { + "balance": "16700000000000000000000" + }, + "9ab988b505cfee1dbe9cd18e9b5473b9a2d4f536": { + "balance": "320000000000000000000" + }, + "7fef8c38779fb307ec6f044bebe47f3cfae796f1": { + "balance": "168561000000000000000" + }, + "322d6f9a140d213f4c80cd051afe25c620bf4c7d": { + "balance": "20000000000000000000" + }, + "3bd9a06d1bd36c4edd27fc0d1f5b088ddae3c72a": { + "balance": "499970000000000000000" + }, + "5dcdb6b87a503c6d8a3c65c2cf9a9aa883479a1e": { + "balance": "9200000000000000000000" + }, + "6e84c2fd18d8095714a96817189ca21cca62bab1": { + "balance": "340935000000000000000" + }, + "a5bad86509fbe0e0e3c0e93f6d381f1af6e9d481": { + "balance": "6000000000000000000000" + }, + "3954bdfe0bf587c695a305d9244c3d5bdddac9bb": { + "balance": "19187461000000000000000" + }, + "63f0e5a752f79f67124eed633ad3fd2705a397d4": { + "balance": "3940000000000000000000" + }, + "33fd718f0b91b5cec88a5dc15eecf0ecefa4ef3d": { + "balance": "432500000000000000000" + }, + "68027d19558ed7339a08aee8de3559be063ec2ea": { + "balance": "2000000000000000000000" + }, + "96f0462ae6f8b96088f7e9c68c74b9d8ad34b347": { + "balance": "1790000000000000000000" + }, + "f1f391ca92808817b755a8b8f4e2ca08d1fd1108": { + "balance": "6000000000000000000000" + }, + "7fcf5ba6666f966c5448c17bf1cb0bbcd8019b06": { + "balance": "99999000000000000000" + }, + "e9b9a2747510e310241d2ece98f56b3301d757e0": { + "balance": "2000000000000000000000" + }, + "2100381d60a5b54adc09d19683a8f6d5bb4bfbcb": { + "balance": "10000000000000000000000" + }, + "7495ae78c0d90261e2140ef2063104731a60d1ed": { + "balance": "34250000000000000000" + }, + "dc911cf7dc5dd0813656670528e9338e67034786": { + "balance": "2000000000000000000000" + }, + "262aed4bc0f4a4b2c6fb35793e835a49189cdfec": { + "balance": "10000000000000000000000" + }, + "9ee93f339e6726ec65eea44f8a4bfe10da3d3282": { + "balance": "2000000000000000000000" + }, + "a3a57b0716132804d60aac281197ff2b3d237b01": { + "balance": "1400000000000000000000" + }, + "c799e34e88ff88be7de28e15e4f2a63d0b33c4cb": { + "balance": "200000000000000000000" + }, + "c7506c1019121ff08a2c8c1591a65eb4bdfb4a3f": { + "balance": "600000000000000000000" + }, + "795ebc2626fc39b0c86294e0e837dcf523553090": { + "balance": "1000000000000000000000" + }, + "441aca82631324acbfa2468bda325bbd78477bbf": { + "balance": "6000000000000000000000" + }, + "9f271d285500d73846b18f733e25dd8b4f5d4a8b": { + "balance": "722000000000000000000" + }, + "d77892e2273b235d7689e430e7aeed9cbce8a1f3": { + "balance": "2000000000000000000000" + }, + "4f8972838f70c903c9b6c6c46162e99d6216d451": { + "balance": "4610000000000000000000" + }, + "4c85ed362f24f6b9f04cdfccd022ae535147cbb9": { + "balance": "1500000000000000000000" + }, + "3807eff43aa97c76910a19752dd715ee0182d94e": { + "balance": "250190000000000000000" + }, + "3a9e5441d44b243be55b75027a1ceb9eacf50df2": { + "balance": "1000000000000000000000" + }, + "3deae43327913f62808faa1b6276a2bd6368ead9": { + "balance": "2000000000000000000000" + }, + "c270456885342b640b4cfc1b520e1a544ee0d571": { + "balance": "1820000000000000000000" + }, + "77798f201257b9c35204957057b54674aefa51df": { + "balance": "149000000000000000000" + }, + "225f9eb3fb6ff3e9e3c8447e14a66e8d4f3779f6": { + "balance": "2000000000000000000000" + }, + "78df2681d6d602e22142d54116dea15d454957aa": { + "balance": "298000000000000000000" + }, + "283396ce3cac398bcbe7227f323e78ff96d08767": { + "balance": "400000000000000000000" + }, + "747ff7943b71dc4dcdb1668078f83dd7cc4520c2": { + "balance": "60000000000000000000" + }, + "a4ed11b072d89fb136759fc69b428c48aa5d4ced": { + "balance": "262800000000000000000" + }, + "cc043c4388d345f884c6855e71142a9f41fd6935": { + "balance": "20000000000000000000" + }, + "ab14d221e33d544629198cd096ed63dfa28d9f47": { + "balance": "6000000000000000000000" + }, + "251e6838f7cec5b383c1d90146341274daf8e502": { + "balance": "147510000000000000000" + }, + "36a0e61e1be47fa87e30d32888ee0330901ca991": { + "balance": "20000000000000000000" + }, + "bcfc98e5c82b6adb180a3fcb120b9a7690c86a3f": { + "balance": "1970000000000000000000" + }, + "18a6d2fc52be73084023c91802f05bc24a4be09f": { + "balance": "2000000000000000000000" + }, + "80591a42179f34e64d9df75dcd463b28686f5574": { + "balance": "20000000000000000000000" + }, + "881230047c211d2d5b00d8de4c5139de5e3227c7": { + "balance": "10000000000000000000000" + }, + "9eb1ff71798f28d6e989fa1ea0588e27ba86cb7d": { + "balance": "140800000000000000000" + }, + "a01fd1906a908506dedae1e208128872b56ee792": { + "balance": "3000000000000000000000" + }, + "1b05ea6a6ac8af7cb6a8b911a8cce8fe1a2acfc8": { + "balance": "2000000000000000000000" + }, + "6add932193cd38494aa3f03aeccc4b7ab7fabca2": { + "balance": "89600000000000000000" + }, + "2aaa35274d742546670b7426264521032af4f4c3": { + "balance": "10000000000000000000000" + }, + "67b8a6e90fdf0a1cac441793301e8750a9fa7957": { + "balance": "895000000000000000000" + }, + "5b5be0d8c67276baabd8edb30d48ea75640b8b29": { + "balance": "824480000000000000000" + }, + "28d7e5866f1d85fd1ceb32bfbe1dfc36db434566": { + "balance": "7199000000000000000000" + }, + "98e3e90b28fccaee828779b8d40a5568c4116e21": { + "balance": "40000000000000000000" + }, + "2dd578f7407dfbd548d05e95ccc39c485429626a": { + "balance": "4200000000000000000000" + }, + "8ca6989746b06e32e2487461b1ce996a273acfd7": { + "balance": "20000000000000000000" + }, + "a6f93307f8bce03195fece872043e8a03f7bd11a": { + "balance": "2886000000000000000000" + }, + "efbd52f97da5fd3a673a46cbf330447b7e8aad5c": { + "balance": "100033000000000000000" + }, + "52bdd9af5978850bc24110718b3723759b437e59": { + "balance": "1730000000000000000000" + }, + "6e073b66d1b8c66744d88096a8dd99ec7e0228da": { + "balance": "4000000000000000000000" + }, + "a29d661a6376f66d0b74e2fe9d8f26c0247ec84c": { + "balance": "4117300000000000000000" + }, + "7d34ff59ae840a7413c6ba4c5bb2ba2c75eab018": { + "balance": "3000000000000000000000" + }, + "2eca6a3c5d9f449d0956bd43fa7b4d7be8435958": { + "balance": "2000020000000000000000" + }, + "f59f9f02bbc98efe097eabb78210979021898bfd": { + "balance": "9999800000000000000000" + }, + "90e300ac71451e401f887f6e7728851647a80e07": { + "balance": "400000000000000000000" + }, + "05ae7fd4bbcc80ca11a90a1ec7a301f7cccc83db": { + "balance": "910000000000000000000" + }, + "e54102534de8f23effb093b31242ad3b233facfd": { + "balance": "4000000000000000000000" + }, + "c127aab59065a28644a56ba3f15e2eac13da2995": { + "balance": "600000000000000000000" + }, + "ed60c4ab6e540206317e35947a63a9ca6b03e2cb": { + "balance": "57275000000000000000" + }, + "d855b03ccb029a7747b1f07303e0a664793539c8": { + "balance": "2000000000000000000000" + }, + "1178501ff94add1c5881fe886136f6dfdbe61a94": { + "balance": "158000000000000000000" + }, + "f447108b98df64b57e871033885c1ad71db1a3f9": { + "balance": "6916709000000000000000" + }, + "deee2689fa9006b59cf285237de53b3a7fd01438": { + "balance": "450034000000000000000" + }, + "7f01dc7c3747ca608f983dfc8c9b39e755a3b914": { + "balance": "206980000000000000000" + }, + "9edeac4c026b93054dc5b1d6610c6f3960f2ad73": { + "balance": "1200000000000000000000" + }, + "e3cffe239c64e7e20388e622117391301b298696": { + "balance": "500000000000000000000" + }, + "ebbb4f2c3da8be3eb62d1ffb1f950261cf98ecda": { + "balance": "2000000000000000000000" + }, + "38c10b90c859cbb7815692f99dae520ab5febf5e": { + "balance": "13169000000000000000000" + }, + "23f9ecf3e5dddca38815d3e59ed34b5b90b4a353": { + "balance": "204608000000000000000" + }, + "d7fa5ffb6048f96fb1aba09ef87b1c11dd7005e4": { + "balance": "1000000000000000000000" + }, + "9ca42ee7a0b898f6a5cc60b5a5d7b1bfa3c33231": { + "balance": "2000000000000000000000" + }, + "8b9577920053b1a00189304d888010d9ef2cb4bf": { + "balance": "500000000000000000000" + }, + "fcd0b4827cd208ffbf5e759dba8c3cc61d8c2c3c": { + "balance": "8000000000000000000000" + }, + "01ff1eb1dead50a7f2f9638fdee6eccf3a7b2ac8": { + "balance": "600000000000000000000" + }, + "abde147b2af789eaa586547e66c4fa2664d328a4": { + "balance": "247545000000000000000" + }, + "64042ba68b12d4c151651ca2813b7352bd56f08e": { + "balance": "600000000000000000000" + }, + "dccca42045ec3e16508b603fd936e7fd7de5f36a": { + "balance": "19700000000000000000" + }, + "e77a89bd45dc04eeb4e41d7b596b707e6e51e74c": { + "balance": "12000000000000000000000" + }, + "f77c7b845149efba19e261bc7c75157908afa990": { + "balance": "2000000000000000000000" + }, + "fa5201fe1342af11307b9142a041243ca92e2f09": { + "balance": "152150000000000000000000" + }, + "40df495ecf3f8b4cef2a6c189957248fe884bc2b": { + "balance": "12000000000000000000000" + }, + "3d79a853d71be0621b44e29759656ca075fdf409": { + "balance": "2000000000000000000000" + }, + "6de02f2dd67efdb7393402fa9eaacbcf589d2e56": { + "balance": "1182000000000000000000" + }, + "729aad4627744e53f5d66309aa74448b3acdf46f": { + "balance": "2000000000000000000000" + }, + "4e4318f5e13e824a54edfe30a7ed4f26cd3da504": { + "balance": "2000000000000000000000" + }, + "c6a286e065c85f3af74812ed8bd3a8ce5d25e21d": { + "balance": "18200000000000000000" + }, + "fd686de53fa97f99639e2568549720bc588c9efc": { + "balance": "1969606000000000000000" + }, + "06b0ff834073cce1cbc9ea557ea87b605963e8b4": { + "balance": "300000000000000000000" + }, + "72b5633fe477fe542e742facfd690c137854f216": { + "balance": "1670000000000000000000" + }, + "8bf373d076814cbc57e1c6d16a82c5be13c73d37": { + "balance": "200000000000000000000" + }, + "cf264e6925130906c4d7c18591aa41b2a67f6f58": { + "balance": "2000000000000000000000" + }, + "0ea2a210312b3e867ee0d1cc682ce1d666f18ed5": { + "balance": "10000000000000000000000" + }, + "d02afecf8e2ec2b62ac8ad204161fd1fae771d0e": { + "balance": "2000000000000000000000" + }, + "e6b20f980ad853ad04cbfc887ce6601c6be0b24c": { + "balance": "4000000000000000000000" + }, + "4280a58f8bb10b9440de94f42b4f592120820191": { + "balance": "2000000000000000000000" + }, + "a914cdb571bfd93d64da66a4e108ea134e50d000": { + "balance": "1430143000000000000000" + }, + "60864236930d04d8402b5dcbeb807f3caf611ea2": { + "balance": "4000000000000000000000" + }, + "f9dd239008182fb519fb30eedd2093fed1639be8": { + "balance": "500000000000000000000" + }, + "18e53243981aabc8767da10c73449f1391560eaa": { + "balance": "6000000000000000000000" + }, + "c3a9226ae275df2cab312b911040634a9c9c9ef6": { + "balance": "4000000000000000000000" + }, + "4fcc19ea9f4c57dcbce893193cfb166aa914edc5": { + "balance": "7001380000000000000000" + }, + "c1e1409ca52c25435134d006c2a6a8542dfb7273": { + "balance": "34380000000000000000" + }, + "981ddf0404e4d22dda556a0726f00b2d98ab9569": { + "balance": "999972000000000000000" + }, + "e5bcc88c3b256f6ed5fe550e4a18198b943356ad": { + "balance": "2000000000000000000000" + }, + "74a17f064b344e84db6365da9591ff1628257643": { + "balance": "20000000000000000000" + }, + "2720f9ca426ef2f2cbd2fecd39920c4f1a89e16d": { + "balance": "2000000000000000000000" + }, + "8d04a5ebfb5db409db0617c9fa5631c192861f4a": { + "balance": "970000000000000000000" + }, + "f18b14cbf6694336d0fe12ac1f25df2da0c05dbb": { + "balance": "3999800000000000000000" + }, + "56ac20d63bd803595cec036da7ed1dc66e0a9e07": { + "balance": "63927000000000000000" + }, + "92c94c2820dfcf7156e6f13088ece7958b3676fd": { + "balance": "95500000000000000000" + }, + "968dea60df3e09ae3c8d3505e9c080454be0e819": { + "balance": "6000000000000000000000" + }, + "9268d62646563611dc3b832a30aa2394c64613e3": { + "balance": "2000000000000000000000" + }, + "5a192b964afd80773e5f5eda6a56f14e25e0c6f3": { + "balance": "500000000000000000000" + }, + "df8d48b1eb07b3c217790e6c2df04dc319e7e848": { + "balance": "500000000000000000000" + }, + "7f61fa6cf5f898b440dac5abd8600d6d691fdef9": { + "balance": "280000000000000000000" + }, + "929d368eb46a2d1fbdc8ffa0607ede4ba88f59ad": { + "balance": "2000000000000000000000" + }, + "9982a5890ffb5406d3aca8d2bfc1dd70aaa80ae0": { + "balance": "2000000000000000000000" + }, + "bf2aea5a1dcf6ed3b5e8323944e983fedfd1acfb": { + "balance": "1580000000000000000000" + }, + "46aa501870677e7f0a504876b4e8801a0ad01c46": { + "balance": "800000000000000000000" + }, + "8f473d0ab876ddaa15608621d7013e6ff714b675": { + "balance": "470400000000000000000" + }, + "02290fb5f9a517f82845acdeca0fc846039be233": { + "balance": "2000000000000000000000" + }, + "8a5831282ce14a657a730dc18826f7f9b99db968": { + "balance": "4330268000000000000000" + }, + "0328510c09dbcd85194a98d67c33ac49f2f94d60": { + "balance": "11000000000000000000000" + }, + "cf883a20329667ea226a1e3c765dbb6bab32219f": { + "balance": "3038972000000000000000" + }, + "2615100ea7e25bba9bca746058afbbb4ffbe4244": { + "balance": "500000000000000000000" + }, + "b115ee3ab7641e1aa6d000e41bfc1ec7210c2f32": { + "balance": "13000000000000000000000" + }, + "5cfa8d568575658ca4c1a593ac4c5d0e44c60745": { + "balance": "291000000000000000000" + }, + "d3c24d4b3a5e0ff8a4622d518edd73f16ab28610": { + "balance": "20000000000000000000" + }, + "a639acd96b31ba53b0d08763229e1f06fd105e9d": { + "balance": "8000000000000000000000" + }, + "ffa4aff1a37f984b0a67272149273ae9bd41e3bc": { + "balance": "10000000000000000000000" + }, + "cf684dfb8304729355b58315e8019b1aa2ad1bac": { + "balance": "432500000000000000000" + }, + "5797b60fd2894ab3c2f4aede86daf2e788d745ad": { + "balance": "6000000000000000000000" + }, + "a6a0de421ae54f6d17281308f5646d2f39f7775d": { + "balance": "2000000000000000000000" + }, + "08504f05643fab5919f5eea55925d7a3ed7d807a": { + "balance": "20000000000000000000" + }, + "7a7068e1c3375c0e599db1fbe6b2ea23b8f407d2": { + "balance": "2000000000000000000000" + }, + "1078d7f61b0e56c74ee6635b2e1819ef1e3d8785": { + "balance": "1000000000000000000000" + }, + "6e12b51e225b4a4372e59ad7a2a1a13ea3d3a137": { + "balance": "14172200000000000000000" + }, + "6a2e86469a5bf37cee82e88b4c3863895d28fcaf": { + "balance": "519000000000000000000" + }, + "197672fd39d6f246ce66a790d13aa922d70ea109": { + "balance": "1000000000000000000000" + }, + "8009a7cbd192b3aed4adb983d5284552c16c7451": { + "balance": "4000000000000000000000" + }, + "f6c3c48a1ac0a34799f04db86ec7a975fe7768f3": { + "balance": "1970000000000000000000" + }, + "16be75e98a995a395222d00bd79ff4b6e638e191": { + "balance": "36000000000000000000000" + }, + "6c05e34e5ef2f42ed09deff1026cd66bcb6960bb": { + "balance": "2000000000000000000000" + }, + "5d6ae8cbd6b3393c22d16254100d0238e808147c": { + "balance": "719992000000000000000" + }, + "1a376e1b2d2f590769bb858d4575320d4e149970": { + "balance": "4841200000000000000000" + }, + "f6ead67dbf5b7eb13358e10f36189d53e643cfcf": { + "balance": "40000000000000000000000" + }, + "467d5988249a68614716659840ed0ae6f6f457bc": { + "balance": "387500000000000000000" + }, + "aa960e10c52391c54e15387cc67af827b5316dcc": { + "balance": "2000000000000000000000" + }, + "483ba99034e900e3aedf61499d3b2bce39beb7aa": { + "balance": "985000000000000000000" + }, + "86f23e9c0aafc78b9c404dcd60339a925bffa266": { + "balance": "400000000000000000000" + }, + "d05a447c911dbb275bfb2e5a37e5a703a56f9997": { + "balance": "200000000000000000000" + }, + "edb71ec41bda7dce86e766e6e8c3e9907723a69b": { + "balance": "20000000000000000000" + }, + "f86a3ea8071f7095c7db8a05ae507a8929dbb876": { + "balance": "336000000000000000000" + }, + "323b3cfe3ee62bbde2a261e53cb3ecc05810f2c6": { + "balance": "13790000000000000000000" + }, + "936f3813f5f6a13b8e4ffec83fe7f826186a71cd": { + "balance": "520000000000000000000" + }, + "6db72bfd43fef465ca5632b45aab7261404e13bf": { + "balance": "2000000000000000000000" + }, + "9bb76204186af2f63be79168601687fc9bad661f": { + "balance": "300000000000000000000" + }, + "28ab165ffb69eda0c549ae38e9826f5f7f92f853": { + "balance": "1296890000000000000000" + }, + "c73e2112282215dc0762f32b7e807dcd1a7aae3e": { + "balance": "6900000000000000000000" + }, + "f8086e42661ea929d2dda1ab6c748ce3055d111e": { + "balance": "1000000000000000000000" + }, + "4db21284bcd4f787a7556500d6d7d8f36623cf35": { + "balance": "1939806000000000000000" + }, + "c48651c1d9c16bff4c9554886c3f3f26431f6f68": { + "balance": "658000000000000000000" + }, + "9bdbdc9b973431d13c89a3f9757e9b3b6275bfc7": { + "balance": "499971000000000000000" + }, + "560da37e956d862f81a75fd580a7135c1b246352": { + "balance": "10000000000000000000000" + }, + "4b60a3e253bf38c8d5662010bb93a473c965c3e5": { + "balance": "1490000000000000000000" + }, + "64e02abb016cc23a2934f6bcddb681905021d563": { + "balance": "1000000000000000000000" + }, + "ac2c8e09d06493a63858437bd20be01962450365": { + "balance": "1910000000000000000000" + }, + "9bf9b3b2f23cf461eb591f28340bc719931c8364": { + "balance": "1000000000000000000000" + }, + "9b5c39f7e0ac168c8ed0ed340477117d1b682ee9": { + "balance": "98000000000000000000" + }, + "f75bb39c799779ebc04a336d260da63146ed98d0": { + "balance": "25000000000000000000" + }, + "a7966c489f4c748a7ae980aa27a574251767caf9": { + "balance": "3000000000000000000000" + }, + "ea53c954f4ed97fd4810111bdab69ef981ef25b9": { + "balance": "17300000000000000000000" + }, + "03a26cfc4c18316f70d59e9e1a79ee3e8b962f4c": { + "balance": "2000000000000000000000" + }, + "3e63ce3b24ca2865b4c5a687b7aea3597ef6e548": { + "balance": "2000000000000000000000" + }, + "500c902958f6421594d1b6ded712490d52ed6c44": { + "balance": "1970000000000000000000" + }, + "6f44ca09f0c6a8294cbd519cdc594ad42c67579f": { + "balance": "50000000000000000000" + }, + "3616fb46c81578c9c8eb4d3bf880451a88379d7d": { + "balance": "200000000000000000000" + }, + "57bc20e2d62b3d19663cdb4c309d5b4f2fc2db8f": { + "balance": "100000000000000000000" + }, + "1cebf0985d7f680aaa915c44cc62edb49eab269e": { + "balance": "1000000000000000000000" + }, + "c0cbf6032fa39e7c46ff778a94f7d445fe22cf30": { + "balance": "310000000000000000000" + }, + "c58b9cc61dedbb98c33f224d271f0e228b583433": { + "balance": "3880000000000000000000" + }, + "e9c6dfae97f7099fc5f4e94b784db802923a1419": { + "balance": "48800000000000000000" + }, + "9bacd3d40f3b82ac91a264d9d88d908eac8664b9": { + "balance": "20000000000000000000000" + }, + "63d80048877596e0c28489e650cd4ac180096a49": { + "balance": "280000000000000000000" + }, + "e6a6f6dd6f70a456f4ec15ef7ad5e5dbb68bd7dc": { + "balance": "200000000000000000000" + }, + "d418870bc2e4fa7b8a6121ae0872d55247b62501": { + "balance": "1580000000000000000000" + }, + "e2f9383d5810ea7b43182b8704b62b27f5925d39": { + "balance": "400000000000000000000" + }, + "bd5e473abce8f97a6932f77c2facaf9cc0a00514": { + "balance": "1117350000000000000000" + }, + "2ff1ca55fd9cec1b1fe9f0a9abb74c513c1e2aaa": { + "balance": "3000000000000000000000" + }, + "9d99b189bbd9a48fc2e16e8fcda33bb99a317bbb": { + "balance": "1126900000000000000000" + }, + "6e96faeda3054302c45f58f161324c99a3eebb62": { + "balance": "20000000000000000000" + }, + "ef93818f684db0c3675ec81332b3183ecc28a495": { + "balance": "1550000000000000000000" + }, + "2659facb1e83436553b5b42989adb8075f9953ed": { + "balance": "29356000000000000000" + }, + "c4ffadaaf2823fbea7bff702021bffc4853eb5c9": { + "balance": "42233000000000000000" + }, + "e9864c1afc8eaad37f3ba56fcb7477cc622009b7": { + "balance": "79000000000000000000" + }, + "87ef6d8b6a7cbf9b5c8c97f67ee2adc2a73b3f77": { + "balance": "200400000000000000000" + }, + "c043f2452dcb9602ef62bd360e033dd23971fe84": { + "balance": "2000000000000000000000" + }, + "0fdd65402395df9bd19fee4507ef5345f745104c": { + "balance": "5000000000000000000000" + }, + "939c4313d2280edf5e071bced846063f0a975d54": { + "balance": "120000000000000000000000" + }, + "b28245037cb192f75785cb86cbfe7c930da258b0": { + "balance": "16000000000000000000000" + }, + "a80cb1738bac08d4f9c08b4deff515545fa8584f": { + "balance": "500000000000000000000" + }, + "62971bf2634cee0be3c9890f51a56099dbb9519b": { + "balance": "656000000000000000000" + }, + "f2efe96560c9d97b72bd36447843885c1d90c231": { + "balance": "2000000000000000000000" + }, + "0e390f44053ddfcef0d608b35e4d9c2cbe9871bb": { + "balance": "1970000000000000000000" + }, + "61d101a033ee0e2ebb3100ede766df1ad0244954": { + "balance": "500000000000000000000" + }, + "6785513cf732e47e87670770b5419be10cd1fc74": { + "balance": "2000000000000000000000" + }, + "167699f48a78c615512515739958993312574f07": { + "balance": "39000000000000000000" + }, + "68ec79d5be7155716c40941c79d78d17de9ef803": { + "balance": "500600000000000000000" + }, + "a0e8ba661b48154cf843d4c2a5c0f792d528ee29": { + "balance": "400000000000000000000" + }, + "1a201b4327cea7f399046246a3c87e6e03a3cda8": { + "balance": "1000000000000000000000" + }, + "f60f62d73937953fef35169e11d872d2ea317eec": { + "balance": "5348000000000000000000" + }, + "c0c04d0106810e3ec0e54a19f2ab8597e69a573d": { + "balance": "50000000000000000000" + }, + "ef47cf073e36f271d522d7fa4e7120ad5007a0bc": { + "balance": "2500000000000000000000" + }, + "a44fe800d96fcad73b7170d0f610cb8c0682d6ce": { + "balance": "4000000000000000000000" + }, + "010f4a98dfa1d9799bf5c796fb550efbe7ecd877": { + "balance": "8023366000000000000000" + }, + "708fa11fe33d85ad1befcbae3818acb71f6a7d7e": { + "balance": "18200000000000000000" + }, + "b38c4e537b5df930d65a74d043831d6b485bbde4": { + "balance": "400000000000000000000" + }, + "250a69430776f6347703f9529783955a6197b682": { + "balance": "1940000000000000000000" + }, + "2d35a9df62757f7ffad1049afb06ca4afc464c51": { + "balance": "20000000000000000000" + }, + "6aff1466c2623675e3cb0e75e423d37a25e442eb": { + "balance": "1730000000000000000000" + }, + "fc15cb99a8d1030b12770add033a79ee0d0c908c": { + "balance": "350056000000000000000" + }, + "e784dcc873aa8c1513ec26ff36bc92eac6d4c968": { + "balance": "200000000000000000000" + }, + "b1c328fb98f2f19ab6646f0a7c8c566fda5a8540": { + "balance": "2500000000000000000000" + }, + "247a0a11c57f0383b949de540b66dee68604b0a1": { + "balance": "1069600000000000000000" + }, + "1af60343360e0b2d75255210375720df21db5c7d": { + "balance": "1000000000000000000000" + }, + "8794bf47d54540ece5c72237a1ffb511ddb74762": { + "balance": "2000000000000000000000" + }, + "e76d945aa89df1e457aa342b31028a5e9130b2ce": { + "balance": "1015200000000000000000" + }, + "a30e0acb534c9b3084e8501da090b4eb16a2c0cd": { + "balance": "2000000000000000000000" + }, + "7099d12f6ec656899b049a7657065d62996892c8": { + "balance": "400000000000000000000" + }, + "7be7f2456971883b9a8dbe4c91dec08ac34e8862": { + "balance": "3000000000000000000000" + }, + "42746aeea14f27beff0c0da64253f1e7971890a0": { + "balance": "1550000000000000000000" + }, + "736b44503dd2f6dd5469ff4c5b2db8ea4fec65d0": { + "balance": "313950000000000000000" + }, + "822edff636563a6106e52e9a2598f7e6d0ef2782": { + "balance": "36099000000000000000" + }, + "03c647a9f929b0781fe9ae01caa3e183e876777e": { + "balance": "445800000000000000000" + }, + "63612e7862c27b587cfb6daf9912cb051f030a9f": { + "balance": "43458000000000000000" + }, + "d46bae61b027e5bb422e83a3f9c93f3c8fc77d27": { + "balance": "2000000000000000000000" + }, + "5f23ba1f37a96c45bc490259538a54c28ba3b0d5": { + "balance": "1200000000000000000000" + }, + "d41d7fb49fe701baac257170426cc9b38ca3a9b2": { + "balance": "176000000000000000000" + }, + "1ebacb7844fdc322f805904fbf1962802db1537c": { + "balance": "10000000000000000000000" + }, + "9c80bc18e9f8d4968b185da8c79fa6e11ffc3e23": { + "balance": "240000000000000000000" + }, + "e4ca0a5238564dfc91e8bf22bade2901619a1cd4": { + "balance": "1000000000000000000000" + }, + "1ad72d20a76e7fcc6b764058f48d417d496fa6cd": { + "balance": "2000000000000000000000" + }, + "d3bc730937fa75d8452616ad1ef1fe7fffe0d0e7": { + "balance": "83363000000000000000" + }, + "eac1482826acb6111e19d340a45fb851576bed60": { + "balance": "32177000000000000000" + }, + "01e40521122530d9ac91113c06a0190b6d63850b": { + "balance": "1337000000000000000000" + }, + "9e20e5fd361eabcf63891f5b87b09268b8eb3793": { + "balance": "100000000000000000000" + }, + "69ff429074cb9b6c63bc914284bce5f0c8fbf7d0": { + "balance": "500000000000000000000" + }, + "0d3265d3e7bdb93d5e8e8b1ca47f210a793ecc8e": { + "balance": "200000000000000000000" + }, + "5b4ea16db6809b0352d4b6e81c3913f76a51bb32": { + "balance": "400000000000000000000" + }, + "d8fe088fffce948f5137ee23b01d959e84ac4223": { + "balance": "227942000000000000000" + }, + "7e4e9409704121d1d77997026ff06ea9b19a8b90": { + "balance": "2602600000000000000000" + }, + "96b434fe0657e42acc8212b6865139dede15979c": { + "balance": "4000000000000000000000" + }, + "22f004df8de9e6ebf523ccace457accb26f97281": { + "balance": "10000000000000000000000" + }, + "d8f9240c55cff035523c6d5bd300d370dc8f0c95": { + "balance": "285000000000000000000" + }, + "9d9e57fde30e5068c03e49848edce343b7028358": { + "balance": "1730000000000000000000" + }, + "317cf4a23cb191cdc56312c29d15e210b3b9b784": { + "balance": "144000000000000000000" + }, + "79f08e01ce0988e63c7f8f2908fade43c7f9f5c9": { + "balance": "18200000000000000000" + }, + "04e5f5bc7c923fd1e31735e72ef968fd67110c6e": { + "balance": "1611000000000000000000" + }, + "1ec4ec4b77bf19d091a868e6f49154180541f90e": { + "balance": "2000000000000000000000" + }, + "8737dae671823a8d5917e0157ace9c43468d946b": { + "balance": "1999944000000000000000" + }, + "f998ca3411730a6cd10e7455b0410fb0f6d3ff80": { + "balance": "2000000000000000000000" + }, + "6e2eab85dc89fe29dc0aa1853247dab43a523d56": { + "balance": "80000000000000000000" + }, + "72c083beadbdc227c5fb43881597e32e83c26056": { + "balance": "20000000000000000000000" + }, + "5902e44af769a87246a21e079c08bf36b06efeb3": { + "balance": "1000000000000000000000" + }, + "cc2d04f0a4017189b340ca77198641dcf6456b91": { + "balance": "3940000000000000000000" + }, + "bde4c73f969b89e9ceae66a2b51844480e038e9a": { + "balance": "1000000000000000000000" + }, + "adff0d1d0b97471e76d789d2e49c8a74f9bd54ff": { + "balance": "1880000000000000000000" + }, + "397cdb8c80c67950b18d654229610e93bfa6ee1a": { + "balance": "1172938000000000000000" + }, + "a3e051fb744aa3410c3b88f899f5d57f168df12d": { + "balance": "2955000000000000000000" + }, + "810db25675f45ea4c7f3177f37ce29e22d67999c": { + "balance": "200000000000000000000" + }, + "1e13ec51142cebb7a26083412c3ce35144ba56a1": { + "balance": "5000000000000000000000" + }, + "25bdfa3ee26f3849617b230062588a97e3cae701": { + "balance": "1000008000000000000000" + }, + "ae538c73c5b38d8d584d7ebdadefb15cabe48357": { + "balance": "999000000000000000000" + }, + "a2ecce2c49f72a0995a0bda57aacf1e9f001e22a": { + "balance": "4000000000000000000000" + }, + "7e24fbdad290175eb2df6d180a19b9a9f41370be": { + "balance": "1000000000000000000000" + }, + "e8cc43bc4f8acf39bff04ebfbf42aac06a328470": { + "balance": "400000000000000000000" + }, + "c2779771f0536d79a8708f6931abc44b3035e999": { + "balance": "20002000000000000000000" + }, + "ab27ba78c8e5e3daef31ad05aef0ff0325721e08": { + "balance": "468000000000000000000" + }, + "563cb8803c1d32a25b27b64114852bd04d9c20cd": { + "balance": "204400000000000000000" + }, + "08d4267feb15da9700f7ccc3c84a8918bf17cfde": { + "balance": "1790000000000000000000" + }, + "d1778c13fbd968bc083cb7d1024ffe1f49d02caa": { + "balance": "4020000000000000000000" + }, + "1796bcc97b8abc717f4b4a7c6b1036ea2182639f": { + "balance": "355242000000000000000" + }, + "beecd6af900c8b064afcc6073f2d85d59af11956": { + "balance": "2000000000000000000000" + }, + "045ed7f6d9ee9f252e073268db022c6326adfc5b": { + "balance": "100000000000000000000" + }, + "b88a37c27f78a617d5c091b7d5b73a3761e65f2a": { + "balance": "2000000000000000000000" + }, + "72fb49c29d23a18950c4b2dc0ddf410f532d6f53": { + "balance": "2000000000000000000000" + }, + "6ecaefa6fc3ee534626db02c6f85a0c395571e77": { + "balance": "600000000000000000000" + }, + "d1811c55976980f083901d8a0db269222dfb5cfe": { + "balance": "1550000000000000000000" + }, + "98855c7dfbee335344904a12c40c731795b13a54": { + "balance": "1069600000000000000000" + }, + "92a898d46f19719c38126a8a3c27867ae2cee596": { + "balance": "2000000000000000000000" + }, + "ca428863a5ca30369892d612183ef9fb1a04bcea": { + "balance": "1520000000000000000000" + }, + "797427e3dbf0feae7a2506f12df1dc40326e8505": { + "balance": "1000000000000000000000" + }, + "3d574fcf00fae1d98cc8bf9ddfa1b3953b9741bc": { + "balance": "1970000000000000000000" + }, + "28818e18b610001321b31df6fe7d2815cdadc9f5": { + "balance": "1000000000000000000000" + }, + "5f3e1e6739b0c62200e00a003691d9efb238d89f": { + "balance": "3000000000000000000000" + }, + "d9d370fec63576ab15b318bf9e58364dc2a3552a": { + "balance": "100000000000000000000" + }, + "b223bf1fbf80485ca2b5567d98db7bc3534dd669": { + "balance": "4000000000000000000000" + }, + "7b27d0d1f3dd3c140294d0488b783ebf4015277d": { + "balance": "400000000000000000000" + }, + "7930c2d9cbfa87f510f8f98777ff8a8448ca5629": { + "balance": "199955000000000000000" + }, + "820c19291196505b65059d9914b7090be1db87de": { + "balance": "140000000000000000000" + }, + "e545ee84ea48e564161e9482d59bcf406a602ca2": { + "balance": "1850000000000000000000" + }, + "af4cf41785161f571d0ca69c94f8021f41294eca": { + "balance": "9850000000000000000000" + }, + "7a4f9b850690c7c94600dbee0ca4b0a411e9c221": { + "balance": "1910000000000000000000" + }, + "ddab6b51a9030b40fb95cf0b748a059c2417bec7": { + "balance": "2000000000000000000000" + }, + "315ef2da620fd330d12ee55de5f329a696e0a968": { + "balance": "150000000000000000000" + }, + "4db1c43a0f834d7d0478b8960767ec1ac44c9aeb": { + "balance": "872870000000000000000" + }, + "2fef81478a4b2e8098db5ff387ba2153f4e22b79": { + "balance": "999000000000000000000" + }, + "6c6aa0d30b64721990b9504a863fa0bfb5e57da7": { + "balance": "2700000000000000000000" + }, + "33380c6fff5acd2651309629db9a71bf3f20c5ba": { + "balance": "16100000000000000000000" + }, + "4eebf1205d0cc20cee6c7f8ff3115f56d48fba26": { + "balance": "19400000000000000000" + }, + "03cc9d2d21f86b84ac8ceaf971dba78a90e62570": { + "balance": "1610000000000000000000" + }, + "728f9ab080157db3073156dbca1a169ef3179407": { + "balance": "500000000000000000000" + }, + "30ed11b77bc17e5e6694c8bc5b6e4798f68d9ca7": { + "balance": "143731500000000000000000" + }, + "f617b967b9bd485f7695d2ef51fb7792d898f500": { + "balance": "500000000000000000000" + }, + "c0cbad3ccdf654da22cbcf5c786597ca1955c115": { + "balance": "2000000000000000000000" + }, + "80522ddf944ec52e27d724ed4c93e1f7be6083d6": { + "balance": "200000000000000000000" + }, + "4e90ccb13258acaa9f4febc0a34292f95991e230": { + "balance": "15800000000000000000" + }, + "ff207308ced238a6c01ad0213ca9eb4465d42590": { + "balance": "1999944000000000000000" + }, + "35f2949cf78bc219bb4f01907cf3b4b3d3865482": { + "balance": "289800000000000000000" + }, + "68f525921dc11c329b754fbf3e529fc723c834cd": { + "balance": "1610000000000000000000" + }, + "81139bfdcca656c430203f72958c543b6580d40c": { + "balance": "2000000000000000000000" + }, + "9d511543b3d9dc60d47f09d49d01b6c498d82078": { + "balance": "11245000000000000000000" + }, + "084d103254759b343cb2b9c2d8ff9e1ac5f14596": { + "balance": "7600000000000000000000" + }, + "b323dcbf2eddc5382ee4bbbb201ca3931be8b438": { + "balance": "2000000000000000000000" + }, + "349d2c918fd09e2807318e66ce432909176bd50b": { + "balance": "1120000000000000000000" + }, + "b535f8db879fc67fec58824a5cbe6e5498aba692": { + "balance": "1910000000000000000000" + }, + "824074312806da4748434266ee002140e3819ac2": { + "balance": "1507000000000000000000" + }, + "e8ef100d7ce0895832f2678df72d4acf8c28b8e3": { + "balance": "500038000000000000000" + }, + "84af1b157342d54368260d17876230a534b54b0e": { + "balance": "985000000000000000000" + }, + "419a71a36c11d105e0f2aef5a3e598078e85c80b": { + "balance": "5000000000000000000000" + }, + "55af092f94ba6a79918b0cf939eab3f01b3f51c7": { + "balance": "149940000000000000000" + }, + "35a549e8fd6c368d6dcca6d2e7d18e4db95f5284": { + "balance": "499938000000000000000" + }, + "f0e2649c7e6a3f2c5dfe33bbfbd927ca3c350a58": { + "balance": "2000000000000000000000" + }, + "f4b759cc8a1c75f80849ebbcda878dc8f0d66de4": { + "balance": "400000000000000000000" + }, + "21846f2fdf5a41ed8df36e5ed8544df75988ece3": { + "balance": "1999944000000000000000" + }, + "229ff80bf5708009a9f739e0f8b560914016d5a6": { + "balance": "333333000000000000000" + }, + "da505537537ffb33c415fec64e69bae090c5f60f": { + "balance": "160000000000000000000" + }, + "b91d9e916cd40d193db60e79202778a0087716fc": { + "balance": "404800000000000000000" + }, + "bb6823a1bd819f13515538264a2de052b4442208": { + "balance": "25610000000000000000" + }, + "459393d63a063ef3721e16bd9fde45ee9dbd77fb": { + "balance": "1968818000000000000000" + }, + "95f62d0243ede61dad9a3165f53905270d54e242": { + "balance": "1610000000000000000000" + }, + "b0bb29a861ea1d424d45acd4bfc492fb8ed809b7": { + "balance": "80000000000000000000" + }, + "5e74ed80e9655788e1bb269752319667fe754e5a": { + "balance": "56000000000000000000" + }, + "a276b058cb98d88beedb67e543506c9a0d9470d8": { + "balance": "2668652000000000000000" + }, + "8ae9ef8c8a8adfa6ab798ab2cdc405082a1bbb70": { + "balance": "2000000000000000000000" + }, + "e5102c3b711b810344197419b1cd8a7059f13e32": { + "balance": "299999000000000000000" + }, + "c32038ca52aee19745be5c31fcdc54148bb2c4d0": { + "balance": "49984000000000000000" + }, + "13e321728c9c57628058e93fc866a032dd0bda90": { + "balance": "714580000000000000000" + }, + "c2bae4a233c2d85724f0dabebda0249d833e37d3": { + "balance": "5000000000000000000000" + }, + "10d32416722ca4e648630548ead91edd79c06aff": { + "balance": "100000000000000000000" + }, + "d5f07552b5c693c20067b378b809cee853b8f136": { + "balance": "505540000000000000000" + }, + "8668af868a1e98885f937f2615ded6751804eb2d": { + "balance": "20000000000000000000" + }, + "139d3531c9922ad56269f6309aa789fb2485f98c": { + "balance": "4000000000000000000000" + }, + "1d29c7aab42b2048d2b25225d498dba67a03fbb2": { + "balance": "200000000000000000000" + }, + "d35075ca61fe59d123969c36a82d1ab2d918aa38": { + "balance": "2674000000000000000000" + }, + "d6fc0446c6a8d40ae3551db7e701d1fa876e4a49": { + "balance": "2000000000000000000000" + }, + "fccd0d1ecee27addea95f6857aeec8c7a04b28ee": { + "balance": "10000000000000000000000" + }, + "c12cfb7b3df70fceca0ede263500e27873f8ed16": { + "balance": "1000000000000000000000" + }, + "d0db456178206f5c4430fe005063903c3d7a49a7": { + "balance": "706245000000000000000" + }, + "73cf80ae9688e1580e68e782cd0811f7aa494d2c": { + "balance": "7760000000000000000000" + }, + "d60651e393783423e5cc1bc5f889e44ef7ea243e": { + "balance": "398800000000000000000" + }, + "048a8970ea4145c64d5517b8de5b46d0595aad06": { + "balance": "20000000000000000000000" + }, + "dd9b485a3b1cd33a6a9c62f1e5bee92701856d25": { + "balance": "225073000000000000000" + }, + "5b287c7e734299e727626f93fb1187a60d5057fe": { + "balance": "101230000000000000000" + }, + "635c00fdf035bca15fa3610df3384e0fb79068b1": { + "balance": "9000000000000000000000" + }, + "630a913a9031c9492abd4c41dbb15054cfec4416": { + "balance": "5688000000000000000000" + }, + "af3614dcb68a36e45a4e911e62796247222d595b": { + "balance": "2259800000000000000000" + }, + "335e22025b7a77c3a074c78b8e3dfe071341946e": { + "balance": "10178744000000000000000" + }, + "f0e1dfa42adeac2f17f6fdf584c94862fd563393": { + "balance": "500000000000000000000" + }, + "1a9e702f385dcd105e8b9fa428eea21c57ff528a": { + "balance": "1400000000000000000000" + }, + "8ce4949d8a16542d423c17984e6739fa72ceb177": { + "balance": "24999975000000000000000" + }, + "5f29c9de765dde25852af07d33f2ce468fd20982": { + "balance": "2000000000000000000000" + }, + "dbf5f061a0f48e5e69618739a77d2ec19768d201": { + "balance": "152000000000000000000" + }, + "b247cf9c72ec482af3eaa759658f793d670a570c": { + "balance": "912000000000000000000" + }, + "99f4147ccc6bcb80cc842e69f6d00e30fa4133d9": { + "balance": "400000000000000000000" + }, + "ba6d31b9a261d640b5dea51ef2162c3109f1eba8": { + "balance": "5000000000000000000000" + }, + "f05ba8d7b68539d933300bc9289c3d9474d0419e": { + "balance": "126400000000000000000" + }, + "682e96276f518d31d7e56e30dfb009c1218201bd": { + "balance": "20000000000000000000" + }, + "0927220492194b2eda9fc4bbe38f25d681dfd36c": { + "balance": "6000000000000000000000" + }, + "a3c33afc8cb4704e23153de2049d35ae71332472": { + "balance": "799600000000000000000" + }, + "05c736d365aa37b5c0be9c12c8ad5cd903c32cf9": { + "balance": "6002000000000000000000" + }, + "d8eef4cf4beb01ee20d111748b61cb4d3f641a01": { + "balance": "2740000000000000000000" + }, + "16c1bf5b7dc9c83c179efacbcf2eb174e3561cb3": { + "balance": "1000000000000000000000" + }, + "d79db5ab43621a7a3da795e58929f3dd25af67d9": { + "balance": "1999944000000000000000" + }, + "28efae6356509edface89fc61a7fdcdb39eea8e5": { + "balance": "5348000000000000000000" + }, + "c55005a6c37e8ca7e543ce259973a3cace961a4a": { + "balance": "2000000000000000000000" + }, + "ab3d86bc82927e0cd421d146e07f919327cdf6f9": { + "balance": "1910000000000000000000" + }, + "b74ed2666001c16333cf7af59e4a3d4860363b9c": { + "balance": "193600000000000000000" + }, + "1899f69f653b05a5a6e81f480711d09bbf97588c": { + "balance": "1955000000000000000000" + }, + "27fc85a49cff90dbcfdadc9ddd40d6b9a2210a6c": { + "balance": "100000000000000000000" + }, + "cd1ed263fbf6f6f7b48aef8f733d329d4382c7c7": { + "balance": "18500000000000000000" + }, + "d97fe6f53f2a58f6d76d752adf74a8a2c18e9074": { + "balance": "309990000000000000000" + }, + "80da2fdda29a9e27f9e115975e69ae9cfbf3f27e": { + "balance": "200000000000000000000" + }, + "09146ea3885176f07782e1fe30dce3ce24c49e1f": { + "balance": "20000000000000000000" + }, + "393ff4255e5c658f2e7f10ecbd292572671bc2d2": { + "balance": "2000000000000000000000" + }, + "a390ca122b8501ee3e5e07a8ca4b419f7e4dae15": { + "balance": "100000000000000000000" + }, + "6d9193996b194617211106d1635eb26cc4b66c6c": { + "balance": "399640000000000000000" + }, + "999c49c174ca13bc836c1e0a92bff48b271543ca": { + "balance": "3280000000000000000000" + }, + "7421ce5be381738ddc83f02621974ff0686c79b8": { + "balance": "1632000000000000000000" + }, + "6be9030ee6e2fbc491aca3de4022d301772b7b7d": { + "balance": "26740000000000000000" + }, + "81bd75abd865e0c3f04a0b4fdbcb74d34082fbb7": { + "balance": "4000000000000000000000" + }, + "8bc1ff8714828bf286ff7e8a7709106548ed1b18": { + "balance": "10000000000000000000000" + }, + "a0aadbd9509722705f6d2358a5c79f37970f00f6": { + "balance": "200000000000000000000" + }, + "3d881433f04a7d0d27f84944e08a512da3555287": { + "balance": "1200000000000000000000" + }, + "cc1d6ead01aada3e8dc7b95dca25df26eefa639d": { + "balance": "2000000000000000000000" + }, + "35106ba94e8563d4b3cb3c5c692c10e604b7ced8": { + "balance": "2000000000000000000000" + }, + "4d8697af0fbf2ca36e8768f4af22133570685a60": { + "balance": "20000000000000000000" + }, + "1afcc585896cd0ede129ee2de5c19ea811540b64": { + "balance": "3231259000000000000000" + }, + "e5215631b14248d45a255296bed1fbfa0330ff35": { + "balance": "1310000000000000000000" + }, + "e3878f91ca86053fced5444686a330e09cc388fb": { + "balance": "194000000000000000000" + }, + "555df19390c16d01298772bae8bc3a1152199cbd": { + "balance": "200000000000000000000" + }, + "dc3dae59ed0fe18b58511e6fe2fb69b219689423": { + "balance": "100000000000000000000" + }, + "74648caac748dd135cd91ea14c28e1bd4d7ff6ae": { + "balance": "3100000000000000000000" + }, + "cf2e2ad635e9861ae95cb9bafcca036b5281f5ce": { + "balance": "35200000000000000000000" + }, + "14eec09bf03e352bd6ff1b1e876be664ceffd0cf": { + "balance": "20094000000000000000" + }, + "856e5ab3f64c9ab56b009393b01664fc0324050e": { + "balance": "1790000000000000000000" + }, + "632b9149d70178a7333634275e82d5953f27967b": { + "balance": "700000000000000000000" + }, + "2a39190a4fde83dfb3ddcb4c5fbb83ac6c49755c": { + "balance": "1000000000000000000000" + }, + "369ef761195f3a373e24ece6cd22520fe0b9e86e": { + "balance": "534933000000000000000" + }, + "16afa787fc9f94bdff6976b1a42f430a8bf6fb0f": { + "balance": "2000000000000000000000" + }, + "1b0b31afff4b6df3653a94d7c87978ae35f34aae": { + "balance": "354600000000000000000" + }, + "b4d82f2e69943f7de0f5f7743879406fac2e9cec": { + "balance": "40000000000000000000" + }, + "09d6cefd75b0c4b3f8f1d687a522c96123f1f539": { + "balance": "6000000000000000000000" + }, + "01577afd4e50890247c9b10d44af73229aec884f": { + "balance": "680000000000000000000" + }, + "a35606d51220ee7f2146d411582ee4ee4a45596e": { + "balance": "3996800000000000000000" + }, + "352e77c861696ef96ad54934f894aa8ea35151dd": { + "balance": "1000000000000000000000" + }, + "b87f5376c2de0b6cc3c179c06087aa473d6b4674": { + "balance": "1337000000000000000000" + }, + "5b49afcd75447838f6e7ceda8d21777d4fc1c3c0": { + "balance": "4000000000000000000000" + }, + "b884add88d83dc564ab8e0e02cbdb63919aea844": { + "balance": "2000000000000000000000" + }, + "5c312a56c784b122099b764d059c21ece95e84ca": { + "balance": "95000000000000000000" + }, + "4697baaf9ccb603fd30430689d435445e9c98bf5": { + "balance": "199600000000000000000" + }, + "c625f8c98d27a09a1bcabd5128b1c2a94856af30": { + "balance": "200000000000000000000" + }, + "19f5caf4c40e6908813c0745b0aea9586d9dd931": { + "balance": "664000000000000000000" + }, + "1e596a81b357c6f24970cc313df6dbdaabd0d09e": { + "balance": "2000000000000000000000" + }, + "c1631228efbf2a2e3a4092ee8900c639ed34fbc8": { + "balance": "955000000000000000000" + }, + "6f6cf20649a9e973177ac67dbadee4ebe5c7bdda": { + "balance": "5080000000000000000000" + }, + "5fa7bfe043886127d4011d8356a47e947963aca8": { + "balance": "1820000000000000000000" + }, + "6af8e55969682c715f48ad4fc0fbb67eb59795a3": { + "balance": "2000000000000000000000" + }, + "122f56122549d168a5c5e267f52662e5c5cce5c8": { + "balance": "185000000000000000000" + }, + "7713ab8037411c09ba687f6f9364f0d3239fac28": { + "balance": "10000000000000000000000" + }, + "31ccc616b3118268e75d9ab8996c8858ebd7f3c3": { + "balance": "399924000000000000000" + }, + "09c88f917e4d6ad473fa12e98ea3c4472a5ed6da": { + "balance": "10000000000000000000000" + }, + "e796fd4e839b4c95d7510fb7c5c72b83c6c3e3c7": { + "balance": "512200000000000000000" + }, + "a8285539869d88f8a961533755717d7eb65576ae": { + "balance": "200000000000000000000" + }, + "d929c65d69d5bbaea59762662ef418bc21ad924a": { + "balance": "1000000000000000000000" + }, + "f7418aa0e713d248228776b2e7434222ae75e3a5": { + "balance": "2000000000000000000000" + }, + "7f0b90a1fdd48f27b268feb38382e55ddb50ef0f": { + "balance": "940000000000000000000" + }, + "34a0431fff5ead927f3c69649616dc6e97945f6f": { + "balance": "400000000000000000000" + }, + "1b3cb81e51011b549d78bf720b0d924ac763a7c2": { + "balance": "560000000000000000000000" + }, + "155b3779bb6d56342e2fda817b5b2d81c7f41327": { + "balance": "50200000000000000000" + }, + "ecd486fc196791b92cf612d348614f9156488b7e": { + "balance": "12000000000000000000000" + }, + "82a8cbbfdff02b2e38ae4bbfca15f1f0e83b1aea": { + "balance": "84999000000000000000" + }, + "06b0c1e37f5a5ec4bbf50840548f9d3ac0288897": { + "balance": "4000098000000000000000" + }, + "e6d49f86c228f47367a35e886caacb271e539429": { + "balance": "412656000000000000000" + }, + "704a6eb41ba34f13addde7d2db7df04915c7a221": { + "balance": "1820000000000000000000" + }, + "745ccf2d819edbbddea8117b5c49ed3c2a066e93": { + "balance": "4000000000000000000000" + }, + "6d3b7836a2b9d899721a4d237b522385dce8dfcd": { + "balance": "1000070000000000000000" + }, + "856aa23c82d7215bec8d57f60ad75ef14fa35f44": { + "balance": "20000000000000000000000" + }, + "ea79057dabef5e64e7b44f7f18648e7e533718d2": { + "balance": "200000000000000000000" + }, + "9df057cd03a4e27e8e032f857985fd7f01adc8d7": { + "balance": "2000000000000000000000" + }, + "5f2f07d2d697e8c567fcfdfe020f49f360be2139": { + "balance": "2000000000000000000000" + }, + "5efbdfe5389999633c26605a5bfc2c1bb5959393": { + "balance": "69200000000000000000" + }, + "047e87c8f7d1fce3b01353a85862a948ac049f3e": { + "balance": "1490000000000000000000" + }, + "265383d68b52d034161bfab01ae1b047942fbc32": { + "balance": "21000600000000000000000" + }, + "760ff3354e0fde938d0fb5b82cef5ba15c3d2916": { + "balance": "10000000000000000000000" + }, + "bc46d537cf2edd403565bde733b2e34b215001bd": { + "balance": "20000000000000000000000" + }, + "ee58fb3db29070d0130188ce472be0a172b89055": { + "balance": "10021400000000000000000" + }, + "75abe5270f3a78ce007cf37f8fbc045d489b7bb1": { + "balance": "1999944000000000000000" + }, + "5fc6c11426b4a1eae7e51dd512ad1090c6f1a85b": { + "balance": "2730000000000000000000" + }, + "26cfffd052152bb3f957b478d5f98b233a7c2b92": { + "balance": "4000000000000000000000" + }, + "0a4a011995c681bc999fdd79754e9a324ae3b379": { + "balance": "41350300000000000000000" + }, + "6fa60df818a5446418b1bbd62826e0b9825e1318": { + "balance": "13200000000000000000000" + }, + "63d55ad99b9137fd1b20cc2b4f03d42cbaddf334": { + "balance": "400000000000000000000" + }, + "679b9a109930517e8999099ccf2a914c4c8dd934": { + "balance": "60000000000000000000" + }, + "3e83544f0082552572c782bee5d218f1ef064a9d": { + "balance": "100076000000000000000" + }, + "968b14648f018333687cd213fa640aec04ce6323": { + "balance": "1000000000000000000000" + }, + "427b462ab84e5091f48a46eb0cdc92ddcb26e078": { + "balance": "2000000000000000000000" + }, + "df8510793eee811c2dab1c93c6f4473f30fbef5b": { + "balance": "1000000000000000000000" + }, + "362fbcb10662370a068fc2652602a2577937cce6": { + "balance": "200000000000000000000" + }, + "5d83b21bd2712360436b67a597ee3378db3e7ae4": { + "balance": "2000000000000000000000" + }, + "5777441c83e03f0be8dd340bde636850847c620b": { + "balance": "10000000000000000000000" + }, + "c94a585203da7bbafd93e15884e660d4b1ead854": { + "balance": "7000000000000000000000" + }, + "35a08081799173e001cc5bd46a02406dc95d1787": { + "balance": "10000000000000000000000" + }, + "21d13f0c4024e967d9470791b50f22de3afecf1b": { + "balance": "4452210000000000000000" + }, + "fdfd6134c04a8ab7eb16f00643f8fed7daaaecb2": { + "balance": "400000000000000000000" + }, + "fd812bc69fb170ef57e2327e80affd14f8e4b6d2": { + "balance": "2000000000000000000000" + }, + "7148aef33261d8031fac3f7182ff35928daf54d9": { + "balance": "4100000000000000000000" + }, + "0b06390f2437b20ec4a3d3431b3279c6583e5ed7": { + "balance": "194000000000000000000" + }, + "4909b31998ead414b8fb0e846bd5cbde393935be": { + "balance": "4000000000000000000000" + }, + "b70dba9391682b4a364e77fe99256301a6c0bf1f": { + "balance": "200000000000000000000" + }, + "6b83bae7b565244558555bcf4ba8da2011891c17": { + "balance": "2000000000000000000000" + }, + "70a03549aa6168e97e88a508330a5a0bea74711a": { + "balance": "1337000000000000000000" + }, + "0fc9a0e34145fbfdd2c9d2a499b617d7a02969b9": { + "balance": "180000000000000000000" + }, + "2ddf40905769bcc426cb2c2938ffe077e1e89d98": { + "balance": "3000000000000000000000" + }, + "794b51c39e53d9e762b0613b829a44b472f4fff3": { + "balance": "667965000000000000000" + }, + "d062588171cf99bbeb58f126b870f9a3728d61ec": { + "balance": "4500000000000000000000" + }, + "8db185fe1b70a94a6a080e7e23a8bedc4acbf34b": { + "balance": "1400000000000000000000" + }, + "e73bfeada6f0fd016fbc843ebcf6e370a65be70c": { + "balance": "1970000000000000000000" + }, + "79ed10cf1f6db48206b50919b9b697081fbdaaf3": { + "balance": "2000000000000000000000" + }, + "276b0521b0e68b277df0bb32f3fd48326350bfb2": { + "balance": "50000000000000000000" + }, + "2e439348df8a4277b22a768457d1158e97c40904": { + "balance": "776970000000000000000" + }, + "6c25327f8dcbb2f45e561e86e35d8850e53ab059": { + "balance": "1103200000000000000000" + }, + "04d73896cf6593a691972a13a6e4871ff2c42b13": { + "balance": "2000000000000000000000" + }, + "b10fd2a647102f881f74c9fbc37da632949f2375": { + "balance": "40000000000000000000" + }, + "615f82365c5101f071e7d2cb6af14f7aad2c16c6": { + "balance": "20000000000000000000" + }, + "93aa8f92ebfff991fc055e906e651ac768d32bc8": { + "balance": "940000000000000000000" + }, + "0cbf8770f0d1082e5c20c5aead34e5fca9ae7ae2": { + "balance": "1000000000000000000000" + }, + "ffc9cc3094b041ad0e076f968a0de3b167255866": { + "balance": "432400000000000000000" + }, + "46531e8b1bde097fdf849d6d119885608a008df7": { + "balance": "200000000000000000000" + }, + "23cd2598a20e149ead2ad69379576ecedb60e38e": { + "balance": "2000000000000000000000" + }, + "85ca8bc6da2803d0725f5e1a456c89f9bc774e2f": { + "balance": "600000000000000000000" + }, + "c0725ec2bdc33a1d826071dea29d62d4385a8c25": { + "balance": "40740000000000000000000" + }, + "0e4765790352656bc656682c24fc5ef3e76a23c7": { + "balance": "46610000000000000000" + }, + "2ef9e465716acacfb8c8252fa8e7bc7969ebf6e4": { + "balance": "2760000000000000000000" + }, + "0ec5308b31282e218fc9e759d4fec5db3708cec4": { + "balance": "1001000000000000000000" + }, + "bf7701fc6225d5a17815438a8941d21ebc5d059d": { + "balance": "1880000000000000000000" + }, + "c489c83ffbb0252ac0dbe3521217630e0f491f14": { + "balance": "4000000000000000000000" + }, + "8eb51774af206b966b8909c45aa6722748802c0c": { + "balance": "500000000000000000000" + }, + "7b9226d46fe751940bc416a798b69ccf0dfab667": { + "balance": "4200000000000000000000" + }, + "8f660f8b2e4c7cc2b4ac9c47ed28508d5f8f8650": { + "balance": "20000000000000000000000" + }, + "9f19fac8a32437d80ac6837a0bb7841729f4972e": { + "balance": "650100000000000000000" + }, + "201864a8f784c2277b0b7c9ee734f7b377eab648": { + "balance": "4467000000000000000000" + }, + "a6101c961e8e1c15798ffcd0e3201d7786ec373a": { + "balance": "6000000000000000000000" + }, + "d4ff46203efa23064b1caf00516e28704a82a4f8": { + "balance": "1337000000000000000000" + }, + "aa136b47962bb8b4fb540db4ccf5fdd042ffb8cf": { + "balance": "500038000000000000000" + }, + "704ae21d762d6e1dde28c235d13104597236db1a": { + "balance": "2000000000000000000000" + }, + "f17a92e0361dbacecdc5de0d1894955af6a9b606": { + "balance": "2000000000000000000000" + }, + "8b48e19d39dd35b66e6e1bb6b9c657cb2cf59d04": { + "balance": "17844175000000000000000" + }, + "9ad47fdcf9cd942d28effd5b84115b31a658a13e": { + "balance": "3290000000000000000000" + }, + "df0d08617bd252a911df8bd41a39b83ddf809673": { + "balance": "10000000000000000000000" + }, + "4c666b86f1c5ee8ca41285f5bde4f79052081406": { + "balance": "500000000000000000000" + }, + "88dec5bd3f4eba2d18b8aacefa7b721548c319ba": { + "balance": "1370000000000000000000" + }, + "9f9fe0c95f10fee87af1af207236c8f3614ef02f": { + "balance": "6000000000000000000000" + }, + "f7d0d310acea18406138baaabbfe0571e80de85f": { + "balance": "1337000000000000000000" + }, + "9569c63a9284a805626db3a32e9d236393476151": { + "balance": "1970000000000000000000" + }, + "5d5c2c1099bbeefb267e74b58880b444d94449e0": { + "balance": "253574000000000000000" + }, + "8c6ae7a05a1de57582ae2768204276c0ff47ed03": { + "balance": "208000000000000000000000" + }, + "432d884bd69db1acc0d89c64ade4cb4fc3a88b7a": { + "balance": "2483000000000000000000" + }, + "672cbca8440a8577097b19aff593a2ad9d28a756": { + "balance": "80000000000000000000" + }, + "19df9445a81c1b3d804aeaeb6f6e204e4236663f": { + "balance": "37387000000000000000" + }, + "1cb5f33b4d488936d13e3161da33a1da7df70d1b": { + "balance": "200000000000000000000" + }, + "df60f18c812a11ed4e2776e7a80ecf5e5305b3d6": { + "balance": "900000000000000000000" + }, + "c99a9cd6c9c1be3534eecd92ecc22f5c38e9515b": { + "balance": "4821030000000000000000" + }, + "00c40fe2095423509b9fd9b754323158af2310f3": { + "balance": "0" + }, + "da4a5f557f3bab390a92f49b9b900af30c46ae80": { + "balance": "10000000000000000000000" + }, + "f36df02fbd89607347afce2969b9c4236a58a506": { + "balance": "2000000000000000000000" + }, + "c549df83c6f65eec0f1dc9a0934a5c5f3a50fd88": { + "balance": "2910000000000000000000" + }, + "9f662e95274121f177566e636d23964cf1fd686f": { + "balance": "2000000000000000000000" + }, + "5a267331facb262daaecd9dd63a9700c5f5259df": { + "balance": "100000000000000000000" + }, + "117d9aa3c4d13bee12c7500f09f5dd1c66c46504": { + "balance": "206000000000000000000" + }, + "1b4d07acd38183a61bb2783d2b7b178dd502ac8d": { + "balance": "200000000000000000000" + }, + "3c0c3defac9cea7acc319a96c30b8e1fedab4574": { + "balance": "1940000000000000000000" + }, + "e4dc22ed595bf0a337c01e03cc6be744255fc9e8": { + "balance": "191000000000000000000" + }, + "8f067c7c1bbd57780b7b9eeb9ec0032f90d0dcf9": { + "balance": "20000000000000000000000" + }, + "40e2440ae142c880366a12c6d4102f4b8434b62a": { + "balance": "1000000000000000000000" + }, + "f9ece022bccd2c92346911e79dd50303c01e0188": { + "balance": "1000000000000000000000" + }, + "f70328ef97625fe745faa49ee0f9d4aa3b0dfb69": { + "balance": "1000000000000000000000" + }, + "b6aacb8cb30bab2ae4a2424626e6e12b02d04605": { + "balance": "8000000000000000000000" + }, + "154459fa2f21318e3434449789d826cdc1570ce5": { + "balance": "2000000000000000000000" + }, + "684a44c069339d08e19a75668bdba303be855332": { + "balance": "70000000000000000000000" + }, + "9fe501aa57ead79278937cd6308c5cfa7a5629fe": { + "balance": "50003000000000000000" + }, + "3e45bd55db9060eced923bb9cb733cb3573fb531": { + "balance": "1640000000000000000000" + }, + "9c9f3b8a811b21f3ff3fe20fe970051ce66a824f": { + "balance": "1157740000000000000000" + }, + "e99aece90541cae224b87da673965e0aeb296afd": { + "balance": "920000000000000000000" + }, + "2f6dce1330c59ef921602154572d4d4bacbd048a": { + "balance": "1000000000000000000000" + }, + "6a6353b971589f18f2955cba28abe8acce6a5761": { + "balance": "3000000000000000000000" + }, + "98c10ebf2c4f97cba5a1ab3f2aafe1cac423f8cb": { + "balance": "300000000000000000000" + }, + "8077c3e4c445586e094ce102937fa05b737b568c": { + "balance": "100000000000000000000" + }, + "13371f92a56ea8381e43059a95128bdc4d43c5a6": { + "balance": "1000000000000000000000" + }, + "35a6885083c899dabbf530ed6c12f4dd3a204cf5": { + "balance": "200000000000000000000" + }, + "36b2c85e3aeeebb70d63c4a4730ce2e8e88a3624": { + "balance": "10000000000000000000000" + }, + "5ce44068b8f4a3fe799e6a8311dbfdeda29dee0e": { + "balance": "2000000000000000000000" + }, + "6fa6388d402b30afe59934c3b9e13d1186476018": { + "balance": "670000000000000000000" + }, + "8251358ca4e060ddb559ca58bc0bddbeb4070203": { + "balance": "2000000000000000000000" + }, + "17e86f3b5b30c0ba59f2b2e858425ba89f0a10b0": { + "balance": "2000000000000000000000" + }, + "298ec76b440d8807b3f78b5f90979bee42ed43db": { + "balance": "30000000000000000000000" + }, + "ce4b065dbcb23047203262fb48c1188364977470": { + "balance": "500000000000000000000" + }, + "c8e2adeb545e499d982c0c117363ceb489c5b11f": { + "balance": "985000000000000000000" + }, + "9928ff715afc3a2b60f8eb4cc4ba4ee8dab6e59d": { + "balance": "440000000000000000000" + }, + "c76130c73cb9210238025c9df95d0be54ac67fbe": { + "balance": "1500000000000000000000" + }, + "72d03d4dfab3500cf89b86866f15d4528e14a195": { + "balance": "4488000000000000000000" + }, + "d193e583d6070563e7b862b9614a47e99489f3e5": { + "balance": "999972000000000000000" + }, + "4df140ba796585dd5489315bca4bba680adbb818": { + "balance": "2674000000000000000000" + }, + "009eef0a0886056e3f69211853b9b7457f3782e4": { + "balance": "3000512000000000000000" + }, + "6e255b700ae7138a4bacf22888a9e2c00a285eec": { + "balance": "4000000000000000000000" + }, + "aa47a4ffc979363232c99b99fada0f2734b0aeee": { + "balance": "8121800000000000000000" + }, + "9d069197d1de50045a186f5ec744ac40e8af91c6": { + "balance": "2000000000000000000000" + }, + "b514882c979bb642a80dd38754d5b8c8296d9a07": { + "balance": "955000000000000000000" + }, + "17c0478657e1d3d17aaa331dd429cecf91f8ae5d": { + "balance": "999942000000000000000" + }, + "5f9616c47b4a67f406b95a14fe6fc268396f1721": { + "balance": "200000000000000000000" + }, + "f70a998a717b338d1dd99854409b1a338deea4b0": { + "balance": "2000000000000000000000" + }, + "d1ee905957fe7cc70ec8f2868b43fe47b13febff": { + "balance": "44000000000000000000" + }, + "fc018a690ad6746dbe3acf9712ddca52b6250039": { + "balance": "10000000000000000000000" + }, + "5118557d600d05c2fcbf3806ffbd93d02025d730": { + "balance": "11360000000000000000000" + }, + "1ef5c9c73650cfbbde5c885531d427c7c3fe5544": { + "balance": "6000000000000000000000" + }, + "d1a396dcdab2c7494130b3fd307820340dfd8c1f": { + "balance": "17952000000000000000" + }, + "2d8e061892a5dcce21966ae1bb0788fd3e8ba059": { + "balance": "250066000000000000000" + }, + "8834b2453471f324fb26be5b25166b5b5726025d": { + "balance": "573000000000000000000" + }, + "14f221159518783bc4a706676fc4f3c5ee405829": { + "balance": "200000000000000000000" + }, + "c056d4bd6bf3cbacac65f8f5a0e3980b852740ae": { + "balance": "100000000000000000000" + }, + "560536794a9e2b0049d10233c41adc5f418a264a": { + "balance": "1000000000000000000000" + }, + "bc9e0ec6788f7df4c7fc210aacd220c27e45c910": { + "balance": "500000000000000000000" + }, + "54bcb8e7f73cda3d73f4d38b2d0847e600ba0df8": { + "balance": "1078000000000000000000" + }, + "4361d4846fafb377b6c0ee49a596a78ddf3516a3": { + "balance": "3580000000000000000000" + }, + "41c3c2367534d13ba2b33f185cdbe6ac43c2fa31": { + "balance": "4000000000000000000000" + }, + "5dc6f45fef26b06e3302313f884daf48e2746fb9": { + "balance": "500000000000000000000" + }, + "ad414d29cb7ee973fec54e22a388491786cf5402": { + "balance": "14000000000000000000000" + }, + "802dc3c4ff2d7d925ee2859f4a06d7ba60f1308c": { + "balance": "98040000000000000000" + }, + "2aed2ce531c056b0097efc3c6de10c4762004ed9": { + "balance": "10430000000000000000000" + }, + "39782ffe06ac78822a3c3a8afe305e50a56188ce": { + "balance": "10000000000000000000000" + }, + "ec73833de4b810bb027810fc8f69f544e83c12d1": { + "balance": "1000000000000000000000" + }, + "8d51a4cc62011322c696fd725b9fb8f53feaaa07": { + "balance": "1000000000000000000000" + }, + "29298ccbdff689f87fe41aa6e98fdfb53deaf37a": { + "balance": "19800000000000000000000" + }, + "827531a6c5817ae35f82b00b9754fcf74c55e232": { + "balance": "3600000000000000000000" + }, + "9c581a60b61028d934167929b22d70b313c34fd0": { + "balance": "50000000000000000000000" + }, + "0a077db13ffeb09484c217709d5886b8bf9c5a8b": { + "balance": "4000000000000000000000" + }, + "07b7a57033f8f11330e4665e185d234e83ec140b": { + "balance": "4325683000000000000000" + }, + "17f523f117bc9fe978aa481eb4f5561711371bc8": { + "balance": "1999884000000000000000" + }, + "de42fcd24ce4239383304367595f068f0c610740": { + "balance": "45120000000000000000" + }, + "2a46d353777176ff8e83ffa8001f4f70f9733aa5": { + "balance": "106000000000000000000" + }, + "92e4392816e5f2ef5fb65837cec2c2325cc64922": { + "balance": "10000000000000000000000" + }, + "9a3da65023a13020d22145cfc18bab10bd19ce4e": { + "balance": "456516000000000000000" + }, + "1a085d43ec92414ea27b914fe767b6d46b1eef44": { + "balance": "29550000000000000000000" + }, + "3b2367f8494b5fe18d683c055d89999c9f3d1b34": { + "balance": "10000000000000000000000" + }, + "84244fc95a6957ed7c1504e49f30b8c35eca4b79": { + "balance": "2000000000000000000000" + }, + "5e031b0a724471d476f3bcd2eb078338bf67fbef": { + "balance": "18200000000000000000" + }, + "97e5cc6127c4f885be02f44b42d1c8b0ac91e493": { + "balance": "200000000000000000000" + }, + "eb1cea7b45d1bd4d0e2a007bd3bfb354759e2c16": { + "balance": "198000000000000000000" + }, + "72feaf124579523954645b7fafff0378d1c8242e": { + "balance": "1000000000000000000000" + }, + "8d07d42d831c2d7c838aa1872b3ad5d277176823": { + "balance": "349200000000000000000" + }, + "9637dc12723d9c78588542eab082664f3f038d9d": { + "balance": "1000000000000000000000" + }, + "e84b55b525f1039e744b918cb3332492e45eca7a": { + "balance": "200000000000000000000" + }, + "b1d6b01b94d854fe8b374aa65e895cf22aa2560e": { + "balance": "940000000000000000000" + }, + "8161d940c3760100b9080529f8a60325030f6edc": { + "balance": "300000000000000000000" + }, + "d30ee9a12b4d68abace6baca9ad7bf5cd1faf91c": { + "balance": "1499936000000000000000" + }, + "057949e1ca0570469e4ce3c690ae613a6b01c559": { + "balance": "200000000000000000000" + }, + "4bf8e26f4c2790da6533a2ac9abac3c69a199433": { + "balance": "200000000000000000000" + }, + "36fec62c2c425e219b18448ad757009d8c54026f": { + "balance": "400000000000000000000" + }, + "77bfe93ccda750847e41a1affee6b2da96e7214e": { + "balance": "300000000000000000000" + }, + "cc48414d2ac4d42a5962f29eee4497092f431352": { + "balance": "161000000000000000000" + }, + "ddbddd1bbd38ffade0305d30f02028d92e9f3aa8": { + "balance": "2000000000000000000000" + }, + "30c01142907acb1565f70438b9980ae731818738": { + "balance": "2000000000000000000000" + }, + "cffc49c1787eebb2b56cabe92404b636147d4558": { + "balance": "5679305000000000000000" + }, + "f99eeece39fa7ef5076d855061384009792cf2e0": { + "balance": "500000000000000000000" + }, + "e9b6a790009bc16642c8d820b7cde0e9fd16d8f5": { + "balance": "3640000000000000000000" + }, + "03b41b51f41df20dd279bae18c12775f77ad771c": { + "balance": "1000000000000000000000" + }, + "787d313fd36b053eeeaedbce74b9fb0678333289": { + "balance": "27160000000000000000000" + }, + "35d2970f49dcc81ea9ee707e9c8a0ab2a8bb7463": { + "balance": "1440000000000000000000" + }, + "4c0aca508b3caf5ee028bc707dd1e800b838f453": { + "balance": "18200000000000000000" + }, + "514632efbd642c04de6ca342315d40dd90a2dba6": { + "balance": "2674000000000000000000" + }, + "36810ff9d213a271eda2b8aa798be654fa4bbe06": { + "balance": "2000000000000000000000" + }, + "0c088006c64b30c4ddafbc36cb5f05469eb62834": { + "balance": "2000000000000000000000" + }, + "568df31856699bb5acfc1fe1d680df9960ca4359": { + "balance": "1379999000000000000000" + }, + "d48e3f9357e303513841b3f84bda83fc89727587": { + "balance": "1000000000000000000000" + }, + "953ef652e7b769f53d6e786a58952fa93ee6abe7": { + "balance": "2860000000000000000000" + }, + "7c60a05f7a4a5f8cf2784391362e755a8341ef59": { + "balance": "1892300000000000000000" + }, + "7a6b26f438d9a352449155b8876cbd17c9d99b64": { + "balance": "6000000000000000000000" + }, + "68f719ae342bd7fef18a05cbb02f705ad38ed5b2": { + "balance": "1050000000000000000000" + }, + "45ca8d956608f9e00a2f9974028640888465668f": { + "balance": "2000000000000000000000" + }, + "3eaf316b87615d88f7adc77c58e712ed4d77966b": { + "balance": "100141000000000000000" + }, + "1f0412bfedcd964e837d092c71a5fcbaf30126e2": { + "balance": "20000000000000000000" + }, + "7471f72eeb300624eb282eab4d03723c649b1b58": { + "balance": "8000000000000000000000" + }, + "9bf71f7fb537ac54f4e514947fa7ff6728f16d2f": { + "balance": "33400000000000000000" + }, + "1098c774c20ca1daac5ddb620365316d353f109c": { + "balance": "100000000000000000000" + }, + "7dd8d7a1a34fa1f8e73ccb005fc2a03a15b8229c": { + "balance": "200000000000000000000" + }, + "0151fa5d17a2dce2d7f1eb39ef7fe2ad213d5d89": { + "balance": "4000000000000000000000" + }, + "ad6628352ed3390bafa86d923e56014cfcb360f4": { + "balance": "2000000000000000000000" + }, + "02af2459a93d0b3f4d062636236cd4b29e3bcecf": { + "balance": "1910000000000000000000" + }, + "ace2abb63b0604409fbde3e716d2876d44e8e5dd": { + "balance": "152000000000000000000" + }, + "e710dcd09b8101f9437bd97db90a73ef993d0bf4": { + "balance": "386100000000000000000" + }, + "d43ee438d83de9a37562bb4e286cb1bd19f4964d": { + "balance": "1000000000000000000000" + }, + "ea3779d14a13f6c78566bcde403591413a6239db": { + "balance": "197000000000000000000000" + }, + "6704f169e0d0b36b57bbc39f3c45437b5ee3d28d": { + "balance": "394000000000000000000" + }, + "5584423050e3c2051f0bbd8f44bd6dbc27ecb62c": { + "balance": "3000000000000000000000" + }, + "2f315d9016e8ee5f536681202f9084b032544d4d": { + "balance": "1037400000000000000000" + }, + "e1b63201fae1f129f95c7a116bd9dde5159c6cda": { + "balance": "22837462000000000000000" + }, + "2bbe62eac80ca7f4d6fdee7e7d8e28b63acf770e": { + "balance": "2396000000000000000000" + }, + "38da1ba2de9e2c954b092dd9d81204fd016ba016": { + "balance": "10156000000000000000000" + }, + "8a86e4a51c013b1fb4c76bcf30667c78d52eedef": { + "balance": "2000000000000000000000" + }, + "8f717ec1552f4c440084fba1154a81dc003ebdc0": { + "balance": "10000000000000000000000" + }, + "c760971bbc181c6a7cf77441f24247d19ce9b4cf": { + "balance": "2000000000000000000000" + }, + "7f150afb1a77c2b45928c268c1e9bdb4641d47d8": { + "balance": "2000000000000000000000" + }, + "1ea334b5750807ea74aac5ab8694ec5f28aa77cf": { + "balance": "492500000000000000000" + }, + "2afb058c3d31032b353bf24f09ae20d54de57dbe": { + "balance": "1100000000000000000000" + }, + "caef027b1ab504c73f41f2a10979b474f97e309f": { + "balance": "200000000000000000000" + }, + "5dd112f368c0e6ceff77a9df02a5481651a02fb7": { + "balance": "169800000000000000000" + }, + "bd93e550403e2a06113ed4c3fba1a8913b19407e": { + "balance": "2000000000000000000000" + }, + "500c16352e901d48ba8d04e2c767121772790b02": { + "balance": "30239000000000000000" + }, + "d2a80327cbe55c4c7bd51ff9dde4ca648f9eb3f8": { + "balance": "50000000000000000000" + }, + "355ccfe0e77d557b971be1a558bc02df9eee0594": { + "balance": "1759120000000000000000" + }, + "5aed0e6cfe95f9d680c76472a81a2b680a7f93e2": { + "balance": "197000000000000000000" + }, + "f56442f60e21691395d0bffaa9194dcaff12e2b7": { + "balance": "260000000000000000000" + }, + "7db9eacc52e429dc83b461c5f4d86010e5383a28": { + "balance": "1000000000000000000000" + }, + "4b984ef26c576e815a2eaed2f5177f07dbb1c476": { + "balance": "1560000000000000000000" + }, + "9846648836a307a057184fd51f628a5f8c12427c": { + "balance": "19100000000000000000000" + }, + "4af0db077bb9ba5e443e21e148e59f379105c592": { + "balance": "600000000000000000000" + }, + "e96e2d3813efd1165f12f602f97f4a62909d3c66": { + "balance": "2300000000000000000000" + }, + "30e789b3d2465e946e6210fa5b35de4e8c93085f": { + "balance": "2000000000000000000000" + }, + "97f99b6ba31346cd98a9fe4c308f87c5a58c5151": { + "balance": "6000000000000000000000" + }, + "595e23d788a2d4bb85a15df7136d264a635511b3": { + "balance": "3940000000000000000000" + }, + "2f61efa5819d705f2b1e4ee754aeb8a819506a75": { + "balance": "1460000000000000000000" + }, + "3554947b7b947b0040da52ca180925c6d3b88ffe": { + "balance": "66850000000000000000" + }, + "8feffadb387a1547fb284da9b8147f3e7c6dc6da": { + "balance": "837200000000000000000" + }, + "258939bbf00c9de9af5338f5d714abf6d0c1c671": { + "balance": "1550000000000000000000" + }, + "5b333696e04cca1692e71986579c920d6b2916f9": { + "balance": "500000000000000000000" + }, + "5381448503c0c702542b1de7cc5fb5f6ab1cf6a5": { + "balance": "8000000000000000000000" + }, + "7e81f6449a03374191f3b7cb05d938b72e090dff": { + "balance": "100000000000000000000" + }, + "4ef1c214633ad9c0703b4e2374a2e33e3e429291": { + "balance": "1337000000000000000000" + }, + "fed8476d10d584b38bfa6737600ef19d35c41ed8": { + "balance": "1820000000000000000000" + }, + "1a95c9b7546b5d1786c3858fb1236446bc0ca4ce": { + "balance": "1970000000000000000000" + }, + "3b07db5a357f5af2484cbc9d77d73b1fd0519fc7": { + "balance": "500000000000000000000" + }, + "5f68a24c7eb4117667737b33393fb3c2148a53b6": { + "balance": "51800000000000000000" + }, + "d8f665fd8cd5c2bcc6ddc0a8ae521e4dc6aa6060": { + "balance": "1700000000000000000000" + }, + "d66acc0d11b689cea6d9ea5ff4014c224a5dc7c4": { + "balance": "18200000000000000000" + }, + "6e72b2a1186a8e2916543b1cb36a68870ea5d197": { + "balance": "186000000000000000000" + }, + "5102a4a42077e11c58df4773e3ac944623a66d9f": { + "balance": "2000325000000000000000" + }, + "72480bede81ad96423f2228b5c61be44fb523100": { + "balance": "6400000000000000000000" + }, + "e076db30ab486f79194ebbc45d8fab9a9242f654": { + "balance": "4840000000000000000000" + }, + "8ceea15eec3bdad8023f98ecf25b2b8fef27db29": { + "balance": "2000000000000000000000" + }, + "40652360d6716dc55cf9aab21f3482f816cc2cbd": { + "balance": "10000000000000000000000" + }, + "13e02fb448d6c84ae17db310ad286d056160da95": { + "balance": "2000000000000000000000" + }, + "d6598b1386e93c5ccb9602ff4bbbecdbd3701dc4": { + "balance": "224096000000000000000" + }, + "d5ea472cb9466018110af00c37495b5c2c713112": { + "balance": "4997800000000000000000" + }, + "bb75cb5051a0b0944b4673ca752a97037f7c8c15": { + "balance": "200000000000000000000" + }, + "8af626a5f327d7506589eeb7010ff9c9446020d2": { + "balance": "1400000000000000000000" + }, + "318c76ecfd8af68d70555352e1f601e35988042d": { + "balance": "501600000000000000000" + }, + "5c3d19441d196cb443662020fcad7fbb79b29e78": { + "balance": "14300000000000000000" + }, + "27101a0f56d39a88c5a84f9b324cdde33e5cb68c": { + "balance": "2000000000000000000000" + }, + "e229e746a83f2ce253b0b03eb1472411b57e5700": { + "balance": "5730000000000000000000" + }, + "604cdf18628dbfa8329194d478dd5201eecc4be7": { + "balance": "23000000000000000000" + }, + "657473774f63ac3d6279fd0743d5790c4f161503": { + "balance": "200000000000000000000" + }, + "1ddefefd35ab8f658b2471e54790bc17af98dea4": { + "balance": "1000000000000000000000" + }, + "ac3900298dd14d7cc96d4abb428da1bae213ffed": { + "balance": "24730250000000000000000" + }, + "944f07b96f90c5f0d7c0c580533149f3f585a078": { + "balance": "74000000000000000000" + }, + "232c6d03b5b6e6711efff190e49c28eef36c82b0": { + "balance": "1337000000000000000000" + }, + "c87c77e3c24adecdcd1038a38b56e18dead3b702": { + "balance": "8800000000000000000000" + }, + "c4b6e5f09cc1b90df07803ce3d4d13766a9c46f4": { + "balance": "6000000000000000000000" + }, + "d44334b4e23a169a0c16bd21e866bba52d970587": { + "balance": "2600000000000000000000" + }, + "7757a4b9cc3d0247ccaaeb9909a0e56e1dd6dcc2": { + "balance": "20000000000000000000" + }, + "cf694081c76d18c64ca71382be5cd63b3cb476f8": { + "balance": "1000000000000000000000" + }, + "133e4f15e1e39c53435930aaedf3e0fe56fde843": { + "balance": "20000000000000000000" + }, + "f067fb10dfb293e998abe564c055e3348f9fbf1e": { + "balance": "2000000000000000000000" + }, + "94449c01b32a7fa55af8104f42cdd844aa8cbc40": { + "balance": "16548000000000000000000" + }, + "0e2094ac1654a46ba1c4d3a40bb8c17da7f39688": { + "balance": "358000000000000000000" + }, + "738ca94db7ce8be1c3056cd6988eb376359f3353": { + "balance": "25500000000000000000000" + }, + "0cfb172335b16c87d519cd1475530d20577f5e0e": { + "balance": "100000000000000000000000" + }, + "3cb561ce86424b359891e364ec925ffeff277df7": { + "balance": "200000000000000000000" + }, + "5f981039fcf50225e2adf762752112d1cc26b6e3": { + "balance": "499954000000000000000" + }, + "b43657a50eecbc3077e005d8f8d94f377876bad4": { + "balance": "35460000000000000000" + }, + "d07e511864b1cf9969e3560602829e32fc4e71f5": { + "balance": "50000000000000000000" + }, + "11306c7d57588637780fc9fde8e98ecb008f0164": { + "balance": "1999944000000000000000" + }, + "45ca9862003b4e40a3171fb5cafa9028cac8de19": { + "balance": "13790000000000000000000" + }, + "231d94155dbcfe2a93a319b6171f63b20bd2b6fa": { + "balance": "3819952000000000000000" + }, + "e7533e270cc61fa164ac1553455c105d04887e14": { + "balance": "121550000000000000000" + }, + "070d5d364cb7bbf822fc2ca91a35bdd441b215d5": { + "balance": "2000000000000000000000" + }, + "d475477fa56390d33017518d6711027f05f28dbf": { + "balance": "1975032000000000000000" + }, + "cea34a4dd93dd9aefd399002a97d997a1b4b89cd": { + "balance": "1500000000000000000000" + }, + "560becdf52b71f3d8827d927610f1a980f33716f": { + "balance": "429413000000000000000" + }, + "f632adff490da4b72d1236d04b510f74d2faa3cd": { + "balance": "1400000000000000000000" + }, + "2fdd9b79df8df530ad63c20e62af431ae99216b8": { + "balance": "21000000000000000000" + }, + "535201a0a1d73422801f55ded4dfaee4fbaa6e3b": { + "balance": "39641000000000000000" + }, + "409d5a962edeeebea178018c0f38b9cdb213f289": { + "balance": "20000000000000000000" + }, + "9d911f3682f32fe0792e9fb6ff3cfc47f589fca5": { + "balance": "4000000000000000000000" + }, + "9f7a0392f857732e3004a375e6b1068d49d83031": { + "balance": "2000000000000000000000" + }, + "6a04f5d53fc0f515be942b8f12a9cb7ab0f39778": { + "balance": "3129800000000000000000" + }, + "be478e8e3dde6bd403bb2d1c657c4310ee192723": { + "balance": "492500000000000000000" + }, + "007622d84a234bb8b078230fcf84b67ae9a8acae": { + "balance": "698800000000000000000" + }, + "9475c510ec9a26979247744c3d8c3b0e0b5f44d3": { + "balance": "10000000000000000000000" + }, + "df47a8ef95f2f49f8e6f58184154145d11f72797": { + "balance": "1910000000000000000000" + }, + "13ce332dff65a6ab933897588aa23e000980fa82": { + "balance": "258400000000000000000" + }, + "9c4bbcd5f1644a6f075824ddfe85c571d6abf69c": { + "balance": "1800000000000000000000" + }, + "d42b20bd0311608b66f8a6d15b2a95e6de27c5bf": { + "balance": "2000000000000000000000" + }, + "a4dd59ab5e517d398e49fa537f899fed4c15e95d": { + "balance": "20000000000000000000000" + }, + "1a8a5ce414de9cd172937e37f2d59cff71ce57a0": { + "balance": "10000000000000000000000" + }, + "55c564664166a1edf3913e0169f1cd451fdb5d0c": { + "balance": "2399800000000000000000" + }, + "58ae2ddc5f4c8ada97e06c0086171767c423f5d7": { + "balance": "1610000000000000000000" + }, + "fb79abdb925c55b9f98efeef64cfc9eb61f51bb1": { + "balance": "1794000000000000000000" + }, + "e7a42f59fee074e4fb13ea9e57ecf1cc48282249": { + "balance": "20000000000000000000000" + }, + "07e2b4cdeed9d087b12e556d9e770c13c099615f": { + "balance": "668500000000000000000" + }, + "68473b7a7d965904bedba556dfbc17136cd5d434": { + "balance": "100000000000000000000" + }, + "6c5c3a54cda7c2f118edba434ed81e6ebb11dd7a": { + "balance": "200000000000000000000" + }, + "24c117d1d2b3a97ab11a4679c99a774a9eade8d1": { + "balance": "1000000000000000000000" + }, + "f68c5e33fa97139df5b2e63886ce34ebf3e4979c": { + "balance": "3320000000000000000000" + }, + "bd7419dc2a090a46e2873d7de6eaaad59e19c479": { + "balance": "6802000000000000000000" + }, + "1a0a1ddfb031e5c8cc1d46cf05842d50fddc7130": { + "balance": "1000000000000000000000" + }, + "2b3a68db6b0cae8a7c7a476bdfcfbd6205e10687": { + "balance": "2400000000000000000000" + }, + "426d15f407a01135b13a6b72f8f2520b3531e302": { + "balance": "20000000000000000000" + }, + "0394b90fadb8604f86f43fc1e35d3124b32a5989": { + "balance": "764000000000000000000" + }, + "7412c9bc30b4df439f023100e63924066afd53af": { + "balance": "500000000000000000000" + }, + "80e7b3205230a566a1f061d922819bb4d4d2a0e1": { + "balance": "14000000000000000000000" + }, + "ff4fc66069046c525658c337a917f2d4b832b409": { + "balance": "2000000000000000000000" + }, + "f5061ee2e5ee26b815503677130e1de07a52db07": { + "balance": "100000000000000000000" + }, + "49793463e1681083d6abd6e725d5bba745dccde8": { + "balance": "545974000000000000000" + }, + "23551f56975fe92b31fa469c49ea66ee6662f41e": { + "balance": "1910000000000000000000" + }, + "fad96ab6ac768ad5099452ac4777bd1a47edc48f": { + "balance": "100000000000000000000" + }, + "2a746cd44027af3ebd37c378c85ef7f754ab5f28": { + "balance": "394000000000000000000" + }, + "b8d389e624a3a7aebce4d3e5dbdf6cdc29932aed": { + "balance": "200000000000000000000" + }, + "7b761feb7fcfa7ded1f0eb058f4a600bf3a708cb": { + "balance": "4600000000000000000000" + }, + "5435c6c1793317d32ce13bba4c4ffeb973b78adc": { + "balance": "250070000000000000000" + }, + "dd04eee74e0bf30c3f8d6c2c7f52e0519210df93": { + "balance": "80000000000000000000" + }, + "4331ab3747d35720a9d8ca25165cd285acd4bda8": { + "balance": "2000000000000000000000" + }, + "b84c8b9fd33ece00af9199f3cf5fe0cce28cd14a": { + "balance": "3820000000000000000000" + }, + "393f783b5cdb86221bf0294fb714959c7b45899c": { + "balance": "5910000000000000000000" + }, + "259ec4d265f3ab536b7c70fa97aca142692c13fc": { + "balance": "20400000000000000000" + }, + "5d2f7f0b04ba4be161e19cb6f112ce7a5e7d7fe4": { + "balance": "35200000000000000000" + }, + "d54ba2d85681dc130e5b9b02c4e8c851391fd9b9": { + "balance": "3940000000000000000000" + }, + "5cd8af60de65f24dc3ce5730ba92653022dc5963": { + "balance": "1790000000000000000000" + }, + "3b42a66d979f582834747a8b60428e9b4eeccd23": { + "balance": "620400000000000000000" + }, + "4b19eb0c354bc1393960eb06063b83926f0d67b2": { + "balance": "29000000000000000000" + }, + "8cf3546fd1cda33d58845fc8fcfecabca7c5642a": { + "balance": "574027000000000000000" + }, + "113612bc3ba0ee4898b49dd20233905f2f458f62": { + "balance": "14000000000000000000000" + }, + "1f2afc0aed11bfc71e77a907657b36ea76e3fb99": { + "balance": "4000000000000000000000" + }, + "03714b41d2a6f751008ef8dd4d2b29aecab8f36e": { + "balance": "6000000000000000000000" + }, + "25721c87b0dc21377c7200e524b14a22f0af69fb": { + "balance": "4000000000000000000000" + }, + "335858f749f169cabcfe52b796e3c11ec47ea3c2": { + "balance": "200000000000000000000" + }, + "52fb46ac5d00c3518b2c3a1c177d442f8165555f": { + "balance": "1500000000000000000000" + }, + "7a8c89c014509d56d7b68130668ff6a3ecec7370": { + "balance": "300000000000000000000" + }, + "7d5d2f73949dadda0856b206989df0078d51a1e5": { + "balance": "10560000000000000000000" + }, + "be538246dd4e6f0c20bf5ad1373c3b463a131e86": { + "balance": "200000000000000000000" + }, + "62680a15f8ccb8bdc02f7360c25ad8cfb57b8ccd": { + "balance": "1000000000000000000000" + }, + "aa0ca3737337178a0caac3099c584b056c56301c": { + "balance": "880000000000000000000" + }, + "1d341fa5a3a1bd051f7db807b6db2fc7ba4f9b45": { + "balance": "18200000000000000000" + }, + "6463f715d594a1a4ace4bb9c3b288a74decf294d": { + "balance": "1970000000000000000000" + }, + "e00d153b10369143f97f54b8d4ca229eb3e8f324": { + "balance": "152000000000000000000" + }, + "8d0b9ea53fd263415eac11391f7ce9123c447062": { + "balance": "2000000000000000000000" + }, + "cacb675e0996235404efafbb2ecb8152271b55e0": { + "balance": "700000000000000000000" + }, + "b615e940143eb57f875893bc98a61b3d618c1e8c": { + "balance": "20000000000000000000" + }, + "606f177121f7855c21a5062330c8762264a97b31": { + "balance": "4000000000000000000000" + }, + "e3925509c8d0b2a6738c5f6a72f35314491248ce": { + "balance": "1012961000000000000000" + }, + "3f08d9ad894f813e8e2148c160d24b353a8e74b0": { + "balance": "60000000000000000000000" + }, + "40f4f4c06c732cd35b119b893b127e7d9d0771e4": { + "balance": "10000000000000000000000" + }, + "1406854d149e081ac09cb4ca560da463f3123059": { + "balance": "1337000000000000000000" + }, + "ecf05d07ea026e7ebf4941002335baf2fed0f002": { + "balance": "200000000000000000000" + }, + "9a990b8aeb588d7ee7ec2ed8c2e64f7382a9fee2": { + "balance": "33518000000000000000" + }, + "a2e0683a805de6a05edb2ffbb5e96f0570b637c3": { + "balance": "20000000000000000000" + }, + "fba5486d53c6e240494241abf87e43c7600d413a": { + "balance": "1987592000000000000000" + }, + "d81bd54ba2c44a6f6beb1561d68b80b5444e6dc6": { + "balance": "1163806000000000000000" + }, + "5298ab182a19359ffcecafd7d1b5fa212dede6dd": { + "balance": "20000000000000000000" + }, + "d1acb5adc1183973258d6b8524ffa28ffeb23de3": { + "balance": "4000000000000000000000" + }, + "4e7aa67e12183ef9d7468ea28ad239c2eef71b76": { + "balance": "4925000000000000000000" + }, + "509a20bc48e72be1cdaf9569c711e8648d957334": { + "balance": "2000000000000000000000" + }, + "949f84f0b1d7c4a7cf49ee7f8b2c4a134de32878": { + "balance": "685000000000000000000" + }, + "edbac9527b54d6df7ae2e000cca3613ba015cae3": { + "balance": "1970000000000000000000" + }, + "c697b70477cab42e2b8b266681f4ae7375bb2541": { + "balance": "5577200000000000000000" + }, + "86c934e38e53be3b33f274d0539cfca159a4d0d1": { + "balance": "970000000000000000000" + }, + "0877eeaeab78d5c00e83c32b2d98fa79ad51482f": { + "balance": "439420000000000000000" + }, + "5e11ecf69d551d7f4f84df128046b3a13240a328": { + "balance": "20000000000000000000" + }, + "43ff8853e98ed8406b95000ada848362d6a0392a": { + "balance": "22100000000000000000000" + }, + "f11cf5d363746fee6864d3ca336dd80679bb87ae": { + "balance": "40000000000000000000000" + }, + "fb223c1e22eac1269b32ee156a5385922ed36fb8": { + "balance": "2000000000000000000000" + }, + "4e6600806289454acda330a2a3556010dfacade6": { + "balance": "6000000000000000000000" + }, + "cfe2caaf3cec97061d0939748739bffe684ae91f": { + "balance": "10000000000000000000000" + }, + "adeb52b604e5f77faaac88275b8d6b49e9f9f97f": { + "balance": "2089268000000000000000" + }, + "d53c567f0c3ff2e08b7d59e2b5c73485437fc58d": { + "balance": "600000000000000000000" + }, + "fbf75933e01b75b154ef0669076be87f62dffae1": { + "balance": "78000000000000000000000" + }, + "7dfd2962b575bcbeee97f49142d63c30ab009f66": { + "balance": "4000000000000000000000" + }, + "df6485c4297ac152b289b19dde32c77ec417f47d": { + "balance": "1000000000000000000000" + }, + "ffb974673367f5c07be5fd270dc4b7138b074d57": { + "balance": "2470407000000000000000" + }, + "f7d7af204c56f31fd94398e40df1964bd8bf123c": { + "balance": "150011000000000000000" + }, + "4506fe19fa4b006baa3984529d8516db2b2b50ab": { + "balance": "2000000000000000000000" + }, + "f4dc7ba85480bbb3f535c09568aaa3af6f3721c6": { + "balance": "7214962000000000000000" + }, + "d171c3f2258aef35e599c7da1aa07300234da9a6": { + "balance": "2000000000000000000000" + }, + "33581cee233088c0860d944e0cf1ceabb8261c2e": { + "balance": "13370000000000000000" + }, + "1c2e3607e127caca0fbd5c5948adad7dd830b285": { + "balance": "19700000000000000000000" + }, + "fd7ede8f5240a06541eb699d782c2f9afb2170f6": { + "balance": "1337000000000000000000" + }, + "368c5414b56b8455171fbf076220c1cba4b5ca31": { + "balance": "557940000000000000000" + }, + "3e8745ba322f5fd6cb50124ec46688c7a69a7fae": { + "balance": "4925000000000000000000" + }, + "76506eb4a780c951c74a06b03d3b8362f0999d71": { + "balance": "500000000000000000000" + }, + "96d62dfd46087f62409d93dd606188e70e381257": { + "balance": "2000000000000000000000" + }, + "37eada93c475ded2f7e15e7787d400470fa52062": { + "balance": "200000000000000000000" + }, + "26babf42b267fdcf3861fdd4236a5e474848b358": { + "balance": "1000000000000000000000" + }, + "3526eece1a6bdc3ee7b400fe935b48463f31bed7": { + "balance": "82400000000000000000" + }, + "27b62816e1e3b8d19b79d1513d5dfa855b0c3a2a": { + "balance": "99941000000000000000" + }, + "b3e3c439069880156600c2892e448d4136c92d9b": { + "balance": "850000000000000000000" + }, + "574ad9355390e4889ef42acd138b2a27e78c00ae": { + "balance": "1557000000000000000000" + }, + "f0b9d683cea12ba600baace219b0b3c97e8c00e4": { + "balance": "100000000000000000000" + }, + "a437fe6ec103ca8d158f63b334224eccac5b3ea3": { + "balance": "8000000000000000000000" + }, + "7a48d877b63a8f8f9383e9d01e53e80c528e955f": { + "balance": "8000000000000000000000" + }, + "e965daa34039f7f0df62375a37e5ab8a72b301e7": { + "balance": "4796000000000000000000" + }, + "72cd048a110574482983492dfb1bd27942a696ba": { + "balance": "2000000000000000000000" + }, + "6611ce59a98b072ae959dc49ad511daaaaa19d6b": { + "balance": "200000000000000000000" + }, + "0d92582fdba05eabc3e51538c56db8813785b328": { + "balance": "191000000000000000000" + }, + "e87e9bbfbbb71c1a740c74c723426df55d063dd9": { + "balance": "7998000000000000000000" + }, + "9c99a1da91d5920bc14e0cb914fdf62b94cb8358": { + "balance": "20000000000000000000000" + }, + "fe8e6e3665570dff7a1bda697aa589c0b4e9024a": { + "balance": "2000000000000000000000" + }, + "811461a2b0ca90badac06a9ea16e787b33b196cc": { + "balance": "164000000000000000000" + }, + "d211b21f1b12b5096181590de07ef81a89537ead": { + "balance": "2000000000000000000000" + }, + "01155057002f6b0d18acb9388d3bc8129f8f7a20": { + "balance": "1340000000000000000000" + }, + "8ce22f9fa372449a420610b47ae0c8d565481232": { + "balance": "2000000000000000000000" + }, + "e02b74a47628be315b1f76b315054ad44ae9716f": { + "balance": "4000000000000000000000" + }, + "92a7c5a64362e9f842a23deca21035857f889800": { + "balance": "1999944000000000000000" + }, + "5213f459e078ad3ab95a0920239fcf1633dc04ca": { + "balance": "2599989000000000000000" + }, + "c9957ba94c1b29e5277ec36622704904c63dc023": { + "balance": "1923000000000000000000" + }, + "6ac40f532dfee5118117d2ad352da77d4f6da2c8": { + "balance": "400000000000000000000" + }, + "ea1efb3ce789bedec3d67c3e1b3bc0e9aa227f90": { + "balance": "734000000000000000000" + }, + "b01e389b28a31d8e4995bdd7d7c81beeab1e4119": { + "balance": "1000000000000000000000" + }, + "ee97aa8ac69edf7a987d6d70979f8ec1fbca7a94": { + "balance": "376000000000000000000" + }, + "0fad05507cdc8f24b2be4cb7fa5d927ddb911b88": { + "balance": "3004447000000000000000" + }, + "b6e8afd93dfa9af27f39b4df06076710bee3dfab": { + "balance": "25000000000000000000" + }, + "7d0b255efb57e10f7008aa22d40e9752dfcf0378": { + "balance": "29944000000000000000" + }, + "aef5b12258a18dec07d5ec2e316574919d79d6d6": { + "balance": "2000000000000000000000" + }, + "63666755bd41b5986997783c13043008242b3cb5": { + "balance": "500000000000000000000" + }, + "921f5261f4f612760706892625c75e7bce96b708": { + "balance": "2000000000000000000000" + }, + "10e1e3377885c42d7df218522ee7766887c05e6a": { + "balance": "300031000000000000000" + }, + "134163be9fbbe1c5696ee255e90b13254395c318": { + "balance": "200000000000000000000" + }, + "870f15e5df8b0eabd02569537a8ef93b56785c42": { + "balance": "388000000000000000000" + }, + "68eec1e288ac31b6eaba7e1fbd4f04ad579a6b5d": { + "balance": "2000000000000000000000" + }, + "1a2694ec07cf5e4d68ba40f3e7a14c53f3038c6e": { + "balance": "1000073000000000000000" + }, + "cd9b4cef73390c83a8fd71d7b540a7f9cf8b8c92": { + "balance": "90000000000000000000" + }, + "c8de7a564c7f4012a6f6d10fd08f47890fbf07d4": { + "balance": "300000000000000000000" + }, + "c0345b33f49ce27fe82cf7c84d141c68f590ce76": { + "balance": "1000000000000000000000" + }, + "fe53b94989d89964da2061539526bbe979dd2ea9": { + "balance": "1930600000000000000000" + }, + "14410fb310711be074a80883c635d0ef6afb2539": { + "balance": "2000000000000000000000" + }, + "1d344e962567cb27e44db9f2fac7b68df1c1e6f7": { + "balance": "1940000000000000000000" + }, + "fe016ec17ec5f10e3bb98ff4a1eda045157682ab": { + "balance": "375804000000000000000" + }, + "e89da96e06beaf6bd880b378f0680c43fd2e9d30": { + "balance": "601400000000000000000" + }, + "0fee81ac331efd8f81161c57382bb4507bb9ebec": { + "balance": "400030000000000000000" + }, + "40cf90ef5b768c5da585002ccbe6617650d8e837": { + "balance": "999800000000000000000" + }, + "256fa150cc87b5056a07d004efc84524739e62b5": { + "balance": "200000000000000000000" + }, + "1b9b2dc2960e4cb9408f7405827c9b59071612fd": { + "balance": "1000000000000000000000" + }, + "0efd1789eb1244a3dede0f5de582d8963cb1f39f": { + "balance": "1500000000000000000000" + }, + "049c5d4bc6f25d4e456c697b52a07811ccd19fb1": { + "balance": "300048000000000000000" + }, + "02b7b1d6b34ce053a40eb65cd4a4f7dddd0e9f30": { + "balance": "685000000000000000000" + }, + "c1827686c0169485ec15b3a7c8c01517a2874de1": { + "balance": "40000000000000000000" + }, + "d8e5c9675ef4deed266b86956fc4590ea7d4a27d": { + "balance": "1000000000000000000000" + }, + "48f883e567b436a27bb5a3124dbc84dec775a800": { + "balance": "771840000000000000000" + }, + "a34076f84bd917f20f8342c98ba79e6fb08ecd31": { + "balance": "4200000000000000000000" + }, + "21ce6d5b9018cec04ad6967944bea39e8030b6b8": { + "balance": "20000000000000000000" + }, + "0596a27dc3ee115fce2f94b481bc207a9e261525": { + "balance": "1000000000000000000000" + }, + "717cf9beab3638308ded7e195e0c86132d163fed": { + "balance": "15097428000000000000000" + }, + "d5ce55d1b62f59433c2126bcec09bafc9dfaa514": { + "balance": "197000000000000000000" + }, + "7dd46da677e161825e12e80dc446f58276e1127c": { + "balance": "820000000000000000000" + }, + "98c5494a03ac91a768dffc0ea1dde0acbf889019": { + "balance": "200000000000000000000000" + }, + "617ff2cc803e31c9082233b825d025be3f7b1056": { + "balance": "1970000000000000000000" + }, + "1091176be19b9964a8f72e0ece6bf8e3cfad6e9c": { + "balance": "10020000000000000000000" + }, + "4ea56e1112641c038d0565a9c296c463afefc17e": { + "balance": "182000000000000000000" + }, + "e303167f3d4960fe881b32800a2b4aeff1b088d4": { + "balance": "2000000000000000000000" + }, + "773141127d8cf318aebf88365add3d5527d85b6a": { + "balance": "1000076000000000000000" + }, + "b916b1a01cdc4e56e7657715ea37e2a0f087d106": { + "balance": "2406017000000000000000" + }, + "46a430a2d4a894a0d8aa3feac615361415c3f81f": { + "balance": "2000000000000000000000" + }, + "e6a3010f0201bc94ff67a2f699dfc206f9e76742": { + "balance": "879088000000000000000" + }, + "d7ad09c6d32657685355b5c6ec8e9f57b4ebb982": { + "balance": "1970000000000000000000" + }, + "95e80a82c20cbe3d2060242cb92d735810d034a2": { + "balance": "32511000000000000000" + }, + "9a390162535e398877e416787d6239e0754e937c": { + "balance": "1000000000000000000000" + }, + "d85fdeaf2a61f95db902f9b5a53c9b8f9266c3ac": { + "balance": "2010000000000000000000" + }, + "c3e20c96df8d4e38f50b265a98a906d61bc51a71": { + "balance": "2000000000000000000000" + }, + "2949fd1def5c76a286b3872424809a07db3966f3": { + "balance": "5236067000000000000000" + }, + "86cdb7e51ac44772be3690f61d0e59766e8bfc18": { + "balance": "4000000000000000000000" + }, + "749a4a768b5f237248938a12c623847bd4e688dc": { + "balance": "72000000000000000000" + }, + "3524a000234ebaaf0789a134a2a417383ce5282a": { + "balance": "5635000000000000000000" + }, + "7b43c7eea8d62355b0a8a81da081c6446b33e9e0": { + "balance": "4000000000000000000000" + }, + "0eb189ef2c2d5762a963d6b7bdf9698ea8e7b48a": { + "balance": "1337000000000000000000" + }, + "767fd7797d5169a05f7364321c19843a8c348e1e": { + "balance": "18800000000000000000" + }, + "1b2639588b55c344b023e8de5fd4087b1f040361": { + "balance": "1500000000000000000000" + }, + "1e33d1c2fb5e084f2f1d54bc5267727fec3f985d": { + "balance": "500000000000000000000" + }, + "06b106649aa8c421ddcd1b8c32cd0418cf30da1f": { + "balance": "40000000000000000000000" + }, + "3c5a241459c6abbf630239c98a30d20b8b3ac561": { + "balance": "157600000000000000000" + }, + "0f4f94b9191bb7bb556aaad7c74ddb288417a50b": { + "balance": "1400000000000000000000" + }, + "d6f4a7d04e8faf20e8c6eb859cf7f78dd23d7a15": { + "balance": "131784000000000000000" + }, + "61adf5929a5e2981684ea243baa01f7d1f5e148a": { + "balance": "110302000000000000000" + }, + "8f58d8348fc1dc4e0dd8343b6543c857045ee940": { + "balance": "13632400000000000000000" + }, + "a6e3baa38e104a1e27a4d82869afb1c0ae6eff8d": { + "balance": "19690000000000000000" + }, + "67350b5331926f5e28f3c1e986f96443809c8b8c": { + "balance": "352000000000000000000" + }, + "0b5d66b13c87b392e94d91d5f76c0d450a552843": { + "balance": "2000000000000000000000" + }, + "562a8dcbbeeef7b360685d27303bd69e094accf6": { + "balance": "10000000000000000000000" + }, + "b5d9934d7b292bcf603b2880741eb760288383a0": { + "balance": "16700000000000000000" + }, + "6fc53662371dca587b59850de78606e2359df383": { + "balance": "180000000000000000000" + }, + "e069c0173352b10bf6834719db5bed01adf97bbc": { + "balance": "18894000000000000000" + }, + "10a93457496f1108cd98e140a1ecdbae5e6de171": { + "balance": "399600000000000000000" + }, + "69ff8901b541763f817c5f2998f02dcfc1df2997": { + "balance": "40000000000000000000" + }, + "00c27d63fde24b92ee8a1e7ed5d26d8dc5c83b03": { + "balance": "2000000000000000000000" + }, + "77f81b1b26fc84d6de97ef8b9fbd72a33130cc4a": { + "balance": "1000000000000000000000" + }, + "6d20ef9704670a500bb269b5832e859802049f01": { + "balance": "130000000000000000000" + }, + "186afdc085f2a3dce4615edffbadf71a11780f50": { + "balance": "200000000000000000000" + }, + "7ff0c63f70241bece19b737e5341b12b109031d8": { + "balance": "346000000000000000000" + }, + "9d4174aa6af28476e229dadb46180808c67505c1": { + "balance": "1219430000000000000000" + }, + "5fec49c665e64ee89dd441ee74056e1f01e92870": { + "balance": "6320000000000000000000" + }, + "6cd228dc712169307fe27ceb7477b48cfc8272e5": { + "balance": "77600000000000000000" + }, + "fd918536a8efa6f6cefe1fa1153995fef5e33d3b": { + "balance": "500000000000000000000" + }, + "2fbb504a5dc527d3e3eb0085e2fc3c7dd538cb7a": { + "balance": "1249961000000000000000" + }, + "6ab323ae5056ed0a453072c5abe2e42fcf5d7139": { + "balance": "880000000000000000000" + }, + "67d682a282ef73fb8d6e9071e2614f47ab1d0f5e": { + "balance": "1000000000000000000000" + }, + "1858cf11aea79f5398ad2bb22267b5a3c952ea74": { + "balance": "9850000000000000000000" + }, + "39d6caca22bccd6a72f87ee7d6b59e0bde21d719": { + "balance": "2002000000000000000000" + }, + "daa63cbda45dd487a3f1cd4a746a01bb5e060b90": { + "balance": "4797800000000000000000" + }, + "a90476e2efdfee4f387b0f32a50678b0efb573b5": { + "balance": "10000000000000000000000" + }, + "ae5aa1e6c2b60f6fd3efe721bb4a719cbe3d6f5d": { + "balance": "795860000000000000000" + }, + "ac2e766dac3f648f637ac6713fddb068e4a4f04d": { + "balance": "197000000000000000000" + }, + "6191ddc9b64a8e0890b4323709d7a07c48b92a64": { + "balance": "775000000000000000000" + }, + "cc4f0ff2aeb67d54ce3bc8c6510b9ae83e9d328b": { + "balance": "400000000000000000000" + }, + "ca23f62dff0d6460036c62e840aec5577e0befd2": { + "balance": "140800000000000000000" + }, + "97dc26ec670a31e0221d2a75bc5dc9f90c1f6fd4": { + "balance": "50000000000000000000" + }, + "848c994a79003fe7b7c26cc63212e1fc2f9c19eb": { + "balance": "2000000000000000000000" + }, + "20c284ba10a20830fc3d699ec97d2dfa27e1b95e": { + "balance": "2000000000000000000000" + }, + "4fa3f32ef4086448b344d5f0a9890d1ce4d617c3": { + "balance": "1500000000000000000000" + }, + "255abc8d08a096a88f3d6ab55fbc7352bddcb9ce": { + "balance": "82161000000000000000" + }, + "7c60e51f0be228e4d56fdd2992c814da7740c6bc": { + "balance": "200000000000000000000" + }, + "1c356cfdb95febb714633b28d5c132dd84a9b436": { + "balance": "25000000000000000000" + }, + "5062e5134c612f12694dbd0e131d4ce197d1b6a4": { + "balance": "1000000000000000000000" + }, + "ed862616fcbfb3becb7406f73c5cbff00c940755": { + "balance": "1700000000000000000000" + }, + "62c9b271ffd5b770a5eee4edc9787b5cdc709714": { + "balance": "2000000000000000000000" + }, + "3c925619c9b33144463f0537d896358706c520b0": { + "balance": "2000000000000000000000" + }, + "ffe2e28c3fb74749d7e780dc8a5d422538e6e451": { + "balance": "253319000000000000000" + }, + "37195a635dcc62f56a718049d47e8f9f96832891": { + "balance": "1970000000000000000000" + }, + "90e9a9a82edaa814c284d232b6e9ba90701d4952": { + "balance": "100007000000000000000" + }, + "e0c4ab9072b4e6e3654a49f8a8db026a4b3386a9": { + "balance": "2000000000000000000000" + }, + "439dee3f7679ff1030733f9340c096686b49390b": { + "balance": "2000000000000000000000" + }, + "548558d08cfcb101181dac1eb6094b4e1a896fa6": { + "balance": "1999944000000000000000" + }, + "3090f8130ec44466afadb36ed3c926133963677b": { + "balance": "4000000000000000000000" + }, + "d1648503b1ccc5b8be03fa1ec4f3ee267e6adf7b": { + "balance": "5828000000000000000000" + }, + "65b42faecc1edfb14283ca979af545f63b30e60c": { + "balance": "18200000000000000000" + }, + "6420f8bcc8164a6152a99d6b99693005ccf7e053": { + "balance": "999972000000000000000" + }, + "84b4b74e6623ba9d1583e0cfbe49643f16384149": { + "balance": "20000000000000000000" + }, + "b8310a16cc6abc465007694b930f978ece1930bd": { + "balance": "740000000000000000000" + }, + "16019a4dafab43f4d9bf4163fae0847d848afca2": { + "balance": "25060000000000000000" + }, + "479298a9de147e63a1c7d6d2fce089c7e64083bd": { + "balance": "9999999000000000000000" + }, + "030973807b2f426914ad00181270acd27b8ff61f": { + "balance": "5348000000000000000000" + }, + "b07bcf1cc5d4462e5124c965ecf0d70dc27aca75": { + "balance": "1600000000000000000000" + }, + "a2f798e077b07d86124e1407df32890dbb4b6379": { + "balance": "200000000000000000000" + }, + "0cbd921dbe121563b98a6871fecb14f1cc7e88d7": { + "balance": "200000000000000000000" + }, + "6042276df2983fe2bc4759dc1943e18fdbc34f77": { + "balance": "1970000000000000000000" + }, + "be2b2280523768ea8ac35cd9e888d60a719300d4": { + "balance": "2000000000000000000000" + }, + "2f4da753430fc09e73acbccdcde9da647f2b5d37": { + "balance": "200000000000000000000" + }, + "734223d27ff23e5906caed22595701bb34830ca1": { + "balance": "2000000000000000000000" + }, + "5b430d779696a3653fc60e74fbcbacf6b9c2baf1": { + "balance": "14000000000000000000000" + }, + "84232107932b12e03186583525ce023a703ef8d9": { + "balance": "2000000000000000000000" + }, + "4ed14d81b60b23fb25054d8925dfa573dcae6168": { + "balance": "340000000000000000000" + }, + "8b338411f26ccf37658cc75521d77629099e467d": { + "balance": "2000000000000000000000" + }, + "a37622ac9bbdc4d82b75015d745b9f8de65a28ec": { + "balance": "2910000000000000000000" + }, + "1dd77441844afe9cc18f15d8c77bccfb655ee034": { + "balance": "4850000000000000000000" + }, + "65849be1af20100eb8a3ba5a5be4d3ae8db5a70e": { + "balance": "400000000000000000000" + }, + "d5586da4e59583c8d86cccf71a86197f17996749": { + "balance": "2000000000000000000000" + }, + "4b53ae59c784b6b5c43616b9a0809558e684e10c": { + "balance": "1200000000000000000000" + }, + "55d42eb495bf46a634997b5f2ea362814918e2b0": { + "balance": "106128000000000000000" + }, + "959ff17f1d51b473b44010052755a7fa8c75bd54": { + "balance": "1970000000000000000000" + }, + "5a2daab25c31a61a92a4c82c9925a1d2ef58585e": { + "balance": "225400000000000000000" + }, + "24c0c88b54a3544709828ab4ab06840559f6c5e2": { + "balance": "2674000000000000000000" + }, + "7e8649e690fc8c1bfda1b5e186581f649b50fe33": { + "balance": "98500000000000000000" + }, + "4acfa9d94eda6625c9dfa5f9f4f5d107c4031fdf": { + "balance": "39400000000000000000" + }, + "5778ffdc9b94c5a59e224eb965b6de90f222d170": { + "balance": "335320000000000000000" + }, + "825a7f4e10949cb6f8964268f1fa5f57e712b4c4": { + "balance": "20000000000000000000" + }, + "6f39cc37caaa2ddc9b610f6131e0619fae772a3c": { + "balance": "500000000000000000000" + }, + "5b437365ae3a9a2ff97c68e6f90a7620188c7d19": { + "balance": "2002000000000000000000" + }, + "6710c2c03c65992b2e774be52d3ab4a6ba217ef7": { + "balance": "11600000000000000000000" + }, + "896e335ca47af57962fa0f4dbf3e45e688cba584": { + "balance": "1368500000000000000000" + }, + "b57549bfbc9bdd18f736b22650e48a73601fa65c": { + "balance": "446000000000000000000" + }, + "85ca1e727e9d1a87991cc2c41840ebb9edf21d1b": { + "balance": "13370000000000000000" + }, + "cf4166746e1d3bc1f8d0714b01f17e8a62df1464": { + "balance": "1004700000000000000000" + }, + "4a75c3d4fa6fccbd5dd5a703c15379a1e783e9b7": { + "balance": "1820000000000000000000" + }, + "9e5811b40be1e2a1e1d28c3b0774acde0a09603d": { + "balance": "3000000000000000000000" + }, + "763886e333c56feff85be3951ab0b889ce262e95": { + "balance": "2000000000000000000000" + }, + "2b101e822cd962962a06800a2c08d3b15d82b735": { + "balance": "152000000000000000000" + }, + "a01e9476df84431825c836e8803a97e22fa5a0cd": { + "balance": "6000000000000000000000" + }, + "be4e7d983f2e2a636b1102ec7039efebc842e98d": { + "balance": "66000000000000000000" + }, + "9e427272516b3e67d4fcbf82f59390d04c8e28e5": { + "balance": "4000000000000000000000" + }, + "e0d231e144ec9107386c7c9b02f1702ceaa4f700": { + "balance": "5000057000000000000000" + }, + "6a0f056066c2d56628850273d7ecb7f8e6e9129e": { + "balance": "5000016000000000000000" + }, + "d1538e9a87e59ca9ec8e5826a5b793f99f96c4c3": { + "balance": "1000000000000000000000" + }, + "f85bab1cb3710fc05fa19ffac22e67521a0ba21d": { + "balance": "2003000000000000000000" + }, + "f7cbdba6be6cfe68dbc23c2b0ff530ee05226f84": { + "balance": "20000000000000000000" + }, + "4eb87ba8788eba0df87e5b9bd50a8e45368091c1": { + "balance": "20000000000000000000" + }, + "1479a9ec7480b74b5db8fc499be352da7f84ee9c": { + "balance": "1000000000000000000000" + }, + "d311bcd7aa4e9b4f383ff3d0d6b6e07e21e3705d": { + "balance": "200000000000000000000" + }, + "425c1816868f7777cc2ba6c6d28c9e1e796c52b3": { + "balance": "10000000000000000000000" + }, + "8510ee934f0cbc900e1007eb38a21e2a5101b8b2": { + "balance": "106000000000000000000" + }, + "01e864d354741b423e6f42851724468c74f5aa9c": { + "balance": "20000000000000000000000" + }, + "a543a066fb32a8668aa0736a0c9cd40d78098727": { + "balance": "1000000000000000000000" + }, + "f3eb1948b951e22df1617829bf3b8d8680ec6b68": { + "balance": "4000000000000000000000" + }, + "f6b782f4dcd745a6c0e2e030600e04a24b25e542": { + "balance": "400000000000000000000" + }, + "229f4f1a2a4f540774505b4707a81de44410255b": { + "balance": "2000000000000000000000" + }, + "cff8d06b00e3f50c191099ad56ba6ae26571cd88": { + "balance": "1000000000000000000000" + }, + "910b7d577a7e39aa23acf62ad7f1ef342934b968": { + "balance": "10000000000000000000000" + }, + "392433d2ce83d3fb4a7602cca3faca4ec140a4b0": { + "balance": "51000000000000000000" + }, + "8ff46045687723dc33e4d099a06904f1ebb584dc": { + "balance": "2000000000000000000000" + }, + "9ca0429f874f8dcee2e9c062a9020a842a587ab9": { + "balance": "2000000000000000000000" + }, + "160ceb6f980e04315f53c4fc988b2bf69e284d7d": { + "balance": "19100000000000000000" + }, + "c340f9b91c26728c31d121d5d6fc3bb56d3d8624": { + "balance": "2000000000000000000000" + }, + "afa1d5ad38fed44759c05b8993c1aa0dace19f40": { + "balance": "80000000000000000000" + }, + "3969b4f71bb8751ede43c016363a7a614f76118e": { + "balance": "2000000000000000000000" + }, + "2bb6f578adfbe7b2a116b3554facf9969813c319": { + "balance": "7400000000000000000000" + }, + "8334764b7b397a4e578f50364d60ce44899bff94": { + "balance": "92500000000000000000" + }, + "9dd2196624a1ddf14a9d375e5f07152baf22afa2": { + "balance": "1211747000000000000000" + }, + "f242da845d42d4bf779a00f295b40750fe49ea13": { + "balance": "1000000000000000000000" + }, + "c6234657a807384126f8968ca1708bb07baa493c": { + "balance": "20000000000000000000" + }, + "94c055e858357aaa30cf2041fa9059ce164a1f91": { + "balance": "19999000000000000000000" + }, + "74c73c90528a157336f1e7ea20620ae53fd24728": { + "balance": "8969310000000000000000" + }, + "19e7f3eb7bf67f3599209ebe08b62ad3327f8cde": { + "balance": "2000000000000000000000" + }, + "b2b516fdd19e7f3864b6d2cf1b252a4156f1b03b": { + "balance": "53720000000000000000" + }, + "8164e78314ae16b28926cc553d2ccb16f356270d": { + "balance": "8450000000000000000000" + }, + "4d828894752f6f25175daf2177094487954b6f9f": { + "balance": "1459683000000000000000" + }, + "ab84a0f147ad265400002b85029a41fc9ce57f85": { + "balance": "1000000000000000000000" + }, + "f3fe51fde34413c73318b9c85437fe7e820f561a": { + "balance": "1003200000000000000000" + }, + "16c7b31e8c376282ac2271728c31c95e35d952c3": { + "balance": "2000000000000000000000" + }, + "80d5c40c59c7f54ea3a55fcfd175471ea35099b3": { + "balance": "1000000000000000000000" + }, + "7abb10f5bd9bc33b8ec1a82d64b55b6b18777541": { + "balance": "20000000000000000000000" + }, + "095b0ea2b218d82e0aea7c2889238a39c9bf9077": { + "balance": "20000000000000000000000" + }, + "5d5cdbe25b2a044b7b9be383bcaa5807b06d3c6b": { + "balance": "2000000000000000000000" + }, + "323749a3b971959e46c8b4822dcafaf7aaf9bd6e": { + "balance": "20064000000000000000" + }, + "e0272213e8d2fd3e96bd6217b24b4ba01b617079": { + "balance": "20000000000000000000" + }, + "00acbfb2f25a5485c739ef70a44eeeeb7c65a66f": { + "balance": "100000000000000000000" + }, + "52f15423323c24f19ae2ab673717229d3f747d9b": { + "balance": "1026115000000000000000" + }, + "cb4abfc282aed76e5d57affda542c1f382fcacf4": { + "balance": "8136100000000000000000" + }, + "f71b4534f286e43093b1e15efea749e7597b8b57": { + "balance": "104410000000000000000000" + }, + "44cd77535a893fa7c4d5eb3a240e79d099a72d2d": { + "balance": "820000000000000000000" + }, + "eb3ce7fc381c51db7d5fbd692f8f9e058a4c703d": { + "balance": "200000000000000000000" + }, + "f1c8c4a941b4628c0d6c30fda56452d99c7e1b64": { + "balance": "1449000000000000000000" + }, + "277677aba1e52c3b53bfa2071d4e859a0af7e8e1": { + "balance": "1000000000000000000000" + }, + "a5f075fd401335577b6683c281e6d101432dc6e0": { + "balance": "2680000000000000000000" + }, + "e28dbc8efd5e416a762ec0e018864bb9aa83287b": { + "balance": "24533161000000000000000" + }, + "2b717cd432a323a4659039848d3b87de26fc9546": { + "balance": "500000000000000000000000" + }, + "b358e97c70b605b1d7d729dfb640b43c5eafd1e7": { + "balance": "20000000000000000000000" + }, + "293c2306df3604ae4fda0d207aba736f67de0792": { + "balance": "200000000000000000000" + }, + "74d366b07b2f56477d7c7077ac6fe497e0eb6559": { + "balance": "5000000000000000000000" + }, + "490145afa8b54522bb21f352f06da5a788fa8f1d": { + "balance": "9231182000000000000000" + }, + "862569211e8c6327b5415e3a67e5738b15baaf6e": { + "balance": "140000000000000000000" + }, + "5a74ba62e7c81a3474e27d894fed33dd24ad95fe": { + "balance": "18200000000000000000" + }, + "536e4d8029b73f5579dca33e70b24eba89e11d7e": { + "balance": "1970000000000000000000" + }, + "25c6e74ff1d928df98137af4df8430df24f07cd7": { + "balance": "390000000000000000000" + }, + "19b36b0c87ea664ed80318dc77b688dde87d95a5": { + "balance": "1948386000000000000000" + }, + "abc4caeb474d4627cb6eb456ecba0ecd08ed8ae1": { + "balance": "3940000000000000000000" + }, + "8ea656e71ec651bfa17c5a5759d86031cc359977": { + "balance": "100000000000000000000" + }, + "8d620bde17228f6cbba74df6be87264d985cc179": { + "balance": "100000000000000000000" + }, + "b2aa2f1f8e93e79713d92cea9ffce9a40af9c82d": { + "balance": "2000000000000000000000" + }, + "198ef1ec325a96cc354c7266a038be8b5c558f67": { + "balance": "608334724000000000000000" + }, + "6a13d5e32c1fd26d7e91ff6e053160a89b2c8aad": { + "balance": "53480000000000000000" + }, + "e056bf3ff41c26256fef51716612b9d39ade999c": { + "balance": "100009000000000000000" + }, + "2c128c95d957215101f043dd8fc582456d41016d": { + "balance": "835000000000000000000" + }, + "2560b09b89a4ae6849ed5a3c9958426631714466": { + "balance": "1700000000000000000000" + }, + "d3d6e9fb82542fd29ed9ea3609891e151396b6f7": { + "balance": "54000000000000000000000" + }, + "a7607b42573bb6f6b4d4f23c7e2a26b3a0f6b6f0": { + "balance": "1610000000000000000000" + }, + "020362c3ade878ca90d6b2d889a4cc5510eed5f3": { + "balance": "1042883000000000000000" + }, + "14830704e99aaad5c55e1f502b27b22c12c91933": { + "balance": "620000000000000000000" + }, + "8030b111c6983f0485ddaca76224c6180634789f": { + "balance": "80000000000000000000" + }, + "2c5b7d7b195a371bf9abddb42fe04f2f1d9a9910": { + "balance": "200000000000000000000" + }, + "77d43fa7b481dbf3db530cfbf5fdced0e6571831": { + "balance": "2000000000000000000000" + }, + "2d90b415a38e2e19cdd02ff3ad81a97af7cbf672": { + "balance": "109800000000000000000" + }, + "2fc82ef076932341264f617a0c80dd571e6ae939": { + "balance": "7160000000000000000000" + }, + "dfe549fe8430e552c6d07cc3b92ccd43b12fb50f": { + "balance": "83620000000000000000" + }, + "1e8e689b02917cdc29245d0c9c68b094b41a9ed6": { + "balance": "2000000000000000000000" + }, + "21c3a8bba267c8cca27b1a9afabad86f607af708": { + "balance": "8940000000000000000000" + }, + "143c639752caeecf6a997d39709fc8f19878c7e8": { + "balance": "1970000000000000000000" + }, + "02603d7a3bb297c67c877e5d34fbd5b913d4c63a": { + "balance": "20000000000000000000" + }, + "a166f911c644ac3213d29e0e1ae010f794d5ad26": { + "balance": "2000000000000000000000" + }, + "6eb3819617404058268f0c3cff3596bfe9148c1c": { + "balance": "1670000000000000000000" + }, + "7a67dd043a504fc2f2fc7194e9becf484cecb1fb": { + "balance": "250000000000000000000" + }, + "f824ee331e4ac3cc587693395b57ecf625a6c0c2": { + "balance": "1600930000000000000000" + }, + "1179c60dbd068b150b074da4be23033b20c68558": { + "balance": "680000000000000000000" + }, + "d2a479404347c5543aab292ae1bb4a6f158357fa": { + "balance": "4000000000000000000000" + }, + "b0d32bd7e4e695b7b01aa3d0416f80557dba9903": { + "balance": "16300000000000000000000" + }, + "f734ec03724ddee5bb5279aa1afcf61b0cb448a1": { + "balance": "4238080000000000000000" + }, + "c04069dfb18b096c7867f8bee77a6dc7477ad062": { + "balance": "2674000000000000000000" + }, + "80c53ee7e3357f94ce0d7868009c208b4a130125": { + "balance": "2000000000000000000000" + }, + "0f32d9cb4d0fdaa0150656bb608dcc43ed7d9301": { + "balance": "753978000000000000000" + }, + "6ddb6092779d5842ead378e21e8120fd4c6bc132": { + "balance": "2000000000000000000000" + }, + "82ea01e3bf2e83836e71704e22a2719377efd9c3": { + "balance": "3040000000000000000000" + }, + "44c1110b18870ec81178d93d215838c551d48e64": { + "balance": "199958000000000000000" + }, + "7727af101f0aaba4d23a1cafe17c6eb5dab1c6dc": { + "balance": "2000000000000000000000" + }, + "a11a03c4bb26d21eff677d5d555c80b25453ee7a": { + "balance": "69979000000000000000" + }, + "19e5dea3370a2c746aae34a37c531f41da264e83": { + "balance": "200000000000000000000" + }, + "c325c352801ba883b3226c5feb0df9eae2d6e653": { + "balance": "3940000000000000000000" + }, + "ae5055814cb8be0c117bb8b1c8d2b63b4698b728": { + "balance": "32035000000000000000" + }, + "deb1bc34d86d4a4dde2580d8beaf074eb0e1a244": { + "balance": "1580000000000000000000" + }, + "558360206883dd1b6d4a59639e5629d0f0c675d0": { + "balance": "2000000000000000000000" + }, + "a9d6f871ca781a759a20ac3adb972cf12829a208": { + "balance": "925000000000000000000" + }, + "b0ac4eff6680ee14169cdadbffdb30804f6d25f5": { + "balance": "2000000000000000000000" + }, + "f1b58faffa8794f50af8e88309c7a6265455d51a": { + "balance": "999800000000000000000" + }, + "a61a54df784a44d71b771b87317509211381f200": { + "balance": "1000000000000000000000" + }, + "baa4b64c2b15b79f5f204246fd70bcbd86e4a92a": { + "balance": "500000000000000000000" + }, + "a20d8ff60caae31d02e0b665fa435d76f77c9442": { + "balance": "489600000000000000000" + }, + "f3e74f470c7d3a3f0033780f76a89f3ef691e6cb": { + "balance": "3021800000000000000000" + }, + "d330728131fe8e3a15487a34573c93457e2afe95": { + "balance": "4000000000000000000000" + }, + "9af9dbe47422d177f945bdead7e6d82930356230": { + "balance": "3940000000000000000000" + }, + "0eb5b662a1c718608fd52f0c25f9378830178519": { + "balance": "6091400000000000000000" + }, + "fda6810ea5ac985d6ffbf1c511f1c142edcfddf7": { + "balance": "4000000000000000000000" + }, + "832c54176bdf43d2c9bcd7b808b89556b89cbf31": { + "balance": "200000000000000000000" + }, + "704d5de4846d39b53cd21d1c49f096db5c19ba29": { + "balance": "152000000000000000000" + }, + "344a8db086faed4efc37131b3a22b0782dad7095": { + "balance": "500000000000000000000" + }, + "8c7fa5cae82fedb69ab189d3ff27ae209293fb93": { + "balance": "400030000000000000000" + }, + "ad660dec825522a9f62fcec3c5b731980dc286ea": { + "balance": "3000000000000000000000" + }, + "13b9b10715714c09cfd610cf9c9846051cb1d513": { + "balance": "1970000000000000000000" + }, + "40467d80e74c35407b7db51789234615fea66818": { + "balance": "388000000000000000000" + }, + "30e9d5a0088f1ddb2fd380e2a049192266c51cbf": { + "balance": "196910000000000000000" + }, + "b2d1e99af91231858e7065dd1918330dc4c747d5": { + "balance": "16700000000000000000000" + }, + "9f21302ca5096bea7402b91b0fd506254f999a3d": { + "balance": "1246832000000000000000" + }, + "d24b6644f439c8051dfc64d381b8c86c75c17538": { + "balance": "2000000000000000000000" + }, + "8228ebc087480fd64547ca281f5eace3041453b9": { + "balance": "1970000000000000000000" + }, + "29da3e35b23bb1f72f8e2258cf7f553359d24bac": { + "balance": "20000000000000000000000" + }, + "c8e558a3c5697e6fb23a2594c880b7a1b68f9860": { + "balance": "10000000000000000000000" + }, + "6b951a43274eeafc8a0903b0af2ec92bf1efc839": { + "balance": "100000000000000000000" + }, + "d015f6fcb84df7bb410e8c8f04894a881dcac237": { + "balance": "1038000000000000000000" + }, + "6ccb03acf7f53ce87aadcc21a9932de915f89804": { + "balance": "8000000000000000000000" + }, + "388c85a9b9207d8146033fe38143f6d34b595c47": { + "balance": "200000000000000000000" + }, + "429c06b487e8546abdfc958a25a3f0fba53f6f00": { + "balance": "13503000000000000000" + }, + "771507aeee6a255dc2cd9df55154062d0897b297": { + "balance": "334250000000000000000" + }, + "5a2b1c853aeb28c45539af76a00ac2d8a8242896": { + "balance": "25000000000000000000" + }, + "f4d67a9044b435b66e8977ff39a28dc4bd53729a": { + "balance": "200000000000000000000" + }, + "063759dd1c4e362eb19398951ff9f8fad1d31068": { + "balance": "10000000000000000000000" + }, + "cb58990bcd90cfbf6d8f0986f6fa600276b94e2d": { + "balance": "999925000000000000000" + }, + "6df5c84f7b909aab3e61fe0ecb1b3bf260222ad2": { + "balance": "4000000000000000000000" + }, + "deb2495d6aca7b2a6a2d138b6e1a42e2dc311fdd": { + "balance": "2000000000000000000000" + }, + "59203cc37599b648312a7cc9e06dacb589a9ae6a": { + "balance": "148689000000000000000" + }, + "fc9b347464b2f9929d807e039dae48d3d98de379": { + "balance": "14000000000000000000000" + }, + "48d2434b7a7dbbff08223b6387b05da2e5093126": { + "balance": "18000000000000000000000" + }, + "c9d76446d5aadff80b68b91b08cd9bc8f5551ac1": { + "balance": "714000000000000000000" + }, + "3d31587b5fd5869845788725a663290a49d3678c": { + "balance": "500000000000000000000" + }, + "d8715ef9176f850b2e30eb8e382707f777a6fbe9": { + "balance": "2000000000000000000000" + }, + "2c2147947ae33fb098b489a5c16bfff9abcd4e2a": { + "balance": "200000000000000000000" + }, + "d6c0d0bc93a62e257174700e10f024c8b23f1f87": { + "balance": "2000000000000000000000" + }, + "d1978f2e34407fab1dc2183d95cfda6260b35982": { + "balance": "788000000000000000000" + }, + "1bf974d9904f45ce81a845e11ef4cbcf27af719e": { + "balance": "100000000000000000000" + }, + "6e761eaa0f345f777b5441b73a0fa5b56b85f22d": { + "balance": "2000000000000000000000" + }, + "ea60436912de6bf187d3a472ff8f5333a0f7ed06": { + "balance": "19700000000000000000" + }, + "94f8f057db7e60e675ad940f155885d1a477348e": { + "balance": "401100000000000000000" + }, + "8933491760c8f0b4df8caac78ed835caee21046d": { + "balance": "20000000000000000000000" + }, + "a7775e4af6a23afa201fb78b915e51a515b7a728": { + "balance": "120000000000000000000" + }, + "d8d64384249b776794063b569878d5e3b530a4b2": { + "balance": "177569000000000000000" + }, + "be633a3737f68439bac7c90a52142058ee8e8a6f": { + "balance": "960000000000000000000" + }, + "90bd62a050845261fa4a9f7cf241ea630b05efb8": { + "balance": "500000000000000000000" + }, + "552987f0651b915b2e1e5328c121960d4bdd6af4": { + "balance": "1790000000000000000000" + }, + "0baf6ecdb91acb3606a8357c0bc4f45cfd2d7e6f": { + "balance": "1000000000000000000000" + }, + "9e5a311d9f69898a7c6a9d6360680438e67a7b2f": { + "balance": "1490000000000000000000" + }, + "78859c5b548b700d9284cee4b6633c2f52e529c2": { + "balance": "2955000000000000000000" + }, + "d572309169b1402ec8131a17a6aac3222f89e6eb": { + "balance": "13800000000000000000000" + }, + "8e6d7485cbe990acc1ad0ee9e8ccf39c0c93440e": { + "balance": "955000000000000000000" + }, + "75c11d024d12ae486c1095b7a7b9c4af3e8edeb9": { + "balance": "20000000000000000000" + }, + "903413878aea3bc1086309a3fe768b65559e8cab": { + "balance": "8000000000000000000000" + }, + "6d0569e5558fc7df2766f2ba15dc8aeffc5beb75": { + "balance": "4001070000000000000000" + }, + "3815b0743f94fc8cc8654fd9d597ed7d8b77c57e": { + "balance": "738578000000000000000" + }, + "0f26480a150961b8e30750713a94ee6f2e47fc00": { + "balance": "1000000000000000000000" + }, + "ede5de7c7fb7eee0f36e64530a41440edfbefacf": { + "balance": "617200000000000000000" + }, + "763a7cbab70d7a64d0a7e52980f681472593490c": { + "balance": "600000000000000000000" + }, + "6e270ad529f1f0b8d9cb6d2427ec1b7e2dc64a74": { + "balance": "200000000000000000000" + }, + "eb3bdd59dcdda5a9bb2ac1641fd02180f5f36560": { + "balance": "6600000000000000000000" + }, + "f4ebf50bc7e54f82e9b9bd24baef29438e259ce6": { + "balance": "10000000000000000000000" + }, + "882c8f81872c79fed521cb5f950d8b032322ea69": { + "balance": "40000000000000000000000" + }, + "394132600f4155e07f4d45bc3eb8d9fb72dcd784": { + "balance": "2941000000000000000000" + }, + "0be2b94ad950a2a62640c35bfccd6c67dae450f6": { + "balance": "1940000000000000000000" + }, + "d4c6ac742e7c857d4a05a04c33d4d05c1467571d": { + "balance": "200000000000000000000" + }, + "1fddd85fc98be9c4045961f40f93805ecc4549e5": { + "balance": "164000000000000000000" + }, + "534065361cb854fac42bfb5c9fcde0604ac919da": { + "balance": "2000000000000000000000" + }, + "9a6ff5f6a7af7b7ae0ed9c20ecec5023d281b786": { + "balance": "2547000000000000000000" + }, + "4f3a4854911145ea01c644044bdb2e5a960a982f": { + "balance": "4000000000000000000000" + }, + "00497e92cdc0e0b963d752b2296acb87da828b24": { + "balance": "194800000000000000000" + }, + "4ff67fb87f6efba9279930cfbd1b7a343c79fade": { + "balance": "400000000000000000000" + }, + "62f2e5ccecd52cc4b95e0597df27cc079715608c": { + "balance": "143000000000000000000" + }, + "1eda084e796500ba14c5121c0d90846f66e4be62": { + "balance": "534800000000000000000" + }, + "9836b4d30473641ab56aeee19242761d72725178": { + "balance": "2000000000000000000000" + }, + "de55de0458f850b37e4d78a641dd2eb2dd8f38ce": { + "balance": "4000000000000000000000" + }, + "140ca28ff33b9f66d7f1fc0078f8c1eef69a1bc0": { + "balance": "1600000000000000000000" + }, + "2014261f01089f53795630ba9dd24f9a34c2d942": { + "balance": "1337000000000000000000" + }, + "11415fab61e0dfd4b90676141a557a869ba0bde9": { + "balance": "2048000000000000000000" + }, + "88344909644c7ad4930fd873ca1c0da2d434c07f": { + "balance": "131970000000000000000" + }, + "88b217ccb786a254cf4dc57f5d9ac3c455a30483": { + "balance": "925000000000000000000" + }, + "dfdbcec1014b96da2158ca513e9c8d3b9af1c3d0": { + "balance": "2000000000000000000000" + }, + "1ba9f7997e5387b6b2aa0135ac2452fe36b4c20d": { + "balance": "850000000000000000000" + }, + "d70ad2c4e9eebfa637ef56bd486ad2a1e5bce093": { + "balance": "200000000000000000000" + }, + "9ce27f245e02d1c312c1d500788c9def7690453b": { + "balance": "200000000000000000000" + }, + "8234f463d18485501f8f85ace4972c9b632dbccc": { + "balance": "2000000000000000000000" + }, + "994152fc95d5c1ca8b88113abbad4d710e40def6": { + "balance": "500000000000000000000" + }, + "e5b980d28eece2c06fca6c9473068b37d4a6d6e9": { + "balance": "695200000000000000000" + }, + "2d426912d059fad9740b2e390a2eeac0546ff01b": { + "balance": "1400000000000000000000" + }, + "6d9997509882027ea947231424bedede2965d0ba": { + "balance": "2001600000000000000000" + }, + "167ce7de65e84708595a525497a3eb5e5a665073": { + "balance": "575400000000000000000" + }, + "e430c0024fdbf73a82e21fccf8cbd09138421c21": { + "balance": "4000000000000000000000" + }, + "2e52912bc10ea39d54e293f7aed6b99a0f4c73be": { + "balance": "400000000000000000000" + }, + "12cf8b0e465213211a5b53dfb0dd271a282c12c9": { + "balance": "15200000000000000000" + }, + "06964e2d17e9189f88a8203936b40ac96e533c06": { + "balance": "18200000000000000000" + }, + "66b1a63da4dcd9f81fe54f5e3fcb4055ef7ec54f": { + "balance": "201412000000000000000" + }, + "0a77e7f72b437b574f00128b21f2ac265133528c": { + "balance": "2000000000000000000000" + }, + "78f5c74785c5668a838072048bf8b453594ddaab": { + "balance": "400000000000000000000" + }, + "58e554af3d87629620da61d538c7f5b4b54c4afe": { + "balance": "1297081000000000000000" + }, + "37a10451f36166cf643dd2de6c1cbba8a011cfa3": { + "balance": "380000000000000000000" + }, + "fe9ad12ef05d6d90261f96c8340a0381974df477": { + "balance": "2000000000000000000000" + }, + "057f7f81cd7a406fc45994408b5049912c566463": { + "balance": "1700000000000000000000" + }, + "55a3df57b7aaec16a162fd5316f35bec082821cf": { + "balance": "1970000000000000000000" + }, + "c0e0b903088e0c63f53dd069575452aff52410c3": { + "balance": "3000000000000000000000" + }, + "63e88e2e539ffb450386b4e46789b223f5476c45": { + "balance": "6292000000000000000000" + }, + "3727341f26c12001e378405ee38b2d8464ec7140": { + "balance": "2000000000000000000000" + }, + "c96751656c0a8ef4357b7344322134b983504aca": { + "balance": "2000000000000000000000" + }, + "1e060dc6c5f1cb8cc7e1452e02ee167508b56542": { + "balance": "12715500000000000000000" + }, + "18136c9df167aa17b6f18e22a702c88f4bc28245": { + "balance": "4000000000000000000000" + }, + "116108c12084612eeda7a93ddcf8d2602e279e5c": { + "balance": "2000000000000000000000" + }, + "bbb643d2187b364afc10a6fd368d7d55f50d1a3c": { + "balance": "1000000000000000000000" + }, + "ec83e798c396b7a55e2a2224abcd834b27ea459c": { + "balance": "12000000000000000000000" + }, + "973f4e361fe5decd989d4c8f7d7cc97990385daf": { + "balance": "388500000000000000000" + }, + "c0f29ed0076611b5e55e130547e68a48e26df5e4": { + "balance": "3000000000000000000000" + }, + "fd4b551f6fdbcda6c511b5bb372250a6b783e534": { + "balance": "20600000000000000000" + }, + "144b19f1f66cbe318347e48d84b14039466c5909": { + "balance": "2000000000000000000000" + }, + "bf183641edb886ce60b8190261e14f42d93cce01": { + "balance": "25019000000000000000" + }, + "94db807873860aac3d5aea1e885e52bff2869954": { + "balance": "3220000000000000000000" + }, + "7a74cee4fa0f6370a7894f116cd00c1147b83e59": { + "balance": "800000000000000000000" + }, + "cd32a4a8a27f1cc63954aa634f7857057334c7a3": { + "balance": "1085000000000000000000" + }, + "7cbeb99932e97e6e02058cfc62d0b26bc7cca52b": { + "balance": "2000000000000000000000" + }, + "8cde8b732e6023878eb23ed16229124b5f7afbec": { + "balance": "133700000000000000000" + }, + "45c4ecb4ee891ea984a7c5cefd8dfb00310b2850": { + "balance": "1980000000000000000000" + }, + "8b393fb0813ee101db1e14ecc7d322c72b8c0473": { + "balance": "455578000000000000000" + }, + "7b66126879844dfa34fe65c9f288117fefb449ad": { + "balance": "6000000000000000000000" + }, + "162ba503276214b509f97586bd842110d103d517": { + "balance": "9002000000000000000000" + }, + "7dece6998ae1900dd3770cf4b93812bad84f0322": { + "balance": "100000000000000000000" + }, + "ec0927bac7dc36669c28354ab1be83d7eec30934": { + "balance": "2000000000000000000000" + }, + "8d7f3e61299c2db9b9c0487cf627519ed00a9123": { + "balance": "1742400000000000000000" + }, + "4fc46c396e674869ad9481638f0013630c87caac": { + "balance": "1000000000000000000000" + }, + "bf68d28aaf1eeefef646b65e8cc8d190f6c6da9c": { + "balance": "2000000000000000000000" + }, + "00969747f7a5b30645fe00e44901435ace24cc37": { + "balance": "1700000000000000000000" + }, + "494dec4d5ee88a2771a815f1ee7264942fb58b28": { + "balance": "2000000000000000000000" + }, + "ffeac0305ede3a915295ec8e61c7f881006f4474": { + "balance": "98500000000000000000" + }, + "b39139576194a0866195151f33f2140ad1cc86cf": { + "balance": "100000000000000000000000" + }, + "fead1803e5e737a68e18472d9ac715f0994cc2be": { + "balance": "500000000000000000000" + }, + "698ab9a2f33381e07c0c47433d0d21d6f336b127": { + "balance": "20000000000000000000" + }, + "e5edc73e626f5d3441a45539b5f7a398c593edf6": { + "balance": "865000000000000000000" + }, + "dd4f5fa2111db68f6bde3589b63029395b69a92d": { + "balance": "158400000000000000000" + }, + "8c93c3c6db9d37717de165c3a1b4fe51952c08de": { + "balance": "400000000000000000000" + }, + "f87bb07b289df7301e54c0efda6a2cf291e89200": { + "balance": "1400000000000000000000" + }, + "e7a4560c84b20e0fb54c49670c2903b0a96c42a4": { + "balance": "598000000000000000000" + }, + "00a5797f52c9d58f189f36b1d45d1bf6041f2f6b": { + "balance": "5456900000000000000000" + }, + "9da3302240af0511c6fd1857e6ddb7394f77ab6b": { + "balance": "3100000000000000000000" + }, + "2c2d15ff39561c1b72eda1cc027ffef23743a144": { + "balance": "3920000000000000000000" + }, + "9b4c2715780ca4e99e60ebf219f1590c8cad500a": { + "balance": "1600000000000000000000" + }, + "ff5e7ee7d5114821e159dca5e81f18f1bfffbff9": { + "balance": "2000000000000000000000" + }, + "0169c1c210eae845e56840412e1f65993ea90fb4": { + "balance": "2000000000000000000000" + }, + "abc45f84db7382dde54c5f7d8938c42f4f3a3bc4": { + "balance": "200000000000000000000" + }, + "d9383d4b6d17b3f9cd426e10fb944015c0d44bfb": { + "balance": "800000000000000000000" + }, + "c090fe23dcd86b358c32e48d2af91024259f6566": { + "balance": "200000000000000000000" + }, + "9ffedcc36b7cc312ad2a9ede431a514fccb49ba3": { + "balance": "669800000000000000000" + }, + "2ffe93ec1a5636e9ee34af70dff52682e6ff7079": { + "balance": "2000000000000000000000" + }, + "6e01e4ad569c95d007ada30d5e2db12888492294": { + "balance": "4000000000000000000000" + }, + "d4d92c62b280e00f626d8657f1b86166cb1f740f": { + "balance": "200028000000000000000" + }, + "1d36683063b7e9eb99462dabd569bddce71686f2": { + "balance": "1000000000000000000000" + }, + "3a48e0a7098b06a905802b87545731118e89f439": { + "balance": "2000000000000000000000" + }, + "bd9e56e902f4be1fc8768d8038bac63e2acbbf8e": { + "balance": "999972000000000000000" + }, + "4d67f2ab8599fef5fc413999aa01fd7fce70b43d": { + "balance": "10000000000000000000000" + }, + "8e74e0d1b77ebc823aca03f119854cb12027f6d7": { + "balance": "107200000000000000000000" + }, + "7e5b19ae1be94ff4dee635492a1b012d14db0213": { + "balance": "100000000000000000000" + }, + "5de9e7d5d1b667d095dd34099c85b0421a0bc681": { + "balance": "20000000000000000000" + }, + "316eb4e47df71b42e16d6fe46825b7327baf3124": { + "balance": "4000000000000000000000" + }, + "772c297f0ad194482ee8c3f036bdeb01c201d5cc": { + "balance": "200000000000000000000" + }, + "d7052519756af42590f15391b723a03fa564a951": { + "balance": "4615591000000000000000" + }, + "2c6846a1aa999a2246a287056000ba4dcba8e63d": { + "balance": "10020000000000000000000" + }, + "de5b005fe8daae8d1f05de3eda042066c6c4691c": { + "balance": "1100000000000000000000" + }, + "254c1ecc630c2877de8095f0a8dba1e8bf1f550c": { + "balance": "1700000000000000000000" + }, + "f8f226142a428434ab17a1864a2597f64aab2f06": { + "balance": "172473000000000000000" + }, + "a6c910ce4d494a919ccdaaa1fc3b82aa74ba06cf": { + "balance": "8000000000000000000000" + }, + "e587b16abc8a74081e3613e14342c03375bf0847": { + "balance": "2000000000000000000000" + }, + "6f176065e88e3c6fe626267d18a088aaa4db80bc": { + "balance": "3520000000000000000000" + }, + "50dcbc27bcad984093a212a9b4178eabe9017561": { + "balance": "145512000000000000000" + }, + "e1953c6e975814c571311c34c0f6a99cdf48ab82": { + "balance": "50000000000000000000" + }, + "be0a2f385f09dbfce96732e12bb40ac349871ba8": { + "balance": "1610348000000000000000" + }, + "4712540265cbeec3847022c59f1b318d43400a9e": { + "balance": "3500000000000000000000" + }, + "29bdc4f28de0180f433c2694eb74f5504ce94337": { + "balance": "2000000000000000000000" + }, + "2f66bfbf2262efcc8d2bd0444fc5b0696298ff1e": { + "balance": "9940000000000000000000" + }, + "506411fd79003480f6f2b6aac26b7ba792f094b2": { + "balance": "500000000000000000000" + }, + "23ea669e3564819a83b0c26c00a16d9e826f6c46": { + "balance": "1430590000000000000000" + }, + "e3ffb02cb7d9ea5243701689afd5d417d7ed2ece": { + "balance": "78000000000000000000" + }, + "38e7dba8fd4f1f850dbc2649d8e84f0952e3eb3c": { + "balance": "50000000000000000000" + }, + "8644cc281be332ccced36da483fb2a0746d9ba2e": { + "balance": "400000000000000000000" + }, + "e8a91da6cf1b9d65c74a02ec1f96eecb6dd241f3": { + "balance": "1940000000000000000000" + }, + "0631dc40d74e5095e3729eddf49544ecd4396f67": { + "balance": "160000000000000000000" + }, + "83c897a84b695eebe46679f7da19d776621c2694": { + "balance": "500000000000000000000" + }, + "db73460b59d8e85045d5e752e62559875e42502e": { + "balance": "999800000000000000000" + }, + "0dd4e674bbadb1b0dc824498713dce3b5156da29": { + "balance": "170000000000000000000" + }, + "e3933d61b77dcdc716407f8250bc91e4ffaeb09d": { + "balance": "86600000000000000000000" + }, + "58c90754d2f20a1cb1dd330625e04b45fa619d5c": { + "balance": "2000000000000000000000" + }, + "895ec5545644e0b78330fffab8ddeac9e833156c": { + "balance": "600000000000000000000" + }, + "7e1e29721d6cb91057f6c4042d8a0bbc644afe73": { + "balance": "159800000000000000000" + }, + "72b90a4dc097239492c5b9777dcd1e52ba2be2c2": { + "balance": "6000000000000000000000" + }, + "64241a7844290e0ab855f1d4aa75b55345032224": { + "balance": "1600000000000000000000" + }, + "6fd4e0f3f32bee6d3767fdbc9d353a6d3aab7899": { + "balance": "695240000000000000000" + }, + "3a035594c747476d42d1ee966c36224cdd224993": { + "balance": "355890000000000000000" + }, + "de97f4330700b48c496d437c91ca1de9c4b01ba4": { + "balance": "2910840000000000000000" + }, + "716ad3c33a9b9a0a18967357969b94ee7d2abc10": { + "balance": "482000000000000000000" + }, + "bfbe05e88c9cbbcc0e92a405fac1d85de248ee24": { + "balance": "100000000000000000000" + }, + "cfc4e6f7f8b011414bfba42f23adfaa78d4ecc5e": { + "balance": "1850000000000000000000" + }, + "d931ac2668ba6a84481ab139735aec14b7bfbabf": { + "balance": "2000000000000000000000" + }, + "e3263ce8af6db3e467584502ed7109125eae22a5": { + "balance": "2000000000000000000000" + }, + "f78258c12481bcdddbb72a8ca0c043097261c6c5": { + "balance": "20000000000000000000" + }, + "4493123c021ece3b33b1a452c9268de14007f9d3": { + "balance": "6685000000000000000000" + }, + "431f2c19e316b044a4b3e61a0c6ff8c104a1a12f": { + "balance": "1000000000000000000000" + }, + "e63e787414b9048478a50733359ecdd7e3647aa6": { + "balance": "1580000000000000000000" + }, + "e4715956f52f15306ee9506bf82bccc406b3895e": { + "balance": "274944000000000000000" + }, + "f7f91e7acb5b8129a306877ce3168e6f438b66a1": { + "balance": "176000000000000000000" + }, + "dcdbbd4e2604e40e1710cc6730289dccfad3892d": { + "balance": "4600000000000000000000" + }, + "2b5f4b3f1e11707a227aa5e69fa49dded33fb321": { + "balance": "6000000000000000000000" + }, + "01488ad3da603c4cdd6cb0b7a1e30d2a30c8fc38": { + "balance": "200000000000000000000" + }, + "841145b44840c946e21dbc190264b8e0d5029369": { + "balance": "300000000000000000000000" + }, + "bf05070c2c34219311c4548b2614a438810ded6d": { + "balance": "2000000000000000000000" + }, + "38f387e1a4ed4a73106ef2b462e474e2e3143ad0": { + "balance": "6000000000000000000000" + }, + "f116b0b4680f53ab72c968ba802e10aa1be11dc8": { + "balance": "20000000000000000000" + }, + "bea0afc93aae2108a3fac059623bf86fa582a75e": { + "balance": "1700000000000000000000" + }, + "4c997992036c5b433ac33d25a8ea1dc3d4e4e6d8": { + "balance": "29200000000000000000" + }, + "ab7e0b83ed9a424c6d1e6a6f87a4dbf06409c7d6": { + "balance": "2400000000000000000000" + }, + "d71fb130f0150c565269e00efb43902b52a455a6": { + "balance": "200000000000000000000" + }, + "99b018932bcad355b6792b255db6702dec8ce5dd": { + "balance": "4000086000000000000000" + }, + "4b904e934bd0cc8b20705f879e905b93ea0ccc30": { + "balance": "2000000000000000000000" + }, + "672ec42faa8cd69aaa71b32cc7b404881d52ff91": { + "balance": "10000000000000000000000" + }, + "acbc2d19e06c3babbb5b6f052b6bf7fc37e07229": { + "balance": "200000000000000000000" + }, + "cea8743341533cb2f0b9c6efb8fda80d77162825": { + "balance": "100000000000000000000" + }, + "9568b7de755628af359a84543de23504e15e41e6": { + "balance": "40000000000000000000000" + }, + "6ec96d13bdb24dc7a557293f029e02dd74b97a55": { + "balance": "4000000000000000000000" + }, + "d95c90ffbe5484864780b867494a83c89256d6e4": { + "balance": "1640000000000000000000" + }, + "ade6f8163bf7c7bb4abe8e9893bd0cc112fe8872": { + "balance": "327600000000000000000" + }, + "250eb7c66f869ddf49da85f3393e980c029aa434": { + "balance": "4000000000000000000000" + }, + "a35c19132cac1935576abfed6c0495fb07881ba0": { + "balance": "2000000000000000000000" + }, + "d5550caaf743b037c56fd2558a1c8ed235130750": { + "balance": "5347598000000000000000" + }, + "03097923ba155e16d82f3ad3f6b815540884b92c": { + "balance": "1820000000000000000000" + }, + "d6d9e30f0842012a7176a917d9d2048ca0738759": { + "balance": "4000000000000000000000" + }, + "ab9ad36e5c74ce2e96399f57839431d0e79f96ab": { + "balance": "164000000000000000000" + }, + "75be8ff65e5788aec6b2a52d5fa7b1e7a03ba675": { + "balance": "67720000000000000000" + }, + "4f6d4737d7a940382487264886697cf7637f8015": { + "balance": "1670000000000000000000" + }, + "5f7b3bbac16dab831a4a0fc53b0c549dc36c31ca": { + "balance": "1940000000000000000000" + }, + "d843ee0863ce933e22f89c802d31287b9671e81c": { + "balance": "13370000000000000000" + }, + "361f3ba9ed956b770f257d3672fe1ff9f7b0240c": { + "balance": "600000000000000000000" + }, + "6c0ae9f043c834d44271f13406593dfe094f389f": { + "balance": "1517545000000000000000" + }, + "db34745ede8576b499db01beb7c1ecda85cf4abe": { + "balance": "80000000000000000000" + }, + "7be8ccb4f11b66ca6e1d57c0b5396221a31ba53a": { + "balance": "20000000000000000000" + }, + "128b908fe743a434203de294c441c7e20a86ea67": { + "balance": "713304000000000000000" + }, + "df236bf6abf4f3293795bf0c28718f93e3b1b36b": { + "balance": "1337000000000000000000" + }, + "14254ea126b52d0142da0a7e188ce255d8c47178": { + "balance": "775000000000000000000" + }, + "ceed47ca5b899fd1623f21e9bd4db65a10e5b09d": { + "balance": "133196000000000000000" + }, + "30acd858875fa24eef0d572fc7d62aad0ebddc35": { + "balance": "400000000000000000000" + }, + "47a281dff64167197855bf6e705eb9f2cef632ea": { + "balance": "1000072000000000000000" + }, + "297d5dbe222f2fb52531acbd0b013dc446ac7368": { + "balance": "20000000000000000000000" + }, + "adf85203c8376a5fde9815384a350c3879c4cb93": { + "balance": "1147300000000000000000" + }, + "c3e0471c64ff35fa5232cc3121d1d38d1a0fb7de": { + "balance": "2000000000000000000000" + }, + "fdecc82ddfc56192e26f563c3d68cb544a96bfed": { + "balance": "440000000000000000000" + }, + "2614f42d5da844377578e6b448dc24305bef2b03": { + "balance": "2000000000000000000000" + }, + "1d96bcd58457bbf1d3c2a46ffaf16dbf7d836859": { + "balance": "171313000000000000000" + }, + "bd66ffedb530ea0b2e856dd12ac2296c31fe29e0": { + "balance": "200000000000000000000" + }, + "6e84876dbb95c40b6656e42ba9aea08a993b54dc": { + "balance": "1101932000000000000000" + }, + "a1c4f45a82e1c478d845082eb18875c4ea6539ab": { + "balance": "200000000000000000000000" + }, + "2c964849b1f69cc7cea4442538ed87fdf16cfc8f": { + "balance": "2000000000000000000000" + }, + "45b47105fe42c4712dce6e2a21c05bffd5ea47a9": { + "balance": "2000000000000000000000" + }, + "31e9c00f0c206a4e4e7e0522170dc81e88f3eb70": { + "balance": "2685000000000000000000" + }, + "5fe77703808f823e6c399352108bdb2c527cb87c": { + "balance": "1960000000000000000000" + }, + "2272186ef27dcbe2f5fc373050fdae7f2ace2316": { + "balance": "16100000000000000000000" + }, + "b7576e9d314df41ec5506494293afb1bd5d3f65d": { + "balance": "20000000000000000000" + }, + "ac9fff68c61b011efbecf038ed72db97bb9e7281": { + "balance": "9550000000000000000000" + }, + "cd9529492b5c29e475acb941402b3d3ba50686b0": { + "balance": "1970000000000000000000" + }, + "f19b39389d47b11b8a2c3f1da9124decffbefaf7": { + "balance": "2000000000000000000000" + }, + "9e951f6dc5e352afb8d04299d2478a451259bf56": { + "balance": "72004000000000000000" + }, + "8eb1fbe4e5d3019cd7d30dae9c0d5b4c76fb6331": { + "balance": "2000000000000000000000" + }, + "29cc804d922be91f5909f348b0aaa5d21b607830": { + "balance": "4000000000000000000000" + }, + "5c7b9ec7a2438d1e3c7698b545b9c3fd77b7cd55": { + "balance": "1000000000000000000000" + }, + "a16160851d2b9c349b92e46f829abfb210943595": { + "balance": "1790000000000000000000" + }, + "eac6b98842542ea10bb74f26d7c7488f698b6452": { + "balance": "20000000000000000000000" + }, + "57825aeb09076caa477887fbc9ae37e8b27cc962": { + "balance": "100000000000000000000" + }, + "b35e8a1c0dac7e0e66dbac736a592abd44012561": { + "balance": "14974000000000000000" + }, + "756b84eb85fcc1f4fcdcc2b08db6a86e135fbc25": { + "balance": "3220000000000000000000" + }, + "e13b3d2bbfdcbc8772a23315724c1425167c5688": { + "balance": "1032115000000000000000" + }, + "0a2dcb7a671701dbb8f495728088265873356c8e": { + "balance": "152120000000000000000" + }, + "03cb4c4f4516c4ff79a1b6244fbf572e1c7fea79": { + "balance": "2740000000000000000000" + }, + "98ba4e9ca72fddc20c69b4396f76f8183f7a2a4e": { + "balance": "12800000000000000000000" + }, + "f8087786b42da04ed6d1e0fe26f6c0eefe1e9f5a": { + "balance": "10000000000000000000000" + }, + "02f7f67209b16a17550c694c72583819c80b54ad": { + "balance": "98400000000000000000" + }, + "32bb2e9693e4e085344d2f0dbd46a283e3a087fd": { + "balance": "400000000000000000000" + }, + "9c78963fbc263c09bd72e4f8def74a9475f7055c": { + "balance": "13790000000000000000000" + }, + "27144ca9a7771a836ad50f803f64d869b2ae2b20": { + "balance": "4000000000000000000000" + }, + "cc758d071d25a6320af68c5dc9c4f6955ba94520": { + "balance": "6000000000000000000000" + }, + "cb42b44eb5fd60b5837e4f9eb47267523d1a229c": { + "balance": "865000000000000000000" + }, + "aaf5b207b88b0de4ac40d747cee06e172df6e745": { + "balance": "31428000000000000000000" + }, + "52d380511df19d5ec2807bbcb676581b67fd37a3": { + "balance": "13400000000000000000" + }, + "aa1b3768c16d821f580e76c8e4c8e86d7dc78853": { + "balance": "400000000000000000000" + }, + "41098a81452317c19e3eef0bd123bbe178e9e9ca": { + "balance": "2800000000000000000000" + }, + "267148fd72c54f620a592fb92799319cc4532b5c": { + "balance": "410000000000000000000" + }, + "d7cdbd41fff20df727c70b6255c1ba7606055468": { + "balance": "200000000000000000000" + }, + "0e33fcbbc003510be35785b52a9c5d216bc005f4": { + "balance": "1880000000000000000000" + }, + "6727daf5b9d68efcab489fedec96d7f7325dd423": { + "balance": "2000000000000000000000" + }, + "cd0a161bc367ae0927a92aac9cf6e5086714efca": { + "balance": "2000000000000000000000" + }, + "612667f172135b950b2cd1de10afdece6857b873": { + "balance": "1000000000000000000000" + }, + "900194c4b1074305d19de405b0ac78280ecaf967": { + "balance": "1000000000000000000000" + }, + "51f55ef47e6456a418ab32b9221ed27dba6608ee": { + "balance": "4200000000000000000000" + }, + "0da532c910e3ac0dfb14db61cd739a93353fd05f": { + "balance": "1336866000000000000000" + }, + "21df2dcdaf74b2bf803404dd4de6a35eabec1bbd": { + "balance": "6920000000000000000000" + }, + "f0e7fb9e420a5340d536f40408344feaefc06aef": { + "balance": "1000000000000000000000" + }, + "6742a2cfce8d79a2c4a51b77747498912245cd6a": { + "balance": "258064000000000000000" + }, + "8663a241a0a89e70e182c845e2105c8ad7264bcf": { + "balance": "14825507000000000000000" + }, + "18e113d8177c691a61be785852fa5bb47aeebdaf": { + "balance": "1337000000000000000000" + }, + "1bec4d02ce85fc48feb62489841d85b170586a9b": { + "balance": "2400000000000000000000" + }, + "287cf9d0902ef819a7a5f149445bf1775ee8c47c": { + "balance": "16000000000000000000000" + }, + "28967280214e218a120c5dda37041b111ea36d74": { + "balance": "200000000000000000000" + }, + "a0b771951ce1deee363ae2b771b73e07c4b5e800": { + "balance": "1400000000000000000000" + }, + "29f8fba4c30772b057edbbe62ae7420c390572e1": { + "balance": "1000000000000000000000" + }, + "ee34c7e7995db9f187cff156918cfb6f13f6e003": { + "balance": "1960000000000000000000" + }, + "916bf7e3c545921d3206d900c24f14127cbd5e70": { + "balance": "18020000000000000000000" + }, + "93235f340d2863e18d2f4c52996516138d220267": { + "balance": "73800000000000000000" + }, + "7efec0c6253caf397f71287c1c07f6c9582b5b86": { + "balance": "482839000000000000000" + }, + "8d2e31b08803b2c5f13d398ecad88528209f6057": { + "balance": "9993000000000000000000" + }, + "964eab4b276b4cd8983e15ca72b106900fe41fce": { + "balance": "500000000000000000000" + }, + "eea1e97988de75d821cd28ad6822b22cce988b31": { + "balance": "520000000000000000000" + }, + "278c0bde630ec393b1e7267fc9d7d97019e4145b": { + "balance": "2000000000000000000000" + }, + "82e4461eb9d849f0041c1404219e4272c4900ab4": { + "balance": "2000000000000000000000" + }, + "4a73389298031b8816cca946421c199e18b343d6": { + "balance": "631254000000000000000" + }, + "9a5af31c7e06339ac8b4628d7c4db0ce0f45c8a4": { + "balance": "500000000000000000000" + }, + "cb9b5103e4ce89af4f64916150bff9eecb9faa5c": { + "balance": "500000000000000000000" + }, + "740f641614779dcfa88ed1d425d60db42a060ca6": { + "balance": "998630000000000000000" + }, + "a4e623451e7e94e7e89ba5ed95c8a83a62ffc4ea": { + "balance": "20000000000000000000" + }, + "25a500eeec7a662a841552b5168b707b0de21e9e": { + "balance": "10020000000000000000000" + }, + "185a7fc4ace368d233e620b2a45935661292bdf2": { + "balance": "20000000000000000000000" + }, + "9b68f67416a63bf4451a31164c92f672a68759e9": { + "balance": "60000000000000000000000" + }, + "a38b5bd81a9db9d2b21d5ec7c60552cd02ed561b": { + "balance": "6000000000000000000000" + }, + "61c830f1654718f075ccaba316faacb85b7d120b": { + "balance": "400000000000000000000" + }, + "8392e53776713578015bff4940cf43849d7dcba1": { + "balance": "153190000000000000000" + }, + "dc57477dafa42f705c7fe40eae9c81756e0225f1": { + "balance": "500044000000000000000" + }, + "febc3173bc9072136354002b7b4fb3bfc53f22f1": { + "balance": "370000000000000000000" + }, + "d78f84e38944a0e0255faece48ba4950d4bd39d2": { + "balance": "5000000000000000000000" + }, + "a7a3bb6139b0ada00c1f7f1f9f56d994ba4d1fa8": { + "balance": "2000000000000000000000" + }, + "aa3f29601a1331745e05c42830a15e71938a6237": { + "balance": "1700000000000000000000" + }, + "bec6640f4909b58cbf1e806342961d607595096c": { + "balance": "1999944000000000000000" + }, + "9be3c329b62a28b8b0886cbd8b99f8bc930ce3e6": { + "balance": "74500000000000000000" + }, + "e3eb2c0a132a524f72ccc0d60fee8b41685d39e2": { + "balance": "1970000000000000000000" + }, + "90b1f370f9c1eb0be0fb8e2b8ad96a416371dd8a": { + "balance": "900000000000000000000" + }, + "f2742e6859c569d5f2108351e0bf4dca352a48a8": { + "balance": "10000000000000000000000" + }, + "b134c004391ab4992878337a51ec242f42285742": { + "balance": "2000000000000000000000" + }, + "ab7416ff32254951cbbc624ec7fb45fc7ecaa872": { + "balance": "340000000000000000000" + }, + "9795f64319fc17dd0f8261f9d206fb66b64cd0c9": { + "balance": "200000000000000000000" + }, + "64e03ef070a54703b7184e48276c5c0077ef4b34": { + "balance": "320000000000000000000" + }, + "3430a16381f869f6ea5423915855e800883525a9": { + "balance": "17900000000000000000000" + }, + "f4a367b166d2991a2bfda9f56463a09f252c1b1d": { + "balance": "1970000000000000000000" + }, + "77c4a697e603d42b12056cbba761e7f51d0443f5": { + "balance": "680000000000000000000" + }, + "153ef58a1e2e7a3eb6b459a80ab2a547c94182a2": { + "balance": "96000000000000000000000" + }, + "6dbe8abfa1742806263981371bf3d35590806b6e": { + "balance": "20000000000000000000000" + }, + "4c99dae96481e807c1f99f8b7fbde29b7547c5bf": { + "balance": "150000000000000000000" + }, + "d5b9d277d8aad20697a51f76e20978996bffe055": { + "balance": "143250000000000000000" + }, + "0f24105abbdaa03fa6309ef6c188e51f714a6e59": { + "balance": "200000000000000000000" + }, + "1cb6b2d7cfc559b7f41e6f56ab95c7c958cd0e4c": { + "balance": "1337000000000000000000" + }, + "f37b426547a1642d8033324814f0ede3114fc212": { + "balance": "401100000000000000000" + }, + "318f1f8bd220b0558b95fb33100ffdbb640d7ca6": { + "balance": "4000000000000000000000" + }, + "206d55d5792a514ec108e090599f2a065e501185": { + "balance": "200550000000000000000" + }, + "11d2247a221e70c2d66d17ee138d38c55ffb8640": { + "balance": "10000000000000000000000" + }, + "e8de725eca5def805ff7941d31ac1c2e342dfe95": { + "balance": "2462500000000000000000" + }, + "d561cbbc05515de73ab8cf9eae1357341e7dfdf4": { + "balance": "6000000000000000000000" + }, + "0455dcec8a7fc4461bfd7f37456fce3f4c3caac7": { + "balance": "400000000000000000000" + }, + "5161fd49e847f67455f1c8bb7abb36e985260d03": { + "balance": "1200000000000000000000" + }, + "8e073bad25e42218615f4a0e6b2ea8f8de2230c0": { + "balance": "2402500000000000000000" + }, + "6c08a6dc0173c7342955d1d3f2c065d62f83aec7": { + "balance": "20000000000000000000" + }, + "95cb6d8a6379f94aba8b885669562c4d448e56a7": { + "balance": "2000000000000000000000" + }, + "2805415e1d7fdec6dedfb89e521d10592d743c10": { + "balance": "100000000000000000000" + }, + "daacdaf42226d15cb1cf98fa15048c7f4ceefe69": { + "balance": "300000000000000000000" + }, + "e33df4ce80ccb62a76b12bcdfcecc46289973aa9": { + "balance": "6000000000000000000000" + }, + "8f8cd26e82e7c6defd02dfad07979021cbf7150c": { + "balance": "3000000000000000000000" + }, + "77a17122fa31b98f1711d32a99f03ec326f33d08": { + "balance": "1700000000000000000000" + }, + "6f791d359bc3536a315d6382b88311af8ed6da47": { + "balance": "92000000000000000000" + }, + "de30e49e5ab313214d2f01dcabce8940b81b1c76": { + "balance": "197000000000000000000" + }, + "cf9be9b9ab86c66b59968e67b8d4dcff46b1814a": { + "balance": "660000000000000000000" + }, + "7fdfc88d78bf1b285ac64f1adb35dc11fcb03951": { + "balance": "2287900000000000000000" + }, + "c5134cfbb1df7a20b0ed7057622eeed280947dad": { + "balance": "3800000000000000000000" + }, + "fa9ec8efe08686fa58c181335872ba698560ecab": { + "balance": "1999944000000000000000" + }, + "f6a8635757c5e8c134d20d028cf778cf8609e46a": { + "balance": "1459416000000000000000" + }, + "6265b2e7730f36b776b52d0c9d02ada55d8e3cb6": { + "balance": "1000000000000000000000" + }, + "6a8cea2de84a8df997fd3f84e3083d93de57cda9": { + "balance": "100007000000000000000" + }, + "1b7ed974b6e234ce81247498429a5bd4a0a2d139": { + "balance": "2000000000000000000000" + }, + "9ba53dc8c95e9a472feba2c4e32c1dc4dd7bab46": { + "balance": "1337000000000000000000" + }, + "d7b740dff8c457668fdf74f6a266bfc1dcb723f9": { + "balance": "20000000000000000000" + }, + "07bc2cc8eedc01970700efc9c4fb36735e98cd71": { + "balance": "4000000000000000000000" + }, + "3e1c962063e0d5295941f210dca3ab531eec8809": { + "balance": "3000000000000000000000" + }, + "b447571dacbb3ecbb6d1cf0b0c8f3838e52324e2": { + "balance": "30199000000000000000" + }, + "87764e3677eef604cbc59aed24abdc566b09fc25": { + "balance": "3000000000000000000000" + }, + "03aa622881236dd0f4940c24c324ff8b7b7e2186": { + "balance": "3200000000000000000000" + }, + "a4a7d306f510cd58359428c0d2f7c3609d5674d7": { + "balance": "3349000000000000000000" + }, + "3c83c1701db0388b68210d00f5717cd9bd322c6a": { + "balance": "30000000000000000000000" + }, + "047d5a26d7ad8f8e70600f70a398ddaa1c2db26f": { + "balance": "6000000000000000000000" + }, + "43767bf7fd2af95b72e9312da9443cb1688e4343": { + "balance": "300000000000000000000" + }, + "34a85d6d243fb1dfb7d1d2d44f536e947a4cee9e": { + "balance": "20000000000000000000000" + }, + "65a9dad42e1632ba3e4e49623fab62a17e4d3611": { + "balance": "93120000000000000000" + }, + "48e0cbd67f18acdb7a6291e1254db32e0972737f": { + "balance": "100007000000000000000" + }, + "a5de5e434fdcdd688f1c31b6fb512cb196724701": { + "balance": "800000000000000000000" + }, + "6d63d38ee8b90e0e6ed8f192eda051b2d6a58bfd": { + "balance": "30000000000000000000" + }, + "b079bb4d9866143a6da72ae7ac0022062981315c": { + "balance": "760000000000000000000" + }, + "c0413f5a7c2d9a4b8108289ef6ecd271781524f4": { + "balance": "50000000000000000000000" + }, + "a91a5a7b341f99c535144e20be9c6b3bb4c28e4d": { + "balance": "5431790000000000000000" + }, + "993f146178605e66d517be782ef0b3c61a4e1925": { + "balance": "7011998000000000000000" + }, + "966c04781cb5e67dde3235d7f8620e1ab663a9a5": { + "balance": "75800000000000000000000" + }, + "b3f82a87e59a39d0d2808f0751eb72c2329cdcc5": { + "balance": "5000000000000000000000" + }, + "9b77ebced7e215f0920e8c2b870024f6ecb2ff31": { + "balance": "1000000000000000000000" + }, + "fe697ff22ca547bfc95e33d960da605c6763f35b": { + "balance": "1325000000000000000000" + }, + "480af52076009ca73781b70e43b95916a62203ab": { + "balance": "924171000000000000000" + }, + "a9dc0424c6969d798358b393b1933a1f51bee00a": { + "balance": "20000000000000000000000" + }, + "7aba56f63a48bc0817d6b97039039a7ad62fae2e": { + "balance": "600000000000000000000" + }, + "59d139e2e40c7b97239d23dfaca33858f602d22b": { + "balance": "2000000000000000000000" + }, + "8d6170ff66978e773bb621bf72b1ba7be3a7f87e": { + "balance": "200000000000000000000" + }, + "d668523a90f0293d65c538d2dd6c57673710196e": { + "balance": "39500000000000000000" + }, + "bbb5a0f4802c8648009e8a6998af352cde87544f": { + "balance": "95500000000000000000" + }, + "fc43829ac787ff88aaf183ba352aadbf5a15b193": { + "balance": "3960000000000000000000" + }, + "fe22a0b388668d1ae2643e771dacf38a434223cc": { + "balance": "4000304000000000000000" + }, + "092acb624b08c05510189bbbe21e6524d644ccad": { + "balance": "18200000000000000000" + }, + "8f0538ed71da1155e0f3bde5667ceb84318a1a87": { + "balance": "1940000000000000000000" + }, + "06994cd83aa2640a97b2600b41339d1e0d3ede6c": { + "balance": "250000000000000000000" + }, + "9d460c1b379ddb19a8c85b4c6747050ddf17a875": { + "balance": "3340000000000000000000" + }, + "77a769fafdecf4a638762d5ba3969df63120a41d": { + "balance": "2000000000000000000000" + }, + "5f375b86600c40cca8b2676b7a1a1d1644c5f52c": { + "balance": "78838000000000000000" + }, + "15ee0fc63ebf1b1fc49d7bb38f8863823a2e17d2": { + "balance": "1910000000000000000000" + }, + "6651736fb59b91fee9c93aa0bd6ea2f7b2506180": { + "balance": "500000000000000000000" + }, + "361d9ed80b5bd27cf9f1226f26753258ee5f9b3f": { + "balance": "3530900000000000000000" + }, + "c9b6b686111691ee6aa197c7231a88dc60bd295d": { + "balance": "500000000000000000000" + }, + "e9b4a4853577a9dbcc2e795be0310d1bed28641a": { + "balance": "1000000000000000000000" + }, + "36758e049cd98bcea12277a676f9297362890023": { + "balance": "4000000000000000000000" + }, + "6bb50813146a9add42ee22038c9f1f7469d47f47": { + "balance": "200200000000000000000" + }, + "6de4b581385cf7fc9fe8c77d131fe2ee7724c76a": { + "balance": "2308840000000000000000" + }, + "d2a5a024230a57ccc666760b89b0e26cafd189c7": { + "balance": "49997115000000000000000" + }, + "65af9087e05167715497c9a5a749189489004def": { + "balance": "835000000000000000000" + }, + "ead21c1deccfbf1c5cd96688a2476b69ba07ce4a": { + "balance": "72800000000000000000" + }, + "e308435204793764f5fcbe65eb510f5a744a655a": { + "balance": "200000000000000000000" + }, + "9376dce2af2ec8dcda741b7e7345664681d93668": { + "balance": "1000000000000000000000" + }, + "a1b47c4d0ed6018842e6cfc8630ac3a3142e5e6b": { + "balance": "20000000000000000000" + }, + "e2198c8ca1b399f7521561fd5384a7132fba486b": { + "balance": "1015200000000000000000" + }, + "92c13fe0d6ce87fd50e03def9fa6400509bd7073": { + "balance": "40000000000000000000" + }, + "7517f16c28d132bb40e3ba36c6aef131c462da17": { + "balance": "18200000000000000000" + }, + "6a023af57d584d845e698736f130db9db40dfa9a": { + "balance": "98800000000000000000" + }, + "1518627b88351fede796d3f3083364fbd4887b0c": { + "balance": "16000000000000000000000" + }, + "f5b6e9061a4eb096160777e26762cf48bdd8b55d": { + "balance": "254030000000000000000" + }, + "28073efc17d05cab3195c2db332b61984777a612": { + "balance": "1000000000000000000000" + }, + "f06a854a3c5dc36d1c49f4c87d6db333b57e4add": { + "balance": "10000000000000000000000" + }, + "9225983860a1cb4623c72480ac16272b0c95e5f5": { + "balance": "2000000000000000000000" + }, + "5260dc51ee07bddaababb9ee744b393c7f4793a6": { + "balance": "34040000000000000000" + }, + "0f127bbf8e311caea2ba502a33feced3f730ba42": { + "balance": "188000000000000000000" + }, + "17d521a8d9779023f7164d233c3b6420ffd223ed": { + "balance": "20000000000000000000" + }, + "8c2b7d8b608d28b77f5caa9cd645242a823e4cd9": { + "balance": "1820000000000000000000" + }, + "6e866d032d405abdd65cf651411d803796c22311": { + "balance": "2000000000000000000000" + }, + "dc51b2dc9d247a1d0e5bc36ca3156f7af21ff9f6": { + "balance": "1000000000000000000000" + }, + "c84d9bea0a7b9f140220fd8b9097cfbfd5edf564": { + "balance": "123047000000000000000" + }, + "ff86e5e8e15b53909600e41308dab75f0e24e46b": { + "balance": "902400000000000000000" + }, + "d7164aa261c09ad9b2b5068d453ed8eb6aa13083": { + "balance": "3000000000000000000000" + }, + "76aaf8c1ac012f8752d4c09bb46607b6651d5ca8": { + "balance": "20000000000000000000" + }, + "41786a10d447f484d33244ccb7facd8b427b5b8c": { + "balance": "1000000000000000000000" + }, + "2e0c57b47150f95aa6a7e16ab9b1cbf54328979a": { + "balance": "100000000000000000000" + }, + "3f747237806fed3f828a6852eb0867f79027af89": { + "balance": "1500000000000000000000" + }, + "a568db4d57e4d67462d733c69a9e0fe26e218327": { + "balance": "1096140000000000000000" + }, + "1f88f8a1338fc7c10976abcd3fb8d38554b5ec9c": { + "balance": "13400000000000000000" + }, + "d1ea4d72a67b5b3e0f315559f52bd0614d713069": { + "balance": "2000000000000000000000" + }, + "bfaeb91067617dcf8b44172b02af615674835dba": { + "balance": "160661000000000000000" + }, + "b71a13ba8e95167b80331b52d69e37054fe7a826": { + "balance": "200000000000000000000" + }, + "b67a80f170197d96cdcc4ab6cba627b4afa6e12c": { + "balance": "2400000000000000000000" + }, + "35af040a0cc2337a76af288154c7561e1a233349": { + "balance": "1000000000000000000000" + }, + "c86190904b8d079ec010e462cbffc90834ffaa5c": { + "balance": "10100000000000000000000" + }, + "383304dd7a5720b29c1a10f60342219f48032f80": { + "balance": "5600000000000000000000" + }, + "191313525238a21c767457a91374f02200c55448": { + "balance": "116400000000000000000" + }, + "cc4a2f2cf86cf3e43375f360a4734691195f1490": { + "balance": "1348127000000000000000" + }, + "4e020779b5ddd3df228a00cb48c2fc979da6ae38": { + "balance": "2000000000000000000000" + }, + "e206fb7324e9deb79e19903496d6961b9be56603": { + "balance": "100000000000000000000" + }, + "3ae160e3cd60ae31b9d6742d68e14e76bd96c517": { + "balance": "30000000000000000000" + }, + "1f7d8e86d6eeb02545aad90e91327bd369d7d2f3": { + "balance": "20000000000000000000" + }, + "68c7d1711b011a33f16f1f55b5c902cce970bdd7": { + "balance": "152000000000000000000" + }, + "637be71b3aa815ff453d5642f73074450b64c82a": { + "balance": "2000000000000000000000" + }, + "1584a2c066b7a455dbd6ae2807a7334e83c35fa5": { + "balance": "130000000000000000000" + }, + "9c05e9d0f0758e795303717e31da213ca157e686": { + "balance": "1000000000000000000000" + }, + "4f1a2da54a4c6da19d142412e56e815741db2325": { + "balance": "100000000000000000000" + }, + "9a4ca8b82117894e43db72b9fa78f0b9b93ace09": { + "balance": "50000000000000000000" + }, + "26c99f8849c9802b83c861217fd07a9e84cdb79d": { + "balance": "300000000000000000000" + }, + "45c0d19f0b8e054f9e893836d5ecae7901af2812": { + "balance": "5000000000000000000000" + }, + "00dc01cbf44978a42e8de8e436edf94205cfb6ec": { + "balance": "1458440000000000000000" + }, + "de7dee220f0457a7187d56c1c41f2eb00ac56021": { + "balance": "629924000000000000000" + }, + "1c128bd6cda5fca27575e4b43b3253c8c4172afe": { + "balance": "2000000000000000000000" + }, + "666746fb93d1935c5a3c684e725010c4fad0b1d8": { + "balance": "20000000000000000000" + }, + "51d78b178d707e396e8710965c4f41b1a1d9179d": { + "balance": "110600000000000000000" + }, + "68f7573cd457e14c03fea43e302d30347c10705c": { + "balance": "5000000000000000000000" + }, + "9d30cb237bc096f17036fc80dd21ca68992ca2d9": { + "balance": "30380000000000000000000" + }, + "fbcfcc4a7b0f26cf26e9f3332132e2fc6a230766": { + "balance": "8000000000000000000000" + }, + "b166e37d2e501ae73c84142b5ffb5aa655dd5a99": { + "balance": "1999000000000000000000" + }, + "6df24f6685a62f791ba337bf3ff67e91f3d4bc3a": { + "balance": "2166000000000000000000" + }, + "92e435340e9d253c00256389f52b067d55974e76": { + "balance": "268000000000000000000" + }, + "ea53d26564859d9e90bb0e53b7abf560e0162c38": { + "balance": "400000000000000000000" + }, + "e26657f0ed201ea2392c9222b80a7003608ddf30": { + "balance": "40000000000000000000" + }, + "f4177a0d85d48b0e264211ce2aa2efd3f1b47f08": { + "balance": "3593425000000000000000" + }, + "9d47ba5b4c8505ad8da42934280b61a0e1e8b971": { + "balance": "100000000000000000000" + }, + "63c2a3d235e5eeabd0d4a6afdb89d94627396495": { + "balance": "1241620000000000000000" + }, + "446a8039cecf9dce4879cbcaf3493bf545a88610": { + "balance": "7000000000000000000000" + }, + "7fa37ed67887751a471f0eb306be44e0dbcd6089": { + "balance": "1060000000000000000000" + }, + "26d4a16891f52922789217fcd886f7fce296d400": { + "balance": "2000000000000000000000" + }, + "487e108502b0b189ef9c8c6da4d0db6261eec6c0": { + "balance": "1910000000000000000000" + }, + "7484d26becc1eea8c6315ec3ee0a450117dc86a0": { + "balance": "12000000000000000000000" + }, + "ad9e97a0482f353a05c0f792b977b6c7e811fa5f": { + "balance": "200000000000000000000" + }, + "2273bad7bc4e487622d175ef7a66988b6a93c4ee": { + "balance": "20000000000000000000" + }, + "3b93b16136f11eaf10996c95990d3b2739ccea5f": { + "balance": "10000000000000000000000" + }, + "f3f1fa3918ca34e2cf7e84670b1f4d8eca160db3": { + "balance": "680000000000000000000" + }, + "88a2154430c0e41147d3c1fee3b3b006f851edbd": { + "balance": "999972000000000000000" + }, + "25185f325acf2d64500698f65c769ddf68301602": { + "balance": "5000000000000000000000" + }, + "e9cafe41a5e8bbd90ba02d9e06585b4eb546c57f": { + "balance": "2000000000000000000000" + }, + "95681cdae69b2049ce101e325c759892cac3f811": { + "balance": "2857600000000000000000" + }, + "475066f9ad26655196d5535327bbeb9b7929cb04": { + "balance": "3040000000000000000000" + }, + "6685fd2e2544702c360b8bb9ee78f130dad16da5": { + "balance": "2000000000000000000000" + }, + "45e68db94c7d0ab7ac41857a71d67147870f4e71": { + "balance": "400000000000000000000000" + }, + "4ad95d188d6464709add2555fb4d97fe1ebf311f": { + "balance": "346000000000000000000" + }, + "73bedd6fda7ba3272185087b6351fc133d484e37": { + "balance": "5057200000000000000000" + }, + "1ea4715504c6af107b0194f4f7b1cb6fcccd6f4b": { + "balance": "590598000000000000000" + }, + "77306ffe2e4a8f3ca826c1a249f7212da43aeffd": { + "balance": "20000000000000000000000" + }, + "eb453f5a3adddd8ab56750fadb0fe7f94d9c89e7": { + "balance": "20000000000000000000" + }, + "7201d1c06920cd397ae8ad869bcda6e47ffb1b5a": { + "balance": "20000000000000000000" + }, + "821cb5cd05c7ef909fe1be60733d8963d760dc41": { + "balance": "4000000000000000000000" + }, + "496e319592b341eaccd778dda7c8196d54cac775": { + "balance": "9250000000000000000000" + }, + "88609e0a465b6e99fce907166d57e9da0814f5c8": { + "balance": "20000000000000000000000" + }, + "c7ec62b804b1f69b1e3070b5d362c62fb309b070": { + "balance": "13068074000000000000000" + }, + "3eb9ef06d0c259040319947e8c7a6812aa0253d8": { + "balance": "167000000000000000000" + }, + "cbf37ff854a2f1ce53934494777892d3ec655782": { + "balance": "10000000000000000000000" + }, + "02b1af72339b2a2256389fd64607de24f0de600a": { + "balance": "2000000000000000000000" + }, + "a8beb91c2b99c8964aa95b6b4a184b1269fc3483": { + "balance": "400000000000000000000" + }, + "922a20c79a1d3a26dd3829677bf1d45c8f672bb6": { + "balance": "4000000000000000000000" + }, + "c5843399d150066bf7979c34ba294620368ad7c0": { + "balance": "200000000000000000000" + }, + "8cd0cd22e620eda79c0461e896c93c44837e2968": { + "balance": "2000000000000000000000" + }, + "6170dd0687bd55ca88b87adef51cfdc55c4dd458": { + "balance": "2005160000000000000000" + }, + "eed384ef2d41d9d203974e57c12328ea760e08ea": { + "balance": "1000000000000000000000" + }, + "b129a5cb7105fe810bd895dc7206a991a4545488": { + "balance": "30000000000000000000" + }, + "3872f48dc5e3f817bc6b2ad2d030fc5e0471193d": { + "balance": "4000000000000000000000" + }, + "514b7512c9ae5ea63cbf11715b63f21e18d296c1": { + "balance": "1999944000000000000000" + }, + "7ab256b204800af20137fabcc916a23258752501": { + "balance": "20000000000000000000000" + }, + "fc66faba277f4b5de64ad45eb19c31e00ced3ed5": { + "balance": "5640000000000000000000" + }, + "39824f8bced176fd3ea22ec6a493d0ccc33fc147": { + "balance": "4000000000000000000000" + }, + "e338e859fe2e8c15554848b75caecda877a0e832": { + "balance": "1801800000000000000000" + }, + "e53c68796212033e4e6f9cff56e19c461eb454f9": { + "balance": "1000000000000000000000" + }, + "8461ecc4a6a45eb1a5b947fb86b88069b91fcd6f": { + "balance": "2000000000000000000000" + }, + "6b4b99cb3fa9f7b74ce3a48317b1cd13090a1a7a": { + "balance": "57300000000000000000" + }, + "97de21e421c37fe4b8025f9a51b7b390b5df7804": { + "balance": "80000000000000000000000" + }, + "d25aecd7eb8bd6345b063b5dbd271c77d3514494": { + "balance": "1820000000000000000000" + }, + "57b23d6a1adc06c652a779c6a7fb6b95b9fead66": { + "balance": "200000000000000000000" + }, + "0d658014a199061cf6b39433140303c20ffd4e5a": { + "balance": "8200000000000000000000" + }, + "30eac740e4f02cb56eef0526e5d300322600d03e": { + "balance": "1970000000000000000000" + }, + "4eead40aad8c73ef08fc84bc0a92c9092f6a36bf": { + "balance": "26740000000000000000" + }, + "30f7d025d16f7bee105580486f9f561c7bae3fef": { + "balance": "500000000000000000000" + }, + "0977bfba038a44fb49b03970d8d8cf2cb61f8b25": { + "balance": "420000000000000000000" + }, + "b14bbeff70720975dc6191b2a44ff49f2672873c": { + "balance": "143000000000000000000" + }, + "d588c3a5df228185d98ee7e60748255cdea68b01": { + "balance": "4000000000000000000000" + }, + "225d35faedb391c7bc2db7fa9071160405996d00": { + "balance": "167774000000000000000" + }, + "c0e457bd56ec36a1246bfa3230fff38e5926ef22": { + "balance": "1940000000000000000000" + }, + "2a9c57fe7b6b138a920d676f3c76b6c2a0eef699": { + "balance": "9400000000000000000000" + }, + "36df8f883c1273ec8a171f7a33cfd649b1fe6075": { + "balance": "227290000000000000000" + }, + "234f46bab73fe45d31bf87f0a1e0466199f2ebac": { + "balance": "485000000000000000000" + }, + "a2e1b8aa900e9c139b3fa122354f6156d92a18b1": { + "balance": "500000000000000000000" + }, + "517cd7608e5d0d83a26b717f3603dac2277dc3a4": { + "balance": "2000000000000000000000" + }, + "75f7539d309e9039989efe2e8b2dbd865a0df088": { + "balance": "2460000000000000000000" + }, + "4b792e29683eb586e394bb33526c6001b397999e": { + "balance": "600000000000000000000" + }, + "a34f9d568bf7afd94c2a5b8a5ff55c66c4087999": { + "balance": "2444000000000000000000" + }, + "4b31bf41abc75c9ae2cd8f7f35163b6e2b745054": { + "balance": "382000000000000000000" + }, + "e35453eef2cc3c7a044d0ac134ba615908fa82ee": { + "balance": "147510000000000000000" + }, + "7aa79ac04316cc8d08f20065baa6d4142897d54e": { + "balance": "1400000000000000000000" + }, + "f1dc8ac81042c67a9c3c6792b230c46ac016ca10": { + "balance": "200000000000000000000" + }, + "2bb366b9edcb0da680f0e10b3b6e28748190d6c3": { + "balance": "5799400000000000000000" + }, + "a567770b6ae320bdde50f904d663e746a61dace6": { + "balance": "2000000000000000000000" + }, + "d9d42fd13ebd4bf69cac5e9c7e82483ab46dd7e9": { + "balance": "5348000000000000000000" + }, + "27830c5f6023afaaf79745676c204a0faccda0ba": { + "balance": "240000000000000000000" + }, + "3cb179cb4801a99b95c3b0c324a2bdc101a65360": { + "balance": "26000000000000000000" + }, + "976e3ceaf3f1af51f8c29aff5d7fa21f0386d8ee": { + "balance": "240000000000000000000" + }, + "752a5ee232612cd3005fb26e5b597de19f776be6": { + "balance": "5460000000000000000000" + }, + "7d5aa33fc14b51841a06906edb2bb49c2a117269": { + "balance": "300048000000000000000" + }, + "55ca6abe79ea2497f46fdbb830346010fe469cbe": { + "balance": "5730000000000000000000" + }, + "6bec311ad05008b4af353c958c40bd06739a3ff3": { + "balance": "16380000000000000000000" + }, + "30e9698cf1e08a9d048bd8d8048f28be7ed9409f": { + "balance": "6685000000000000000000" + }, + "9afa536b4c66bc38d875c4b30099d9261fdb38eb": { + "balance": "205981000000000000000" + }, + "6b63a2dfb2bcd0caec0022b88be30c1451ea56aa": { + "balance": "809021000000000000000" + }, + "d07be0f90997caf903c8ac1d53cde904fb190741": { + "balance": "1000200000000000000000" + }, + "893cdddf5377f3c751bf2e541120045a47cba101": { + "balance": "100000000000000000000" + }, + "c1cdc601f89c0428b31302d187e0dc08ad7d1c57": { + "balance": "6000000000000000000000" + }, + "8f8acb107607388479f64baaabea8ff007ada97d": { + "balance": "27281800000000000000000" + }, + "88bc43012edb0ea9f062ac437843250a39b78fbb": { + "balance": "20000000000000000000000" + }, + "fcfc3a5004d678613f0b36a642269a7f371c3f6a": { + "balance": "1000000000000000000000" + }, + "f509557e90183fbf0f0651a786487bcc428ba175": { + "balance": "194000000000000000000" + }, + "e3d915eda3b825d6ee4af9328d32ac18ada35497": { + "balance": "500000000000000000000" + }, + "f237ef05261c34d79cc22b860de0f17f793c3860": { + "balance": "200000000000000000000" + }, + "a3a2e319e7d3a1448b5aa2468953160c2dbcba71": { + "balance": "2000000000000000000000" + }, + "3a368efe4ad786e26395ec9fc6ad698cae29fe01": { + "balance": "632200000000000000000" + }, + "8e3240b0810e1cf407a500804740cf8d616432a4": { + "balance": "40309000000000000000" + }, + "5691dd2f6745f20e22d2e1d1b955aa2903d65656": { + "balance": "1969606000000000000000" + }, + "5f93ff832774db5114c55bb4bf44ccf3b58f903f": { + "balance": "192026650000000000000000" + }, + "2c1cc6e18c152488ba11c2cc1bcefa2df306abd1": { + "balance": "1670000000000000000000" + }, + "bde9786a84e75b48f18e726dd78d70e4af3ed802": { + "balance": "5730000000000000000000" + }, + "79551cede376f747e3716c8d79400d766d2e0195": { + "balance": "46250000000000000000000" + }, + "49f028395b5a86c9e07f7778630e4c2e3d373a77": { + "balance": "122735000000000000000" + }, + "6a3694424c7cc6b8bcd9bccaba540cc1f5df18d7": { + "balance": "2000000000000000000000" + }, + "068e29b3f191c812a6393918f71ab933ae6847f2": { + "balance": "1999944000000000000000" + }, + "6e64e6129f224e378c0e6e736a7e7a06c211e9ec": { + "balance": "1000000000000000000000" + }, + "c4c15318d370c73318cc18bdd466dbaa4c6603bf": { + "balance": "19700000000000000000" + }, + "8035bcffaefdeeea35830c497d14289d362023de": { + "balance": "300000000000000000000" + }, + "a997dfc7986a27050848fa1c64d7a7d6e07acca2": { + "balance": "143000000000000000000" + }, + "2fe13a8d0785de8758a5e41876c36e916cf75074": { + "balance": "4000000000000000000000" + }, + "6f24c9af2b763480515d1b0951bb77a540f1e3f9": { + "balance": "1970000000000000000000" + }, + "4c23b370fc992bb67cec06e26715b62f0b3a4ac3": { + "balance": "10000000000000000000000" + }, + "4ac07673e42f64c1a25ec2fa2d86e5aa2b34e039": { + "balance": "2000000000000000000000" + }, + "117db836377fe15455e02c2ebda40b1ceb551b19": { + "balance": "6000000000000000000000" + }, + "ef1c0477f1184d60accab374d374557a0a3e10f3": { + "balance": "152000000000000000000" + }, + "99fe0d201228a753145655d428eb9fd94985d36d": { + "balance": "1939268000000000000000" + }, + "b3731b046c8ac695a127fd79d0a5d5fa6ae6d12e": { + "balance": "1998000000000000000000" + }, + "dce30c31f3ca66721ecb213c809aab561d9b52e4": { + "balance": "2000000000000000000000" + }, + "ddd69c5b9bf5eb5a39cee7c3341a120d973fdb34": { + "balance": "1987730000000000000000" + }, + "216e41864ef98f060da08ecae19ad1166a17d036": { + "balance": "5730000000000000000000" + }, + "6a53d41ae4a752b21abed5374649953a513de5e5": { + "balance": "2000000000000000000000" + }, + "20dd8fcbb46ea46fe381a68b8ca0ea5be21fe9a5": { + "balance": "2000000000000000000000" + }, + "19732bf973055dbd91a4533adaa2149a91d38380": { + "balance": "2000000000000000000000" + }, + "51ea1c0934e3d04022ed9c95a087a150ef705e81": { + "balance": "6280000000000000000000" + }, + "a0de5c601e696635c698b7ae9ca4539fc7b941ec": { + "balance": "346150000000000000000" + }, + "94e1f5cb9b8abace03a1a6428256553b690c2355": { + "balance": "20000000000000000000" + }, + "a539b4a401b584dfe0f344b1b422c65543167e2e": { + "balance": "200000000000000000000" + }, + "50584d9206a46ce15c301117ee28f15c30e60e75": { + "balance": "13400000000000000000" + }, + "856eb204241a87830fb229031343dc30854f581a": { + "balance": "1000000000000000000000" + }, + "9dd46b1c6d3f05e29e9c6f037eed9a595af4a9aa": { + "balance": "500000000000000000000" + }, + "8925da4549e15155e57a628522cea9dddf627d81": { + "balance": "1000070000000000000000" + }, + "a89df34859edd7c820db887740d8ff9e15157c7b": { + "balance": "2000000000000000000000" + }, + "ad9f4c890a3b511cee51dfe6cfd7f1093b76412c": { + "balance": "506600000000000000000" + }, + "f8c7f34a38b31801da43063477b12b27d0f203ff": { + "balance": "494800000000000000000" + }, + "a642501004c90ea9c9ed1998ba140a4cd62c6f5f": { + "balance": "250543000000000000000" + }, + "508cf19119db70aa86454253da764a2cb1b2be1a": { + "balance": "1000000000000000000000" + }, + "2979741174a8c1ea0b7f9edf658177859417f512": { + "balance": "461283000000000000000" + }, + "654f524847b3a6acc0d3d5f1f362b603edf65f96": { + "balance": "8000000000000000000000" + }, + "5cf18fa7c8a7c0a2b3d5efd1990f64ddc569242c": { + "balance": "1000000000000000000000" + }, + "17e82e7078dc4fd9e879fb8a50667f53a5c54591": { + "balance": "200000000000000000000" + }, + "8b07d050754dc9ba230db01c310afdb5395aa1b3": { + "balance": "118080000000000000000" + }, + "5f77a107ab1226b3f95f10ee83aefc6c5dff3edc": { + "balance": "500000000000000000000" + }, + "475a6193572d4a4e59d7be09cb960ddd8c530e2f": { + "balance": "667323000000000000000" + }, + "6470a4f92ec6b0fccd01234fa59023e9ff1f3aac": { + "balance": "3000000000000000000000" + }, + "2fbcef3384d420e4bf61a0669990bc7054f1a5af": { + "balance": "2000000000000000000000" + }, + "bbabf6643beb4bd01c120bd0598a0987d82967d1": { + "balance": "3342500000000000000000" + }, + "41a2f2e6ecb86394ec0e338c0fc97e9c5583ded2": { + "balance": "2009400000000000000000" + }, + "fb9473cf7712350a1fa0395273fc80560752e4fb": { + "balance": "123300000000000000000" + }, + "38b2197106123387a0d4de368431a8bacdda30e2": { + "balance": "20000000000000000000" + }, + "5ed56115bd6505a88273df5c56839470d24a2db7": { + "balance": "65601000000000000000" + }, + "523f6d64690fdacd942853591bb0ff20d3656d95": { + "balance": "1820000000000000000000" + }, + "55caff4bba04d220c9a5d2018672ec85e31ef83e": { + "balance": "2000000000000000000000" + }, + "65af8d8b5b1d1eedfa77bcbc96c1b133f83306df": { + "balance": "98000000000000000000" + }, + "7456c5b2c5436e3e571008933f1805ccfe34e9ec": { + "balance": "1000000000000000000000" + }, + "a6eebbe464d39187bf80ca9c13d72027ec5ba8be": { + "balance": "3000000000000000000000" + }, + "dd35cfdbcb993395537aecc9f59085a8d5ddb6f5": { + "balance": "1000000000000000000000" + }, + "98e2b6d606fd2d6991c9d6d4077fdf3fdd4585da": { + "balance": "901520000000000000000" + }, + "860f5ffc10de767ded807f71e861d647dfd219b1": { + "balance": "10000000000000000000000" + }, + "1a644a50cbc2aee823bd2bf243e825be4d47df02": { + "balance": "100007000000000000000" + }, + "a8455b411765d6901e311e726403091e42c56683": { + "balance": "3380000000000000000000" + }, + "3a86ee94862b743dd34f410969d94e2c5652d4ad": { + "balance": "201610000000000000000" + }, + "a57360f002e0d64d2d74457d8ca4857ee00bcddf": { + "balance": "335780000000000000000" + }, + "e59b3bd300893f97233ef947c46f7217e392f7e9": { + "balance": "1000000000000000000000" + }, + "9f3a74fd5e7edcc1162993171381cbb632b7cff0": { + "balance": "10000000000000000000000" + }, + "675d5caa609bf70a18aca580465d8fb7310d1bbb": { + "balance": "20000000000000000000000" + }, + "77f609ca8720a023262c55c46f2d26fb3930ac69": { + "balance": "17300000000000000000" + }, + "f8ac4a39b53c11307820973b441365cffe596f66": { + "balance": "2000000000000000000000" + }, + "112634b4ec30ff786e024159f796a57939ea144e": { + "balance": "1999944000000000000000" + }, + "49d2c28ee9bc545eaaf7fd14c27c4073b4bb5f1a": { + "balance": "1474134000000000000000" + }, + "91cc46aa379f856a6640dccd5a648a7902f849d9": { + "balance": "200000000000000000000" + }, + "b46440c797a556e04c7d9104660491f96bb076bf": { + "balance": "14900000000000000000" + }, + "e5968797468ef767101b761d431fce14abffdbb4": { + "balance": "8040000000000000000000" + }, + "c0895efd056d9a3a81c3da578ada311bfb9356cf": { + "balance": "200000000000000000000" + }, + "76846f0de03b5a76971ead298cdd08843a4bc6c6": { + "balance": "15500000000000000000" + }, + "5f708eaf39d823946c51b3a3e9b7b3c003e26341": { + "balance": "1820000000000000000000" + }, + "24f7450ddbf18b020feb1a2032d9d54b633edf37": { + "balance": "50000000000000000000" + }, + "cae3a253bcb2cf4e13ba80c298ab0402da7c2aa0": { + "balance": "5400000000000000000000" + }, + "91e8810652e8e6161525d63bb7751dc20f676076": { + "balance": "725000000000000000000" + }, + "543629c95cdef428ad37d453ca9538a9f90900ac": { + "balance": "43250000000000000000000" + }, + "6e79edd4845b076e4cd88d188b6e432dd93f35aa": { + "balance": "955000000000000000000" + }, + "bd325d4029e0d8729f6d399c478224ae9e7ae41e": { + "balance": "3880000000000000000000" + }, + "42cecfd2921079c2d7df3f08b07aa3beee5e219a": { + "balance": "1000000000000000000000" + }, + "3690246ba3c80679e22eac4412a1aefce6d7cd82": { + "balance": "20000000000000000000000" + }, + "577aeee8d4bc08fc97ab156ed57fb970925366be": { + "balance": "333046000000000000000" + }, + "fe00bf439911a553982db638039245bcf032dbdc": { + "balance": "394000000000000000000" + }, + "91f624b24a1fa5a056fe571229e7379db14b9a1e": { + "balance": "11999974000000000000000" + }, + "f206d328e471d0117b246d2a4619827709e96df3": { + "balance": "3001000000000000000000" + }, + "073f1ed1c9c3e9c52a9b0249a5c1caa0571fdf05": { + "balance": "70400000000000000000" + }, + "f56048dd2181d4a36f64fcecc6215481e42abc15": { + "balance": "200000000000000000000" + }, + "ef76a4cd8febcbc9b818f17828f8d93473f3f3cb": { + "balance": "4000000000000000000000" + }, + "1031e0ecb54985ae21af1793950dc811888fde7c": { + "balance": "20000000000000000000" + }, + "8e0fee38685a94aabcd7ce857b6b1409824f75b8": { + "balance": "500000000000000000000" + }, + "f0cbef84e169630098d4e301b20208ef05846ac9": { + "balance": "259084000000000000000" + }, + "bbca65b3266ea2fb73a03f921635f912c7bede00": { + "balance": "1970000000000000000000" + }, + "0aec2e426ed6cc0cf3c249c1897eac47a7faa9bd": { + "balance": "200000000000000000000" + }, + "b8f30758faa808dbc919aa7b425ec922b93b8129": { + "balance": "1000076000000000000000" + }, + "936dcf000194e3bff50ac5b4243a3ba014d661d8": { + "balance": "10000000000000000000000" + }, + "b14ddb0386fb606398b8cc47565afae00ff1d66a": { + "balance": "2973024000000000000000" + }, + "2ec95822eb887bc113b4712a4dfd7f13b097b5e7": { + "balance": "1000000000000000000000" + }, + "0136a5af6c3299c6b5f005fdaddb148c070b299b": { + "balance": "20368000000000000000" + }, + "37cb868d2c3f95b257611eb34a4188d58b749802": { + "balance": "2000000000000000000000" + }, + "cd7f09d7ed66d0c38bc5ad4e32b7f2b08dc1b30d": { + "balance": "1148000000000000000000" + }, + "b5fa8184e43ed3e0b8ab91216461b3528d84fd09": { + "balance": "2680000000000000000000" + }, + "3dbf0dbfd77890800533f09dea8301b9f025d2a6": { + "balance": "1000000000000000000000" + }, + "b553d25d6b5421e81c2ad05e0b8ba751f8f010e3": { + "balance": "2000000000000000000000" + }, + "dbf8b13967f55125272de0562536c450ba5655a0": { + "balance": "2046830000000000000000" + }, + "0f6e840a3f2a24647d8e43e09d45c7c335df4248": { + "balance": "2500000000000000000000" + }, + "fa2fd29d03fee9a07893df3a269f56b72f2e1e64": { + "balance": "10000000000000000000000" + }, + "8b57b2bc83cc8d4de331204e893f2f3b1db1079a": { + "balance": "40000000000000000000" + }, + "7f541491d2ac00d2612f94aa7f0bcb014651fbd4": { + "balance": "376000000000000000000" + }, + "4f4a9be10cd5d3fb5de48c17be296f895690645b": { + "balance": "40000000000000000000000" + }, + "45d1c9eedf7cab41a779057b79395f5428d80528": { + "balance": "2000000000000000000000" + }, + "662334814724935b7931ddca6100e00d467727cd": { + "balance": "637000000000000000000" + }, + "2c52c984102ee0cd3e31821b84d408930efa1ac7": { + "balance": "2000000000000000000000" + }, + "000d836201318ec6899a67540690382780743280": { + "balance": "200000000000000000000" + }, + "81498ca07b0f2f17e8bbc7e61a7f4ae7be66b78b": { + "balance": "101600000000000000000" + }, + "7860a3de38df382ae4a4dce18c0c07b98bce3dfa": { + "balance": "1000000000000000000000" + }, + "5e8e4df18cf0af770978a8df8dac90931510a679": { + "balance": "2000000000000000000000" + }, + "05d68dad61d3bbdfb3f779265c49474aff3fcd30": { + "balance": "39399000000000000000" + }, + "96eafbf2fb6f4db9a436a74c45b5654452e23819": { + "balance": "20000000000000000000" + }, + "d7d7f2caa462a41b3b30a34aeb3ba61010e2626f": { + "balance": "2000000000000000000000" + }, + "0b71f554122469ef978e2f1fefd7cbb410982772": { + "balance": "3880000000000000000000" + }, + "504666ce8931175e11a5ed11c1dcaa06e57f4e66": { + "balance": "11792000000000000000000" + }, + "d00f067286c0fbd082f9f4a61083ec76deb3cee6": { + "balance": "1000000000000000000000" + }, + "02e4cb22be46258a40e16d4338d802fffd00c151": { + "balance": "379786000000000000000" + }, + "1c13d38637b9a47ce79d37a86f50fb409c060728": { + "balance": "1337000000000000000000" + }, + "e30212b2011bb56bdbf1bc35690f3a4e0fd905ea": { + "balance": "8022000000000000000000" + }, + "1df6911672679bb0ef3509038c0c27e394fdfe30": { + "balance": "540000000000000000000" + }, + "2b8fe4166e23d11963c0932b8ade8e0145ea0770": { + "balance": "43250000000000000000000" + }, + "6509eeb1347e842ffb413e37155e2cbc738273fd": { + "balance": "2000000000000000000000" + }, + "8b7e9f6f05f7e36476a16e3e7100c9031cf404af": { + "balance": "1000000000000000000000" + }, + "bec8caf7ee49468fee552eff3ac5234eb9b17d42": { + "balance": "2000000000000000000000" + }, + "38898bbb4553e00bbfd0cf268b2fc464d154add5": { + "balance": "320000000000000000000" + }, + "cbb3189e4bd7f45f178b1c30c76e26314d4a4b0a": { + "balance": "295007000000000000000" + }, + "be1cd7f4c472070968f3bde268366b21eeea8321": { + "balance": "4300000000000000000000" + }, + "976a18536af41874426308871bcd1512a775c9f8": { + "balance": "10000000000000000000000" + }, + "e9c758f8da41e3346e4350e5ac3976345c6c1082": { + "balance": "1930050000000000000000" + }, + "64ec8a5b743f3479e707dae9ee20ddaa4f40f1d9": { + "balance": "200000000000000000000" + }, + "9e01765aff08bc220550aca5ea2e1ce8e5b09923": { + "balance": "1000000000000000000000" + }, + "ba0f39023bdb29eb1862a9f9059cab5d306e662f": { + "balance": "2000000000000000000000" + }, + "2baf8d6e221174124820ee492b9459ec4fadafbb": { + "balance": "2000000000000000000000" + }, + "655d5cd7489629e2413c2105b5a172d933c27af8": { + "balance": "4040060000000000000000" + }, + "badc2aef9f5951a8d78a6b35c3d0b3a4e6e2e739": { + "balance": "6000000000000000000000" + }, + "e64f6e1d6401b56c076b64a1b0867d0b2f310d4e": { + "balance": "51570000000000000000" + }, + "7a8563867901206f3f2bf0fa3e1c8109cabccd85": { + "balance": "137000000000000000000" + }, + "d17fbe22d90462ed37280670a2ea0b3086a0d6d6": { + "balance": "199955000000000000000" + }, + "e96d7d4cdd15553a4e4d316d6d6480ca3cea1e38": { + "balance": "12200000000000000000000" + }, + "f04d2c91efb6e9c45ffbe74b434c8c5f2b028f1f": { + "balance": "1000000000000000000000" + }, + "81164deb10814ae08391f32c08667b6248c27d7a": { + "balance": "394000000000000000000" + }, + "7f5ae05ae0f8cbe5dfe721f044d7a7bef4c27997": { + "balance": "60000000000000000000" + }, + "c982586d63b0d74c201b1af8418372e30c7616be": { + "balance": "100000000000000000000" + }, + "64cf0935bf19d2cebbecd8780d27d2e2b2c34166": { + "balance": "1970000000000000000000" + }, + "cd566ad7b883f01fd3998a9a58a9dee4724ddca5": { + "balance": "58848000000000000000" + }, + "9da609fa3a7e6cf2cc0e70cdabe78dc4e382e11e": { + "balance": "1200000000000000000000" + }, + "0d69100c395ce6c5eaadf95d05d872837ededd21": { + "balance": "400000000000000000000" + }, + "fe91eccf2bd566afa11696c5049fa84c69630a52": { + "balance": "1940000000000000000000" + }, + "005d0ee8155ec0a6ff6808552ca5f16bb5be323a": { + "balance": "197000000000000000000" + }, + "3e5cb8928c417825c03a3bfcc52183e5c91e42d7": { + "balance": "4264790000000000000000" + }, + "9c1b771f09af882af0643083de2aa79dc097c40e": { + "balance": "2480000000000000000000" + }, + "eba388b0da27c87b1cc0eac6c57b2c5a0b459c1a": { + "balance": "6800000000000000000000" + }, + "7529f3797bb6a20f7ea6492419c84c867641d81c": { + "balance": "2000000000000000000000" + }, + "532a7da0a5ad7407468d3be8e07e69c7dd64e861": { + "balance": "500000000000000000000" + }, + "de82cc8d4a1bb1d9434392965b3e80bad3c03d4f": { + "balance": "1477500000000000000000" + }, + "4a82694fa29d9e213202a1a209285df6e745c209": { + "balance": "4000000000000000000000" + }, + "3e53ff2107a8debe3328493a92a586a7e1f49758": { + "balance": "23143470000000000000000" + }, + "b2ddb786d3794e270187d0451ad6c8b79e0e8745": { + "balance": "400000000000000000000" + }, + "6ebcf9957f5fc5e985add475223b04b8c14a7aed": { + "balance": "1730000000000000000000" + }, + "c5c7590b5621ecf8358588de9b6890f2626143f1": { + "balance": "3000000000000000000000" + }, + "ae4f122e35c0b1d1e4069291457c83c07f965fa3": { + "balance": "1000000000000000000000" + }, + "47885ababedf4d928e1c3c71d7ca40d563ed595f": { + "balance": "1820000000000000000000" + }, + "78ce3e3d474a8a047b92c41542242d0a08c70f99": { + "balance": "10000000000000000000000" + }, + "6134d942f037f2cc3d424a230c603d67abd3edf7": { + "balance": "2000000000000000000000" + }, + "1360e87df24c69ee6d51c76e73767ffe19a2131c": { + "balance": "92000000000000000000" + }, + "5fd1c3e31778276cb42ea740f5eae9c641dbc701": { + "balance": "194000000000000000000" + }, + "98397342ec5f3d4cb877e54ef5d6f1d366731bd4": { + "balance": "5910000000000000000000" + }, + "6d4b5c05d06a20957e1748ab6df206f343f92f01": { + "balance": "10020475000000000000000" + }, + "e6115b13f9795f7e956502d5074567dab945ce6b": { + "balance": "100000000000000000000000" + }, + "23730c357a91026e44b1d0e2fc2a51d071d8d77b": { + "balance": "4000000000000000000000" + }, + "fae881937047895a660cf229760f27e66828d643": { + "balance": "182000000000000000000" + }, + "ff3ef6ba151c21b59986ae64f6e8228bc9a2c733": { + "balance": "2000000000000000000000" + }, + "dfbd4232c17c407a980db87ffbcda03630e5c459": { + "balance": "553150000000000000000" + }, + "4429a29fee198450672c0c1d073162250bec6474": { + "balance": "999200000000000000000" + }, + "7e8f96cc29f57b0975120cb593b7dd833d606b53": { + "balance": "197000000000000000000" + }, + "5ed3f1ebe2ae6756b5d8dc19cad02c419aa5778b": { + "balance": "0" + }, + "daa776a6754469d7b9267a89b86725e740da0fa0": { + "balance": "1970000000000000000000" + }, + "139e479764b499d666208c4a8a047a97043163dd": { + "balance": "598880000000000000000" + }, + "5ad5e420755613886f35aa56ac403eebdfe4b0d0": { + "balance": "80000000000000000000000" + }, + "3fe801e61335c5140dc7eda2ef5204460a501230": { + "balance": "2000000000000000000000" + }, + "ce8a6b6d5033b1498b1ffeb41a41550405fa03a2": { + "balance": "4000000000000000000000" + }, + "26c2ffc30efdc5273e76183a16c2698d6e531286": { + "balance": "776000000000000000000" + }, + "71ec3aec3f8f9221f9149fede06903a0f9a232f2": { + "balance": "200000000000000000000" + }, + "ef35f6d4b1075e6aa139151c974b2f4658f70538": { + "balance": "1111111000000000000000" + }, + "26a68eab905a8b3dce00e317308225dab1b9f6b8": { + "balance": "1980000000000000000000" + }, + "63f5b53d79bf2e411489526530223845fac6f601": { + "balance": "30000000000000000000000" + }, + "481115296ab7db52492ff7b647d63329fb5cbc6b": { + "balance": "16100000000000000000000" + }, + "f19f193508393e4d2a127b20b2031f39c82581c6": { + "balance": "3500088000000000000000" + }, + "500e34cde5bd9e2b71bb92d7cf55eee188d5fa0c": { + "balance": "5348000000000000000000" + }, + "65ea67ad3fb56ad5fb94387dd38eb383001d7c68": { + "balance": "100000000000000000000" + }, + "7f9f9b56e4289dfb58e70fd5f12a97b56d35c6a5": { + "balance": "1970000000000000000000" + }, + "60be6f953f2a4d25b6256ffd2423ac1438252e4e": { + "balance": "150000000000000000000" + }, + "ac1dfc984b71a19929a81d81f04a7cbb14073703": { + "balance": "600000000000000000000" + }, + "a3c14ace28b192cbb062145fcbbd5869c67271f6": { + "balance": "8000000000000000000000" + }, + "2da76b7c39b420e388ba2c1020b0856b0270648a": { + "balance": "2000000000000000000000" + }, + "622be4b45495fcd93143efc412d699d6cdc23dc5": { + "balance": "17300000000000000000" + }, + "d3f873bd9956135789ab00ebc195b922e94b259d": { + "balance": "2000000000000000000000" + }, + "975f3764e97bbccf767cbd3b795ba86d8ba9840e": { + "balance": "346000000000000000000" + }, + "fc39be41094b1997d2169e8264c2c3baa6c99bc4": { + "balance": "2000000000000000000000" + }, + "12ffc1128605cb0c13709a7290506f2690977193": { + "balance": "3340000000000000000000" + }, + "9b1168de8ab64b47552f3389800a9cc08b4666cf": { + "balance": "1730000000000000000000" + }, + "9f1aa8fcfc89a1a5328cbd6344b71f278a2ca4a0": { + "balance": "500000000000000000000" + }, + "505a33a18634dd4800693c67f48a1d693d4833f8": { + "balance": "7252000000000000000000" + }, + "d08fc09a0030fd0928cd321198580182a76aae9f": { + "balance": "1000000000000000000000" + }, + "6acddca3cd2b4990e25cd65c24149d0912099e79": { + "balance": "3000037000000000000000" + }, + "397a6ef8763a18f00fac217e055c0d3094101011": { + "balance": "2000000000000000000000" + }, + "4e0bd32473c4c51bf25654def69f797c6b29a232": { + "balance": "1600930000000000000000" + }, + "28d8c35fb7eea622582135e3ad47a227c9a663bd": { + "balance": "18200000000000000000" + }, + "f96488698590dc3b2c555642b871348dfa067ad5": { + "balance": "500000000000000000000" + }, + "4eebe80cb6f3ae5904f6f4b28d907f907189fcab": { + "balance": "1999944000000000000000" + }, + "8d1abd897dacd4312e18080c88fb9647eab44052": { + "balance": "216000000000000000000" + }, + "457029c469c4548d168cec3e65872e4428d42b67": { + "balance": "2000000000000000000000" + }, + "1296acded1e063af39fe8ba0b4b63df789f70517": { + "balance": "100014000000000000000" + }, + "71762c63678c18d1c6378ce068e666381315147e": { + "balance": "2000000000000000000000" + }, + "6cc1c878fa6cde8a9a0b8311247e741e4642fe6d": { + "balance": "985000000000000000000" + }, + "8d9ed7f4553058c26f7836a3802d3064eb1b363d": { + "balance": "90000000000000000000" + }, + "5032e4bcf7932b49fdba377b6f1499636513cfc3": { + "balance": "100000000000000000000" + }, + "462b678b51b584f3ed7ada070b5cd99c0bf7b87f": { + "balance": "100000000000000000000" + }, + "c8aa49e3809f0899f28ab57e6743709d58419033": { + "balance": "880000000000000000000" + }, + "01b1cae91a3b9559afb33cdc6d689442fdbfe037": { + "balance": "200000000000000000000" + }, + "b1043004ec1941a8cf4f2b00b15700ddac6ff17e": { + "balance": "1000000000000000000000" + }, + "5ba2c6c35dfaec296826591904d544464aeabd5e": { + "balance": "20000000000000000000" + }, + "b32400fd13c5500917cb037b29fe22e7d5228f2d": { + "balance": "40000000000000000000000" + }, + "d59d92d2c8701980cc073c375d720af064743c0c": { + "balance": "19000000000000000000000" + }, + "11dd6185d9a8d73ddfdaa71e9b7774431c4dfec2": { + "balance": "1000000000000000000000" + }, + "d4cb21e590c5a0e06801366aff342c7d7db16424": { + "balance": "494000000000000000000" + }, + "5b6d55f6712967405c659129f4b1de09acf2cb7b": { + "balance": "267400000000000000000" + }, + "6179979907fe7f037e4c38029d60bcbab832b3d6": { + "balance": "1610000000000000000000" + }, + "33c407133b84b3ca4c3ded1f4658900c38101624": { + "balance": "2800000000000000000000" + }, + "cd2a36d753e9e0ed012a584d716807587b41d56a": { + "balance": "261400000000000000000" + }, + "8155fa6c51eb31d808412d748aa086105018122f": { + "balance": "1880000000000000000000" + }, + "3ecc8e1668dde995dc570fe414f44211c534a615": { + "balance": "2000000000000000000000" + }, + "d6395db5a4bb66e60f4cfbcdf0057bb4d97862e2": { + "balance": "910000000000000000000" + }, + "b6fb39786250081426a342c70d47ee521e5bc563": { + "balance": "15000000000000000000000" + }, + "510eda5601499a0d5e1a006bfffd833672f2e267": { + "balance": "2000000000000000000000" + }, + "98c19dba810ba611e68f2f83ee16f6e7744f0c1f": { + "balance": "200000000000000000000" + }, + "34ff26eb60a8d1a95a489fae136ee91d4e58084c": { + "balance": "600000000000000000000" + }, + "6ad90be252d9cd464d998125fab693060ba8e429": { + "balance": "4000000000000000000000" + }, + "038323b184cff7a82ae2e1bda7793fe4319ca0bf": { + "balance": "20000000000000000000000" + }, + "dc5305b4020a06b49d657c7ca34c35c91c5f2c56": { + "balance": "7045990000000000000000" + }, + "c9c80dc12e7bab86e949d01e4c3ed35f2b9bba5f": { + "balance": "2000000000000000000000" + }, + "7beb81fb2f5e91526b2ac9795e76c69bcff04bc0": { + "balance": "69400000000000000000000" + }, + "b8bc9bca7f71b4ed12e620438d620f53c114342f": { + "balance": "500000000000000000000" + }, + "d288e7cb7ba9f620ab0f7452e508633d1c5aa276": { + "balance": "4000000000000000000000" + }, + "a2e460a989cb15565f9ecca7d121a18e4eb405b6": { + "balance": "2000000000000000000000" + }, + "7489cc8abe75cda4ef0d01cef2605e47eda67ab1": { + "balance": "133700000000000000000" + }, + "38b403fb1fb7c14559a2d6f6564a5552bca39aff": { + "balance": "2000000000000000000000" + }, + "e55c80520a1b0f755b9a2cd3ce214f7625653e8a": { + "balance": "2000000000000000000000" + }, + "451b7070259bdba27100e36e23428a53dfe304e9": { + "balance": "13370000000000000000" + }, + "8b5c914b128bf1695c088923fa467e7911f351fa": { + "balance": "98500000000000000000" + }, + "17df49518d73b129f0da36b1c9b40cb66420fdc7": { + "balance": "10000000000000000000000" + }, + "c1950543554d8a713003f662bb612c10ad4cdf21": { + "balance": "18200000000000000000" + }, + "fa7606435b356cee257bd2fcd3d9eacb3cd1c4e1": { + "balance": "100000000000000000000" + }, + "e0bad98eee9698dbf6d76085b7923de5754e906d": { + "balance": "167000000000000000000" + }, + "ce53c8cdd74296aca987b2bc19c2b875a48749d0": { + "balance": "3000000000000000000000" + }, + "d0c55abf976fdc3db2afe9be99d499484d576c02": { + "balance": "1000000000000000000000" + }, + "238a6b7635252f5244486c0af0a73a207385e039": { + "balance": "1370000000000000000000" + }, + "ceb389381d48a8ae4ffc483ad0bb5e204cfdb1ec": { + "balance": "740745000000000000000" + }, + "3847667038f33b01c1cc795d8daf5475eff5a0d4": { + "balance": "728330000000000000000" + }, + "a08d215b5b6aac4861a281ac7e400b78fef04cbf": { + "balance": "20000000000000000000" + }, + "2d0dec51a6e87330a6a8fa2a0f65d88d4abcdf73": { + "balance": "185000000000000000000" + }, + "9e8f64ddcde9b8b451bafaa235a9bf511a25ac91": { + "balance": "2674000000000000000000" + }, + "ddac6bf4bbdd7d597d9c686d0695593bedccc7fa": { + "balance": "865000000000000000000" + }, + "22e15158b5ee3e86eb0332e3e6a9ac6cd9b55ecd": { + "balance": "160000000000000000000" + }, + "3aea4e82d2400248f99871a41ca257060d3a221b": { + "balance": "1000000000000000000000" + }, + "fb126f0ec769f49dcefca2f200286451583084b8": { + "balance": "5013750000000000000000" + }, + "1b8bd6d2eca20185a78e7d98e8e185678dac4830": { + "balance": "16700000000000000000000" + }, + "664cd67dccc9ac8228b45c55db8d76550b659cdc": { + "balance": "394000000000000000000" + }, + "553f37d92466550e9fd775ae74362df030179132": { + "balance": "2000000000000000000000" + }, + "730d8763c6a4fd824ab8b859161ef7e3a96a1200": { + "balance": "20000000000000000000000" + }, + "04c2c64bb54c3eccd05585e10ec6f99a0cdb01a3": { + "balance": "100000000000000000000" + }, + "f1624d980b65336feac5a6d54125005cfcf2aacb": { + "balance": "2000000000000000000000" + }, + "0b7fc9ddf70576f6330669eaaa71b6a831e99528": { + "balance": "140000000000000000000" + }, + "fa2bbca15d3fe39f8a328e91f90da14f7ac6253d": { + "balance": "200000000000000000000" + }, + "07feef54c136850829badc4b49c3f2a73c89fb9e": { + "balance": "118200000000000000000" + }, + "3703350c4d6fe337342cddc65bf1e2386bf3f9b2": { + "balance": "2020000000000000000000" + }, + "6d7d1c949511f88303808c60c5ea0640fcc02683": { + "balance": "10000000000000000000000" + }, + "34fa7792bad8bbd7ff64056214a33eb6600c1ea8": { + "balance": "50000000000000000000" + }, + "994cc2b5227ec3cf048512467c41b7b7b748909f": { + "balance": "2000000000000000000000" + }, + "08da3a7a0f452161cfbcec311bb68ebfdee17e88": { + "balance": "2000000000000000000000" + }, + "bbb4ee1d82f2e156442cc93338a2fc286fa28864": { + "balance": "1370000000000000000000" + }, + "7a2dfc770e24368131b7847795f203f3d50d5b56": { + "balance": "11400000000000000000000" + }, + "7cef4d43aa417f9ef8b787f8b99d53f1fea1ee88": { + "balance": "1910000000000000000000" + }, + "c6a30ef5bb3320f40dc5e981230d52ae3ac19322": { + "balance": "182000000000000000000" + }, + "6a74844d8e9cb5581c45079a2e94462a6cee8821": { + "balance": "1082970000000000000000" + }, + "c3110be01dc9734cfc6e1ce07f87d77d1345b7e1": { + "balance": "4999998000000000000000" + }, + "aeb916ebf49d0f86c13f7331cef19e129937512d": { + "balance": "599908000000000000000" + }, + "3e5abd09ce5af7ba8487c359e0f2a93a986b0b18": { + "balance": "10000000000000000000000" + }, + "cdd60d73efaad873c9bbfb178ca1b7105a81a681": { + "balance": "32000000000000000000" + }, + "31eb123c95c82bf685ace7a75a1881a289efca10": { + "balance": "920034000000000000000" + }, + "86e8670e27598ea09c3899ab7711d3b9fe901c17": { + "balance": "200000000000000000000" + }, + "a144f6b60f72d64a21e330dadb62d8990ade2b09": { + "balance": "1000000000000000000000" + }, + "68883e152e5660fee59626e7e3b4f05110e6222f": { + "balance": "54683300000000000000000" + }, + "fe4249127950e2f896ec0e7e2e3d055aab10550f": { + "balance": "668500000000000000000" + }, + "403d53cf620f0922b417848dee96c190b5bc8271": { + "balance": "9850000000000000000000" + }, + "bec2e6de39c07c2bae556acfbee2c4728b9982e3": { + "balance": "573000000000000000000" + }, + "f3c4716d1ee5279a86d0163a14618181e16136c7": { + "balance": "1000000000000000000000" + }, + "e38ef28a5ed984a7db24a1ae782dfb87f397dfc6": { + "balance": "143000000000000000000" + }, + "30fbe5885f9fcce9ea5edb82ed4a1196dd259aed": { + "balance": "5200000000000000000000" + }, + "48bf14d7b1fc84ebf3c96be12f7bce01aa69b03e": { + "balance": "120000000000000000000" + }, + "b8d5c324a8209d7c8049d0d4aede02ba80ab578b": { + "balance": "16889329000000000000000" + }, + "43d5a71ce8b8f8ae02b2eaf8eaf2ca2840b93fb6": { + "balance": "6000000000000000000000" + }, + "f9a59c3cc5ffacbcb67be0fc7256f64c9b127cb4": { + "balance": "2000000000000000000000" + }, + "0e21af1b8dbf27fcf63f37e047b87a825cbe7c27": { + "balance": "3000000000000000000000" + }, + "1c35aab688a0cd8ef82e76541ba7ac39527f743b": { + "balance": "500000000000000000000" + }, + "91ac5cfe67c54aa7ebfba448666c461a3b1fe2e1": { + "balance": "401880000000000000000" + }, + "4ba53ab549e2016dfa223c9ed5a38fad91288d07": { + "balance": "1400000000000000000000" + }, + "99a4de19ded79008cfdcd45d014d2e584b8914a8": { + "balance": "1500000000000000000000" + }, + "4adbf4aae0e3ef44f7dd4d8985cfaf096ec48e98": { + "balance": "150000000000000000000" + }, + "9a633fcd112cceeb765fe0418170732a9705e79c": { + "balance": "18200000000000000000" + }, + "292f228b0a94748c8eec612d246f989363e08f08": { + "balance": "185000000000000000000" + }, + "9f3497f5ef5fe63095836c004eb9ce02e9013b4b": { + "balance": "633424000000000000000" + }, + "0e6dfd553b2e873d2aec15bd5fbb3f8472d8d394": { + "balance": "12000000000000000000000" + }, + "74ebf4425646e6cf81b109ce7bf4a2a63d84815f": { + "balance": "40000000000000000000" + }, + "8ce5e3b5f591d5eca38abf228f2e3c35134bdac0": { + "balance": "2319920000000000000000" + }, + "90c41eba008e20cbe927f346603fc88698125969": { + "balance": "42000000000000000000" + }, + "382ba76db41b75606dd48a48f0137e9174e031b6": { + "balance": "20000000000000000000" + }, + "5d24bdbc1c47f0eb83d128cae48ac33c4817e91f": { + "balance": "1000000000000000000000" + }, + "a64e5ffb704c2c9139d77ef61d8cdfa31d7a88e9": { + "balance": "143000000000000000000" + }, + "a18360e985f2062e8f8efe02ad2cbc91ad9a5aad": { + "balance": "3000000000000000000000" + }, + "d251f903ae18727259eee841a189a1f569a5fd76": { + "balance": "10000000000000000000000" + }, + "efa6b1f0db603537826891b8b4bc163984bb40cd": { + "balance": "985000000000000000000" + }, + "47fff42c678551d141eb75a6ee398117df3e4a8d": { + "balance": "100010000000000000000" + }, + "f2294adbb6f0dcc76e632ebef48ab49f124dbba4": { + "balance": "1443690000000000000000" + }, + "53700d53254d430f22781a4a76a463933b5d6b08": { + "balance": "1970000000000000000000" + }, + "b14a7aaa8f49f2fb9a8102d6bbe4c48ae7c06fb2": { + "balance": "8000000000000000000000" + }, + "9ed4e63f526542d44fddd34d59cd25388ffd6bda": { + "balance": "3885000000000000000000" + }, + "4cac91fb83a147d2f76c3267984b910a79933348": { + "balance": "2167000000000000000000" + }, + "9b32cf4f5115f4b34a00a64c617de06387354323": { + "balance": "105501000000000000000" + }, + "b8bedd576a4b4c2027da735a5bc3f533252a1808": { + "balance": "2000000000000000000000" + }, + "c5a3b98e4593fea0b38c4f455a5065f051a2f815": { + "balance": "20309030000000000000000" + }, + "eaf52388546ec35aca6f6c6393d8d609de3a4bf3": { + "balance": "20000000000000000000" + }, + "4c423c76930d07f93c47a5cc4f615745c45a9d72": { + "balance": "100000000000000000000" + }, + "9052f2e4a3e3c12dd1c71bf78a4ec3043dc88b7e": { + "balance": "267400000000000000000" + }, + "2bade91d154517620fd4b439ac97157a4102a9f7": { + "balance": "4000000000000000000000" + }, + "da698d64c65c7f2b2c7253059cd3d181d899b6b7": { + "balance": "295500000000000000000" + }, + "c6d8954e8f3fc533d2d230ff025cb4dce14f3426": { + "balance": "400000000000000000000" + }, + "349a816b17ab3d27bbc0ae0051f6a070be1ff29d": { + "balance": "10000000000000000000000" + }, + "ff4d9c8484c43c42ff2c5ab759996498d323994d": { + "balance": "4000000000000000000000" + }, + "22944fbca9b57963084eb84df7c85fb9bcdfb856": { + "balance": "4649845000000000000000" + }, + "bfd93c90c29c07bc5fb5fc49aeea55a40e134f35": { + "balance": "28000000000000000000000" + }, + "3caedb5319fe806543c56e5021d372f71be9062e": { + "balance": "40000000000000000000000" + }, + "9a079c92a629ca15c8cafa2eb28d5bc17af82811": { + "balance": "500000000000000000000" + }, + "7d2a52a7cf0c8436a8e007976b6c26b7229d1e15": { + "balance": "438040000000000000000" + }, + "cf89f7460ba3dfe83c5a1d3a019ee1250f242f0f": { + "balance": "985177000000000000000" + }, + "577bfe64e3a1e3800e94db1c6c184d8dc8aafc66": { + "balance": "1498000000000000000000" + }, + "7ffd02ed370c7060b2ae53c078c8012190dfbb75": { + "balance": "10000000000000000000000" + }, + "90b62f131a5f29b45571513ee7a74a8f0b232202": { + "balance": "158000000000000000000" + }, + "6e8212b722afd408a7a73ed3e2395ee6454a0330": { + "balance": "159000000000000000000" + }, + "515f30bc90cdf4577ee47d65d785fbe2e837c6bc": { + "balance": "10166128000000000000000" + }, + "c27376f45d21e15ede3b26f2655fcee02ccc0f2a": { + "balance": "20000000000000000000" + }, + "3da39ce3ef4a7a3966b32ee7ea4ebc2335a8f11f": { + "balance": "2000000000000000000000" + }, + "25259d975a21d83ae30e33f800f53f37dfa01938": { + "balance": "20000000000000000000" + }, + "8ed143701f2f72280fd04a7b4164281979ea87c9": { + "balance": "14000000000000000000" + }, + "5ac99ad7816ae9020ff8adf79fa9869b7cea6601": { + "balance": "21000000000000000000000" + }, + "f51fded80acb502890e87369741f3722514cefff": { + "balance": "20000042000000000000000" + }, + "f657fcbe682eb4e8db152ecf892456000b513d15": { + "balance": "1940000000000000000000" + }, + "62c37c52b97f4b040b1aa391d6dec152893c4707": { + "balance": "1000000000000000000000" + }, + "89fc8e4d386b0d0bb4a707edf3bd560df1ad8f4e": { + "balance": "2955000000000000000000" + }, + "53c0bb7fc88ea422d2ef7e540e2d8f28b1bb8183": { + "balance": "20000000000000000000" + }, + "56f493a3d108aaa2d18d98922f8efe1662cfb73d": { + "balance": "2020000000000000000000" + }, + "e9458f68bb272cb5673a04f781b403556fd3a387": { + "balance": "61000000000000000000" + }, + "be525a33ea916177f17283fca29e8b350b7f530b": { + "balance": "2638000000000000000000" + }, + "4feb846be43041fd6b34202897943e3f21cb7f04": { + "balance": "83226000000000000000" + }, + "15aa530dc36958b4edb38eee6dd9e3c77d4c9145": { + "balance": "2000000000000000000000" + }, + "2458d6555ff98a129cce4037953d00206eff4287": { + "balance": "197000000000000000000" + }, + "8035fe4e6b6af27ae492a578515e9d39fa6fa65b": { + "balance": "4000000000000000000000" + }, + "296b71c0015819c242a7861e6ff7eded8a5f71e3": { + "balance": "1999800000000000000000" + }, + "8f1952eed1c548d9ee9b97d0169a07933be69f63": { + "balance": "1000000000000000000000" + }, + "a421dbb89b3a07419084ad10c3c15dfe9b32d0c2": { + "balance": "20000000000000000000000" + }, + "554336ee4ea155f9f24f87bca9ca72e253e12cd2": { + "balance": "100000000000000000000" + }, + "ffc5fc4b7e8a0293ff39a3a0f7d60d2646d37a74": { + "balance": "2000000000000000000000" + }, + "ea2c197d26e98b0da83e1b72c787618c979d3db0": { + "balance": "19700000000000000000" + }, + "96aa573fed2f233410dbae5180145b23c31a02f0": { + "balance": "1730000000000000000000" + }, + "c23b2f921ce4a37a259ee4ad8b2158d15d664f59": { + "balance": "25403000000000000000" + }, + "d874b9dfae456a929ba3b1a27e572c9b2cecdfb3": { + "balance": "170000000000000000000" + }, + "bf8b8005d636a49664f74275ef42438acd65ac91": { + "balance": "200000000000000000000" + }, + "441a52001661fac718b2d7b351b7c6fb521a7afd": { + "balance": "400000000000000000000" + }, + "812a55c43caedc597218379000ce510d548836fd": { + "balance": "18200000000000000000" + }, + "5e90c85877198756b0366c0e17b28e52b446505a": { + "balance": "374288000000000000000" + }, + "da3017c150dd0dce7fcf881b0a48d0d1c756c4c7": { + "balance": "100014000000000000000" + }, + "6baf7a2a02ae78801e8904ad7ac05108fc56cff6": { + "balance": "1000000000000000000000" + }, + "177dae78bc0113d8d39c4402f2a641ae2a105ab8": { + "balance": "1818320000000000000000" + }, + "01b5b5bc5a117fa08b34ed1db9440608597ac548": { + "balance": "200000000000000000000" + }, + "aae732eda65988c3a00c7f472f351c463b1c968e": { + "balance": "2000000000000000000000" + }, + "d95342953c8a21e8b635eefac7819bea30f17047": { + "balance": "94160000000000000000000" + }, + "8d616b1eee77eef6f176e0698db3c0c141b2fc8f": { + "balance": "500000000000000000000" + }, + "12d20790b7d3dbd88c81a279b812039e8a603bd0": { + "balance": "1604400000000000000000" + }, + "3734cb187491ede713ae5b3b2d12284af46b8101": { + "balance": "3000000000000000000000" + }, + "dd967c4c5f8ae47e266fb416aad1964ee3e7e8c3": { + "balance": "7750000000000000000000" + }, + "3dcef19c868b15d34eda426ec7e04b18b6017002": { + "balance": "1999800000000000000000" + }, + "ce9d21c692cd3c01f2011f505f870036fa8f6cd2": { + "balance": "400000000000000000000" + }, + "d44f6ac3923b5fd731a4c45944ec4f7ec52a6ae4": { + "balance": "10000000000000000000000" + }, + "b424d68d9d0d00cec1938c854e15ffb880ba0170": { + "balance": "200000000000000000000" + }, + "1f2186ded23e0cf9521694e4e164593e690a9685": { + "balance": "300000000000000000000" + }, + "7f4b5e278578c046cceaf65730a0e068329ed5b6": { + "balance": "1880000000000000000000" + }, + "8c50aa2a9212bcde56418ae261f0b35e7a9dbb82": { + "balance": "400000000000000000000" + }, + "1953313e2ad746239cb2270f48af34d8bb9c4465": { + "balance": "2000000000000000000000" + }, + "a15025f595acdbf3110f77c5bf24477e6548f9e8": { + "balance": "2000000000000000000000" + }, + "53af32c22fef99803f178cf90b802fb571c61cb9": { + "balance": "3880000000000000000000" + }, + "d0a8abd80a199b54b08b65f01d209c27fef0115b": { + "balance": "6525979000000000000000" + }, + "2b68306ba7f8daaf73f4c644ef7d2743c0f26856": { + "balance": "864800000000000000000" + }, + "96924191b7df655b3319dc6d6137f481a73a0ff3": { + "balance": "4020000000000000000000" + }, + "6fa72015fa78696efd9a86174f7f1f21019286b1": { + "balance": "1337000000000000000000" + }, + "0b119df99c6b8de58a1e2c3f297a6744bf552277": { + "balance": "2000000000000000000000" + }, + "61733947fab820dbd351efd67855ea0e881373a0": { + "balance": "20000000000000000000" + }, + "8ae6f80b70e1f23c91fbd5a966b0e499d95df832": { + "balance": "197000000000000000000" + }, + "01a7d9fa7d0eb1185c67e54da83c2e75db69e39f": { + "balance": "7623900000000000000000" + }, + "9932ef1c85b75a9b2a80057d508734c51085becc": { + "balance": "50170000000000000000" + }, + "aefcfe88c826ccf131d54eb4ea9eb80e61e1ee25": { + "balance": "340000000000000000000" + }, + "c21fa6643a1f14c02996ad7144b75926e87ecb4b": { + "balance": "20000000000000000000000" + }, + "97d9e46a7604d7b5a4ea4ee61a42b3d2350fc3ed": { + "balance": "2000000000000000000000" + }, + "3cafaf5e62505615068af8eb22a13ad8a9e55070": { + "balance": "1999600000000000000000" + }, + "22f2dcff5ad78c3eb6850b5cb951127b659522e6": { + "balance": "13700000000000000000" + }, + "aaad1baade5af04e2b17439e935987bf8c2bb4b9": { + "balance": "2000000000000000000000" + }, + "298887bab57c5ba4f0615229d7525fa113b7ea89": { + "balance": "40000000000000000000" + }, + "7539333046deb1ef3c4daf50619993f444e1de68": { + "balance": "1182000000000000000000" + }, + "9752d14f5e1093f071711c1adbc4e3eb1e5c57f3": { + "balance": "2000000000000000000000" + }, + "ed641e06368fb0efaa1703e01fe48f4a685309eb": { + "balance": "200000000000000000000" + }, + "d0ee4d02cf24382c3090d3e99560de3678735cdf": { + "balance": "2400000000000000000000" + }, + "47e25df8822538a8596b28c637896b4d143c351d": { + "balance": "80500000000000000000000" + }, + "559706c332d20779c45f8a6d046a699159b74921": { + "balance": "380123000000000000000" + }, + "3a4da78dce05aeb87de9aead9185726da1926798": { + "balance": "200000000000000000000" + }, + "3041445a33ba158741160d9c344eb88e5c306f94": { + "balance": "60000000000000000000" + }, + "08d4311c9c1bbaf87fabe1a1d01463828d5d98ce": { + "balance": "90000000000000000000000" + }, + "6bd3e59f239fafe4776bb9bddd6bee83ba5d9d9f": { + "balance": "1000000000000000000000" + }, + "29eaae82761762f4d2db53a9c68b0f6b0b6d4e66": { + "balance": "2000000000000000000000" + }, + "0b7d339371e5be6727e6e331b5821fa24bdb9d5a": { + "balance": "857738000000000000000" + }, + "4714cfa4f46bd6bd70737d75878197e08f88e631": { + "balance": "11792000000000000000000" + }, + "ad92ca066edb7c711dfc5b166192d1edf8e77185": { + "balance": "36000000000000000000000" + }, + "f97b56ebd5b77abc9fbacbabd494b9d2c221cd03": { + "balance": "1970000000000000000000" + }, + "591bef3171d1c5957717a4e98d17eb142c214e56": { + "balance": "20000000000000000000000" + }, + "899b3c249f0c4b81df75d212004d3d6d952fd223": { + "balance": "2000000000000000000000" + }, + "a819d2ece122e028c8e8a04a064d02b9029b08b9": { + "balance": "1000000000000000000000" + }, + "e341642d40d2afce2e9107c67079ac7a2660086c": { + "balance": "400000000000000000000" + }, + "0329188f080657ab3a2afa522467178279832085": { + "balance": "216700000000000000000" + }, + "03317826d1f70aa4bddfa09be0c4105552d2358b": { + "balance": "38800000000000000000" + }, + "3ac9dc7a436ae98fd01c7a9621aa8e9d0b8b531d": { + "balance": "1790000000000000000000" + }, + "93c88e2d88621e30f58a9586bed4098999eb67dd": { + "balance": "31200000000000000000000" + }, + "cd1e66ed539dd92fc40bbaa1fa16de8c02c14d45": { + "balance": "230000000000000000000" + }, + "e6c81ffcecb47ecdc55c0b71e4855f3e5e97fc1e": { + "balance": "334250000000000000000" + }, + "50f8fa4bb9e2677c990a4ee8ce70dd1523251e4f": { + "balance": "26030000000000000000" + }, + "4f64a85e8e9a40498c0c75fceb0337fb49083e5e": { + "balance": "1000000000000000000000" + }, + "4b29437c97b4a844be71cca3b648d4ca0fdd9ba4": { + "balance": "150200000000000000000" + }, + "1eee6cbee4fe96ad615a9cf5857a647940df8c78": { + "balance": "19400000000000000000" + }, + "29f0edc60338e7112085a1d114da8c42ce8f55d6": { + "balance": "2958000000000000000000" + }, + "23b1c4917fbd93ee3d48389306957384a5496cbf": { + "balance": "4000086000000000000000" + }, + "1767525c5f5a22ed80e9d4d7710f0362d29efa33": { + "balance": "400000000000000000000" + }, + "3064899a963c4779cbf613cd6980846af1e6ec65": { + "balance": "6999908000000000000000" + }, + "68531f4dda808f5320767a03113428ca0ce2f389": { + "balance": "19400000000000000000" + }, + "1db9ac9a9eaeec0a523757050c71f47278c72d50": { + "balance": "1337000000000000000000" + }, + "7592c69d067b51b6cc639d1164d5578c60d2d244": { + "balance": "20000000000000000000" + }, + "cf3fbfa1fd32d7a6e0e6f8ef4eab57be34025c4c": { + "balance": "1063120000000000000000" + }, + "8efec058cc546157766a632775404a334aaada87": { + "balance": "1999000000000000000000" + }, + "faf5f0b7b6d558f5090d9ea1fb2d42259c586078": { + "balance": "6401000000000000000000" + }, + "19ecf2abf40c9e857b252fe1dbfd3d4c5d8f816e": { + "balance": "2000000000000000000000" + }, + "6e8a26689f7a2fdefd009cbaaa5310253450daba": { + "balance": "2049982000000000000000" + }, + "e2f40d358f5e3fe7463ec70480bd2ed398a7063b": { + "balance": "20000000000000000000" + }, + "fa19d6f7a50f4f079893d167bf14e21d0073d196": { + "balance": "530000000000000000000" + }, + "3e2ca0d234baf607ad466a1b85f4a6488ef00ae7": { + "balance": "89505000000000000000" + }, + "f8a49ca2390c1f6d5c0e62513b079571743f7cc6": { + "balance": "3000000000000000000000" + }, + "5d3f3b1f7130b0bb21a0fd32396239179a25657f": { + "balance": "62474000000000000000000" + }, + "f332c0f3e05a27d9126fd0b641a8c2d4060608fd": { + "balance": "5001041000000000000000" + }, + "e304a32f05a83762744a9542976ff9b723fa31ea": { + "balance": "1576256000000000000000" + }, + "f768f321fd6433d96b4f354d3cc1652c1732f57f": { + "balance": "10000000000000000000000" + }, + "147af46ae9ccd18bb35ca01b353b51990e49dce1": { + "balance": "4000000000000000000000" + }, + "21eae6feffa9fbf4cd874f4739ace530ccbe5937": { + "balance": "5000000000000000000000" + }, + "6994fb3231d7e41d491a9d68d1fa4cae2cc15960": { + "balance": "4000000000000000000000" + }, + "51126446ab3d8032557e8eba65597d75fadc815c": { + "balance": "322000000000000000000" + }, + "24daaaddf7b06bbcea9b80590085a88567682b4e": { + "balance": "319008000000000000000" + }, + "cd020f8edfcf524798a9b73a640334bbf72f80a5": { + "balance": "133700000000000000000" + }, + "56febf9e1003af15b1bd4907ec089a4a1b91d268": { + "balance": "200000000000000000000" + }, + "3c79c863c3d372b3ff0c6f452734a7f97042d706": { + "balance": "176000000000000000000" + }, + "e1203eb3a723e99c2220117ca6afeb66fa424f61": { + "balance": "9461996000000000000000" + }, + "18fb09188f27f1038e654031924f628a2106703d": { + "balance": "2000000000000000000000" + }, + "2eba0c6ee5a1145c1c573984963a605d880a7a20": { + "balance": "500000000000000000000" + }, + "4cefbe2398e47d52e78db4334c8b697675f193ae": { + "balance": "4011000000000000000000" + }, + "c02471e3fc2ea0532615a7571d493289c13c36ef": { + "balance": "20000000000000000000" + }, + "ba469aa5c386b19295d4a1b5473b540353390c85": { + "balance": "2000000000000000000000" + }, + "7b11673cc019626b290cbdce26046f7e6d141e21": { + "balance": "500000000000000000000" + }, + "26784ade91c8a83a8e39658c8d8277413ccc9954": { + "balance": "6000000000000000000000" + }, + "57d3df804f2beee6ef53ab94cb3ee9cf524a18d3": { + "balance": "393606000000000000000" + }, + "ccae0d3d852a7da3860f0636154c0a6ca31628d4": { + "balance": "106560000000000000000" + }, + "bfe3a1fc6e24c8f7b3250560991f93cba2cf8047": { + "balance": "80000000000000000000000" + }, + "724ce858857ec5481c86bd906e83a04882e5821d": { + "balance": "3000000000000000000000" + }, + "fb37cf6b4f81a9e222fba22e9bd24b5098b733cf": { + "balance": "38800000000000000000" + }, + "9b22a80d5c7b3374a05b446081f97d0a34079e7f": { + "balance": "3000000000000000000000" + }, + "0a29a8a4d5fd950075ffb34d77afeb2d823bd689": { + "balance": "200000000000000000000" + }, + "d01af9134faf5257174e8b79186f42ee354e642d": { + "balance": "1000000000000000000000" + }, + "7f1619988f3715e94ff1d253262dc5581db3de1c": { + "balance": "900000000000000000000" + }, + "6f137a71a6f197df2cbbf010dcbd3c444ef5c925": { + "balance": "2000000000000000000000" + }, + "11efb8a20451161b644a8ccebbc1d343a3bbcb52": { + "balance": "3200000000000000000000" + }, + "46504e6a215ac83bccf956befc82ab5a679371c8": { + "balance": "518898000000000000000" + }, + "b523fff9749871b35388438837f7e6e0dea9cb6b": { + "balance": "2000000000000000000000" + }, + "c5c6a4998a33feb764437a8be929a73ba34a0764": { + "balance": "50000000000000000000000" + }, + "3cd7f7c7c2353780cde081eeec45822b25f2860c": { + "balance": "200000000000000000000" + }, + "b3050beff9de33c80e1fa15225e28f2c413ae313": { + "balance": "700000000000000000000" + }, + "59268171b833e0aa13c54b52ccc0422e4fa03aeb": { + "balance": "3000000000000000000000" + }, + "7169724ee72271c534cad6420fb04ee644cb86fe": { + "balance": "410164000000000000000" + }, + "6e6d5bbbb9053b89d744a27316c2a7b8c09b547d": { + "balance": "909831000000000000000" + }, + "3f3f46b75cabe37bfacc8760281f4341ca7f463d": { + "balance": "602709000000000000000" + }, + "7a33834e8583733e2d52aead589bd1affb1dd256": { + "balance": "1000000000000000000000" + }, + "e94ded99dcb572b9bb1dcba32f6dee91e057984e": { + "balance": "394000000000000000000" + }, + "19336a236ded755872411f2e0491d83e3e00159e": { + "balance": "940000000000000000000" + }, + "63ac545c991243fa18aec41d4f6f598e555015dc": { + "balance": "600000000000000000000" + }, + "cfee05c69d1f29e7714684c88de5a16098e91399": { + "balance": "1970000000000000000000" + }, + "77be6b64d7c733a436adec5e14bf9ad7402b1b46": { + "balance": "1000000000000000000000" + }, + "233bdddd5da94852f4ade8d212885682d9076bc6": { + "balance": "4000000000000000000000" + }, + "952c57d2fb195107d4cd5ca300774119dfad2f78": { + "balance": "2000000000000000000000" + }, + "e237baa4dbc9926e32a3d85d1264402d54db012f": { + "balance": "2000000000000000000000" + }, + "aa91237e740d25a92f7fa146faa18ce56dc6e1f3": { + "balance": "925000000000000000000" + }, + "2339e9492870afea2537f389ac2f838302a33c06": { + "balance": "2000000000000000000000" + }, + "1d45586eb803ca2190650bf748a2b174312bb507": { + "balance": "1400000000000000000000" + }, + "c61446b754c24e3b1642d9e51765b4d3e46b34b6": { + "balance": "2000000000000000000000" + }, + "ac28b5edea05b76f8c5f97084541277c96696a4c": { + "balance": "1000000000000000000000" + }, + "1a1c9a26e0e02418a5cf687da75a275c622c9440": { + "balance": "5000000000000000000000" + }, + "299368609042a858d1ecdf1fc0ada5eaceca29cf": { + "balance": "2000000000000000000000" + }, + "095f5a51d06f6340d80b6d29ea2e88118ad730fe": { + "balance": "2000200000000000000000" + }, + "751a2ca34e7187c163d28e3618db28b13c196d26": { + "balance": "500000000000000000000" + }, + "75b0e9c942a4f0f6f86d3f95ff998022fa67963b": { + "balance": "1490000000000000000000" + }, + "d1b37f03cb107424e9c4dd575ccd4f4cee57e6cd": { + "balance": "2000000000000000000000" + }, + "7f993ddb7e02c282b898f6155f680ef5b9aff907": { + "balance": "20000000000000000000000" + }, + "a3d583a7b65b23f60b7905f3e4aa62aac87f4227": { + "balance": "1046779000000000000000" + }, + "526bb533b76e20c8ee1ebf123f1e9ff4148e40be": { + "balance": "197000000000000000000" + }, + "2160b4c02cac0a81de9108de434590a8bfe68735": { + "balance": "1970000000000000000000" + }, + "010007394b8b7565a1658af88ce463499135d6b7": { + "balance": "100000000000000000000" + }, + "64457fa33b0832506c4f7d1180dce48f46f3e0ff": { + "balance": "2000000000000000000000" + }, + "b51e558eb5512fbcfa81f8d0bd938c79ebb5242b": { + "balance": "715000000000000000000" + }, + "94f13f9f0836a3ee2437a84922d2984dc0f7d53b": { + "balance": "2999916000000000000000" + }, + "6bd457ade051795df3f2465c3839aed3c5dee978": { + "balance": "999925000000000000000" + }, + "f3dbcf135acb9dee1a489c593c024f03c2bbaece": { + "balance": "2000000000000000000000" + }, + "61b902c5a673885826820d1fe14549e4865fbdc2": { + "balance": "334703000000000000000" + }, + "2acc9c1a32240b4d5b2f777a2ea052b42fc1271c": { + "balance": "41764000000000000000000" + }, + "6ddfef639155daab0a5cb4953aa8c5afaa880453": { + "balance": "1820000000000000000000" + }, + "96ff6f509968f36cb42cba48db32f21f5676abf8": { + "balance": "1970000000000000000000" + }, + "b4c8170f7b2ab536d1d9a25bdd203ae1288dc3d5": { + "balance": "200000000000000000000" + }, + "78d4f8c71c1e68a69a98f52fcb45da8af56ea1a0": { + "balance": "2000000000000000000000" + }, + "dec99e972fca7177508c8e1a47ac22d768acab7c": { + "balance": "2000000000000000000000" + }, + "a07aa16d74aee8a9a3288d52db1551d593883297": { + "balance": "600000000000000000000" + }, + "cf1169041c1745e45b172435a2fc99b49ace2b00": { + "balance": "31960000000000000000" + }, + "526cb09ce3ada3672eec1deb46205be89a4b563e": { + "balance": "2468000000000000000000" + }, + "ee6959de2b67967b71948c891ab00d8c8f38c7dc": { + "balance": "118200000000000000000" + }, + "ca7ba3ff536c7e5f0e153800bd383db8312998e0": { + "balance": "169600000000000000000" + }, + "1ed06ee51662a86c634588fb62dc43c8f27e7c17": { + "balance": "200000000000000000000" + }, + "730447f97ce9b25f22ba1afb36df27f9586beb9b": { + "balance": "820000000000000000000" + }, + "ae5c9bdad3c5c8a1220444aea5c229c1839f1d64": { + "balance": "477500000000000000000" + }, + "a38306cb70baa8e49186bd68aa70a83d242f2907": { + "balance": "2000000000000000000000" + }, + "71213fca313404204ecba87197741aa9dfe96338": { + "balance": "60000000000000000000" + }, + "10e390ad2ba33d82b37388d09c4544c6b0225de5": { + "balance": "200000000000000000000" + }, + "3b6e814f770748a7c3997806347605480a3fd509": { + "balance": "2000000000000000000000" + }, + "fd452c3969ece3801c542020f1cdcaa1c71ed23d": { + "balance": "100000000000000000000000" + }, + "e742b1e6069a8ffc3c4767235defb0d49cbed222": { + "balance": "800000000000000000000" + }, + "d7225738dcf3578438f8e7c8b3837e42e04a262f": { + "balance": "445860000000000000000" + }, + "cd0b0257e783a3d2c2e3ba9d6e79b75ef98024d4": { + "balance": "2945500000000000000000" + }, + "e80e7fef18a5db15b01473f3ad6b78b2a2f8acd9": { + "balance": "500000000000000000000" + }, + "261575e9cf59c8226fa7aaf91de86fb70f5ac3ae": { + "balance": "300022000000000000000" + }, + "7e71171f2949fa0c3ac254254b1f0440e5e6a038": { + "balance": "40000000000000000000" + }, + "96ea6ac89a2bac95347b51dba63d8bd5ebdedce1": { + "balance": "2000000000000000000000" + }, + "e6ec5cf0c49b9c317e1e706315ef9eb7c0bf11a7": { + "balance": "17200000000000000000000" + }, + "2b99b42e4f42619ee36baa7e4af2d65eacfcba35": { + "balance": "40000000000000000000000" + }, + "c6e4cc0c7283fc1c85bc4813effaaf72b49823c0": { + "balance": "276926000000000000000" + }, + "dbc1ce0e49b1a705d22e2037aec878ee0d75c703": { + "balance": "250000000000000000000" + }, + "806f44bdeb688037015e84ff218049e382332a33": { + "balance": "1999000000000000000000" + }, + "1a3a330e4fcb69dbef5e6901783bf50fd1c15342": { + "balance": "4200000000000000000000" + }, + "d2a84f75675c62d80c88756c428eee2bcb185421": { + "balance": "1200000000000000000000" + }, + "c593b546b7698710a205ad468b2c13152219a342": { + "balance": "1550000000000000000000" + }, + "3f627a769e6a950eb87017a7cd9ca20871136831": { + "balance": "13790000000000000000000" + }, + "f2d5763ce073127e2cedde6faba786c73ca94141": { + "balance": "7900000000000000000000" + }, + "162110f29eac5f7d02b543d8dcd5bb59a5e33b73": { + "balance": "2000000000000000000000" + }, + "59473cd300fffae240f5785626c65dfec792b9af": { + "balance": "20000000000000000000" + }, + "4dcd11815818ae29b85d01367349a8a7fb12d06b": { + "balance": "7900000000000000000000" + }, + "9329ffdc268babde8874b366406c81445b9b2d35": { + "balance": "422415000000000000000" + }, + "0ab4281ebb318590abb89a81df07fa3af904258a": { + "balance": "500000000000000000000" + }, + "875061ee12e820041a01942cb0e65bb427b00060": { + "balance": "2800000000000000000000" + }, + "c9b698e898d20d4d4f408e4e4d061922aa856307": { + "balance": "40000000000000000000" + }, + "ca49a5f58adbefae23ee59eea241cf0482622eaa": { + "balance": "1430000000000000000000" + }, + "196e85df7e732b4a8f0ed03623f4db9db0b8fa31": { + "balance": "21165000000000000000" + }, + "4c760cd9e195ee4f2d6bce2500ff96da7c43ee91": { + "balance": "60000000000000000000000" + }, + "024a098ae702bef5406c9c22b78bd4eb2cc7a293": { + "balance": "4000000000000000000000" + }, + "9d81aea69aed6ad07089d61445348c17f34bfc5b": { + "balance": "300000000000000000000" + }, + "76ab87dd5a05ad839a4e2fc8c85aa6ba05641730": { + "balance": "2000000000000000000000" + }, + "c6e2f5af979a03fd723a1b6efa728318cf9c1800": { + "balance": "668500000000000000000" + }, + "5db69fe93e6fb6fbd450966b97238b110ad8279a": { + "balance": "40000000000000000000000" + }, + "a4259f8345f7e3a8b72b0fec2cf75e321fda4dc2": { + "balance": "1910000000000000000000" + }, + "095030e4b82692dcf8b8d0912494b9b378ec9328": { + "balance": "1340000000000000000000" + }, + "4b470f7ba030bc7cfcf338d4bf0432a91e2ea5ff": { + "balance": "2000000000000000000000" + }, + "99c9f93e45fe3c1418c353e4c5ac3894eef8121e": { + "balance": "101870000000000000000" + }, + "ffac3db879a6c7158e8dec603b407463ba0d31cf": { + "balance": "1970000000000000000000" + }, + "ac8e87ddda5e78fcbcb9fa7fc3ce038f9f7d2e34": { + "balance": "2000000000000000000000" + }, + "7a0589b143a8e5e107c9ac66a9f9f8597ab3e7ab": { + "balance": "1510990000000000000000" + }, + "b7d581fe0af1ec383f3b3c416783f385146a7612": { + "balance": "20000000000000000000000" + }, + "bb3fc0a29c034d710812dcc775c8cab9d28d6975": { + "balance": "1066806000000000000000" + }, + "2c603ff0fe93616c43573ef279bfea40888d6ae7": { + "balance": "4740000000000000000000" + }, + "15f2b7b16432ee50a5f55b41232f6334ed58bdc0": { + "balance": "400000000000000000000" + }, + "7f3d7203c8a447f7bf36d88ae9b6062a5eee78ae": { + "balance": "6000000000000000000000" + }, + "f067e1f1d683556a4cc4fd0c0313239f32c4cfd8": { + "balance": "1000000000000000000000" + }, + "52738c90d860e04cb12f498d96fdb5bf36fc340e": { + "balance": "30000000000000000000" + }, + "45781bbe7714a1c8f73b1c747921df4f84278b70": { + "balance": "2000000000000000000000" + }, + "4a97e8fcf4635ea7fc5e96ee51752ec388716b60": { + "balance": "546000000000000000000" + }, + "54939ff08921b467cf2946751d856378296c63ed": { + "balance": "1000000000000000000000" + }, + "6485470e61db110aebdbafd536769e3c599cc908": { + "balance": "600000000000000000000" + }, + "e20d1bcb71286dc7128a9fc7c6ed7f733892eef5": { + "balance": "1003400000000000000000" + }, + "d6eea898d4ae2b718027a19ce9a5eb7300abe3ca": { + "balance": "27475000000000000000" + }, + "014974a1f46bf204944a853111e52f1602617def": { + "balance": "2000000000000000000000" + }, + "6aa5732f3b86fb8c81efbe6b5b47b563730b06c8": { + "balance": "1000000000000000000000" + }, + "6107d71dd6d0eefb11d4c916404cb98c753e117d": { + "balance": "2000000000000000000000" + }, + "dd7bcda65924aaa49b80984ae173750258b92847": { + "balance": "10000000000000000000000" + }, + "4e7b54474d01fefd388dfcd53b9f662624418a05": { + "balance": "8000000000000000000000" + }, + "24fc73d20793098e09ddab5798506224fa1e1850": { + "balance": "200000000000000000000" + }, + "2b8488bd2d3c197a3d26151815b5a798d27168dc": { + "balance": "6680000000000000000000" + }, + "949131f28943925cfc97d41e0cea0b262973a730": { + "balance": "2800000000000000000000" + }, + "60b8d6b73b79534fb08bb8cbcefac7f393c57bfe": { + "balance": "1760000000000000000000" + }, + "d6acc220ba2e51dfcf21d443361eea765cbd35d8": { + "balance": "20000000000000000000" + }, + "c4c6cb723dd7afa7eb535615e53f3cef14f18118": { + "balance": "1999999000000000000000" + }, + "4c9a862ad115d6c8274ed0b944bdd6a5500510a7": { + "balance": "100000000000000000000" + }, + "85732c065cbd64119941aed430ac59670b6c51c4": { + "balance": "731345000000000000000" + }, + "0126e12ebc17035f35c0e9d11dd148393c405d7a": { + "balance": "1999600000000000000000" + }, + "472048cc609aeb242165eaaa8705850cf3125de0": { + "balance": "1000000000000000000000" + }, + "d2edd1ddd6d86dc005baeb541d22b640d5c7cae5": { + "balance": "20000000000000000000" + }, + "4549b15979255f7e65e99b0d5604db98dfcac8bf": { + "balance": "4000000000000000000000" + }, + "c6c7c191379897dd9c9d9a33839c4a5f62c0890d": { + "balance": "4000085000000000000000" + }, + "d367009ab658263b62c2333a1c9e4140498e1389": { + "balance": "2000000000000000000000" + }, + "143f5f1658d9e578f4f3d95f80c0b1bd3933cbda": { + "balance": "1490000000000000000000" + }, + "1a09fdc2c7a20e23574b97c69e93deba67d37220": { + "balance": "1998000000000000000000" + }, + "ac8b509aefea1dbfaf2bb33500d6570b6fd96d51": { + "balance": "1820000000000000000000" + }, + "16ffac84032940f0121a09668b858a7e79ffa3bb": { + "balance": "3879210000000000000000" + }, + "f338459f32a159b23db30ac335769ab2351aa63c": { + "balance": "30000000000000000000000" + }, + "d82251456dc1380f8f5692f962828640ab9f2a03": { + "balance": "4879980000000000000000" + }, + "47f4696bd462b20da09fb83ed2039818d77625b3": { + "balance": "149000000000000000000" + }, + "3dde8b15b3ccbaa5780112c3d674f313bba68026": { + "balance": "1773000000000000000000" + }, + "f70d637a845c06db6cdc91e6371ce7c4388a628e": { + "balance": "20000000000000000000" + }, + "68295e8ea5afd9093fc0a465d157922b5d2ae234": { + "balance": "19982000000000000000" + }, + "614e8bef3dd2c59b59a4145674401018351884ea": { + "balance": "20000000000000000000" + }, + "4737d042dc6ae73ec73ae2517acea2fdd96487c5": { + "balance": "1000000000000000000000" + }, + "cec6fc65853f9cce5f8e844676362e1579015f02": { + "balance": "2000000000000000000000" + }, + "ae47e2609cfafe369d66d415d939de05081a9872": { + "balance": "27060000000000000000000" + }, + "09a928d528ec1b3e25ffc83e218c1e0afe8928c7": { + "balance": "18200000000000000000" + }, + "9b444fd337e5d75293adcfff70e1ea01db023222": { + "balance": "100000000000000000000" + }, + "168bdec818eafc6d2992e5ef54aa0e1601e3c561": { + "balance": "1000110000000000000000" + }, + "353dbec42f92b50f975129b93c4c997375f09073": { + "balance": "1999000000000000000000" + }, + "6fcc2c732bdd934af6ccd16846fb26ef89b2aa9b": { + "balance": "10001242000000000000000" + }, + "6f2576da4de283bbe8e3ee69ddd66e5e711db3f5": { + "balance": "1260800000000000000000" + }, + "3a3dd104cd7eb04f21932fd433ea7affd39369f5": { + "balance": "357500000000000000000" + }, + "d44f4ac5fad76bdc1537a3b3af6472319b410d9d": { + "balance": "1600000000000000000000" + }, + "3d9d6be57ff83e065985664f12564483f2e600b2": { + "balance": "2041600000000000000000" + }, + "88f1045f19f2d3191816b1df18bb6e1435ad1b38": { + "balance": "240000000000000000000" + }, + "ddab75fb2ff9fecb88f89476688e2b00e367ebf9": { + "balance": "19400000000000000000000" + }, + "092e815558402d67f90d6bfe6da0b2fffa91455a": { + "balance": "60000000000000000000" + }, + "a7024cfd742c1ec13c01fea18d3042e65f1d5dee": { + "balance": "11272229000000000000000" + }, + "7f46bb25460dd7dae4211ca7f15ad312fc7dc75c": { + "balance": "6685000000000000000000" + }, + "93f18cd2526040761488c513174d1e7963768b2c": { + "balance": "2416500000000000000000" + }, + "352f25babf4a690673e35195efa8f79d05848aad": { + "balance": "66800000000000000000000" + }, + "f7b151cc5e571c17c76539dbe9964cbb6fe5de79": { + "balance": "2148000000000000000000" + }, + "ff3eee57c34d6dae970d8b311117c53586cd3502": { + "balance": "1700000000000000000000" + }, + "ae6f0c73fdd77c489727512174d9b50296611c4c": { + "balance": "6000000000000000000000" + }, + "7819b0458e314e2b53bfe00c38495fd4b9fdf8d6": { + "balance": "20000000000000000000" + }, + "7fdba031c78f9c096d62d05a369eeab0bccc55e5": { + "balance": "2800000000000000000000" + }, + "735e328666ed5637142b3306b77ccc5460e72c3d": { + "balance": "1968682000000000000000" + }, + "0bfbb6925dc75e52cf2684224bbe0550fea685d3": { + "balance": "1970000000000000000000" + }, + "6be16313643ebc91ff9bb1a2e116b854ea933a45": { + "balance": "500000000000000000000" + }, + "d6acffd0bfd99c382e7bd56ff0e6144a9e52b08e": { + "balance": "160000000000000000000" + }, + "276a006e3028ecd44cdb62ba0a77ce94ebd9f10f": { + "balance": "1800000000000000000000" + }, + "10711c3dda32317885f0a2fd8ae92e82069b0d0b": { + "balance": "4000000000000000000000" + }, + "43cb9652818c6f4d6796b0e89409306c79db6349": { + "balance": "2000000000000000000000" + }, + "7109dd011d15f3122d9d3a27588c10d77744508b": { + "balance": "2000000000000000000000" + }, + "3497dd66fd118071a78c2cb36e40b6651cc82598": { + "balance": "109600000000000000000" + }, + "9bf672d979b36652fc5282547a6a6bc212ae4368": { + "balance": "656000000000000000000" + }, + "eaed16eaf5daab5bf0295e5e077f59fb8255900b": { + "balance": "4000000000000000000000" + }, + "7ac58f6ffc4f8107ae6e30378e4e9f99c57fbb24": { + "balance": "40000000000000000000" + }, + "45a570dcc2090c86a6b3ea29a60863dde41f13b5": { + "balance": "232500000000000000000" + }, + "433a3b68e56b0df1862b90586bbd39c840ff1936": { + "balance": "2000000000000000000000" + }, + "e8eaf12944092dc3599b3953fa7cb1c9761cc246": { + "balance": "1800000000000000000000" + }, + "ec11362cec810985d0ebbd7b73451444985b369f": { + "balance": "30000047000000000000000" + }, + "78e83f80b3678c7a0a4e3e8c84dccde064426277": { + "balance": "1790000000000000000000" + }, + "0cc67f8273e1bae0867fd42e8b8193d72679dbf8": { + "balance": "500000000000000000000" + }, + "c70d856d621ec145303c0a6400cd17bbd6f5eaf7": { + "balance": "20000000000000000000" + }, + "f468906e7edf664ab0d8be3d83eb7ab3f7ffdc78": { + "balance": "1700000000000000000000" + }, + "3c286cfb30146e5fd790c2c8541552578de334d8": { + "balance": "10203000000000000000000" + }, + "c401c427cccff10decb864202f36f5808322a0a8": { + "balance": "3329300000000000000000" + }, + "afd019ff36a09155346b69974815a1c912c90aa4": { + "balance": "2000000000000000000000" + }, + "96fe59c3dbb3aa7cc8cb62480c65e56e6204a7e2": { + "balance": "20000000000000000000000" + }, + "a47779d8bc1c7bce0f011ccb39ef68b854f8de8f": { + "balance": "2000000000000000000000" + }, + "58c650ced40bb65641b8e8a924a039def46854df": { + "balance": "18500000000000000000" + }, + "86f4f40ad984fbb80933ae626e0e42f9333fdd41": { + "balance": "1000000000000000000000" + }, + "b22d5055d9623135961e6abd273c90deea16a3e7": { + "balance": "1400000000000000000000" + }, + "ee3564f5f1ba0f94ec7bac164bddbf31c6888b55": { + "balance": "100000000000000000000" + }, + "cf26b47bd034bc508e6c4bcfd6c7d30034925761": { + "balance": "1800000000000000000000" + }, + "e87dbac636a37721df54b08a32ef4959b5e4ff82": { + "balance": "2000000000000000000000" + }, + "3bf86ed8a3153ec933786a02ac090301855e576b": { + "balance": "450000000000000000000000" + }, + "cfd2728dfb8bdbf3bf73598a6e13eaf43052ea2b": { + "balance": "170000000000000000000" + }, + "85b16f0b8b34dff3804f69e2168a4f7b24d1042b": { + "balance": "317000000000000000000" + }, + "84db1459bb00812ea67ecb3dc189b72187d9c501": { + "balance": "148851000000000000000" + }, + "8c3a9ee71f729f236cba3867b4d79d8ceee25dbc": { + "balance": "100000000000000000000" + }, + "e677c31fd9cb720075dca49f1abccd59ec33f734": { + "balance": "7800000000000000000000" + }, + "8889448316ccf14ed86df8e2f478dc63c4338340": { + "balance": "15200000000000000000" + }, + "b279c7d355c2880392aad1aa21ee867c3b3507df": { + "balance": "1261000000000000000000" + }, + "12b5e28945bb2969f9c64c63cc05b6f1f8d6f4d5": { + "balance": "7722162000000000000000" + }, + "8d2303341e1e1eb5e8189bde03f73a60a2a54861": { + "balance": "100000000000000000000" + }, + "94d81074db5ae197d2bb1373ab80a87d121c4bd3": { + "balance": "9400000000000000000000" + }, + "752c9febf42f66c4787bfa7eb17cf5333bba5070": { + "balance": "1966448000000000000000" + }, + "16816aac0ede0d2d3cd442da79e063880f0f1d67": { + "balance": "2000000000000000000000" + }, + "daac91c1e859d5e57ed3084b50200f9766e2c52b": { + "balance": "400000000000000000000" + }, + "32c2fde2b6aabb80e5aea2b949a217f3cb092283": { + "balance": "5614827000000000000000" + }, + "cdab46a5902080646fbf954204204ae88404822b": { + "balance": "544942000000000000000" + }, + "fdf42343019b0b0c6bf260b173afab7e45b9d621": { + "balance": "1999944000000000000000" + }, + "791f6040b4e3e50dcf3553f182cd97a90630b75d": { + "balance": "4000000000000000000000" + }, + "4b762166dd1118e84369f804c75f9cd657bf730c": { + "balance": "500000000000000000000" + }, + "a76d3f156251b72c0ccf4b47a3393cbd6f49a9c5": { + "balance": "1337000000000000000000" + }, + "c5eb42295e9cadeaf2af12dede8a8d53c579c469": { + "balance": "3820000000000000000000" + }, + "db9371b30c4c844e59e03e924be606a938d1d310": { + "balance": "2000000000000000000000" + }, + "2cd39334ac7eac797257abe3736195f5b4b5ce0f": { + "balance": "99964000000000000000" + }, + "ad44357e017e244f476931c7b8189efee80a5d0a": { + "balance": "300000000000000000000" + }, + "4ca7b717d9bc8793b04e051a8d23e1640f5ba5e3": { + "balance": "1248980000000000000000" + }, + "73e4a2b60cf48e8baf2b777e175a5b1e4d0c2d8f": { + "balance": "100000000000000000000" + }, + "5a1d2d2d1d520304b6208849570437eb3091bb9f": { + "balance": "1970000000000000000000" + }, + "53047dc8ac9083d90672e8b3473c100ccd278323": { + "balance": "40000000000000000000" + }, + "26fe174cbf526650e0cd009bd6126502ce8e684d": { + "balance": "11640000000000000000000" + }, + "e2df23f6ea04becf4ab701748dc0963184555cdb": { + "balance": "2000000000000000000000" + }, + "c1170dbaadb3dee6198ea544baec93251860fda5": { + "balance": "1200000000000000000000" + }, + "8bbeacfc29cfe93402db3c41d99ab759662e73ec": { + "balance": "2000000000000000000000" + }, + "165305b787322e25dc6ad0cefe6c6f334678d569": { + "balance": "2000000000000000000000" + }, + "095457f8ef8e2bdc362196b9a9125da09c67e3ab": { + "balance": "200000000000000000000" + }, + "702802f36d00250fab53adbcd696f0176f638a49": { + "balance": "2000000000000000000000" + }, + "489334c2b695c8ee0794bd864217fb9fd8f8b135": { + "balance": "18200000000000000000" + }, + "fa8cf4e627698c5d5788abb7880417e750231399": { + "balance": "4244640000000000000000" + }, + "3329eb3baf4345d600ced40e6e9975656f113742": { + "balance": "4999711000000000000000" + }, + "b4dd5499daeb2507fb2de12297731d4c72b16bb0": { + "balance": "20000000000000000000" + }, + "88c2516a7cdb09a6276d7297d30f5a4db1e84b86": { + "balance": "4000000000000000000000" + }, + "612ced8dc0dc9e899ee46f7962333315f3f55e44": { + "balance": "338830000000000000000" + }, + "d71e43a45177ad51cbe0f72184a5cb503917285a": { + "balance": "200000000000000000000" + }, + "2fb566c94bbba4e3cb67cdda7d5fad7131539102": { + "balance": "2000000000000000000000" + }, + "03be5b4629aefbbcab9de26d39576cb7f691d764": { + "balance": "200550000000000000000" + }, + "025367960304beee34591118e9ac2d1358d8021a": { + "balance": "2000000000000000000000" + }, + "a5d5b8b62d002def92413710d13b6ff8d4fc7dd3": { + "balance": "400000000000000000000" + }, + "df3b72c5bd71d4814e88a62321a93d4011e3578b": { + "balance": "4000000000000000000000" + }, + "3588895ac9fbafec012092dc05c0c302d90740fa": { + "balance": "3000000000000000000000" + }, + "6021e85a8814fce1e82a41abd1d3b2dad2faefe0": { + "balance": "2000000000000000000000" + }, + "17ee9f54d4ddc84d670eff11e54a659fd72f4455": { + "balance": "16000000000000000000000" + }, + "873c6f70efb6b1d0f2bbc57eebcd70617c6ce662": { + "balance": "1013478000000000000000" + }, + "1fcc7ce6a8485895a3199e16481f72e1f762defe": { + "balance": "1000000000000000000000" + }, + "d0a7209b80cf60db62f57d0a5d7d521a69606655": { + "balance": "160000000000000000000" + }, + "a514d00edd7108a6be839a638db2415418174196": { + "balance": "30000000000000000000000" + }, + "046377f864b0143f282174a892a73d3ec8ec6132": { + "balance": "191000000000000000000" + }, + "c126573d87b0175a5295f1dd07c575cf8cfa15f2": { + "balance": "10000000000000000000000" + }, + "0e123d7da6d1e6fac2dcadd27029240bb39052fe": { + "balance": "1000000000000000000000" + }, + "ad5a8d3c6478b69f657db3837a2575ef8e1df931": { + "balance": "36990000000000000000" + }, + "db882eacedd0eff263511b312adbbc59c6b8b25b": { + "balance": "9100000000000000000000" + }, + "0b43bd2391025581d8956ce42a072579cbbfcb14": { + "balance": "18800000000000000000" + }, + "affea0473722cb7f0e0e86b9e11883bf428d8d54": { + "balance": "1940000000000000000000" + }, + "e32b1c4725a1875449e98f970eb3e54062d15800": { + "balance": "200000000000000000000" + }, + "98f4af3af0aede5fafdc42a081ecc1f89e3ccf20": { + "balance": "9400000000000000000000" + }, + "3b4768fd71e2db2cbe7fa050483c27b4eb931df3": { + "balance": "2000000000000000000000" + }, + "d5f7c41e07729dfa6dfc64c4423160a22c609fd3": { + "balance": "1790000000000000000000" + }, + "d944c8a69ff2ca1249690c1229c7192f36251062": { + "balance": "1970000000000000000000" + }, + "5ae64e853ba0a51282cb8db52e41615e7c9f733f": { + "balance": "2000000000000000000000" + }, + "b13f93af30e8d7667381b2b95bc1a699d5e3e129": { + "balance": "420000000000000000000" + }, + "8a20e5b5cee7cd1f5515bace3bf4f77ffde5cc07": { + "balance": "80000000000000000000" + }, + "2448596f91c09baa30bc96106a2d37b5705e5d28": { + "balance": "2000000000000000000000" + }, + "ccca24d8c56d6e2c07db086ec07e585be267ac8d": { + "balance": "200000000000000000000" + }, + "f67bb8e2118bbcd59027666eedf6943ec9f880a5": { + "balance": "4000000000000000000000" + }, + "7ae659eb3bc46852fa86fac4e21c768d50388945": { + "balance": "286000000000000000000" + }, + "467e0ed54f3b76ae0636176e07420815a021736e": { + "balance": "2000000000000000000000" + }, + "a46cd237b63eea438c8e3b6585f679e4860832ac": { + "balance": "1000000000000000000000" + }, + "6b760d4877e6a627c1c967bee451a8507ddddbab": { + "balance": "910000000000000000000" + }, + "593044670faeff00a55b5ae051eb7be870b11694": { + "balance": "133700000000000000000" + }, + "533c06928f19d0a956cc28866bf6c8d8f4191a94": { + "balance": "292320000000000000000" + }, + "262dc1364ccf6df85c43268ee182554dae692e29": { + "balance": "4927600000000000000000" + }, + "e4368bc1420b35efda95fafbc73090521916aa34": { + "balance": "4000000000000000000000" + }, + "feb92d30bf01ff9a1901666c5573532bfa07eeec": { + "balance": "1000000000000000000000" + }, + "ee25b9a7032679b113588ed52c137d1a053a1e94": { + "balance": "199820000000000000000" + }, + "20134cbff88bfadc466b52eceaa79857891d831e": { + "balance": "1000000000000000000000" + }, + "07b1a306cb4312df66482c2cae72d1e061400fcd": { + "balance": "20000000000000000000000" + }, + "e791d585b89936b25d298f9d35f9f9edc25a2932": { + "balance": "2000000000000000000000" + }, + "2e6933543d4f2cc00b5350bd8068ba9243d6beb0": { + "balance": "2000000000000000000000" + }, + "dae0d33eaa341569fa9ff5982684854a4a328a6e": { + "balance": "1000000000000000000000" + }, + "125cc5e4d56b2bcc2ee1c709fb9e68fb177440bd": { + "balance": "2000000000000000000000" + }, + "ec99e95dece46ffffb175eb6400fbebb08ee9b95": { + "balance": "100000000000000000000" + }, + "c538a0ff282aaa5f4b75cfb62c70037ee67d4fb5": { + "balance": "2000000000000000000000" + }, + "60676d1fa21fca052297e24bf96389c5b12a70d7": { + "balance": "241500000000000000000" + }, + "4b3dfbdb454be5279a3b8addfd0ed1cd37a9420d": { + "balance": "2000000000000000000000" + }, + "cdb597299030183f6e2d238533f4642aa58754b6": { + "balance": "400000000000000000000" + }, + "1ef2dcbfe0a500411d956eb8c8939c3d6cfe669d": { + "balance": "776000000000000000000" + }, + "a7247c53d059eb7c9310f628d7fc6c6a0a773f08": { + "balance": "500000000000000000000" + }, + "9799ca21dbcf69bfa1b3f72bac51b9e3ca587cf9": { + "balance": "1700000000000000000000" + }, + "ddf95c1e99ce2f9f5698057c19d5c94027ee4a6e": { + "balance": "6000000000000000000000" + }, + "83563bc364ed81a0c6da3b56ff49bbf267827a9c": { + "balance": "17332000000000000000000" + }, + "a192698007cc11aa603d221d5feea076bcf7c30d": { + "balance": "2000000000000000000000" + }, + "0134ff38155fabae94fd35c4ffe1d79de7ef9c59": { + "balance": "985000000000000000000" + }, + "80977316944e5942e79b0e3abad38da746086519": { + "balance": "38800000000000000000" + }, + "193d37ed347d1c2f4e35350d9a444bc57ca4db43": { + "balance": "60000000000000000000" + }, + "009a6d7db326679b77c90391a7476d238f3ba33e": { + "balance": "200200000000000000000" + }, + "337b3bdf86d713dbd07b5dbfcc022b7a7b1946ae": { + "balance": "3980000000000000000000" + }, + "7de7fe419cc61f91f408d234cc80d5ca3d054d99": { + "balance": "20000000000000000000" + }, + "f47bb134da30a812d003af8dccb888f44bbf5724": { + "balance": "5190000000000000000000" + }, + "fd920f722682afb5af451b0544d4f41b3b9d5742": { + "balance": "2330200000000000000000" + }, + "0a917f3b5cb0b883047fd9b6593dbcd557f453b9": { + "balance": "1000000000000000000000" + }, + "ce9786d3712fa200e9f68537eeaa1a06a6f45a4b": { + "balance": "1790000000000000000000" + }, + "9ab98d6dbb1eaae16d45a04568541ad3d8fe06cc": { + "balance": "272451000000000000000" + }, + "0b7bb342f01bc9888e6a9af4a887cbf4c2dd2caf": { + "balance": "16000000000000000000000" + }, + "4c0b1515dfced7a13e13ee12c0f523ae504f032b": { + "balance": "50000000000000000000000" + }, + "ac2889b5966f0c7f9edb42895cb69d1c04f923a2": { + "balance": "5000000000000000000000" + }, + "d008513b27604a89ba1763b6f84ce688b346945b": { + "balance": "1000000000000000000000" + }, + "a4b09de6e713dc69546e76ef0acf40b94f0241e6": { + "balance": "322656000000000000000" + }, + "b153f828dd076d4a7c1c2574bb2dee1a44a318a8": { + "balance": "400000000000000000000" + }, + "02ade5db22f8b758ee1443626c64ec2f32aa0a15": { + "balance": "20000000000000000000000" + }, + "0a0650861f785ed8e4bf1005c450bbd06eb48fb6": { + "balance": "3066860000000000000000" + }, + "b75149e185f6e3927057739073a1822ae1cf0df2": { + "balance": "4000086000000000000000" + }, + "84cb7da0502df45cf561817bbd2362f451be02da": { + "balance": "1337000000000000000000" + }, + "c91bb562e42bd46130e2d3ae4652b6a4eb86bc0f": { + "balance": "540000000000000000000" + }, + "b234035f7544463ce1e22bc553064684c513cd51": { + "balance": "249750000000000000000" + }, + "e5e33800a1b2e96bde1031630a959aa007f26e51": { + "balance": "1337000000000000000000" + }, + "ae5ce3355a7ba9b332760c0950c2bc45a85fa9a0": { + "balance": "400000000000000000000" + }, + "e6f5eb649afb99599c414b27a9c9c855357fa878": { + "balance": "2674000000000000000000" + }, + "7010be2df57bd0ab9ae8196cd50ab0c521aba9f9": { + "balance": "1970000000000000000000" + }, + "ca4288014eddc5632f5facb5e38517a8f8bc5d98": { + "balance": "340000000000000000000" + }, + "2784903f1d7c1b5cd901f8875d14a79b3cbe2a56": { + "balance": "22388000000000000000000" + }, + "f8dce867f0a39c5bef9eeba609229efa02678b6c": { + "balance": "2000000000000000000000" + }, + "e020e86362b487752836a6de0bc02cd8d89a8b6a": { + "balance": "6000000000000000000000" + }, + "c4088c025f3e85013f5439fb3440a17301e544fe": { + "balance": "2325000000000000000000" + }, + "befb448c0c5f683fb67ee570baf0db5686599751": { + "balance": "1970000000000000000000" + }, + "2f187d5a704d5a338c5b2876a090dce964284e29": { + "balance": "4000000000000000000000" + }, + "ec0e18a01dc4dc5daae567c3fa4c7f8f9b590205": { + "balance": "315900000000000000000" + }, + "637f5869d6e4695f0eb9e27311c4878aff333380": { + "balance": "1969212000000000000000" + }, + "d1100dd00fe2ddf18163ad964d0b69f1f2e9658a": { + "balance": "5959598000000000000000" + }, + "17ef4acc1bf147e326749d10e677dcffd76f9e06": { + "balance": "39980000000000000000000" + }, + "200dfc0b71e359b2b465440a36a6cdc352773007": { + "balance": "1500000000000000000000" + }, + "efe0675da98a5dda70cd96196b87f4e726b43348": { + "balance": "1164000000000000000000" + }, + "d5bd5e8455c130169357c471e3e681b7996a7276": { + "balance": "841500000000000000000" + }, + "9c7b6dc5190fe2912963fcd579683ec7395116b0": { + "balance": "776000000000000000000" + }, + "b105dd3d987cffd813e9c8500a80a1ad257d56c6": { + "balance": "1999944000000000000000" + }, + "145250b06e4fa7cb2749422eb817bdda8b54de5f": { + "balance": "219000000000000000000" + }, + "d96db33b7b5a950c3efa2dc31b10ba10a532ef87": { + "balance": "2000000000000000000000" + }, + "af529bdb459cc185bee5a1c58bf7e8cce25c150d": { + "balance": "197000000000000000000" + }, + "185546e8768d506873818ac9751c1f12116a3bef": { + "balance": "200000000000000000000" + }, + "51d24bc3736f88dd63b7222026886630b6eb878d": { + "balance": "2000000000000000000000" + }, + "69af28b0746cac0da17084b9398c5e36bb3a0df2": { + "balance": "1004700000000000000000" + }, + "76f83ac3da30f7092628c7339f208bfc142cb1ee": { + "balance": "2842600000000000000000" + }, + "00f463e137dcf625fbf3bca39eca98d2b968cf7f": { + "balance": "5910000000000000000000" + }, + "2084fce505d97bebf1ad8c5ff6826fc645371fb2": { + "balance": "30000000000000000000" + }, + "53a714f99fa00fef758e23a2e746326dad247ca7": { + "balance": "1490000000000000000000" + }, + "0bf064428f83626722a7b5b26a9ab20421a7723e": { + "balance": "133700000000000000000" + }, + "ac6f68e837cf1961cb14ab47446da168a16dde89": { + "balance": "1337000000000000000000" + }, + "4b3c7388cc76da3d62d40067dabccd7ef0433d23": { + "balance": "100076000000000000000" + }, + "deb9a49a43873020f0759185e20bbb4cf381bb8f": { + "balance": "211628000000000000000" + }, + "5bf9f2226e5aeacf1d80ae0a59c6e38038bc8db5": { + "balance": "6000000000000000000000" + }, + "9d0e7d92fb305853d798263bf15e97c72bf9d7e0": { + "balance": "1000000000000000000000" + }, + "2b5c60e84535eeb4d580de127a12eb2677ccb392": { + "balance": "20000000000000000000000" + }, + "d8d65420c18c2327cc5af97425f857e4a9fd51b3": { + "balance": "1760000000000000000000" + }, + "30ec9392244a2108c987bc5cdde0ed9f837a817b": { + "balance": "1560562000000000000000" + }, + "56a1d60d40f57f308eebf087dee3b37f1e7c2cba": { + "balance": "1159600000000000000000" + }, + "a9a1cdc33bfd376f1c0d76fb6c84b6b4ac274d68": { + "balance": "5000000000000000000000" + }, + "a67f38819565423aa85f3e3ab61bc763cbab89dd": { + "balance": "2130000000000000000000" + }, + "62d5cc7117e18500ac2f9e3c26c86b0a94b0de15": { + "balance": "105000000000000000000" + }, + "4970d3acf72b5b1f32a7003cf102c64ee0547941": { + "balance": "140000000000000000000000" + }, + "76628150e2995b5b279fc83e0dd5f102a671dd1c": { + "balance": "40000000000000000000000" + }, + "3d8f39881b9edfe91227c33fa4cdd91e678544b0": { + "balance": "86111000000000000000" + }, + "ff0b7cb71da9d4c1ea6ecc28ebda504c63f82fd1": { + "balance": "1043000000000000000000" + }, + "8d795c5f4a5689ad62da961671f028065286d554": { + "balance": "2048000000000000000000" + }, + "be2346a27ff9b702044f500deff2e7ffe6824541": { + "balance": "20000000000000000000" + }, + "0dbd417c372b8b0d01bcd944706bd32e60ae28d1": { + "balance": "340000000000000000000" + }, + "467fbf41441600757fe15830c8cd5f4ffbbbd560": { + "balance": "10000000000000000000000" + }, + "090cd67b60e81d54e7b5f6078f3e021ba65b9a1e": { + "balance": "1000000000000000000000" + }, + "55a4cac0cb8b582d9fef38c5c9fff9bd53093d1f": { + "balance": "1970000000000000000000" + }, + "3b7b4f53c45655f3dc5f017edc23b16f9bc536fa": { + "balance": "100000000000000000000" + }, + "d508d39c70916f6abc4cc7f999f011f077105802": { + "balance": "100470000000000000000" + }, + "037dd056e7fdbd641db5b6bea2a8780a83fae180": { + "balance": "140000000000000000000" + }, + "660557bb43f4be3a1b8b85e7df7b3c5bcd548057": { + "balance": "6000000000000000000000" + }, + "02089361a3fe7451fb1f87f01a2d866653dc0b07": { + "balance": "39976000000000000000" + }, + "c4bec96308a20f90cab18399c493fd3d065abf45": { + "balance": "14000000000000000000000" + }, + "cca07bb794571d4acf041dad87f0d1ef3185b319": { + "balance": "2000000000000000000000" + }, + "f2d0e986d814ea13c8f466a0538c53dc922651f0": { + "balance": "1380000000000000000000" + }, + "662cfa038fab37a01745a364e1b98127c503746d": { + "balance": "3940000000000000000000" + }, + "3336c3ef6e8b50ee90e037b164b7a8ea5faac65d": { + "balance": "272712000000000000000" + }, + "30e33358fc21c85006e40f32357dc8895940aaf0": { + "balance": "1910000000000000000000" + }, + "41a9a404fc9f5bfee48ec265b12523338e29a8bf": { + "balance": "388000000000000000000" + }, + "6af235d2bbe050e6291615b71ca5829658810142": { + "balance": "3000000000000000000000" + }, + "fd5a63157f914fd398eab19c137dd9550bb7715c": { + "balance": "100000000000000000000" + }, + "8a4314fb61cd938fc33e15e816b113f2ac89a7fb": { + "balance": "432800000000000000000" + }, + "b216dc59e27c3d7279f5cd5bb2becfb2606e14d9": { + "balance": "400000000000000000000" + }, + "f5a5459fcdd5e5b273830df88eea4cb77ddadfb9": { + "balance": "74500000000000000000" + }, + "df31025f5649d2c6eea41ed3bdd3471a790f759a": { + "balance": "20000000000000000000" + }, + "721f9d17e5a0e74205947aeb9bc6a7938961038f": { + "balance": "51900000000000000000" + }, + "08d0864dc32f9acb36bf4ea447e8dd6726906a15": { + "balance": "2000200000000000000000" + }, + "54575c3114751e3c631971da6a2a02fd3ffbfcc8": { + "balance": "1940000000000000000000" + }, + "8f60895fbebbb5017fcbff3cdda397292bf25ba6": { + "balance": "429177000000000000000" + }, + "91fe8a4c6164df8fa606995d6ba7adcaf1c893ce": { + "balance": "17000000000000000000000" + }, + "889087f66ff284f8b5efbd29493b706733ab1447": { + "balance": "9850000000000000000000" + }, + "051633080d07a557adde319261b074997f14692d": { + "balance": "5800000000000000000000" + }, + "59a12df2e3ef857aceff9306b309f6a500f70134": { + "balance": "1000000000000000000000" + }, + "9f64a8e8dacf4ade30d10f4d59b0a3d5abfdbf74": { + "balance": "1000060000000000000000" + }, + "8846928d683289a2d11df8db7a9474988ef01348": { + "balance": "10000000000000000000000" + }, + "dff1b220de3d8e9ca4c1b5be34a799bcded4f61c": { + "balance": "385428000000000000000" + }, + "7e7c1e9a61a08a83984835c70ec31d34d3eaa87f": { + "balance": "191000000000000000000" + }, + "fe210b8f04dc6d4f76216acfcbd59ba83be9b630": { + "balance": "20000000000000000000" + }, + "dc8c2912f084a6d184aa73638513ccbc326e0102": { + "balance": "1295000000000000000000" + }, + "dddd7b9e6eab409b92263ac272da801b664f8a57": { + "balance": "500000000000000000000000" + }, + "86a5f8259ed5b09e188ce346ee92d34aa5dd93fa": { + "balance": "200000000000000000000" + }, + "dc1f1979615f082140b8bb78c67b27a1942713b1": { + "balance": "60000000000000000000" + }, + "ea66e7b84dcdbf36eea3e75b85382a75f1a15d96": { + "balance": "1729135000000000000000" + }, + "039e7a4ebc284e2ccd42b1bdd60bd6511c0f7706": { + "balance": "17300000000000000000" + }, + "36bfe1fa3b7b70c172eb042f6819a8972595413e": { + "balance": "1000000000000000000000" + }, + "039ef1ce52fe7963f166d5a275c4b1069fe3a832": { + "balance": "400008000000000000000" + }, + "f1df55dcc34a051012b575cb968bc9c458ea09c9": { + "balance": "4000000000000000000000" + }, + "168b5019b818691644835fe69bf229e17112d52c": { + "balance": "28000000000000000000000" + }, + "f60bd735543e6bfd2ea6f11bff627340bc035a23": { + "balance": "2000000000000000000000" + }, + "2cbb0c73df91b91740b6693b774a7d05177e8e58": { + "balance": "1850000000000000000000" + }, + "9ffcf5ef46d933a519d1d16c6ba3189b27496224": { + "balance": "1000000000000000000000" + }, + "0e11d77a8977fac30d268445e531149b31541a24": { + "balance": "2000000000000000000000" + }, + "dfb1626ef48a1d7d7552a5e0298f1fc23a3b482d": { + "balance": "1713860000000000000000" + }, + "cc943be1222cd1400a2399dd1b459445cf6d54a9": { + "balance": "12530000000000000000000" + }, + "b37c2b9f50637bece0ca959208aefee6463ba720": { + "balance": "400000000000000000000" + }, + "96b906ea729f4655afe3e57d35277c967dfa1577": { + "balance": "1000000000000000000000" + }, + "7995bd8ce2e0c67bf1c7a531d477bca1b2b97561": { + "balance": "5945100000000000000000" + }, + "96f820500b70f4a3e3239d619cff8f222075b135": { + "balance": "200000000000000000000" + }, + "ad3565d52b688added08168b2d3872d17d0a26ae": { + "balance": "100000000000000000000" + }, + "9e7c2050a227bbfd60937e268cea3e68fea8d1fe": { + "balance": "100000000000000000000" + }, + "7e59dc60be8b2fc19abd0a5782c52c28400bce97": { + "balance": "1000000000000000000000" + }, + "01ed5fba8d2eab673aec042d30e4e8a611d8c55a": { + "balance": "2000000000000000000000" + }, + "59a087b9351ca42f58f36e021927a22988284f38": { + "balance": "18500000000000000000" + }, + "2fe0023f5722650f3a8ac01009125e74e3f82e9b": { + "balance": "3000000000000000000000" + }, + "bd1803370bddb129d239fd16ea8526a6188ae58e": { + "balance": "500000000000000000000" + }, + "c70527d444c490e9fc3f5cc44e66eb4f306b380f": { + "balance": "4000000000000000000000" + }, + "0f206e1a1da7207ea518b112418baa8b06260328": { + "balance": "600000000000000000000" + }, + "6e1a046caf5b4a57f4fd4bc173622126b4e2fd86": { + "balance": "1790000000000000000000" + }, + "84008a72f8036f3feba542e35078c057f32a8825": { + "balance": "100000000000000000000" + }, + "246291165b59332df5f18ce5c98856fae95897d6": { + "balance": "1700000000000000000000" + }, + "7e99dfbe989d3ba529d19751b7f4317f8953a3e2": { + "balance": "400000000000000000000" + }, + "748c285ef1233fe4d31c8fb1378333721c12e27a": { + "balance": "2000000000000000000000" + }, + "3dd12e556a603736feba4a6fa8bd4ac45d662a04": { + "balance": "167450000000000000000000" + }, + "d0ae735d915e946866e1fea77e5ea466b5cadd16": { + "balance": "2000000000000000000000" + }, + "4f767bc8794aef9a0a38fea5c81f14694ff21a13": { + "balance": "512200000000000000000" + }, + "0e2f8e28a681f77c583bd0ecde16634bdd7e00cd": { + "balance": "95060000000000000000" + }, + "d74a6e8d6aab34ce85976814c1327bd6ea0784d2": { + "balance": "100000000000000000000000" + }, + "629be7ab126a5398edd6da9f18447e78c692a4fd": { + "balance": "2000000000000000000000" + }, + "2e46fcee6a3bb145b594a243a3913fce5dad6fba": { + "balance": "10000000000000000000000" + }, + "e39b11a8ab1ff5e22e5ae6517214f73c5b9b55dc": { + "balance": "2000000000000000000000" + }, + "119aa64d5b7d181dae9d3cb449955c89c1f963fa": { + "balance": "700000000000000000000" + }, + "ce079f51887774d8021cb3b575f58f18e9acf984": { + "balance": "180000000000000000000" + }, + "550c306f81ef5d9580c06cb1ab201b95c748a691": { + "balance": "665800000000000000000" + }, + "06dc7f18cee7edab5b795337b1df6a9e8bd8ae59": { + "balance": "400000000000000000000" + }, + "e21c778ef2a0d7f751ea8c074d1f812243863e4e": { + "balance": "5308559000000000000000" + }, + "45d4b54d37a8cf599821235f062fa9d170ede8a4": { + "balance": "324000000000000000000" + }, + "893a6c2eb8b40ab096b4f67e74a897b840746e86": { + "balance": "1730000000000000000000" + }, + "d44d81e18f46e2cfb5c1fcf5041bc8569767d100": { + "balance": "36381800000000000000000" + }, + "c5de1203d3cc2cea31c82ee2de5916880799eafd": { + "balance": "5000000000000000000000" + }, + "7f0f04fcf37a53a4e24ede6e93104e78be1d3c9e": { + "balance": "2000000000000000000000" + }, + "3ce1dc97fcd7b7c4d3a18a49d6f2a5c1b1a906d7": { + "balance": "200000000000000000000" + }, + "ac4ee9d502e7d2d2e99e59d8ca7d5f00c94b4dd6": { + "balance": "1000000000000000000000" + }, + "7640a37f8052981515bce078da93afa4789b5734": { + "balance": "2000000000000000000000" + }, + "76cac488111a4fd595f568ae3a858770fc915d5f": { + "balance": "200000000000000000000" + }, + "ff4a408f50e9e72146a28ce4fc8d90271f116e84": { + "balance": "1970000000000000000000" + }, + "249db29dbc19d1235da7298a04081c315742e9ac": { + "balance": "1801800000000000000000" + }, + "3a04572847d31e81f7765ca5bfc9d557159f3683": { + "balance": "133031000000000000000" + }, + "b6771b0bf3427f9ae7a93e7c2e61ee63941fdb08": { + "balance": "18800000000000000000000" + }, + "30c26a8e971baa1855d633ba703f028cc7873140": { + "balance": "10000000000000000000000" + }, + "167e3e3ae2003348459392f7dfce44af7c21ad59": { + "balance": "500000000000000000000" + }, + "43f16f1e75c3c06a9478e8c597a40a3cb0bf04cc": { + "balance": "2914000000000000000000" + }, + "056b1546894f9a85e203fb336db569b16c25e04f": { + "balance": "169397000000000000000" + }, + "70616e2892fa269705b2046b8fe3e72fa55816d3": { + "balance": "20000000000000000000000" + }, + "8f4d1d41693e462cf982fd81d0aa701d3a5374c9": { + "balance": "4000000000000000000000" + }, + "c518799a5925576213e21896e0539abb85b05ae3": { + "balance": "1000000000000000000000" + }, + "0e3a28c1dfafb0505bdce19fe025f506a6d01ceb": { + "balance": "2000000000000000000000" + }, + "e4a47e3933246c3fd62979a1ea19ffdf8c72ef37": { + "balance": "148273000000000000000" + }, + "d231929735132102471ba59007b6644cc0c1de3e": { + "balance": "1000090000000000000000" + }, + "555d8d3ce1798aca902754f164b8be2a02329c6c": { + "balance": "10000000000000000000000" + }, + "5ab1a5615348001c7c775dc75748669b8be4de14": { + "balance": "690200000000000000000" + }, + "2fee36a49ee50ecf716f1047915646779f8ba03f": { + "balance": "1056230000000000000000" + }, + "54db5e06b4815d31cb56a8719ba33af2d73e7252": { + "balance": "670000000000000000000" + }, + "7c8bb65a6fbb49bd413396a9d7e31053bbb37aa9": { + "balance": "6000000000000000000000" + }, + "c1384c6e717ebe4b23014e51f31c9df7e4e25b31": { + "balance": "500000000000000000000" + }, + "474158a1a9dc693c133f65e47b5c3ae2f773a86f": { + "balance": "200200000000000000000" + }, + "2934c0df7bbc172b6c186b0b72547ace8bf75454": { + "balance": "60000000000000000000" + }, + "6966063aa5de1db5c671f3dd699d5abe213ee902": { + "balance": "8000000000000000000000" + }, + "9225d46a5a80943924a39e5b84b96da0ac450581": { + "balance": "40000000000000000000000" + }, + "671bbca099ff899bab07ea1cf86965c3054c8960": { + "balance": "50000000000000000000" + }, + "f1f766b0e46d73fcd4d52e7a72e1b9190cc632b3": { + "balance": "8000000000000000000000" + }, + "ef0dc7dd7a53d612728bcbd2b27c19dd4d7d666f": { + "balance": "705668000000000000000" + }, + "38d2e9154964b41c8d50a7487d391e7ee2c3d3c2": { + "balance": "3500000000000000000000" + }, + "352a785f4a921632504ce5d015f83c49aa838d6d": { + "balance": "4314800000000000000000" + }, + "743de50026ca67c94df54f066260e1d14acc11ac": { + "balance": "2000000000000000000000" + }, + "b188078444027e386798a8ae68698919d5cc230d": { + "balance": "267400000000000000000" + }, + "53608105ce4b9e11f86bf497ffca3b78967b5f96": { + "balance": "20000000000000000000000" + }, + "3b159099075207c6807663b1f0f7eda54ac8cce3": { + "balance": "1969543000000000000000" + }, + "141a5e39ee2f680a600fbf6fa297de90f3225cdd": { + "balance": "10000000000000000000000" + }, + "44fff37be01a3888d3b8b8e18880a7ddefeeead3": { + "balance": "259145000000000000000" + }, + "c5a629a3962552cb8eded889636aafbd0c18ce65": { + "balance": "10000000000000000000000" + }, + "fdba5359f7ec3bc770ac49975d844ec9716256f1": { + "balance": "1000000000000000000000" + }, + "7c1df24a4f7fb2c7b472e0bb006cb27dcd164156": { + "balance": "1000000000000000000000" + }, + "ab7d54c7c6570efca5b4b8ce70f52a5773e5d53b": { + "balance": "279600000000000000000" + }, + "3f173aa6edf469d185e59bd26ae4236b92b4d8e1": { + "balance": "320000000000000000000" + }, + "a3f4ad14e0bb44e2ce2c14359c75b8e732d37054": { + "balance": "200000000000000000000" + }, + "ac5f627231480d0d95302e6d89fc32cb1d4fe7e3": { + "balance": "200000000000000000000" + }, + "d0775dba2af4c30a3a78365939cd71c2f9de95d2": { + "balance": "1940000000000000000000" + }, + "ad94235fc3b3f47a2413af31e884914908ef0c45": { + "balance": "500008000000000000000" + }, + "eaedcc6b8b6962d5d9288c156c579d47c0a9fcff": { + "balance": "85000000000000000000" + }, + "7ac48d40c664cc9a6d89f1c5f5c80a1c70e744e6": { + "balance": "3008000000000000000000" + }, + "ec73114c5e406fdbbe09b4fa621bd70ed54ea1ef": { + "balance": "24500000000000000000000" + }, + "a690f1a4b20ab7ba34628620de9ca040c43c1963": { + "balance": "4000000000000000000000" + }, + "cad14f9ebba76680eb836b079c7f7baaf481ed6d": { + "balance": "238600000000000000000" + }, + "6c714a58fff6e97d14b8a5e305eb244065688bbd": { + "balance": "4000000000000000000000" + }, + "3e618350fa01657ab0ef3ebac8e37012f8fc2b6f": { + "balance": "2804400000000000000000" + }, + "c946d5acc1346eba0a7279a0ac1d465c996d827e": { + "balance": "16385128000000000000000" + }, + "1164caaa8cc5977afe1fad8a7d6028ce2d57299b": { + "balance": "400000000000000000000" + }, + "7917e5bd82a9790fd650d043cdd930f7799633db": { + "balance": "3999800000000000000000" + }, + "d52aecc6493938a28ca1c367b701c21598b6a02e": { + "balance": "1100000000000000000000" + }, + "98bed3a72eccfbafb923489293e429e703c7e25b": { + "balance": "2000000000000000000000" + }, + "42db0b902559e04087dd5c441bc7611934184b89": { + "balance": "2014420000000000000000" + }, + "43bc2d4ddcd6583be2c7bc094b28fb72e62ba83b": { + "balance": "2000000000000000000000" + }, + "85f0e7c1e3aff805a627a2aaf2cff6b4c0dbe9cb": { + "balance": "20000000000000000000" + }, + "581b9fd6eae372f3501f42eb9619eec820b78a84": { + "balance": "19699015000000000000000" + }, + "541db20a80cf3b17f1621f1b3ff79b882f50def3": { + "balance": "1000000000000000000000" + }, + "4e8a6d63489ccc10a57f885f96eb04ecbb546024": { + "balance": "18500000000000000000000" + }, + "28349f7ef974ea55fe36a1583b34cec3c45065f0": { + "balance": "234490000000000000000" + }, + "a3241d890a92baf52908dc4aa049726be426ebd3": { + "balance": "19999560000000000000000" + }, + "b4b11d109f608fa8edd3fea9f8c315649aeb3d11": { + "balance": "5000000000000000000000" + }, + "5f321b3daaa296cadf29439f9dab062a4bffedd6": { + "balance": "81868000000000000000" + }, + "c5ae86b0c6c7e3900f1368105c56537faf8d743e": { + "balance": "188000000000000000000" + }, + "9a8eca4189ff4aa8ff7ed4b6b7039f0902219b15": { + "balance": "20000000000000000000" + }, + "a3facc50195c0b4933c85897fecc5bbd995c34b8": { + "balance": "20000000000000000000" + }, + "f07bd0e5c2ce69c7c4a724bd26bbfa9d2a17ca03": { + "balance": "5910000000000000000000" + }, + "640aba6de984d94517377803705eaea7095f4a11": { + "balance": "10000000000000000000000" + }, + "204ac98867a7c9c7ed711cb82f28a878caf69b48": { + "balance": "6000000000000000000000" + }, + "9d34dac25bd15828faefaaf28f710753b39e89dc": { + "balance": "1090400000000000000000" + }, + "fe418b421a9c6d373602790475d2303e11a75930": { + "balance": "1015200000000000000000" + }, + "3f472963197883bbda5a9b7dfcb22db11440ad31": { + "balance": "481445000000000000000" + }, + "1578bdbc371b4d243845330556fff2d5ef4dff67": { + "balance": "100000000000000000000" + }, + "dba4796d0ceb4d3a836b84c96f910afc103f5ba0": { + "balance": "166666000000000000000" + }, + "466fda6b9b58c5532750306a10a2a8c768103b07": { + "balance": "199955000000000000000" + }, + "2770f14efb165ddeba79c10bb0af31c31e59334c": { + "balance": "3000000000000000000000" + }, + "7c382c0296612e4e97e440e02d3871273b55f53b": { + "balance": "197600000000000000000" + }, + "1fb7bd310d95f2a6d9baaf8a8a430a9a04453a8b": { + "balance": "3000000000000000000000" + }, + "a9acf600081bb55bb6bfbab1815ffc4e17e85a95": { + "balance": "200000000000000000000" + }, + "f93d5bcb0644b0cce5fcdda343f5168ffab2877d": { + "balance": "209978000000000000000" + }, + "db0cc78f74d9827bdc8a6473276eb84fdc976212": { + "balance": "2000000000000000000000" + }, + "b66411e3a02dedb726fa79107dc90bc1cae64d48": { + "balance": "2000000000000000000000" + }, + "4d6e8fe109ccd2158e4db114132fe75fecc8be5b": { + "balance": "25019000000000000000" + }, + "6fd947d5a73b175008ae6ee8228163da289b167d": { + "balance": "30000000000000000000000" + }, + "32d950d5e93ea1d5b48db4714f867b0320b31c0f": { + "balance": "1015200000000000000000" + }, + "9c99b62606281b5cefabf36156c8fe62839ef5f3": { + "balance": "4000000000000000000000" + }, + "86c8d0d982b539f48f9830f9891f9d607a942659": { + "balance": "13260000000000000000000" + }, + "f2127d54188fedef0f338a5f38c7ff73ad9f6f42": { + "balance": "20000000000000000000000" + }, + "e864fec07ed1214a65311e11e329de040d04f0fd": { + "balance": "1656353000000000000000" + }, + "1d09ad2412691cc581c1ab36b6f9434cd4f08b54": { + "balance": "7000000000000000000000" + }, + "4ea70f04313fae65c3ff224a055c3d2dab28dddf": { + "balance": "19999800000000000000000" + }, + "e0668fa82c14d6e8d93a53113ef2862fa81581bc": { + "balance": "870400000000000000000" + }, + "f0d858105e1b648101ac3f85a0f8222bf4f81d6a": { + "balance": "600000000000000000000" + }, + "0f3a1023cac04dbf44f5a5fa6a9cf8508cd4fddf": { + "balance": "1820000000000000000000" + }, + "5793abe6f1533311fd51536891783b3f9625ef1c": { + "balance": "827268000000000000000" + }, + "8d667637e29eca05b6bfbef1f96d460eefbf9984": { + "balance": "4000000000000000000000" + }, + "d76dbaebc30d4ef67b03e6e6ecc6d84e004d502d": { + "balance": "2019250000000000000000" + }, + "42d1a6399b3016a8597f8b640927b8afbce4b215": { + "balance": "2980000000000000000000" + }, + "21fd47c5256012198fa5abf131c06d6aa1965f75": { + "balance": "7880000000000000000000" + }, + "2f2bba1b1796821a766fce64b84f28ec68f15aea": { + "balance": "20000000000000000000" + }, + "d24bf12d2ddf457decb17874efde2052b65cbb49": { + "balance": "14000000000000000000000" + }, + "88de13b09931877c910d593165c364c8a1641bd3": { + "balance": "3000000000000000000000" + }, + "555ca9f05cc134ab54ae9bea1c3ff87aa85198ca": { + "balance": "100000000000000000000" + }, + "ae9ecd6bdd952ef497c0050ae0ab8a82a91898ce": { + "balance": "30000000000000000000" + }, + "ad8bfef8c68a4816b3916f35cb7bfcd7d3040976": { + "balance": "40000000000000000000000" + }, + "dad136b88178b4837a6c780feba226b98569a94c": { + "balance": "200000000000000000000" + }, + "800e7d631c6e573a90332f17f71f5fd19b528cb9": { + "balance": "152000000000000000000" + }, + "94a9a71691317c2064271b51c9353fbded3501a8": { + "balance": "3340000000000000000000" + }, + "80a0f6cc186cf6201400736e065a391f52a9df4a": { + "balance": "10000000000000000000000" + }, + "712ff7370a13ed360973fedc9ff5d2c93a505e9e": { + "balance": "3940000000000000000000" + }, + "42399659aca6a5a863ea2245c933fe9a35b7880e": { + "balance": "2044000000000000000000" + }, + "ae239acffd4ebe2e1ba5b4170572dc79cc6533ec": { + "balance": "12000000000000000000000" + }, + "007b9fc31905b4994b04c9e2cfdc5e2770503f42": { + "balance": "1999000000000000000000" + }, + "7480de62254f2ba82b578219c07ba5be430dc3cb": { + "balance": "7040000000000000000000" + }, + "917b8f9f3a8d09e9202c52c29e724196b897d35e": { + "balance": "161000000000000000000" + }, + "708ea707bae4357f1ebea959c3a250acd6aa21b3": { + "balance": "500000000000000000000" + }, + "6dc7053a718616cfc78bee6382ee51add0c70330": { + "balance": "2000000000000000000000" + }, + "c4dac5a8a0264fbc1055391c509cc3ee21a6e04c": { + "balance": "6501000000000000000000" + }, + "c1b2a0fb9cad45cd699192cd27540b88d3384279": { + "balance": "500000000000000000000" + }, + "b07cb9c12405b711807543c4934465f87f98bd2d": { + "balance": "2000000000000000000000" + }, + "c7f72bb758016b374714d4899bce22b4aec70a31": { + "balance": "1072706000000000000000" + }, + "0c480de9f7461002908b49f60fc61e2b62d3140b": { + "balance": "10000000000000000000000" + }, + "83d532d38d6dee3f60adc68b936133c7a2a1b0dd": { + "balance": "500000000000000000000" + }, + "12afbcba1427a6a39e7ba4849f7ab1c4358ac31b": { + "balance": "20000000000000000000000" + }, + "f8f6645e0dee644b3dad81d571ef9baf840021ad": { + "balance": "2000000000000000000000" + }, + "40cf890591eae4a18f812a2954cb295f633327e6": { + "balance": "48132000000000000000" + }, + "735b97f2fc1bd24b12076efaf3d1288073d20c8c": { + "balance": "20000000000000000000" + }, + "47c7e5efb48b3aed4b7c6e824b435f357df4c723": { + "balance": "18200000000000000000" + }, + "d34d708d7398024533a5a2b2309b19d3c55171bb": { + "balance": "400000000000000000000" + }, + "64370e87202645125a35b207af1231fb6072f9a7": { + "balance": "200000000000000000000" + }, + "b055af4cadfcfdb425cf65ba6431078f07ecd5ab": { + "balance": "100000000000000000000" + }, + "c7de5e8eafb5f62b1a0af2195cf793c7894c9268": { + "balance": "1000000000000000000000" + }, + "c63cd7882118b8a91e074d4c8f4ba91851303b9a": { + "balance": "260000000000000000000" + }, + "164d7aac3eecbaeca1ad5191b753f173fe12ec33": { + "balance": "744090000000000000000" + }, + "e4fb26d1ca1eecba3d8298d9d148119ac2bbf580": { + "balance": "400000000000000000000" + }, + "613ac53be565d46536b820715b9b8d3ae68a4b95": { + "balance": "3760000000000000000000" + }, + "7f616c6f008adfa082f34da7d0650460368075fb": { + "balance": "1000000000000000000000" + }, + "9af100cc3dae83a33402051ce4496b16615483f6": { + "balance": "2000000000000000000000" + }, + "b45cca0d36826662683cf7d0b2fdac687f02d0c4": { + "balance": "1000000000000000000000" + }, + "93a6b3ab423010f981a7489d4aad25e2625c5741": { + "balance": "20190033000000000000000" + }, + "ee049af005974dd1c7b3a9ca8d9aa77175ba53aa": { + "balance": "333333000000000000000" + }, + "687927e3048bb5162ae7c15cf76bd124f9497b9e": { + "balance": "2000000000000000000000" + }, + "1aa40270d21e5cde86b6316d1ac3c533494b79ed": { + "balance": "20000000000000000000" + }, + "426259b0a756701a8b663528522156c0288f0f24": { + "balance": "9900000000000000000000" + }, + "91c75e3cb4aa89f34619a164e2a47898f5674d9c": { + "balance": "2000000000000000000000" + }, + "437983388ab59a4ffc215f8e8269461029c3f1c1": { + "balance": "20000000000000000000000" + }, + "272a131a5a656a7a3aca35c8bd202222a7592258": { + "balance": "2674000000000000000000" + }, + "bc0ca4f217e052753614d6b019948824d0d8688b": { + "balance": "400000000000000000000" + }, + "cc6c03bd603e09de54e9c4d5ac6d41cbce715724": { + "balance": "98500000000000000000" + }, + "d79aff13ba2da75d46240cac0a2467c656949823": { + "balance": "1730000000000000000000" + }, + "477b24eee8839e4fd19d1250bd0b6645794a61ca": { + "balance": "8000000000000000000000" + }, + "79fd6d48315066c204f9651869c1096c14fc9781": { + "balance": "2000000000000000000000" + }, + "1463a873555bc0397e575c2471cf77fa9db146e0": { + "balance": "10000000000000000000000" + }, + "89ab13ee266d779c35e8bb04cd8a90cc2103a95b": { + "balance": "60000000000000000000000" + }, + "90acced7e48c08c6b934646dfa0adf29dc94074f": { + "balance": "56154000000000000000" + }, + "31ea6eab19d00764e9a95e183f2b1b22fc7dc40f": { + "balance": "20000000000000000000" + }, + "87a53ea39f59a35bada8352521645594a1a714cb": { + "balance": "1910000000000000000000" + }, + "1e1aed85b86c6562cb8fa1eb6f8f3bc9dcae6e79": { + "balance": "4516200000000000000000" + }, + "e36a8ea87f1e99e8a2dc1b2608d166667c9dfa01": { + "balance": "100000000000000000000" + }, + "ec2cb8b9378dff31aec3c22e0e6dadff314ab5dd": { + "balance": "2000000000000000000000" + }, + "3cadeb3d3eed3f62311d52553e70df4afce56f23": { + "balance": "4000000000000000000000" + }, + "3ceca96bb1cdc214029cbc5e181d398ab94d3d41": { + "balance": "80000000000000000000000" + }, + "3283eb7f9137dd39bed55ffe6b8dc845f3e1a079": { + "balance": "66224000000000000000" + }, + "0954a8cb5d321fc3351a7523a617d0f58da676a7": { + "balance": "2506000000000000000000" + }, + "de33d708a3b89e909eaf653b30fdc3a5d5ccb4b3": { + "balance": "177300000000000000000" + }, + "1c6702b3b05a5114bdbcaeca25531aeeb34835f4": { + "balance": "26071500000000000000000" + }, + "e5b96fc9ac03d448c1613ac91d15978145dbdfd1": { + "balance": "200000000000000000000" + }, + "fbf204c813f836d83962c7870c7808ca347fd33e": { + "balance": "20000000000000000000" + }, + "3b13631a1b89cb566548899a1d60915cdcc4205b": { + "balance": "2000000000000000000000" + }, + "a87f7abd6fa31194289678efb63cf584ee5e2a61": { + "balance": "4000000000000000000000" + }, + "c0a39308a80e9e84aaaf16ac01e3b01d74bd6b2d": { + "balance": "136499000000000000000" + }, + "ffd6da958eecbc016bab91058440d39b41c7be83": { + "balance": "20000000000000000000000" + }, + "0e3dd7d4e429fe3930a6414035f52bdc599d784d": { + "balance": "40110000000000000000" + }, + "e0663e8cd66792a641f56e5003660147880f018e": { + "balance": "2000000000000000000000" + }, + "5b78eca27fbdea6f26befba8972b295e7814364b": { + "balance": "2000000000000000000000" + }, + "ec9851bd917270610267d60518b54d3ca2b35b17": { + "balance": "40000000000000000000000" + }, + "bc9c95dfab97a574cea2aa803b5caa197cef0cff": { + "balance": "420000000000000000000" + }, + "100b4d0977fcbad4debd5e64a0497aeae5168fab": { + "balance": "314500000000000000000" + }, + "1b6610fb68bad6ed1cfaa0bbe33a24eb2e96fafb": { + "balance": "152000000000000000000" + }, + "b4524c95a7860e21840296a616244019421c4aba": { + "balance": "8000000000000000000000" + }, + "88975a5f1ef2528c300b83c0c607b8e87dd69315": { + "balance": "83500000000000000000" + }, + "853e6abaf44469c72f151d4e223819aced4e3728": { + "balance": "2000000000000000000000" + }, + "d604abce4330842e3d396ca73ddb5519ed3ec03f": { + "balance": "163940000000000000000" + }, + "d209482bb549abc4777bea6d7f650062c9c57a1c": { + "balance": "320880000000000000000" + }, + "590acbda37290c0d3ec84fc2000d7697f9a4b15d": { + "balance": "500000000000000000000" + }, + "571950ea2c90c1427d939d61b4f2de4cf1cfbfb0": { + "balance": "20000000000000000000" + }, + "cb94e76febe208116733e76e805d48d112ec9fca": { + "balance": "1000000000000000000000" + }, + "fa8e3b1f13433900737daaf1f6299c4887f85b5f": { + "balance": "715000000000000000000" + }, + "162d76c2e6514a3afb6fe3d3cb93a35c5ae783f1": { + "balance": "2000000000000000000000" + }, + "4bea288eea42c4955eb9faad2a9faf4783cbddac": { + "balance": "28790618000000000000000" + }, + "c8ab1a3cf46cb8b064df2e222d39607394203277": { + "balance": "2000000000000000000000" + }, + "318b2ea5f0aaa879c4d5e548ac9d92a0c67487b7": { + "balance": "200000000000000000000" + }, + "53c5fe0119e1e848640cee30adea96940f2a5d8b": { + "balance": "21746000000000000000000" + }, + "0701f9f147ec486856f5e1b71de9f117e99e2105": { + "balance": "173360000000000000000" + }, + "337cfe1157a5c6912010dd561533791769c2b6a6": { + "balance": "1000000000000000000000" + }, + "fd60d2b5af3d35f7aaf0c393052e79c4d823d985": { + "balance": "56400000000000000000" + }, + "0f049a8bdfd761de8ec02cee2829c4005b23c06b": { + "balance": "252000000000000000000" + }, + "924bce7a853c970bb5ec7bb759baeb9c7410857b": { + "balance": "13700000000000000000" + }, + "16abb8b021a710bdc78ea53494b20614ff4eafe8": { + "balance": "158000000000000000000" + }, + "9e7f65a90e8508867bccc914256a1ea574cf07e3": { + "balance": "1240000000000000000000" + }, + "01d03815c61f416b71a2610a2daba59ff6a6de5b": { + "balance": "9553100000000000000000" + }, + "3df762049eda8ac6927d904c7af42f94e5519601": { + "balance": "2000000000000000000000" + }, + "5593c9d4b664730fd93ca60151c25c2eaed93c3b": { + "balance": "200000000000000000000" + }, + "e023f09b2887612c7c9cf1988e3a3a602b3394c9": { + "balance": "2000000000000000000000" + }, + "4c13980c32dcf3920b78a4a7903312907c1b123f": { + "balance": "60024000000000000000" + }, + "a282e969cac9f7a0e1c0cd90f5d0c438ac570da3": { + "balance": "627760000000000000000" + }, + "3b22da2a0271c8efe102532773636a69b1c17e09": { + "balance": "502000000000000000000" + }, + "1aa1021f550af158c747668dd13b463160f95a40": { + "balance": "1470000000000000000000" + }, + "f15178ffc43aa8070ece327e930f809ab1a54f9d": { + "balance": "197600000000000000000" + }, + "db1293a506e90cad2a59e1b8561f5e66961a6788": { + "balance": "2000000000000000000000" + }, + "88c361640d6b69373b081ce0c433bd590287d5ec": { + "balance": "50000000000000000000000" + }, + "3737216ee91f177732fb58fa4097267207e2cf55": { + "balance": "1520000000000000000000" + }, + "a16d9e3d63986159a800b46837f45e8bb980ee0b": { + "balance": "2030400000000000000000" + }, + "ec76f12e57a65504033f2c0bce6fc03bd7fa0ac4": { + "balance": "3580000000000000000000" + }, + "d9f1b26408f0ec67ad1d0d6fe22e8515e1740624": { + "balance": "24000000000000000000" + }, + "716ba01ead2a91270635f95f25bfaf2dd610ca23": { + "balance": "44750000000000000000000" + }, + "42a98bf16027ce589c4ed2c95831e2724205064e": { + "balance": "10000000000000000000000" + }, + "0f88aac9346cb0e7347fba70905475ba8b3e5ece": { + "balance": "10000000000000000000000" + }, + "2d8c52329f38d2a2fa9cbaf5c583daf1490bb11c": { + "balance": "20000000000000000000" + }, + "3cea302a472a940379dd398a24eafdbadf88ad79": { + "balance": "3000000000000000000000" + }, + "a29d5bda74e003474872bd5894b88533ff64c2b5": { + "balance": "10000000000000000000000" + }, + "2d23766b6f6b05737dad80a419c40eda4d77103e": { + "balance": "3820000000000000000000" + }, + "b07249e055044a9155359a402937bbd954fe48b6": { + "balance": "100000000000000000000" + }, + "f1e980c559a1a8e5e50a47f8fffdc773b7e06a54": { + "balance": "30104784000000000000000" + }, + "8275cd684c3679d5887d03664e338345dc3cdde1": { + "balance": "15800000000000000000" + }, + "b27c1a24204c1e118d75149dd109311e07c073ab": { + "balance": "3100000000000000000000" + }, + "451b3699475bed5d7905f8905aa3456f1ed788fc": { + "balance": "2560000000000000000000" + }, + "31ad4d9946ef09d8e988d946b1227f9141901736": { + "balance": "22880000000000000000000" + }, + "52b8a9592634f7300b7c5c59a3345b835f01b95c": { + "balance": "2000000000000000000000" + }, + "b161725fdcedd17952d57b23ef285b7e4b1169e8": { + "balance": "50071000000000000000" + }, + "74fc5a99c0c5460503a13b0509459da19ce7cd90": { + "balance": "200000000000000000000" + }, + "d99df7421b9382e42c89b006c7f087702a0757c0": { + "balance": "480000000000000000000" + }, + "8a4f4a7f52a355ba105fca2072d3065fc8f7944b": { + "balance": "500000000000000000000" + }, + "12316fc7f178eac22eb2b25aedeadf3d75d00177": { + "balance": "19999999000000000000000" + }, + "f598db2e09a8a5ee7d720d2b5c43bb126d11ecc2": { + "balance": "200000000000000000000" + }, + "37b8beac7b1ca38829d61ab552c766f48a10c32f": { + "balance": "400000000000000000000" + }, + "851dc38adb4593729a76f33a8616dab6f5f59a77": { + "balance": "100000000000000000000" + }, + "bf4096bc547dbfc4e74809a31c039e7b389d5e17": { + "balance": "3940000000000000000000" + }, + "98d3731992d1d40e1211c7f735f2189afa0702e0": { + "balance": "8000000000000000000000" + }, + "0f4073c1b99df60a1549d69789c7318d9403a814": { + "balance": "20000000000000000000000" + }, + "a430995ddb185b9865dbe62539ad90d22e4b73c2": { + "balance": "10000000000000000000000" + }, + "898c72dd736558ef9e4be9fdc34fef54d7fc7e08": { + "balance": "1000000000000000000000" + }, + "f9b617f752edecae3e909fbb911d2f8192f84209": { + "balance": "2674000000000000000000" + }, + "e1ae029b17e373cde3de5a9152201a14cac4e119": { + "balance": "99968000000000000000" + }, + "d8e8474292e7a051604ca164c0707783bb2885e8": { + "balance": "13370000000000000000000" + }, + "f476f2cb7208a32e051fd94ea8662992638287a2": { + "balance": "100000000000000000000" + }, + "3a84e950ed410e51b7e8801049ab2634b285fea1": { + "balance": "18690000000000000000000" + }, + "5b7784caea01799ca30227827667ce207c5cbc76": { + "balance": "2000000000000000000000" + }, + "3af65b3e28895a4a001153391d1e69c31fb9db39": { + "balance": "3940000000000000000000" + }, + "95fb5afb14c1ef9ab7d179c5c300503fd66a5ee2": { + "balance": "34225000000000000000" + }, + "a8446c4781a737ac4328b1e15b8a0b3fbb0fd668": { + "balance": "21390500000000000000000" + }, + "4888fb25cd50dbb9e048f41ca47d78b78a27c7d9": { + "balance": "17300000000000000000000" + }, + "566c10d638e8b88b47d6e6a414497afdd00600d4": { + "balance": "99960000000000000000" + }, + "bd47f5f76e3b930fd9485209efa0d4763da07568": { + "balance": "1000000000000000000000" + }, + "1e1c6351776ac31091397ecf16002d979a1b2d51": { + "balance": "1400000000000000000000" + }, + "edf603890228d7d5de9309942b5cad4219ef9ad7": { + "balance": "5000000000000000000000" + }, + "1923cfc68b13ea7e2055803645c1e320156bd88d": { + "balance": "1337000000000000000000" + }, + "8f8f37d0ad8f335d2a7101b41156b688a81a9cbe": { + "balance": "70000000000000000000" + }, + "63334fcf1745840e4b094a3bb40bb76f9604c04c": { + "balance": "3978000000000000000000" + }, + "001762430ea9c3a26e5749afdb70da5f78ddbb8c": { + "balance": "200000000000000000000" + }, + "512116817ba9aaf843d1507c65a5ea640a7b9eec": { + "balance": "50000000000000000000" + }, + "2961fb391c61957cb5c9e407dda29338d3b92c80": { + "balance": "999942000000000000000" + }, + "fc2952b4c49fedd0bc0528a308495e6d6a1c71d6": { + "balance": "2000000000000000000000" + }, + "13ec812284026e409bc066dfebf9d5a4a2bf801e": { + "balance": "1610000000000000000000" + }, + "ef463c2679fb279164e20c3d2691358773a0ad95": { + "balance": "2000000000000000000000" + }, + "3aadf98b61e5c896e7d100a3391d3250225d61df": { + "balance": "234000000000000000000" + }, + "e8137fc1b2ec7cc7103af921899b4a39e1d959a1": { + "balance": "1490000000000000000000" + }, + "b1a2b43a7433dd150bb82227ed519cd6b142d382": { + "balance": "2738000000000000000000" + }, + "c1f39bd35dd9cec337b96f47c677818160df37b7": { + "balance": "20000000000000000000" + }, + "b587b44a2ca79e4bc1dd8bfdd43a207150f2e7e0": { + "balance": "630400000000000000000" + }, + "41485612d03446ec4c05e5244e563f1cbae0f197": { + "balance": "970000000000000000000" + }, + "a12623e629df93096704b16084be2cd89d562da4": { + "balance": "8500000000000000000000" + }, + "3f2f381491797cc5c0d48296c14fd0cd00cdfa2d": { + "balance": "804000000000000000000" + }, + "9470cc36594586821821c5c996b6edc83b6d5a32": { + "balance": "24000000000000000000" + }, + "3605372d93a9010988018f9f315d032ed1880fa1": { + "balance": "500066000000000000000" + }, + "12632388b2765ee4452b50161d1fffd91ab81f4a": { + "balance": "740000000000000000000" + }, + "274a3d771a3d709796fbc4d5f48fce2fe38c79d6": { + "balance": "20000000000000000000" + }, + "d60a52580728520df7546bc1e283291788dbae0c": { + "balance": "999910000000000000000" + }, + "1ab53a11bcc63ddfaa40a02b9e186496cdbb8aff": { + "balance": "1996800000000000000000" + }, + "c282e6993fbe7a912ea047153ffd9274270e285b": { + "balance": "139939000000000000000" + }, + "a291e9c7990d552dd1ae16cebc3fca342cbaf1d1": { + "balance": "20000000000000000000000" + }, + "5547fdb4ae11953e01292b7807fa9223d0e4606a": { + "balance": "98940000000000000000" + }, + "bded11612fb5c6da99d1e30e320bc0995466141e": { + "balance": "400000000000000000000" + }, + "b73b4ff99eb88fd89b0b6d57a9bc338e886fa06a": { + "balance": "32000000000000000000" + }, + "b1c751786939bba0d671a677a158c6abe7265e46": { + "balance": "10000000000000000000000" + }, + "e881bbbe69722d81efecaa48d1952a10a2bfac8f": { + "balance": "16000000000000000000000" + }, + "fe96c4cd381562401aa32a86e65b9d52fa8aee27": { + "balance": "2640000000000000000000" + }, + "683dba36f7e94f40ea6aea0d79b8f521de55076e": { + "balance": "140000000000000000000" + }, + "5ac2908b0f398c0df5bac2cb13ca7314fba8fa3d": { + "balance": "199800000000000000000" + }, + "8914a680a5aec5226d4baaec2e5552b44dd7c874": { + "balance": "100076000000000000000" + }, + "041170f581de80e58b2a045c8f7c1493b001b7cb": { + "balance": "889800000000000000000" + }, + "4665e47396c7db97eb2a03d90863d5d4ba319a94": { + "balance": "600000000000000000000" + }, + "ed4be04a052d7accb3dcce90319dba4020ab2c68": { + "balance": "37547947000000000000000" + }, + "4b0619d9d8aa313a9531ac7dbe04ca0d6a5ad1b6": { + "balance": "2000000000000000000000" + }, + "a21442ab05340ade68c915f3c3399b9955f3f7eb": { + "balance": "775000000000000000000" + }, + "655934da8e744eaa3de34dbbc0894c4eda0b61f2": { + "balance": "200000000000000000000" + }, + "6038740ae28d66ba93b0be08482b3205a0f7a07b": { + "balance": "316000000000000000000" + }, + "99924a9816bb7ddf3fec1844828e9ad7d06bf4e6": { + "balance": "1760000000000000000000" + }, + "6847825bdee8240e28042c83cad642f286a3bddc": { + "balance": "1500000000000000000000" + }, + "a718aaad59bf395cba2b23e09b02fe0c89816247": { + "balance": "999600000000000000000" + }, + "2c89f5fdca3d155409b638b98a742e55eb4652b7": { + "balance": "98500000000000000000000" + }, + "1a7044e2383f8708305b495bd1176b92e7ef043a": { + "balance": "200000000000000000000" + }, + "282e80a554875a56799fa0a97f5510e795974c4e": { + "balance": "1000000000000000000000" + }, + "ffb3bcc3196a8c3cb834cec94c34fed35b3e1054": { + "balance": "1340000000000000000000" + }, + "d135794b149a18e147d16e621a6931f0a40a969a": { + "balance": "20000000000000000000000" + }, + "6b94615db750656ac38c7e1cf29a9d13677f4e15": { + "balance": "12000000000000000000000" + }, + "ecbe425e670d39094e20fb5643a9d818eed236de": { + "balance": "5000000000000000000000" + }, + "511e0efb04ac4e3ff2e6550e498295bfcd56ffd5": { + "balance": "668500000000000000000" + }, + "ff65511cada259260c1ddc41974ecaecd32d6357": { + "balance": "1760000000000000000000" + }, + "9ffc5fe06f33f5a480b75aa94eb8556d997a16c0": { + "balance": "20000000000000000000" + }, + "57df23bebdc65eb75feb9cb2fad1c073692b2baf": { + "balance": "4000000000000000000000" + }, + "207ef80b5d60b6fbffc51f3a64b8c72036a5abbd": { + "balance": "6685000000000000000000" + }, + "c573e841fa08174a208b060ccb7b4c0d7697127f": { + "balance": "668500000000000000000" + }, + "411610b178d5617dfab934d293f512a93e5c10e1": { + "balance": "170000000000000000000" + }, + "9991614c5baa47dd6c96874645f97add2c3d8380": { + "balance": "1970000000000000000000" + }, + "2d3480bf0865074a72c7759ee5137b4d70c51ce9": { + "balance": "200000000000000000000" + }, + "9d40e012f60425a340d82d03a1c757bfabc706fb": { + "balance": "169799000000000000000" + }, + "47648bed01f3cd3249084e635d14daa9e7ec3c8a": { + "balance": "194000000000000000000" + }, + "a5ff62222d80c013cec1a0e8850ed4d354dac16d": { + "balance": "207600000000000000000" + }, + "f80d3619702fa5838c48391859a839fb9ce7160f": { + "balance": "1992800000000000000000" + }, + "7c0f5e072043c9ee740242197e78cc4b98cdf960": { + "balance": "200000000000000000000" + }, + "a40aa2bbce0c72b4d0dfffcc42715b2b54b01bfa": { + "balance": "1000000000000000000000" + }, + "2eeed50471a1a2bf53ee30b1232e6e9d80ef866d": { + "balance": "20000000000000000000" + }, + "0c2808b951ed9e872d7b32790fcc5994ae41ffdc": { + "balance": "102000000000000000000000" + }, + "7f06c89d59807fa60bc60136fcf814cbaf2543bd": { + "balance": "10000000000000000000000" + }, + "8d4b603c5dd4570c34669515fdcc665890840c77": { + "balance": "18200000000000000000" + }, + "d5e5c135d0c4c3303934711993d0d16ff9e7baa0": { + "balance": "2000000000000000000000" + }, + "241361559feef80ef137302153bd9ed2f25db3ef": { + "balance": "20000000000000000000000" + }, + "db63122de7037da4971531fae9af85867886c692": { + "balance": "277000000000000000000" + }, + "417e4e2688b1fd66d821529e46ed4f42f8b3db3d": { + "balance": "2000000000000000000000" + }, + "127db1cadf1b771cbd7475e1b272690f558c8565": { + "balance": "14000000000000000000000" + }, + "48659d8f8c9a2fd44f68daa55d23a608fbe500dc": { + "balance": "2000000000000000000000" + }, + "b3a64b1176724f5409e1414a3523661baee74b4a": { + "balance": "25610000000000000000" + }, + "aa14422d6f0ae5a758194ed15780c838d67f1ee1": { + "balance": "28503824000000000000000" + }, + "a0a0e65204541fca9b2fb282cd95138fae16f809": { + "balance": "10000000000000000000000" + }, + "d2107b353726c3a2b46566eaa7d9f80b5d21dbe3": { + "balance": "20000000000000000000" + }, + "e4cafb727fb5c6b70bb27533b8a9ccc9ef6888e1": { + "balance": "300443000000000000000" + }, + "09f3f601f605441140586ce0656fa24aa5b1d9ae": { + "balance": "1539400000000000000000" + }, + "87fcbe7c4193ffcb08143779c9bec83fe7fda9fc": { + "balance": "100275000000000000000" + }, + "03ebc63fda6660a465045e235fbe6e5cf195735f": { + "balance": "141840000000000000000" + }, + "bdbaf6434d40d6355b1e80e40cc4ab9c68d96116": { + "balance": "100000000000000000000" + }, + "4e2225a1bb59bc88a2316674d333b9b0afca6655": { + "balance": "155000000000000000000" + }, + "4dc3da13b2b4afd44f5d0d3189f444d4ddf91b1b": { + "balance": "2000000000000000000000" + }, + "4ba8e0117fc0b6a3e56b24a3a58fe6cef442ff98": { + "balance": "5640000000000000000000" + }, + "27146913563aa745e2588430d9348e86ea7c3510": { + "balance": "400000000000000000000" + }, + "4c5afe40f18ffc48d3a1aec41fc29de179f4d297": { + "balance": "2000000000000000000000" + }, + "8a810114b2025db9fbb50099a6e0cb9e2efa6bdc": { + "balance": "1910000000000000000000" + }, + "2dee90a28f192d676a8773232b56f18f239e2fad": { + "balance": "18587970000000000000000" + }, + "60676e92d18b000509c61de540e6c5ddb676d509": { + "balance": "1200000000000000000000" + }, + "9bfc659c9c601ea42a6b21b8f17084ec87d70212": { + "balance": "10000000000000000000000" + }, + "5d5d6e821c6eef96810c83c491468560ef70bfb5": { + "balance": "2000000000000000000000" + }, + "d5787668c2c5175b01a8ee1ac3ecc9c8b2aba95a": { + "balance": "1999944000000000000000" + }, + "33b336f5ba5edb7b1ccc7eb1a0d984c1231d0edc": { + "balance": "2000000000000000000000" + }, + "3abb8adfc604f48d5984811d7f1d52fef6758270": { + "balance": "4475000000000000000000" + }, + "980a84b686fc31bdc83c221058546a71b11f838a": { + "balance": "779471000000000000000" + }, + "0b507cf553568daaf65504ae4eaa17a8ea3cdbf5": { + "balance": "2000000000000000000000" + }, + "896009526a2c7b0c09a6f63a80bdf29d9c87de9c": { + "balance": "3462830000000000000000" + }, + "9696052138338c722f1140815cf7749d0d3b3a74": { + "balance": "500000000000000000000" + }, + "3831757eae7557cb8a37a4b10644b63e4d3b3c75": { + "balance": "200000000000000000000" + }, + "62dc72729024375fc37cbb9c7c2393d10233330f": { + "balance": "2000000000000000000000" + }, + "44098866a69b68c0b6bc168229b9603587058967": { + "balance": "188000000000000000000" + }, + "25adb8f96f39492c9bb47c5edc88624e46075697": { + "balance": "26740000000000000000000" + }, + "fd4de8e3748a289cf7d060517d9d38388db01fb8": { + "balance": "250000000000000000000" + }, + "6be7595ea0f068489a2701ec4649158ddc43e178": { + "balance": "2000000000000000000000" + }, + "d402b4f6a099ebe716cb14df4f79c0cd01c6071b": { + "balance": "2000000000000000000000" + }, + "a07682000b1bcf3002f85c80c0fa2949bd1e82fd": { + "balance": "4000000000000000000000" + }, + "eb4f00e28336ea09942588eeac921811c522143c": { + "balance": "2000000000000000000000" + }, + "8f31c7005197ec997a87e69bec48649ab94bb2a5": { + "balance": "4000000000000000000000" + }, + "e7fd8fd959aed2767ea7fa960ce1db53af802573": { + "balance": "1000000000000000000000" + }, + "a8ef9ad274436042903e413c3b0c62f5f52ed584": { + "balance": "10000000000000000000000" + }, + "d83ad260e9a6f432fb6ea28743299b4a09ad658c": { + "balance": "2000000000000000000000" + }, + "b5c816a8283ca4df68a1a73d63bd80260488df08": { + "balance": "200000000000000000000" + }, + "d7d3c75920590438b82c3e9515be2eb6ed7a8b1a": { + "balance": "60000000000000000000000" + }, + "af3cb5965933e7dad883693b9c3e15beb68a4873": { + "balance": "2000000000000000000000" + }, + "6e899e59a9b41ab7ea41df7517860f2acb59f4fd": { + "balance": "20000000000000000000000" + }, + "527a8ca1268633a6c939c5de1b929aee92aeac8d": { + "balance": "900000000000000000000" + }, + "1680cec5021ee93050f8ae127251839e74c1f1fd": { + "balance": "13098657000000000000000" + }, + "ff7843c7010aa7e61519b762dfe49124a76b0e4e": { + "balance": "933580000000000000000000" + }, + "140fba58dbc04803d84c2130f01978f9e0c73129": { + "balance": "400000000000000000000" + }, + "0261ad3a172abf1315f0ffec3270986a8409cb25": { + "balance": "203500000000000000000" + }, + "ab5a79016176320973e8cd38f6375530022531c0": { + "balance": "1000000000000000000000" + }, + "fca73eff8771c0103ba3cc1a9c259448c72abf0b": { + "balance": "1000000000000000000000" + }, + "07d41217badca5e0e60327d845a3464f0f27f84a": { + "balance": "4000000000000000000000" + }, + "2c1c19114e3d6de27851484b8d2715e50f8a1065": { + "balance": "100000000000000000000" + }, + "abd21eff954fc6a7de26912a7cbb303a6607804e": { + "balance": "1517000000000000000000" + }, + "f303d5a816affd97e83d9e4dac2f79072bb0098f": { + "balance": "960000000000000000000" + }, + "114cfefe50170dd97ae08f0a44544978c599548d": { + "balance": "863000000000000000000" + }, + "647b85044df2cf0b4ed4882e88819fe22ae5f793": { + "balance": "1000032000000000000000" + }, + "1b130d6fa51d5c48ec8d1d52dc8a227be8735c8a": { + "balance": "2000000000000000000000" + }, + "0d9d3f9bc4a4c6efbd59679b69826bc1f63d9916": { + "balance": "600000000000000000000" + }, + "c765e00476810947816af142d46d2ee7bca8cc4f": { + "balance": "500000000000000000000" + }, + "b57b04fa23d1203fae061eac4542cb60f3a57637": { + "balance": "191000000000000000000" + }, + "e192489b85a982c1883246d915b229cb13207f38": { + "balance": "5000000000000000000000" + }, + "5f483ffb8f680aedf2a38f7833afdcde59b61e4b": { + "balance": "2000000000000000000000" + }, + "b46d1182e5aacaff0d26b2fcf72f3c9ffbcdd97d": { + "balance": "3139000000000000000000" + }, + "59c7f785c93160e5807ed34e5e534bc6188647a7": { + "balance": "640000000000000000000" + }, + "18e4ce47483b53040adbab35172c01ef64506e0c": { + "balance": "9000000000000000000000" + }, + "296d66b521571a4e4103a7f562c511e6aa732d81": { + "balance": "668500000000000000000" + }, + "bcd99edc2160f210a05e3a1fa0b0434ced00439b": { + "balance": "2000000000000000000000" + }, + "f14f0eb86db0eb68753f16918e5d4b807437bd3e": { + "balance": "200000000000000000000" + }, + "60d5667140d12614b21c8e5e8a33082e32dfcf23": { + "balance": "20000000000000000000000" + }, + "8ccabf25077f3aa41545344d53be1b2b9c339000": { + "balance": "1695400000000000000000" + }, + "8cc0d7c016fa7aa950114aa1db094882eda274ea": { + "balance": "159800000000000000000" + }, + "c71145e529c7a714e67903ee6206e4c3042b6727": { + "balance": "1430000000000000000000" + }, + "c5e9939334f1252ed2ba26814487dfd2982b3128": { + "balance": "70000000000000000000" + }, + "f09b3e87f913ddfd57ae8049c731dba9b636dfc3": { + "balance": "608000000000000000000" + }, + "4349225a62f70aea480a029915a01e5379e64fa5": { + "balance": "2598000000000000000000" + }, + "666b4f37d55d63b7d056b615bb74c96b3b01991a": { + "balance": "4000000000000000000000" + }, + "8bd6b1c6d74d010d1008dba6ef835d4430b35c32": { + "balance": "50000000000000000000" + }, + "7363cd90fbab5bb8c49ac20fc62c398fe6fb744c": { + "balance": "2000000000000000000000" + }, + "b7479dab5022c4d5dbaaf8de171b4e951dd1a457": { + "balance": "80000000000000000000" + }, + "5a5468fa5ca226c7532ecf06e1bc1c45225d7ec9": { + "balance": "1910000000000000000000" + }, + "32a20d028e2c6218b9d95b445c771524636a22ef": { + "balance": "9500000000000000000000" + }, + "1bd28cd5c78aee51357c95c1ef9235e7c18bc854": { + "balance": "2000000000000000000000" + }, + "693492a5c51396a482881669ccf6d8d779f00951": { + "balance": "345827000000000000000" + }, + "bd723b289a7367b6ece2455ed61edb49670ab9c4": { + "balance": "4999995000000000000000" + }, + "1be3542c3613687465f15a70aeeb81662b65cca8": { + "balance": "2000000000000000000000" + }, + "5803e68b34da121aef08b602badbafb4d12481ca": { + "balance": "18000000000000000000000" + }, + "9ac907ee85e6f3e223459992e256a43fa08fa8b2": { + "balance": "10000000000000000000000" + }, + "833b6a8ec8da408186ac8a7d2a6dd61523e7ce84": { + "balance": "16000000000000000000000" + }, + "64628c6fb8ec743adbd87ce5e018d531d9210437": { + "balance": "26740000000000000000" + }, + "566c28e34c3808d9766fe8421ebf4f2b1c4f7d77": { + "balance": "1970000000000000000000" + }, + "171ad9a04bedc8b861e8ed4bddf5717813b1bb48": { + "balance": "400000000000000000000" + }, + "4f85bc1fc5cbc9c001e8f1372e07505370d8c71f": { + "balance": "940000000000000000000" + }, + "6d2f976734b9d0070d1883cf7acab8b3e4920fc1": { + "balance": "10000000000000000000000" + }, + "357a02c0a9dfe287de447fb67a70ec5b62366647": { + "balance": "26740000000000000000" + }, + "44a01fb04ac0db2cce5dbe281e1c46e28b39d878": { + "balance": "1999944000000000000000" + }, + "3630c5e565ceaa8a0f0ffe32875eae2a6ce63c19": { + "balance": "170016000000000000000" + }, + "334340ee4b9cdc81f850a75116d50ee9b69825bf": { + "balance": "2000000000000000000000" + }, + "c0afb7d8b79370cfd663c68cc6b9702a37cd9eff": { + "balance": "1000000000000000000000" + }, + "2016895df32c8ed5478269468423aea7b7fbce50": { + "balance": "20000000000000000000" + }, + "1e2fe4e4a77d141ff49a0c7fbc95b0a2b283eeeb": { + "balance": "2000000000000000000000" + }, + "260df8943a8c9a5dba7945327fd7e0837c11ad07": { + "balance": "200000000000000000000" + }, + "32fbeed6f626fcdfd51acafb730b9eeff612f564": { + "balance": "2000000000000000000000" + }, + "9bd88068e13075f3a8cac464a5f949d6d818c0f6": { + "balance": "6000000000000000000000" + }, + "ab4572fbb1d72b575d69ec6ad17333873e8552fc": { + "balance": "1999942000000000000000" + }, + "e44ea51063405154aae736be2bf1ee3b9be639ae": { + "balance": "4000000000000000000000" + }, + "617f20894fa70e94a86a49cd74e03238f64d3cd9": { + "balance": "5000057000000000000000" + }, + "3e914e3018ac00449341c49da71d04dfeeed6221": { + "balance": "4000000000000000000000" + }, + "590181d445007bd0875aaf061c8d51153900836a": { + "balance": "2000000000000000000000" + }, + "27987110221a880826adb2e7ab5eca78c6e31aec": { + "balance": "4000000000000000000000" + }, + "06618e9d5762df62028601a81d4487d6a0ecb80e": { + "balance": "1337000000000000000000" + }, + "8cc652dd13e7fe14dabbb36d5d320db9ffee8a54": { + "balance": "1790000000000000000000" + }, + "8973aefd5efaee96095d9e288f6a046c97374b43": { + "balance": "141000000000000000000" + }, + "dbd51cdf2c3bfacdff106221de2e19ad6d420414": { + "balance": "1760000000000000000000" + }, + "25697ef20cccaa70d32d376f8272d9c1070c3d78": { + "balance": "200000000000000000000" + }, + "0726c42e00f45404836eb1e280d073e7059687f5": { + "balance": "1623331000000000000000" + }, + "5e0785532c7723e4c0af9357d5274b73bdddddde": { + "balance": "25000088000000000000000" + }, + "38430e931d93be01b4c3ef0dc535f1e0a9610063": { + "balance": "10000000000000000000000" + }, + "143d536b8b1cb84f56a39e0bc81fd5442bcacce1": { + "balance": "100000000000000000000" + }, + "5c6d041da7af4487b9dc48e8e1f60766d0a56dbc": { + "balance": "1457800000000000000000" + }, + "f9bfb59d538afc4874d4f5941b08c9730e38e24b": { + "balance": "40000000000000000000" + }, + "83dbfd8eda01d0de8e158b16d0935fc2380a5dc7": { + "balance": "600000000000000000000" + }, + "0e6cd664ad9c1ed64bf98749f40644b626e3792c": { + "balance": "60000000000000000000000" + }, + "ce2e0da8934699bb1a553e55a0b85c169435bea3": { + "balance": "4999962000000000000000" + }, + "a39bfee4aec9bd75bd22c6b672898ca9a1e95d32": { + "balance": "10000000000000000000000" + }, + "1bc44c8761231ba1f11f5faa40fa669a013e12ce": { + "balance": "203586000000000000000" + }, + "68809af5d532a11c1a4d6e32aac75c4c52b08ead": { + "balance": "10000000000000000000000" + }, + "80cc21bd99f39005c58fe4a448909220218f66cb": { + "balance": "1000072000000000000000" + }, + "1080c1d8358a15bc84dac8253c6883319020df2c": { + "balance": "2674000000000000000000" + }, + "9eaf6a328a4076024efa6b67b48b21eedcc0f0b8": { + "balance": "158000000000000000000" + }, + "1e7b5e4d1f572becf2c00fc90cb4767b4a6e33d4": { + "balance": "112970000000000000000" + }, + "acbd185589f7a68a67aa4b1bd65077f8c64e4e21": { + "balance": "200000000000000000000" + }, + "ff78541756ab2b706e0d70b18adb700fc4f1643d": { + "balance": "43250000000000000000000" + }, + "7f0ec3db804692d4d1ea3245365aab0590075bc4": { + "balance": "4000000000000000000000" + }, + "4a918032439159bb315b6725b6830dc83697739f": { + "balance": "343800000000000000000" + }, + "bc1b021a78fde42d9b5226d6ec26e06aa3670090": { + "balance": "80000000000000000000" + }, + "2f2523cc834f0086052402626296675186a8e582": { + "balance": "16000000000000000000000" + }, + "9db2e15ca681f4c66048f6f9b7941ed08b1ff506": { + "balance": "4000000000000000000000" + }, + "20b9a9e6bd8880d9994ae00dd0b9282a0beab816": { + "balance": "500000000000000000000" + }, + "3bddbc8134f77d55597fc97c26d26698090604eb": { + "balance": "13700000000000000000" + }, + "80c3a9f695b16db1597286d1b3a8b7696c39fa27": { + "balance": "100000000000000000000" + }, + "53194d8afa3e883502767edbc30586af33b114d3": { + "balance": "2000000000000000000000" + }, + "e2efd0a9bc407ece03d67e8ec8e9d283f48d2a49": { + "balance": "12280000000000000000000" + }, + "1cb450920078aab2317c7db3b38af7dd298b2d41": { + "balance": "340000000000000000000" + }, + "ca8276c477b4a07b80107b843594189607b53bec": { + "balance": "6000000000000000000000" + }, + "147f4210ab5804940a0b7db8c14c28396b62a6bf": { + "balance": "2000000000000000000000" + }, + "d3df3b53cb3b4755de54e180451cc44c9e8ae0aa": { + "balance": "659801000000000000000" + }, + "f7c708015071d4fb0a3a2a09a45d156396e3349e": { + "balance": "3000000000000000000000" + }, + "a8cafac32280d021020bf6f2a9782883d7aabe12": { + "balance": "100000000000000000000" + }, + "399aa6f5d078cb0970882bc9992006f8fbdf3471": { + "balance": "1000000000000000000000" + }, + "15669180dee29598869b08a721c7d24c4c0ee63f": { + "balance": "1000000000000000000000" + }, + "bba8ab22d2fedbcfc63f684c08afdf1c175090b5": { + "balance": "99091000000000000000" + }, + "5e5a441974a83d74c687ebdc633fb1a49e7b1ad7": { + "balance": "3000000000000000000000" + }, + "98b769cc305cecfb629a00c907069d7ef9bc3a12": { + "balance": "26000000000000000000" + }, + "c820c711f07705273807aaaa6de44d0e4b48be2e": { + "balance": "155000000000000000000" + }, + "12aa7d86ddfbad301692feac8a08f841cb215c37": { + "balance": "137000000000000000000" + }, + "6ff5d361b52ad0b68b1588607ec304ae5665fc98": { + "balance": "1940000000000000000000" + }, + "2382a9d48ec83ea3652890fd0ee79c907b5b2dc1": { + "balance": "133700000000000000000" + }, + "b2a144b1ea67b9510f2267f9da39d3f93de26642": { + "balance": "2000000000000000000000" + }, + "b3e20eb4de18bd060221689894bee5aeb25351ee": { + "balance": "73535000000000000000" + }, + "101a0a64f9afcc448a8a130d4dfcbee89537d854": { + "balance": "15200000000000000000000" + }, + "1b826fb3c012b0d159e294ba5b8a499ff3c0e03c": { + "balance": "2000000000000000000000" + }, + "aafb7b013aa1f8541c7e327bf650adbd194c208f": { + "balance": "1358000000000000000000" + }, + "96eb523e832f500a017de13ec27f5d366c560eff": { + "balance": "307600000000000000000" + }, + "c7bf17c4c11f98941f507e77084fffbd2dbd3db5": { + "balance": "1000000000000000000000" + }, + "840ec83ea93621f034e7bb3762bb8e29ded4c479": { + "balance": "2500000000000000000000" + }, + "0e9c511864a177f49be78202773f60489fe04e52": { + "balance": "6000000000000000000000" + }, + "f6f1a44309051c6b25e47dff909b179bb9ab591c": { + "balance": "1940000000000000000000" + }, + "63fe6bcc4b8a9850abbe75803730c932251f145b": { + "balance": "18200000000000000000" + }, + "f88b58db37420b464c0be88b45ee2b95290f8cfa": { + "balance": "40000000000000000000" + }, + "9d4d321177256ebd9afbda304135d517c3dc5693": { + "balance": "616000000000000000000" + }, + "8c1fbe5f0aea359c5aa1fa08c8895412ca8e05a6": { + "balance": "1000000000000000000000" + }, + "cb0dd7cf4e5d8661f6028943a4b9b75c914436a7": { + "balance": "120000000000000000000000" + }, + "a3979a92760a135adf69d72f75e167755f1cb8c3": { + "balance": "100000000000000000000" + }, + "ca22cda3606da5cad013b8074706d7e9e721a50c": { + "balance": "6816200000000000000000" + }, + "157559adc55764cc6df79323092534e3d6645a66": { + "balance": "6000000000000000000000" + }, + "4f52ad6170d25b2a2e850eadbb52413ff2303e7f": { + "balance": "3040000000000000000000" + }, + "eed28c3f068e094a304b853c950a6809ebcb03e0": { + "balance": "17300000000000000000000" + }, + "2e47f287f498233713850d3126823cc67dcee255": { + "balance": "14600000000000000000" + }, + "6c359e58a13d4578a9338e335c67e7639f5fb4d7": { + "balance": "218000000000000000000" + }, + "4968a2cedb457555a139295aea28776e54003c87": { + "balance": "10092310000000000000000" + }, + "4041374b0feef4792e4b33691fb86897a4ff560c": { + "balance": "365000000000000000000" + }, + "83e48055327c28b5936fd9f4447e73bdb2dd3376": { + "balance": "2674000000000000000000" + }, + "32b7feebc5c59bf65e861c4c0be42a7611a5541a": { + "balance": "2212000000000000000000" + }, + "21a6db6527467bc6dad54bc16e9fe2953b6794ed": { + "balance": "14000000000000000000000" + }, + "e8ead1bb90ccc3aea2b0dcc5b58056554655d1d5": { + "balance": "7760000000000000000000" + }, + "7a94b19992ceb8ce63bc92ee4b5aded10c4d9725": { + "balance": "16770000000000000000000" + }, + "90e93e4dc17121487952333614002be42356498e": { + "balance": "1910000000000000000000" + }, + "aab00abf5828d7ebf26b47ceaccdb8ba03325166": { + "balance": "10000000000000000000000" + }, + "0a9ab2638b1cfd654d25dab018a0aebddf85fd55": { + "balance": "21801000000000000000" + }, + "b12ed07b8a38ad5506363fc07a0b6d799936bdaf": { + "balance": "10000000000000000000000" + }, + "f4a9d00cefa97b7a58ef9417fc6267a5069039ee": { + "balance": "21800000000000000000" + }, + "04a1cada1cc751082ff8da928e3cfa000820a9e9": { + "balance": "40000000000000000000" + }, + "9018cc1f48d2308e252ab6089fb99a7c1d569410": { + "balance": "200000000000000000000" + }, + "895d694e880b13ccd0848a86c5ce411f88476bbf": { + "balance": "199955000000000000000" + }, + "40a7f72867a7dc86770b162b7557a434ed50cce9": { + "balance": "1000000000000000000000" + }, + "467ea10445827ef1e502daf76b928a209e0d4032": { + "balance": "2000000000000000000000" + }, + "7553aa23b68aa5f57e135fe39fdc235eaca8c98c": { + "balance": "1000000000000000000000" + }, + "31b43b015d0081643c6cda46a7073a6dfdbca825": { + "balance": "50019600000000000000000" + }, + "d82fd9fdf6996bedad2843159c06f37e0924337d": { + "balance": "1688800000000000000000" + }, + "24a4eb36a7e498c36f99975c1a8d729fd6b305d7": { + "balance": "258000000000000000000" + }, + "91d66ea6288faa4b3d606c2aa45c7b6b8a252739": { + "balance": "2000000000000000000000" + }, + "83a402438e0519773d5448326bfb61f8b20cf52d": { + "balance": "1520000000000000000000" + }, + "c2fafdd30acb6d6706e9293cb02641f9edbe07b5": { + "balance": "1494224000000000000000" + }, + "79dba256472db4e058f2e4cdc3ea4e8a42773833": { + "balance": "1460000000000000000000" + }, + "498abdeb14c26b7b7234d70fceaef361a76dff72": { + "balance": "3000000000000000000000" + }, + "7b73242d75ca9ad558d650290df17692d54cd8b8": { + "balance": "2000200000000000000000" + }, + "6ec3659571b11f889dd439bcd4d67510a25be57e": { + "balance": "123000000000000000000" + }, + "ab098633eeee0ccefdf632f9575456f6dd80fc86": { + "balance": "200000000000000000000000" + }, + "f4a51fce4a1d5b94b0718389ba4e7814139ca738": { + "balance": "300000000000000000000" + }, + "8f561b41b209f248c8a99f858788376250609cf3": { + "balance": "1700000000000000000000" + }, + "05d0f4d728ebe82e84bf597515ad41b60bf28b39": { + "balance": "4200000000000000000000" + }, + "dfdf43393c649caebe1bb18059decb39f09fb4e8": { + "balance": "400000000000000000000" + }, + "0089508679abf8c71bf6781687120e3e6a84584d": { + "balance": "1800000000000000000000" + }, + "80907f593148b57c46c177e23d25abc4aae18361": { + "balance": "100000000000000000000" + }, + "94fcceadfe5c109c5eaeaf462d43873142c88e22": { + "balance": "4800000000000000000000" + }, + "e89249738b7eced7cb666a663c49cbf6de8343ea": { + "balance": "2000000000000000000000" + }, + "23c99ba087448e19c9701df66e0cab52368331fa": { + "balance": "2000000000000000000000" + }, + "a68e0c30cba3bc5a883e540320f999c7cd558e5c": { + "balance": "1799869000000000000000" + }, + "88888a57bd9687cbf950aeeacf9740dcc4d1ef59": { + "balance": "1820000000000000000000" + }, + "e9b36fe9b51412ddca1a521d6e94bc901213dda8": { + "balance": "10000000000000000000000" + }, + "a9145046fa3628cf5fd4c613927be531e6db1fdd": { + "balance": "112000000000000000000" + }, + "e82c58c579431b673546b53a86459acaf1de9b93": { + "balance": "1000000000000000000000" + }, + "bd6a474d66345bcdd707594adb63b30c7822af54": { + "balance": "4000000000000000000000" + }, + "6a6159074ab573e0ee581f0f3df2d6a594629b74": { + "balance": "310000000000000000000" + }, + "2e7f465520ec35cc23d68e75651bb6689544a196": { + "balance": "1050049000000000000000" + }, + "ac6d02e9a46b379fac4ac9b1d7b5d47bc850ce16": { + "balance": "1760000000000000000000" + }, + "bd59094e074f8d79142ab1489f148e32151f2089": { + "balance": "20000000000000000000" + }, + "0ba6e46af25a13f57169255a34a4dac7ce12be04": { + "balance": "500000000000000000000" + }, + "35145f620397c69cb8e00962961f0f4886643989": { + "balance": "6000000000000000000000" + }, + "d84b922f7841fc5774f00e14604ae0df42c8551e": { + "balance": "4011000000000000000000" + }, + "44232ff66ddad1fd841266380036afd7cf7d7f42": { + "balance": "200000000000000000000" + }, + "516954025fca2608f47da81c215eedfd844a09ff": { + "balance": "382000000000000000000" + }, + "e5aa0b833bb916dc19a8dd683f0ede241d988eba": { + "balance": "3000000000000000000000" + }, + "80ea1acc136eca4b68c842a95adf6b7fee7eb8a2": { + "balance": "4000000000000000000000" + }, + "98a0e54c6d9dc8be96276cebf4fec460f6235d85": { + "balance": "1969803000000000000000" + }, + "91620f3eb304e813d28b0297556d65dc4e5de5aa": { + "balance": "3820000000000000000000" + }, + "7bb984c6dbb9e279966afafda59c01d02627c804": { + "balance": "8050000000000000000000" + }, + "41f489a1ec747bc29c3e5f9d8db97877d4d1b4e9": { + "balance": "133700000000000000000" + }, + "8dbc3e6cb433e194f40f82b40faadb1f8b856116": { + "balance": "1910000000000000000000" + }, + "889da40fb1b60f9ea9bd7a453e584cf7b1b4d9f7": { + "balance": "40000000000000000000" + }, + "debbdd831e0f20ae6e378252decdf92f7cf0c658": { + "balance": "2000000000000000000000" + }, + "a22ade0ddb5c6ef8d0cd8de94d82b11082cb2e91": { + "balance": "1020000000000000000000" + }, + "823219a25976bb2aa4af8bad41ac3526b493361f": { + "balance": "2000000000000000000000" + }, + "6d39a9e98f81f769d73aad2cead276ac1387babe": { + "balance": "394000000000000000000" + }, + "751abcb6cc033059911815c96fd191360ab0442d": { + "balance": "8000000000000000000000" + }, + "64d80c3b8ba68282290b75e65d8978a15a87782c": { + "balance": "1970000000000000000000" + }, + "6ba8f7e25fc2d871618e24e40184199137f9f6aa": { + "balance": "400020000000000000000" + }, + "25a74c2ac75dc8baa8b31a9c7cb4b7829b2456da": { + "balance": "2000000000000000000000" + }, + "0f7b61c59b016322e8226cafaee9d9e76d50a1b3": { + "balance": "4000000000000000000000" + }, + "7526e482529f0a14eec98871dddd0e721b0cd9a2": { + "balance": "20000000000000000000" + }, + "071dd90d14d41f4ff7c413c24238d3359cd61a07": { + "balance": "36400000000000000000000" + }, + "a986762f7a4f294f2e0b173279ad2c81a2223458": { + "balance": "20000000000000000000" + }, + "e667f652f957c28c0e66d0b63417c80c8c9db878": { + "balance": "601650000000000000000" + }, + "7b98e23cb96beee80a168069ebba8f20edd55ccf": { + "balance": "214500000000000000000" + }, + "2d8e5bb8d3521695c77e7c834e0291bfacee7408": { + "balance": "1970000000000000000000" + }, + "f23d01589eb12d439f7448ff54307529f191858d": { + "balance": "2000000000000000000000" + }, + "abd9605b3e91acfd777830d16463478ae0fc7720": { + "balance": "133700000000000000000" + }, + "eabb90d37989aab31feae547e0e6f3999ce6a35d": { + "balance": "2000000000000000000000" + }, + "0abfb39b11486d79572866195ba26c630b6784db": { + "balance": "121500000000000000000000" + }, + "d56a144d7af0ae8df649abae535a15983aa04d02": { + "balance": "5000000000000000000000" + }, + "998c1f93bcdb6ff23c10d0dc924728b73be2ff9f": { + "balance": "1002750000000000000000" + }, + "bc62b3096a91e7dc11a1592a293dd2542150d751": { + "balance": "1000000000000000000000" + }, + "0c8f66c6017bce5b20347204b602b743bad78d60": { + "balance": "2000000000000000000000" + }, + "4c5b3dc0e2b9360f91289b1fe13ce12c0fbda3e1": { + "balance": "2000000000000000000000" + }, + "b44605552471a6eee4daab71ff3bb41326d473e0": { + "balance": "839200000000000000000" + }, + "fc3d226bb36a58f526568857b0bb12d109ec9301": { + "balance": "2000000000000000000000" + }, + "adc8228ef928e18b2a807d00fb3c6c79cd1d9e96": { + "balance": "22800000000000000000" + }, + "9df32a501c0b781c0281022f42a1293ffd7b892a": { + "balance": "9000000000000000000000" + }, + "e7da609d40cde80f00ce5b4ffb6aa9d0b03494fc": { + "balance": "1000000000000000000000" + }, + "9b64d3cd8d2b73f66841b5c46bb695b88a9ab75d": { + "balance": "20769000000000000000" + }, + "8e9c08f738661f9676236eff82ba6261dd3f4822": { + "balance": "100000000000000000000" + }, + "deb97254474c0d2f5a7970dcdb2f52fb1098b896": { + "balance": "1000000000000000000000" + }, + "b4256273962bf631d014555cc1da0dcc31616b49": { + "balance": "2000000000000000000000" + }, + "23abd9e93e7957e5b636be6579051c15e5ce0b0e": { + "balance": "17188400000000000000000" + }, + "382591e7217b435e8e884cdbf415fe377a6fe29e": { + "balance": "8022000000000000000000" + }, + "f17adb740f45cbbde3094e7e13716f8103f563bd": { + "balance": "2000000000000000000000" + }, + "61ed5596c697207f3d55b2a51aa7d50f07fa09e8": { + "balance": "2000000000000000000000" + }, + "788e809741a3b14a22a4b1d937c82cfea489eebe": { + "balance": "7000000000000000000000" + }, + "992646ac1acaabf5ddaba8f9429aa6a94e7496a7": { + "balance": "1000110000000000000000" + }, + "51296f5044270d17707646129c86aad1645eadc1": { + "balance": "1337133000000000000000" + }, + "6ee8aad7e0a065d8852d7c3b9a6e5fdc4bf50c00": { + "balance": "20000000000000000000" + }, + "30db6b9b107e62102f434a9dd0960c2021f5ce4c": { + "balance": "599742000000000000000" + }, + "63fc93001305adfbc9b85d29d9291a05f8f1410b": { + "balance": "1000000000000000000000" + }, + "df6ed6006a6abe886ed33d95a4de28fc12183927": { + "balance": "910000000000000000000" + }, + "4745ab181a36aa8cbf2289d0c45165bc7ebe2381": { + "balance": "39400000000000000000" + }, + "7bb0fdf5a663b5fba28d9c902af0c811e252f298": { + "balance": "200000000000000000000" + }, + "e0ff0bd9154439c4a5b7233e291d7d868af53f33": { + "balance": "396110000000000000000" + }, + "09261f9acb451c3788844f0c1451a35bad5098e3": { + "balance": "8664000000000000000000" + }, + "2813d263fc5ff2479e970595d6b6b560f8d6d6d1": { + "balance": "2000000000000000000000" + }, + "2cd19694d1926a0fa9189edebafc671cf1b2caa5": { + "balance": "1000000000000000000000" + }, + "05336e9a722728d963e7a1cf2759fd0274530fca": { + "balance": "915583000000000000000" + }, + "e5b7af146986c0ff8f85d22e6cc334077d84e824": { + "balance": "2000000000000000000000" + }, + "3e4fbd661015f6461ed6735cefef01f31445de3a": { + "balance": "16200000000000000000000" + }, + "4f5df5b94357de948604c51b7893cddf6076baad": { + "balance": "3760000000000000000000" + }, + "9567a0de811de6ff095b7ee64e7f1b83c2615b80": { + "balance": "267400000000000000000" + }, + "955db3b74360b9a268677e73cea821668af6face": { + "balance": "30000000000000000000000" + }, + "3e040d40cb80ba0125f3b15fdefcc83f3005da1b": { + "balance": "1038000000000000000000" + }, + "43f470ed659e2991c375957e5ddec5bd1d382231": { + "balance": "100000000000000000000" + }, + "047f9bf1529daf87d407175e6f171b5e59e9ff3e": { + "balance": "650000000000000000000" + }, + "15e3b584056b62c973cf5eb096f1733e54c15c91": { + "balance": "936702000000000000000" + }, + "c03de42a109b657a64e92224c08dc1275e80d9b2": { + "balance": "20000000000000000000" + }, + "e4fc13cfcbac1b17ce7783acd423a845943f6b3a": { + "balance": "20000000000000000000" + }, + "65ff874fafce4da318d6c93d57e2c38a0d73e820": { + "balance": "1000160000000000000000" + }, + "8b997dbc078ad02961355da0a159f2927ed43d64": { + "balance": "197000000000000000000" + }, + "2f5080b83f7e2dc0a1dd11b092ad042bff788f4c": { + "balance": "3338355000000000000000" + }, + "1b3920d001c43e72b24e7ca46f0fd6e0c20a5ff2": { + "balance": "2000000000000000000000" + }, + "5ade77fd81c25c0af713b10702768c1eb2f975e7": { + "balance": "20000000000000000000" + }, + "acaaddcbf286cb0e215dda55598f7ff0f4ada5c6": { + "balance": "1000000000000000000000" + }, + "64e0217a5b38aa40583625967fa9883690388b6f": { + "balance": "200000000000000000000" + }, + "ae648155a658370f929be384f7e001047e49dd46": { + "balance": "13561000000000000000000" + }, + "f7c1b443968b117b5dd9b755572fcd39ca5ec04b": { + "balance": "456082000000000000000" + }, + "de027efbb38503226ed871099cb30bdb02af1335": { + "balance": "1000000000000000000000" + }, + "49cf1e54be363106b920729d2d0ba46f0867989a": { + "balance": "268000000000000000000" + }, + "e7f4d7fe6f561f7fa1da3005fd365451ad89df89": { + "balance": "200000000000000000000" + }, + "b036916bdacf94b69e5a8a65602975eb026104dd": { + "balance": "20000000000000000000" + }, + "e923c06177b3427ea448c0a6ff019b54cc548d95": { + "balance": "36281000000000000000" + }, + "ad927e03d1599a78ca2bf0cad2a183dceb71eac0": { + "balance": "1970000000000000000000" + }, + "ef39ca9173df15531d73e6b72a684b51ba0f2bb4": { + "balance": "1598000000000000000000" + }, + "6443b8ae639de91cf73c5ae763eeeed3ddbb9253": { + "balance": "2000000000000000000000" + }, + "8026435aac728d497b19b3e7e57c28c563954f2b": { + "balance": "1730000000000000000000" + }, + "ed327a14d5cfadd98103fc0999718d7ed70528ea": { + "balance": "1440000000000000000000" + }, + "38a3dccf2fcfe0c91a2624bd0cbf88ee4a076c33": { + "balance": "2000000000000000000000" + }, + "f0b1f9e27832c6de6914d70afc238c749995ace4": { + "balance": "2000000000000000000000" + }, + "770d98d31b4353fceee8560c4ccf803e88c0c4e0": { + "balance": "600000000000000000000" + }, + "ba1f0e03cb9aa021f4dcebfa94e5c889c9c7bc9e": { + "balance": "32200000000000000000000" + }, + "233842b1d0692fd11140cf5acda4bf9630bae5f8": { + "balance": "2000000000000000000000" + }, + "b5dd50a15da34968890a53b4f13fe1af081baaaa": { + "balance": "4000000000000000000000" + }, + "72072a0ef1cff3d567cdd260e708ddc11cbc9a31": { + "balance": "100000000000000000000" + }, + "81a88196fac5f23c3e12a69dec4b880eb7d97310": { + "balance": "2000000000000000000000" + }, + "6c63f84556d290bfcd99e434ee9997bfd779577a": { + "balance": "2000000000000000000000" + }, + "5f167aa242bc4c189adecb3ac4a7c452cf192fcf": { + "balance": "1999980000000000000000" + }, + "445cb8de5e3df520b499efc980f52bff40f55c76": { + "balance": "2000000000000000000000" + }, + "aec27ce2133e82d052520afb5c576d9f7eb93ed2": { + "balance": "65232380000000000000000" + }, + "07dc2bf83bc6af19a842ffea661af5b41b67fda1": { + "balance": "1500000000000000000000" + }, + "febd48d0ffdbd5656cd5e686363a61145228f279": { + "balance": "2800000000000000000000" + }, + "a86db07d9f812f4796622d40e03d135874a88a74": { + "balance": "20000000000000000000" + }, + "5413c97ffa4a6e2a7bba8961dc9fce8530a787d7": { + "balance": "1000000000000000000000" + }, + "e2ff9ee4b6ecc14141cc74ca52a9e7a2ee14d908": { + "balance": "1400000000000000000000" + }, + "2e8eb30a716e5fe15c74233e039bfb1106e81d12": { + "balance": "100000000000000000000" + }, + "fd88d114220f081cb3d5e15be8152ab07366576a": { + "balance": "300000000000000000000" + }, + "e408fceaa1b98f3c640f48fcba39f056066d6308": { + "balance": "10000000000000000000000" + }, + "057dd29f2d19aa3da42327ea50bce86ff5c911d9": { + "balance": "4000000000000000000000" + }, + "ed1065dbcf9d73c04ffc7908870d881468c1e132": { + "balance": "2000000000000000000000" + }, + "bbc9d8112e5beb02dd29a2257b1fe69b3536a945": { + "balance": "2000000000000000000000" + }, + "79c1be19711f73bee4e6316ae7549459aacea2e0": { + "balance": "400000000000000000000" + }, + "1bcf3441a866bdbe963009ce33c81cbb0261b02c": { + "balance": "182000000000000000000" + }, + "e2e26e4e1dcf30d048cc6ecf9d51ec1205a4e926": { + "balance": "4000000000000000000000" + }, + "77701e2c493da47c1b58f421b5495dee45bea39b": { + "balance": "6068279000000000000000" + }, + "37a05aceb9395c8635a39a7c5d266ae610d10bf2": { + "balance": "30000000000000000000000" + }, + "c6355ec4768c70a49af69513cd83a5bca7e3b9cd": { + "balance": "6000000000000000000000" + }, + "e3c0c128327a9ad80148139e269773428e638cb0": { + "balance": "2000000000000000000000" + }, + "f7f4898c4c526d955f21f055cb6e47b915e51964": { + "balance": "2288000000000000000000" + }, + "29824e94cc4348bc963279dcdf47391715324cd3": { + "balance": "1940000000000000000000" + }, + "eaa45cea02d87d2cc8fda9434e2d985bd4031584": { + "balance": "1920750000000000000000" + }, + "e08b9aba6bd9d28bc2056779d2fbf0f2855a3d9d": { + "balance": "2000000000000000000000" + }, + "87c498170934b8233d1ad1e769317d5c475f2f40": { + "balance": "1015200000000000000000" + }, + "352d29a26e8a41818181746467f582e6e84012e0": { + "balance": "6000000000000000000000" + }, + "403220600a36f73f24e190d1edb2d61be3f41354": { + "balance": "304000000000000000000" + }, + "0a48296f7631708c95d2b74975bc4ab88ac1392a": { + "balance": "5000000000000000000000" + }, + "ffe0e997f1977a615f5a315af413fd4869343ba0": { + "balance": "100076000000000000000" + }, + "ca66b2280fa282c5b67631ce552b62ee55ad8474": { + "balance": "1969488000000000000000" + }, + "2b6ed29a95753c3ad948348e3e7b1a251080ffb9": { + "balance": "250000000000000000000000" + }, + "492e70f04d18408cb41e25603730506b35a2876b": { + "balance": "39400000000000000000" + }, + "0e6baaa3deb989f289620076668618e9ac332865": { + "balance": "200000000000000000000" + }, + "b753a75f9ed10b21643a0a3dc0517ac96b1a4068": { + "balance": "401800000000000000000" + }, + "3ad915d550b723415620f5a9b5b88a85f382f035": { + "balance": "1000000000000000000000" + }, + "c992be59c6721caf4e028f9e8f05c25c55515bd4": { + "balance": "20000000000000000000" + }, + "02b643d6fabd437a851accbe79abb7fde126dccf": { + "balance": "7200000000000000000000" + }, + "88797e58675ed5cc4c19980783dbd0c956085153": { + "balance": "2000000000000000000000" + }, + "ac142eda1157b9a9a64390df7e6ae694fac98905": { + "balance": "200000000000000000000" + }, + "656579daedd29370d9b737ee3f5cd9d84bc2b342": { + "balance": "1430000000000000000000" + }, + "9bb9b02a26bfe1ccc3f0c6219e261c397fc5ca78": { + "balance": "1337000000000000000000" + }, + "bee8d0b008421954f92d000d390fb8f8e658eaee": { + "balance": "1000000000000000000000" + }, + "7989d09f3826c3e5af8c752a8115723a84d80970": { + "balance": "415554000000000000000" + }, + "7cd5d81eab37e11e6276a3a1091251607e0d7e38": { + "balance": "62856000000000000000" + }, + "6ce1b0f6adc47051e8ab38b39edb4186b03babcc": { + "balance": "1207800000000000000000" + }, + "abfcf5f25091ce57875fc674dcf104e2a73dd2f2": { + "balance": "19700000000000000000" + }, + "1c3ef05dae9dcbd489f3024408669de244c52a02": { + "balance": "20000000000000000000000" + }, + "cfa8b37127149bdbfee25c34d878510951ea10eb": { + "balance": "2000000000000000000000" + }, + "74863acec75d03d53e860e64002f2c165e538377": { + "balance": "1000000000000000000000" + }, + "59b9e733cba4be00429b4bd9dfa64732053a7d55": { + "balance": "20000000000000000000" + }, + "aeadfcd0978edad74a32bd01a0a51d37f246e661": { + "balance": "260000000000000000000" + }, + "08090876baadfee65c3d363ba55312748cfa873d": { + "balance": "1700170000000000000000" + }, + "e589fa76984db5ec4004b46ee8a59492c30744ce": { + "balance": "2800000000000000000000" + }, + "3485361ee6bf06ef6508ccd23d94641f814d3e2f": { + "balance": "2000000000000000000000" + }, + "5cb731160d2e8965670bde925d9de5510935347d": { + "balance": "40000000000000000000" + }, + "8ef4d8a2c23c5279187b64e96f741404085385f3": { + "balance": "299598000000000000000" + }, + "e246683cc99db7c4a52bcbacaab0b32f6bfc93d7": { + "balance": "2000000000000000000000" + }, + "7d273e637ef1eac481119413b91c989dc5eac122": { + "balance": "500000000000000000000" + }, + "6efba8fb2ac5b6730729a972ec224426a287c3ad": { + "balance": "283152000000000000000" + }, + "0773eeacc050f74720b4a1bd57895b1cceeb495d": { + "balance": "10000000000000000000000" + }, + "88a122a2382c523931fb51a0ccad3beb5b7259c3": { + "balance": "2000000000000000000000" + }, + "b0b779b94bfa3c2e1f587bcc9c7e21789222378f": { + "balance": "1550000000000000000000" + }, + "86f95c5b11a293940e35c0b898d8b75f08aab06d": { + "balance": "29605000000000000000000" + }, + "cf2288ef4ebf88e86db13d8a0e0bf52a056582c3": { + "balance": "2533000000000000000000" + }, + "71ea5b11ad8d29b1a4cb67bf58ca6c9f9c338c16": { + "balance": "1600000000000000000000" + }, + "9917d68d4af341d651e7f0075c6de6d7144e7409": { + "balance": "5660000000000000000000" + }, + "1e5800227d4dcf75e30f5595c5bed3f72e341e3b": { + "balance": "248300000000000000000" + }, + "123759f333e13e3069e2034b4f05398918119d36": { + "balance": "20000000000000000000000" + }, + "f798d16da4e460c460cd485fae0fa0599708eb82": { + "balance": "1000000000000000000000" + }, + "864bec5069f855a4fd5892a6c4491db07c88ff7c": { + "balance": "1000000000000000000000" + }, + "fa283299603d8758e8cab082125d2c8f7d445429": { + "balance": "6415633000000000000000" + }, + "c811c2e9aa1ac3462eba5e88fcb5120e9f6e2ca2": { + "balance": "1400140000000000000000" + }, + "61547d376e5369bcf978fc162c3c56ae453547e8": { + "balance": "200000000000000000000" + }, + "0d747ee5969bf79d57381d6fe3a2406cd0d8ce27": { + "balance": "100000000000000000000000" + }, + "f8962b75db5d24c7e8b7cef1068c3e67cebb30a5": { + "balance": "280000000000000000000" + }, + "35bf6688522f35467a7f75302314c02ba176800e": { + "balance": "17400000000000000000000" + }, + "05cb6c3b0072d3116761b532b218443b53e8f6c5": { + "balance": "141722000000000000000000" + }, + "91c80caa081b38351d2a0e0e00f80a34e56474c1": { + "balance": "1000000000000000000000" + }, + "d75a502a5b677287470f65c5aa51b87c10150572": { + "balance": "907400000000000000000" + }, + "3e194b4ecef8bb711ea2ff24fec4e87bd032f7d1": { + "balance": "2575465000000000000000" + }, + "736bf1402c83800f893e583192582a134eb532e9": { + "balance": "9999996000000000000000" + }, + "c2cb1ada5da9a0423873814793f16144ef36b2f3": { + "balance": "1334326000000000000000" + }, + "efcce06bd6089d0e458ef561f5a689480afe7000": { + "balance": "600000000000000000000" + }, + "bfe6bcb0f0c07852643324aa5df5fd6225abc3ca": { + "balance": "74500000000000000000" + }, + "9d799e943e306ba2e5b99c8a6858cbb52c0cf735": { + "balance": "300000000000000000000" + }, + "f45b1dcb2e41dc27ffa024daadf619c11175c087": { + "balance": "19700000000000000000" + }, + "08e38ee0ce48c9ca645c1019f73b5355581c56e6": { + "balance": "1600000000000000000000" + }, + "2cb4c3c16bb1c55e7c6b7a19b127a1ac9390cc09": { + "balance": "3397053000000000000000" + }, + "bdc02cd4330c93d6fbda4f6db2a85df22f43c233": { + "balance": "2000000000000000000000" + }, + "acec91ef6941cf630ba9a3e787a012f4a2d91dd4": { + "balance": "80000000000000000000000" + }, + "27ac073be79ce657a93aa693ee43bf0fa41fef04": { + "balance": "50000000000000000000000" + }, + "22fe884d9037291b4d52e6285ae68dea0be9ffb5": { + "balance": "2000000000000000000000" + }, + "c3107a9af3322d5238df0132419131629539577d": { + "balance": "492650000000000000000" + }, + "b5cac5ed03477d390bb267d4ebd46101fbc2c3da": { + "balance": "197000000000000000000" + }, + "58fb947364e7695765361ebb1e801ffb8b95e6d0": { + "balance": "200000000000000000000" + }, + "32860997d730b2d83b73241a25d3667d51c908ef": { + "balance": "499938000000000000000" + }, + "c79d5062c796dd7761f1f13e558d73a59f82f38b": { + "balance": "8000000000000000000000" + }, + "fa142fe47eda97e6503b386b18a2bedd73ccb5b1": { + "balance": "850080000000000000000" + }, + "6ca5de00817de0cedce5fd000128dede12648b3c": { + "balance": "20000000000000000000" + }, + "214b743955a512de6e0d886a8cbd0282bee6d2a2": { + "balance": "2000000000000000000000" + }, + "ede79ae1ff4f1606d59270216fa46ab2ddd4ecaa": { + "balance": "146000000000000000000" + }, + "528101ce46b720a2214dcdae6618a53177ffa377": { + "balance": "508876000000000000000" + }, + "b5870ce342d43343333673038b4764a46e925f3e": { + "balance": "1000000000000000000000" + }, + "843bd3502f45f8bc4da370b323bdac3fcf5f19a6": { + "balance": "1476000000000000000000" + }, + "5067f4549afbfe884c59cbc12b96934923d45db0": { + "balance": "1000000000000000000000" + }, + "6f2a42e6e033d01061131929f7a6ee1538021e52": { + "balance": "2000000000000000000000" + }, + "e9e1f7cb00a110edd0ebf8b377ef8a7bb856117f": { + "balance": "200000000000000000000" + }, + "a387ecde0ee4c8079499fd8e03473bd88ad7522a": { + "balance": "1970000000000000000000" + }, + "6dff90e6dc359d2590882b1483edbcf887c0e423": { + "balance": "1000000000000000000000" + }, + "22e512149a18d369b73c71efa43e86c9edabaf1d": { + "balance": "1455000000000000000000" + }, + "a3203095edb7028e6871ce0a84f548459f83300a": { + "balance": "4000000000000000000000" + }, + "93b4bf3fdff6de3f4e56ba6d7799dc4b93a6548f": { + "balance": "19100000000000000000" + }, + "8c75956e8fed50f5a7dd7cfd27da200f6746aea6": { + "balance": "1000000000000000000000" + }, + "afc8ebe8988bd4105acc4c018e546a1e8f9c7888": { + "balance": "500000000000000000000" + }, + "bf9acd4445d9c9554689cabbbab18800ff1741c2": { + "balance": "1000000000000000000000" + }, + "603f2fab7afb6e017b94766069a4b43b38964923": { + "balance": "1656954000000000000000" + }, + "a1f765c44fe45f790677944844be4f2d42165fbd": { + "balance": "3687750000000000000000" + }, + "4dc9d5bb4b19cecd94f19ec25d200ea72f25d7ed": { + "balance": "2000000000000000000000" + }, + "48f60a35484fe7792bcc8a7b6393d0dda1f6b717": { + "balance": "3600000000000000000000" + }, + "588ed990a2aff44a94105d58c305257735c868ac": { + "balance": "16100000000000000000000" + }, + "710be8fd5e2918468be2aabea80d828435d79612": { + "balance": "17600000000000000000" + }, + "03ea6d26d080e57aee3926b18e8ed73a4e5b2826": { + "balance": "200000000000000000000" + }, + "20824ba1dbebbef9846ef3d0f6c1b017e6912ec4": { + "balance": "7170194000000000000000" + }, + "f7500c166f8bea2f82347606e5024be9e4f4ce99": { + "balance": "20000000000000000000" + }, + "9d369165fb70b81a3a765f188fd60cbe5e7b0968": { + "balance": "2000000000000000000000" + }, + "6fddbd9bca66e28765c2162c8433548c1052ed11": { + "balance": "82720000000000000000000" + }, + "8b81156e698639943c01a75272ad3d35851ab282": { + "balance": "344946000000000000000" + }, + "75804aac64b4199083982902994d9c5ed8828f11": { + "balance": "557800000000000000000" + }, + "d6e8e97ae9839b9ee507eedb28edfb7477031439": { + "balance": "2000000000000000000000" + }, + "6c808cabb8ff5fbb6312d9c8e84af8cf12ef0875": { + "balance": "4000086000000000000000" + }, + "afa539586e4719174a3b46b9b3e663a7d1b5b987": { + "balance": "5000000000000000000000" + }, + "f8a065f287d91d77cd626af38ffa220d9b552a2b": { + "balance": "1910000000000000000000" + }, + "30e60900cacc7203f314dc604347255167fc2a0f": { + "balance": "2000000000000000000000" + }, + "796f87ba617a2930b1670be92ed1281fb0b346e1": { + "balance": "128400000000000000000" + }, + "f114ff0d0f24eff896edde5471dea484824a99b3": { + "balance": "13700000000000000000" + }, + "0b80fc70282cbdd5fde35bf78984db3bdb120188": { + "balance": "1000160000000000000000" + }, + "da7ad025ebde25d22243cb830ea1d3f64a566323": { + "balance": "500000000000000000000" + }, + "65a52141f56bef98991724c6e7053381da8b5925": { + "balance": "60140000000000000000" + }, + "bbc8eaff637e94fcc58d913c7770c88f9b479277": { + "balance": "200000000000000000000" + }, + "0469e8c440450b0e512626fe817e6754a8152830": { + "balance": "2000000000000000000000" + }, + "0727be0a2a00212048b5520fbefb953ebc9d54a0": { + "balance": "10000000000000000000000" + }, + "7d858493f07415e0912d05793c972113eae8ae88": { + "balance": "1818000000000000000000" + }, + "7091303116d5f2389b23238b4d656a8596d984d3": { + "balance": "1094014000000000000000" + }, + "3702e704cc21617439ad4ea27a5714f2fda1e932": { + "balance": "1000000000000000000000" + }, + "b87de1bcd29269d521b8761cc39cfb4319d2ead5": { + "balance": "1000000000000000000000" + }, + "f639ac31da9f67271bd10402b7654e5ce763bd47": { + "balance": "399996000000000000000" + }, + "e7735ec76518fc6aa92da8715a9ee3f625788f13": { + "balance": "1997803000000000000000" + }, + "51277fe7c81eebd252a03df69a6b9f326e272207": { + "balance": "59965000000000000000" + }, + "3b8098533f7d9bdcd307dbb23e1777ca18418936": { + "balance": "2000000000000000000000" + }, + "2cba6d5d0dc204ea8a25ada2e26f5675bd5f2fdc": { + "balance": "1330755000000000000000" + }, + "5c3c1c645b917543113b3e6c1c054da1fe742b9a": { + "balance": "800000000000000000000" + }, + "5ecdbaeab9106ffe5d7b519696609a05baeb85ad": { + "balance": "20000000000000000000" + }, + "45a820a0672f17dc74a08112bc643fd1167736c3": { + "balance": "199943000000000000000" + }, + "beef94213879e02622142bea61290978939a60d7": { + "balance": "5728109000000000000000" + }, + "6cd212aee04e013f3d2abad2a023606bfb5c6ac7": { + "balance": "1999944000000000000000" + }, + "92698e345378c62d8eda184d94366a144b0c105b": { + "balance": "1400000000000000000000" + }, + "2d5b42fc59ebda0dfd66ae914bc28c1b0a6ef83a": { + "balance": "206764195000000000000000" + }, + "b7a6791c16eb4e2162f14b6537a02b3d63bfc602": { + "balance": "780700000000000000000" + }, + "fa105f1a11b6e4b1f56012a27922e2ac2da4812f": { + "balance": "9550000000000000000000" + }, + "2306df931a940d58c01665fa4d0800802c02edfe": { + "balance": "1000000000000000000000" + }, + "f37bf78c5875154711cb640d37ea6d28cfcb1259": { + "balance": "200000000000000000000" + }, + "66201bd227ae6dc6bdfed5fbde811fecfe5e9dd9": { + "balance": "594808000000000000000" + }, + "2bafbf9e9ed2c219f7f2791374e7d05cb06777e7": { + "balance": "220000000000000000000" + }, + "8e9b35ad4a0a86f758446fffde34269d940ceacd": { + "balance": "4000000000000000000000" + }, + "1b43232ccd4880d6f46fa751a96cd82473315841": { + "balance": "80000000000000000000" + }, + "6eefdc850e87b715c72791773c0316c3559b58a4": { + "balance": "4000000000000000000000" + }, + "f2c03e2a38998c21648760f1e5ae7ea3077d8522": { + "balance": "2642456000000000000000" + }, + "0625d06056968b002206ff91980140242bfaa499": { + "balance": "1000000000000000000000" + }, + "6158e107c5eb54cb7604e0cd8dc1e07500d91c3c": { + "balance": "50000000000000000000" + }, + "02477212ffdd75e5155651b76506b1646671a1eb": { + "balance": "1760000000000000000000" + }, + "fa44a855e404c86d0ca8ef3324251dfb349c539e": { + "balance": "1552000000000000000000" + }, + "49897fe932bbb3154c95d3bce6d93b6d732904dd": { + "balance": "4000000000000000000000" + }, + "9b6641b13e172fc072ca4b8327a3bc28a15b66a9": { + "balance": "120000000000000000000" + }, + "a46b4387fb4dcce011e76e4d73547d4481e09be5": { + "balance": "1337000000000000000000" + }, + "72bb27cb99f3e2c2cf90a98f707d30e4a201a071": { + "balance": "1640000000000000000000" + }, + "b6bfe1c3ef94e1846fb9e3acfe9b50c3e9069233": { + "balance": "1999944000000000000000" + }, + "e6cb3f3124c9c9cc3834b1274bc3336456a38bac": { + "balance": "427382000000000000000" + }, + "fcbc5c71ace79741450b012cf6b8d3f17db68a70": { + "balance": "9550000000000000000000" + }, + "15dbb48c98309764f99ced3692dcca35ee306bac": { + "balance": "150000000000000000000000" + }, + "2e10910ba6e0bc17e055556614cb87090f4d7e5b": { + "balance": "200000000000000000000" + }, + "e5fbe34984b637196f331c679d0c0c47d83410e1": { + "balance": "2000050000000000000000" + }, + "6d120f0caae44fd94bcafe55e2e279ef96ba5c7a": { + "balance": "4000000000000000000000" + }, + "aa5afcfd8309c2df9d15be5e6a504e7d706624c5": { + "balance": "5846763000000000000000" + }, + "37959c20b7e9931d72f5a8ae869dafddad3b6d5c": { + "balance": "200000000000000000000" + }, + "b041310fe9eed6864cedd4bee58df88eb4ed3cac": { + "balance": "10000000000000000000000" + }, + "986df47e76e4d7a789cdee913cc9831650936c9d": { + "balance": "5000000000000000000000" + }, + "35aaa0465d1c260c420fa30e2629869fb6559207": { + "balance": "704976000000000000000" + }, + "7f655c6789eddf455cb4b88099720639389eebac": { + "balance": "6000000000000000000000" + }, + "9e3eb509278fe0dcd8e0bbe78a194e06b6803943": { + "balance": "940000000000000000000" + }, + "3e9410d3b9a87ed5e451a6b91bb8923fe90fb2b5": { + "balance": "200000000000000000000" + }, + "9e960dcd03d5ba99cb115d17ff4c09248ad4d0be": { + "balance": "200000000000000000000" + }, + "f057aa66ca767ede124a1c5b9cc5fc94ef0b0137": { + "balance": "2077730000000000000000" + }, + "f38a6ca80168537e974d14e1c3d13990a44c2c1b": { + "balance": "6000000000000000000000" + }, + "229e430de2b74f442651ddcdb70176bc054cad54": { + "balance": "13545000000000000000" + }, + "27bf9f44ba7d05c33540c3a53bb02cbbffe7c3c6": { + "balance": "2000000000000000000000" + }, + "10389858b800e8c0ec32f51ed61a355946cc409b": { + "balance": "200000000000000000000" + }, + "fd2929271e9d2095a264767e7b0df52ea0d1d400": { + "balance": "3000040000000000000000" + }, + "44250d476e062484e9080a3967bf3a4a732ad73f": { + "balance": "20000000000000000000" + }, + "0c67033dd8ee7f0c8ae534d42a51f7d9d4f7978f": { + "balance": "200000000000000000000" + }, + "e083d34863e0e17f926b7928edff317e998e9c4b": { + "balance": "400000000000000000000" + }, + "7f7192c0df1c7db6d9ed65d71184d8e4155a17ba": { + "balance": "79800000000000000000" + }, + "51e7b55c2f9820eed73884361b5066a59b6f45c6": { + "balance": "2000000000000000000000" + }, + "4fa983bb5e3073a8edb557effeb4f9fb1d60ef86": { + "balance": "1599800000000000000000" + }, + "5a5ee8e9bb0e8ab2fecb4b33d29478be50bbd44b": { + "balance": "776000000000000000000" + }, + "1f3959fc291110e88232c36b7667fc78a379613f": { + "balance": "18200000000000000000" + }, + "2d7d5c40ddafc450b04a74a4dabc2bb5d665002e": { + "balance": "2000000000000000000000" + }, + "5215183b8f80a9bc03d26ce91207832a0d39e620": { + "balance": "1000000000000000000000" + }, + "5607590059a9fec1881149a44b36949aef85d560": { + "balance": "2000000000000000000000" + }, + "f7c50f922ad16b61c6d1baa045ed816815bac48f": { + "balance": "12566370000000000000000" + }, + "da10978a39a46ff0bb848cf65dd9c77509a6d70e": { + "balance": "2000000000000000000000" + }, + "a7dcbba9b9bf6762c145416c506a71e3b497209c": { + "balance": "1999944000000000000000" + }, + "54e01283cc8b384538dd646770b357c960d6cacd": { + "balance": "5000000000000000000000" + }, + "78cf8336b328db3d87813a472b9e89b75e0cf3bc": { + "balance": "1000000000000000000000" + }, + "ba24fc436753a739db2c8d40e6d4d04c528e86fa": { + "balance": "13000000000000000000000" + }, + "dfe929a61c1b38eddbe82c25c2d6753cb1e12d68": { + "balance": "402500000000000000000" + }, + "2b49fba29830360fcdb6da23bbfea5c0bbac5281": { + "balance": "20000000000000000000" + }, + "76becae4a31d36f3cb577f2a43594fb1abc1bb96": { + "balance": "24860000000000000000000" + }, + "e0cf698a053327ebd16b7d7700092fe2e8542446": { + "balance": "95275000000000000000" + }, + "a3802d8a659e89a2c47e905430b2a827978950a7": { + "balance": "1000000000000000000000" + }, + "75636cdb109050e43d5d6ec47e359e218e857eca": { + "balance": "22886800000000000000000" + }, + "3d813ff2b6ed57b937dabf2b381d148a411fa085": { + "balance": "100000000000000000000" + }, + "a9252551a624ae513719dabe5207fbefb2fd7749": { + "balance": "40000000000000000000" + }, + "c749668042e71123a648975e08ed6382f83e05e2": { + "balance": "14000000000000000000000" + }, + "04eca501630abce35218b174956b891ba25efb23": { + "balance": "1000060000000000000000" + }, + "790f91bd5d1c5cc4739ae91300db89e1c1303c93": { + "balance": "2000000000000000000000" + }, + "009560a3de627868f91fa8bfe1c1b7afaf08186b": { + "balance": "524000000000000000000" + }, + "1329dd19cd4baa9fc64310efeceab22117251f12": { + "balance": "200000000000000000000" + }, + "7005a772282b1f62afda63f89b5dc6ab64c84cb9": { + "balance": "18000000000000000000000" + }, + "abfe936425dcc7b74b955082bbaaf2a11d78bc05": { + "balance": "1400000000000000000000" + }, + "97d0d9725e3b70e675843173938ed371b62c7fac": { + "balance": "170000000000000000000" + }, + "41ed2d8e7081482c919fc23d8f0091b3c82c4685": { + "balance": "1295460000000000000000" + }, + "992365d764c5ce354039ddfc912e023a75b8e168": { + "balance": "18200000000000000000" + }, + "e1c607c0a8a060da8f02a8eb38a013ea8cda5b8c": { + "balance": "805000000000000000000" + }, + "3b2c45990e21474451cf4f59f01955b331c7d7c9": { + "balance": "2000000000000000000000" + }, + "29ac2b458454a36c7e96c73a8667222a12242c71": { + "balance": "4000000000000000000000" + }, + "b8555010776e3c5cb311a5adeefe9e92bb9a64b9": { + "balance": "4000000000000000000000" + }, + "30380087786965149e81423b15e313ba32c5c783": { + "balance": "18200000000000000000" + }, + "a2f86bc061884e9eef05640edd51a2f7c0596c69": { + "balance": "2000050000000000000000" + }, + "9f98eb34d46979b0a6de8b05aa533a89b825dcf1": { + "balance": "86500000000000000000" + }, + "c81fb7d20fd2800192f0aac198d6d6a37d3fcb7d": { + "balance": "259500000000000000000" + }, + "a4035ab1e5180821f0f380f1131b7387c8d981cd": { + "balance": "20000000000000000000" + }, + "782f52f0a676c77716d574c81ec4684f9a020a97": { + "balance": "850055000000000000000" + }, + "261e0fa64c51137465eecf5b90f197f7937fdb05": { + "balance": "18000000000000000000000" + }, + "276fd7d24f8f883f5a7a28295bf17151c7a84b03": { + "balance": "2000000000000000000000" + }, + "a1f5b840140d5a9acef402ac3cc3886a68cad248": { + "balance": "2000000000000000000000" + }, + "d2bf67a7f3c6ce56b7be41675dbbadfe7ea93a33": { + "balance": "400000000000000000000" + }, + "8ee584337ddbc80f9e3498df55f0a21eacb57fb1": { + "balance": "20000000000000000000" + }, + "34393c5d91b9de597203e75bac4309b5fa3d28c3": { + "balance": "194000000000000000000" + }, + "114cbbbf6fb52ac414be7ec61f7bb71495ce1dfa": { + "balance": "3000000000000000000000" + }, + "ab7c42c5e52d641a07ad75099c62928b7f86622f": { + "balance": "335940000000000000000" + }, + "80bf995ed8ba92701d10fec49f9e7d014dbee026": { + "balance": "572153000000000000000" + }, + "4a192035e2619b24b0709d56590e9183ccf2c1d9": { + "balance": "10000000000000000000000" + }, + "376cd7577383e902951b60a2017ba7ea29e33576": { + "balance": "2000000000000000000000" + }, + "f5437e158090b2a2d68f82b54a5864b95dd6dbea": { + "balance": "4010732000000000000000" + }, + "13a5eecb38305df94971ef2d9e179ae6cebab337": { + "balance": "330000000000000000000" + }, + "efc8cf1963c9a95267b228c086239889f4dfd467": { + "balance": "10000000000000000000000" + }, + "db77b88dcb712fd17ee91a5b94748d720c90a994": { + "balance": "2000000000000000000000" + }, + "9aaafa0067647ed999066b7a4ca5b4b3f3feaa6f": { + "balance": "1000000000000000000000" + }, + "ae36f7452121913e800e0fcd1a65a5471c23846f": { + "balance": "164000000000000000000" + }, + "b124bcb6ffa430fcae2e86b45f27e3f21e81ee08": { + "balance": "2000000000000000000000" + }, + "f2813a64c5265d020235cb9c319b6c96f906c41e": { + "balance": "350000000000000000000" + }, + "e848ca7ebff5c24f9b9c316797a43bf7c356292d": { + "balance": "114000000000000000000" + }, + "21a6feb6ab11c766fdd977f8df4121155f47a1c0": { + "balance": "57200000000000000000" + }, + "e95e92bbc6de07bf3a660ebf5feb1c8a3527e1c5": { + "balance": "18200000000000000000" + }, + "0b369e002e1b4c7913fcf00f2d5e19c58165478f": { + "balance": "64520000000000000000" + }, + "0909648c18a3ce5bae7a047ec2f868d24cdda81d": { + "balance": "3820000000000000000000" + }, + "d32b45564614516c91b07fa9f72dcf787cce4e1c": { + "balance": "291000000000000000000" + }, + "cf1bdb799b2ea63ce134668bdc198b54840f180b": { + "balance": "18200000000000000000" + }, + "ae062c448618643075de7a0030342dced63dbad7": { + "balance": "825982000000000000000" + }, + "99dfd0504c06c743e46534fd7b55f1f9c7ec3329": { + "balance": "2000000000000000000000" + }, + "87fc4635263944ce14a46c75fa4a821f39ce7f72": { + "balance": "20000000000000000000" + }, + "27c2d7ca504daa3d9066dc09137dc42f3aaab452": { + "balance": "600000000000000000000" + }, + "cc60f836acdef3548a1fefcca13ec6a937db44a0": { + "balance": "86500000000000000000" + }, + "c910a970556c9716ea53af66ddef93143124913d": { + "balance": "1580000000000000000000" + }, + "8173c835646a672e0152be10ffe84162dd256e4c": { + "balance": "492000000000000000000" + }, + "e989733ca1d58d9e7b5029ba5d444858bec03172": { + "balance": "581595000000000000000" + }, + "86806474c358047d9406e6a07f40945bc8328e67": { + "balance": "6884000000000000000000" + }, + "5395a4455d95d178b4532aa4725b193ffe512961": { + "balance": "1000000000000000000000" + }, + "56397638bb3cebf1f62062794b5eb942f916171d": { + "balance": "2000000000000000000000" + }, + "6958f83bb2fdfb27ce0409cd03f9c5edbf4cbedd": { + "balance": "20000000000000000000000" + }, + "26ff0a51e7cece8400276978dbd6236ef162c0e6": { + "balance": "100020000000000000000000" + }, + "4ca783b556e5bf53aa13c8116613d65782c9b642": { + "balance": "25200000000000000000000" + }, + "15a0aec37ff9ff3d5409f2a4f0c1212aaccb0296": { + "balance": "1000000000000000000000" + }, + "50378af7ef54043f892ab7ce97d647793511b108": { + "balance": "19700000000000000000" + }, + "e7c6b5fc05fc748e5b4381726449a1c0ad0fb0f1": { + "balance": "2000000000000000000000" + }, + "5317ecb023052ca7f5652be2fa854cfe4563df4d": { + "balance": "499986000000000000000" + }, + "c94f7c35c027d47df8ef4f9df85a9248a17dd23b": { + "balance": "29944000000000000000" + }, + "6a63fc89abc7f36e282d80787b7b04afd6553e71": { + "balance": "160000000000000000000" + }, + "5fd3d6777ec2620ae83a05528ed425072d3ca8fd": { + "balance": "2000000000000000000000" + }, + "29adcf83b6b20ac6a434abb1993cbd05c60ea2e4": { + "balance": "10000000000000000000000" + }, + "8c6f9f4e5b7ae276bf58497bd7bf2a7d25245f64": { + "balance": "2730000000000000000000" + }, + "d94a57882a52739bbe2a0647c80c24f58a2b4f1c": { + "balance": "1341230000000000000000" + }, + "7286e89cd9de8f7a8a00c86ffdb53992dd9251d1": { + "balance": "1940000000000000000000" + }, + "5773b6026721a1dd04b7828cd62b591bfb34534c": { + "balance": "27000000000000000000000" + }, + "11fefb5dc1a4598aa712640c517775dfa1d91f8c": { + "balance": "10000000000000000000000" + }, + "c6e324beeb5b36765ecd464260f7f26006c5c62e": { + "balance": "2000000000000000000000" + }, + "118fbd753b9792395aef7a4d78d263cdcaabd4f7": { + "balance": "999800000000000000000" + }, + "f8298591523e50b103f0b701d623cbf0f74556f6": { + "balance": "200000000000000000000" + }, + "ab0ced762e1661fae1a92afb1408889413794825": { + "balance": "1910000000000000000000" + }, + "fa67b67b4f37a0150915110ede073b05b853bda2": { + "balance": "647490000000000000000" + }, + "ca122cf0f2948896b74843f49afed0ba1618eed7": { + "balance": "560000000000000000000" + }, + "186b95f8e5effddcc94f1a315bf0295d3b1ea588": { + "balance": "1999944000000000000000" + }, + "2915624bcb679137b8dae9ab57d11b4905eaee4b": { + "balance": "20000000000000000000" + }, + "0c6845bf41d5ee273c3ee6b5b0d69f6fd5eabbf7": { + "balance": "3000026000000000000000" + }, + "cb7479109b43b26657f4465f4d18c6f974be5f42": { + "balance": "1820000000000000000000" + }, + "8dd6a9bae57f518549ada677466fea8ab04fd9b4": { + "balance": "4000000000000000000000" + }, + "34958a46d30e30b273ecc6e5d358a212e5307e8c": { + "balance": "2000000000000000000000" + }, + "2003717907a72560f4307f1beecc5436f43d21e7": { + "balance": "500000000000000000000" + }, + "55ab99b0e0e55d7bb874b7cfe834de631c97ec23": { + "balance": "1031400000000000000000" + }, + "79b48d2d6137c3854d611c01ea42427a0f597bb7": { + "balance": "191000000000000000000" + }, + "d609ec0be70d0ad26f6e67c9d4762b52ee51122c": { + "balance": "1000000000000000000000" + }, + "e8c3f045bb7d38c9d2f395b0ba8492b253230901": { + "balance": "9000000000000000000000" + }, + "aaca60d9d700e78596bbbbb1f1e2f70f4627f9d8": { + "balance": "999996000000000000000" + }, + "89d75b8e0831e46f80bc174188184e006fde0eae": { + "balance": "1000000000000000000000" + }, + "b3667894b7863c068ad344873fcff4b5671e0689": { + "balance": "20000000000000000000000" + }, + "bc1609d685b76b48ec909aa099219022f89b2ccd": { + "balance": "1182000000000000000000" + }, + "88ee7f0efc8f778c6b687ec32be9e7d6f020b674": { + "balance": "2000000000000000000000" + }, + "470ac5d1f3efe28f3802af925b571e63868b397d": { + "balance": "2000000000000000000000" + }, + "abf8ffe0708a99b528cc1ed4e9ce4b0d0630be8c": { + "balance": "2263600000000000000000" + }, + "8cee38d6595788a56e3fb94634b3ffe1fbdb26d6": { + "balance": "20000000000000000000000" + }, + "19798cbda715ea9a9b9d6aab942c55121e98bf91": { + "balance": "1200000000000000000000" + }, + "e25a167b031e84616d0f013f31bda95dcc6350b9": { + "balance": "10560000000000000000000" + }, + "6196c3d3c0908d254366b7bca55745222d9d4db1": { + "balance": "4000000000000000000000" + }, + "e8e9850586e94f5299ab494bb821a5f40c00bd04": { + "balance": "3820000000000000000000" + }, + "1059cbc63e36c43e88f30008aca7ce058eeaa096": { + "balance": "100000000000000000000000" + }, + "c4f2913b265c430fa1ab8adf26c333fc1d9b66f2": { + "balance": "20000000000000000000" + }, + "26e9e2ad729702626417ef25de0dc800f7a779b3": { + "balance": "1000000000000000000000" + }, + "0dfbd4817050d91d9d625c02053cf61a3ee28572": { + "balance": "340000000000000000000" + }, + "709fe9d2c1f1ce42207c9585044a60899f35942f": { + "balance": "2000000000000000000000" + }, + "7ad82caea1a8b4ed05319b9c9870173c814e06ee": { + "balance": "616000000000000000000" + }, + "2a595f16eee4cb0c17d9a2d939b3c10f6c677243": { + "balance": "1100000000000000000000" + }, + "a8f89dd5cc6e64d7b1eeace00702022cd7d2f03d": { + "balance": "700000000000000000000" + }, + "c0a6cbad77692a3d88d141ef769a99bb9e3c9951": { + "balance": "100000000000000000000" + }, + "868c23be873466d4c74c220a19b245d1787e807f": { + "balance": "1366481000000000000000" + }, + "2905b192e83ce659aa355b9d0c204e3e95f9bb9a": { + "balance": "2160817000000000000000" + }, + "50b9fef0a1329b02d16506255f5a2db71ec92d1f": { + "balance": "1325464000000000000000" + }, + "fc10b7a67b3268d5331bfb6a14def5ea4a162ca3": { + "balance": "200000000000000000000" + }, + "85eb256b51c819d60ea61a82d12c9358d59c1cae": { + "balance": "460000000000000000000" + }, + "75de7e9352e90b13a59a5878ffecc7831cac4d82": { + "balance": "2740000000000000000000" + }, + "d32b2c79c36478c5431901f6d700b04dbe9b8810": { + "balance": "396000000000000000000" + }, + "2d0326b23f0409c0c0e9236863a133075a94ba18": { + "balance": "210380000000000000000" + }, + "d2e21ed56868fab28e0947927adaf29f23ebad6c": { + "balance": "1994000000000000000000" + }, + "2ad6c9d10c261819a1a0ca2c48d8c7b2a71728df": { + "balance": "1000000000000000000000" + }, + "7d445267c59ab8d2a2d9e709990e09682580c49f": { + "balance": "1000000000000000000000" + }, + "b6047cdf932db3e4045f4976122341537ed5961e": { + "balance": "20000000000000000000" + }, + "2b3cf97311ff30f460945a9d8099f4a88e26d456": { + "balance": "2000000000000000000000" + }, + "7f4f593b618c330ba2c3d5f41eceeb92e27e426c": { + "balance": "2775000000000000000000" + }, + "72a2fc8675feb972fa41b50dffdbbae7fa2adfb7": { + "balance": "2853840000000000000000" + }, + "076561a856455d7ef86e63f87c73dbb628a55f45": { + "balance": "900000000000000000000" + }, + "03d1724fd00e54aabcd2de2a91e8462b1049dd3a": { + "balance": "2640000000000000000000" + }, + "7ea0f96ee0a573a330b56897761f3d4c0130a8e3": { + "balance": "1337000000000000000000" + }, + "fe65c4188d7922576909642044fdc52395560165": { + "balance": "4000000000000000000000" + }, + "57883010b4ac857fedac03eab2551723a8447ffb": { + "balance": "1000000000000000000000" + }, + "0729a8a4a5ba23f579d0025b1ad0f8a0d35cdfd2": { + "balance": "9700000000000000000000" + }, + "e75c1fb177089f3e58b1067935a6596ef1737fb5": { + "balance": "99910000000000000000" + }, + "e0e978753d982f7f9d1d238a18bd4889aefe451b": { + "balance": "9700000000000000000000" + }, + "5620f46d1451c2353d6243a5d4b427130be2d407": { + "balance": "60000000000000000000" + }, + "f3d688f06bbdbf50f9932c4145cbe48ecdf68904": { + "balance": "20000000000000000000" + }, + "3aa948ea02397755effb2f9dc9392df1058f7e33": { + "balance": "850000000000000000000" + }, + "20d1417f99c569e3beb095856530fe12d0fceaaa": { + "balance": "1182175000000000000000" + }, + "ac77bdf00fd5985b5db12bbef800380abc2a0677": { + "balance": "1000000000000000000000" + }, + "267a7e6e82e1b91d51deddb644f0e96dbb1f7f7e": { + "balance": "20000000000000000000" + }, + "4bbcbf38b3c90163a84b1cd2a93b58b2a3348d87": { + "balance": "8000000000000000000000" + }, + "4c6b93a3bec16349540cbfcae96c9621d6645010": { + "balance": "2000000000000000000000" + }, + "c9308879056dfe138ef8208f79a915c6bc7e70a8": { + "balance": "10000000000000000000000" + }, + "c48b693cacefdbd6cb5d7895a42e3196327e261c": { + "balance": "1000000000000000000000" + }, + "a0951970dfd0832fb83bda12c23545e79041756c": { + "balance": "600000000000000000000" + }, + "7cdf74213945953db39ad0e8a9781add792e4d1d": { + "balance": "2000000000000000000000" + }, + "75621865b6591365606ed378308c2d1def4f222c": { + "balance": "3100000000000000000000" + }, + "67d6a8aa1bf8d6eaf7384e993dfdf10f0af68a61": { + "balance": "198067000000000000000" + }, + "8f0af37566d152802f1ae8f928b25af9b139b448": { + "balance": "200000000000000000000" + }, + "2c6afcd4037c1ed14fa74ff6758e0945a185a8e8": { + "balance": "17600000000000000000" + }, + "c1b2aa8cb2bf62cdc13a47ecc4657facaa995f98": { + "balance": "1000129000000000000000" + }, + "9e8144e08e89647811fe6b72d445d6a5f80ad244": { + "balance": "10000000000000000000000" + }, + "e04ff5e5a7e2af995d8857ce0290b53a2b0eda5d": { + "balance": "1000000000000000000000" + }, + "03dedfcd0b3c2e17c705da248790ef98a6bd5751": { + "balance": "1337000000000000000000" + }, + "698a8a6f01f9ab682f637c7969be885f6c5302bf": { + "balance": "19400000000000000000" + }, + "d82c6fedbdac98af2eed10b00f32b00056ca5a6d": { + "balance": "200000000000000000000" + }, + "2697b339813b0c2d964b2471eb1c606f4ecb9616": { + "balance": "1154000000000000000000" + }, + "987c9bcd6e3f3990a52be3eda4710c27518f4f72": { + "balance": "400000000000000000000" + }, + "c5d48ca2db2f85d8c555cb0e9cfe826936783f9e": { + "balance": "200000000000000000000" + }, + "da214c023e2326ff696c00393168ce46ffac39ec": { + "balance": "1000000000000000000000" + }, + "86570ab259c9b1c32c9729202f77f590c07dd612": { + "balance": "200000000000000000000" + }, + "a646a95c6d6f59f104c6541d7760757ab392b08c": { + "balance": "4200000000000000000000" + }, + "1933e334c40f3acbad0c0b851158206924beca3a": { + "balance": "7551541000000000000000" + }, + "3552a496eba67f12be6eedab360cd13661dc7480": { + "balance": "300000000000000000000" + }, + "2a9c96c19151ffcbe29a4616d0c52b3933b4659f": { + "balance": "69263000000000000000" + }, + "3b7b8e27de33d3ce7961b98d19a52fe79f6c25be": { + "balance": "100000000000000000000000" + }, + "a1911405cf6e999ed011f0ddcd2a4ff7c28f2526": { + "balance": "40000000000000000000" + }, + "0cae108e6db99b9e637876b064c6303eda8a65c8": { + "balance": "3000000000000000000000" + }, + "3883becc08b9be68ad3b0836aac3b620dc0017ef": { + "balance": "2000000000000000000000" + }, + "d0abcc70c0420e0e172f97d43b87d5e80c336ea9": { + "balance": "10000000000000000000000" + }, + "cbf16a0fe2745258cd52db2bf21954c975fc6a15": { + "balance": "300000000000000000000" + }, + "1b23cb8663554871fbbe0d9e60397efb6faedc3e": { + "balance": "200000000000000000000" + }, + "fbede32c349f3300ef4cd33b4de7dc18e443d326": { + "balance": "3160000000000000000000" + }, + "5e806e845730f8073e6cc9018ee90f5c05f909a3": { + "balance": "9480000000000000000000" + }, + "425c338a1325e3a1578efa299e57d986eb474f81": { + "balance": "2000000000000000000000" + }, + "8bf297f8f453523ed66a1acb7676856337b93bf0": { + "balance": "4000000000000000000000" + }, + "38e8a31af2d265e31a9fff2d8f46286d1245a467": { + "balance": "20000000000000000000" + }, + "7edafba8984baf631a820b6b92bbc2c53655f6bd": { + "balance": "2000000000000000000000" + }, + "aa0200f1d17e9c54da0647bb96395d57a78538d8": { + "balance": "1056000000000000000000" + }, + "433eb94a339086ed12d9bde9cd1d458603c97dd6": { + "balance": "100000000000000000000000" + }, + "cd7e47909464d871b9a6dc76a8e9195db3485e7a": { + "balance": "9850000000000000000000" + }, + "5975d78d974ee5bb9e4d4ca2ae77c84b9c3b4b82": { + "balance": "1370000000000000000000" + }, + "cea2896623f4910287a2bdc5be83aea3f2e6de08": { + "balance": "9359000000000000000000" + }, + "cb4ad0c723da46ab56d526da0c1d25c73daff10a": { + "balance": "510000000000000000000" + }, + "e2cf360aa2329eb79d2bf7ca04a27a17c532e4d8": { + "balance": "102000000000000000000" + }, + "ea60549ec7553f511d2149f2d4666cbd9243d93c": { + "balance": "2000000000000000000000" + }, + "cbb7be17953f2ccc93e1bc99805bf45511434e4c": { + "balance": "50440000000000000000000" + }, + "3549bd40bbbc2b30095cac8be2c07a0588e0aed6": { + "balance": "20000000000000000000" + }, + "6510df42a599bcb0a519cca961b488759a6f6777": { + "balance": "2000000000000000000000" + }, + "ed12a1ba1fb8adfcb20dfa19582e525aa3b74524": { + "balance": "6685000000000000000000" + }, + "135eb8c0e9e101deedec11f2ecdb66ae1aae8867": { + "balance": "20000000000000000000000" + }, + "ee906d7d5f1748258174be4cbc38930302ab7b42": { + "balance": "200000000000000000000" + }, + "253f1e742a2cec86b0d7b306e5eacb6ccb2f8554": { + "balance": "20040000000000000000000" + }, + "ecd1a62802351a41568d23033004acc6c005a5d3": { + "balance": "50000000000000000000" + }, + "558c54649a8a6e94722bd6d21d14714f71780534": { + "balance": "2000000000000000000000" + }, + "ca657ec06fe5bc09cf23e52af7f80cc3689e6ede": { + "balance": "900000000000000000000" + }, + "74bf7a5ab59293149b5c60cf364263e5ebf1aa0d": { + "balance": "115800000000000000000" + }, + "7a6d781c77c4ba1fcadf687341c1e31799e93d27": { + "balance": "274000000000000000000" + }, + "77028e409cc43a3bd33d21a9fc53ec606e94910e": { + "balance": "3880000000000000000000" + }, + "4781a10a4df5eebc82f4cfe107ba1d8a7640bd66": { + "balance": "1790000000000000000000" + }, + "78e08bc533413c26e291b3143ffa7cc9afb97b78": { + "balance": "200000000000000000000" + }, + "03ef6ad20ff7bd4f002bac58d47544cf879ae728": { + "balance": "6895000000000000000000" + }, + "0e3696cf1f4217b163d1bc12a5ea730f1c32a14a": { + "balance": "4000000000000000000000" + }, + "825135b1a7fc1605614c8aa4d0ac6dbad08f480e": { + "balance": "1430000000000000000000" + }, + "286b186d61ea1fd78d9930fe12b06537b05c3d51": { + "balance": "1000000000000000000000" + }, + "8d6657f59711b1f803c6ebef682f915b62f92dc9": { + "balance": "2000000000000000000000" + }, + "da8bbee182e455d2098acb338a6d45b4b17ed8b6": { + "balance": "2000000000000000000000" + }, + "3f2da093bb16eb064f8bfa9e30b929d15f8e1c4c": { + "balance": "2000000000000000000000" + }, + "f5d9cf00d658dd45517a48a9d3f5f633541a533d": { + "balance": "116400000000000000000" + }, + "c5f64babb7033142f20e46d7aa6201ed86f67103": { + "balance": "2000000000000000000000" + }, + "a2e2b5941e0c01944bfe1d5fb4e8a34b922ccfb1": { + "balance": "200000000000000000000" + }, + "6114b0eae5576903f80bfb98842d24ed92237f1e": { + "balance": "100000000000000000000" + }, + "38df0c4abe7ded5fe068eadf154ac691774324a4": { + "balance": "1790000000000000000000" + }, + "1c2010bd662df417f2a271879afb13ef4c88a3ae": { + "balance": "4000000000000000000000" + }, + "918967918cd897dd0005e36dc6c883ef438fc8c7": { + "balance": "140000000000000000000" + }, + "a522de7eb6ae1250522a513133a93bd42849475c": { + "balance": "20000000000000000000000" + }, + "7de442c82386154d2e993cbd1280bb7ca6b12ada": { + "balance": "4002000000000000000000" + }, + "66424bd8785b8cb461102a900283c35dfa07ef6a": { + "balance": "40221000000000000000" + }, + "7bbbec5e70bdead8bb32b42805988e9648c0aa97": { + "balance": "1000076000000000000000" + }, + "fec06fe27b44c784b2396ec92f7b923ad17e9077": { + "balance": "2000000000000000000000" + }, + "95d550427b5a514c751d73a0f6d29fb65d22ed10": { + "balance": "300000000000000000000" + }, + "8dde60eb08a099d7daa356daaab2470d7b025a6b": { + "balance": "197000000000000000000" + }, + "81bccbff8f44347eb7fca95b27ce7c952492aaad": { + "balance": "152240000000000000000" + }, + "3995e096b08a5a726800fcd17d9c64c64e088d2b": { + "balance": "200000000000000000000" + }, + "4ee13c0d41200b46d19dee5c4bcec71d82bb8e38": { + "balance": "7893915000000000000000" + }, + "c41461a3cfbd32c9865555a4813137c076312360": { + "balance": "999999000000000000000" + }, + "3300fb149aded65bcba6c04e9cd6b7a03b893bb1": { + "balance": "18200000000000000000" + }, + "29f9286c0e738d1721a691c6b95ab3d9a797ede8": { + "balance": "200000000000000000000000" + }, + "34c8e5f1330fcb4b14ca75cb2580a4b93d204e36": { + "balance": "2000000000000000000000" + }, + "ec5df227bfa85d7ad76b426e1cee963bc7f519dd": { + "balance": "1000000000000000000000" + }, + "797510e386f56393ced8f477378a444c484f7dad": { + "balance": "1000000000000000000000" + }, + "0191eb547e7bf6976b9b1b577546761de65622e2": { + "balance": "1999980000000000000000" + }, + "615a6f36777f40d6617eb5819896186983fd3731": { + "balance": "5910000000000000000000" + }, + "17580b766f7453525ca4c6a88b01b50570ea088c": { + "balance": "100000000000000000000" + }, + "945d96ea573e8df7262bbfa572229b4b16016b0f": { + "balance": "209300000000000000000" + }, + "2de0964400c282bdd78a919c6bf77c6b5f796179": { + "balance": "200000000000000000000" + }, + "304ec69a74545721d7316aef4dcfb41ac59ee2f0": { + "balance": "200000000000000000000" + }, + "be2b326e78ed10e550fee8efa8f8070396522f5a": { + "balance": "39400000000000000000000" + }, + "1a0841b92a7f7075569dc4627e6b76cab05ade91": { + "balance": "1520000000000000000000" + }, + "5fa61f152de6123516c751242979285f796ac791": { + "balance": "204000000000000000000" + }, + "68c8791dc342c373769ea61fb7b510f251d32088": { + "balance": "1000000000000000000000" + }, + "4167cd48e733418e8f99ffd134121c4a4ab278c4": { + "balance": "3640000000000000000000" + }, + "598aaabae9ed833d7bc222e91fcaa0647b77580b": { + "balance": "1800000000000000000000" + }, + "979f30158b574b999aab348107b9eed85b1ff8c1": { + "balance": "970000000000000000000" + }, + "3ad06149b21c55ff867cc3fb9740d2bcc7101231": { + "balance": "197000000000000000000000" + }, + "7133843a78d939c69d4486e10ebc7b602a349ff7": { + "balance": "329000000000000000000" + }, + "8bdfda6c215720eda2136f91052321af4e936c1f": { + "balance": "1000008000000000000000" + }, + "3e1c53300e4c168912163c7e99b95da268ad280a": { + "balance": "1003200000000000000000" + }, + "e07ebbc7f4da416e42c8d4f842aba16233c12580": { + "balance": "2000000000000000000000" + }, + "bac8922c4acc7d2cb6fd59a14eb45cf3e702214b": { + "balance": "800000000000000000000" + }, + "bb6c284aac8a69b75cddb00f28e145583b56bece": { + "balance": "2000000000000000000000" + }, + "0372ee5508bf8163ed284e5eef94ce4d7367e522": { + "balance": "100000000000000000000" + }, + "17125b59ac51cee029e4bd78d7f5947d1ea49bb2": { + "balance": "22000000000000000000000" + }, + "c88ca1e6e5f4d558d13780f488f10d4ad3130d34": { + "balance": "1550000000000000000000" + }, + "a825fd5abb7926a67cf36ba246a24bd27be6f6ed": { + "balance": "17600000000000000000" + }, + "04241b41ecbd0bfdf1295e9d4fa59ea09e6c6186": { + "balance": "1870000000000000000000" + }, + "6de4d15219182faf3aa2c5d4d2595ff23091a727": { + "balance": "1580000000000000000000" + }, + "b203d29e6c56b92699c4b92d1f6f84648dc4cfbc": { + "balance": "400000000000000000000" + }, + "80b42de170dbd723f454e88f7716452d92985092": { + "balance": "300202000000000000000" + }, + "0a5b79d8f23b6483dbe2bdaa62b1064cc76366ae": { + "balance": "1969803000000000000000" + }, + "32034e8581d9484e8af42a28df190132ec29c466": { + "balance": "3460000000000000000000" + }, + "7ee604c7a9dc2909ce321de6b9b24f5767577555": { + "balance": "5533575000000000000000" + }, + "a387ce4e961a7847f560075c64e1596b5641d21c": { + "balance": "668500000000000000000" + }, + "fcc9d4a4262e7a027ab7519110d802c495ceea39": { + "balance": "6370000000000000000000" + }, + "ff8a2ca5a81333f19998255f203256e1a819c0aa": { + "balance": "224000000000000000000" + }, + "f9811fa19dadbf029f8bfe569adb18228c80481a": { + "balance": "200000000000000000000" + }, + "0d1f2a57713ebc6e94de29846e8844d376665763": { + "balance": "5000000000000000000000" + }, + "eab0bd148309186cf8cbd13b7232d8095acb833a": { + "balance": "10691800000000000000000" + }, + "36928b55bc861509d51c8cf1d546bfec6e3e90af": { + "balance": "1970000000000000000000" + }, + "30480164bcd84974ebc0d90c9b9afab626cd1c73": { + "balance": "800000000000000000000" + }, + "36339f84a5c2b44ce53dfdb6d4f97df78212a7df": { + "balance": "321600000000000000000" + }, + "cfeacaaed57285e0ac7268ce6a4e35ecfdb242d7": { + "balance": "1086400000000000000000" + }, + "572dd8cd3fe399d1d0ec281231b7cefc20b9e4bb": { + "balance": "10400000000000000000000" + }, + "5dded049a6e1f329dc4b971e722c9c1f2ade83f0": { + "balance": "1000000000000000000000" + }, + "9756e176c9ef693ee1eec6b9f8b151d313beb099": { + "balance": "1200000000000000000000" + }, + "01e6415d587b065490f1ed7f21d6e0f386ee6747": { + "balance": "2000000000000000000000" + }, + "b4413576869c08f9512ad311fe925988a52d3414": { + "balance": "10000000000000000000000" + }, + "da9f55460946d7bfb570ddec757ca5773b58429a": { + "balance": "507600000000000000000" + }, + "7180b83ee5574317f21c8072b191d895d46153c3": { + "balance": "460000000000000000000" + }, + "0aca9a5626913b08cfc9a66d40508dce52b60f87": { + "balance": "1910000000000000000000" + }, + "5cd0e475b54421bdfc0c12ea8e082bd7a5af0a6a": { + "balance": "59000000000000000000" + }, + "7edb02c61a227287611ad950696369cc4e647a68": { + "balance": "274000000000000000000" + }, + "b2676841ee9f2d31c172e82303b0fe9bbf9f1e09": { + "balance": "200000000000000000000" + }, + "a2222259dd9c3e3ded127084f808e92a1887302c": { + "balance": "162000000000000000000" + }, + "4b3a7cc3a7d7b00ed5282221a60259f25bf6538a": { + "balance": "1000000000000000000000" + }, + "e33ff987541dde5cdee0a8a96dcc3f33c3f24cc2": { + "balance": "200000000000000000000000" + }, + "1e1a4828119be309bd88236e4d482b504dc55711": { + "balance": "2955000000000000000000" + }, + "9b1811c3051f46e664ae4bc9c824d18592c4574a": { + "balance": "199955000000000000000" + }, + "59fe00696dbd87b7976b29d1156c8842a2e17914": { + "balance": "2000000000000000000000" + }, + "48010ef3b8e95e3f308f30a8cb7f4eb4bf60d965": { + "balance": "2000000000000000000000" + }, + "c90300cb1d4077e6a6d7e169a460468cf4a492d7": { + "balance": "2000000000000000000000" + }, + "6dedf62e743f4d2c2a4b87a787f5424a7aeb393c": { + "balance": "180000000000000000000" + }, + "fb744b951d094b310262c8f986c860df9ab1de65": { + "balance": "52009000000000000000" + }, + "193ac65183651800e23580f8f0ead3bb597eb8a4": { + "balance": "50020000000000000000" + }, + "bf05ff5ecf0df2df887759fb8274d93238ac267d": { + "balance": "800000000000000000000" + }, + "6c0e712f405c59725fe829e9774bf4df7f4dd965": { + "balance": "57413800000000000000000" + }, + "2744ff67464121e35afc2922177164fa2fcb0267": { + "balance": "100000000000000000000" + }, + "d09cb2e6082d693a13e8d2f68dd1dd8461f55840": { + "balance": "1000000000000000000000" + }, + "bc171e53d17ac9b61241ae436deec7af452e7496": { + "balance": "5348000000000000000000" + }, + "71fa22cc6d33206b7d701a163a0dab31ae4d31d6": { + "balance": "1610000000000000000000" + }, + "4da8030769844bc34186b85cd4c7348849ff49e9": { + "balance": "10000000000000000000000" + }, + "c8616b4ec09128cdff39d6e4b9ac86eec471d5f2": { + "balance": "19400000000000000000" + }, + "407295ebd94b48269c2d569c9b9af9aa05e83e5e": { + "balance": "10000000000000000000000" + }, + "d45d5daa138dd1d374c71b9019916811f4b20a4e": { + "balance": "576000000000000000000" + }, + "42c6edc515d35557808d13cd44dcc4400b2504e4": { + "balance": "197876000000000000000" + }, + "0bc95cb32dbb574c832fa8174a81356d38bc92ac": { + "balance": "2000000000000000000000" + }, + "5a6071bcebfcba4ab57f4db96fc7a68bece2ba5b": { + "balance": "2000000000000000000000" + }, + "54c93e03a9b2e8e4c3672835a9ee76f9615bc14e": { + "balance": "19400000000000000000" + }, + "3c03bbc023e1e93fa3a3a6e428cf0cd8f95e1ec6": { + "balance": "1520000000000000000000" + }, + "ba1531fb9e791896bcf3a80558a359f6e7c144bd": { + "balance": "3940000000000000000000" + }, + "aa56a65dc4abb72f11bae32b6fbb07444791d5c9": { + "balance": "748600000000000000000" + }, + "e437acbe0f6227b0e36f36e4bcf7cf613335fb68": { + "balance": "200000000000000000000" + }, + "39d4a931402c0c79c457186f24df8729cf957031": { + "balance": "4000000000000000000000" + }, + "e22b20c77894463baf774cc256d5bddbbf7ddd09": { + "balance": "1000000000000000000000" + }, + "70a4067d448cc25dc8e70e651cea7cf84e92109e": { + "balance": "176000000000000000000" + }, + "aa3925dc220bb4ae2177b2883078b6dc346ca1b2": { + "balance": "8000000000000000000000" + }, + "ad57aa9d00d10c439b35efcc0becac2e3955c313": { + "balance": "200000000000000000000" + }, + "e93d47a8ca885d540c4e526f25d5c6f2c108c4b8": { + "balance": "112640000000000000000000" + }, + "232ce782506225fd9860a2edc14a7a3047736da2": { + "balance": "20000000000000000000" + }, + "49a645e0667dfd7b32d075cc2467dd8c680907c4": { + "balance": "129560000000000000000" + }, + "cf2e734042a355d05ffb2e3915b16811f45a695e": { + "balance": "2000000000000000000000" + }, + "39b1c471ae94e12164452e811fbbe2b3cd7275ac": { + "balance": "2000000000000000000000" + }, + "ffad3dd74e2c1f796ac640de56dc99b4c792a402": { + "balance": "5000000000000000000000" + }, + "a69d7cd17d4842fe03f62a90b2fbf8f6af7bb380": { + "balance": "100000000000000000000" + }, + "2001bef77b66f51e1599b02fb110194a0099b78d": { + "balance": "2000000000000000000000" + }, + "95e7616424cd0961a71727247437f0069272280e": { + "balance": "400000000000000000000" + }, + "c04f4bd4049f044685b883b62959ae631d667e35": { + "balance": "5820000000000000000000" + }, + "ede0147ec032c3618310c1ff25690bf172193dac": { + "balance": "2000000000000000000000" + }, + "66719c0682b2ac7f9e27abebec7edf8decf0ae0d": { + "balance": "20000000000000000000" + }, + "45272b8f62e9f9fa8ce04420e1aea3eba9686eac": { + "balance": "4000000000000000000000" + }, + "d1da0c8fb7c210e0f2ec618f85bdae7d3e734b1c": { + "balance": "1970000000000000000000" + }, + "e9133e7d31845d5f2b66a2618792e869311acf66": { + "balance": "24050000000000000000000" + }, + "ebb62cf8e22c884b1b28c6fa88fbbc17938aa787": { + "balance": "798000000000000000000" + }, + "6205c2d5647470848a3840f3887e9b015d34755c": { + "balance": "1800000000000000000000" + }, + "76ca22bcb8799e5327c4aa2a7d0949a1fcce5f29": { + "balance": "1524180000000000000000" + }, + "6b925dd5d8ed6132ab6d0860b82c44e1a51f1fee": { + "balance": "1480000000000000000000" + }, + "797bb7f157d9feaa17f76da4f704b74dc1038341": { + "balance": "3340000000000000000000" + }, + "ae8954f8d6166de507cf61297d0fc7ca6b9e7128": { + "balance": "300000000000000000000" + }, + "75c1ad23d23f24b384d0c3149177e86697610d21": { + "balance": "6426082000000000000000" + }, + "805d846fb0bc02a7337226d685be9ee773b9198a": { + "balance": "19999800000000000000000" + }, + "c3cb6b36af443f2c6e258b4a39553a818747811f": { + "balance": "1610000000000000000000" + }, + "cea43f7075816b60bbfce68b993af0881270f6c4": { + "balance": "2000000000000000000000" + }, + "e0388aeddd3fe2ad56f85748e80e710a34b7c92e": { + "balance": "500000000000000000000" + }, + "e131f87efc5ef07e43f0f2f4a747b551d750d9e6": { + "balance": "19999000000000000000000" + }, + "c2b2cbe65bc6c2ee7a3c75b2e47c189c062e8d8b": { + "balance": "20000000000000000000000" + }, + "bd8765f41299c7f479923c4fd18f126d7229047d": { + "balance": "4000000000000000000000" + }, + "c83ba6dd9549be1d3287a5a654d106c34c6b5da2": { + "balance": "7000000000000000000000" + }, + "f870995fe1e522321d754337a45c0c9d7b38951c": { + "balance": "20000000000000000000" + }, + "0d8ed7d0d15638330ed7e4eaccab8a458d75737e": { + "balance": "2000000000000000000000" + }, + "36c510bf8d6e569bf2f37d47265dbcb502ff2bce": { + "balance": "30000000000000000000000" + }, + "0eccf617844fd61fba62cb0e445b7ac68bcc1fbe": { + "balance": "387260000000000000000" + }, + "ae10e27a014f0d306baf266d4897c89aeee2e974": { + "balance": "20000000000000000000000" + }, + "1827039f09570294088fddf047165c33e696a492": { + "balance": "9550000000000000000000" + }, + "23378f42926d0184b793b0c827a6dd3e3d334fcd": { + "balance": "56000000000000000000" + }, + "467124ae7f452f26b3d574f6088894fa5d1cfb3b": { + "balance": "2700000000000000000000" + }, + "aae61e43cb0d0c96b30699f77e00d711d0a3979b": { + "balance": "1000000000000000000000" + }, + "15c7edb8118ee27b342285eb5926b47a855bc7a5": { + "balance": "20000000000000000000" + }, + "0d5d98565c647ca5f177a2adb9d3022fac287f21": { + "balance": "200000000000000000000" + }, + "7222fec7711781d26eaa4e8485f7aa3fac442483": { + "balance": "456000000000000000000" + }, + "dc44275b1715baea1b0345735a29ac42c9f51b4f": { + "balance": "1164000000000000000000" + }, + "04d82af9e01a936d97f8f85940b970f9d4db9936": { + "balance": "200000000000000000000" + }, + "45533390e340fe0de3b3cf5fb9fc8ea552e29e62": { + "balance": "1460000000000000000000" + }, + "1284f0cee9d2ff2989b65574d06ffd9ab0f7b805": { + "balance": "400000000000000000000" + }, + "ed9ebccba42f9815e78233266dd6e835b6afc31b": { + "balance": "6000000000000000000000" + }, + "e4324912d64ea3aef76b3c2ff9df82c7e13ae991": { + "balance": "2000000000000000000000" + }, + "94c742fd7a8b7906b3bfe4f8904fc0be5c768033": { + "balance": "20000000000000000000000" + }, + "62fb8bd1f0e66b90533e071e6cbe6111fef0bc63": { + "balance": "17600000000000000000000" + }, + "2c83aeb02fcf067d65a47082fd977833ab1cec91": { + "balance": "150400000000000000000" + }, + "06cbfa08cdd4fba737bac407be8224f4eef35828": { + "balance": "593459000000000000000" + }, + "67ee406ea4a7ae6a3a381eb4edd2f09f174b4928": { + "balance": "1036000000000000000000" + }, + "83c23d8a502124ee150f08d71dc6727410a0f901": { + "balance": "33999600000000000000000" + }, + "f7c00cdb1f020310d5acab7b496aaa44b779085e": { + "balance": "1670000000000000000000" + }, + "d096565b7c7407d06536580355fdd6d239144aa1": { + "balance": "250000000000000000000" + }, + "f8d52dcc5f96cc28007b3ecbb409f7e22a646caa": { + "balance": "149200000000000000000" + }, + "0c222c7c41c9b048efcce0a232434362e12d673b": { + "balance": "10007600000000000000000" + }, + "503bdbd8bc421c32a443032deb2e3e4cd5ba8b4e": { + "balance": "2000000000000000000000" + }, + "77da5e6c72fb36bce1d9798f7bcdf1d18f459c2e": { + "balance": "22380000000000000000" + }, + "e62f98650712eb158753d82972b8e99ca3f61877": { + "balance": "2000000000000000000000" + }, + "87a7c508ef71582dd9a54372f89cb01f252fb180": { + "balance": "200000000000000000000" + }, + "f61283b4bd8504058ca360e993999b62cbc8cd67": { + "balance": "255000000000000000000" + }, + "9ccddcb2cfc2b25b08729a0a98d9e6f0202ea2c1": { + "balance": "100000000000000000000" + }, + "d460a4b908dd2b056759b488850b66a838fc77a8": { + "balance": "1970000000000000000000" + }, + "5431b1d18751b98fc9e2888ac7759f1535a2db47": { + "balance": "2000000000000000000000" + }, + "da2a14f9724015d79014ed8e5909681d596148f1": { + "balance": "48499000000000000000" + }, + "c989434f825aaf9c552f685eba7c11db4a5fc73a": { + "balance": "501000000000000000000" + }, + "2b701d16c0d3cc1e4cd85445e6ad02eea4ac012d": { + "balance": "600000000000000000000" + }, + "78b978a9d7e91ee529ea4fc4b76feaf8762f698c": { + "balance": "32000000000000000000000" + }, + "c89cf504b9f3f835181fd8424f5ccbc8e1bddf7d": { + "balance": "10000000000000000000000" + }, + "e94941b6036019b4016a30c1037d5a6903babaad": { + "balance": "780000000000000000000" + }, + "95d98d0c1069908f067a52acac2b8b534da37afd": { + "balance": "2054053000000000000000" + }, + "8284923b62e68bbf7c2b9f3414d13ef6c812a904": { + "balance": "3880000000000000000000" + }, + "3e5a39fdda70df1126ab0dc49a7378311a537a1f": { + "balance": "2400000000000000000000" + }, + "a2ace4c993bb1e5383f8ac74e179066e814f0591": { + "balance": "100000000000000000000" + }, + "0609d83a6ce1ffc9b690f3e9a81e983e8bdc4d9d": { + "balance": "70000000000000000000000" + }, + "d119417c46732cf34d1a1afb79c3e7e2cd8eece4": { + "balance": "2000000000000000000000" + }, + "fdb33944f2360615e5be239577c8a19ba52d9887": { + "balance": "601650000000000000000" + }, + "dd95dbe30f1f1877c5dd7684aeef302ab6885192": { + "balance": "8372000000000000000000" + }, + "413f4b02669ccff6806bc826fcb7deca3b0ea9bc": { + "balance": "20000000000000000000" + }, + "5800cd8130839e94495d2d8415a8ea2c90e0c5cb": { + "balance": "200000000000000000000" + }, + "65053191319e067a25e6361d47f37f6318f83419": { + "balance": "394000000000000000000" + }, + "9bc573bcda23b8b26f9073d90c230e8e71e0270b": { + "balance": "999544000000000000000" + }, + "97f7760657c1e202759086963eb4211c5f8139b9": { + "balance": "49770000000000000000000" + }, + "126897a311a14ad43b78e0920100c4426bfd6bdd": { + "balance": "973581000000000000000" + }, + "d5276f0cd5ffd5ffb63f98b5703d5594ede0838b": { + "balance": "400000000000000000000" + }, + "e9c35c913ca1fceab461582fe1a5815164b4fd21": { + "balance": "8000000000000000000000" + }, + "b43067fe70d9b55973ba58dc64dd7f311e554259": { + "balance": "200000000000000000000" + }, + "6f8f0d15cc96fb7fe94f1065bc6940f8d12957b2": { + "balance": "1000000000000000000000" + }, + "b1dba5250ba9625755246e067967f2ad2f0791de": { + "balance": "80000000000000000000000" + }, + "72b7a03dda14ca9c661a1d469fd33736f673c8e8": { + "balance": "2000000000000000000000" + }, + "e792349ce9f6f14f81d0674096befa1f9221cdea": { + "balance": "1685365000000000000000" + }, + "1815279dff9952da3be8f77249dbe22243377be7": { + "balance": "4749800000000000000000" + }, + "33481e856ebed48ea708a27426ef28e867f57cd1": { + "balance": "200000000000000000000" + }, + "8eb8c71982a00fb84275293253f8044544b66b49": { + "balance": "400000000000000000000" + }, + "65f5870f26bce089677dfc23b5001ee492483428": { + "balance": "5067230000000000000000" + }, + "8e23facd12c765c36ab81a6dd34d8aa9e68918ae": { + "balance": "167310000000000000000" + }, + "4912d902931676ff39fc34fe3c3cc8fb2182fa7a": { + "balance": "20000000000000000000" + }, + "c09a66172aea370d9a63da04ff71ffbbfcff7f94": { + "balance": "2000000000000000000000" + }, + "e969ea1595edc5c4a707cfde380929633251a2b0": { + "balance": "200000000000000000000" + }, + "4f2b47e2775a1fa7178dad92985a5bbe493ba6d6": { + "balance": "200000000000000000000" + }, + "cab9a97ada065c87816e6860a8f1426fe6b3d775": { + "balance": "1000000000000000000000" + }, + "cdfd8217339725d7ebac11a63655f265eff1cc3d": { + "balance": "4999962000000000000000" + }, + "ab4004c0403f7eabb0ea586f212156c4203d67f1": { + "balance": "1999944000000000000000" + }, + "1c7cb2fe6bf3e09cbcdc187af38fa8f5053a70b6": { + "balance": "9970823000000000000000" + }, + "a951b244ff50cfae591d5e1a148df6a938ef2a1a": { + "balance": "1734000000000000000000" + }, + "b158db43fa62d30e65f3d09bf781c7b67372ebaa": { + "balance": "1999000000000000000000" + }, + "25e037f00a18270ba5ec3420229ddb0a2ce38fa2": { + "balance": "10000000000000000000000" + }, + "2aaea1f1046f30f109faec1c63ef5c7594eb08da": { + "balance": "4000000000000000000000" + }, + "73d7269ff06c9ffd33754ce588f74a966abbbbba": { + "balance": "6600000000000000000000" + }, + "4c767b65fd91161f4fbdcc6a69e2f6ad711bb918": { + "balance": "720000000000000000000" + }, + "92ae5b7c7eb492ff1ffa16dd42ad9cad40b7f8dc": { + "balance": "865000000000000000000" + }, + "a04f2ae02add14c12faf65cb259022d0830a8e26": { + "balance": "100000000000000000000000" + }, + "63ef2fbc3daf5edaf4a295629ccf31bcdf4038e5": { + "balance": "1460000000000000000000" + }, + "749ad6f2b5706bbe2f689a44c4b640b58e96b992": { + "balance": "100000000000000000000" + }, + "4d836d9d3b0e2cbd4de050596faa490cffb60d5d": { + "balance": "300000000000000000000" + }, + "59f6247b0d582aaa25e5114765e4bf3c774f43c2": { + "balance": "50000000000000000000" + }, + "1293c78c7d6a443b9d74b0ba5ee7bb47fd418588": { + "balance": "6685000000000000000000" + }, + "67bc85e87dc34c4e80aafa066ba8d29dbb8e438e": { + "balance": "402500000000000000000" + }, + "a09f4d5eaa65a2f4cb750a49923401dae59090af": { + "balance": "140000000000000000000" + }, + "ebbd4db9019952d68b1b0f6d8cf0683c00387bb5": { + "balance": "332330000000000000000" + }, + "b16479ba8e7df8f63e1b95d149cd8529d735c2da": { + "balance": "846477000000000000000" + }, + "e1b2aca154b8e0766c4eba30bc10c7f35036f368": { + "balance": "19980000000000000000" + }, + "5c464197791c8a3da3c925436f277ab13bf2faa2": { + "balance": "8000000000000000000000" + }, + "170a88a8997f92d238370f1affdee6347050b013": { + "balance": "3000800000000000000000" + }, + "dadbfafd8b62b92a24efd75256dd83abdbd7bbdb": { + "balance": "19700000000000000000" + }, + "bb993b96ee925ada7d99d786573d3f89180ce3aa": { + "balance": "2000000000000000000000" + }, + "f2c362b0ef991bc82fb36e66ff75932ae8dd8225": { + "balance": "74000000000000000000" + }, + "7f2382ffd8f83956467937f9ba72374623f11b38": { + "balance": "600000000000000000000" + }, + "74d1a4d0c7524e018d4e06ed3b648092b5b6af2c": { + "balance": "50000000000000000000" + }, + "24a750eae5874711116dd7d47b7186ce990d3103": { + "balance": "200000000000000000000" + }, + "a8e42a4e33d7526cca19d9a36dcd6e8040d0ea73": { + "balance": "1080000000000000000000" + }, + "3e1b2230afbbd310b4926a4c776d5ae7819c661d": { + "balance": "30000000000000000000000" + }, + "6af9f0dfeeaebb5f64bf91ab771669bf05295553": { + "balance": "400000000000000000000" + }, + "41e4a20275e39bdcefeb655c0322744b765140c2": { + "balance": "10000000000000000000000" + }, + "ceb089ec8a78337e8ef88de11b49e3dd910f748f": { + "balance": "1000000000000000000000" + }, + "e6bcd30a8fa138c5d9e5f6c7d2da806992812dcd": { + "balance": "260000000000000000000000" + }, + "e08c60313106e3f9334fe6f7e7624d211130c077": { + "balance": "40000000000000000000" + }, + "f5cffbba624e7eb321bc83c60ca68199b4e36671": { + "balance": "2000000000000000000000" + }, + "d7c2803ed7b0e0837351411a8e6637d168bc5b05": { + "balance": "29549015000000000000000" + }, + "0f3665d48e9f1419cd984fc7fa92788710c8f2e4": { + "balance": "2000000000000000000000" + }, + "b48921c9687d5510744584936e8886bdbf2df69b": { + "balance": "1000000000000000000000" + }, + "a94bbb8214cf8da0c2f668a2ac73e86248528d4b": { + "balance": "960000000000000000000" + }, + "be0c2a80b9de084b172894a76cf4737a4f529e1a": { + "balance": "1999944000000000000000" + }, + "fcf199f8b854222f182e4e1d099d4e323e2aae01": { + "balance": "1000000000000000000000" + }, + "b52dfb45de5d74e3df208332bc571c809b8dcf32": { + "balance": "6000000000000000000000" + }, + "704819d2e44d6ed1da25bfce84c49fcca25613e5": { + "balance": "400000000000000000000" + }, + "6ff6cc90d649de4e96cffee1077a5b302a848dcb": { + "balance": "28600000000000000000" + }, + "4d9c77d0750c5e6fbc247f2fd79274686cb353d6": { + "balance": "20000000000000000000" + }, + "68e8022740f4af29eb48db32bcecddfd148d3de3": { + "balance": "1000000000000000000000" + }, + "2cb615073a40dcdb99faa848572e987b3b056efb": { + "balance": "799600000000000000000" + }, + "64adcceec53dd9d9dd15c8cc1a9e736de4241d2c": { + "balance": "56000000000000000000" + }, + "2aec809df9325b9f483996e99f7331097f08aa0e": { + "balance": "4000000000000000000000" + }, + "438c2f54ff8e629bab36b1442b760b12a88f02ae": { + "balance": "2000000000000000000000" + }, + "9e35399071a4a101e9194daa3f09f04a0b5f9870": { + "balance": "4000000000000000000000" + }, + "a5c336083b04f9471b8c6ed73679b74d66c363ec": { + "balance": "3014100000000000000000" + }, + "7ad3f307616f19dcb143e6444dab9c3c33611f52": { + "balance": "50000000000000000000" + }, + "455cb8ee39ffbc752331e5aefc588ef0ee593454": { + "balance": "999963000000000000000" + }, + "c4c01afc3e0f045221da1284d7878574442fb9ac": { + "balance": "7419944000000000000000" + }, + "99268327c373332e06c3f6164287d455b9d5fa4b": { + "balance": "2000000000000000000000" + }, + "4367ae4b0ce964f4a54afd4b5c368496db169e9a": { + "balance": "2000000000000000000000" + }, + "2cd79eb52027b12c18828e3eaab2969bfcd287e9": { + "balance": "20000000000000000000" + }, + "b96841cabbc7dbd69ef0cf8f81dff3c8a5e21570": { + "balance": "12000000000000000000000" + }, + "d7ebddb9f93987779b680155375438db65afcb6a": { + "balance": "100600000000000000000" + }, + "0631d18bbbbd30d9e1732bf36edae2ce8901ab80": { + "balance": "3024800000000000000000" + }, + "5fad960f6b2c84569c9f4d47bf1985fcb2c65da6": { + "balance": "999972000000000000000" + }, + "01d599ee0d5f8c38ab2d392e2c65b74c3ce31820": { + "balance": "510000000000000000000" + }, + "ff0cc8dac824fa24fc3caa2169e6e057cf638ad6": { + "balance": "4000000000000000000000" + }, + "c25266c7676632f13ef29be455ed948add567792": { + "balance": "1337000000000000000000" + }, + "9c344098ba615a398f11d009905b177c44a7b602": { + "balance": "1000000000000000000000" + }, + "3b0accaf4b607cfe61d17334c214b75cdefdbd89": { + "balance": "2000000000000000000000" + }, + "6d6634b5b8a40195d949027af4828802092ceeb6": { + "balance": "3000000000000000000000" + }, + "208c45732c0a378f17ac8324926d459ba8b658b4": { + "balance": "2955000000000000000000" + }, + "c24399b4bf86f7338fbf645e3b22b0e0b7973912": { + "balance": "2000000000000000000000" + }, + "29763dd6da9a7c161173888321eba6b63c8fb845": { + "balance": "328000000000000000000" + }, + "9c2fd54089af665df5971d73b804616039647375": { + "balance": "1000000000000000000000" + }, + "0e09646c99af438e99fa274cb2f9c856cb65f736": { + "balance": "1910000000000000000000" + }, + "be73274d8c5aa44a3cbefc8263c37ba121b20ad3": { + "balance": "500000000000000000000" + }, + "ecfd004d02f36cd4d8b4a8c1a9533b6af85cd716": { + "balance": "5003800000000000000000" + }, + "f978b025b64233555cc3c19ada7f4199c9348bf7": { + "balance": "400000000000000000000000" + }, + "705ddd38355482b8c7d3b515bda1500dd7d7a817": { + "balance": "400000000000000000000" + }, + "2b8a0dee5cb0e1e97e15cfca6e19ad21f995efad": { + "balance": "504206000000000000000" + }, + "1098cc20ef84bad5146639c4cd1ca6c3996cb99b": { + "balance": "18200000000000000000" + }, + "afdac5c1cb56e245bf70330066a817eaafac4cd1": { + "balance": "20000000000000000000" + }, + "910e996543344c6815fb97cda7af4b8698765a5b": { + "balance": "103400000000000000000" + }, + "94612781033b57b146ee74e753c672017f5385e4": { + "balance": "3600000000000000000000" + }, + "d03fc165576aaed525e5502c8e140f8b2e869639": { + "balance": "6850000000000000000000" + }, + "293384c42b6f8f2905ce52b7205c2274376c612b": { + "balance": "1400000000000000000000" + }, + "09ee12b1b42b05af9cf207d5fcac255b2ec411f2": { + "balance": "58929000000000000000" + }, + "dbd71efa4b93c889e76593de609c3b04cbafbe08": { + "balance": "20000000000000000000" + }, + "fa86ca27bf2854d98870837fb6f6dfe4bf6453fc": { + "balance": "322061000000000000000" + }, + "61ff8e67b34d9ee6f78eb36ffea1b9f7c15787af": { + "balance": "1640000000000000000000" + }, + "6d4cbf3d8284833ae99344303e08b4d614bfda3b": { + "balance": "12000000000000000000000" + }, + "2ff160c44f72a299b5ec2d71e28ce5446d2fcbaf": { + "balance": "360000000000000000000" + }, + "94a7cda8f481f9d89d42c303ae1632b3b709db1d": { + "balance": "300000000000000000000" + }, + "7566496162ba584377be040a4f87777a707acaeb": { + "balance": "4000000000000000000000" + }, + "bdc461462b6322b462bdb33f22799e8108e2417d": { + "balance": "668500000000000000000" + }, + "7e47637e97c14622882be057bea229386f4052e5": { + "balance": "440000000000000000000" + }, + "3b5c251d7fd7893ba209fe541cecd0ce253a990d": { + "balance": "30000000000000000000000" + }, + "0e498800447177b8c8afc3fdfa7f69f4051bb629": { + "balance": "2140234000000000000000" + }, + "b71623f35107cf7431a83fb3d204b29ee0b1a7f4": { + "balance": "19700000000000000000" + }, + "1d395b30adda1cf21f091a4f4a7b753371189441": { + "balance": "100000000000000000000000" + }, + "2c2428e4a66974edc822d5dbfb241b2728075158": { + "balance": "2000000000000000000000" + }, + "a575f2891dcfcda83c5cf01474af11ee01b72dc2": { + "balance": "100076000000000000000" + }, + "ad728121873f0456d0518b80ab6580a203706595": { + "balance": "500000000000000000000" + }, + "48669eb5a801d8b75fb6aa58c3451b7058c243bf": { + "balance": "30940000000000000000000" + }, + "b3ae54fba09d3ee1d6bdd1e957923919024c35fa": { + "balance": "65513000000000000000" + }, + "0d35408f226566116fb8acdaa9e2c9d59b76683f": { + "balance": "940000000000000000000" + }, + "df211cd21288d6c56fae66c3ff54625dd4b15427": { + "balance": "2500024000000000000000" + }, + "8a746c5d67064711bfca685b95a4fe291a27028e": { + "balance": "40000000000000000000" + }, + "1cf105ab23023b554c583e86d7921179ee83169f": { + "balance": "1970000000000000000000" + }, + "8cfedef198db0a9143f09129b3fd64dcbb9b4956": { + "balance": "2000000000000000000000" + }, + "1e381adcf801a3bf9fd7bfac9ccc2b8482ad5e66": { + "balance": "600200000000000000000" + }, + "e74608f506866ada6bfbfdf20fea440be76989ef": { + "balance": "1999944000000000000000" + }, + "27e63989ca1e903bc620cf1b9c3f67b9e2ae6581": { + "balance": "1337000000000000000000" + }, + "bb0857f1c911b24b86c8a70681473fe6aaa1cce2": { + "balance": "100000000000000000000" + }, + "4f8e8d274fb22a3fd36a47fe72980471544b3434": { + "balance": "200000000000000000000" + }, + "127d3fc5003bf63c0d83e93957836515fd279045": { + "balance": "111890000000000000000" + }, + "95809e8da3fbe4b7f281f0b8b1715f420f7d7d63": { + "balance": "2000000000000000000000" + }, + "28904bb7c4302943b709b14d7970e42b8324e1a1": { + "balance": "10027500000000000000000" + }, + "c07e3867ada096807a051a6c9c34cc3b3f4ad34a": { + "balance": "1788210000000000000000" + }, + "f0b469eae89d400ce7d5d66a9695037036b88903": { + "balance": "20000000000000000000000" + }, + "7445202f0c74297a004eb3726aa6a82dd7c02fa1": { + "balance": "2000000000000000000000" + }, + "c58f62fee9711e6a05dc0910b618420aa127f288": { + "balance": "3980000000000000000000" + }, + "801d65c518b11d0e3f4f470221417013c8e53ec5": { + "balance": "4000000000000000000000" + }, + "41010fc8baf8437d17a04369809a168a17ca56fb": { + "balance": "100000000000000000000" + }, + "a1998144968a5c70a6415554cefec2824690c4a5": { + "balance": "20000000000000000000" + }, + "e9559185f166fc9513cc71116144ce2deb0f1d4b": { + "balance": "20000000000000000000000" + }, + "ed5b4c41e762d942404373caf21ed4615d25e6c1": { + "balance": "2013960000000000000000" + }, + "665b000f0b772750cc3c217a5ef429a92bf1ccbb": { + "balance": "4000000000000000000000" + }, + "febd9f81cf78bd5fb6c4b9a24bd414bb9bfa4c4e": { + "balance": "1990019000000000000000" + }, + "a072691c8dd7cd4237ff72a75c1a9506d0ce5b9e": { + "balance": "370000000000000000000" + }, + "6765df25280e8e4f38d4b1cf446fc5d7eb659e34": { + "balance": "100000000000000000000" + }, + "524fb210522c5e23bb67dfbf8c26aa616da49955": { + "balance": "999971000000000000000" + }, + "e987e6139e6146a717fef96bc24934a5447fe05d": { + "balance": "2000000000000000000000" + }, + "d6110276cfe31e42825a577f6b435dbcc10cf764": { + "balance": "1000000000000000000000" + }, + "5e51b8a3bb09d303ea7c86051582fd600fb3dc1a": { + "balance": "20000000000000000000" + }, + "5c4f24e994ed8f850ea7818f471c8fac3bcf0452": { + "balance": "1724800000000000000000" + }, + "85b2998d0c73302cb2ba13f489313301e053be15": { + "balance": "10000000000000000000000" + }, + "0af6c8d539c96d50259e1ba6719e9c8060f388c2": { + "balance": "1000000000000000000000" + }, + "7d901b28bf7f88ef73d8f73cca97564913ea8a24": { + "balance": "955000000000000000000" + }, + "e01859f242f1a0ec602fa8a3b0b57640ec89075e": { + "balance": "555000000000000000000" + }, + "c66ae4cee87fb3353219f77f1d6486c580280332": { + "balance": "29550000000000000000" + }, + "2d40558b06f90a3923145592123b6774e46e31f4": { + "balance": "1000000000000000000000" + }, + "ccf43975b76bfe735fec3cb7d4dd24f805ba0962": { + "balance": "60000000000000000000" + }, + "1703b4b292b8a9deddede81bb25d89179f6446b6": { + "balance": "19690000000000000000000" + }, + "0e9096d343c060db581a120112b278607ec6e52b": { + "balance": "20000000000000000000" + }, + "f65819ac4cc14c137f05dd7977c7dae08d1a4ab5": { + "balance": "102000000000000000000" + }, + "ca373fe3c906b8c6559ee49ccd07f37cd4fb5266": { + "balance": "1790000000000000000000" + }, + "d28298524df5ec4b24b0ffb9df85170a145a9eb5": { + "balance": "287700000000000000000" + }, + "5fcda847aaf8d7fa8bca08029ca2849166aa15a3": { + "balance": "623350000000000000000" + }, + "bdc739a699700b2e8e2c4a4c7b058a0e513ddebe": { + "balance": "2000000000000000000000" + }, + "0bb05f7224bb5804856556c07eeadbed87ba8f7c": { + "balance": "401100000000000000000" + }, + "ab416fe30d58afe5d9454c7fce7f830bcc750356": { + "balance": "114515000000000000000" + }, + "3eee6f1e96360b7689b3069adaf9af8eb60ce481": { + "balance": "1000000000000000000000" + }, + "9a0d3cee3d9892ea3b3700a27ff84140d9025493": { + "balance": "60000000000000000000" + }, + "5dc36de5359450a1ec09cb0c44cf2bb42b3ae435": { + "balance": "1117500000000000000000" + }, + "35c8adc11125432b3b77acd64625fe58ebee9d66": { + "balance": "2000000000000000000000" + }, + "a5e9cd4b74255d22b7d9b27ae8dd43ed6ed0252b": { + "balance": "766527000000000000000" + }, + "31ea12d49a35a740780ddeeaece84c0835b26270": { + "balance": "200000000000000000000" + }, + "7aef7b551f0b9c46e755c0f38e5b3a73fe1199f5": { + "balance": "1490000000000000000000" + }, + "cc6d7b12061bc96d104d606d65ffa32b0036eb07": { + "balance": "10000000000000000000000" + }, + "322021022678a0166d204b3aaa7ad4ec4b88b7d0": { + "balance": "400000000000000000000" + }, + "b31196714a48dff726ea9433cd2912f1a414b3b3": { + "balance": "2680000000000000000000" + }, + "0f2fb884c8aaff6f543ac6228bd08e4f60b0a5fd": { + "balance": "3145000000000000000000" + }, + "7d9d221a3df89ddd7b5f61c1468c6787d6b333e6": { + "balance": "138000000000000000000" + }, + "367f59cc82795329384e41e1283115e791f26a01": { + "balance": "2000000000000000000000" + }, + "fd9579f119bbc819a02b61e38d8803c942f24d32": { + "balance": "105600000000000000000" + }, + "3e2f26235e137a7324e4dc154b5df5af46ea1a49": { + "balance": "22458000000000000000" + }, + "4c1579af3312e4f88ae93c68e9449c2e9a68d9c4": { + "balance": "2000000000000000000000" + }, + "ffb04726dfa41afdc819168418610472970d7bfc": { + "balance": "4000000000000000000000" + }, + "403c64896a75cad816a9105e18d8aa5bf80f238e": { + "balance": "985000000000000000000" + }, + "5cd588a14ec648ccf64729f9167aa7bf8be6eb3d": { + "balance": "1000000000000000000000" + }, + "24b2be118b16d8b2174769d17b4cf84f07ca946d": { + "balance": "2000000000000000000000" + }, + "d3bb59fa31258be62f8ed232f1a7d47b4a0b41ee": { + "balance": "100000000000000000000" + }, + "cc9ac715cd6f2610c52b58676456884297018b29": { + "balance": "13370000000000000000" + }, + "6f2a31900e240395b19f159c1d00dfe4d898ebdf": { + "balance": "1999600000000000000000" + }, + "d60b247321a32a5affb96b1e279927cc584de943": { + "balance": "2265500000000000000000" + }, + "f7a1ade2d0f529123d1055f19b17919f56214e67": { + "balance": "500000000000000000000" + }, + "bea00df17067a43a82bc1daecafb6c14300e89e6": { + "balance": "1820000000000000000000" + }, + "a2968fc1c64bac0b7ae0d68ba949874d6db253f4": { + "balance": "20000000000000000000000" + }, + "92d8ad9a4d61683b80d4a6672e84c20d62421e80": { + "balance": "20000000000000000000" + }, + "6ed2a12b02f8c688c7b5d3a6ea14d63687dab3b6": { + "balance": "2000000000000000000000" + }, + "7a63869fc767a4c6b1cd0e0649f3634cb121d24b": { + "balance": "77500000000000000000" + }, + "84f522f0520eba52dd18ad21fa4b829f2b89cb97": { + "balance": "4949566000000000000000" + }, + "d6234aaf45c6f22e66a225ffb93add629b4ef80f": { + "balance": "1000000000000000000000" + }, + "e3d8bf4efe84b1616d1b89e427ddc6c8830685ae": { + "balance": "2000000000000000000000" + }, + "a3db364a332d884ba93b2617ae4d85a1489bea47": { + "balance": "1700000000000000000000" + }, + "9f7986924aeb02687cd64189189fb167ded2dd5c": { + "balance": "985000000000000000000" + }, + "2eaf4e2a46b789ccc288c8d1d9294e3fb0853896": { + "balance": "2000000000000000000000" + }, + "a02dc6aa328b880de99eac546823fccf774047fb": { + "balance": "1970000000000000000000" + }, + "873b7f786d3c99ff012c4a7cae2677270240b9c5": { + "balance": "1730000000000000000000" + }, + "1d69c83d28ff0474ceebeacb3ad227a144ece7a3": { + "balance": "5474937000000000000000" + }, + "7b827cae7ff4740918f2e030ab26cb98c4f46cf5": { + "balance": "7460000000000000000000" + }, + "3083ef0ed4c4401196774a95cf4edc83edc1484f": { + "balance": "170000000000000000000000" + }, + "40ad74bc0bce2a45e52f36c3debb1b3ada1b7619": { + "balance": "6790000000000000000000" + }, + "05423a54c8d0f9707e704173d923b946edc8e700": { + "balance": "127543000000000000000" + }, + "22eb7db0ba56b0f8b816ccb206e615d929185b0d": { + "balance": "80500000000000000000" + }, + "66082c75a8de31a53913bbd44de3a0374f7faa41": { + "balance": "1460000000000000000000" + }, + "e3d3eaa299887865569e88be219be507189be1c9": { + "balance": "456156000000000000000" + }, + "ae57cc129a96a89981dac60d2ffb877d5dc5e432": { + "balance": "1110994000000000000000" + }, + "1a2434cc774422d48d53d59c5d562cce8407c94b": { + "balance": "30000000000000000000" + }, + "21546914dfd3af2add41b0ff3e83ffda7414e1e0": { + "balance": "5969100000000000000000" + }, + "4dcf62a3de3f061db91498fd61060f1f6398ff73": { + "balance": "1999944000000000000000" + }, + "6fd98e563d12ce0fd60f4f1f850ae396a9823c02": { + "balance": "1261000000000000000000" + }, + "edf8a3e1d40f13b79ec8e3e1ecf262fd92116263": { + "balance": "158000000000000000000" + }, + "c09e3cfc19f605ff3ec9c9c70e2540d7ee974366": { + "balance": "500000000000000000000" + }, + "953572f0ea6df9b197cae40e4b8ecc056c4371c5": { + "balance": "1000000000000000000000" + }, + "163cc8be227646cb09719159f28ed09c5dc0dce0": { + "balance": "1337000000000000000000" + }, + "a3932a31d6ff75fb3b1271ace7caa7d5e1ff1051": { + "balance": "20000000000000000000000" + }, + "f9a94bd56198da245ed01d1e6430b24b2708dcc0": { + "balance": "749938000000000000000" + }, + "3eb8b33b21d23cda86d8288884ab470e164691b5": { + "balance": "500000000000000000000" + }, + "84bcbf22c09607ac84341d2edbc03bfb1739d744": { + "balance": "500000000000000000000" + }, + "961c59adc74505d1864d1ecfcb8afa0412593c93": { + "balance": "40000000000000000000000" + }, + "f068dfe95d15cd3a7f98ffa688b4346842be2690": { + "balance": "1255160000000000000000" + }, + "291efe0081dce8c14799f7b2a43619c0c3b3fc1f": { + "balance": "1200000000000000000000" + }, + "be4fd073617022b67f5c13499b827f763639e4e3": { + "balance": "2000000000000000000000" + }, + "e40a7c82e157540a0b00901dbb86c716e1a062da": { + "balance": "49800000000000000000" + }, + "6635b46f711d2da6f0e16370cd8ee43efb2c2d52": { + "balance": "2000000000000000000000" + }, + "43748928e8c3ec4436a1d092fbe43ac749be1251": { + "balance": "400000000000000000000" + }, + "b557ab9439ef50d237b553f02508364a466a5c03": { + "balance": "200000000000000000000" + }, + "11928378d27d55c520ceedf24ceb1e822d890df0": { + "balance": "8000000000000000000000" + }, + "61518464fdd8b73c1bb6ac6db600654938dbf17a": { + "balance": "200000000000000000000" + }, + "004bfbe1546bc6c65b5c7eaa55304b38bbfec6d3": { + "balance": "2000000000000000000000" + }, + "a5e0fc3c3affed3db6710947d1d6fb017f3e276d": { + "balance": "2000000000000000000000" + }, + "8ecbcfacbfafe9f00c3922a24e2cf0026756ca20": { + "balance": "5640000000000000000000" + }, + "fb5ffaa0f7615726357891475818939d2037cf96": { + "balance": "20000000000000000000" + }, + "ae222865799079aaf4f0674a0cdaab02a6d570ff": { + "balance": "2000000000000000000000" + }, + "9edc90f4be210865214ab5b35e5a8dd77415279d": { + "balance": "4000000000000000000000" + }, + "9d7831e834c20b1baa697af1d8e0c621c5afff9a": { + "balance": "86500000000000000000" + }, + "046d274b1af615fb505a764ad8dda770b1db2f3d": { + "balance": "2000000000000000000000" + }, + "eaea23aa057200e7c9c15e8ff190d0e66c0c0e83": { + "balance": "2000000000000000000000" + }, + "417a3cd19496530a6d4204c3b5a17ce0f207b1a5": { + "balance": "8000000000000000000000" + }, + "a035a3652478f82dbd6d115faa8ca946ec9e681d": { + "balance": "109880000000000000000" + }, + "4f5801b1eb30b712d8a0575a9a71ff965d4f34eb": { + "balance": "300000000000000000000" + }, + "91dbb6aaad149585be47375c5d6de5ff09191518": { + "balance": "20000000000000000000000" + }, + "d043a011ec4270ee7ec8b968737515e503f83028": { + "balance": "500000000000000000000" + }, + "bb371c72c9f0316cea2bd9c6fbb4079e775429ef": { + "balance": "1760000000000000000000" + }, + "aa1df92e51dff70b1973e0e924c66287b494a178": { + "balance": "534400000000000000000" + }, + "bd5f46caab2c3d4b289396bbb07f203c4da82530": { + "balance": "80000000000000000000" + }, + "4d29fc523a2c1629532121da9998e9b5ab9d1b45": { + "balance": "15800000000000000000" + }, + "addb26317227f45c87a2cb90dc4cfd02fb23caf8": { + "balance": "1000000000000000000000" + }, + "52e46783329a769301b175009d346768f4c87ee4": { + "balance": "2000000000000000000000" + }, + "caad9dc20d589ce428d8fda3a9d53a607b7988b5": { + "balance": "4000000000000000000000" + }, + "95034e1621865137cd4739b346dc17da3a27c34e": { + "balance": "1580000000000000000000" + }, + "0c3239e2e841242db989a61518c22247e8c55208": { + "balance": "263656000000000000000" + }, + "5a0d609aae2332b137ab3b2f26615a808f37e433": { + "balance": "160000000000000000000000" + }, + "2334c590c7a48769103045c5b6534c8a3469f44a": { + "balance": "17443200000000000000000" + }, + "ddfcca13f934f0cfbe231da13039d70475e6a1d0": { + "balance": "1000169000000000000000" + }, + "ee7288d91086d9e2eb910014d9ab90a02d78c2a0": { + "balance": "2000000000000000000000" + }, + "fb91fb1a695553f0c68e21276decf0b83909b86d": { + "balance": "100016000000000000000" + }, + "38695fc7e1367ceb163ebb053751f9f68ddb07a0": { + "balance": "2000000000000000000000" + }, + "65093b239bbfba23c7775ca7da5a8648a9f54cf7": { + "balance": "400000000000000000000" + }, + "73d8fee3cb864dce22bb26ca9c2f086d5e95e63b": { + "balance": "1000000000000000000000" + }, + "f7155213449892744bc60f2e04400788bd041fdd": { + "balance": "66850000000000000000" + }, + "d1a71b2d0858e83270085d95a3b1549650035e23": { + "balance": "14900000000000000000000" + }, + "eac17b81ed5191fb0802aa54337313834107aaa4": { + "balance": "8000000000000000000000" + }, + "bb076aac92208069ea318a31ff8eeb14b7e996e3": { + "balance": "149000000000000000000" + }, + "9f46e7c1e9078cae86305ac7060b01467d6685ee": { + "balance": "668500000000000000000" + }, + "1598127982f2f8ad3b6b8fc3cf27bf617801ba2b": { + "balance": "173000000000000000000" + }, + "e91dac0195b19e37b59b53f7c017c0b2395ba44c": { + "balance": "1880000000000000000000" + }, + "a436c75453ccca4a1f1b62e5c4a30d86dde4be68": { + "balance": "2000000000000000000000" + }, + "11001b89ed873e3aaec1155634b4681643986323": { + "balance": "1000000000000000000000" + }, + "ab93b26ece0a0aa21365afed1fa9aea31cd54468": { + "balance": "1608000000000000000000" + }, + "e77febabdf080f0f5dca1d3f5766f2a79c0ffa7c": { + "balance": "1386000000000000000000" + }, + "1c4af0e863d2656c8635bc6ffec8dd9928908cb5": { + "balance": "2000000000000000000000" + }, + "0c48ae62d1539788eba013d75ea60b64eeba4e80": { + "balance": "2213311000000000000000" + }, + "423cc4594cf4abb6368de59fd2b1230734612143": { + "balance": "2000000000000000000000" + }, + "7f6b28c88421e4857e459281d78461692489d3fb": { + "balance": "2000000000000000000000" + }, + "806854588ecce541495f81c28a290373df0274b2": { + "balance": "582000000000000000000" + }, + "dc76e85ba50b9b31ec1e2620bce6e7c8058c0eaf": { + "balance": "20000000000000000000" + }, + "b00996b0566ecb3e7243b8227988dcb352c21899": { + "balance": "12000000000000000000000" + }, + "f5d14552b1dce0d6dc1f320da6ffc8a331cd6f0c": { + "balance": "1337000000000000000000" + }, + "55a61b109480b5b2c4fcfdef92d90584160c0d35": { + "balance": "44700000000000000000" + }, + "b8947822d5ace7a6ad8326e95496221e0be6b73d": { + "balance": "20000000000000000000" + }, + "492de46aaf8f1d708d59d79af1d03ad2cb60902f": { + "balance": "2000000000000000000000" + }, + "0e0d6633db1e0c7f234a6df163a10e0ab39c200f": { + "balance": "200000000000000000000" + }, + "f8bf9c04874e5a77f38f4c38527e80c676f7b887": { + "balance": "2000000000000000000000" + }, + "15528350e0d9670a2ea27f7b4a33b9c0f9621d21": { + "balance": "4000086000000000000000" + }, + "eccf7a0457b566b346ca673a180f444130216ac3": { + "balance": "100000000000000000000" + }, + "10cf560964ff83c1c9674c783c0f73fcd89943fc": { + "balance": "40000000000000000000000" + }, + "e7f06f699be31c440b43b4db0501ec0e25261644": { + "balance": "500000000000000000000" + }, + "b6ce4dc560fc73dc69fb7a62e388db7e72ea764f": { + "balance": "966000000000000000000" + }, + "f456055a11ab91ff668e2ec922961f2a23e3db25": { + "balance": "18200000000000000000" + }, + "8dfbafbc0e5b5c86cd1ad697feea04f43188de96": { + "balance": "390060000000000000000" + }, + "085b4ab75d8362d914435cedee1daa2b1ee1a23b": { + "balance": "3880000000000000000000" + }, + "e400d651bb3f2d23d5f849e6f92d9c5795c43a8a": { + "balance": "2674000000000000000000" + }, + "851aa91c82f42fad5dd8e8bb5ea69c8f3a5977d1": { + "balance": "148607000000000000000" + }, + "4c935bb250778b3c4c7f7e07fc251fa630314aab": { + "balance": "1500000000000000000000" + }, + "ebd356156a383123343d48843bffed6103e866b3": { + "balance": "1970000000000000000000" + }, + "da0b48e489d302b4b7bf204f957c1c9be383b0df": { + "balance": "2000000000000000000000" + }, + "7085ae7e7e4d932197b5c7858c00a3674626b7a5": { + "balance": "6000000000000000000000" + }, + "5b06d1e6930c1054692b79e3dbe6ecce53966420": { + "balance": "205400000000000000000" + }, + "8df53d96191471e059de51c718b983e4a51d2afd": { + "balance": "32000000000000000000000" + }, + "0678654ac6761db904a2f7e8595ec1eaac734308": { + "balance": "878000000000000000000" + }, + "89fee30d1728d96cecc1dab3da2e771afbcfaa41": { + "balance": "1999944000000000000000" + }, + "59c5d06b170ee4d26eb0a0eb46cb7d90c1c91019": { + "balance": "10000000000000000000000" + }, + "2b129c26b75dde127f8320bd0f63410c92a9f876": { + "balance": "2200000000000000000000" + }, + "3d6ae053fcbc318d6fd0fbc353b8bf542e680d27": { + "balance": "14300000000000000000" + }, + "755a60bf522fbd8fff9723446b7e343a7068567e": { + "balance": "20000000000000000000000" + }, + "947e11e5ea290d6fc3b38048979e0cd44ec7c17f": { + "balance": "2000000000000000000000" + }, + "711ecf77d71b3d0ea95ce4758afecdb9c131079d": { + "balance": "760000000000000000000" + }, + "de9eff4c798811d968dccb460d9b069cf30278e0": { + "balance": "400000000000000000000" + }, + "4e892e8081bf36e488fddb3b2630f3f1e8da30d2": { + "balance": "12003800000000000000000" + }, + "8ede7e3dc50749c6c50e2e28168478c34db81946": { + "balance": "19999800000000000000000" + }, + "0c30cacc3f72269f8b4f04cf073d2b05a83d9ad1": { + "balance": "2001000000000000000000" + }, + "e51eb87e7fb7311f5228c479b48ec9878831ac4c": { + "balance": "2000000000000000000000" + }, + "8b01da34d470c1d115acf4d8113c4dd8a8c338e4": { + "balance": "25220000000000000000000" + }, + "4329fc0931cbeb033880fe4c9398ca45b0e2d11a": { + "balance": "2000400000000000000000" + }, + "540c072802014ef0d561345aec481e8e11cb3570": { + "balance": "8000000000000000000000" + }, + "21e5d2bae995ccfd08a5c16bb524e1f630448f82": { + "balance": "2800000000000000000000" + }, + "5cf8c03eb3e872e50f7cfd0c2f8d3b3f2cb5183a": { + "balance": "200000000000000000000" + }, + "5c0f2e51378f6b0d7bab617331580b6e39ad3ca5": { + "balance": "9600000000000000000000" + }, + "d2f241255dd7c3f73c07043071ec08ddd9c5cde5": { + "balance": "500000000000000000000" + }, + "cbe1b948864d8474e765145858fca4550f784b92": { + "balance": "10000000000000000000000" + }, + "30742ccdf4abbcd005681f8159345c9e79054b1a": { + "balance": "668500000000000000000" + }, + "6aeb9f74742ea491813dbbf0d6fcde1a131d4db3": { + "balance": "440800000000000000000" + }, + "821eb90994a2fbf94bdc3233910296f76f9bf6e7": { + "balance": "10000000000000000000000" + }, + "25c1a37ee5f08265a1e10d3d90d5472955f97806": { + "balance": "1820000000000000000000" + }, + "7ef98b52bee953bef992f305fda027f8911c5851": { + "balance": "514717000000000000000" + }, + "8adc53ef8c18ed3051785d88e996f3e4b20ecd51": { + "balance": "42000000000000000000000" + }, + "007f4a23ca00cd043d25c2888c1aa5688f81a344": { + "balance": "773658000000000000000" + }, + "4a735d224792376d331367c093d31c8794341582": { + "balance": "1900000000000000000000" + }, + "05440c5b073b529b4829209dff88090e07c4f6f5": { + "balance": "1288000000000000000000" + }, + "5e772e27f28800c50dda973bb33e10762e6eea20": { + "balance": "1790000000000000000000" + }, + "a429fa88731fdd350e8ecd6ea54296b6484fe695": { + "balance": "1969606000000000000000" + }, + "e0d76b7166b1f3a12b4091ee2b29de8caa7d07db": { + "balance": "2000000000000000000000" + }, + "7ebd95e9c470f7283583dc6e9d2c4dce0bea8f84": { + "balance": "14000000000000000000000" + }, + "883a78aeabaa50d8ddd8570bcd34265f14b19363": { + "balance": "3879951000000000000000" + }, + "51f9c432a4e59ac86282d6adab4c2eb8919160eb": { + "balance": "530000000000000000000000" + }, + "b86607021b62d340cf2652f3f95fd2dc67698bdf": { + "balance": "5000000000000000000000" + }, + "acc0909fda2ea6b7b7a88db7a0aac868091ddbf6": { + "balance": "22155000000000000000" + }, + "69b80ed90f84834afa3ff82eb964703b560977d6": { + "balance": "26740000000000000000" + }, + "ca4ca9e4779d530ecbacd47e6a8058cfde65d98f": { + "balance": "800000000000000000000" + }, + "5d6c5c720d66a6abca8397142e63d26818eaab54": { + "balance": "40000000000000000000" + }, + "c2c13e72d268e7150dc799e7c6cf03c88954ced7": { + "balance": "700000000000000000000" + }, + "6bbd1e719390e6b91043f8b6b9df898ea8001b34": { + "balance": "2000053000000000000000" + }, + "a9ba6f413b82fcddf3affbbdd09287dcf50415ca": { + "balance": "4000000000000000000000" + }, + "ced3c7be8de7585140952aeb501dc1f876ecafb0": { + "balance": "4000000000000000000000" + }, + "1c63fa9e2cbbf23c49fcdef1cbabfe6e0d1e14c1": { + "balance": "1000000000000000000000" + }, + "7d6e990daa7105de2526339833f77b5c0b85d84f": { + "balance": "20000000000000000000000" + }, + "68addf019d6b9cab70acb13f0b3117999f062e12": { + "balance": "49941000000000000000" + }, + "a77428bcb2a0db76fc8ef1e20e461a0a32c5ac15": { + "balance": "401100000000000000000" + }, + "26048fe84d9b010a62e731627e49bc2eb73f408f": { + "balance": "4000000000000000000000" + }, + "ff26138330274df4e0a3081e6df7dd983ec6e78f": { + "balance": "2000000000000000000000" + }, + "b7382d37db0398ac72410cf9813de9f8e1ec8dad": { + "balance": "1000070000000000000000" + }, + "44f62f2aaabc29ad3a6b04e1ff6f9ce452d1c140": { + "balance": "17000000000000000000000" + }, + "47fef58584465248a0810d60463ee93e5a6ee8d3": { + "balance": "283100000000000000000" + }, + "bd2b70fecc37640f69514fc7f3404946aad86b11": { + "balance": "1200000000000000000000" + }, + "649a85b93653075fa6562c409a565d087ba3e1ba": { + "balance": "2000000000000000000000" + }, + "55866486ec168f79dbe0e1abb18864d98991ae2c": { + "balance": "16100000000000000000" + }, + "d7e74afdbad55e96cebc5a374f2c8b768680f2b0": { + "balance": "99000000000000000000" + }, + "a8c1d6aa41fe3d65f67bd01de2a866ed1ed9ae52": { + "balance": "30000000000000000000" + }, + "744c0c77ba7f236920d1e434de5da33e48ebf02c": { + "balance": "1970000000000000000000" + }, + "9445ba5c30e98961b8602461d0385d40fbd80311": { + "balance": "10000000000000000000000" + }, + "eb835c1a911817878a33d167569ea3cdd387f328": { + "balance": "1000000000000000000000" + }, + "761a6e362c97fbbd7c5977acba2da74687365f49": { + "balance": "183840000000000000000" + }, + "38202c5cd7078d4f887673ab07109ad8ada89720": { + "balance": "1000000000000000000000" + }, + "5abfec25f74cd88437631a7731906932776356f9": { + "balance": "11901484239480000000000000" + }, + "28e4af30cd93f686a122ad7bb19f8a8785eee342": { + "balance": "2101000000000000000000" + }, + "3a9b111029ce1f20c9109c7a74eeeef34f4f2eb2": { + "balance": "4000000000000000000000" + }, + "7bb9571f394b0b1a8eba5664e9d8b5e840677bea": { + "balance": "19700000000000000000" + }, + "50fb36c27107ee2ca9a3236e2746cca19ace6b49": { + "balance": "2000000000000000000000" + }, + "a3bc979b7080092fa1f92f6e0fb347e28d995045": { + "balance": "2800000000000000000000" + }, + "d04b861b3d9acc563a901689941ab1e1861161a2": { + "balance": "20000000000000000000" + }, + "58c555bc293cdb16c6362ed97ae9550b92ea180e": { + "balance": "20000000000000000000" + }, + "8bf02bd748690e1fd1c76d270833048b66b25fd3": { + "balance": "11800000000000000000000" + }, + "fbc01db54e47cdc3c438694ab717a856c23fe6e9": { + "balance": "8456774000000000000000" + }, + "9c9a07a8e57c3172a919ef64789474490f0d9f51": { + "balance": "10000000000000000000000" + }, + "fc7e22a503ec5abe9b08c50bd14999f520fa4884": { + "balance": "6387725000000000000000" + }, + "9b773669e87d76018c090f8255e54409b9dca8b2": { + "balance": "20000000000000000000" + }, + "ffe8cbc1681e5e9db74a0f93f8ed25897519120f": { + "balance": "1507000000000000000000" + }, + "4d4cf5807429615e30cdface1e5aae4dad3055e6": { + "balance": "600000000000000000000" + }, + "cfde0fc75d6f16c443c3038217372d99f5d907f7": { + "balance": "2419000000000000000000" + }, + "818ffe271fc3973565c303f213f6d2da89897ebd": { + "balance": "5734655000000000000000" + }, + "ba1fcaf223937ef89e85675503bdb7ca6a928b78": { + "balance": "640000000000000000000" + }, + "a30a45520e5206d9004070e6af3e7bb2e8dd5313": { + "balance": "400000000000000000000" + }, + "a747439ad0d393b5a03861d77296326de8bb9db9": { + "balance": "1000000000000000000000" + }, + "14d00aad39a0a7d19ca05350f7b03727f08dd82e": { + "balance": "500000000000000000000" + }, + "551999ddd205563327b9b530785acff9bc73a4ba": { + "balance": "6000000000000000000000" + }, + "a4670731175893bbcff4fa85ce97d94fc51c4ba8": { + "balance": "8000000000000000000000" + }, + "f858171a04d357a13b4941c16e7e55ddd4941329": { + "balance": "41984000000000000000" + }, + "a6484cc684c4c91db53eb68a4da45a6a6bda3067": { + "balance": "6000000000000000000000" + }, + "00d75ed60c774f8b3a5a5173fb1833ad7105a2d9": { + "balance": "2005500000000000000000" + }, + "bf92418a0c6c31244d220260cb3e867dd7b4ef49": { + "balance": "99800000000000000000" + }, + "716d50cca01e938500e6421cc070c3507c67d387": { + "balance": "2000000000000000000000" + }, + "82a8b96b6c9e13ebec1e9f18ac02a60ea88a48ff": { + "balance": "1999998000000000000000" + }, + "5a565285374a49eedd504c957d510874d00455bc": { + "balance": "100000000000000000000" + }, + "778c79f4de1953ebce98fe8006d53a81fb514012": { + "balance": "999800000000000000000" + }, + "41b2d34fde0b1029262b4172c81c1590405b03ae": { + "balance": "1000000000000000000000" + }, + "4039bd50a2bde15ffe37191f410390962a2b8886": { + "balance": "200000000000000000000" + }, + "c033be10cb48613bd5ebcb33ed4902f38b583003": { + "balance": "3000000000000000000000" + }, + "5d5751819b4f3d26ed0c1ac571552735271dbefa": { + "balance": "1000000000000000000000" + }, + "b600429752f399c80d0734744bae0a022eca67c6": { + "balance": "20000000000000000000" + }, + "f875619d8a23e45d8998d184d480c0748970822a": { + "balance": "4000000000000000000000" + }, + "71c7230a1d35bdd6819ed4b9a88e94a0eb0786dd": { + "balance": "4365000000000000000000" + }, + "b2f9c972c1e9737755b3ff1b3088738396395b26": { + "balance": "20000000000000000000000" + }, + "a66a4963b27f1ee1932b172be5964e0d3ae54b51": { + "balance": "173000000000000000000" + }, + "53ce88e66c5af2f29bbd8f592a56a3d15f206c32": { + "balance": "140840000000000000000" + }, + "433e3ba1c51b810fc467d5ba4dea42f7a9885e69": { + "balance": "40000000000000000000000" + }, + "c7837ad0a0bf14186937ace06c5546a36aa54f46": { + "balance": "4000000000000000000000" + }, + "c3f8f67295a5cd049364d05d23502623a3e52e84": { + "balance": "6000000000000000000000" + }, + "3fd0bb47798cf44cdfbe4d333de637df4a00e45c": { + "balance": "100040000000000000000" + }, + "a1ae8d4540d4db6fdde7146f415b431eb55c7983": { + "balance": "197000000000000000000" + }, + "5cccf1508bfd35c20530aa642500c10dee65eaed": { + "balance": "850000000000000000000" + }, + "a53ead54f7850af21438cbe07af686279a315b86": { + "balance": "10000000000000000000000" + }, + "8cf6da0204dbc4860b46ad973fc111008d9e0c46": { + "balance": "200000000000000000000" + }, + "8e7936d592008fdc7aa04edeeb755ab513dbb89d": { + "balance": "20000000000000000000" + }, + "4a53dcdb56ce4cdce9f82ec0eb13d67352e7c88b": { + "balance": "4200000000000000000000" + }, + "2b4f4507bb6b9817942ce433781b708fbcd166fd": { + "balance": "18200000000000000000" + }, + "026432af37dc5113f1f46d480a4de0b28052237e": { + "balance": "355800000000000000000" + }, + "e780a56306ba1e6bb331952c22539b858af9f77d": { + "balance": "50000000000000000000000" + }, + "d1f1694d22671b5aad6a94995c369fbe6133676f": { + "balance": "1000000000000000000000" + }, + "7c45f0f8442a56dbd39dbf159995415c52ed479b": { + "balance": "2000000000000000000000" + }, + "b65941d44c50d24666670d364766e991c02e11c2": { + "balance": "600000000000000000000" + }, + "45e68db8dbbaba5fc2cb337c62bcd0d61b059189": { + "balance": "2000000000000000000000" + }, + "05f3631f5664bdad5d0132c8388d36d7d8920918": { + "balance": "20000000000000000000" + }, + "5475d7f174bdb1f789017c7c1705989646079d49": { + "balance": "9400000000000000000000" + }, + "c7bf2ed1ed312940ee6aded1516e268e4a604856": { + "balance": "6000000000000000000000" + }, + "39aaf0854db6eb39bc7b2e43846a76171c0445de": { + "balance": "1850000000000000000000" + }, + "c817df1b91faf30fe3251571727c9711b45d8f06": { + "balance": "1999944000000000000000" + }, + "7d13d6705884ab2157dd8dcc7046caf58ee94be4": { + "balance": "137200000000000000000000" + }, + "478dc09a1311377c093f9cc8ae74111f65f82f39": { + "balance": "4000000000000000000000" + }, + "8043ed22f997e5a2a4c16e364486ae64975692c4": { + "balance": "1130513000000000000000" + }, + "b9a985501ee950829b17fae1c9cf348c3156542c": { + "balance": "294100000000000000000" + }, + "d5cba5b26bea5d73fabb1abafacdef85def368cc": { + "balance": "200000000000000000000" + }, + "6776e133d9dc354c12a951087b639650f539a433": { + "balance": "120000000000000000000" + }, + "804ca94972634f633a51f3560b1d06c0b293b3b1": { + "balance": "200000000000000000000" + }, + "0be1fdf626ee6189102d70d13b31012c95cd1cd6": { + "balance": "2000000000000000000000" + }, + "f848fce9ab611c7d99206e23fac69ad488b94fe1": { + "balance": "48500000000000000000" + }, + "f01195d657ef3c942e6cb83949e5a20b5cfa8b1e": { + "balance": "25760000000000000000000" + }, + "78a5e89900bd3f81dd71ba869d25fec65261df15": { + "balance": "51900000000000000000000" + }, + "d6f1e55b1694089ebcb4fe7d7882aa66c8976176": { + "balance": "19998846000000000000000" + }, + "d5294b666242303b6df0b1c88d37429bc8c965aa": { + "balance": "300700000000000000000" + }, + "3171877e9d820cc618fc0919b29efd333fda4934": { + "balance": "1000000000000000000000" + }, + "2901f8077f34190bb47a8e227fa29b30ce113b31": { + "balance": "100000000000000000000" + }, + "6b2284440221ce16a8382de5ff0229472269deec": { + "balance": "1000000000000000000000" + }, + "1bba03ff6b4ad5bf18184acb21b188a399e9eb4a": { + "balance": "1790000000000000000000" + }, + "80744618de396a543197ee4894abd06398dd7c27": { + "balance": "2000000000000000000000" + }, + "1b799033ef6dc7127822f74542bb22dbfc09a308": { + "balance": "100000000000000000000" + }, + "d513a45080ff2febe62cd5854abe29ee4467f996": { + "balance": "153200000000000000000" + }, + "e761d27fa3502cc76bb1a608740e1403cf9dfc69": { + "balance": "280000000000000000000" + }, + "53989ed330563fd57dfec9bd343c3760b0799390": { + "balance": "6208000000000000000000" + }, + "ccf7110d1bd9a74bfd1d7d7d2d9d55607e7b837d": { + "balance": "900000000000000000000" + }, + "f373e9daac0c8675f53b797a160f6fc034ae6b23": { + "balance": "100000000000000000000" + }, + "abc9a99e8a2148a55a6d82bd51b98eb5391fdbaf": { + "balance": "6000000000000000000000" + }, + "ffec0913c635baca2f5e57a37aa9fb7b6c9b6e26": { + "balance": "805000000000000000000" + }, + "581a3af297efa4436a29af0072929abf9826f58b": { + "balance": "2000000000000000000000" + }, + "924efa6db595b79313277e88319625076b580a10": { + "balance": "2000000000000000000000" + }, + "65d8dd4e251cbc021f05b010f2d5dc520c3872e0": { + "balance": "834956000000000000000" + }, + "6c67d6db1d03516c128b8ff234bf3d49b26d2941": { + "balance": "100000000000000000000000" + }, + "496d365534530a5fc1577c0a5241cb88c4da7072": { + "balance": "1790000000000000000000" + }, + "b85ff03e7b5fc422981fae5e9941dacbdaba7584": { + "balance": "1337000000000000000000" + }, + "e13540ecee11b212e8b775dc8e71f374aae9b3f8": { + "balance": "2000000000000000000000" + }, + "a02e3f8f5959a7aab7418612129b701ca1b80010": { + "balance": "20000000000000000000" + }, + "a7a3f153cdc38821c20c5d8c8241b294a3f82b24": { + "balance": "500000000000000000000" + }, + "366175403481e0ab15bb514615cbb989ebc68f82": { + "balance": "2000000000000000000000" + }, + "5104ecc0e330dd1f81b58ac9dbb1a9fbf88a3c85": { + "balance": "100000000000000000000000" + }, + "a466d770d898d8c9d405e4a0e551efafcde53cf9": { + "balance": "492500000000000000000" + }, + "5fa8a54e68176c4fe2c01cf671c515bfbdd528a8": { + "balance": "330000000000000000000000" + }, + "e2e15c60dd381e3a4be25071ab249a4c5c5264da": { + "balance": "2350502000000000000000" + }, + "0628bfbe5535782fb588406bc96660a49b011af5": { + "balance": "1520000000000000000000" + }, + "04d6b8d4da867407bb997749debbcdc0b358538a": { + "balance": "1000000000000000000000" + }, + "0e6ec313376271dff55423ab5422cc3a8b06b22b": { + "balance": "4000000000000000000000" + }, + "8787d12677a5ec291e57e31ffbfad105c3324b87": { + "balance": "12438777000000000000000" + }, + "58e2f11223fc8237f69d99c6289c148c0604f742": { + "balance": "24000000000000000000000" + }, + "5600730a55f6b20ebd24811faa3de96d1662abab": { + "balance": "1880000000000000000000" + }, + "fce089635ce97abac06b44819be5bb0a3e2e0b37": { + "balance": "92491000000000000000" + }, + "fa0c1a988c8a17ad3528eb28b3409daa58225f26": { + "balance": "200000000000000000000" + }, + "7ae1c19e53c71cee4c73fae2d7fc73bf9ab5e392": { + "balance": "1000000000000000000000" + }, + "bd17eed82b9a2592019a1b1b3c0fbad45c408d22": { + "balance": "250000000000000000000" + }, + "884a7a39d0916e05f1c242df55607f37df8c5fda": { + "balance": "23400000000000000000000" + }, + "ca70f4ddbf069d2143bd6bbc7f696b52789b32e7": { + "balance": "3000000000000000000000" + }, + "7b25bb9ca8e702217e9333225250e53c36804d48": { + "balance": "1880000000000000000000" + }, + "ea8317197959424041d9d7c67a3ece1dbb78bb55": { + "balance": "394000000000000000000" + }, + "5cb953a0e42f5030812226217fffc3ce230457e4": { + "balance": "100000000000000000000" + }, + "d1f4dc1ddb8abb8848a8b14e25f3b55a8591c266": { + "balance": "250000000000000000000" + }, + "6a42ca971c6578d5ade295c3e7f4ad331dd3424e": { + "balance": "6000000000000000000000" + }, + "07e1162ceae3cf21a3f62d105990302e307f4e3b": { + "balance": "1530000000000000000000" + }, + "5d1dc3387b47b8451e55106c0cc67d6dc72b7f0b": { + "balance": "2000000000000000000000" + }, + "5d2819e8d57821922ee445650ccaec7d40544a8d": { + "balance": "200000000000000000000" + }, + "4c24b78baf2bafc7fcc69016426be973e20a50b2": { + "balance": "3000000000000000000000" + }, + "630c5273126d517ce67101811cab16b8534cf9a8": { + "balance": "9422595000000000000000" + }, + "291f929ca59b54f8443e3d4d75d95dee243cef78": { + "balance": "499938000000000000000" + }, + "2dd325fdffb97b19995284afa5abdb574a1df16a": { + "balance": "500000000000000000000" + }, + "4fce8429ba49caa0369d1e494db57e89eab2ad39": { + "balance": "200000000000000000000000" + }, + "712b76510214dc620f6c3a1dd29aa22bf6d214fb": { + "balance": "6000000000000000000000" + }, + "266f2da7f0085ef3f3fa09baee232b93c744db2e": { + "balance": "60000000000000000000000" + }, + "0770c61be78772230cb5a3bb2429a72614a0b336": { + "balance": "6767695000000000000000" + }, + "02dfcb17a1b87441036374b762a5d3418b1cb4d4": { + "balance": "1340860000000000000000" + }, + "5e67df8969101adabd91accd6bb1991274af8df2": { + "balance": "500000000000000000000" + }, + "7d9c59631e2ba2e8e82891f3979922aaa3b567a1": { + "balance": "8000000000000000000000" + }, + "949f8c107bc7f0aceaa0f17052aadbd2f9732b2e": { + "balance": "2000000000000000000000" + }, + "ea4e809e266ae5f13cdbe38f9d0456e6386d1274": { + "balance": "4500000000000000000000" + }, + "cd5510a242dfb0183de925fba866e312fabc1657": { + "balance": "2400000000000000000000" + }, + "a36e0d94b95364a82671b608cb2d373245612909": { + "balance": "150011000000000000000" + }, + "0ec46696ffac1f58005fa8439824f08eed1df89b": { + "balance": "10000000000000000000000" + }, + "c6fb1ee37417d080a0d048923bdabab095d077c6": { + "balance": "200000000000000000000" + }, + "53c9eca40973f63bb5927be0bc6a8a8be1951f74": { + "balance": "2000000000000000000000" + }, + "ea14bfda0a6e76668f8788321f07df37824ec5df": { + "balance": "200000000000000000000000" + }, + "dfb4d4ade52fcc818acc7a2c6bb2b00224658f78": { + "balance": "7750000000000000000000" + }, + "5997ffefb3c1d9d10f1ae2ac8ac3c8e2d2292783": { + "balance": "1000000000000000000000" + }, + "8eceb2e124536c5b5ffc640ed14ff15ed9a8cb71": { + "balance": "2000000000000000000000" + }, + "8f02bda6c36922a6be6a509be51906d393f7b99b": { + "balance": "1019835000000000000000" + }, + "530077c9f7b907ff9cec0c77a41a70e9029add4a": { + "balance": "2000000000000000000000" + }, + "08936a37df85b3a158cafd9de021f58137681347": { + "balance": "18200000000000000000" + }, + "8e9c429266df057efa78dd1d5f77fc40742ad466": { + "balance": "300061000000000000000" + }, + "acc59f3b30ceffc56461cc5b8df48902240e0e7b": { + "balance": "2000000000000000000000" + }, + "f5534815dc635efa5cc84b2ac734723e21b29372": { + "balance": "1580000000000000000000" + }, + "f873e57a65c93b6e18cb75f0dc077d5b8933dc5c": { + "balance": "197000000000000000000" + }, + "25b78c9fad85b43343f0bfcd0fac11c9949ca5eb": { + "balance": "2000000000000000000000" + }, + "aad2b7f8106695078e6c138ec81a7486aaca1eb2": { + "balance": "200000000000000000000" + }, + "509c8668036d143fb8ae70b11995631f3dfcad87": { + "balance": "1000000000000000000000" + }, + "3602458da86f6d6a9d9eb03daf97fe5619d442fa": { + "balance": "2000000000000000000000" + }, + "9f607b3f12469f446121cebf3475356b71b4328c": { + "balance": "4000000000000000000000" + }, + "fe3827d57630cf8761d512797b0b858e478bbd12": { + "balance": "20000000000000000000" + }, + "9d9c4efe9f433989e23be94049215329fa55b4cb": { + "balance": "256215000000000000000" + }, + "9bd905f1719fc7acd0159d4dc1f8db2f21472338": { + "balance": "1000000000000000000000" + }, + "7d82e523cc2dc591da3954e8b6bb2caf6461e69c": { + "balance": "2316058000000000000000" + }, + "74afe54902d615782576f8baac13ac970c050f6e": { + "balance": "177670000000000000000" + }, + "aff11ccf699304d5f5862af86083451c26e79ae5": { + "balance": "1999000000000000000000" + }, + "3885fee67107dc3a3c741ee290c98918c9b99397": { + "balance": "20000000000000000000" + }, + "36343aeca07b6ed58a0e62fa4ecb498a124fc971": { + "balance": "300000000000000000000" + }, + "c94a28fb3230a9ddfa964e770f2ce3c253a7be4f": { + "balance": "200000000000000000000" + }, + "9882967cee68d2a839fad8ab4a7c3dddf6c0adc8": { + "balance": "1336866000000000000000" + }, + "95df4e3445d7662624c48eba74cf9e0a53e9f732": { + "balance": "56000000000000000000000" + }, + "ca9faa17542fafbb388eab21bc4c94e8a7b34788": { + "balance": "1999999000000000000000" + }, + "c8b1850525d946f2ae84f317b15188c536a5dc86": { + "balance": "2685000000000000000000" + }, + "39bac68d947859f59e9226089c96d62e9fbe3cde": { + "balance": "40000000000000000000" + }, + "a9bfc410dddb20711e45c07387eab30a054e19ac": { + "balance": "1154750000000000000000" + }, + "540a1819bd7c35861e791804e5fbb3bc97c9abb1": { + "balance": "1454400000000000000000" + }, + "667b61c03bb937a9f5d0fc5a09f1ea3363c77035": { + "balance": "4250000000000000000000" + }, + "010df1df4bed23760d2d1c03781586ddf7918e54": { + "balance": "60000000000000000000" + }, + "bd51ee2ea143d7b1d6b77e7e44bdd7da12f485ac": { + "balance": "1318800000000000000000" + }, + "fb5125bf0f5eb0b6f020e56bfc2fdf3d402c097e": { + "balance": "5910000000000000000000" + }, + "3f0c83aac5717962734e5ceaeaecd39b28ad06be": { + "balance": "2000000000000000000000" + }, + "f10661ff94140f203e7a482572437938bec9c3f7": { + "balance": "20000000000000000000000" + }, + "bd3097a79b3c0d2ebff0e6e86ab0edadbed47096": { + "balance": "1670000000000000000000" + }, + "edeb4894aadd0081bbddd3e8846804b583d19f27": { + "balance": "2000000000000000000000" + }, + "49c9771fca19d5b9d245c891f8158fe49f47a062": { + "balance": "10000000000000000000000" + }, + "6405dd13e93abcff377e700e3c1a0086eca27d29": { + "balance": "18200000000000000000" + }, + "ce5e04f0184369bcfa06aca66ffa91bf59fa0fb9": { + "balance": "40000000000000000000" + }, + "4364309a9fa07095600f79edc65120cdcd23dc64": { + "balance": "10000000000000000000000" + }, + "b749b54e04d5b19bdcedfb84da7701ab478c27ae": { + "balance": "2680000000000000000000" + }, + "f593c65285ee6bbd6637f3be8f89ad40d489f655": { + "balance": "3000000000000000000000" + }, + "d224f880f9479a89d32f09e52be990b288135cef": { + "balance": "17300000000000000000000" + }, + "85bb51bc3bfe9a1b2a2f6b1cda95bca8b38c8d5e": { + "balance": "321750000000000000000" + }, + "caf4481d9db78dc4f25f7b4ac8bd3b1ca0106b31": { + "balance": "5000000000000000000000" + }, + "51ca8bd4dc644fac47af675563d5804a0da21eeb": { + "balance": "788000000000000000000" + }, + "19f643e1a8fa04ae16006028138333a59a96de87": { + "balance": "20000000000000000000" + }, + "58b808a65b51e6338969afb95ec70735e451d526": { + "balance": "39998000000000000000000" + }, + "574921838cc77d6c98b17d903a3ae0ee0da95bd0": { + "balance": "53480000000000000000000" + }, + "7c6924d07c3ef5891966fe0a7856c87bef9d2034": { + "balance": "2000000000000000000000" + }, + "f9767e4ecb4a5980527508d7bec3d45e4c649c13": { + "balance": "1910000000000000000000" + }, + "f3be99b9103ce7550aa74ff1db18e09dfe32e005": { + "balance": "2000000000000000000000" + }, + "625644c95a873ef8c06cdb9e9f6d8d7680043d62": { + "balance": "1800000000000000000000" + }, + "6a44af96b3f032ae641beb67f4b6c83342d37c5d": { + "balance": "29000000000000000000" + }, + "d3a10ec7a5c9324999dd9e9b6bde7c911e584bda": { + "balance": "600000000000000000000" + }, + "e8ddbed732ebfe754096fde9086b8ea4a4cdc616": { + "balance": "2000000000000000000000" + }, + "235fa66c025ef5540070ebcf0d372d8177c467ab": { + "balance": "33400000000000000000000" + }, + "4d08471d68007aff2ae279bc5e3fe4156fbbe3de": { + "balance": "40000000000000000000000" + }, + "dadc00ab7927603c2fcf31cee352f80e6c4d6351": { + "balance": "1999664000000000000000" + }, + "7393cbe7f9ba2165e5a7553500b6e75da3c33abf": { + "balance": "100000000000000000000" + }, + "77617ebc4bebc5f5ddeb1b7a70cdeb6ae2ffa024": { + "balance": "1970000000000000000000" + }, + "7fea1962e35d62059768c749bedd96cab930d378": { + "balance": "2000000000000000000000" + }, + "243b3bca6a299359e886ce33a30341fafe4d573d": { + "balance": "20000000000000000000000" + }, + "b94d47b3c052a5e50e4261ae06a20f45d8eee297": { + "balance": "2000000000000000000000" + }, + "e727e67ef911b81f6cf9c73fcbfebc2b02b5bfc6": { + "balance": "2000000000000000000000" + }, + "e510d6797fba3d6693835a844ea2ad540691971b": { + "balance": "17381000000000000000000" + }, + "0cdc960b998c141998160dc179b36c15d28470ed": { + "balance": "500038000000000000000" + }, + "3e76a62db187aa74f63817533b306cead0e8cebe": { + "balance": "31200000000000000000000" + }, + "495b641b1cdea362c3b4cbbd0f5cc50b1e176b9c": { + "balance": "1000000000000000000000" + }, + "5126460d692c71c9af6f05574d93998368a23799": { + "balance": "52000000000000000000" + }, + "a008019863c1a77c1499eb39bbd7bf2dd7a31cb9": { + "balance": "137000000000000000000" + }, + "65ee20b06d9ad589a7e7ce04b9f5f795f402aece": { + "balance": "2000000000000000000000" + }, + "f432b9dbaf11bdbd73b6519fc0a904198771aac6": { + "balance": "152000000000000000000" + }, + "85946d56a4d371a93368539690b60ec825107454": { + "balance": "1730000000000000000000" + }, + "26f9f7cefd7e394b9d3924412bf2c2831faf1f85": { + "balance": "4000000000000000000000" + }, + "d4ebb1929a23871cf77fe049ab9602be08be0a73": { + "balance": "1910000000000000000000" + }, + "4fdac1aa517007e0089430b3316a1badd12c01c7": { + "balance": "500000000000000000000" + }, + "05e671de55afec964b074de574d5158d5d21b0a3": { + "balance": "3940000000000000000000" + }, + "20181c4b41f6f972b66958215f19f570c15ddff1": { + "balance": "1600000000000000000000" + }, + "cc9519d1f3985f6b255eaded12d5624a972721e1": { + "balance": "1000000000000000000000" + }, + "169bbefc41cfd7d7cbb8dfc63020e9fb06d49546": { + "balance": "2000000000000000000000" + }, + "175a183a3a235ffbb03ba835675267229417a091": { + "balance": "16000000000000000000000" + }, + "8dde3cb8118568ef4503fe998ccdf536bf19a098": { + "balance": "4000000000000000000000" + }, + "6a05b21c4f17f9d73f5fb2b0cb89ff5356a6cc7e": { + "balance": "1500000000000000000000" + }, + "5cc4cba621f220637742057f6055b80dffd77e13": { + "balance": "39997692000000000000000" + }, + "ecb94c568bfe59ade650645f4f26306c736cace4": { + "balance": "267400000000000000000" + }, + "dfa6b8b8ad3184e357da282951d79161cfb089bc": { + "balance": "400000000000000000000" + }, + "a3058c51737a4e96c55f2ef6bd7bb358167ec2a7": { + "balance": "606093000000000000000" + }, + "051d424276b21239665186133d653bb8b1862f89": { + "balance": "1000000000000000000000" + }, + "d05ffb2b74f867204fe531653b0248e21c13544e": { + "balance": "1000000000000000000000" + }, + "e1f63ebbc62c7b7444040eb99623964f7667b376": { + "balance": "20000000000000000000" + }, + "e5a3d7eb13b15c100177236d1beb30d17ee15420": { + "balance": "2000000000000000000000" + }, + "18fa8625c9dc843c78c7ab259ff87c9599e07f10": { + "balance": "1000000000000000000000" + }, + "64264aedd52dcae918a012fbcd0c030ee6f71821": { + "balance": "1000000000000000000000" + }, + "6f1f4907b8f61f0c51568d692806b382f50324f5": { + "balance": "2000000000000000000000" + }, + "becef61c1c442bef7ce04b73adb249a8ba047e00": { + "balance": "1000400000000000000000" + }, + "7b893286427e72db219a21fc4dcd5fbf59283c31": { + "balance": "10000000000000000000000" + }, + "ce5eb63a7bf4fbc2f6e4baa0c68ab1cb4cf98fb4": { + "balance": "2000000000000000000000" + }, + "66ec16ee9caab411c55a6629e318de6ee216491d": { + "balance": "865000000000000000000" + }, + "30b66150f1a63457023fdd45d0cc6cb54e0c0f06": { + "balance": "1000000000000000000000" + }, + "87183160d172d2e084d327b86bcb7c1d8e6784ef": { + "balance": "4000086000000000000000" + }, + "c420388fbee84ad656dd68cdc1fbaa9392780b34": { + "balance": "187767000000000000000" + }, + "90f774c9147dde90853ddc43f08f16d455178b8c": { + "balance": "4000000000000000000000" + }, + "1e1d7a5f2468b94ea826982dbf2125793c6e4a5a": { + "balance": "999940000000000000000" + }, + "8043fdd0bc4c973d1663d55fc135508ec5d4f4fa": { + "balance": "20000000000000000000" + }, + "7bca1da6c80a66baa5db5ac98541c4be276b447d": { + "balance": "679000000000000000000" + }, + "73550beb732ba9ddafda7ae406e18f7feb0f8bb2": { + "balance": "2800000000000000000000" + }, + "adc19ec835afe3e58d87dc93a8a9213c90451326": { + "balance": "1971200000000000000000" + }, + "821d798af19989c3ae5b84a7a7283cd7fda1fabe": { + "balance": "20000000000000000000000" + }, + "4c4e6f13fb5e3f70c3760262a03e317982691d10": { + "balance": "100000000000000000000" + }, + "664e43119870af107a448db1278b044838ffcdaf": { + "balance": "400000000000000000000" + }, + "8da1178f55d97772bb1d24111a404a4f8715b95d": { + "balance": "878149000000000000000" + }, + "5e6e9747e162f8b45c656e0f6cae7a84bac80e4e": { + "balance": "2000000000000000000000" + }, + "c7eac31abce6d5f1dea42202b6a674153db47a29": { + "balance": "591000000000000000000" + }, + "d96711540e2e998343d4f590b6fc8fac3bb8b31d": { + "balance": "1758944000000000000000" + }, + "9da4ec407077f4b9707b2d9d2ede5ea5282bf1df": { + "balance": "4000000000000000000000" + }, + "f60c1b45f164b9580e20275a5c39e1d71e35f891": { + "balance": "2000000000000000000000" + }, + "eb6394a7bfa4d28911d5a5b23e93f35e340c2294": { + "balance": "78000000000000000000" + }, + "a89ac93b23370472daac337e9afdf642543f3e57": { + "balance": "10000000000000000000000" + }, + "bb618e25221ad9a740b299ed1406bc3934b0b16d": { + "balance": "1000000000000000000000" + }, + "817ac33bd8f847567372951f4a10d7a91ce3f430": { + "balance": "200015000000000000000" + }, + "fe6a895b795cb4bf85903d3ce09c5aa43953d3bf": { + "balance": "3400000000000000000000" + }, + "3673954399f6dfbe671818259bb278e2e92ee315": { + "balance": "200000000000000000000000" + }, + "df0ff1f3d27a8ec9fb8f6b0cb254a63bba8224a5": { + "balance": "4367636000000000000000" + }, + "ff12e49d8e06aa20f886293c0b98ed7eff788805": { + "balance": "4000000000000000000000" + }, + "5aef16a226dd68071f2483e1da42598319f69b2c": { + "balance": "2000000000000000000000" + }, + "0266ab1c6b0216230b9395443d5fa75e684568c6": { + "balance": "1000000000000000000000" + }, + "14a7352066364404db50f0d0d78d754a22198ef4": { + "balance": "1880000000000000000000" + }, + "444caf79b71338ee9aa7c733b02acaa7dc025948": { + "balance": "40000000000000000000" + }, + "64e2de21200b1899c3a0c0653b5040136d0dc842": { + "balance": "20000000000000000000000" + }, + "36e156610cd8ff64e780d89d0054385ca76755aa": { + "balance": "14000000000000000000000" + }, + "0a6ebe723b6ed1f9a86a69ddda68dc47465c2b1b": { + "balance": "1185000000000000000000" + }, + "38bf2a1f7a69de0e2546adb808b36335645da9ff": { + "balance": "2000320000000000000000" + }, + "39f44663d92561091b82a70dcf593d754005973a": { + "balance": "199999000000000000000" + }, + "24b9e6644f6ba4cde126270d81f6ab60f286dff4": { + "balance": "133700000000000000000" + }, + "9b59eb213b1e7565e45047e04ea0374f10762d16": { + "balance": "2000000000000000000000" + }, + "309544b6232c3dd737f945a03193d19b5f3f65b9": { + "balance": "1087440000000000000000" + }, + "b28bb39f3466517cd46f979cf59653ee7d8f152e": { + "balance": "450000000000000000000" + }, + "9da8e22ca10e67fea44e525e4751eeac36a31194": { + "balance": "260000000000000000000" + }, + "4f8ae80238e60008557075ab6afe0a7f2e74d729": { + "balance": "100000000000000000000" + }, + "74ed33acf43f35b98c9230b9e6642ecb5330839e": { + "balance": "681872000000000000000" + }, + "22842ab830da509913f81dd1f04f10af9edd1c55": { + "balance": "2000000000000000000000" + }, + "a8f37f0ab3a1d448a9e3ce40965f97a646083a34": { + "balance": "329800000000000000000" + }, + "582b70669c97aab7d68148d8d4e90411e2810d56": { + "balance": "999972000000000000000" + }, + "d5e55100fbd1956bbed2ca518d4b1fa376032b0b": { + "balance": "100000000000000000000" + }, + "b7cc6b1acc32d8b295df68ed9d5e60b8f64cb67b": { + "balance": "300000000000000000000" + }, + "e081ca1f4882db6043d5a9190703fde0ab3bf56d": { + "balance": "400000000000000000000" + }, + "c02077449a134a7ad1ef7e4d927affeceeadb5ae": { + "balance": "18200000000000000000" + }, + "e09fea755aee1a44c0a89f03b5deb762ba33006f": { + "balance": "1100070000000000000000" + }, + "b3717731dad65132da792d876030e46ac227bb8a": { + "balance": "1000000000000000000000" + }, + "157eb3d3113bd3b597714d3a954edd018982a5cb": { + "balance": "2000000000000000000000" + }, + "dc57345b38e0f067c9a31d9deac5275a10949321": { + "balance": "200000000000000000000" + }, + "40ea5044b204b23076b1a5803bf1d30c0f88871a": { + "balance": "14000000000000000000000" + }, + "2bab0fbe28d58420b52036770a12f9952aea6911": { + "balance": "3820000000000000000000" + }, + "adaa0e548c035affed64ca678a963fabe9a26bfd": { + "balance": "70000000000000000000" + }, + "bb48eaf516ce2dec3e41feb4c679e4957641164f": { + "balance": "3820000000000000000000" + }, + "7693bdeb6fc82b5bca721355223175d47a084b4d": { + "balance": "22000000000000000000000" + }, + "03cb98d7acd817de9d886d22fab3f1b57d92a608": { + "balance": "1600000000000000000000" + }, + "f88900db737955b1519b1a7d170a18864ce590eb": { + "balance": "18200000000000000000" + }, + "757fa55446c460968bb74b5ebca96c4ef2c709c5": { + "balance": "1015200000000000000000" + }, + "da855d53477f505ec4c8d5e8bb9180d38681119c": { + "balance": "5600000000000000000000" + }, + "e41aea250b877d423a63ba2bce2f3a61c0248d56": { + "balance": "260000000000000000000" + }, + "8262169b615870134eb4ac6c5f471c6bf2f789fc": { + "balance": "462500000000000000000" + }, + "66b0c100c49149935d14c0dc202cce907cea1a3d": { + "balance": "1970000000000000000000" + }, + "854c0c469c246b83b5d1b3eca443b39af5ee128a": { + "balance": "1600000000000000000000" + }, + "eb6810691d1ae0d19e47bd22cebee0b3ba27f88a": { + "balance": "2499922000000000000000" + }, + "24dcc24bd9c7210ceacfb30da98ae04a4d7b8ab9": { + "balance": "1000000000000000000000" + }, + "e31b4eef184c24ab098e36c802714bd4743dd0d4": { + "balance": "200000000000000000000" + }, + "99b8c824869de9ed24f3bff6854cb6dd45cc3f9f": { + "balance": "1880000000000000000000" + }, + "2ae73a79aea0278533accf21070922b1613f8f32": { + "balance": "3097417000000000000000" + }, + "ddbd2b932c763ba5b1b7ae3b362eac3e8d40121a": { + "balance": "10000000000000000000000" + }, + "1b4bbcb18165211b265b280716cb3f1f212176e8": { + "balance": "472325000000000000000" + }, + "e177e0c201d335ba3956929c571588b51c5223ae": { + "balance": "2000000000000000000000" + }, + "1945fe377fe6d4b71e3e791f6f17db243c9b8b0f": { + "balance": "2185500000000000000000" + }, + "3e9b34a57f3375ae59c0a75e19c4b641228d9700": { + "balance": "17900000000000000000" + }, + "a4d6c82eddae5947fbe9cdfbd548ae33d91a7191": { + "balance": "8000000000000000000000" + }, + "bad4425e171c3e72975eb46ac0a015db315a5d8f": { + "balance": "2000000000000000000000" + }, + "a2d2aa626b09d6d4e4b13f7ffc5a88bd7ad36742": { + "balance": "4639390000000000000000" + }, + "b61c34fcacda701a5aa8702459deb0e4ae838df8": { + "balance": "35000000000000000000000" + }, + "145e0600e2a927b2dd8d379356b45a2e7d51d3ae": { + "balance": "2545843000000000000000" + }, + "8df339214b6ad1b24663ce716034749d6ef838d9": { + "balance": "11000000000000000000000" + }, + "8fd9a5c33a7d9edce0997bdf77ab306424a11ea9": { + "balance": "2000000000000000000000" + }, + "097da12cfc1f7c1a2464def08c29bed5e2f851e9": { + "balance": "20000000000000000000" + }, + "ddabf13c3c8ea4e3d73d78ec717afafa430e5479": { + "balance": "41600000000000000000000" + }, + "9eeb07bd2b7890195e7d46bdf2071b6617514ddb": { + "balance": "2000000000000000000000" + }, + "819af9a1c27332b1c369bbda1b3de1c6e933d640": { + "balance": "314308000000000000000" + }, + "d7d2c6fca8ad1f75395210b57de5dfd673933909": { + "balance": "340000000000000000000" + }, + "cdd5d881a7362c9070073bdfbc75e72453ac510e": { + "balance": "842000000000000000000" + }, + "e9ac36376efa06109d40726307dd1a57e213eaa9": { + "balance": "194000000000000000000" + }, + "1bea4df5122fafdeb3607eddda1ea4ffdb9abf2a": { + "balance": "346000000000000000000" + }, + "3e5e93fb4c9c9d1246f8f247358e22c3c5d17b6a": { + "balance": "150000000000000000000" + }, + "6c1ddd33c81966dc8621776071a4129482f2c65f": { + "balance": "40000000000000000000000" + }, + "2ccb66494d0af689abf9483d365d782444e7dead": { + "balance": "1000000000000000000000" + }, + "19571a2b8f81c6bcf66ab3a10083295617150003": { + "balance": "492500000000000000000" + }, + "38ac664ee8e0795e4275cb852bcba6a479ad9c8d": { + "balance": "20000000000000000000" + }, + "c4803bb407c762f90b7596e6fde194931e769590": { + "balance": "4000000000000000000000" + }, + "93507e9e8119cbceda8ab087e7ecb071383d6981": { + "balance": "14000000000000000000000" + }, + "b672734afcc224e2e609fc51d4f059732744c948": { + "balance": "295500000000000000000" + }, + "fbbbebcfbe235e57dd2306ad1a9ec581c7f9f48f": { + "balance": "40000000000000000000" + }, + "8c81410ea8354cc5c65c41be8bd5de733c0b111d": { + "balance": "9550000000000000000000" + }, + "942c6b8c955bc0d88812678a236725b32739d947": { + "balance": "1550000000000000000000" + }, + "d2e817738abf1fb486583f80c350318bed860c80": { + "balance": "240010000000000000000" + }, + "bff5df769934b8943ca9137d0efef2fe6ebbb34e": { + "balance": "100000000000000000000" + }, + "6c4e426e8dc005dfa3516cb8a680b02eea95ae8e": { + "balance": "1337000000000000000000" + }, + "f645dd7c890093e8e4c8aa92a6bb353522d3dc98": { + "balance": "134000000000000000000" + }, + "4bac846af4169f1d95431b341d8800b22180af1a": { + "balance": "20000000000000000000" + }, + "0514954c3c2fb657f9a06f510ea22748f027cdd3": { + "balance": "400000000000000000000" + }, + "163dca73d7d6ea3f3e6062322a8734180c0b78ef": { + "balance": "2941400000000000000000" + }, + "feaca2ac74624bf348dac9985143cfd652a4be55": { + "balance": "26148245000000000000000" + }, + "fe80e9232deaff19baf99869883a4bdf0004e53c": { + "balance": "855680000000000000000" + }, + "17108dab2c50f99de110e1b3b3b4cd82f5df28e7": { + "balance": "980000000000000000000" + }, + "837a645dc95c49549f899c4e8bcf875324b2f57c": { + "balance": "600400000000000000000" + }, + "762998e1d75227fced7a70be109a4c0b4ed86414": { + "balance": "20000000000000000000" + }, + "c0a7e8435dff14c25577739db55c24d5bf57a3d9": { + "balance": "49250000000000000000000" + }, + "aead88d689416b1c91f2364421375b7d3c70fb2e": { + "balance": "2000000000000000000000" + }, + "9279b2228cec8f7b4dda3f320e9a0466c2f585ca": { + "balance": "5000000000000000000000" + }, + "36726f3b885a24f92996da81625ec8ad16d8cbe6": { + "balance": "1543723000000000000000" + }, + "3951e48e3c869e6b72a143b6a45068cdb9d466d0": { + "balance": "20000000000000000000" + }, + "f5d61ac4ca95475e5b7bffd5f2f690b316759615": { + "balance": "31040000000000000000000" + }, + "158a0d619253bf4432b5cd02c7b862f7c2b75636": { + "balance": "135733000000000000000" + }, + "e56d431324c92911a1749df292709c14b77a65cd": { + "balance": "8200000000000000000000" + }, + "9976947eff5f6ae5da08dd541192f378b428ff94": { + "balance": "8000000000000000000000" + }, + "83210583c16a4e1e1dac84ebd37e3d0f7c57eba4": { + "balance": "2000000000000000000000" + }, + "dcb64df43758c7cf974fa660484fbb718f8c67c1": { + "balance": "20000000000000000000000" + }, + "d4205592844055b3c7a1f80cefe3b8eb509bcde7": { + "balance": "178973000000000000000" + }, + "d0648a581b3508e135a2935d12c9657045d871ca": { + "balance": "8022000000000000000000" + }, + "e7d17524d00bad82497c0f27156a647ff51d2792": { + "balance": "20000000000000000000" + }, + "21582e99e502cbf3d3c23bdffb76e901ac6d56b2": { + "balance": "100000000000000000000" + }, + "e61f280915c774a31d223cf80c069266e5adf19b": { + "balance": "880000000000000000000" + }, + "03c91d92943603e752203e05340e566013b90045": { + "balance": "802200000000000000000" + }, + "22561c5931143536309c17e832587b625c390b9a": { + "balance": "4000000000000000000000" + }, + "e399c81a1d701b44f0b66f3399e66b275aaaf8c1": { + "balance": "1000000000000000000000" + }, + "7f8dbce180ed9c563635aad2d97b4cbc428906d9": { + "balance": "2674000000000000000000" + }, + "9f61beb46f5e853d0a8521c7446e68e34c7d0973": { + "balance": "560000000000000000000" + }, + "6d3f2ba856ccbb0237fa7661156b14b013f21240": { + "balance": "1000000000000000000000" + }, + "5f742e487e3ab81af2f94afdbe1b9b8f5ccc81bc": { + "balance": "2172412000000000000000" + }, + "b600feab4aa96c537504d96057223141692c193a": { + "balance": "400000000000000000000" + }, + "fab487500df20fb83ebed916791d561772adbebf": { + "balance": "1999980000000000000000" + }, + "f8704c16d2fd5ba3a2c01d0eb20484e6ecfa3109": { + "balance": "200000000000000000000" + }, + "3f1bc420c53c002c9e90037c44fe6a8ef4ddc962": { + "balance": "173000000000000000000" + }, + "82e577b515cb2b0860aafe1ce09a59e09fe7d040": { + "balance": "600000000000000000000" + }, + "bc999e385c5aebcac8d6f3f0d60d5aa725336d0d": { + "balance": "2000000000000000000000" + }, + "e16ce35961cd74bd590d04c4ad4a1989e05691c6": { + "balance": "146000000000000000000" + }, + "eb76424c0fd597d3e341a9642ad1ee118b2b579d": { + "balance": "4000000000000000000000" + }, + "c440c7ca2f964b6972ef664a2261dde892619d9c": { + "balance": "20000000000000000000000" + }, + "460d5355b2ceeb6e62107d81e51270b26bf45620": { + "balance": "2005500000000000000000" + }, + "fcada300283f6bcc134a91456760b0d77de410e0": { + "balance": "2000000000000000000000" + }, + "be8d7f18adfe5d6cc775394989e1930c979d007d": { + "balance": "1000000000000000000000" + }, + "a7f9220c8047826bd5d5183f4e676a6d77bfed36": { + "balance": "153368000000000000000" + }, + "98d204f9085f8c8e7de23e589b64c6eff692cc63": { + "balance": "2000000000000000000000" + }, + "5a2916b8d2e8cc12e207ab464d433e2370d823d9": { + "balance": "2000000000000000000000" + }, + "c42d6aeb710e3a50bfb44d6c31092969a11aa7f3": { + "balance": "150052000000000000000" + }, + "04ce45f600db18a9d0851b29d9393ebdaafe3dc5": { + "balance": "20000000000000000000" + }, + "7a1370a742ec2687e761a19ac5a794329ee67404": { + "balance": "2999988000000000000000" + }, + "da2ad58e77deddede2187646c465945a8dc3f641": { + "balance": "660000000000000000000" + }, + "ec58bc0d0c20d8f49465664153c5c196fe59e6be": { + "balance": "400000000000000000000" + }, + "f8063af4cc1dd9619ab5d8bff3fcd1faa8488221": { + "balance": "2000000000000000000000" + }, + "b9231eb26e5f9e4b4d288f03906704fab96c87d6": { + "balance": "19700000000000000000000" + }, + "6e5c2d9b1c546a86eefd5d0a5120c9e4e730190e": { + "balance": "199600000000000000000" + }, + "e49936a92a8ccf710eaac342bc454b9b14ebecb1": { + "balance": "2000000000000000000000" + }, + "21dbdb817a0d8404c6bdd61504374e9c43c9210e": { + "balance": "9999917000000000000000" + }, + "5cebe30b2a95f4aefda665651dc0cf7ef5758199": { + "balance": "18200000000000000000" + }, + "597038ff91a0900cbbab488af483c790e6ec00a0": { + "balance": "10000000000000000000000" + }, + "0fa5d8c5b3f294efd495ab69d768f81872508548": { + "balance": "2000000000000000000000" + }, + "feef3b6eabc94affd3310c1c4d0e65375e131119": { + "balance": "20000000000000000000" + }, + "1ce81d31a7923022e125bf48a3e03693b98dc9dd": { + "balance": "2000000000000000000000" + }, + "5887dc6a33dfed5ac1edefe35ef91a216231ac96": { + "balance": "250000000000000000000" + }, + "4e8e47ae3b1ef50c9d54a38e14208c1abd3603c2": { + "balance": "2235000000000000000000" + }, + "e845e387c4cbdf982280f6aa01c40e4be958ddb2": { + "balance": "25000000000000000000000" + }, + "71d9494e50c5dd59c599dba3810ba1755e6537f0": { + "balance": "4000000000000000000000" + }, + "6eb5578a6bb7c32153195b0d8020a6914852c059": { + "balance": "660000000000000000000000" + }, + "543f8c674e2462d8d5daa0e80195a8708e11a29e": { + "balance": "63940000000000000000" + }, + "a0459ef3693aacd1647cd5d8929839204cef53be": { + "balance": "1000000000000000000000" + }, + "dda371e600d30688d4710e088e02fdf2b9524d5f": { + "balance": "6920000000000000000000" + }, + "dd4dd6d36033b0636fcc8d0938609f4dd64f4a86": { + "balance": "60000000000000000000" + }, + "3bd624b548cb659736907ed8aa3c0c705e24b575": { + "balance": "2000000000000000000000" + }, + "414599092e879ae25372a84d735af5c4e510cd6d": { + "balance": "400000000000000000000" + }, + "3d66cd4bd64d5c8c1b5eea281e106d1c5aad2373": { + "balance": "1951100000000000000000" + }, + "5948bc3650ed519bf891a572679fd992f8780c57": { + "balance": "197000000000000000000" + }, + "8b74a7cb1bb8c58fce267466a30358adaf527f61": { + "balance": "13620000000000000000000" + }, + "3f10800282d1b7ddc78fa92d8230074e1bf6aeae": { + "balance": "4925000000000000000000" + }, + "32dbb6716c54e83165829a4abb36757849b6e47d": { + "balance": "1000000000000000000000" + }, + "e6b3ac3f5d4da5a8857d0b3f30fc4b2b692b77d7": { + "balance": "1460000000000000000000" + }, + "052a58e035f1fe9cdd169bcf20970345d12b9c51": { + "balance": "1490000000000000000000" + }, + "581bdf1bb276dbdd86aedcdb397a01efc0e00c5b": { + "balance": "1000000000000000000000" + }, + "604e9477ebf4727c745bcabbedcb6ccf29994022": { + "balance": "1000060000000000000000" + }, + "59b96deb8784885d8d3b4a166143cc435d2555a1": { + "balance": "1337000000000000000000" + }, + "37d980a12ee3bf23cc5cdb63b4ae45691f74c837": { + "balance": "2000000000000000000000" + }, + "3bfbd3847c17a61cf3f17b52f8eba1b960b3f39f": { + "balance": "3000000000000000000000" + }, + "49c941e0e5018726b7290fc473b471d41dae80d1": { + "balance": "500000000000000000000" + }, + "f26bcedce3feadcea3bc3e96eb1040dfd8ffe1a0": { + "balance": "775000000000000000000" + }, + "d0944aa185a1337061ae20dc9dd96c83b2ba4602": { + "balance": "200000000000000000000" + }, + "904caa429c619d940f8e6741826a0db692b19728": { + "balance": "1000000000000000000000" + }, + "b95c9b10aa981cf4a67a71cc52c504dee8cf58bd": { + "balance": "4000000000000000000000" + }, + "15874686b6733d10d703c9f9bec6c52eb8628d67": { + "balance": "2000000000000000000000" + }, + "1374facd7b3f8d68649d60d4550ee69ff0484133": { + "balance": "269700000000000000000" + }, + "b0e469c886593815b3495638595daef0665fae62": { + "balance": "1940000000000000000000" + }, + "47ff6feb43212060bb1503d7a397fc08f4e70352": { + "balance": "2000000000000000000000" + }, + "c60b04654e003b4683041f1cbd6bc38fda7cdbd6": { + "balance": "2000000000000000000000" + }, + "3ecdb532e397579662b2a46141e78f8235936a5f": { + "balance": "66850000000000000000" + }, + "b3a8c2cb7d358e5739941d945ba9045a023a8bbb": { + "balance": "1000000000000000000000" + }, + "32ef5cdc671df5562a901aee5db716b9be76dcf6": { + "balance": "2000000000000000000000" + }, + "c94110e71afe578aa218e4fc286403b0330ace8d": { + "balance": "2000000000000000000000" + }, + "9b43dcb95fde318075a567f1e6b57617055ef9e8": { + "balance": "3940000000000000000000" + }, + "efeea010756f81da4ba25b721787f058170befbd": { + "balance": "32470000000000000000" + }, + "c88255eddcf521c6f81d97f5a42181c9073d4ef1": { + "balance": "290793000000000000000" + }, + "dd47189a3e64397167f0620e484565b762bfbbf4": { + "balance": "1850000000000000000000" + }, + "82f39b2758ae42277b86d69f75e628d958ebcab0": { + "balance": "40000000000000000000000" + }, + "e37f5fdc6ec97d2f866a1cfd0d3a4da4387b22b5": { + "balance": "10000000000000000000000" + }, + "62331df2a3cbee3520e911dea9f73e905f892505": { + "balance": "2000000000000000000000" + }, + "8c5d16ed65e3ed7e8b96ca972bc86173e3500b03": { + "balance": "2000000000000000000000" + }, + "8b9841862e77fbbe919470935583a93cf027e450": { + "balance": "2000054000000000000000" + }, + "c8dd27f16bf22450f5771b9fe4ed4ffcb30936f4": { + "balance": "197000000000000000000" + }, + "dec8a1a898f1b895d8301fe64ab3ad5de941f689": { + "balance": "787803000000000000000" + }, + "61c4ee7c864c4d6b5e37ea1331c203739e826b2f": { + "balance": "30063000000000000000" + }, + "3250e3e858c26adeccadf36a5663c22aa84c4170": { + "balance": "5000000000000000000000" + }, + "299e0bca55e069de8504e89aca6eca21d38a9a5d": { + "balance": "55500000000000000000" + }, + "d50f7fa03e389876d3908b60a537a6706304fb56": { + "balance": "100000000000000000000" + }, + "69073269729e6414b26ec8dc0fd935c73b579f1e": { + "balance": "30000000000000000000000" + }, + "14fcd1391e7d732f41766cdacd84fa1deb9ffdd2": { + "balance": "2000000000000000000000" + }, + "823768746737ce6da312d53e54534e106f967cf3": { + "balance": "20000000000000000000" + }, + "882f75708386653c80171d0663bfe30b017ed0ad": { + "balance": "2000000000000000000000" + }, + "a25b086437fd2192d0a0f64f6ed044f38ef3da32": { + "balance": "335000000000000000000" + }, + "5a9c8b69fc614d69564999b00dcb42db67f97e90": { + "balance": "3429227000000000000000" + }, + "a2b701f9f5cdd09e4ba62baebae3a88257105885": { + "balance": "1000000000000000000000" + }, + "5e7b8c54dc57b0402062719dee7ef5e37ea35d62": { + "balance": "2877224000000000000000" + }, + "7ffabfbc390cbe43ce89188f0868b27dcb0f0cad": { + "balance": "6370000000000000000000" + }, + "b5cdbc4115406f52e5aa85d0fea170d2979cc7ba": { + "balance": "1337000000000000000000" + }, + "263814309de4e635cf585e0d365477fc40e66cf7": { + "balance": "146000000000000000000" + }, + "24cff0e9336a9f80f9b1cb968caf6b1d1c4932a4": { + "balance": "200200000000000000000" + }, + "d3a941c961e8ca8b1070f23c6d6d0d2a758a4444": { + "balance": "200000000000000000000" + }, + "a97beb3a48c45f1528284cb6a95f7de453358ec6": { + "balance": "31000000000000000000000" + }, + "4dd131c74a068a37c90aded4f309c2409f6478d3": { + "balance": "400008000000000000000" + }, + "653675b842d7d8b461f722b4117cb81dac8e639d": { + "balance": "31000000000000000000" + }, + "561be9299b3e6b3e63b79b09169d1a948ae6db01": { + "balance": "500000000000000000000" + }, + "dc067ed3e12d711ed475f5156ef7e71a80d934b9": { + "balance": "9550000000000000000000" + }, + "08d97eadfcb7b064e1ccd9c8979fbee5e77a9719": { + "balance": "266063000000000000000" + }, + "6e4c2ab7db026939dbd3bc68384af660a61816b2": { + "balance": "167000000000000000000" + }, + "bf4c73a7ede7b164fe072114843654e4d8781dde": { + "balance": "2000000000000000000000" + }, + "f504943aaf16796e0b341bbcdf21d11cc586cdd1": { + "balance": "9000000000000000000000" + }, + "ea81ca8638540cd9d4d73d060f2cebf2241ffc3e": { + "balance": "1970000000000000000000" + }, + "9944fee9d34a4a880023c78932c00b59d5c82a82": { + "balance": "750022000000000000000" + }, + "12f460ae646cd2780fd35c50a6af4b9accfa85c6": { + "balance": "1000000000000000000000" + }, + "4e232d53b3e6be8f895361d31c34d4762b12c82e": { + "balance": "1760000000000000000000" + }, + "6bb2aca23fa1626d18efd6777fb97db02d8e0ae4": { + "balance": "40000000000000000000000" + }, + "bc4e471560c99c8a2a4b1b1ad0c36aa6502b7c4b": { + "balance": "12000000000000000000000" + }, + "2e2cbd7ad82547b4f5ff8b3ab56f942a6445a3b0": { + "balance": "200000000000000000000" + }, + "21ecb2dfa65779c7592d041cd2105a81f4fd4e46": { + "balance": "1000000000000000000000" + }, + "34318625818ec13f11835ae97353ce377d6f590a": { + "balance": "1520000000000000000000" + }, + "a7ef35ce87eda6c28df248785815053ec97a5045": { + "balance": "4999998000000000000000" + }, + "6a514e6242f6b68c137e97fea1e78eb555a7e5f7": { + "balance": "20000000000000000000" + }, + "9340b5f678e45ee05eb708bb7abb6ec8f08f1b6b": { + "balance": "6000000000000000000000" + }, + "43cc08d0732aa58adef7619bed46558ad7774173": { + "balance": "4443926000000000000000" + }, + "12e9a4ad2ad57484dd700565bddb46423bd9bd31": { + "balance": "19999800000000000000000" + }, + "ebbeeb259184a6e01cccfc2207bbd883785ac90a": { + "balance": "619966000000000000000" + }, + "704ab1150d5e10f5e3499508f0bf70650f028d4b": { + "balance": "4000000000000000000000" + }, + "fc361105dd90f9ede566499d69e9130395f12ac8": { + "balance": "395000000000000000000000" + }, + "c1b9a5704d351cfe983f79abeec3dbbbae3bb629": { + "balance": "20000000000000000000" + }, + "66f50406eb1b11a946cab45927cca37470e5a208": { + "balance": "2000000000000000000000" + }, + "53942e7949d6788bb780a7e8a0792781b1614b84": { + "balance": "15899600000000000000000" + }, + "32ba9a7d0423e03a525fe2ebeb661d2085778bd8": { + "balance": "20000000000000000000000" + }, + "11c0358aa6479de21866fe21071924b65e70f8b9": { + "balance": "36400000000000000000000" + }, + "76cb9c8b69f4387675c48253e234cb7e0d74a426": { + "balance": "7396300000000000000000" + }, + "9f5f44026b576a4adb41e95961561d41039ca391": { + "balance": "250000000000000000000" + }, + "533a73a4a2228eee05c4ffd718bbf3f9c1b129a7": { + "balance": "6000000000000000000000" + }, + "dcc52d8f8d9fc742a8b82767f0555387c563efff": { + "balance": "500000000000000000000" + }, + "f456a75bb99655a7412ce97da081816dfdb2b1f2": { + "balance": "200000000000000000000" + }, + "d0c101fd1f01c63f6b1d19bc920d9f932314b136": { + "balance": "20000000000000000000000" + }, + "dabc225042a6592cfa13ebe54efa41040878a5a2": { + "balance": "259550000000000000000" + }, + "38eec6e217f4d41aa920e424b9525197041cd4c6": { + "balance": "4428166000000000000000" + }, + "8a247d186510809f71cffc4559471c3910858121": { + "balance": "1790000000000000000000" + }, + "4f152b2fb8659d43776ebb1e81673aa84169be96": { + "balance": "2000000000000000000000" + }, + "b4496ddb27799a222457d73979116728e8a1845b": { + "balance": "2610331000000000000000" + }, + "4a4053b31d0ee5dbafb1d06bd7ac7ff3222c47d6": { + "balance": "1400000000000000000000" + }, + "0f7bea4ef3f73ae0233df1e100718cbe29310bb0": { + "balance": "2000000000000000000000" + }, + "c836e24a6fcf29943b3608e662290a215f6529ea": { + "balance": "292000000000000000000" + }, + "1765361c2ec2f83616ce8363aae21025f2566f40": { + "balance": "5000000000000000000000" + }, + "b6e6c3222b6b6f9be2875d2a89f127fb64100fe2": { + "balance": "8008000000000000000000" + }, + "01bbc14f67af0639aab1441e6a08d4ce7162090f": { + "balance": "1309500000000000000000" + }, + "af2058c7282cf67c8c3cf930133c89617ce75d29": { + "balance": "6920000000000000000000" + }, + "464d9c89cce484df000277198ed8075fa63572d1": { + "balance": "20000000000000000000" + }, + "50cd97e9378b5cf18f173963236c9951ef7438a5": { + "balance": "1400000000000000000000" + }, + "cb47bd30cfa8ec5468aaa6a94642ced9c819c8d4": { + "balance": "4000000000000000000000" + }, + "6b10f8f8b3e3b60de90aa12d155f9ff5ffb22c50": { + "balance": "2000000000000000000000" + }, + "09b7a988d13ff89186736f03fdf46175b53d16e0": { + "balance": "6000000000000000000000" + }, + "5bfafe97b1dd1d712be86d41df79895345875a87": { + "balance": "500000000000000000000" + }, + "a06cd1f396396c0a64464651d7c205efaf387ca3": { + "balance": "1999944000000000000000" + }, + "fc0096b21e95acb8d619d176a4a1d8d529badbef": { + "balance": "384601000000000000000" + }, + "a74444f90fbb54e56f3ac9b6cfccaa4819e4614a": { + "balance": "20000000000000000000" + }, + "3c15b3511df6f0342e7348cc89af39a168b7730f": { + "balance": "1000000000000000000000" + }, + "3d6ff82c9377059fb30d9215723f60c775c891fe": { + "balance": "250066000000000000000" + }, + "a524a8cccc49518d170a328270a2f88133fbaf5d": { + "balance": "294500000000000000000" + }, + "8a7a06be199a3a58019d846ac9cbd4d95dd757de": { + "balance": "3000200000000000000000" + }, + "d744ac7e5310be696a63b003c40bd039370561c6": { + "balance": "1670000000000000000000" + }, + "fe362688845fa244cc807e4b1130eb3741a8051e": { + "balance": "1000000000000000000000" + }, + "b2d0360515f17daba90fcbac8205d569b915d6ac": { + "balance": "6000000000000000000000" + }, + "c53594c7cfb2a08f284cc9d7a63bbdfc0b319732": { + "balance": "49200000000000000000000" + }, + "b3c228731d186d2ded5b5fbe004c666c8e469b86": { + "balance": "29000000000000000000" + }, + "63e414603e80d4e5a0f5c18774204642258208e4": { + "balance": "5000000000000000000000" + }, + "826ce5790532e0548c6102a30d3eac836bd6388f": { + "balance": "18000000000000000000000" + }, + "c5e812f76f15f2e1f2f9bc4823483c8804636f67": { + "balance": "73000000000000000000" + }, + "116fef5e601642c918cb89160fc2293ba71da936": { + "balance": "802200000000000000000" + }, + "08b84536b74c8c01543da88b84d78bb95747d822": { + "balance": "200000000000000000000" + }, + "04a80afad53ef1f84165cfd852b0fdf1b1c24ba8": { + "balance": "58000000000000000000" + }, + "2b0362633614bfcb583569438ecc4ea57b1d337e": { + "balance": "20000000000000000000000" + }, + "e95179527deca5916ca9a38f215c1e9ce737b4c9": { + "balance": "10000000000000000000000" + }, + "2c5df866666a194b26cebb407e4a1fd73e208d5e": { + "balance": "1000000000000000000000" + }, + "529e824fa072582b4032683ac7eecc1c04b4cac1": { + "balance": "2000000000000000000000" + }, + "78634371e17304cbf339b1452a4ce438dc764cce": { + "balance": "10000000000000000000000" + }, + "e172dfc8f80cd1f8cd8539dc26082014f5a8e3e8": { + "balance": "3000000000000000000000" + }, + "b07618328a901307a1b7a0d058fcd5786e9e72fe": { + "balance": "30239500000000000000000" + }, + "b0571153db1c4ed7acaefe13ecdfdb72e7e4f06a": { + "balance": "80520000000000000000000" + }, + "ad910a23d6850613654af786337ad2a70868ac6d": { + "balance": "1999800000000000000000" + }, + "4da5edc688b0cb62e1403d1700d9dcb99ffe3fd3": { + "balance": "2000000000000000000000" + }, + "be2471a67f6047918772d0e36839255ed9d691ae": { + "balance": "4000000000000000000000" + }, + "28868324337e11ba106cb481da962f3a8453808d": { + "balance": "2000000000000000000000" + }, + "d8f94579496725b5cb53d7985c989749aff849c0": { + "balance": "17000000000000000000000" + }, + "4981c5ff66cc4e9680251fc4cd2ff907cb327865": { + "balance": "750000000000000000000" + }, + "fd2872d19e57853cfa16effe93d0b1d47b4f93fb": { + "balance": "4000000000000000000000" + }, + "63c8dfde0b8e01dadc2e748c824cc0369df090b3": { + "balance": "3880000000000000000000" + }, + "c4dd048bfb840e2bc85cb53fcb75abc443c7e90f": { + "balance": "3716000000000000000000" + }, + "f579714a45eb8f52c3d57bbdefd2c15b2e2f11df": { + "balance": "1560000000000000000000" + }, + "cc7b0481cc32e6faef2386a07022bcb6d2c3b4fc": { + "balance": "3160000000000000000000" + }, + "a0aa5f0201f04d3bbeb898132f7c11679466d901": { + "balance": "36600000000000000000" + }, + "f3df63a97199933330383b3ed7570b96c4812334": { + "balance": "2000000000000000000000" + }, + "42732d8ef49ffda04b19780fd3c18469fb374106": { + "balance": "425068000000000000000" + }, + "6f92d6e4548c78996509ee684b2ee29ba3c532b4": { + "balance": "1000000000000000000000" + }, + "fff4bad596633479a2a29f9a8b3f78eefd07e6ee": { + "balance": "100000000000000000000" + }, + "ac4460a76e6db2b9fcd152d9c7718d9ac6ed8c6f": { + "balance": "200000000000000000000" + }, + "553b6b1c57050e88cf0c31067b8d4cd1ff80cb09": { + "balance": "400000000000000000000" + }, + "84b6b6adbe2f5b3e2d682c66af1bc4905340c3ed": { + "balance": "619333000000000000000" + }, + "9f4a7195ac7c151ca258cafda0cab083e049c602": { + "balance": "1537100000000000000000" + }, + "2955c357fd8f75d5159a3dfa69c5b87a359dea8c": { + "balance": "2000000000000000000000" + }, + "11d7844a471ef89a8d877555583ceebd1439ea26": { + "balance": "10098000000000000000000" + }, + "34b454416e9fb4274e6addf853428a0198d62ee1": { + "balance": "407000000000000000000" + }, + "308dd21cebe755126704b48c0f0dc234c60ba9b1": { + "balance": "200000000000000000000" + }, + "381db4c8465df446a4ce15bf81d47e2f17c980bf": { + "balance": "32000000000000000000000" + }, + "1abc4e253b080aeb437984ab05bca0979aa43e1c": { + "balance": "1000000000000000000000" + }, + "53e35b12231f19c3fd774c88fec8cbeedf1408b2": { + "balance": "512000000000000000000" + }, + "69e2e2e704307ccc5b5ca3f164fece2ea7b2e512": { + "balance": "7000000000000000000000" + }, + "1914f1eb95d1277e93b6e61b668b7d77f13a11a1": { + "balance": "970000000000000000000" + }, + "50e13023bd9ca96ad4c53fdfd410cb6b1f420bdf": { + "balance": "200000000000000000000" + }, + "46224f32f4ece5c8867090d4409d55e50b18432d": { + "balance": "6000000000000000000000" + }, + "ff83855051ee8ffb70b4817dba3211ed2355869d": { + "balance": "400000000000000000000" + }, + "fb39189af876e762c71d6c3e741893df226cedd6": { + "balance": "4000000000000000000000" + }, + "9875623495a46cdbf259530ff838a1799ec38991": { + "balance": "2000000000000000000000" + }, + "e1b39b88d9900dbc4a6cdc481e1060080a8aec3c": { + "balance": "2000000000000000000000" + }, + "5baf6d749620803e8348af3710e5c4fbf20fc894": { + "balance": "5003680000000000000000" + }, + "9c54e4ed479a856829c6bb42da9f0b692a75f728": { + "balance": "7520000000000000000000" + }, + "486a6c8583a84484e3df43a123837f8c7e2317d0": { + "balance": "323378000000000000000" + }, + "d235d15cb5eceebb61299e0e827fa82748911d89": { + "balance": "4000000000000000000000" + }, + "47d792a756779aedf1343e8883a6619c6c281184": { + "balance": "2000000000000000000000" + }, + "70c213488a020c3cfb39014ef5ba6404724bcaa3": { + "balance": "1940000000000000000000" + }, + "133c490fa5bf7f372888e607d958fab7f955bae1": { + "balance": "1580000000000000000000" + }, + "a9e194661aac704ee9dea043974e9692ded84a5d": { + "balance": "482400000000000000000" + }, + "bc6b58364bf7f1951c309e0cba0595201cd73f9a": { + "balance": "1812400000000000000000" + }, + "2309d34091445b3232590bd70f4f10025b2c9509": { + "balance": "10000000000000000000000" + }, + "d89bc271b27ba3ab6962c94a559006ae38d5f56a": { + "balance": "2000000000000000000000" + }, + "ff0e2fec304207467e1e3307f64cbf30af8fd9cd": { + "balance": "2000000000000000000000" + }, + "c0b0b7a8a6e1acdd05e47f94c09688aa16c7ad8d": { + "balance": "64234000000000000000" + }, + "b66f92124b5e63035859e390628869dbdea9485e": { + "balance": "9850000000000000000000" + }, + "a9e6e25e656b762558619f147a21985b8874edfe": { + "balance": "2000000000000000000000" + }, + "a43e1947a9242b355561c30a829dfeeca2815af8": { + "balance": "3878255000000000000000" + }, + "8b20ad3b94656dbdc0dd21a393d8a7d9e02138cb": { + "balance": "3000000000000000000000" + }, + "aca2a838330b17302da731d30db48a04f0f207c1": { + "balance": "1337000000000000000000" + }, + "fa60868aafd4ff4c5c57914b8ed58b425773dfa9": { + "balance": "8557400000000000000000" + }, + "1848003c25bfd4aa90e7fcb5d7b16bcd0cffc0d8": { + "balance": "1000000000000000000000" + }, + "b4b185d943ee2b58631e33dff5af6854c17993ac": { + "balance": "1000000000000000000000" + }, + "7719888795ad745924c75760ddb1827dffd8cda8": { + "balance": "1999980000000000000000" + }, + "ccd521132d986cb96869842622a7dda26c3ed057": { + "balance": "2000000000000000000000" + }, + "253e32b74ea4490ab92606fda0aa257bf23dcb8b": { + "balance": "10000000000000000000000" + }, + "3712367e5e55a96d5a19168f6eb2bc7e9971f869": { + "balance": "1000000000000000000000" + }, + "8f29a14a845ad458f2d108b568d813166bcdf477": { + "balance": "10000000000000000000000" + }, + "51a8c2163602a32ee24cf4aa97fd9ea414516941": { + "balance": "62904000000000000000" + }, + "61cea71fa464d62a07063f920b0cc917539733d8": { + "balance": "1670000000000000000000" + }, + "6f81f3abb1f933b1df396b8e9cc723a89b7c9806": { + "balance": "280000000000000000000" + }, + "61b1b8c012cd4c78f698e470f90256e6a30f48dd": { + "balance": "200000000000000000000" + }, + "4f3f2c673069ac97c2023607152981f5cd6063a0": { + "balance": "600000000000000000000" + }, + "e2efa5fca79538ce6068bf31d2c516d4d53c08e5": { + "balance": "131200000000000000000" + }, + "2383c222e67e969190d3219ef14da37850e26c55": { + "balance": "2000000000000000000000" + }, + "eac3af5784927fe9a598fc4eec38b8102f37bc58": { + "balance": "1000000000000000000000" + }, + "4fe56ab3bae1b0a44433458333c4b05a248f8241": { + "balance": "2180000000000000000000" + }, + "fe9cfc3bb293ddb285e625f3582f74a6b0a5a6cd": { + "balance": "1970000000000000000000" + }, + "f48e1f13f6af4d84b371d7de4b273d03a263278e": { + "balance": "600000000000000000000" + }, + "1ba9228d388727f389150ea03b73c82de8eb2e09": { + "balance": "7258000000000000000000" + }, + "37a7a6ff4ea3d60ec307ca516a48d3053bb79cbb": { + "balance": "2000000000000000000000" + }, + "e33840d8bca7da98a6f3d096d83de78b70b71ef8": { + "balance": "2000000000000000000000" + }, + "8e7fd23848f4db07906a7d10c04b21803bb08227": { + "balance": "1000000000000000000000" + }, + "07d4334ec385e8aa54eedaeadb30022f0cdfa4ab": { + "balance": "2629946000000000000000" + }, + "d4b085fb086f3d0d68bf12926b1cc3142cae8770": { + "balance": "3700000000000000000000" + }, + "5a87f034e6f68f4e74ffe60c64819436036cf7d7": { + "balance": "20000000000000000000" + }, + "c00ab080b643e1c2bae363e0d195de2efffc1c44": { + "balance": "500000000000000000000" + }, + "22f3c779dd79023ea92a78b65c1a1780f62d5c4a": { + "balance": "1970000000000000000000" + }, + "c7d5c7054081e918ec687b5ab36e973d18132935": { + "balance": "182000000000000000000" + }, + "9662ee021926682b31c5f200ce457abea76c6ce9": { + "balance": "670500000000000000000" + }, + "116a09df66cb150e97578e297fb06e13040c893c": { + "balance": "2000000000000000000000" + }, + "b7240af2af90b33c08ae9764103e35dce3638428": { + "balance": "8464547000000000000000" + }, + "e8b28acda971725769db8f563d28666d41ddab6c": { + "balance": "10000000000000000000000" + }, + "17d4918dfac15d77c47f9ed400a850190d64f151": { + "balance": "2000000000000000000000" + }, + "c42250b0fe42e6b7dcd5c890a6f0c88f5f5fb574": { + "balance": "149800000000000000000" + }, + "5da2a9a4c2c0a4a924cbe0a53ab9d0c627a1cfa0": { + "balance": "733202000000000000000" + }, + "5869fb867d71f1387f863b698d09fdfb87c49b5c": { + "balance": "3666000000000000000000" + }, + "d49a75bb933fca1fca9aa1303a64b6cb44ea30e1": { + "balance": "10000000000000000000000" + }, + "76331e30796ce664b2700e0d4153700edc869777": { + "balance": "2000000000000000000000" + }, + "8a5fb75793d043f1bcd43885e037bd30a528c927": { + "balance": "356500000000000000000" + }, + "fc0ee6f7c2b3714ae9916c45566605b656f32441": { + "balance": "1760000000000000000000" + }, + "bf50ce2e264b9fe2b06830617aedf502b2351b45": { + "balance": "1000000000000000000000" + }, + "0f6000de1578619320aba5e392706b131fb1de6f": { + "balance": "499986000000000000000" + }, + "c953f934c0eb2d0f144bdab00483fd8194865ce7": { + "balance": "2000000000000000000000" + }, + "24fd9a6c874c2fab3ff36e9afbf8ce0d32c7de92": { + "balance": "1337000000000000000000" + }, + "c6cd68ec35362c5ad84c82ad4edc232125912d99": { + "balance": "27750000000000000000000" + }, + "2a67660a1368efcd626ef36b2b1b601980941c05": { + "balance": "133700000000000000000" + }, + "9deb39027af877992b89f2ec4a1f822ecdf12693": { + "balance": "2000000000000000000000" + }, + "c12f881fa112b8199ecbc73ec4185790e614a20f": { + "balance": "2000000000000000000000" + }, + "d58a52e078a805596b0d56ea4ae1335af01c66eb": { + "balance": "267400000000000000000" + }, + "4d7cfaa84cb33106800a8c802fb8aa463896c599": { + "balance": "1790000000000000000000" + }, + "0ee391f03c765b11d69026fd1ab35395dc3802a0": { + "balance": "200000000000000000000" + }, + "a192f06ab052d5fd7f94eea8318e827815fe677a": { + "balance": "131400000000000000000" + }, + "8f0ab894bd3f4e697dbcfb859d497a9ba195994a": { + "balance": "39501652000000000000000" + }, + "387eeafd6b4009deaf8bd5b85a72983a8dcc3487": { + "balance": "4000000000000000000000" + }, + "03b0f17cd4469ddccfb7da697e82a91a5f9e7774": { + "balance": "20000000000000000000" + }, + "11172b278ddd44eea2fdf4cb1d16962391c453d9": { + "balance": "935900000000000000000000" + }, + "33d172ab075c51db1cd40a8ca8dbff0d93b843bb": { + "balance": "5727139000000000000000" + }, + "909b5e763a39dcc795223d73a1dbb7d94ca75ac8": { + "balance": "2000000000000000000000" + }, + "0ca12ab0b9666cf0cec6671a15292f2653476ab2": { + "balance": "210000600000000000000000" + }, + "6b5ae7bf78ec75e90cb503c778ccd3b24b4f1aaf": { + "balance": "800000000000000000000" + }, + "d9e3857efd1e202a441770a777a49dcc45e2e0d3": { + "balance": "223500000000000000000" + }, + "d703c6a4f11d60194579d58c2766a7ef16c30a29": { + "balance": "2000000000000000000000" + }, + "838bd565f99fde48053f7917fe333cf84ad548ab": { + "balance": "200000000000000000000" + }, + "8168edce7f2961cf295b9fcd5a45c06cdeda6ef5": { + "balance": "200000000000000000000" + }, + "de50868eb7e3c71937ec73fa89dd8b9ee10d45aa": { + "balance": "1000000000000000000000" + }, + "087498c0464668f31150f4d3c4bcdda5221ba102": { + "balance": "20000000000000000000" + }, + "613fab44b16bbe554d44afd178ab1d02f37aeaa5": { + "balance": "2000000000000000000000" + }, + "e2ee691f237ee6529b6557f2fcdd3dcf0c59ec63": { + "balance": "5450048000000000000000" + }, + "a9ed377b7d6ec25971c1a597a3b0f3bead57c98f": { + "balance": "400000000000000000000" + }, + "175feeea2aa4e0efda12e1588d2f483290ede81a": { + "balance": "200000000000000000000" + }, + "b51ddcb4dd4e8ae6be336dd9654971d9fec86b41": { + "balance": "421133000000000000000" + }, + "92c0f573eccf62c54810ee6ba8d1f113542b301b": { + "balance": "3384000000000000000000" + }, + "a109e18bb0a39c9ef82fa19597fc5ed8e9eb6d58": { + "balance": "1640000000000000000000" + }, + "f74e6e145382b4db821fe0f2d98388f45609c69f": { + "balance": "100000000000000000000" + }, + "378f37243f3ff0bef5e1dc85eb4308d9340c29f9": { + "balance": "2000200000000000000000" + }, + "84e9949680bece6841b9a7e5250d08acd87d16cd": { + "balance": "200000000000000000000" + }, + "882bd3a2e9d74110b24961c53777f22f1f46dc5d": { + "balance": "13370000000000000000000" + }, + "acce01e0a70610dc70bb91e9926fa9957f372fba": { + "balance": "537000000000000000000" + }, + "c5f687717246da8a200d20e5e9bcac60b67f3861": { + "balance": "28650000000000000000" + }, + "e14617f6022501e97e7b3e2d8836aa61f0ff2dba": { + "balance": "200000000000000000000" + }, + "076ee99d3548623a03b5f99859d2d785a1778d48": { + "balance": "200000000000000000000" + }, + "2c424ee47f583cdce07ae318b6fad462381d4d2b": { + "balance": "4000000000000000000000" + }, + "f98250730c4c61c57f129835f2680894794542f3": { + "balance": "4000000000000000000000" + }, + "ed1b24b6912d51b334ac0de6e771c7c0454695ea": { + "balance": "40000000000000000000" + }, + "ffd5170fd1a8118d558e7511e364b24906c4f6b3": { + "balance": "60085000000000000000" + }, + "bf49c14898316567d8b709c2e50594b366c6d38c": { + "balance": "733202000000000000000" + }, + "65ea26eabbe2f64ccccfe06829c25d4637520225": { + "balance": "700000000000000000000" + }, + "5c5419565c3aad4e714e0739328e3521c98f05cc": { + "balance": "528000000000000000000" + }, + "c53b50fd3b2b72bc6c430baf194a515585d3986d": { + "balance": "20000000000000000000" + }, + "2b74c373d04bfb0fd60a18a01a88fbe84770e58c": { + "balance": "40000000000000000000" + }, + "d97f4526dea9b163f8e8e33a6bcf92fb907de6ec": { + "balance": "284000000000000000000" + }, + "a4a49f0bc8688cc9e6dc04e1e08d521026e65574": { + "balance": "200000000000000000000" + }, + "575c00c2818210c28555a0ff29010289d3f82309": { + "balance": "10000000000000000000000" + }, + "3f1233714f204de9de4ee96d073b368d8197989f": { + "balance": "38606000000000000000" + }, + "f964d98d281730ba35b2e3a314796e7b42fedf67": { + "balance": "1543800000000000000000" + }, + "1deec01abe5c0d952de9106c3dc30639d85005d6": { + "balance": "2000000000000000000000" + }, + "12d60d65b7d9fc48840be5f891c745ce76ee501e": { + "balance": "21359400000000000000000" + }, + "5c6136e218de0a61a137b2b3962d2a6112b809d7": { + "balance": "294273000000000000000" + }, + "cd43258b7392a930839a51b2ef8ad23412f75a9f": { + "balance": "2000000000000000000000" + }, + "db3f258ab2a3c2cf339c4499f75a4bd1d3472e9e": { + "balance": "1500000000000000000000" + }, + "0edd4b580ff10fe06c4a03116239ef96622bae35": { + "balance": "197000000000000000000" + }, + "1d157c5876c5cad553c912caf6ce2d5277e05c73": { + "balance": "2000000000000000000000" + }, + "cda1b886e3a795c9ba77914e0a2fe5676f0f5ccf": { + "balance": "106024000000000000000" + }, + "f50cbafd397edd556c0678988cb2af5c2617e0a2": { + "balance": "716000000000000000000" + }, + "327bb49e754f6fb4f733c6e06f3989b4f65d4bee": { + "balance": "20000000000000000000" + }, + "c44bdec8c36c5c68baa2ddf1d431693229726c43": { + "balance": "100000000000000000000000" + }, + "34e2849bea583ab0cc37975190f322b395055582": { + "balance": "7780340000000000000000" + }, + "9221c9ce01232665741096ac07235903ad1fe2fc": { + "balance": "126489000000000000000" + }, + "ff3ded7a40d3aff0d7a8c45fa6136aa0433db457": { + "balance": "1999800000000000000000" + }, + "10b5b34d1248fcf017f8c8ffc408ce899ceef92f": { + "balance": "267400000000000000000" + }, + "f1a1f320407964fd3c8f2e2cc8a4580da94f01ea": { + "balance": "2000040000000000000000" + }, + "6c800d4b49ba07250460f993b8cbe00b266a2553": { + "balance": "492500000000000000000" + }, + "f827d56ed2d32720d4abf103d6d0ef4d3bcd559b": { + "balance": "26265000000000000000" + }, + "ffb9c7217e66743031eb377af65c77db7359dcda": { + "balance": "40000000000000000000" + }, + "530319db0a8f93e5bb7d4dbf4816314fbed8361b": { + "balance": "2000000000000000000000" + }, + "9c28a2c4086091cb5da226a657ce3248e8ea7b6f": { + "balance": "280000000000000000000" + }, + "db23a6fef1af7b581e772cf91882deb2516fc0a7": { + "balance": "200000000000000000000" + }, + "6636d7ac637a48f61d38b14cfd4865d36d142805": { + "balance": "500000000000000000000" + }, + "b3c260609b9df4095e6c5dff398eeb5e2df49985": { + "balance": "254030000000000000000" + }, + "58e5c9e344c806650dacfc904d33edba5107b0de": { + "balance": "19100000000000000000" + }, + "4f67396d2553f998785f704e07a639197dd1948d": { + "balance": "300080000000000000000" + }, + "510d8159cc945768c7450790ba073ec0d9f89e30": { + "balance": "2560000000000000000000" + }, + "593c48935beaff0fde19b04d309cd530a28e52ce": { + "balance": "4000000000000000000000" + }, + "c27f4e08099d8cf39ee11601838ef9fc06d7fc41": { + "balance": "1790000000000000000000" + }, + "07723e3c30e8b731ee456a291ee0e798b0204a77": { + "balance": "2000000000000000000000" + }, + "0a652e2a8b77bd97a790d0e91361c98890dbb04e": { + "balance": "1000000000000000000000" + }, + "671015b97670b10d5e583f3d62a61c1c79c5143f": { + "balance": "400000000000000000000" + }, + "7cc24a6a958c20c7d1249660f7586226950b0d9a": { + "balance": "1970000000000000000000" + }, + "6ef9e8c9b6217d56769af97dbb1c8e1b8be799d2": { + "balance": "182000000000000000000" + }, + "5c4368918ace6409c79eca80cdaae4391d2b624e": { + "balance": "4000000000000000000000" + }, + "043707071e2ae21eed977891dc79cd5d8ee1c2da": { + "balance": "2000000000000000000000" + }, + "39bfd978689bec048fc776aa15247f5e1d7c39a2": { + "balance": "20000000000000000000000" + }, + "05915d4e225a668162aee7d6c25fcfc6ed18db03": { + "balance": "66348000000000000000" + }, + "3f551ba93cd54693c183fb9ad60d65e1609673c9": { + "balance": "2000000000000000000000" + }, + "a8c0b02faf02cb5519dda884de7bbc8c88a2da81": { + "balance": "16700000000000000000" + }, + "bd0c5cd799ebc48642ef97d74e8e429064fee492": { + "balance": "326000000000000000000" + }, + "0a931b449ea8f12cdbd5e2c8cc76bad2c27c0639": { + "balance": "23031000000000000000" + }, + "2ea5fee63f337a376e4b918ea82148f94d48a626": { + "balance": "1864242000000000000000" + }, + "cc6c2df00e86eca40f21ffda1a67a1690f477c65": { + "balance": "3160000000000000000000" + }, + "e5e37e19408f2cfbec83349dd48153a4a795a08f": { + "balance": "4200000000000000000000" + }, + "f555a27bb1e2fd4e2cc784caee92939fc06e2fc9": { + "balance": "2000000000000000000000" + }, + "dcf9719be87c6f46756db4891db9b611d2469c50": { + "balance": "1000000000000000000000" + }, + "8e2f9034c9254719c38e50c9aa64305ed696df1e": { + "balance": "4728000000000000000000" + }, + "a01f12d70f44aa7b113b285c22dcdb45873454a7": { + "balance": "18200000000000000000" + }, + "bce40475d345b0712dee703d87cd7657fc7f3b62": { + "balance": "7750000000000000000000" + }, + "bb19bf91cbad74cceb5f811db27e411bc2ea0656": { + "balance": "17600000000000000000" + }, + "acc062702c59615d3444ef6214b8862b009a02ed": { + "balance": "1499936000000000000000" + }, + "449ac4fbe383e36738855e364a57f471b2bfa131": { + "balance": "197000000000000000000000" + }, + "ad59a78eb9a74a7fbdaefafa82eada8475f07f95": { + "balance": "500000000000000000000" + }, + "6b6577f3909a4d6de0f411522d4570386400345c": { + "balance": "1880000000000000000000" + }, + "79bf2f7b6e328aaf26e0bb093fa22da29ef2f471": { + "balance": "1790000000000000000000" + }, + "940f715140509ffabf974546fab39022a41952d2": { + "balance": "1400000000000000000000" + }, + "1d572edd2d87ca271a6714c15a3b37761dcca005": { + "balance": "127674000000000000000" + }, + "d78ecd25adc86bc2051d96f65364866b42a426b7": { + "balance": "3877300000000000000000" + }, + "f9729d48282c9e87166d5eef2d01eda9dbf78821": { + "balance": "99981000000000000000" + }, + "17762560e82a93b3f522e0e524adb8612c3a7470": { + "balance": "1000000000000000000000" + }, + "d500e4d1c9824ba9f5b635cfa3a8c2c38bbd4ced": { + "balance": "400000000000000000000" + }, + "a11effab6cf0f5972cffe4d56596e98968144a8f": { + "balance": "1670000000000000000000" + }, + "f64ecf2117931c6d535a311e4ffeaef9d49405b8": { + "balance": "2674000000000000000000" + }, + "229cc4711b62755ea296445ac3b77fc633821cf2": { + "balance": "39481000000000000000" + }, + "fc989cb487bf1a7d17e4c1b7c4b7aafdda6b0a8d": { + "balance": "20000000000000000000" + }, + "ea8527febfa1ade29e26419329d393b940bbb7dc": { + "balance": "1999944000000000000000" + }, + "bce13e22322acfb355cd21fd0df60cf93add26c6": { + "balance": "200000000000000000000" + }, + "19ff244fcfe3d4fa2f4fd99f87e55bb315b81eb6": { + "balance": "200000000000000000000" + }, + "d2581a55ce23ab10d8ad8c44378f59079bd6f658": { + "balance": "8800000000000000000000" + }, + "4073fa49b87117cb908cf1ab512da754a932d477": { + "balance": "1970000000000000000000" + }, + "b6a82933c9eadabd981e5d6d60a6818ff806e36b": { + "balance": "400000000000000000000" + }, + "c79806032bc7d828f19ac6a640c68e3d820fa442": { + "balance": "20000000000000000000" + }, + "577b2d073c590c50306f5b1195a4b2ba9ecda625": { + "balance": "373600000000000000000" + }, + "7f13d760498d7193ca6859bc95c901386423d76c": { + "balance": "5000000000000000000000" + }, + "416784af609630b070d49a8bcd12235c6428a408": { + "balance": "20000000000000000000000" + }, + "fbe71622bcbd31c1a36976e7e5f670c07ffe16de": { + "balance": "400000000000000000000" + }, + "a5698035391e67a49013c0002079593114feb353": { + "balance": "240000000000000000000" + }, + "ab2871e507c7be3965498e8fb462025a1a1c4264": { + "balance": "775000000000000000000" + }, + "9c78fbb4df769ce2c156920cfedfda033a0e254a": { + "balance": "1970000000000000000000" + }, + "95e6f93dac228bc7585a25735ac2d076cc3a4017": { + "balance": "6000000000000000000000" + }, + "3c1f91f301f4b565bca24751aa1f761322709ddd": { + "balance": "1790000000000000000000" + }, + "f77f9587ff7a2d7295f1f571c886bd33926a527c": { + "balance": "1999800000000000000000" + }, + "755f587e5efff773a220726a13d0f2130d9f896b": { + "balance": "1000000000000000000000" + }, + "8c6aa882ee322ca848578c06cb0fa911d3608305": { + "balance": "600000000000000000000" + }, + "492cb5f861b187f9df21cd4485bed90b50ffe22d": { + "balance": "499928000000000000000" + }, + "95a577dc2eb3ae6cb9dfc77af697d7efdfe89a01": { + "balance": "136000000000000000000" + }, + "4173419d5c9f6329551dc4d3d0ceac1b701b869e": { + "balance": "88000000000000000000" + }, + "456ae0aca48ebcfae166060250525f63965e760f": { + "balance": "300000000000000000000" + }, + "81f8de2c283d5fd4afbda85dedf9760eabbbb572": { + "balance": "3000000000000000000000" + }, + "cd0af3474e22f069ec3407870dd770443d5b12b0": { + "balance": "2626262000000000000000" + }, + "283c2314283c92d4b064f0aef9bb5246a7007f39": { + "balance": "200000000000000000000" + }, + "29b3f561ee7a6e25941e98a5325b78adc79785f3": { + "balance": "100000000000000000000" + }, + "cd4306d7f6947ac1744d4e13b8ef32cb657e1c00": { + "balance": "499986000000000000000" + }, + "d9ec2efe99ff5cf00d03a8317b92a24aef441f7e": { + "balance": "2000000000000000000000" + }, + "83dbf8a12853b40ac61996f8bf1dc8fdbaddd329": { + "balance": "970000000000000000000" + }, + "9d93fab6e22845f8f45a07496f11de71530debc7": { + "balance": "1998000000000000000000" + }, + "fd204f4f4aba2525ba728afdf78792cbdeb735ae": { + "balance": "2000000000000000000000" + }, + "99fad50038d0d9d4c3fbb4bce05606ecadcd5121": { + "balance": "2000000000000000000000" + }, + "d206aaddb336d45e7972e93cb075471d15897b5d": { + "balance": "600000000000000000000" + }, + "428a1ee0ed331d7952ccbe1c7974b2852bd1938a": { + "balance": "2208370000000000000000" + }, + "690228e4bb12a8d4b5e0a797b0c5cf2a7509131e": { + "balance": "1880000000000000000000" + }, + "fa3a1aa4488b351aa7560cf5ee630a2fd45c3222": { + "balance": "878850000000000000000" + }, + "0372e852582e0934344a0fed2178304df25d4628": { + "balance": "20000000000000000000000" + }, + "35ea2163a38cdf9a123f82a5ec00258dae0bc767": { + "balance": "4000000000000000000000" + }, + "d1fed0aee6f5dfd7e25769254c3cfad15adeccaa": { + "balance": "730000000000000000000" + }, + "c05b740620f173f16e52471dc38b9c514a0b1526": { + "balance": "140000000000000000000" + }, + "87e3062b2321e9dfb0875ce3849c9b2e3522d50a": { + "balance": "10000000000000000000000" + }, + "303fbaebbe46b35b6e5b74946a5f99bc1585cae7": { + "balance": "878148000000000000000" + }, + "e7a8e471eafb798f4554cc6e526730fd56e62c7d": { + "balance": "1000000000000000000000" + }, + "ad7dd053859edff1cb6f9d2acbed6dd5e332426f": { + "balance": "1970000000000000000000" + }, + "dc4345d6812e870ae90c568c67d2c567cfb4f03c": { + "balance": "6700000000000000000000" + }, + "a6a08252c8595177cc2e60fc27593e2379c81fb1": { + "balance": "20055000000000000000" + }, + "a9af21acbe482f8131896a228036ba51b19453c3": { + "balance": "49999000000000000000" + }, + "86e3fe86e93da486b14266eadf056cbfa4d91443": { + "balance": "2000000000000000000000" + }, + "744b03bba8582ae5498e2dc22d19949467ab53fc": { + "balance": "500000000000000000000" + }, + "d3118ea3c83505a9d893bb67e2de142d537a3ee7": { + "balance": "20000000000000000000" + }, + "b32f1c2689a5ce79f1bc970b31584f1bcf2283e7": { + "balance": "20000000000000000000" + }, + "4828e4cbe34e1510afb72c2beeac8a4513eaebd9": { + "balance": "3940000000000000000000" + }, + "b07bcc085ab3f729f24400416837b69936ba8873": { + "balance": "2000140000000000000000" + }, + "bdc74873af922b9df474853b0fa7ff0bf8c82695": { + "balance": "3999000000000000000000" + }, + "15ebd1c7cad2aff19275c657c4d808d010efa0f5": { + "balance": "200550000000000000000" + }, + "cbc04b4d8b82caf670996f160c362940d66fcf1a": { + "balance": "6000000000000000000000" + }, + "8197948121732e63d9c148194ecad46e30b749c8": { + "balance": "4000000000000000000000" + }, + "69797bfb12c9bed682b91fbc593591d5e4023728": { + "balance": "10000000000000000000000" + }, + "be9b8c34b78ee947ff81472eda7af9d204bc8466": { + "balance": "150000000000000000000" + }, + "df3f57b8ee6434d047223def74b20f63f9e4f955": { + "balance": "250500000000000000000" + }, + "a3ae1879007d801cb5f352716a4dd8ba2721de3d": { + "balance": "200000000000000000000000" + }, + "cb4bb1c623ba28dc42bdaaa6e74e1d2aa1256c2a": { + "balance": "1999944000000000000000" + }, + "e03c00d00388ecbf4f263d0ac778bb41a57a40d9": { + "balance": "1000072000000000000000" + }, + "fc2c1f88961d019c3e9ea33009152e0693fbf88a": { + "balance": "8000000000000000000000" + }, + "8599cbd5a6a9dcd4b966be387d69775da5e33c6f": { + "balance": "58180000000000000000000" + }, + "b7a31a7c38f3db09322eae11d2272141ea229902": { + "balance": "2000000000000000000000" + }, + "231a15acc199c89fa9cb22441cc70330bdcce617": { + "balance": "500000000000000000000" + }, + "3fbed6e7e0ca9c84fbe9ebcf9d4ef9bb49428165": { + "balance": "2000000000000000000000" + }, + "92cfd60188efdfb2f8c2e7b1698abb9526c1511f": { + "balance": "2000000000000000000000" + }, + "5c936f3b9d22c403db5e730ff177d74eef42dbbf": { + "balance": "75000000000000000000" + }, + "931fe712f64207a2fd5022728843548bfb8cbb05": { + "balance": "2000000000000000000000" + }, + "08d54e83ad486a934cfaeae283a33efd227c0e99": { + "balance": "1039000000000000000000" + }, + "a339a3d8ca280e27d2415b26d1fc793228b66043": { + "balance": "1013600000000000000000" + }, + "581f34b523e5b41c09c87c298e299cbc0e29d066": { + "balance": "1131607000000000000000" + }, + "caaa68ee6cdf0d34454a769b0da148a1faaa1865": { + "balance": "7216000000000000000000" + }, + "0838a7768d9c2aca8ba279adfee4b1f491e326f1": { + "balance": "200000000000000000000" + }, + "dde77a4740ba08e7f73fbe3a1674912931742eeb": { + "balance": "19867021000000000000000" + }, + "cbe810fe0fecc964474a1db97728bc87e973fcbd": { + "balance": "10000000000000000000000" + }, + "86c28b5678af37d727ec05e4447790f15f71f2ea": { + "balance": "200000000000000000000" + }, + "dd6c062193eac23d2fdbf997d5063a346bb3b470": { + "balance": "20000000000000000000" + }, + "5975b9528f23af1f0e2ec08ac8ebaa786a2cb8e0": { + "balance": "345827000000000000000" + }, + "e29d8ae452dcf3b6ac645e630409385551faae0a": { + "balance": "80276000000000000000" + }, + "2fbc85798a583598b522166d6e9dda121d627dbc": { + "balance": "200000000000000000000" + }, + "7a36aba5c31ea0ca7e277baa32ec46ce93cf7506": { + "balance": "20000000000000000000000" + }, + "dbcbcd7a57ea9db2349b878af34b1ad642a7f1d1": { + "balance": "200000000000000000000" + }, + "92aae59768eddff83cfe60bb512e730a05a161d7": { + "balance": "1708015000000000000000" + }, + "a5e93b49ea7c509de7c44d6cfeddef5910deaaf2": { + "balance": "2000000000000000000000" + }, + "e33d980220fab259af6a1f4b38cf0ef3c6e2ea1a": { + "balance": "2000000000000000000000" + }, + "8ed0af11ff2870da0681004afe18b013f7bd3882": { + "balance": "4000000000000000000000" + }, + "f23e5c633221a8f7363e65870c9f287424d2a960": { + "balance": "1380000000000000000000" + }, + "96334bfe04fffa590213eab36514f338b864b736": { + "balance": "400000000000000000000" + }, + "fa1f1971a775c3504fef5079f640c2c4bce7ac05": { + "balance": "2000000000000000000000" + }, + "df44c47fc303ac76e74f97194cca67b5bb3c023f": { + "balance": "591000000000000000000" + }, + "4b74f5e58e2edf76daf70151964a0b8f1de0663c": { + "balance": "324020000000000000000" + }, + "e38b91b35190b6d9deed021c30af094b953fdcaa": { + "balance": "33340000000000000000" + }, + "6b38de841fad7f53fe02da115bd86aaf662466bd": { + "balance": "1730000000000000000000" + }, + "11675a25554607a3b6c92a9ee8f36f75edd3e336": { + "balance": "159800000000000000000" + }, + "0ba8705bf55cf219c0956b5e3fc01c4474a6cdc1": { + "balance": "94963000000000000000" + }, + "0f05f120c89e9fbc93d4ab0c5e2b4a0df092b424": { + "balance": "30000000000000000000000" + }, + "fdd1195f797d4f35717d15e6f9810a9a3ff55460": { + "balance": "18200000000000000000" + }, + "63a61dc30a8e3b30a763c4213c801cbf98738178": { + "balance": "1000000000000000000000" + }, + "e5bdf34f4ccc483e4ca530cc7cf2bb18febe92b3": { + "balance": "126260000000000000000" + }, + "d6e09e98fe1300332104c1ca34fbfac554364ed9": { + "balance": "2000000000000000000000" + }, + "5bd6862d517d4de4559d4eec0a06cad05e2f946e": { + "balance": "200000000000000000000" + }, + "7294ec9da310bc6b4bbdf543b0ef45abfc3e1b4d": { + "balance": "22000000000000000000000" + }, + "ae34861d342253194ffc6652dfde51ab44cad3fe": { + "balance": "466215000000000000000" + }, + "f50ae7fab4cfb5a646ee04ceadf9bf9dd5a8e540": { + "balance": "3999952000000000000000" + }, + "dd2bdfa917c1f310e6fa35aa8af16939c233cd7d": { + "balance": "400000000000000000000" + }, + "e0060462c47ff9679baef07159cae08c29f274a9": { + "balance": "2000000000000000000000" + }, + "b7d12e84a2e4c4a6345af1dd1da9f2504a2a996e": { + "balance": "200000000000000000000" + }, + "f5500178cb998f126417831a08c2d7abfff6ab5f": { + "balance": "1308923000000000000000" + }, + "fd377a385272900cb436a3bb7962cdffe93f5dad": { + "balance": "2000000000000000000000" + }, + "a4a83a0738799b971bf2de708c2ebf911ca79eb2": { + "balance": "600000000000000000000" + }, + "52a5e4de4393eeccf0581ac11b52c683c76ea15d": { + "balance": "19999800000000000000000" + }, + "b07fdeaff91d4460fe6cd0e8a1b0bd8d22a62e87": { + "balance": "5260000000000000000000" + }, + "35f5860149e4bbc04b8ac5b272be55ad1aca58e0": { + "balance": "200000000000000000000" + }, + "fb135eb15a8bac72b69915342a60bbc06b7e077c": { + "balance": "20000000000000000000000" + }, + "02d4a30968a39e2b3498c3a6a4ed45c1c6646822": { + "balance": "2000000000000000000000" + }, + "e44b7264dd836bee8e87970340ed2b9aed8ed0a5": { + "balance": "5772100000000000000000" + }, + "e90a354cec04d69e5d96ddc0c5138d3d33150aa0": { + "balance": "499971000000000000000" + }, + "693d83be09459ef8390b2e30d7f7c28de4b4284e": { + "balance": "2000000000000000000000" + }, + "87bf7cd5d8a929e1c785f9e5449106ac232463c9": { + "balance": "77800000000000000000" + }, + "e5f8ef6d970636b0dcaa4f200ffdc9e75af1741c": { + "balance": "2000000000000000000000" + }, + "fef09d70243f39ed8cd800bf9651479e8f4aca3c": { + "balance": "200000000000000000000" + }, + "e98c91cadd924c92579e11b41217b282956cdaa1": { + "balance": "135800000000000000000" + }, + "c2836188d9a29253e0cbda6571b058c289a0bb32": { + "balance": "2000000000000000000000" + }, + "afa6946effd5ff53154f82010253df47ae280ccc": { + "balance": "1970000000000000000000" + }, + "43c7ebc5b3e7af16f47dc5617ab10e0f39b4afbb": { + "balance": "1910000000000000000000" + }, + "097ecda22567c2d91cb03f8c5215c22e9dcda949": { + "balance": "20055000000000000000" + }, + "3e66b84769566ab67945d5fa81373556bcc3a1fa": { + "balance": "152000000000000000000" + }, + "56373daab46316fd7e1576c61e6affcb6559ddd7": { + "balance": "215340000000000000000" + }, + "faaeba8fc0bbda553ca72e30ef3d732e26e82041": { + "balance": "1338337000000000000000" + }, + "f54c19d9ef3873bfd1f7a622d02d86249a328f06": { + "balance": "44284729000000000000000" + }, + "825309a7d45d1812f51e6e8df5a7b96f6c908887": { + "balance": "2365000000000000000000" + }, + "89009e3c6488bd5e570d1da34eabe28ed024de1b": { + "balance": "20000000000000000000000" + }, + "63977cad7d0dcdc52b9ac9f2ffa136e8642882b8": { + "balance": "75000000000000000000" + }, + "c239abdfae3e9af5457f52ed2b91fd0ab4d9c700": { + "balance": "2000000000000000000000" + }, + "1a4ec6a0ae7f5a9427d23db9724c0d0cffb2ab2f": { + "balance": "179000000000000000000" + }, + "a12a6c2d985daf0e4f5f207ae851aaf729b332cd": { + "balance": "100000000000000000000000" + }, + "cbe52fc533d7dd608c92a260b37c3f45deb4eb33": { + "balance": "1000000000000000000000" + }, + "abb2e6a72a40ba6ed908cdbcec3c5612583132fe": { + "balance": "1460000000000000000000" + }, + "6503860b191008c15583bfc88158099301762828": { + "balance": "1000000000000000000000" + }, + "a0228240f99e1de9cb32d82c0f2fa9a3d44b0bf3": { + "balance": "1600000000000000000000" + }, + "e154daeadb545838cbc6aa0c55751902f528682a": { + "balance": "4925000000000000000000" + }, + "8e92aba38e72a098170b92959246537a2e5556c0": { + "balance": "267400000000000000000" + }, + "d23d7affacdc3e9f3dae7afcb4006f58f8a44600": { + "balance": "3600000000000000000000" + }, + "00d78d89b35f472716eceafebf600527d3a1f969": { + "balance": "27750000000000000000000" + }, + "120f9de6e0af7ec02a07c609ca8447f157e6344c": { + "balance": "267400000000000000000" + }, + "e0352fdf819ba265f14c06a6315c4ac1fe131b2e": { + "balance": "1000000000000000000000" + }, + "8f47328ee03201c9d35ed2b5412b25decc859362": { + "balance": "2000000000000000000000" + }, + "453e359a3397944c5a275ab1a2f70a5e5a3f6989": { + "balance": "240000000000000000000" + }, + "9bf58efbea0784eb068adecfa0bb215084c73a35": { + "balance": "5800000000000000000000" + }, + "21bfe1b45cacde6274fd8608d9a178bf3eeb6edc": { + "balance": "2009400000000000000000" + }, + "d1d5b17ffe2d7bbb79cc7d7930bcb2e518fb1bbf": { + "balance": "3000000000000000000000" + }, + "20a29c5079e26b3f18318bb2e50e8e8b346e5be8": { + "balance": "499986000000000000000" + }, + "7d392852f3abd92ff4bb5bb26cb60874f2be6795": { + "balance": "1000070000000000000000" + }, + "55852943492970f8d629a15366cdda06a94f4513": { + "balance": "2000000000000000000000" + }, + "ab5dfc1ea21adc42cf8c3f6e361e243fd0da61e5": { + "balance": "300000000000000000000" + }, + "9d2bfc36106f038250c01801685785b16c86c60d": { + "balance": "380000000000000000000000" + }, + "6e60aee1a78f8eda8b424c73e353354ae67c3042": { + "balance": "3490300000000000000000" + }, + "7e29290038493559194e946d4e460b96fc38a156": { + "balance": "309072000000000000000" + }, + "6006e36d929bf45d8f16231b126a011ae283d925": { + "balance": "176000000000000000000" + }, + "d6d03572a45245dbd4368c4f82c95714bd2167e2": { + "balance": "1162200000000000000000" + }, + "d1432538e35b7664956ae495a32abdf041a7a21c": { + "balance": "19700000000000000000000" + }, + "2276264bec8526c0c0f270677abaf4f0e441e167": { + "balance": "1000000000000000000000" + }, + "c8814e34523e38e1f927a7dce8466a447a093603": { + "balance": "10000000000000000000000" + }, + "688a569e965524eb1d0ac3d3733eab909fb3d61e": { + "balance": "1320000000000000000000" + }, + "90dc09f717fc2a5b69fd60ba08ebf40bf4e8246c": { + "balance": "4000086000000000000000" + }, + "239a733e6b855ac592d663156186a8a174d2449e": { + "balance": "1637020000000000000000" + }, + "bcdfacb9d9023c3417182e9100e8ea1d373393a3": { + "balance": "59100000000000000000" + }, + "ba6440aeb3737b8ef0f1af9b0c15f4c214ffc7cf": { + "balance": "1000000000000000000000" + }, + "322e5c43b0f524389655a9b3ff24f2d4db3da10f": { + "balance": "4650000000000000000000" + }, + "be5a60689998639ad75bc105a371743eef0f7940": { + "balance": "501700000000000000000" + }, + "b727a9fc82e1cffc5c175fa1485a9befa2cdbdd1": { + "balance": "999000000000000000000" + }, + "a3883a24f7f166205f1a6a9949076c26a76e7178": { + "balance": "1820000000000000000000" + }, + "5e95fe5ffcf998f9f9ac0e9a81dab83ead77003d": { + "balance": "539766000000000000000" + }, + "e60955dc0bc156f6c41849f6bd776ba44b0ef0a1": { + "balance": "299982000000000000000" + }, + "af203e229d7e6d419df4378ea98715515f631485": { + "balance": "1970000000000000000000" + }, + "86499a1228ff2d7ee307759364506f8e8c8307a5": { + "balance": "1970000000000000000000" + }, + "1a04cec420ad432215246d77fe178d339ed0b595": { + "balance": "316000000000000000000" + }, + "cc2b5f448f3528d3fe41cc7d1fa9c0dc76f1b776": { + "balance": "60000000000000000000" + }, + "cb50587412822304ebcba07dab3a0f09fffee486": { + "balance": "1370000000000000000000" + }, + "4ae2a04d3909ef454e544ccfd614bfefa71089ae": { + "balance": "442800000000000000000" + }, + "c8a2c4e59e1c7fc54805580438aed3e44afdf00e": { + "balance": "44000000000000000000" + }, + "5792814f59a33a1843faa01baa089eb02ffb5cf1": { + "balance": "499986000000000000000" + }, + "a1f2854050f872658ed82e52b0ad7bbc1cb921f6": { + "balance": "2010918000000000000000" + }, + "92dca5e102b3b81b60f1a504634947c374a88ccb": { + "balance": "2000000000000000000000" + }, + "732fead60f7bfdd6a9dec48125e3735db1b6654f": { + "balance": "20000000000000000000" + }, + "6bf7b3c065f2c1e7c6eb092ba0d15066f393d1b8": { + "balance": "400000000000000000000" + }, + "cde36d81d128c59da145652193eec2bfd96586ef": { + "balance": "4000000000000000000000" + }, + "40eddb448d690ed72e05c225d34fc8350fa1e4c5": { + "balance": "7000000000000000000000" + }, + "454b61b344c0ef965179238155f277c3829d0b38": { + "balance": "2000000000000000000000" + }, + "ac3da526cfce88297302f34c49ca520dc271f9b2": { + "balance": "800000000000000000000" + }, + "c989eec307e8839b9d7237cfda08822962abe487": { + "balance": "400000000000000000000" + }, + "e99de258a4173ce9ac38ede26c0b3bea3c0973d5": { + "balance": "1656800000000000000000" + }, + "ff0cb06c42e3d88948e45bd7b0d4e291aefeea51": { + "balance": "1910000000000000000000" + }, + "0990e81cd785599ea236bd1966cf526302c35b9c": { + "balance": "1000000000000000000000" + }, + "6da0ed8f1d69339f059f2a0e02471cb44fb8c3bb": { + "balance": "935900000000000000000" + }, + "5d958a9bd189c2985f86c58a8c69a7a78806e8da": { + "balance": "10200000000000000000000" + }, + "98be696d51e390ff1c501b8a0f6331b628ddc5ad": { + "balance": "2000000000000000000000" + }, + "09d0b8cd077c69d9f32d9cca43b3c208a21ed48b": { + "balance": "150011000000000000000" + }, + "96e7c0c9d5bf10821bf140c558a145b7cac21397": { + "balance": "1056000000000000000000" + }, + "5b736eb18353629bde9676dadd165034ce5ecc68": { + "balance": "1970000000000000000000" + }, + "e5a365343cc4eb1e770368e1f1144a77b832d7e0": { + "balance": "20000000000000000000" + }, + "4cf5537b85842f89cfee359eae500fc449d2118f": { + "balance": "1000000000000000000000" + }, + "c71f1d75873f33dcb2dd4b3987a12d0791a5ce27": { + "balance": "1015200000000000000000" + }, + "9bf703b41c3624e15f4054962390bcba3052f0fd": { + "balance": "6055000000000000000000" + }, + "145e1de0147911ccd880875fbbea61f6a142d11d": { + "balance": "4000000000000000000000" + }, + "68419c6dd2d3ce6fcbb3c73e2fa079f06051bde6": { + "balance": "1970000000000000000000" + }, + "d8eb78503ec31a54a90136781ae109004c743257": { + "balance": "1000000000000000000000" + }, + "f25e4c70bc465632c89e5625a832a7722f6bffab": { + "balance": "4488000000000000000000" + }, + "7b4d2a38269069c18557770d591d24c5121f5e83": { + "balance": "700000000000000000000" + }, + "27d158ac3d3e1109ab6e570e90e85d3892cd7680": { + "balance": "100000000000000000000" + }, + "d3679a47df2d99a49b01c98d1c3e0c987ce1e158": { + "balance": "280000000000000000000" + }, + "095b949de3333a377d5019d893754a5e4656ff97": { + "balance": "340000000000000000000" + }, + "6b17598a8ef54f797ae515ccb6517d1859bf8011": { + "balance": "100000000000000000000" + }, + "3eaf0879b5b6db159b589f84578b6a74f6c10357": { + "balance": "7253657000000000000000" + }, + "40d45d9d7625d15156c932b771ca7b0527130958": { + "balance": "100000000000000000000000" + }, + "0392549a727f81655429cb928b529f25df4d1385": { + "balance": "26248000000000000000" + }, + "c5b009baeaf788a276bd35813ad65b400b849f3b": { + "balance": "1000000000000000000000" + }, + "6ed884459f809dfa1016e770edaf3e9fef46fa30": { + "balance": "3400170000000000000000" + }, + "439d2f2f5110a4d58b1757935015408740fec7f8": { + "balance": "3830421000000000000000" + }, + "dc46c13325cd8edf0230d068896486f007bf4ef1": { + "balance": "1337000000000000000000" + }, + "8c54c7f8b9896e75d7d5f5c760258699957142ad": { + "balance": "40000000000000000000" + }, + "61c8f1fa43bf846999ecf47b2b324dfb6b63fe3a": { + "balance": "800000000000000000000" + }, + "935069444a6a984de2084e46692ab99f671fc727": { + "balance": "9000000000000000000000" + }, + "fc49c1439a41d6b3cf26bb67e0365224e5e38f5f": { + "balance": "1000076000000000000000" + }, + "e1dfb5cc890ee8b2877e885d267c256187d019e6": { + "balance": "100000000000000000000" + }, + "ee7c3ded7c28f459c92fe13b4d95bafbab02367d": { + "balance": "700000000000000000000" + }, + "a5874d754635a762b381a5c4c792483af8f23d1d": { + "balance": "50000000000000000000" + }, + "cfbb32b7d024350e3321fa20c9a914035372ffc6": { + "balance": "401100000000000000000" + }, + "2bc429d618a66a4cf82dbb2d824e9356effa126a": { + "balance": "1999944000000000000000" + }, + "db244f97d9c44b158a40ed9606d9f7bd38913331": { + "balance": "102000000000000000000" + }, + "55e220876262c218af4f56784798c7e55da09e91": { + "balance": "133566000000000000000" + }, + "ca41ccac30172052d522cd2f2f957d248153409f": { + "balance": "1970000000000000000000" + }, + "b11fa7fb270abcdf5a2eab95aa30c4b53636efbf": { + "balance": "800000000000000000000" + }, + "0ffea06d7113fb6aec2869f4a9dfb09007facef4": { + "balance": "225416000000000000000" + }, + "646628a53c2c4193da88359ce718dadd92b7a48d": { + "balance": "200032000000000000000" + }, + "ca8409083e01b397cf12928a05b68455ce6201df": { + "balance": "1600000000000000000000" + }, + "dbbcbb79bf479a42ad71dbcab77b5adfaa872c58": { + "balance": "1730000000000000000000" + }, + "db7d4037081f6c65f9476b0687d97f1e044d0a1d": { + "balance": "660000000000000000000" + }, + "4be90d412129d5a4d0424361d6649d4e47a62316": { + "balance": "1015200000000000000000" + }, + "e3ab3ca9b870e3f548517306bba4de2591afafc2": { + "balance": "1200062000000000000000" + }, + "5c61ab79b408dd3229f662593705d72f1e147bb8": { + "balance": "22729000000000000000000" + }, + "4f177f9d56953ded71a5611f393322c30279895c": { + "balance": "246000000000000000000" + }, + "e6cb260b716d4c0ab726eeeb07c8707204e276ae": { + "balance": "1000000000000000000000" + }, + "44355253b27748e3f34fe9cae1fb718c8f249529": { + "balance": "200000000000000000000" + }, + "a309df54cabce70c95ec3033149cd6678a6fd4cf": { + "balance": "223600000000000000000" + }, + "ec4867d2175ab5b9469361595546554684cda460": { + "balance": "3000000000000000000000" + }, + "8d06e464245cad614939e0af0845e6d730e20374": { + "balance": "200359000000000000000" + }, + "9810e34a94db6ed156d0389a0e2b80f4fd6b0a8a": { + "balance": "2000000000000000000000" + }, + "dcfff3e8d23c2a34b56bd1b3bd45c79374432239": { + "balance": "5000000000000000000000" + }, + "7d7dd5ee614dbb6fbfbcd26305247a058c41faa1": { + "balance": "2000000000000000000000" + }, + "8a9eca9c5aba8e139f8003edf1163afb70aa3aa9": { + "balance": "660000000000000000000" + }, + "d942de4784f7a48716c0fd4b9d54a6e54c5f2f3e": { + "balance": "20000000000000000000000" + }, + "07dae622630d1136381933d2ad6b22b839d82102": { + "balance": "200000000000000000000" + }, + "abf12fa19e82f76c718f01bdca0003674523ef30": { + "balance": "2000000000000000000000" + }, + "411c831cc6f44f1965ec5757ab4e5b3ca4cffd1f": { + "balance": "425000000000000000000" + }, + "99129d5b3c0cde47ea0def4dfc070d1f4a599527": { + "balance": "2000000000000000000000" + }, + "c5cdcee0e85d117dabbf536a3f4069bf443f54e7": { + "balance": "1969606000000000000000" + }, + "f218bd848ee7f9d38bfdd1c4eb2ed2496ae4305f": { + "balance": "500000000000000000000" + }, + "fe549bbfe64740189892932538daaf46d2b61d4f": { + "balance": "40000000000000000000" + }, + "dc3f0e7672f71fe7525ba30b9755183a20b9166a": { + "balance": "9603617000000000000000" + }, + "0e83b850481ab44d49e0a229a2e464902c69539b": { + "balance": "100000000000000000000" + }, + "07ddd0422c86ef65bf0c7fc3452862b1228b08b8": { + "balance": "2065302000000000000000" + }, + "a68c313445c22d919ee46cc2d0cdff043a755825": { + "balance": "75189000000000000000" + }, + "a9e9dbce7a2cb03694799897bed7c54d155fdaa8": { + "balance": "197559000000000000000" + }, + "18fccf62d2c3395453b7587b9e26f5cff9eb7482": { + "balance": "1000000000000000000000" + }, + "ff41d9e1b4effe18d8b0d1f63fc4255fb4e06c3d": { + "balance": "1337000000000000000000" + }, + "8f69eafd0233cadb4059ab779c46edf2a0506e48": { + "balance": "1788210000000000000000" + }, + "9aa48c66e4fb4ad099934e32022e827427f277ba": { + "balance": "10000000000000000000000" + }, + "f46980e3a4a9d29a6a6e90604537a3114bcb2897": { + "balance": "500000000000000000000" + }, + "801732a481c380e57ed62d6c29de998af3fa3b13": { + "balance": "100000000000000000000" + }, + "0cd6a141918d126b106d9f2ebf69e102de4d3277": { + "balance": "20000000000000000000" + }, + "17589a6c006a54cad70103123aae0a82135fdeb4": { + "balance": "4000000000000000000000" + }, + "8725e8c753b3acbfdca55f3c62dfe1a59454968a": { + "balance": "1000090000000000000000" + }, + "d20dcb0b78682b94bc3000281448d557a20bfc83": { + "balance": "895000000000000000000" + }, + "e84f8076a0f2969ecd333eef8de41042986291f2": { + "balance": "432000000000000000000" + }, + "b3145b74506d1a8d047cdcdc55392a7b5350799a": { + "balance": "129314663000000000000000" + }, + "0d9a825ff2bcd397cbad5b711d9dcc95f1cc112d": { + "balance": "12800000000000000000000" + }, + "0ca670eb2c8b96cba379217f5929c2b892f39ef6": { + "balance": "2000000000000000000000" + }, + "25cfc4e25c35c13b69f7e77dbfb08baf58756b8d": { + "balance": "40000000000000000000000" + }, + "182db85293f606e88988c3704cb3f0c0bbbfca5a": { + "balance": "133700000000000000000" + }, + "bd73c3cbc26a175062ea0320dd84b253bce64358": { + "balance": "394000000000000000000" + }, + "2680713d40808e2a50ed013150a2a694b96a7f1d": { + "balance": "1790000000000000000000" + }, + "51e32f14f4ca5e287cdac057a7795ea9e0439953": { + "balance": "500000000000000000000" + }, + "b1e9c5f1d21e61757a6b2ee75913fc5a1a4101c3": { + "balance": "2000000000000000000000" + }, + "d4c4d1a7c3c74984f6857b2f5f07e8face68056d": { + "balance": "2000000000000000000000" + }, + "4651dc420e08c3293b27d2497890eb50223ae2f4": { + "balance": "20000000000000000000000" + }, + "c74a3995f807de1db01a2eb9c62e97d0548f696f": { + "balance": "1000000000000000000000" + }, + "0505a08e22a109015a22f685305354662a5531d5": { + "balance": "2600000000000000000000" + }, + "39c773367c8825d3596c686f42bf0d14319e3f84": { + "balance": "133700000000000000000" + }, + "0f929cf895db017af79f3ead2216b1bd69c37dc7": { + "balance": "2000000000000000000000" + }, + "bdd3254e1b3a6dc6cc2c697d45711aca21d516b2": { + "balance": "2000000000000000000000" + }, + "ae5d221afcd3d29355f508eadfca408ce33ca903": { + "balance": "100000000000000000000000" + }, + "916cf17d71412805f4afc3444a0b8dd1d9339d16": { + "balance": "14300000000000000000" + }, + "4319263f75402c0b5325f263be4a5080651087f0": { + "balance": "983086000000000000000" + }, + "0f1c249cd962b00fd114a9349f6a6cc778d76c4d": { + "balance": "2000000000000000000000" + }, + "54febcce20fe7a9098a755bd90988602a48c089e": { + "balance": "640000000000000000000" + }, + "2c1800f35fa02d3eb6ff5b25285f5e4add13b38d": { + "balance": "906400000000000000000" + }, + "72b904440e90e720d6ac1c2ad79c321dcc1c1a86": { + "balance": "1550000000000000000000" + }, + "b0aa00950c0e81fa3210173e729aaf163a27cd71": { + "balance": "40000000000000000000000" + }, + "663604b0503046e624cd26a8b6fb4742dce02a6f": { + "balance": "65400000000000000000" + }, + "3c98594bf68b57351e8814ae9e6dfd2d254aa06f": { + "balance": "300000000000000000000" + }, + "9c45202a25f6ad0011f115a5a72204f2f2198866": { + "balance": "5014000000000000000000" + }, + "b02d062873334545cea29218e4057760590f7423": { + "balance": "3186000000000000000000" + }, + "7bddb2ee98de19ee4c91f661ee8e67a91d054b97": { + "balance": "1000000000000000000000" + }, + "9cf2928beef09a40f9bfc953be06a251116182fb": { + "balance": "6000000000000000000000" + }, + "51b4758e9e1450e7af4268c3c7b1e7bd6f5c7550": { + "balance": "1000000000000000000000" + }, + "eb570dba975227b1c42d6e8dea2c56c9ad960670": { + "balance": "2000000000000000000000" + }, + "970d8b8a0016d143054f149fb3b8e550dc0797c7": { + "balance": "1000000000000000000000" + }, + "c7b39b060451000ca1049ba154bcfa00ff8af262": { + "balance": "100000000000000000000000" + }, + "945e18769d7ee727c7013f92de24d117967ff317": { + "balance": "2000000000000000000000" + }, + "d18eb9e1d285dabe93e5d4bae76beefe43b521e8": { + "balance": "668500000000000000000" + }, + "c618521321abaf5b26513a4a9528086f220adc6f": { + "balance": "27000000000000000000" + }, + "dd65f6e17163b5d203641f51cc7b24b00f02c8fb": { + "balance": "200000000000000000000" + }, + "131faed12561bb7aee04e5185af802b1c3438d9b": { + "balance": "219000000000000000000" + }, + "1ced6715f862b1ff86058201fcce5082b36e62b2": { + "balance": "6684522000000000000000" + }, + "a0ff5b4cf016027e8323497d4428d3e5a83b8795": { + "balance": "6596500000000000000000" + }, + "02e816afc1b5c0f39852131959d946eb3b07b5ad": { + "balance": "1000000000000000000000" + }, + "153cf2842cb9de876c276fa64767d1a8ecf573bb": { + "balance": "2000000000000000000000" + }, + "3bc6e3ee7a56ce8f14a37532590f63716b9966e8": { + "balance": "2000000000000000000000" + }, + "f6d25d3f3d846d239f525fa8cac97bc43578dbac": { + "balance": "896000000000000000000" + }, + "2066774d822793ff25f1760909479cf62491bf88": { + "balance": "55160000000000000000000" + }, + "46779a5656ff00d73eac3ad0c38b6c853094fb40": { + "balance": "230752000000000000000" + }, + "22eed327f8eb1d1338a3cb7b0f8a4baa5907cd95": { + "balance": "23445000000000000000" + }, + "ff88ebacc41b3687f39e4b59e159599b80cba33f": { + "balance": "400000000000000000000" + }, + "2874f3e2985d5f7b406627e17baa772b01abcc9e": { + "balance": "6014000000000000000000" + }, + "eb10458daca79e4a6b24b29a8a8ada711b7f2eb6": { + "balance": "3998000000000000000000" + }, + "541060fc58c750c40512f83369c0a63340c122b6": { + "balance": "1970000000000000000000" + }, + "fd2757cc3551a095878d97875615fe0c6a32aa8a": { + "balance": "598200000000000000000" + }, + "be659d85e7c34f8833ea7f488de1fbb5d4149bef": { + "balance": "9072500000000000000000" + }, + "e149b5726caf6d5eb5bf2acc41d4e2dc328de182": { + "balance": "1940000000000000000000" + }, + "2fe0cc424b53a31f0916be08ec81c50bf8eab0c1": { + "balance": "600000000000000000000" + }, + "e3712701619ca7623c55db3a0ad30e867db0168b": { + "balance": "20000000000000000000" + }, + "f8ca336c8e91bd20e314c20b2dd4608b9c8b9459": { + "balance": "846000000000000000000" + }, + "68acdaa9fb17d3c309911a77b05f5391fa034ee9": { + "balance": "8950000000000000000000" + }, + "e77d7deab296c8b4fa07ca3be184163d5a6d606c": { + "balance": "92538000000000000000" + }, + "e6b9545f7ed086e552924639f9a9edbbd5540b3e": { + "balance": "3760000000000000000000" + }, + "2866b81decb02ee70ae250cee5cdc77b59d7b679": { + "balance": "2000000000000000000000" + }, + "60e3cc43bcdb026aad759c7066f555bbf2ac66f5": { + "balance": "2000000000000000000000" + }, + "fcbd85feea6a754fcf3449449e37ff9784f7773c": { + "balance": "3086000000000000000000" + }, + "38a744efa6d5c2137defef8ef9187b649eee1c78": { + "balance": "4000000000000000000000" + }, + "9d7655e9f3e5ba5d6e87e412aebe9ee0d49247ee": { + "balance": "2620100000000000000000" + }, + "2020b81ae53926ace9f7d7415a050c031d585f20": { + "balance": "341200000000000000000" + }, + "4244f1331158b9ce26bbe0b9236b9203ca351434": { + "balance": "10000000000000000000000" + }, + "99c236141daec837ece04fdaee1d90cf8bbdc104": { + "balance": "2184000000000000000000" + }, + "943d37864a4a537d35c8d99723cd6406ce2562e6": { + "balance": "2000000000000000000000" + }, + "d79483f6a8444f2549d611afe02c432d15e11051": { + "balance": "20000000000000000000" + }, + "9fd64373f2fbcd9c0faca60547cad62e26d9851f": { + "balance": "1000000000000000000000" + }, + "b89c036ed7c492879921be41e10ca1698198a74c": { + "balance": "1820000000000000000000" + }, + "7462c89caa9d8d7891b2545def216f7464d5bb21": { + "balance": "109162000000000000000" + }, + "bb0366a7cfbd3445a70db7fe5ae34885754fd468": { + "balance": "6160000000000000000000" + }, + "6c52cf0895bb35e656161e4dc46ae0e96dd3e62c": { + "balance": "4000086000000000000000" + }, + "b9cf71b226583e3a921103a5316f855a65779d1b": { + "balance": "24000000000000000000000" + }, + "016b60bb6d67928c29fd0313c666da8f1698d9c5": { + "balance": "2000000000000000000000" + }, + "9454b3a8bff9709fd0e190877e6cb6c89974dbd6": { + "balance": "2674000000000000000000" + }, + "84aac7fa197ff85c30e03b7a5382b957f41f3afb": { + "balance": "157600000000000000000" + }, + "db6e560c9bc620d4bea3a94d47f7880bf47f2d5f": { + "balance": "89500000000000000000" + }, + "eefd05b0e3c417d55b3343060486cdd5e92aa7a6": { + "balance": "1430000000000000000000" + }, + "3a59a08246a8206f8d58f70bb1f0d35c5bcc71bd": { + "balance": "185000000000000000000" + }, + "9bfff50db36a785555f07652a153b0c42b1b8b76": { + "balance": "2000000000000000000000" + }, + "d44f5edf2bcf2433f211dadd0cc450db1b008e14": { + "balance": "267400000000000000000" + }, + "2378fd4382511e968ed192106737d324f454b535": { + "balance": "1000000000000000000000" + }, + "c94089553ae4c22ca09fbc98f57075cf2ec59504": { + "balance": "4000000000000000000000" + }, + "08ef3fa4c43ccdc57b22a4b9b2331a82e53818f2": { + "balance": "4000000000000000000000" + }, + "e48e65125421880d42bdf1018ab9778d96928f3f": { + "balance": "4200000000000000000000" + }, + "67518e5d02b205180f0463a32004471f753c523e": { + "balance": "1984289000000000000000" + }, + "0da7401262384e2e8b4b26dd154799b55145efa0": { + "balance": "300000000000000000000" + }, + "0b6920a64b363b8d5d90802494cf564b547c430d": { + "balance": "1200000000000000000000" + }, + "a5ab4bd3588f46cb272e56e93deed386ba8b753d": { + "balance": "1332989000000000000000" + }, + "1788da9b57fd05edc4ff99e7fef301519c8a0a1e": { + "balance": "2000000000000000000000" + }, + "17b2d6cf65c6f4a347ddc6572655354d8a412b29": { + "balance": "2000000000000000000000" + }, + "d0319139fbab2e8e2accc1d924d4b11df6696c5a": { + "balance": "200000000000000000000" + }, + "4c377bb03ab52c4cb79befa1dd114982924c4ae9": { + "balance": "1827814000000000000000" + }, + "fb949c647fdcfd2514c7d58e31f28a532d8c5833": { + "balance": "20000000000000000000000" + }, + "70e5e9da735ff077249dcb9aaf3db2a48d9498c0": { + "balance": "1000000000000000000000" + }, + "fe6f5f42b6193b1ad16206e4afb5239d4d7db45e": { + "balance": "1730000000000000000000" + }, + "bda4be317e7e4bed84c0495eee32d607ec38ca52": { + "balance": "2309457000000000000000" + }, + "5910106debd291a1cd80b0fbbb8d8d9e93a7cc1e": { + "balance": "2000000000000000000000" + }, + "ba42f9aace4c184504abf5425762aca26f71fbdc": { + "balance": "37400000000000000000" + }, + "beb4fd315559436045dcb99d49dcec03f40c42dc": { + "balance": "2000000000000000000000" + }, + "452b64db8ef7d6df87c788639c2290be8482d575": { + "balance": "8000000000000000000000" + }, + "66e09427c1e63deed7e12b8c55a6a19320ef4b6a": { + "balance": "170000000000000000000" + }, + "faad905d847c7b23418aeecbe3addb8dd3f8924a": { + "balance": "1970000000000000000000" + }, + "a29319e81069e5d60df00f3de5adee3505ecd5fb": { + "balance": "2000000000000000000000" + }, + "cf348f2fe47b7e413c077a7baf3a75fbf8428692": { + "balance": "2000000000000000000000" + }, + "e1e8c50b80a352b240ce7342bbfdf5690cc8cb14": { + "balance": "394000000000000000000" + }, + "131c792c197d18bd045d7024937c1f84b60f4438": { + "balance": "4000000000000000000000" + }, + "e49af4f34adaa2330b0e49dc74ec18ab2f92f827": { + "balance": "2000000000000000000000" + }, + "f2e99f5cbb836b7ad36247571a302cbe4b481c69": { + "balance": "1970000000000000000000" + }, + "c93fbde8d46d2bcc0fa9b33bd8ba7f8042125565": { + "balance": "1400000000000000000000" + }, + "038779ca2dbe663e63db3fe75683ea0ec62e2383": { + "balance": "1670000000000000000000" + }, + "a33cb450f95bb46e25afb50fe05feee6fb8cc8ea": { + "balance": "776000000000000000000" + }, + "40ab66fe213ea56c3afb12c75be33f8e32fd085d": { + "balance": "4000000000000000000000" + }, + "6403d062549690c8e8b63eae41d6c109476e2588": { + "balance": "2000000000000000000000" + }, + "bfb0ea02feb61dec9e22a5070959330299c43072": { + "balance": "20000000000000000000000" + }, + "99c475bf02e8b9214ada5fad02fdfd15ba365c0c": { + "balance": "591000000000000000000" + }, + "904966cc2213b5b8cb5bd6089ef9cddbef7edfcc": { + "balance": "2000000000000000000000" + }, + "767a03655af360841e810d83f5e61fb40f4cd113": { + "balance": "985000000000000000000" + }, + "ab209fdca979d0a647010af9a8b52fc7d20d8cd1": { + "balance": "9129000000000000000000" + }, + "6294eae6e420a3d5600a39c4141f838ff8e7cc48": { + "balance": "2955000000000000000000" + }, + "9777cc61cf756be3b3c20cd4491c69d275e7a120": { + "balance": "10000000000000000000000" + }, + "bcbf6ba166e2340db052ea23d28029b0de6aa380": { + "balance": "3880000000000000000000" + }, + "9f10f2a0463b65ae30b070b3df18cf46f51e89bd": { + "balance": "1910000000000000000000" + }, + "8d9952d0bb4ebfa0efd01a3aa9e8e87f0525742e": { + "balance": "3460000000000000000000" + }, + "4f23b6b817ffa5c664acdad79bb7b726d30af0f9": { + "balance": "1760000000000000000000" + }, + "b4c20040ccd9a1a3283da4d4a2f365820843d7e2": { + "balance": "1000000000000000000000" + }, + "7f49e7a4269882bd8722d4a6f566347629624079": { + "balance": "2000000000000000000000" + }, + "33629bd52f0e107bc071176c64df108f64777d49": { + "balance": "33425000000000000000" + }, + "6a7b2e0d88867ff15d207c222bebf94fa6ce8397": { + "balance": "60000000000000000000000" + }, + "b7ce684b09abda53389a875369f71958aeac3bdd": { + "balance": "2000000000000000000000" + }, + "ffbc3da0381ec339c1c049eb1ed9ee34fdcea6ca": { + "balance": "4000000000000000000000" + }, + "849ab80790b28ff1ffd6ba394efc7463105c36f7": { + "balance": "34600000000000000000" + }, + "b0b36af9aeeedf97b6b02280f114f13984ea3260": { + "balance": "985000000000000000000" + }, + "4d57e716876c0c95ef5eaebd35c8f41b069b6bfe": { + "balance": "2000000000000000000000" + }, + "2d2b032359b363964fc11a518263bfd05431e867": { + "balance": "149600000000000000000" + }, + "2ccc1f1cb5f4a8002e186b20885d9dbc030c0894": { + "balance": "2000000000000000000000" + }, + "016c85e1613b900fa357b8283b120e65aefcdd08": { + "balance": "799954000000000000000" + }, + "710b0274d712c77e08a5707d6f3e70c0ce3d92cf": { + "balance": "6400000000000000000000" + }, + "3cd3a6e93579c56d494171fc533e7a90e6f59464": { + "balance": "2000000000000000000000" + }, + "fe0e30e214290d743dd30eb082f1f0a5225ade61": { + "balance": "200000000000000000000" + }, + "d0718520eae0a4d62d70de1be0ca431c5eea2482": { + "balance": "2000000000000000000000" + }, + "af7f79cb415a1fb8dbbd094607ee8d41fb7c5a3b": { + "balance": "10000000000000000000000" + }, + "b7d252ee9402b0eef144295f0e69f0db586c0871": { + "balance": "660000000000000000000" + }, + "c3b928a76fad6578f04f0555e63952cd21d1520a": { + "balance": "2000000000000000000000" + }, + "a7a517d7ad35820b09d497fa7e5540cde9495853": { + "balance": "2000000000000000000000" + }, + "e6e886317b6a66a5b4f81bf164c538c264351765": { + "balance": "2000000000000000000000" + }, + "0770b43dbae4b1f35a927b4fa8124d3866caf97b": { + "balance": "1016390000000000000000" + }, + "52b4257cf41b6e28878d50d57b99914ffa89873a": { + "balance": "3930150000000000000000" + }, + "e08bc29c2b48b169ff2bdc16714c586e6cb85ccf": { + "balance": "20000000000000000000" + }, + "2372c4c1c9939f7aaf6cfac04090f00474840a09": { + "balance": "10000000000000000000000" + }, + "ab6b65eab8dfc917ec0251b9db0ecfa0fa032849": { + "balance": "500000000000000000000" + }, + "582e7cc46f1d7b4e6e9d95868bfd370573178f4c": { + "balance": "2000000000000000000000" + }, + "f167f5868dcf4233a7830609682caf2df4b1b807": { + "balance": "2396150000000000000000" + }, + "ec82f50d06475f684df1b392e00da341aa145444": { + "balance": "2000000000000000000000" + }, + "0968ee5a378f8cadb3bafdbed1d19aaacf936711": { + "balance": "1000000000000000000000" + }, + "a86613e6c4a4c9c55f5c10bcda32175dcbb4af60": { + "balance": "10696140000000000000000" + }, + "a5cd123992194b34c4781314303b03c54948f4b9": { + "balance": "2010462000000000000000" + }, + "52f058d46147e9006d29bf2c09304ad1cddd6e15": { + "balance": "1500000000000000000000" + }, + "160226efe7b53a8af462d117a0108089bdecc2d1": { + "balance": "200550000000000000000" + }, + "256292a191bdda34c4da6b6bd69147bf75e2a9ab": { + "balance": "14051000000000000000" + }, + "1b8aa0160cd79f005f88510a714913d70ad3be33": { + "balance": "201760000000000000000" + }, + "d4b2ff3bae1993ffea4d3b180231da439f7502a2": { + "balance": "2000000000000000000000" + }, + "e408aa99835307eea4a6c5eb801fe694117f707d": { + "balance": "500000000000000000000" + }, + "e60a55f2df996dc3aedb696c08dde039b2641de8": { + "balance": "2000000000000000000000" + }, + "73df3c3e7955f4f2d859831be38000b1076b3884": { + "balance": "1970000000000000000000" + }, + "6228ade95e8bb17d1ae23bfb0518414d497e0eb8": { + "balance": "400000000000000000000" + }, + "0f46c81db780c1674ac73d314f06539ee56ebc83": { + "balance": "9850000000000000000000" + }, + "762d6f30dab99135e4eca51d5243d6c8621102d5": { + "balance": "282000000000000000000" + }, + "4ba0d9e89601772b496847a2bb4340186787d265": { + "balance": "1000000000000000000000" + }, + "ca747576446a4c8f30b08340fee198de63ec92cf": { + "balance": "7020000000000000000000" + }, + "99c31fe748583787cdd3e525b281b218961739e3": { + "balance": "1015200000000000000000" + }, + "1210f80bdb826c175462ab0716e69e46c24ad076": { + "balance": "100000000000000000000" + }, + "3f75ae61cc1d8042653b5baec4443e051c5e7abd": { + "balance": "95500000000000000000" + }, + "5c4892907a0720df6fd3413e63ff767d6b398023": { + "balance": "13189467000000000000000" + }, + "17f14632a7e2820be6e8f6df823558283dadab2d": { + "balance": "2000000000000000000000" + }, + "1dc7f7dad85df53f1271152403f4e1e4fdb3afa0": { + "balance": "200000000000000000000" + }, + "5a30feac37ac9f72d7b4af0f2bc73952c74fd5c3": { + "balance": "2000000000000000000000" + }, + "136d4b662bbd1080cfe4445b0fa213864435b7f1": { + "balance": "4000000000000000000000" + }, + "c1ec81dd123d4b7c2dd9b4d438a7072c11dc874c": { + "balance": "2000000000000000000000" + }, + "09f9575be57d004793c7a4eb84b71587f97cbb6a": { + "balance": "200000000000000000000" + }, + "2c4b470307a059854055d91ec3794d80b53d0f4a": { + "balance": "20000000000000000000000" + }, + "6af6c7ee99df271ba15bf384c0b764adcb4da182": { + "balance": "999972000000000000000" + }, + "0dae3ee5b915b36487f9161f19846d101433318a": { + "balance": "1910000000000000000000" + }, + "0dcf9d8c9804459f647c14138ed50fad563b4154": { + "balance": "173000000000000000000" + }, + "bfa8c858df102cb12421008b0a31c4c7190ad560": { + "balance": "200000000000000000000" + }, + "c2fd0bf7c725ef3e047e5ae1c29fe18f12a7299c": { + "balance": "1337000000000000000000" + }, + "d70a612bd6dda9eab0dddcff4aaf4122d38feae4": { + "balance": "540000000000000000000" + }, + "e07137ae0d116d033533c4eab496f8a9fb09569c": { + "balance": "1400000000000000000000" + }, + "7f49f20726471ac1c7a83ef106e9775ceb662566": { + "balance": "5910000000000000000000" + }, + "1e706655e284dcf0bb37fe075d613a18dc12ff4a": { + "balance": "4376760000000000000000" + }, + "03af7ad9d5223cf7c8c13f20df67ebe5ffc5bb41": { + "balance": "200000000000000000000" + }, + "228242f8336eecd8242e1f000f41937e71dffbbf": { + "balance": "5000000000000000000000" + }, + "e8ed51bbb3ace69e06024b33f86844c47348db9e": { + "balance": "165170600000000000000000" + }, + "3b566a8afad19682dc2ce8679a3ce444a5b0fd4f": { + "balance": "2000000000000000000000" + }, + "dc738fb217cead2f69594c08170de1af10c419e3": { + "balance": "100000000000000000000000" + }, + "13032446e7d610aa00ec8c56c9b574d36ca1c016": { + "balance": "2000000000000000000000" + }, + "6ca6a132ce1cd288bee30ec7cfeffb85c1f50a54": { + "balance": "2000000000000000000000" + }, + "b85f26dd0e72d9c29ebaf697a8af77472c2b58b5": { + "balance": "11900000000000000000000" + }, + "055bd02caf19d6202bbcdc836d187bd1c01cf261": { + "balance": "100000000000000000000" + }, + "3c322e611fdb820d47c6f8fc64b6fad74ca95f5e": { + "balance": "242514000000000000000" + }, + "8daddf52efbd74da95b969a5476f4fbbb563bfd2": { + "balance": "835000000000000000000" + }, + "c63ac417992e9f9b60386ed953e6d7dff2b090e8": { + "balance": "4000086000000000000000" + }, + "27f03cf1abc5e1b51dbc444b289e542c9ddfb0e6": { + "balance": "5000000000000000000000" + }, + "d8f4bae6f84d910d6d7d5ac914b1e68372f94135": { + "balance": "100000000000000000000" + }, + "9f83a293c324d4106c18faa8888f64d299054ca0": { + "balance": "200000000000000000000" + }, + "39ee4fe00fbced647068d4f57c01cb22a80bccd1": { + "balance": "6000000000000000000000" + }, + "404100db4c5d0eec557823b58343758bcc2c8083": { + "balance": "20000000000000000000" + }, + "02751dc68cb5bd737027abf7ddb77390cd77c16b": { + "balance": "20000000000000000000" + }, + "d10302faa1929a326904d376bf0b8dc93ad04c4c": { + "balance": "1790000000000000000000" + }, + "cc419fd9912b85135659e77a93bc3df182d45115": { + "balance": "10000000000000000000000" + }, + "10097198b4e7ee91ff82cc2f3bd95fed73c540c0": { + "balance": "2000000000000000000000" + }, + "7e24d9e22ce1da3ce19f219ccee523376873f367": { + "balance": "5900150000000000000000" + }, + "2e4ee1ae996aa0a1d92428d06652a6bea6d2d15d": { + "balance": "2000000000000000000000" + }, + "91a4149a2c7b1b3a67ea28aff34725e0bf8d7524": { + "balance": "1940000000000000000000" + }, + "ead65262ed5d122df2b2751410f98c32d1238f51": { + "balance": "101680000000000000000" + }, + "e20954d0f4108c82d4dcb2148d26bbd924f6dd24": { + "balance": "10000000000000000000000" + }, + "ebb7d2e11bc6b58f0a8d45c2f6de3010570ac891": { + "balance": "26740000000000000000" + }, + "ef115252b1b845cd857f002d630f1b6fa37a4e50": { + "balance": "1970000000000000000000" + }, + "01a818135a414210c37c62b625aca1a54611ac36": { + "balance": "260000000000000000000" + }, + "ea1ea0c599afb9cd36caacbbb52b5bbb97597377": { + "balance": "1069600000000000000000" + }, + "7a7a4f807357a4bbe68e1aa806393210c411ccb3": { + "balance": "30000000000000000000000" + }, + "6d40ca27826d97731b3e86effcd7b92a4161fe89": { + "balance": "2000000000000000000000" + }, + "8431277d7bdd10457dc017408c8dbbbd414a8df3": { + "balance": "39400000000000000000" + }, + "69b81d5981141ec7a7141060dfcf8f3599ffc63e": { + "balance": "5000000000000000000000" + }, + "47688410ff25d654d72eb2bc06e4ad24f833b094": { + "balance": "160440000000000000000" + }, + "6c101205b323d77544d6dc52af37aca3cec6f7f1": { + "balance": "10000000000000000000000" + }, + "fb685c15e439965ef626bf0d834cd1a89f2b5695": { + "balance": "3940000000000000000000" + }, + "673706b1b0e4dc7a949a7a796258a5b83bb5aa83": { + "balance": "16100000000000000000000" + }, + "ecdaf93229b45ee672f65db506fb5eca00f7fce6": { + "balance": "1605009000000000000000" + }, + "ec6904bae1f69790591709b0609783733f2573e3": { + "balance": "500000000000000000000" + }, + "812ea7a3b2c86eed32ff4f2c73514cc63bacfbce": { + "balance": "1000000000000000000000" + }, + "196c02210a450ab0b36370655f717aa87bd1c004": { + "balance": "259456000000000000000" + }, + "d96ac2507409c7a383ab2eee1822a5d738b36b56": { + "balance": "200000000000000000000" + }, + "ae2f9c19ac76136594432393b0471d08902164d3": { + "balance": "698600000000000000000" + }, + "9d32962ea99700d93228e9dbdad2cc37bb99f07e": { + "balance": "3327560000000000000000" + }, + "17e584e810e567702c61d55d434b34cdb5ee30f6": { + "balance": "5000000000000000000000" + }, + "a3a93ef9dbea2636263d06d8492f6a41de907c22": { + "balance": "60000000000000000000" + }, + "2b5016e2457387956562587115aa8759d8695fdf": { + "balance": "200000000000000000000000" + }, + "140129eaa766b5a29f5b3af2574e4409f8f6d3f1": { + "balance": "6400000000000000000000" + }, + "7025965d2b88da197d4459be3dc9386344cc1f31": { + "balance": "2005500000000000000000" + }, + "388bdcdae794fc44082e667501344118ea96cd96": { + "balance": "1670000000000000000000" + }, + "eee9d0526eda01e43116a395322dda8970578f39": { + "balance": "9999980000000000000000" + }, + "6ec89b39f9f5276a553e8da30e6ec17aa47eefc7": { + "balance": "447500000000000000000" + }, + "7e236666b2d06e63ea4e2ab84357e2dfc977e50e": { + "balance": "999972000000000000000" + }, + "68df947c495bebaeb8e889b3f953d533874bf106": { + "balance": "546000000000000000000" + }, + "d40ed66ab3ceff24ca05ecd471efb492c15f5ffa": { + "balance": "500000000000000000000" + }, + "f0c70d0d6dab7663aa9ed9ceea567ee2c6b02765": { + "balance": "2089349000000000000000" + }, + "b589676d15a04448344230d4ff27c95edf122c49": { + "balance": "1000000000000000000000" + }, + "a0347f0a98776390165c166d32963bf74dcd0a2f": { + "balance": "1000000000000000000000" + }, + "d47d8685faee147c520fd986709175bf2f886bef": { + "balance": "2000000000000000000000" + }, + "a1dcd0e5b05a977c9623e5ae2f59b9ada2f33e31": { + "balance": "100000000000000000000" + }, + "4979194ec9e97db9bee8343b7c77d9d7f3f1dc9f": { + "balance": "20000000000000000000" + }, + "7cd20eccb518b60cab095b720f571570caaa447e": { + "balance": "500000000000000000000" + }, + "2ff830cf55fb00d5a0e03514fecd44314bd6d9f1": { + "balance": "10000000000000000000000" + }, + "0bb25ca7d188e71e4d693d7b170717d6f8f0a70a": { + "balance": "336870000000000000000" + }, + "e9a2b4914e8553bf0d7c00ca532369b879f931bf": { + "balance": "2000000000000000000000" + }, + "720e6b22bf430966fa32b6acb9a506eebf662c61": { + "balance": "152000000000000000000" + }, + "7ade5d66b944bb860c0efdc86276d58f4653f711": { + "balance": "2000000000000000000000" + }, + "2eaff9f8f8113064d3957ac6d6e11eee42c8195d": { + "balance": "1970000000000000000000" + }, + "0c8fd7775e54a6d9c9a3bf890e761f6577693ff0": { + "balance": "9850000000000000000000" + }, + "290a56d41f6e9efbdcea0342e0b7929a8cdfcb05": { + "balance": "344000000000000000000" + }, + "d73ed2d985b5f21b55b274643bc6da031d8edd8d": { + "balance": "49250000000000000000000" + }, + "80156d10efa8b230c99410630d37e269d4093cea": { + "balance": "2000000000000000000000" + }, + "0989c200440b878991b69d6095dfe69e33a22e70": { + "balance": "1910000000000000000000" + }, + "ec8014efc7cbe5b0ce50f3562cf4e67f8593cd32": { + "balance": "17300000000000000000" + }, + "de612d0724e84ea4a7feaa3d2142bd5ee82d3201": { + "balance": "20000000000000000000" + }, + "0f832a93df9d7f74cd0fb8546b7198bf5377d925": { + "balance": "143000000000000000000" + }, + "aa2c670096d3f939305325427eb955a8a60db3c5": { + "balance": "2003010000000000000000" + }, + "25287b815f5c82380a73b0b13fbaf982be24c4d3": { + "balance": "40000000000000000000" + }, + "e75c3b38a58a3f33d55690a5a59766be185e0284": { + "balance": "500000000000000000000" + }, + "1940dc9364a852165f47414e27f5002445a4f143": { + "balance": "10850000000000000000000" + }, + "e5b826196c0e1bc1119b021cf6d259a610c99670": { + "balance": "200000000000000000000" + }, + "82a15cef1d6c8260eaf159ea3f0180d8677dce1c": { + "balance": "2000000000000000000000" + }, + "da06044e293c652c467fe74146bf185b21338a1c": { + "balance": "1000000000000000000000" + }, + "f815c10a032d13c34b8976fa6e3bd2c9131a8ba9": { + "balance": "1337000000000000000000" + }, + "cd95fa423d6fc120274aacde19f4eeb766f10420": { + "balance": "200000000000000000000" + }, + "e3a4f83c39f85af9c8b1b312bfe5fc3423afa634": { + "balance": "28650000000000000000" + }, + "768ce0daa029b7ded022e5fc574d11cde3ecb517": { + "balance": "322000000000000000000" + }, + "e3ec18a74ed43855409a26ade7830de8e42685ef": { + "balance": "19700000000000000000" + }, + "b2bdbedf95908476d7148a370cc693743628057f": { + "balance": "4000000000000000000000" + }, + "bbb8ffe43f98de8eae184623ae5264e424d0b8d7": { + "balance": "107600000000000000000" + }, + "090cebef292c3eb081a05fd8aaf7d39bf07b89d4": { + "balance": "4000000000000000000000" + }, + "dd2a233adede66fe1126d6c16823b62a021feddb": { + "balance": "2000000000000000000000" + }, + "d8cd64e0284eec53aa4639afc4750810b97fab56": { + "balance": "20000000000000000000" + }, + "e5953fea497104ef9ad2d4e5841c271f073519c2": { + "balance": "704000000000000000000" + }, + "967d4142af770515dd7062af93498dbfdff29f20": { + "balance": "20200000000000000000" + }, + "fd191a35157d781373fb411bf9f25290047c5eef": { + "balance": "1000000000000000000000" + }, + "8967d7b9bdb7b4aed22e65a15dc803cb7a213f10": { + "balance": "400000000000000000000" + }, + "51e43fe0d25c782860af81ea89dd793c13f0cbb1": { + "balance": "60000000000000000000" + }, + "a38476691d34942eea6b2f76889223047db4617a": { + "balance": "2000000000000000000000" + }, + "1321ccf29739b974e5a516f18f3a843671e39642": { + "balance": "4000000000000000000000" + }, + "4d71a6eb3d7f327e1834278e280b039eddd31c2f": { + "balance": "6000000000000000000000" + }, + "dc2d15a69f6bb33b246aef40450751c2f6756ad2": { + "balance": "1996000000000000000000" + }, + "ec89f2b678a1a15b9134ec5eb70c6a62071fbaf9": { + "balance": "200000000000000000000" + }, + "27bf943c1633fe32f8bcccdb6302b407a5724e44": { + "balance": "940229000000000000000" + }, + "d0a6c6f9e9c4b383d716b31de78d56414de8fa91": { + "balance": "300000000000000000000" + }, + "7b6175ec9befc738249535ddde34688cd36edf25": { + "balance": "10000000000000000000000" + }, + "41ce79950935cff55bf78e4ccec2fe631785db95": { + "balance": "2000000000000000000000" + }, + "5598b3a79a48f32b1f5fc915b87b645d805d1afe": { + "balance": "500000000000000000000" + }, + "5c4881165cb42bb82e97396c8ef44adbf173fb99": { + "balance": "110600000000000000000" + }, + "25b0533b81d02a617b9229c7ec5d6f2f672e5b5a": { + "balance": "1000000000000000000000" + }, + "015f097d9acddcddafaf2a107eb93a40fc94b04c": { + "balance": "20000000000000000000000" + }, + "b84b53d0bb125656cddc52eb852ab71d7259f3d5": { + "balance": "16000000000000000000000" + }, + "1a79c7f4039c67a39d7513884cdc0e2c34222490": { + "balance": "20000000000000000000" + }, + "926209b7fda54e8ddb9d9e4d3d19ebdc8e88c29f": { + "balance": "2000000000000000000000" + }, + "c2fe7d75731f636dcd09dbda0671393ba0c82a7d": { + "balance": "2200000000000000000000" + }, + "30248d58e414b20fed3a6c482b59d9d8f5a4b7e2": { + "balance": "60000000000000000000" + }, + "d0e194f34b1db609288509ccd2e73b6131a2538b": { + "balance": "999972000000000000000" + }, + "e8f29969e75c65e01ce3d86154207d0a9e7c76f2": { + "balance": "2991807000000000000000" + }, + "cb93199b9c90bc4915bd859e3d42866dc8c18749": { + "balance": "231800000000000000000" + }, + "e6fe0afb9dcedd37b2e22c451ba6feab67348033": { + "balance": "10000000000000000000000" + }, + "82f854c9c2f087dffa985ac8201e626ca5467686": { + "balance": "100000000000000000000000" + }, + "63bb664f9117037628594da7e3c5089fd618b5b5": { + "balance": "20000000000000000000" + }, + "f8d17424c767bea31205739a2b57a7277214eebe": { + "balance": "42000000000000000000" + }, + "4ca8db4a5efefc80f4cd9bbcccb03265931332b6": { + "balance": "200000000000000000000" + }, + "c56e6b62ba6e40e52aab167d21df025d0055754b": { + "balance": "2000000000000000000000" + }, + "0d8c40a79e18994ff99ec251ee10d088c3912e80": { + "balance": "114600000000000000000" + }, + "40a331195b977325c2aa28fa2f42cb25ec3c253c": { + "balance": "2000000000000000000000" + }, + "a2c5854ff1599f98892c5725d262be1da98aadac": { + "balance": "314315000000000000000" + }, + "23ab09e73f87aa0f3be0139df0c8eb6be5634f95": { + "balance": "8000000000000000000000" + }, + "b8040536958d5998ce4bec0cfc9c2204989848e9": { + "balance": "24472420000000000000000" + }, + "42d6b263d9e9f4116c411424fc9955783c763030": { + "balance": "2000000000000000000000" + }, + "c496cbb0459a6a01600fc589a55a32b454217f9d": { + "balance": "274000000000000000000" + }, + "48302c311ef8e5dc664158dd583c81194d6e0d58": { + "balance": "3364760000000000000000" + }, + "d5b284040130abf7c1d163712371cc7e28ad66da": { + "balance": "1970000000000000000000" + }, + "d22f0ca4cd479e661775053bcc49e390f670dd8a": { + "balance": "1000000000000000000000" + }, + "e597f083a469c4591c3d2b1d2c772787befe27b2": { + "balance": "280000000000000000000" + }, + "668b6ba8ab08eace39c502ef672bd5ccb6a67a20": { + "balance": "31135320000000000000000" + }, + "a3bff1dfa9971668360c0d82828432e27bf54e67": { + "balance": "200000000000000000000" + }, + "ee655bb4ee0e8d5478526fb9f15e4064e09ff3dd": { + "balance": "200000000000000000000" + }, + "121f855b70149ac83473b9706fb44d47828b983b": { + "balance": "1400000000000000000000" + }, + "20a15256d50ce058bf0eac43aa533aa16ec9b380": { + "balance": "20000000000000000000" + }, + "69bcfc1d43b4ba19de7b274bdffb35139412d3d7": { + "balance": "985000000000000000000" + }, + "db288f80ffe232c2ba47cc94c763cf6fc9b82b0d": { + "balance": "85000000000000000000" + }, + "e1cb83ec5eb6f1eeb85e99b2fc63812fde957184": { + "balance": "20000000000000000000000" + }, + "a419a984142363267575566089340eea0ea20819": { + "balance": "1999944000000000000000" + }, + "8489f6ad1d9a94a297789156899db64154f1dbb5": { + "balance": "358849000000000000000" + }, + "d609bf4f146eea6b0dc8e06ddcf4448a1fccc9fa": { + "balance": "2000000000000000000000" + }, + "df1fa2e20e31985ebe2c0f0c93b54c0fb67a264b": { + "balance": "200000000000000000000" + }, + "efe8ff87fc260e0767638dd5d02fc4672e0ec06d": { + "balance": "2000000000000000000000" + }, + "eef1bbb1e5a83fde8248f88ee3018afa2d1332eb": { + "balance": "200000000000000000000" + }, + "4b3aab335ebbfaa870cc4d605e7d2e74c668369f": { + "balance": "60000000000000000000000" + }, + "8f4fb1aea7cd0f570ea5e61b40a4f4510b6264e4": { + "balance": "4000000000000000000000" + }, + "0b0b3862112aeec3a03492b1b05f440eca54256e": { + "balance": "4000000000000000000000" + }, + "dff4007931786593b229efe5959f3a4e219e51af": { + "balance": "4925000000000000000000" + }, + "fec14e5485de2b3eef5e74c46146db8e454e0335": { + "balance": "179000000000000000000" + }, + "ac21c1e5a3d7e0b50681679dd6c792dbca87decb": { + "balance": "100000000000000000000000" + }, + "796ebbf49b3e36d67694ad79f8ff36767ac6fab0": { + "balance": "60800000000000000000" + }, + "ae7739124ed153052503fc101410d1ffd8cd13b7": { + "balance": "999942000000000000000" + }, + "86026cad3fe4ea1ce7fca260d3d45eb09ea6a364": { + "balance": "200000000000000000000" + }, + "b2fc84a3e50a50af02f94da0383ed59f71ff01d7": { + "balance": "30000000000000000000000" + }, + "bbab000b0408ed015a37c04747bc461ab14e151b": { + "balance": "6000000000000000000000" + }, + "c4ff6fbb1f09bd9e102ba033d636ac1c4c0f5304": { + "balance": "1000000000000000000000" + }, + "cc606f511397a38fc7872bd3b0bd03c71bbd768b": { + "balance": "1000000000000000000000" + }, + "f346d7de92741c08fc58a64db55b062dde012d14": { + "balance": "295106000000000000000" + }, + "33f15223310d44de8b6636685f3a4c3d9c5655a5": { + "balance": "250500000000000000000" + }, + "3c860e2e663f46db53427b29fe3ea5e5bf62bbcc": { + "balance": "98500000000000000000" + }, + "acb94338554bc488cc88ae2d9d94080d6bdf8410": { + "balance": "1000000000000000000000" + }, + "9c5cc111092c122116f1a85f4ee31408741a7d2f": { + "balance": "492500000000000000000" + }, + "5f76f0a306269c78306b3d650dc3e9c37084db61": { + "balance": "2400000000000000000000" + }, + "2c0cc3f951482cc8a2925815684eb9f94e060200": { + "balance": "6000000000000000000000" + }, + "b74372dbfa181dc9242f39bf1d3731dffe2bdacf": { + "balance": "2000000000000000000000" + }, + "3bab4b01a7c84ba13feea9b0bb191b77a3aadca3": { + "balance": "200000000000000000000" + }, + "39aa05e56d7d32385421cf9336e90d3d15a9f859": { + "balance": "26000000000000000000" + }, + "4a52bad20357228faa1e996bed790c93674ba7d0": { + "balance": "1337000000000000000000" + }, + "ff128f4b355be1dc4a6f94fa510d7f15d53c2aff": { + "balance": "2720000000000000000000" + }, + "92793ac5b37268774a7130de2bbd330405661773": { + "balance": "40110000000000000000" + }, + "db19a3982230368f0177219cb10cb259cdb2257c": { + "balance": "2000000000000000000000" + }, + "8d1794da509cb297053661a14aa892333231e3c1": { + "balance": "199600000000000000000" + }, + "9b7c8810cc7cc89e804e6d3e38121850472877fe": { + "balance": "2000000000000000000000" + }, + "ed3cbc3782cebd67989b305c4133b2cde32211eb": { + "balance": "400000000000000000000" + }, + "8532490897bbb4ce8b7f6b837e4cba848fbe9976": { + "balance": "100000000000000000000" + }, + "c384ac6ee27c39e2f278c220bdfa5baed626d9d3": { + "balance": "600000000000000000000" + }, + "b1459285863ea2db3759e546ceb3fb3761f5909c": { + "balance": "1122309000000000000000" + }, + "634efc24371107b4cbf03f79a93dfd93e431d5fd": { + "balance": "1221341000000000000000" + }, + "ef9f59aeda418c1494682d941aab4924b5f4929a": { + "balance": "100000000000000000000000" + }, + "e7311c9533f0092c7248c9739b5b2c864a34b1ce": { + "balance": "2803436000000000000000" + }, + "e6e621eaab01f20ef0836b7cad47464cb5fd3c96": { + "balance": "316014000000000000000" + }, + "cd102cd6db3df14ad6af0f87c72479861bfc3d24": { + "balance": "2000000000000000000000" + }, + "005a9c03f69d17d66cbb8ad721008a9ebbb836fb": { + "balance": "2000000000000000000000" + }, + "a072cebe62a9e9f61cc3fbf88a9efbfe3e9a8d70": { + "balance": "400000000000000000000" + }, + "f2ab1161750244d0ecd048ee0d3e51abb143a2fd": { + "balance": "1235800000000000000000" + }, + "f686785b89720b61145fea80978d6acc8e0bc196": { + "balance": "4000000000000000000000" + }, + "0a2b4fc5d81ace67dc4bba03f7b455413d46fe3d": { + "balance": "197000000000000000000" + }, + "c32ec7e42ad16ce3e2555ad4c54306eda0b26758": { + "balance": "2000000000000000000000" + }, + "f3fa723552a5d0512e2b62f48dca7b2b8105305b": { + "balance": "137000000000000000000" + }, + "6dc3f92baa1d21dab7382b893261a0356fa7c187": { + "balance": "1730000000000000000000" + }, + "4627c606842671abde8295ee5dd94c7f549534f4": { + "balance": "286600000000000000000" + }, + "e39e46e15d22ce56e0c32f1877b7d1a264cf94f3": { + "balance": "20000000000000000000000" + }, + "d7d157e4c0a96437a6d285741dd23ec4361fa36b": { + "balance": "2000000000000000000000" + }, + "68f8f45155e98c5029a4ebc5b527a92e9fa83120": { + "balance": "4436101000000000000000" + }, + "9aba2b5e27ff78baaab5cdc988b7be855cebbdce": { + "balance": "9999000000000000000000" + }, + "66b39837cb3cac8a802afe3f12a258bbca62dacd": { + "balance": "400000000000000000000" + }, + "d39b7cbc94003fc948f0cde27b100db8ccd6e063": { + "balance": "400000000000000000000" + }, + "3db9ed7f024c7e26372feacf2b050803445e3810": { + "balance": "1285600000000000000000" + }, + "3fbc1e4518d73400c6d046359439fb68ea1a49f4": { + "balance": "16400000000000000000000" + }, + "e3da4f3240844c9b6323b4996921207122454399": { + "balance": "11539639000000000000000" + }, + "09afa73bc047ef46b977fd9763f87286a6be68c6": { + "balance": "501500000000000000000" + }, + "1dbe8e1c2b8a009f85f1ad3ce80d2e05350ee39c": { + "balance": "135400000000000000000" + }, + "2c5a2d0abda03bbe215781b4ff296c8c61bdbaf6": { + "balance": "30617000000000000000" + }, + "9a9d1dc0baa77d6e20c3d849c78862dd1c054c87": { + "balance": "880000000000000000000" + }, + "3ccef88679573947e94997798a1e327e08603a65": { + "balance": "807700000000000000000" + }, + "850b9db18ff84bf0c7da49ea3781d92090ad7e64": { + "balance": "2600000000000000000000" + }, + "361c75931696bc3d427d93e76c77fd13b241f6f4": { + "balance": "549212000000000000000" + }, + "c8f2b320e6dfd70906c597bad2f9501312c78259": { + "balance": "1504800000000000000000" + }, + "8dc1d5111d09af25fdfcac455c7cec283e6d6775": { + "balance": "2000000000000000000000" + }, + "cd7ece086b4b619b3b369352ee38b71ddb06439a": { + "balance": "200000000000000000000" + }, + "f607c2150d3e1b99f24fa1c7d540add35c4ebe1e": { + "balance": "3098020000000000000000" + }, + "32485c818728c197fea487fbb6e829159eba8370": { + "balance": "1053893000000000000000" + }, + "8e670815fb67aeaea57b86534edc00cdf564fee5": { + "balance": "3300000000000000000000" + }, + "10df681506e34930ac7a5c67a54c3e89ce92b981": { + "balance": "2153800000000000000000" + }, + "1cf2eb7a8ccac2adeaef0ee87347d535d3b94058": { + "balance": "2000000000000000000000" + }, + "f0dc43f205619127507b2b1c1cfdf32d28310920": { + "balance": "301973000000000000000" + }, + "f2c2904e9fa664a11ee25656d8fd2cc0d9a522a0": { + "balance": "13370000000000000000" + }, + "70670fbb05d33014444b8d1e8e7700258b8caa6d": { + "balance": "2000000000000000000000" + }, + "5160ed612e1b48e73f3fc15bc4321b8f23b8a24b": { + "balance": "562800000000000000000" + }, + "54a62bf9233e146ffec3876e45f20ee8414adeba": { + "balance": "10000000000000000000000" + }, + "26d4ec17d5ceb2c894bdc59d0a6a695dad2b43cc": { + "balance": "2935300000000000000000" + }, + "205fc843e19a4913d1881eb69b69c0fa3be5c50b": { + "balance": "9700000000000000000000" + }, + "e001aba77c02e172086c1950fffbcaa30b83488f": { + "balance": "1970000000000000000000" + }, + "21efbca09b3580b98e73f5b2f7f4dc0bf02c529c": { + "balance": "2000000000000000000000" + }, + "c4d916574e68c49f7ef9d3d82d1638b2b7ee0985": { + "balance": "1580000000000000000000" + }, + "cab0d32cf3767fa6b3537c84328baa9f50458136": { + "balance": "8960000000000000000000" + }, + "7ce4686446f1949ebed67215eb0d5a1dd72c11b8": { + "balance": "2217776000000000000000" + }, + "7837fcb876da00d1eb3b88feb3df3fa4042fac82": { + "balance": "1760000000000000000000" + }, + "71e38ff545f30fe14ca863d4f5297fd48c73a5ce": { + "balance": "3580000000000000000000" + }, + "e528a0e5a267d667e9393a6584e19b34dc9be973": { + "balance": "5600000000000000000000" + }, + "c5374928cdf193705443b14cc20da423473cd9cf": { + "balance": "138139000000000000000" + }, + "e406f5dd72cab66d8a6ecbd6bfb494a7b6b09afe": { + "balance": "100000000000000000000" + }, + "d7ef340e66b0d7afcce20a19cb7bfc81da33d94e": { + "balance": "3000000000000000000000" + }, + "e012db453827a58e16c1365608d36ed658720507": { + "balance": "2000000000000000000000" + }, + "d59638d3c5faa7711bf085745f9d5bdc23d498d8": { + "balance": "2000000000000000000000" + }, + "008fc7cbadffbd0d7fe44f8dfd60a79d721a1c9c": { + "balance": "1000000000000000000000" + }, + "8a3470282d5e2a2aefd7a75094c822c4f5aeef8a": { + "balance": "242743000000000000000" + }, + "38b3965c21fa893931079beacfffaf153678b6eb": { + "balance": "170374000000000000000" + }, + "57dd9471cbfa262709f5f486bcb774c5f527b8f8": { + "balance": "197000000000000000000" + }, + "5a60c924162873fc7ea4da7f972e350167376031": { + "balance": "83583000000000000000" + }, + "b9013c51bd078a098fae05bf2ace0849c6be17a5": { + "balance": "80000000000000000000" + }, + "dc23b260fcc26e7d10f4bd044af794579460d9da": { + "balance": "500038000000000000000" + }, + "45db03bccfd6a5f4d0266b82a22a368792c77d83": { + "balance": "8000000000000000000000" + }, + "3e0cbe6a6dcb61f110c45ba2aa361d7fcad3da73": { + "balance": "8022000000000000000000" + }, + "42d3a5a901f2f6bd9356f112a70180e5a1550b60": { + "balance": "925000000000000000000" + }, + "47219229e8cd56659a65c2a943e2dd9a8f4bfd89": { + "balance": "1520000000000000000000" + }, + "a20d071b1b003063497d7990e1249dabf36c35f7": { + "balance": "1000000000000000000000" + }, + "6835c8e8b74a2ca2ae3f4a8d0f6b954a3e2a8392": { + "balance": "60140000000000000000" + }, + "0c2d5c920538e953caaf24f0737f554cc6927742": { + "balance": "1000000000000000000000" + }, + "eedf6c4280e6eb05b934ace428e11d4231b5905b": { + "balance": "200000000000000000000" + }, + "ffa696ecbd787e66abae4fe87b635f07ca57d848": { + "balance": "1337000000000000000000" + }, + "3e81772175237eb4cbe0fe2dcafdadffeb6a1999": { + "balance": "8800000000000000000000" + }, + "b44783c8e57b480793cbd69a45d90c7b4f0c48ac": { + "balance": "20000000000000000000" + }, + "f84f090adf3f8db7e194b350fbb77500699f66fd": { + "balance": "1970000000000000000000" + }, + "2e9824b5c132111bca24ddfba7e575a5cd7296c1": { + "balance": "17201900000000000000000" + }, + "5cce72d068c7c3f55b1d2819545e77317cae8240": { + "balance": "1940000000000000000000" + }, + "d815e1d9f4e2b5e57e34826b7cfd8881b8546890": { + "balance": "17300000000000000000" + }, + "f901c00fc1db88b69c4bc3252b5ca70ea6ee5cf6": { + "balance": "400000000000000000000" + }, + "a960b1cadd3b5c1a8e6cb3abcaf52ee7c3d9fa88": { + "balance": "1522704000000000000000" + }, + "f7e45a12aa711c709acefe95f33b78612d2ad22a": { + "balance": "66230000000000000000000" + }, + "c332df50b13c013490a5d7c75dbfa366da87b6d6": { + "balance": "4000000000000000000000" + }, + "d467cf064c0871989b90d8b2eb14ccc63b360823": { + "balance": "200000000000000000000" + }, + "b9144b677c2dc614ceefdf50985f1183208ea64c": { + "balance": "2000000000000000000000" + }, + "ea7c4d6dc729cd6b157c03ad237ca19a209346c3": { + "balance": "2000000000000000000000" + }, + "9c9de44724a4054da0eaa605abcc802668778bea": { + "balance": "200020000000000000000" + }, + "d7140c8e5a4307fab0cc27badd9295018bf87970": { + "balance": "109600000000000000000" + }, + "c33acdb3ba1aab27507b86b15d67faf91ecf6293": { + "balance": "2000000000000000000000" + }, + "db2a0c9ab64df58ddfb1dbacf8ba0d89c85b31b4": { + "balance": "4000000000000000000000" + }, + "bfcb9730246304700da90b4153e71141622e1c41": { + "balance": "1000000000000000000000" + }, + "07dc8c8b927adbedfa8f5d639b4352351f2f36d2": { + "balance": "314382000000000000000" + }, + "2d5391e938b34858cf965b840531d5efda410b09": { + "balance": "1400000000000000000000" + }, + "0b5e2011ebc25a007f21362960498afb8af280fb": { + "balance": "2000000000000000000000" + }, + "ed9fb1f5af2fbf7ffc5029cee42b70ff5c275bf5": { + "balance": "280000000000000000000" + }, + "a3232d068d50064903c9ebc563b515acc8b7b097": { + "balance": "2002000000000000000000" + }, + "66274fea82cd30b6c29b23350e4f4f3d310a5899": { + "balance": "2070000000000000000000" + }, + "dbfb1bb464b8a58e500d2ed8de972c45f5f1c0fb": { + "balance": "1600000000000000000000" + }, + "a1f8d8bcf90e777f19b3a649759ad95027abdfc3": { + "balance": "200000000000000000000" + }, + "5bd23547477f6d09d7b2a005c5ee650c510c56d7": { + "balance": "10000000000000000000000" + }, + "ec3b8b58a12703e581ce5ffd7e21c57d1e5c663f": { + "balance": "1700000000000000000000" + }, + "54310b3aa88703a725dfa57de6e646935164802c": { + "balance": "1910000000000000000000" + }, + "8f41b1fbf54298f5d0bc2d122f4eb95da4e5cd3d": { + "balance": "354200000000000000000" + }, + "c80b36d1beafba5fcc644d60ac6e46ed2927e7dc": { + "balance": "13370000000000000000" + }, + "1ea492bce1ad107e337f4bd4a7ac9a7babcccdab": { + "balance": "100000000000000000000" + }, + "aaf023fef290a49bb78bb7abc95d669c50d528b0": { + "balance": "200000000000000000000" + }, + "80b79f338390d1ba1b3737a29a0257e5d91e0731": { + "balance": "20000000000000000000" + }, + "f382e4c20410b951089e19ba96a2fee3d91cce7e": { + "balance": "5054000000000000000000" + }, + "0748713145ef83c3f0ef4d31d823786f7e9cc689": { + "balance": "4500000000000000000000" + }, + "21e219c89ca8ac14ae4cba6130eeb77d9e6d3962": { + "balance": "789580000000000000000" + }, + "ca9a042a6a806ffc92179500d24429e8ab528117": { + "balance": "1100000000000000000000" + }, + "bcc9593b2da6df6a34d71b1aa38dacf876f95b88": { + "balance": "20000000000000000000" + }, + "d1438267231704fc7280d563adf4763844a80722": { + "balance": "200000000000000000000" + }, + "4989e1ab5e7cd00746b3938ef0f0d064a2025ba5": { + "balance": "2000000000000000000000" + }, + "bd4b60faec740a21e3071391f96aa534f7c1f44e": { + "balance": "182000000000000000000" + }, + "8c7cb4e48b25031aa1c4f92925d631a8c3edc761": { + "balance": "1000000000000000000000" + }, + "322788b5e29bf4f5f55ae1ddb32085fda91b8ebe": { + "balance": "200000000000000000000" + }, + "f15e182c4fbbad79bd93342242d4dccf2be58925": { + "balance": "1940000000000000000000" + }, + "1548b770a5118ede87dba2f690337f616de683ab": { + "balance": "527558000000000000000" + }, + "69c2d835f13ee90580408e6a3283c8cca6a434a2": { + "balance": "656000000000000000000" + }, + "a1e4380a3b1f749673e270229993ee55f35663b4": { + "balance": "2000000000000000000000" + }, + "c7675e5647b9d8daf4d3dff1e552f6b07154ac38": { + "balance": "180000000000000000000" + }, + "a02c1e34064f0475f7fa831ccb25014c3aa31ca2": { + "balance": "60000000000000000000" + }, + "517c75430de401c341032686112790f46d4d369e": { + "balance": "388000000000000000000" + }, + "29681d9912ddd07eaabb88d05d90f766e862417d": { + "balance": "1000000000000000000000" + }, + "544dda421dc1eb73bb24e3e56a248013b87c0f44": { + "balance": "1970000000000000000000" + }, + "2ab97e8d59eee648ab6caf8696f89937143864d6": { + "balance": "3820000000000000000000" + }, + "79c130c762b8765b19d2abc9a083ab8f3aad7940": { + "balance": "3940000000000000000000" + }, + "f9650d6989f199ab1cc479636ded30f241021f65": { + "balance": "850000000000000000000" + }, + "d1c96e70f05ae0e6cd6021b2083750a7717cde56": { + "balance": "500000000000000000000" + }, + "88106c27d20b74b4b98ca62b232bd5c97411171f": { + "balance": "197000000000000000000" + }, + "37ab66083a4fa23848b886f9e66d79cdc150cc70": { + "balance": "88510000000000000000000" + }, + "8e6156336be2cdbe32140df08a2ba55fd0a58463": { + "balance": "74480000000000000000" + }, + "2982d76a15f847dd41f1922af368fe678d0e681e": { + "balance": "100000000000000000000" + }, + "209e8e29d33beae8fb6baa783d133e1d9ec1bc0b": { + "balance": "835000000000000000000" + }, + "b325674c01e3f7290d5226339fbeac67d221279f": { + "balance": "2800000000000000000000" + }, + "f20c9a99b74759d782f25c1ceca802a27e0b436c": { + "balance": "1670000000000000000000" + }, + "61bf84d5ab026f58c873f86ff0dfca82b55733ae": { + "balance": "2000000000000000000000" + }, + "0734a0a81c9562f4d9e9e10a8503da15db46d76e": { + "balance": "18200000000000000000" + }, + "0521bc3a9f8711fecb10f50797d71083e341eb9d": { + "balance": "20000000000000000000" + }, + "3301d9ca2f3bfe026279cd6819f79a293d98156e": { + "balance": "50000000000000000000000" + }, + "549d51af29f724c967f59423b85b2681e7b15136": { + "balance": "3760000000000000000000" + }, + "2053ac97548a0c4e8b80bc72590cd6a098fe7516": { + "balance": "187000000000000000000" + }, + "aa321fdbd449180db8ddd34f0fe906ec18ee0914": { + "balance": "685000000000000000000" + }, + "697f55536bf85ada51841f0287623a9f0ed09a17": { + "balance": "10000000000000000000000" + }, + "df57353aaff2aadb0a04f9014e8da7884e86589c": { + "balance": "152800000000000000000" + }, + "6807ddc88db489b033e6b2f9a81553571ab3c805": { + "balance": "29944000000000000000" + }, + "90057af9aa66307ec9f033b29724d3b2f41eb6f9": { + "balance": "121930000000000000000000" + }, + "3ff836b6f57b901b440c30e4dbd065cf37d3d48c": { + "balance": "200000000000000000000" + }, + "91051764af6b808e4212c77e30a5572eaa317070": { + "balance": "1000000000000000000000" + }, + "7faa30c31519b584e97250ed2a3cf3385ed5fd50": { + "balance": "2000000000000000000000" + }, + "fb842ca2c5ef133917a236a0d4ac40690110b038": { + "balance": "306000000000000000000" + }, + "aa167026d39ab7a85635944ed9edb2bfeba11850": { + "balance": "8298000000000000000000" + }, + "57beea716cbd81700a73d67f9ff039529c2d9025": { + "balance": "200000000000000000000" + }, + "654b7e808799a83d7287c67706f2abf49a496404": { + "balance": "1970000000000000000000" + }, + "dde8f0c31b7415511dced1cd7d46323e4bd12232": { + "balance": "1610000000000000000000" + }, + "8667fa1155fed732cfb8dca5a0d765ce0d0705ed": { + "balance": "81770000000000000000" + }, + "905526568ac123afc0e84aa715124febe83dc87c": { + "balance": "17900000000000000000" + }, + "8e98766524b0cf2747c50dd43b9567594d9731de": { + "balance": "1997200000000000000000" + }, + "c6df2075ebd240d44869c2be6bdf82e63d4ef1f5": { + "balance": "20000000000000000000" + }, + "2ff5cab12c0d957fd333f382eeb75107a64cb8e8": { + "balance": "10000000000000000000000" + }, + "3055efd26029e0d11b930df4f53b162c8c3fd2ce": { + "balance": "499938000000000000000" + }, + "b2c53efa33fe4a3a1a80205c73ec3b1dbcad0602": { + "balance": "1918595000000000000000" + }, + "766b3759e8794e926dac473d913a8fb61ad0c2c9": { + "balance": "86500000000000000000" + }, + "882aa798bf41df179f85520130f15ccdf59b5e58": { + "balance": "2000000000000000000000" + }, + "80b23d380b825c46e0393899a85556462da0e18c": { + "balance": "2000000000000000000000" + }, + "51f4663ab44ff79345f427a0f6f8a6c8a53ff234": { + "balance": "20000000000000000000000" + }, + "8d5ef172bf77315ea64e85d0061986c794c6f519": { + "balance": "3940000000000000000000" + }, + "75ac547017134c04ae1e11d60e63ec04d18db4ef": { + "balance": "6000000000000000000000" + }, + "ce1b0cb46aaecfd79b880cad0f2dda8a8dedd0b1": { + "balance": "20000000000000000000" + }, + "21408b4d7a2c0e6eca4143f2cacdbbccba121bd8": { + "balance": "20000000000000000000000" + }, + "9c526a140683edf1431cfaa128a935e2b614d88b": { + "balance": "111000000000000000000" + }, + "599728a78618d1a17b9e34e0fed8e857d5c40622": { + "balance": "14000000000000000000000" + }, + "6ac4d4be2db0d99da3faaaf7525af282051d6a90": { + "balance": "80185000000000000000" + }, + "785c8ea774d73044a734fa790a1b1e743e77ed7c": { + "balance": "238750000000000000000" + }, + "ff2726294148b86c78a9372497e459898ed3fee3": { + "balance": "1970000000000000000000" + }, + "68a86c402388fddc59028fec7021e98cbf830eac": { + "balance": "19100000000000000000" + }, + "6121af398a5b2da69f65c6381aec88ce9cc6441f": { + "balance": "640000000000000000000" + }, + "5a6686b0f17e07edfc59b759c77d5bef164d3879": { + "balance": "1490000000000000000000" + }, + "a2d38de1c73906f6a7ca6efeb97cf6f69cc421be": { + "balance": "1000000000000000000000" + }, + "ae3f98a443efe00f3e711d525d9894dc9a61157b": { + "balance": "295500000000000000000" + }, + "5f1c8a04c90d735b8a152909aeae636fb0ce1665": { + "balance": "6999974000000000000000" + }, + "d687cec0059087fdc713d4d2d65e77daefedc15f": { + "balance": "60000000000000000000" + }, + "845203750f7148a9aa262921e86d43bf641974fd": { + "balance": "100000000000000000000" + }, + "64464a6805b462412a901d2db8174b06c22deea6": { + "balance": "475600000000000000000" + }, + "053471cd9a41925b3904a5a8ffca3659e034be23": { + "balance": "199600000000000000000" + }, + "911ff233e1a211c0172c92b46cf997030582c83a": { + "balance": "1970000000000000000000" + }, + "d930b27a78876485d0f48b70dd5336549679ca8f": { + "balance": "40000000000000000000" + }, + "6ba9b21b35106be159d1c1c2657ac56cd29ffd44": { + "balance": "4480000000000000000000" + }, + "ebac2b4408ef5431a13b8508e86250982114e145": { + "balance": "4000000000000000000000" + }, + "931df34d1225bcd4224e63680d5c4c09bce735a6": { + "balance": "68000000000000000000" + }, + "23eb6fd85671a9063ab7678ebe265a20f61a02b3": { + "balance": "2000000000000000000000" + }, + "b32af3d3e8d075344926546f2e32887bf93b16bd": { + "balance": "200000000000000000000" + }, + "8261fa230c901d43ff579f4780d399f31e6076bc": { + "balance": "2000000000000000000000" + }, + "84a74ceecff65cb93b2f949d773ef1ad7fb4a245": { + "balance": "92998000000000000000" + }, + "da982e9643ffece723075a40fe776e5ace04b29b": { + "balance": "160884000000000000000" + }, + "ba70e8b4759c0c3c82cc00ac4e9a94dd5bafb2b8": { + "balance": "890342000000000000000" + }, + "82f2e991fd324c5f5d17768e9f61335db6319d6c": { + "balance": "500000000000000000000" + }, + "3e84b35c5b2265507061d30b6f12da033fe6f8b9": { + "balance": "1790000000000000000000" + }, + "2895e80999d406ad592e2b262737d35f7db4b699": { + "balance": "1940000000000000000000" + }, + "65f534346d2ffb787fa9cf185d745ba42986bd6e": { + "balance": "500000000000000000000" + }, + "c7368b9709a5c1b51c0adf187a65df14e12b7dba": { + "balance": "9489681000000000000000" + }, + "ba176dbe3249e345cd4fa967c0ed13b24c47e586": { + "balance": "399990000000000000000" + }, + "cff6a6fe3e9a922a12f21faa038156918c4fcb9c": { + "balance": "78800000000000000000" + }, + "bcbd31252ec288f91e298cd812c92160e738331a": { + "balance": "1975802000000000000000" + }, + "5543dd6d169eec8a213bbf7a8af9ffd15d4ff759": { + "balance": "18200000000000000000" + }, + "b65bd780c7434115162027565223f44e5498ff8c": { + "balance": "19999800000000000000000" + }, + "4cadf573ce4ceec78b8e1b21b0ed78eb113b2c0e": { + "balance": "2000000000000000000000" + }, + "04aafc8ae5ce6f4903c89d7fac9cb19512224777": { + "balance": "500000000000000000000" + }, + "fdc4d4765a942f5bf96931a9e8cc7ab8b757ff4c": { + "balance": "87000000000000000000000" + }, + "38c7851f5ffd4cee98df30f3b25597af8a6ca263": { + "balance": "2631920000000000000000" + }, + "0e320219838e859b2f9f18b72e3d4073ca50b37d": { + "balance": "2000000000000000000000" + }, + "bbbf39b1b67995a42241504f9703d2a14a515696": { + "balance": "1580000000000000000000" + }, + "5b800bfd1b3ed4a57d875aed26d42f1a7708d72a": { + "balance": "6392000000000000000000" + }, + "5b85e60e2af0544f2f01c64e2032900ebd38a3c7": { + "balance": "2000000000000000000000" + }, + "c9ac01c3fb0929033f0ccc7e1acfeaaba7945d47": { + "balance": "12459235000000000000000" + }, + "f355d3ec0cfb907d8dbb1bf3464e458128190bac": { + "balance": "4925600000000000000000" + }, + "69c08d744754de709ce96e15ae0d1d395b3a2263": { + "balance": "1000000000000000000000" + }, + "cef77451dfa2c643e00b156d6c6ff84e2373eb66": { + "balance": "188000000000000000000" + }, + "f3034367f87d24d3077fa9a2e38a8b0ccb1104ef": { + "balance": "1000000000000000000000" + }, + "73473e72115110d0c3f11708f86e77be2bb0983c": { + "balance": "20000000000000000000" + }, + "761e6caec189c230a162ec006530193e67cf9d19": { + "balance": "2000000000000000000000" + }, + "e9caf827be9d607915b365c83f0d3b7ea8c79b50": { + "balance": "3000000000000000000000" + }, + "eda4b2fa59d684b27a810df8978a73df308a63c2": { + "balance": "4000000000000000000000" + }, + "065ff575fd9c16d3cb6fd68ffc8f483fc32ec835": { + "balance": "200000000000000000000" + }, + "a72ee666c4b35e82a506808b443cebd5c632c7dd": { + "balance": "800000000000000000000" + }, + "5b30608c678e1ac464a8994c3b33e5cdf3497112": { + "balance": "400000000000000000000" + }, + "b0c7ce4c0dc3c2bbb99cc1857b8a455f611711ce": { + "balance": "4000000000000000000000" + }, + "d7274d50804d9c77da93fa480156efe57ba501de": { + "balance": "1940000000000000000000" + }, + "a609c26dd350c235e44b2b9c1dddccd0a9d9f837": { + "balance": "1000000000000000000000" + }, + "bddfa34d0ebf1b04af53b99b82494a9e3d8aa100": { + "balance": "12000000000000000000000" + }, + "fd40242bb34a70855ef0fd90f3802dec2136b327": { + "balance": "1930600000000000000000" + }, + "58aed6674affd9f64233272a578dd9386b99c263": { + "balance": "3400000000000000000000" + }, + "24434a3e32e54ecf272fe3470b5f6f512f675520": { + "balance": "5910000000000000000000" + }, + "a379a5070c503d2fac89b8b3afa080fd45ed4bec": { + "balance": "19700000000000000000000" + }, + "37e169a93808d8035698f815c7235613c1e659f2": { + "balance": "1000000000000000000000" + }, + "849b116f596301c5d8bb62e0e97a8248126e39f3": { + "balance": "300000000000000000000" + }, + "fe7011b698bf3371132d7445b19eb5b094356aee": { + "balance": "2000000000000000000000" + }, + "f16de1891d8196461395f9b136265b3b9546f6ef": { + "balance": "31313000000000000000" + }, + "6c6564e5c9c24eaaa744c9c7c968c9e2c9f1fbae": { + "balance": "1357800000000000000000" + }, + "8bb0212f3295e029cab1d961b04133a1809e7b91": { + "balance": "2000000000000000000000" + }, + "408a69a40715e1b313e1354e600800a1e6dc02a5": { + "balance": "35144000000000000000" + }, + "ddf0cce1fe996d917635f00712f4052091dff9ea": { + "balance": "2000000000000000000000" + }, + "50fef296955588caae74c62ec32a23a454e09ab8": { + "balance": "1201200000000000000000" + }, + "d913f0771949753c4726acaa2bd3619c5c20ff77": { + "balance": "3000000000000000000000" + }, + "9d6ecfa03af2c6e144b7c4692a86951e902e9e1f": { + "balance": "3000310000000000000000" + }, + "ecbe5e1c9ad2b1dccf0a305fc9522f4669dd3ae7": { + "balance": "5000000000000000000000" + }, + "33e9b71823952e1f66958c278fc28b1196a6c5a4": { + "balance": "100000000000000000000" + }, + "9de20bc37e7f48a80ffd7ad84ffbf1a1abe1738c": { + "balance": "200000000000000000000" + }, + "16f313cf8ad000914a0a176dc6a4342b79ec2538": { + "balance": "2000000000000000000000" + }, + "991ac7ca7097115f26205eee0ef7d41eb4e311ae": { + "balance": "20000000000000000000" + }, + "ddfafdbc7c90f1320e54b98f374617fbd01d109f": { + "balance": "13370000000000000000" + }, + "26b11d066588ce74a572a85a6328739212aa8b40": { + "balance": "2000000000000000000000" + }, + "ef2c34bb487d3762c3cca782ccdd7a8fbb0a9931": { + "balance": "180000000000000000000" + }, + "a9be88ad1e518b0bbb024ab1d8f0e73f790e0c76": { + "balance": "2800000000000000000000" + }, + "4a7494cce44855cc80582842be958a0d1c0072ee": { + "balance": "2400000000000000000000" + }, + "23569542c97d566018c907acfcf391d14067e87e": { + "balance": "2000000000000000000000" + }, + "d252960b0bf6b2848fdead80136db5f507f8be02": { + "balance": "2000000000000000000000" + }, + "2c0f5b9df43625798e7e03c1a5fd6a6d091af82b": { + "balance": "31200000000000000000" + }, + "a7c9d388ebd873e66b1713448397d0f37f8bd3a8": { + "balance": "5000000000000000000000" + }, + "3259bd2fddfbbc6fbad3b6e874f0bbc02cda18b5": { + "balance": "11886645000000000000000" + }, + "f287ff52f461117adb3e1daa71932d1493c65f2e": { + "balance": "3640000000000000000000" + }, + "c852428d2b586497acd30c56aa13fb5582f84402": { + "balance": "945600000000000000000" + }, + "296f00de1dc3bb01d47a8ccd1e5d1dd9a1eb7791": { + "balance": "1000000000000000000000" + }, + "817493cd9bc623702a24a56f9f82e3fd48f3cd31": { + "balance": "2920000000000000000000" + }, + "7adfedb06d91f3cc7390450b85550270883c7bb7": { + "balance": "322312000000000000000" + }, + "8d544c32c07fd0842c761d53a897d6c950bb7599": { + "balance": "200000000000000000000" + }, + "86297d730fe0f7a9ee24e08fb1087b31adb306a7": { + "balance": "2000000000000000000000" + }, + "f64fe0939a8d1eea2a0ecd9a9730fd7958e33109": { + "balance": "20600000000000000000" + }, + "b06eab09a610c6a53d56a946b2c43487ac1d5b2d": { + "balance": "1000000000000000000000" + }, + "bae9b82f7299631408659dd74e891cb8f3860fe5": { + "balance": "1970000000000000000000" + }, + "0eda80f4ed074aea697aeddf283b63dbca3dc4da": { + "balance": "2000000000000000000000" + }, + "ea686c5057093c171c66db99e01b0ececb308683": { + "balance": "384907000000000000000" + }, + "425725c0f08f0811f5f006eec91c5c5c126b12ae": { + "balance": "150000000000000000000" + }, + "b18e67a5050a1dc9fb190919a33da838ef445014": { + "balance": "20000000000000000000" + }, + "8dd484ff8a307364eb66c525a571aac701c5c318": { + "balance": "4000000000000000000000" + }, + "6671b182c9f741a0cd3c356c73c23126d4f9e6f4": { + "balance": "200000000000000000000" + }, + "ba0249e01d945bef93ee5ec61925e03c5ca509fd": { + "balance": "4000000000000000000000" + }, + "b2968f7d35f208871631c6687b3f3daeabc6616c": { + "balance": "156060000000000000000" + }, + "a6f62b8a3d7f11220701ab9ffffcb327959a2785": { + "balance": "506000000000000000000" + }, + "c885a18aabf4541b7b7b7ecd30f6fae6869d9569": { + "balance": "2000000000000000000000" + }, + "33fb577a4d214fe010d32cca7c3eeda63f87ceef": { + "balance": "1000000000000000000000" + }, + "be86d0b0438419ceb1a038319237ba5206d72e46": { + "balance": "999942000000000000000" + }, + "466292f0e80d43a78774277590a9eb45961214f4": { + "balance": "970000000000000000000" + }, + "b33c0323fbf9c26c1d8ac44ef74391d0804696da": { + "balance": "20000000000000000000" + }, + "f7bc4c44910d5aedd66ed2355538a6b193c361ec": { + "balance": "96980000000000000000" + }, + "d0f04f52109aebec9a7b1e9332761e9fe2b97bb5": { + "balance": "4000000000000000000000" + }, + "cb4a914d2bb029f32e5fef5c234c4fec2d2dd577": { + "balance": "1800000000000000000000" + }, + "2e619f57abc1e987aa936ae3a2264962e7eb2d9a": { + "balance": "756000000000000000000" + }, + "166bf6dab22d841b486c38e7ba6ab33a1487ed8c": { + "balance": "20000000000000000000000" + }, + "c3a046e3d2b2bf681488826e32d9c061518cfe8c": { + "balance": "2600000000000000000000" + }, + "d082275f745a2cac0276fbdb02d4b2a3ab1711fe": { + "balance": "30000000000000000000" + }, + "a701df79f594901afe1444485e6b20c3bda2b9b3": { + "balance": "1000000000000000000000" + }, + "dec3eec2640a752c466e2b7e7ee685afe9ac41f4": { + "balance": "1324245000000000000000" + }, + "8134dd1c9df0d6c8a5812426bb55c761ca831f08": { + "balance": "122360000000000000000" + }, + "bfc57aa666fae28e9f107a49cb5089a4e22151dd": { + "balance": "1000000000000000000000" + }, + "c3c2297329a6fd99117e54fc6af379b4d556547e": { + "balance": "6000000000000000000000" + }, + "40585200683a403901372912a89834aadcb55fdb": { + "balance": "2000000000000000000000" + }, + "cd49bf185e70d04507999f92a4de4455312827d0": { + "balance": "1000000000000000000000" + }, + "9c6bc9a46b03ae5404f043dfcf21883e4110cc33": { + "balance": "200000000000000000000" + }, + "1f49b86d0d3945590698a6aaf1673c37755ca80d": { + "balance": "700000000000000000000" + }, + "efeb1997aad277cc33430e6111ed0943594048b8": { + "balance": "2000000000000000000000" + }, + "7c0883054c2d02bc7a852b1f86c42777d0d5c856": { + "balance": "500000000000000000000" + }, + "ff49a775814ec00051a795a875de24592ea400d4": { + "balance": "200000000000000000000000" + }, + "f039683d7b3d225bc7d8dfadef63163441be41e2": { + "balance": "34380000000000000000" + }, + "a3ba0d3a3617b1e31b4e422ce269e873828d5d69": { + "balance": "850000000000000000000" + }, + "d116f3dcd5db744bd008887687aa0ec9fd7292aa": { + "balance": "1000000000000000000000" + }, + "5719f49b720da68856f4b9e708f25645bdbc4b41": { + "balance": "640000000000000000000" + }, + "870796abc0db84af82da52a0ed68734de7e636f5": { + "balance": "300000000000000000000" + }, + "68b6854788a7c6496cdbf5f84b9ec5ef392b78bb": { + "balance": "19700000000000000000000" + }, + "8c2fbeee8eacc5c5d77c16abd462ee9c8145f34b": { + "balance": "1940000000000000000000" + }, + "421684baa9c0b4b5f55338e6f6e7c8e146d41cb7": { + "balance": "1500000000000000000000" + }, + "dd26b429fd43d84ec179825324bad5bfb916b360": { + "balance": "5142000000000000000000" + }, + "3821862493242c0aeb84b90de05d250c1e50c074": { + "balance": "322200000000000000000" + }, + "68a7425fe09eb28cf86eb1793e41b211e57bd68d": { + "balance": "668500000000000000000" + }, + "da875e4e2f3cabe4f37e0eaed7d1f6dcc6ffef43": { + "balance": "2000000000000000000000" + }, + "c2663f8145dbfec6c646fc5c49961345de1c9f11": { + "balance": "690000000000000000000" + }, + "e89c22f1a4e1d4746ecfaa59ed386fee12d51e37": { + "balance": "44932000000000000000" + }, + "eff86b5123bcdc17ed4ce8e05b7e12e51393a1f7": { + "balance": "500000000000000000000" + }, + "6c3d18704126aa99ee3342ce60f5d4c85f1867cd": { + "balance": "50000000000000000000" + }, + "b8d531a964bcea13829620c0ced72422dadb4cca": { + "balance": "169990000000000000000" + }, + "7c29d47d57a733f56b9b217063b513dc3b315923": { + "balance": "4000000000000000000000" + }, + "bc1e80c181616342ebb3fb3992072f1b28b802c6": { + "balance": "4000000000000000000000" + }, + "31313ffd635bf2f3324841a88c07ed146144ceeb": { + "balance": "1970000000000000000000" + }, + "cc4feb72df98ff35a138e01761d1203f9b7edf0a": { + "balance": "7000000000000000000000" + }, + "741693c30376508513082020cc2b63e9fa92131b": { + "balance": "1200000000000000000000" + }, + "aa3135cb54f102cbefe09e96103a1a796718ff54": { + "balance": "57800000000000000000" + }, + "ef61155ba009dcdebef10b28d9da3d1bc6c9ced4": { + "balance": "59100000000000000000" + }, + "b3c94811e7175b148b281c1a845bfc9bb6fbc115": { + "balance": "200000000000000000000" + }, + "96d9cca8f55eea0040ec6eb348a1774b95d93ef4": { + "balance": "4000000000000000000000" + }, + "ce62125adec3370ac52110953a4e760be9451e3b": { + "balance": "152000000000000000000" + }, + "aca1e6bc64cc3180f620e94dc5b1bcfd8158e45d": { + "balance": "2000000000000000000000" + }, + "bc237148d30c13836ffa2cad520ee4d2e5c4eeff": { + "balance": "1970000000000000000000" + }, + "0e024e7f029c6aaf3a8b910f5e080873b85795aa": { + "balance": "1000000000000000000000" + }, + "7283cd4675da58c496556151dafd80c7f995d318": { + "balance": "760000000000000000000" + }, + "39b299327490d72f9a9edff11b83afd0e9d3c450": { + "balance": "200000000000000000000" + }, + "5f333a3b2310765a0d1832b9be4c0a03704c1c09": { + "balance": "1000000000000000000000" + }, + "5aaf1c31254a6e005fba7f5ab0ec79d7fc2b630e": { + "balance": "5910000000000000000000" + }, + "833db42c14163c7be4cab86ac593e06266d699d5": { + "balance": "174212000000000000000000" + }, + "f32d25eb0ea2b8b3028a4c7a155dc1aae865784d": { + "balance": "5710684000000000000000" + }, + "1fa2319fed8c2d462adf2e17feec6a6f30516e95": { + "balance": "125300000000000000000" + }, + "c49cfaa967f3afbf55031061fc4cef88f85da584": { + "balance": "2000000000000000000000" + }, + "43db7ff95a086d28ebbfb82fb8fb5f230a5ebccd": { + "balance": "16100000000000000000" + }, + "cf3f9128b07203a3e10d7d5755c0c4abc6e2cac2": { + "balance": "5000000000000000000000" + }, + "8f4d1e7e4561284a34fef9673c0d34e12af4aa03": { + "balance": "2000000000000000000000" + }, + "934af21b7ebfa467e2ced65aa34edd3a0ec71332": { + "balance": "35420000000000000000000" + }, + "5d231a70c1dfeb360abd97f616e2d10d39f3cab5": { + "balance": "400000000000000000000" + }, + "2d5d7335acb0362b47dfa3a8a4d3f5949544d380": { + "balance": "200000000000000000000" + }, + "d1e1f2b9c16c309874dee7fac32675aff129c398": { + "balance": "72800000000000000000" + }, + "a43b6da6cb7aac571dff27f09d39f846f53769b1": { + "balance": "380000000000000000000" + }, + "779274bf1803a336e4d3b00ddd93f2d4f5f4a62e": { + "balance": "1000000000000000000000" + }, + "a644ed922cc237a3e5c4979a995477f36e50bc62": { + "balance": "583900000000000000000" + }, + "ee6c03429969ca1262cb3f0a4a54afa7d348d7f5": { + "balance": "256100000000000000000" + }, + "4f06246b8d4bd29661f43e93762201d286935ab1": { + "balance": "4818730000000000000000" + }, + "e04972a83ca4112bc871c72d4ae1616c2f0728db": { + "balance": "267606000000000000000" + }, + "df098f5e4e3dffa51af237bda8652c4f73ed9ca6": { + "balance": "502000000000000000000" + }, + "dfded2574b27d1613a7d98b715159b0d00baab28": { + "balance": "20000000000000000000000" + }, + "17d931d4c56294dcbe77c8655be4695f006d4a3c": { + "balance": "2000000000000000000000" + }, + "3ccb71aa6880cb0b84012d90e60740ec06acd78f": { + "balance": "2000000000000000000000" + }, + "e57d2995b0ebdf3f3ca6c015eb04260dbb98b7c6": { + "balance": "2000000000000000000000" + }, + "fb3860f4121c432ebdc8ec6a0331b1b709792e90": { + "balance": "600400000000000000000" + }, + "fa00c376e89c05e887817a9dd0748d96f341aa89": { + "balance": "300700000000000000000" + }, + "c7a018f0968a51d1f6603c5c49dc545bcb0ff293": { + "balance": "4000000000000000000000" + }, + "7d73863038ccca22f96affda10496e51e1e6cd48": { + "balance": "20000000000000000000" + }, + "38ea6f5b5a7b88417551b4123dc127dfe9342da6": { + "balance": "400000000000000000000" + }, + "014b7f67b14f5d983d87014f570c8b993b9872b5": { + "balance": "200000000000000000000" + }, + "8ac89bd9b8301e6b0677fa25fcf0f58f0cc7b611": { + "balance": "20000000000000000000" + }, + "7eb4b0185c92b6439a08e7322168cb353c8a774a": { + "balance": "10165988000000000000000" + }, + "d29dc08efbb3d72e263f78ab7610d0226de76b00": { + "balance": "12000000000000000000000" + }, + "72a8260826294726a75bf39cd9aa9e07a3ea14cd": { + "balance": "2000000000000000000000" + }, + "4cb5c6cd713ca447b848ae2f56b761ca14d7ad57": { + "balance": "267400000000000000000" + }, + "49185dd7c23632f46c759473ebae966008cd3598": { + "balance": "254030000000000000000" + }, + "13d67a7e25f2b12cdb85585009f8acc49b967301": { + "balance": "1999944000000000000000" + }, + "9d913b5d339c95d87745562563fea98b23c60cc4": { + "balance": "170718000000000000000" + }, + "abdc9f1bcf4d19ee96591030e772c334302f7d83": { + "balance": "40110000000000000000000" + }, + "e9a5ae3c9e05977dd1069e9fd9d3aefbae04b8df": { + "balance": "1970000000000000000000" + }, + "1fd296be03ad737c92f9c6869e8d80a71c5714aa": { + "balance": "13370000000000000000" + }, + "2f13657526b177cad547c3908c840eff647b45d9": { + "balance": "1170685000000000000000" + }, + "e69fcc26ed225f7b2e379834c524d70c1735e5bc": { + "balance": "2000000000000000000000" + }, + "bade43599e02f84f4c3014571c976b13a36c65ab": { + "balance": "4000000000000000000000" + }, + "184a4f0beb71ffd558a6b6e8f228b78796c4cf3e": { + "balance": "12000000000000000000000" + }, + "d1de5aad3a5fd803f1b1aeb6103cb8e14fe723b7": { + "balance": "20000000000000000000" + }, + "0bd67dbde07a856ebd893b5edc4f3a5be4202616": { + "balance": "2000000000000000000000" + }, + "6b30f1823910b86d3acb5a6afc9defb6f3a30bf8": { + "balance": "4200000000000000000000" + }, + "9a63d185a79129fdab19b58bb631ea36a420544e": { + "balance": "42000000000000000000" + }, + "df660a91dab9f730f6190d50c8390561500756ca": { + "balance": "2000000000000000000000" + }, + "a1a1f0fa6d20b50a794f02ef52085c9d036aa6ca": { + "balance": "1000000000000000000000" + }, + "4ec768295eeabafc42958415e22be216cde77618": { + "balance": "59600000000000000000" + }, + "c348fc5a461323b57be303cb89361b991913df28": { + "balance": "100000000000000000000000" + }, + "3a7db224acae17de7798797d82cdf8253017dfa8": { + "balance": "5000000000000000000000" + }, + "8bea40379347a5c891d59a6363315640f5a7e07a": { + "balance": "1999992000000000000000" + }, + "2257fca16a6e5c2a647c3c29f36ce229ab93b17e": { + "balance": "4000000000000000000000" + }, + "e492818aa684e5a676561b725d42f3cc56ae5198": { + "balance": "800000000000000000000" + }, + "c841884fa4785fb773b28e9715fae99a5134305d": { + "balance": "2000000000000000000000" + }, + "0d9443a79468a5bbf7c13c6e225d1de91aee07df": { + "balance": "70000000000000000000" + }, + "6d4008b4a888a826f248ee6a0b0dfde9f93210b9": { + "balance": "5460000000000000000000" + }, + "884980eb4565c1048317a8f47fdbb461965be481": { + "balance": "3999922000000000000000" + }, + "985d70d207892bed398590024e2421b1cc119359": { + "balance": "20000000000000000000000" + }, + "d9ec8fe69b7716c0865af888a11b2b12f720ed33": { + "balance": "4000000000000000000000" + }, + "49b74e169265f01a89ec4c9072c5a4cd72e4e835": { + "balance": "16100000000000000000000" + }, + "4c3e95cc3957d252ce0bf0c87d5b4f2234672e70": { + "balance": "2500000000000000000000" + }, + "d9ff115d01266c9f73b063c1c238ef3565e63b36": { + "balance": "680000000000000000000" + }, + "48c5c6970b9161bb1c7b7adfed9cdede8a1ba864": { + "balance": "4000000000000000000000" + }, + "ea6afe2cc928ac8391eb1e165fc40040e37421e7": { + "balance": "2997569000000000000000" + }, + "08ccda50e4b26a0ffc0ef92e9205310706bec2c7": { + "balance": "6077440000000000000000" + }, + "e6e9a39d750fe994394eb68286e5ea62a6997882": { + "balance": "600000000000000000000" + }, + "4b58101f44f7e389e12d471d1635b71614fdd605": { + "balance": "160000000000000000000" + }, + "8d93dac785f88f1a84bf927d53652b45a154ccdd": { + "balance": "158000000000000000000" + }, + "415d096ab06293183f3c033d25f6cf7178ac3bc7": { + "balance": "40000000000000000000" + }, + "c3e387b03ce95ccfd7fa51dd840183bc43532809": { + "balance": "2000000000000000000000" + }, + "da34b2eae30bafe8daeccde819a794cd89e09549": { + "balance": "2000000000000000000000" + }, + "fa279bfd8767f956bf7fa0bd5660168da75686bd": { + "balance": "2674000000000000000000" + }, + "b98ca31785ef06be49a1e47e864f60d076ca472e": { + "balance": "4000000000000000000000" + }, + "b768b5234eba3a9968b34d6ddb481c8419b3655d": { + "balance": "14974000000000000000" + }, + "31047d703f63b93424fbbd6e2f1f9e74de13e709": { + "balance": "2850123000000000000000" + }, + "9a24ce8d485cc4c86e49deb39022f92c7430e67e": { + "balance": "1300000000000000000000" + }, + "e62f9d7c64e8e2635aeb883dd73ba684ee7c1079": { + "balance": "8000000000000000000000" + }, + "f15d9d5a21b1929e790371a17f16d95f0c69655c": { + "balance": "2000000000000000000000" + }, + "285ae51b9500c58d541365d97569f14bb2a3709b": { + "balance": "2000000000000000000000" + }, + "09c177f1ae442411ddacf187d46db956148360e7": { + "balance": "8950000000000000000000" + }, + "12173074980153aeaa4b0dcbc7132eadcec21b64": { + "balance": "240000000000000000000" + }, + "351f16e5e0735af56751b0e225b2421171394090": { + "balance": "13370000000000000000000" + }, + "ac52b77e15664814f39e4f271be641308d91d6cc": { + "balance": "220000000000000000000" + }, + "99c883258546cc7e4e971f522e389918da5ea63a": { + "balance": "4000000000000000000000" + }, + "aa16269aac9c0d803068d82fc79151dadd334b66": { + "balance": "4000000000000000000000" + }, + "7c9a110cb11f2598b2b20e2ca400325e41e9db33": { + "balance": "26000000000000000000000" + }, + "583e83ba55e67e13e0e76f8392d873cd21fbf798": { + "balance": "20000000000000000000" + }, + "555ebe84daa42ba256ea789105cec4b693f12f18": { + "balance": "100000000000000000000" + }, + "978c430ce4359b06bc2cdf5c2985fc950e50d5c8": { + "balance": "480000000000000000000" + }, + "dc1eb9b6e64351f56424509645f83e79eee76cf4": { + "balance": "4000000000000000000000" + }, + "5b290c01967c812e4dc4c90b174c1b4015bae71e": { + "balance": "149946000000000000000" + }, + "e7d213947fcb904ad738480b1eed2f5c329f27e8": { + "balance": "18718000000000000000" + }, + "c517d0315c878813c717e18cafa1eab2654e01da": { + "balance": "10000000000000000000000" + }, + "7e972a8a7c2a44c93b21436c38d21b9252c345fe": { + "balance": "1790000000000000000000" + }, + "9cb28ac1a20a106f7f373692c5ce4c73f13732a1": { + "balance": "1000000000000000000000" + }, + "14ab164b3b524c82d6abfbc0de831126ae8d1375": { + "balance": "2000000000000000000000" + }, + "d46f8223452982a1eea019a8816efc2d6fc00768": { + "balance": "137000000000000000000" + }, + "5cdc4708f14f40dcc15a795f7dc8cb0b7faa9e6e": { + "balance": "537000000000000000000" + }, + "66fdc9fee351fa1538eb0d87d819fcf09e7c106a": { + "balance": "6016500000000000000000" + }, + "e7be82c6593c1eeddd2ae0b15001ff201ab57b2f": { + "balance": "19100000000000000000" + }, + "47d20e6ae4cad3f829eac07e5ac97b66fdd56cf5": { + "balance": "1000000000000000000000" + }, + "0f2d8daf04b5414a0261f549ff6477b80f2f1d07": { + "balance": "200000000000000000000000" + }, + "84bfcef0491a0ae0694b37ceac024584f2aa0467": { + "balance": "1999944000000000000000" + }, + "ec5feafe210c12bfc9a5d05925a123f1e73fbef8": { + "balance": "456000000000000000000000" + }, + "7023c70956e04a92d70025aad297b539af355869": { + "balance": "2000000000000000000000" + }, + "d66ddf1159cf22fd8c7a4bc8d5807756d433c43e": { + "balance": "2200000000000000000000" + }, + "d0638ea57189a6a699024ad78c71d939c1c2ff8c": { + "balance": "2632000000000000000000" + }, + "70d25ed2c8ada59c088cf70dd22bf2db93acc18a": { + "balance": "1056600000000000000000" + }, + "a4875928458ec2005dbb578c5cd33580f0cf1452": { + "balance": "1000000000000000000000" + }, + "b5ad5157dda921e6bafacd9086ae73ae1f611d3f": { + "balance": "2000000000000000000000" + }, + "c493489e56c3bdd829007dc2f956412906f76bfa": { + "balance": "48968000000000000000" + }, + "c57612de91110c482e6f505bcd23f3c5047d1d61": { + "balance": "3580000000000000000000" + }, + "9b18478655a4851cc906e660feac61f7f4c8bffc": { + "balance": "4174120000000000000000" + }, + "b21b7979bf7c5ca01fa82dd640b41c39e6c6bc75": { + "balance": "1999944000000000000000" + }, + "a9d4a2bcbe5b9e0869d70f0fe2e1d6aacd45edc5": { + "balance": "198800000000000000000" + }, + "6f29bb375be5ed34ed999bb830ee2957dde76d16": { + "balance": "2000000000000000000000" + }, + "a006268446643ec5e81e7acb3f17f1c351ee2ed9": { + "balance": "4000000000000000000000" + }, + "42ddd014dc52bfbcc555325a40b516f4866a1dd3": { + "balance": "2000000000000000000000" + }, + "d6d6776958ee23143a81adadeb08382009e996c2": { + "balance": "3000000000000000000000" + }, + "d34e03d36a2bd4d19a5fa16218d1d61e3ffa0b15": { + "balance": "320000000000000000000" + }, + "dac0c177f11c5c3e3e78f2efd663d13221488574": { + "balance": "1000000000000000000000" + }, + "814135da8f9811075783bf1ab67062af8d3e9f40": { + "balance": "20000000000000000000" + }, + "7c3eb713c4c9e0381cd8154c7c9a7db8645cde17": { + "balance": "200000000000000000000" + }, + "f49c47b3efd86b6e6a5bc9418d1f9fec814b69ef": { + "balance": "20000000000000000000000" + }, + "35f1da127b83376f1b88c82a3359f67a5e67dd50": { + "balance": "1910000000000000000000" + }, + "44dfba50b829becc5f4f14d1b04aab3320a295e5": { + "balance": "1000000000000000000000" + }, + "0b924df007e9c0878417cfe63b976ea1a382a897": { + "balance": "40000000000000000000" + }, + "82438fd2b32a9bdd674b49d8cc5fa2eff9781847": { + "balance": "20000000000000000000" + }, + "794529d09d017271359730027075b87ad83dae6e": { + "balance": "310000000000000000000" + }, + "f4b49100757772f33c177b9a76ba95226c8f3dd8": { + "balance": "6700000000000000000000" + }, + "8563c49361b625e768771c96151dbfbd1c906976": { + "balance": "2000000000000000000000" + }, + "0b9df80fbe232009dacf0aa8cac59376e2476203": { + "balance": "2000000000000000000000" + }, + "149b6dbde632c19f5af47cb493114bebd9b03c1f": { + "balance": "12000000000000000000000" + }, + "d7a1431ee453d1e49a0550d1256879b4f5d10201": { + "balance": "1670000000000000000000" + }, + "1d37616b793f94911838ac8e19ee9449df921ec4": { + "balance": "1500000000000000000000" + }, + "d6670c036df754be43dadd8f50feea289d061fd6": { + "balance": "5988459000000000000000" + }, + "02778e390fa17510a3428af2870c4273547d386c": { + "balance": "16163700000000000000000" + }, + "b89f4632df5909e58b2a9964f74feb9a3b01e0c5": { + "balance": "21406707000000000000000" + }, + "76c27535bcb59ce1fa2d8c919cabeb4a6bba01d1": { + "balance": "2000000000000000000000" + }, + "36bf43ff35df90908824336c9b31ce33067e2f50": { + "balance": "346837200000000000000000" + }, + "b53bcb174c2518348b818aece020364596466ba3": { + "balance": "2000000000000000000000" + }, + "b4dd460cd016725a64b22ea4f8e06e06674e033e": { + "balance": "5370000000000000000000" + }, + "cda1741109c0265b3fb2bf8d5ec9c2b8a3346b63": { + "balance": "20000000000000000000" + }, + "feb8b8e2af716ae41fc7c04bcf29540156461e6b": { + "balance": "1555396000000000000000" + }, + "a49f523aa51364cbc7d995163d34eb590ded2f08": { + "balance": "2659160000000000000000" + }, + "a7e74f0bdb278ff0a805a648618ec52b166ff1be": { + "balance": "100000000000000000000" + }, + "5ead29037a12896478b1296ab714e9cb95428c81": { + "balance": "71500000000000000000" + }, + "cdecf5675433cdb0c2e55a68db5d8bbe78419dd2": { + "balance": "20000000000000000000" + }, + "c24ccebc2344cce56417fb684cf81613f0f4b9bd": { + "balance": "1550000000000000000000" + }, + "5a70106f20d63f875265e48e0d35f00e17d02bc9": { + "balance": "20000000000000000000" + }, + "2606c3b3b4ca1b091498602cb1978bf3b95221c0": { + "balance": "400000000000000000000" + }, + "1ad4563ea5786be1159935abb0f1d5879c3e7372": { + "balance": "6000000000000000000000" + }, + "b782bfd1e2de70f467646f9bc09ea5b1fcf450af": { + "balance": "267400000000000000000" + }, + "649a2b9879cd8fb736e6703b0c7747849796f10f": { + "balance": "7358102000000000000000" + }, + "1cc1d3c14f0fb8640e36724dc43229d2ea7a1e48": { + "balance": "1700000000000000000000" + }, + "824b3c3c443e19295d7ef6faa7f374a4798486a8": { + "balance": "20000000000000000000" + }, + "a7758cecb60e8f614cce96137ef72b4fbd07774a": { + "balance": "500000000000000000000" + }, + "981f712775c0dad97518ffedcb47b9ad1d6c2762": { + "balance": "6685000000000000000000" + }, + "26e801b62c827191dd68d31a011990947fd0ebe0": { + "balance": "20000000000000000000" + }, + "95447046313b2f3a5e19b948fd3b8bedc82c717c": { + "balance": "500000000000000000000" + }, + "0b701101a4109f9cb360dc57b77442673d5e5983": { + "balance": "2000000000000000000000" + }, + "5b25cae86dcafa2a60e7723631fc5fa49c1ad87d": { + "balance": "2491200000000000000000" + }, + "f73ac46c203be1538111b151ec8220c786d84144": { + "balance": "294515000000000000000" + }, + "e8c3d3b0e17f97d1e756e684f94e1470f99c95a1": { + "balance": "400000000000000000000" + }, + "8c900a8236b08c2b65405d39d75f20062a7561fd": { + "balance": "1640000000000000000000" + }, + "43898c49a34d509bfed4f76041ee91caf3aa6aa5": { + "balance": "300000000000000000000" + }, + "c85325eab2a59b3ed863c86a5f2906a04229ffa9": { + "balance": "465600000000000000000" + }, + "4a430170152de5172633dd8262d107a0afd96a0f": { + "balance": "3160000000000000000000" + }, + "6e0ee70612c976287d499ddfa6c0dcc12c06deea": { + "balance": "129980000000000000000" + }, + "21c07380484f6cbc8724ad32bc864c3b5ad500b7": { + "balance": "1000000000000000000000" + }, + "ff5162f2354dc492c75fd6e3a107268660eecb47": { + "balance": "1700000000000000000000" + }, + "8845e9f90e96336bac3c616be9d88402683e004c": { + "balance": "2000000000000000000000" + }, + "f23c7b0cb8cd59b82bd890644a57daf40c85e278": { + "balance": "50038000000000000000" + }, + "1784948bf99848c89e445638504dd698271b5924": { + "balance": "6037580000000000000000" + }, + "b39f4c00b2630cab7db7295ef43d47d501e17fd7": { + "balance": "4000000000000000000000" + }, + "3fb7d197b3ba4fe045efc23d50a14585f558d9b2": { + "balance": "20000000000000000000" + }, + "bd043b67c63e60f841ccca15b129cdfe6590c8e3": { + "balance": "200000000000000000000" + }, + "86ca0145957e6b0dfe36875fbe7a0dec55e17a28": { + "balance": "10000000000000000000000" + }, + "dae7201eab8c063302930d693929d07f95e71962": { + "balance": "2687370000000000000000" + }, + "cc034985d3f28c2d39b1a34bced4d3b2b6ca234e": { + "balance": "182000000000000000000" + }, + "40e0dbf3efef9084ea1cd7e503f40b3b4a8443f6": { + "balance": "4000000000000000000000" + }, + "b1896a37e5d8825a2d01765ae5de629977de8352": { + "balance": "200000000000000000000" + }, + "d9f547f2c1de0ed98a53d161df57635dd21a00bd": { + "balance": "98500000000000000000" + }, + "2fea1b2f834f02fc54333f8a809f0438e5870aa9": { + "balance": "20200000000000000000" + }, + "68b31836a30a016ada157b638ac15da73f18cfde": { + "balance": "26000000000000000000" + }, + "bc967fe4418c18b99858966d870678dca2b88879": { + "balance": "8740000000000000000000" + }, + "16bae5d24eff91778cd98b4d3a1cc3162f44aa77": { + "balance": "401100000000000000000" + }, + "f476e1267f86247cc908816f2e7ad5388c952db0": { + "balance": "4000000000000000000000" + }, + "0203ae01d4c41cae1865e04b1f5b53cdfaecae31": { + "balance": "1006054000000000000000" + }, + "bd4bd5b122d8ef7b7c8f0667450320db2116142e": { + "balance": "600000000000000000000" + }, + "a394ad4fd9e6530e6f5c53faecbede81cb172da1": { + "balance": "5600000000000000000000" + }, + "3a9960266df6492063538a99f487c950a3a5ec9e": { + "balance": "24000000000000000000000" + }, + "d8069f84b521493f4715037f3226b25f33b60586": { + "balance": "1910000000000000000000" + }, + "136c834bf111326d207395295b2e583ea7f33572": { + "balance": "100000000000000000000" + }, + "c5c73d61cce7c8fe4c8fce29f39092cd193e0fff": { + "balance": "8000000000000000000000" + }, + "3cfbf066565970639e130df2a7d16b0e14d6091c": { + "balance": "1700000000000000000000" + }, + "61b905de663fc17386523b3a28e2f7d037a655cd": { + "balance": "500000000000000000000" + }, + "fda0ce15330707f10bce3201172d2018b9ddea74": { + "balance": "51900000000000000000" + }, + "f7fc45abf76f5088e2e5b5a8d132f28a4d4ec1c0": { + "balance": "2000000000000000000000" + }, + "c3db9fb6f46c480af34465d79753b4e2b74a67ce": { + "balance": "20000000000000000000000" + }, + "ebe46cc3c34c32f5add6c3195bb486c4713eb918": { + "balance": "1000000000000000000000" + }, + "91d2a9ee1a6db20f5317cca7fbe2313895db8ef8": { + "balance": "8499600000000000000000" + }, + "c4cc45a2b63c27c0b4429e58cd42da59be739bd6": { + "balance": "1000000000000000000000" + }, + "a43b81f99356c0af141a03010d77bd042c71c1ee": { + "balance": "2000000000000000000000" + }, + "4c45d4c9a725d11112bfcbca00bf31186ccaadb7": { + "balance": "400000000000000000000" + }, + "bf9f271f7a7e12e36dd2fe9facebf385fe6142bd": { + "balance": "62760000000000000000" + }, + "e0ce80a461b648a501fd0b824690c8868b0e4de8": { + "balance": "500000000000000000000" + }, + "a1f7dde1d738d8cd679ea1ee965bee224be7d04d": { + "balance": "1127000000000000000000" + }, + "7f1c81ee1697fc144b7c0be5493b5615ae7fddca": { + "balance": "500200000000000000000" + }, + "b508f987b2de34ae4cf193de85bff61389621f88": { + "balance": "6000000000000000000000" + }, + "5f26cf34599bc36ea67b9e7a9f9b4330c9d542a3": { + "balance": "1000000000000000000000" + }, + "d02108d2ae3cab10cbcf1657af223e027c8210f6": { + "balance": "2000140000000000000000" + }, + "952183cfd38e352e579d36decec5b18450f7fba0": { + "balance": "2000000000000000000000" + }, + "eb90c793b3539761e1c814a29671148692193eb4": { + "balance": "12000000000000000000000" + }, + "1076212d4f758c8ec7121c1c7d74254926459284": { + "balance": "35000056000000000000000" + }, + "f05ceeab65410564709951773c8445ad9f4ec797": { + "balance": "299982000000000000000" + }, + "05361d8eb6941d4e90fb7e1418a95a32d5257732": { + "balance": "20000000000000000000" + }, + "a5783bf33432ff82ac498985d7d460ae67ec3673": { + "balance": "1820000000000000000000" + }, + "b1cd4bdfd104489a026ec99d597307a04279f173": { + "balance": "20000000000000000000000" + }, + "876c3f218b4776df3ca9dbfb270de152d94ed252": { + "balance": "100000000000000000000" + }, + "8a36869ad478997cbf6d8924d20a3c8018e9855b": { + "balance": "20000000000000000000" + }, + "fb3fe09bb836861529d7518da27635f538505615": { + "balance": "1399904000000000000000" + }, + "d093e829819fd2e25b973800bb3d5841dd152d05": { + "balance": "4000000000000000000000" + }, + "126d91f7ad86debb0557c612ca276eb7f96d00a1": { + "balance": "100000000000000000000" + }, + "2a81d27cb6d4770ff4f3c4a3ba18e5e57f07517c": { + "balance": "2000000000000000000000" + }, + "c4f7b13ac6d4eb4db3d4e6a252af8a07bd5957da": { + "balance": "200000000000000000000" + }, + "305d26c10bdc103f6b9c21272eb7cb2d9108c47e": { + "balance": "500000000000000000000" + }, + "d0d0a2ad45f59a9dccc695d85f25ca46ed31a5a3": { + "balance": "840000000000000000000" + }, + "522323aad71dbc96d85af90f084b99c3f09decb7": { + "balance": "6000000000000000000000" + }, + "f43da3a4e3f5fab104ca9bc1a0f7f3bb4a56f351": { + "balance": "1999944000000000000000" + }, + "a2dc65ee256b59a5bd7929774f904b358df3ada1": { + "balance": "21319600000000000000000" + }, + "f382df583155d8548f3f93440cd5f68cb79d6026": { + "balance": "266619800000000000000000" + }, + "0c967e3061b87a753e84507eb60986782c8f3013": { + "balance": "100000000000000000000" + }, + "a3a262afd2936819230892fde84f2d5a594ab283": { + "balance": "1880000000000000000000" + }, + "93868ddb2a794d02ebda2fa4807c76e3609858dc": { + "balance": "2027851000000000000000" + }, + "cd35ff010ec501a721a1b2f07a9ca5877dfcf95a": { + "balance": "4011000000000000000000" + }, + "5824a7e22838277134308c5f4b50dab65e43bb31": { + "balance": "6000000000000000000000" + }, + "7f7a3a21b3f5a65d81e0fcb7d52dd00a1aa36dba": { + "balance": "100000000000000000000" + }, + "30513fca9f36fd788cfea7a340e86df98294a244": { + "balance": "447000000000000000000" + }, + "283e6252b4efcf4654391acb75f903c59b78c5fb": { + "balance": "12000000000000000000000" + }, + "eddbaafbc21be8f25562f1ed6d05d6afb58f02c2": { + "balance": "2000000000000000000000" + }, + "0dcfe837ea1cf28c65fccec3bef1f84e59d150c0": { + "balance": "200000000000000000000" + }, + "828ba651cb930ed9787156299a3de44cd08b7212": { + "balance": "1337000000000000000000" + }, + "cfd47493c9f89fe680bda5754dd7c9cfe7cb5bbe": { + "balance": "54508000000000000000" + }, + "0e89eddd3fa0d71d8ab0ff8da5580686e3d4f74f": { + "balance": "2000000000000000000000" + }, + "205f5166f12440d85762c967d3ae86184f8f4d98": { + "balance": "432500000000000000000" + }, + "25dad495a11a86b9eeece1eeec805e57f157faff": { + "balance": "16000000000000000000000" + }, + "6c84cba77c6db4f7f90ef13d5ee21e8cfc7f8314": { + "balance": "2000000000000000000000" + }, + "91a787bc5196f34857fe0c372f4df376aaa76613": { + "balance": "2000000000000000000000" + }, + "b0d3c9872b85056ea0c0e6d1ecf7a77e3ce6ab85": { + "balance": "4999711000000000000000" + }, + "6e4d2e39c8836629e5b487b1918a669aebdd9536": { + "balance": "1000000000000000000000" + }, + "dc703a5f3794c84d6cb3544918cae14a35c3bd4f": { + "balance": "1850000000000000000000" + }, + "47beb20f759100542aa93d41118b3211d664920e": { + "balance": "2000000000000000000000" + }, + "5a7735007d70b06844da9901cdfadb11a2582c2f": { + "balance": "6000000000000000000000" + }, + "aff107960b7ec34ed690b665024d60838c190f70": { + "balance": "500000000000000000000" + }, + "563a03ab9c56b600f6d25b660c21e16335517a75": { + "balance": "1000000000000000000000" + }, + "a106465bbd19e1b6bce50d1b1157dc59095a3630": { + "balance": "2000000000000000000000" + }, + "ca9dec02841adf5cc920576a5187edd2bd434a18": { + "balance": "500000000000000000000" + }, + "572ac1aba0de23ae41a7cae1dc0842d8abfc103b": { + "balance": "1910000000000000000000" + }, + "5f74ed0e24ff80d9b2c4a44baa9975428cd6b935": { + "balance": "2980000000000000000000" + }, + "f2049532fd458a83ca1bff2eebacb6d5ca63f4a4": { + "balance": "3625693000000000000000" + }, + "cee699c0707a7836252b292f047ce8ad289b2f55": { + "balance": "324700000000000000000" + }, + "8b3696f3c60de32432a2e4c395ef0303b7e81e75": { + "balance": "30000000000000000000000" + }, + "13dee03e3799952d0738843d4be8fc0a803fb20e": { + "balance": "2000000000000000000000" + }, + "c853215b9b9f2d2cd0741e585e987b5fb80c212e": { + "balance": "1550000000000000000000" + }, + "851c0d62be4635d4777e8035e37e4ba8517c6132": { + "balance": "500000000000000000000" + }, + "a76b743f981b693072a131b22ba510965c2fefd7": { + "balance": "18200000000000000000" + }, + "69bd25ade1a3346c59c4e930db2a9d715ef0a27a": { + "balance": "4000000000000000000000" + }, + "0fec4ee0d7ca180290b6bd20f9992342f60ff68d": { + "balance": "334383000000000000000" + }, + "ccfd725760a68823ff1e062f4cc97e1360e8d997": { + "balance": "399800000000000000000" + }, + "9f017706b830fb9c30efb0a09f506b9157457534": { + "balance": "2000000000000000000000" + }, + "420fb86e7d2b51401fc5e8c72015decb4ef8fc2e": { + "balance": "1000000000000000000000" + }, + "cb7d2b8089e9312cc9aeaa2773f35308ec6c2a7b": { + "balance": "10000000000000000000000" + }, + "6c822029218ac8e98a260c1e064029348839875b": { + "balance": "5010000000000000000000" + }, + "1c68a66138783a63c98cc675a9ec77af4598d35e": { + "balance": "50100000000000000000" + }, + "f270792576f05d514493ffd1f5e84bec4b2df810": { + "balance": "1000000000000000000000" + }, + "9191f94698210516cf6321a142070e20597674ed": { + "balance": "17194000000000000000" + }, + "c0ca3277942e7445874be31ceb902972714f1823": { + "balance": "250000000000000000000" + }, + "35e096120deaa5c1ecb1645e2ccb8b4edbd9299a": { + "balance": "500000000000000000000" + }, + "e2bbf84641e3541f6c33e6ed683a635a70bde2ec": { + "balance": "502763000000000000000" + }, + "d12d77ae01a92d35117bac705aacd982d02e74c1": { + "balance": "1000000000000000000000" + }, + "dabb0889fc042926b05ef57b2520910abc4b4149": { + "balance": "2000000000000000000000" + }, + "5a1a336962d6e0c63031cc83c6a5c6a6f4478ecb": { + "balance": "1000000000000000000000" + }, + "abd154903513b8da4f019f68284b0656a1d0169b": { + "balance": "1000000000000000000000" + }, + "ad377cd25eb53e83ae091a0a1d2b4516f484afde": { + "balance": "1940000000000000000000" + }, + "08c2f236ac4adcd3fda9fbc6e4532253f9da3bec": { + "balance": "20000000000000000000" + }, + "71135d8f05963c905a4a07922909235a896a52ea": { + "balance": "3000000000000000000000" + }, + "080546508a3d2682c8b9884f13637b8847b44db3": { + "balance": "2000000000000000000000" + }, + "2d61bfc56873923c2b00095dc3eaa0f590d8ae0f": { + "balance": "20760000000000000000000" + }, + "cbfa6af6c283b046e2772c6063b0b21553c40106": { + "balance": "2000000000000000000000" + }, + "ccabc6048a53464424fcf76eeb9e6e1801fa23d4": { + "balance": "49250000000000000000" + }, + "60cc3d445ebdf76a7d7ae571c6971dff68cc8585": { + "balance": "1000000000000000000000" + }, + "fff33a3bd36abdbd412707b8e310d6011454a7ae": { + "balance": "8000000000000000000000" + }, + "d2dbebe89b0357aea98bbe8e496338debb28e805": { + "balance": "4000000000000000000000" + }, + "5f521282e9b278dc8c034c72af53ee29e5443d78": { + "balance": "6520000000000000000000" + }, + "c5a48a8500f9b4e22f0eb16c6f4649687674267d": { + "balance": "812721000000000000000" + }, + "8cb3aa3fcd212854d7578fcc30fdede6742a312a": { + "balance": "300000000000000000000" + }, + "90d2809ae1d1ffd8f63eda01de49dd552df3d1bc": { + "balance": "3998000000000000000000" + }, + "96a55f00dff405dc4de5e58c57f6f6f0cac55d2f": { + "balance": "1962711000000000000000" + }, + "ae842e81858ecfedf6506c686dc204ac15bf8b24": { + "balance": "40000000000000000000" + }, + "0be6a09e4307fe48d412b8d1a1a8284dce486261": { + "balance": "19180000000000000000000" + }, + "c9c7ac0bdd9342b5ead4360923f68c72a6ba633a": { + "balance": "500000000000000000000" + }, + "ea8f30b6e4c5e65290fb9864259bc5990fa8ee8a": { + "balance": "20000000000000000000" + }, + "74d37a51747bf8b771bfbf43943933d100d21483": { + "balance": "1000000000000000000000" + }, + "1a04d5389eb006f9ce880c30d15353f8d11c4b31": { + "balance": "17072800000000000000000" + }, + "726a14c90e3f84144c765cffacba3e0df11b48be": { + "balance": "10000000000000000000000" + }, + "86b7bd563ceab686f96244f9ddc02ad7b0b14bc2": { + "balance": "10000000000000000000000" + }, + "2bbe672a1857508f630f2a5edb563d9e9de92815": { + "balance": "2000000000000000000000" + }, + "a17070c2e9c5a940a4ec0e4954c4d7d643be8f49": { + "balance": "1999965000000000000000" + }, + "f2d1b7357724ec4c03185b879b63f57e26589153": { + "balance": "6000000000000000000000" + }, + "d6a7ac4de7b510f0e8de519d973fa4c01ba83400": { + "balance": "1880000000000000000000" + }, + "593b45a1864ac5c7e8f0caaeba0d873cd5d113b2": { + "balance": "6000000000000000000000" + }, + "0837539b5f6a522a482cdcd3a9bb7043af39bdd2": { + "balance": "6000000000000000000000" + }, + "b927abd2d28aaaa24db31778d27419df8e1b04bb": { + "balance": "27531000000000000000" + }, + "b2e085fddd1468ba07415b274e734e11237fb2a9": { + "balance": "100000000000000000000" + }, + "970938522afb5e8f994873c9fbdc26e3b37e314c": { + "balance": "1000000000000000000000" + }, + "f3de5f26ef6aded6f06d3b911346ee70401da4a0": { + "balance": "354718000000000000000" + }, + "bffb6929241f788693273e7022e60e3eab1fe84f": { + "balance": "2000000000000000000000" + }, + "b56ad2aec6c8c3f19e1515bbb7dd91285256b639": { + "balance": "1000000000000000000000" + }, + "47730f5f8ebf89ac72ef80e46c12195038ecdc49": { + "balance": "3160000000000000000000" + }, + "f39a9d7aa3581df07ee4279ae6c312ef21033658": { + "balance": "4000000000000000000000" + }, + "36227cdfa0fd3b9d7e6a744685f5be9aa366a7f0": { + "balance": "198479000000000000000" + }, + "89e3b59a15864737d493c1d23cc53dbf8dcb1362": { + "balance": "4000000000000000000000" + }, + "bd08e0cddec097db7901ea819a3d1fd9de8951a2": { + "balance": "20000000000000000000" + }, + "533444584082eba654e1ad30e149735c6f7ba922": { + "balance": "1730000000000000000000" + }, + "6a8a4317c45faa0554ccdb482548183e295a24b9": { + "balance": "1000000000000000000000" + }, + "22ce349159eeb144ef06ff2636588aef79f62832": { + "balance": "188000000000000000000" + }, + "3cd1d9731bd548c1dd6fcea61beb75d91754f7d3": { + "balance": "5130285000000000000000" + }, + "8b7056f6abf3b118d026e944d5c073433ca451d7": { + "balance": "999999000000000000000" + }, + "15f1b352110d68901d8f67aac46a6cfafe031477": { + "balance": "200000000000000000000" + }, + "0f789e30397c53bf256fc364e6ef39f853504114": { + "balance": "3640000000000000000000" + }, + "750bbb8c06bbbf240843cc75782ee02f08a97453": { + "balance": "835000000000000000000" + }, + "fff7ac99c8e4feb60c9750054bdc14ce1857f181": { + "balance": "1000000000000000000000" + }, + "5c6f36af90ab1a656c6ec8c7d521512762bba3e1": { + "balance": "1999800000000000000000" + }, + "6811b54cd19663b11b94da1de2448285cd9f68d9": { + "balance": "1100000000000000000000" + }, + "6f50929777824c291a49c46dc854f379a6bea080": { + "balance": "360000000000000000000" + }, + "e83604e4ff6be7f96f6018d3ec3072ec525dff6b": { + "balance": "182000000000000000000" + }, + "d731bb6b5f3c37395e09ceaccd14a918a6060789": { + "balance": "3940000000000000000000" + }, + "372e453a6b629f27678cc8aeb5e57ce85ec0aef9": { + "balance": "200000000000000000000" + }, + "86924fb211aad23cf5ce600e0aae806396444087": { + "balance": "10000000000000000000000" + }, + "18c6723a6753299cb914477d04a3bd218df8c775": { + "balance": "1000000000000000000000" + }, + "e00484788db50fc6a48e379d123e508b0f6e5ab1": { + "balance": "1000000000000000000000" + }, + "150e3dbcbcfc84ccf89b73427763a565c23e60d0": { + "balance": "40000000000000000000" + }, + "8ffa062122ac307418821adb9311075a3703bfa3": { + "balance": "1000000000000000000000" + }, + "21206ce22ea480e85940d31314e0d64f4e4d3a04": { + "balance": "1000000000000000000000" + }, + "ac024f594f9558f04943618eb0e6b2ee501dc272": { + "balance": "2000000000000000000000" + }, + "b2b7cdb4ff4b61d5b7ce0b2270bbb5269743ec04": { + "balance": "2000000000000000000000" + }, + "abc74706964960dfe0dca3dca79e9216056f1cf4": { + "balance": "40000000000000000000000" + }, + "d7eb903162271c1afa35fe69e37322c8a4d29b11": { + "balance": "10000000000000000000000" + }, + "d7c6265dea11876c903b718e4cd8ab24fe265bde": { + "balance": "2000000000000000000000" + }, + "cba288cd3c1eb4d59ddb06a6421c14c345a47b24": { + "balance": "4000000000000000000000" + }, + "8c22426055b76f11f0a2de1a7f819a619685fe60": { + "balance": "1980000000000000000000" + }, + "f463a90cb3f13e1f0643423636beab84c123b06d": { + "balance": "40000000000000000000" + }, + "2b5ced9987c0765f900e49cf9da2d9f9c1138855": { + "balance": "400000000000000000000" + }, + "9bb760d5c289a3e1db18db095345ca413b9a43c2": { + "balance": "197000000000000000000" + }, + "d66ab79294074c8b627d842dab41e17dd70c5de5": { + "balance": "1000000000000000000000" + }, + "0bdd58b96e7c916dd2fb30356f2aebfaaf1d8630": { + "balance": "2000000000000000000000" + }, + "d612597bc31743c78633f633f239b1e9426bd925": { + "balance": "76000000000000000000000" + }, + "140518a3194bad1350b8949e650565debe6db315": { + "balance": "2000000000000000000000" + }, + "daedd4ad107b271e89486cbf80ebd621dd974578": { + "balance": "2000000000000000000000" + }, + "c36c0b63bfd75c2f8efb060883d868cccd6cbdb4": { + "balance": "3000000000000000000000" + }, + "e646665872e40b0d7aa2ff82729caaba5bc3e89e": { + "balance": "400000000000000000000" + }, + "b5fb7ea2ddc1598b667a9d57dd39e85a38f35d56": { + "balance": "500000000000000000000" + }, + "e51421f8ee2210c71ed870fe618276c8954afbe9": { + "balance": "1337000000000000000000" + }, + "08a9a44e1f41de3dbba7a363a3ab412c124cd15e": { + "balance": "200000000000000000000" + }, + "562bced38ab2ab6c080f3b0541b8456e70824b3f": { + "balance": "641760000000000000000" + }, + "1e484d0621f0f5331b35d5408d9aae4eb1acf21e": { + "balance": "20000000000000000000" + }, + "3a476bd2c9e664c63ab266aa4c6e4a4825f516c3": { + "balance": "200000000000000000000" + }, + "8d6df209484d7b94702b03a53e56b9fb0660f6f0": { + "balance": "2000000000000000000000" + }, + "5970fb1b144dd751e4ce2eca7caa20e363dc4da3": { + "balance": "10000000000000000000000" + }, + "d1dd79fb158160e5b4e8e23f312e6a907fbc4d4e": { + "balance": "500000000000000000000" + }, + "7ee5ca805dce23af89c2d444e7e40766c54c7404": { + "balance": "240660000000000000000" + }, + "93e0f37ecdfb0086e3e862a97034447b1e4dec1a": { + "balance": "30000000000000000000" + }, + "e10ac19c546fc2547c61c139f5d1f45a6666d5b0": { + "balance": "4775000000000000000000" + }, + "1c73d00b6e25d8eb9c1ff4ad827b6b9e9cf6d20c": { + "balance": "200000000000000000000" + }, + "d771d9e0ca8a08a113775731434eb3270599c40d": { + "balance": "20000000000000000000" + }, + "e69d1c378b771e0feff051db69d966ac6779f4ed": { + "balance": "553000000000000000000" + }, + "0ef85b49d08a75198692914eddb4b22cf5fa4450": { + "balance": "2004800000000000000000" + }, + "ed70a37cdd1cbda9746d939658ae2a6181288578": { + "balance": "9600000000000000000000" + }, + "eee761847e33fd61d99387ee14628694d1bfd525": { + "balance": "2000000000000000000000" + }, + "271d3d481cb88e7671ad216949b6365e06303de0": { + "balance": "4000000000000000000000" + }, + "5255dc69155a45b970c604d30047e2f530690e7f": { + "balance": "20000000000000000000" + }, + "cabab6274ed15089737e287be878b757934864e2": { + "balance": "20000000000000000000000" + }, + "9defe56a0ff1a1947dba0923f7dd258d8f12fa45": { + "balance": "26880000000000000000000" + }, + "b7a2c103728b7305b5ae6e961c94ee99c9fe8e2b": { + "balance": "50000000000000000000000" + }, + "b498bb0f520005b6216a4425b75aa9adc52d622b": { + "balance": "4000000000000000000000" + }, + "c1132878235c5ddba5d9f3228b5236e47020dc6f": { + "balance": "1000000000000000000000" + }, + "f81622e55757daea6675975dd93538da7d16991e": { + "balance": "2000000000000000000000" + }, + "ce2deab51c0a9ae09cd212c4fa4cc52b53cc0dec": { + "balance": "2000000000000000000000" + }, + "86a1eadeeb30461345d9ef6bd05216fa247c0d0c": { + "balance": "2000000000000000000000" + }, + "7b1fe1ab4dfd0088cdd7f60163ef59ec2aee06f5": { + "balance": "2000000000000000000000" + }, + "6bbc3f358a668dd1a11f0380f3f73108426abd4a": { + "balance": "4000000000000000000000" + }, + "b1e6e810c24ab0488de9e01e574837829f7c77d0": { + "balance": "400000000000000000000" + }, + "03eb3cb860f6028da554d344a2bb5a500ae8b86f": { + "balance": "2000000000000000000000" + }, + "e5481a7fed42b901bbed20789bd4ade50d5f83b9": { + "balance": "2000000000000000000000" + }, + "1f3da68fe87eaf43a829ab6d7ec5a6e009b204fb": { + "balance": "554988000000000000000" + }, + "30037988702671acbe892c03fe5788aa98af287a": { + "balance": "2800000000000000000000" + }, + "edb473353979a206879de144c10a3c51d7d7081a": { + "balance": "6000000000000000000000" + }, + "22bdffc240a88ff7431af3bff50e14da37d5183e": { + "balance": "1000000000000000000000" + }, + "9374869d4a9911ee1eaf558bc4c2b63ec63acfdd": { + "balance": "1000000000000000000000" + }, + "b756ad52f3bf74a7d24c67471e0887436936504c": { + "balance": "20000000000000000000000" + }, + "8bd0b65a50ef5cef84fec420be7b89ed1470ceb9": { + "balance": "11999000000000000000000" + }, + "af26f7c6bf453e2078f08953e4b28004a2c1e209": { + "balance": "100000000000000000000" + }, + "7c532db9e0c06c26fd40acc56ac55c1ee92d3c3a": { + "balance": "300000000000000000000000" + }, + "dde670d01639667576a22dd05d3246d61f06e083": { + "balance": "26740000000000000000" + }, + "5cf44e10540d65716423b1bcb542d21ff83a94cd": { + "balance": "10000000000000000000000" + }, + "f96b4c00766f53736a8574f822e6474c2f21da2d": { + "balance": "400000000000000000000" + }, + "8d89170b92b2be2c08d57c48a7b190a2f146720f": { + "balance": "19700000000000000000000" + }, + "142b87c5043ffb5a91df18c2e109ced6fe4a71db": { + "balance": "200000000000000000000" + }, + "42d34940edd2e7005d46e2188e4cfece8311d74d": { + "balance": "158000000000000000000" + }, + "562105e82b099735de49f62692cc87cd38a8edcd": { + "balance": "6000000000000000000000" + }, + "457bcef37dd3d60b2dd019e3fe61d46b3f1e7252": { + "balance": "20000000000000000000" + }, + "cf8882359c0fb23387f5674074d8b17ade512f98": { + "balance": "6000000000000000000000" + }, + "f0c081da52a9ae36642adf5e08205f05c54168a6": { + "balance": "111000000000000000000" + }, + "551e7784778ef8e048e495df49f2614f84a4f1dc": { + "balance": "600000000000000000000" + }, + "3c869c09696523ced824a070414605bb76231ff2": { + "balance": "1000000000000000000000" + }, + "7e7f18a02eccaa5d61ab8fbf030343c434a25ef7": { + "balance": "66850000000000000000" + }, + "9328d55ccb3fce531f199382339f0e576ee840a3": { + "balance": "4000000000000000000000" + }, + "9d0f347e826b7dceaad279060a35c0061ecf334b": { + "balance": "4000000000000000000000" + }, + "680640838bd07a447b168d6d923b90cf6c43cdca": { + "balance": "1730000000000000000000" + }, + "c951900c341abbb3bafbf7ee2029377071dbc36a": { + "balance": "327600000000000000000" + }, + "ddf5810a0eb2fb2e32323bb2c99509ab320f24ac": { + "balance": "17900000000000000000000" + }, + "2489ac126934d4d6a94df08743da7b7691e9798e": { + "balance": "1000000000000000000000" + }, + "f42f905231c770f0a406f2b768877fb49eee0f21": { + "balance": "197000000000000000000" + }, + "756f45e3fa69347a9a973a725e3c98bc4db0b5a0": { + "balance": "200000000000000000000" + } + } +} diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 4c92d1083..0e90e3867 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -41,6 +41,8 @@ pub struct EthashParams { pub registrar: Address, /// Homestead transition block number. pub frontier_compatibility_mode_limit: u64, + /// Enable the soft-fork logic. + pub dao_rescue_soft_fork: bool, } impl From for EthashParams { @@ -53,6 +55,7 @@ impl From for EthashParams { block_reward: p.block_reward.into(), registrar: p.registrar.into(), frontier_compatibility_mode_limit: p.frontier_compatibility_mode_limit.into(), + dao_rescue_soft_fork: p.dao_rescue_soft_fork.into(), } } } @@ -102,7 +105,9 @@ impl Engine for Ethash { Schedule::new_frontier() } else { let mut s = Schedule::new_homestead(); - s.reject_dao_transactions = env_info.dao_rescue_block_gas_limit.map(|x| x <= 4_000_000.into()).unwrap_or(false); + if self.ethash_params.dao_rescue_soft_fork { + s.reject_dao_transactions = env_info.dao_rescue_block_gas_limit.map(|x| x <= 4_000_000.into()).unwrap_or(false); + } s } } diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index 9c9e48342..ed75576c6 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -33,7 +33,12 @@ use super::spec::*; pub fn new_olympic() -> Spec { Spec::load(include_bytes!("../../res/ethereum/olympic.json")) } /// Create a new Frontier mainnet chain spec. -pub fn new_frontier() -> Spec { Spec::load(include_bytes!("../../res/ethereum/frontier.json")) } +pub fn new_frontier(dao_rescue: bool) -> Spec { + Spec::load(match dao_rescue { + true => include_bytes!("../../res/ethereum/frontier_dao_rescue.json"), + false => include_bytes!("../../res/ethereum/frontier.json"), + }) +} /// Create a new Frontier chain spec as though it never changes to Homestead. pub fn new_frontier_test() -> Spec { Spec::load(include_bytes!("../../res/ethereum/frontier_test.json")) } @@ -84,7 +89,7 @@ mod tests { #[test] fn frontier() { - let frontier = new_frontier(); + let frontier = new_frontier(true); assert_eq!(frontier.state_root(), H256::from_str("d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544").unwrap()); let genesis = frontier.genesis_block(); diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index 254ffff9b..5cb7475f2 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -42,6 +42,9 @@ pub struct EthashParams { /// Homestead transition block number. #[serde(rename="frontierCompatibilityModeLimit")] pub frontier_compatibility_mode_limit: Uint, + /// DAO rescue soft-fork? + #[serde(rename="daoRescueSoftFork")] + pub dao_rescue_soft_fork: bool, } /// Ethash engine deserialization. @@ -65,8 +68,9 @@ mod tests { "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", - "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "frontierCompatibilityModeLimit" : "0x42" + "registrar": "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "frontierCompatibilityModeLimit": "0x42", + "daoRescueSoftFork": true } }"#; diff --git a/parity/cli.rs b/parity/cli.rs index 6fe38224a..39d7451ed 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -42,12 +42,20 @@ Protocol Options: [default: $HOME/.parity/keys]. --identity NAME Specify your node's name. +DAO-Rescue Soft-fork Options: + --rescue-my-ether Does nothing - on by default. + --assist-dao-attack Votes against the DAO-rescue soft-fork, but supports + it if it is triggered anyway. + Equivalent to --gas-floor-target=3141592. + --dogmatic Ignores all DAO-rescue soft-fork behaviour. Even if + it means losing mining rewards. + Account Options: --unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution. ACCOUNTS is a comma-delimited list of addresses. --password FILE Provide a file containing a password for unlocking an account. - --keys-iterations NUM Specify the number of iterations to use when + --keys-iterations NUM Specify the number of iterations to use when deriving key from the password (bigger is more secure) [default: 10240]. --no-import-keys Do not import keys from legacy clients. @@ -220,6 +228,8 @@ pub struct Args { pub flag_chain: String, pub flag_db_path: String, pub flag_identity: String, + pub flag_assist_dao_attack: bool, + pub flag_dogmatic: bool, pub flag_unlock: Option, pub flag_password: Vec, pub flag_cache: Option, diff --git a/parity/configuration.rs b/parity/configuration.rs index 3aff2ee27..637110a2c 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -75,12 +75,18 @@ impl Configuration { } pub fn gas_floor_target(&self) -> U256 { - let d = &self.args.flag_gas_floor_target; - U256::from_dec_str(d).unwrap_or_else(|_| { - die!("{}: Invalid target gas floor given. Must be a decimal unsigned 256-bit number.", d) - }) + if self.args.flag_assist_dao_attack || self.args.flag_dogmatic { + 4_700_000.into() + } else { + let d = &self.args.flag_gas_floor_target; + U256::from_dec_str(d).unwrap_or_else(|_| { + die!("{}: Invalid target gas floor given. Must be a decimal unsigned 256-bit number.", d) + }) + } } + + pub fn gas_price(&self) -> U256 { match self.args.flag_gasprice.as_ref() { Some(d) => { @@ -124,7 +130,7 @@ impl Configuration { pub fn spec(&self) -> Spec { match self.chain().as_str() { - "frontier" | "homestead" | "mainnet" => ethereum::new_frontier(), + "frontier" | "homestead" | "mainnet" => ethereum::new_frontier(!self.args.flag_dogmatic), "morden" | "testnet" => ethereum::new_morden(), "olympic" => ethereum::new_olympic(), f => Spec::load(contents(f).unwrap_or_else(|_| { diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 86f70ff0a..f4f017686 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -44,8 +44,8 @@ //! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap(); //! service.start().unwrap(); //! let dir = env::temp_dir(); -//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, Arc::new(Miner::default()), service.io().channel()).unwrap(); -//! let miner = Miner::new(false, ethereum::new_frontier()); +//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(true), &dir, Arc::new(Miner::default()), service.io().channel()).unwrap(); +//! let miner = Miner::new(false, ethereum::new_frontier(true)); //! let sync = EthSync::new(SyncConfig::default(), client); //! EthSync::register(&mut service, sync); //! } From 5ceb1b084cf2fb522ed329703784c0ed4ff91ad0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 19 Jun 2016 14:49:06 +0200 Subject: [PATCH 084/239] Add missing args and some new JSONs for testing. --- ethcore/res/ethereum/frontier_like_test.json | 3 +- .../frontier_like_test_dao_rescue.json | 43 +++++++++++++++++++ ethcore/res/ethereum/frontier_test.json | 3 +- ethcore/res/ethereum/homestead_test.json | 3 +- .../ethereum/homestead_test_dao_rescue.json | 43 +++++++++++++++++++ ethcore/res/ethereum/morden.json | 3 +- ethcore/res/ethereum/olympic.json | 3 +- 7 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 ethcore/res/ethereum/frontier_like_test_dao_rescue.json create mode 100644 ethcore/res/ethereum/homestead_test_dao_rescue.json diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index ca31927e7..78299bf4e 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -9,7 +9,8 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "frontierCompatibilityModeLimit": "0x118c30" + "frontierCompatibilityModeLimit": "0x118c30", + "daoRescueSoftFork": false } } }, diff --git a/ethcore/res/ethereum/frontier_like_test_dao_rescue.json b/ethcore/res/ethereum/frontier_like_test_dao_rescue.json new file mode 100644 index 000000000..ba0881508 --- /dev/null +++ b/ethcore/res/ethereum/frontier_like_test_dao_rescue.json @@ -0,0 +1,43 @@ +{ + "name": "Frontier (Test)", + "engine": { + "Ethash": { + "params": { + "gasLimitBoundDivisor": "0x0400", + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "frontierCompatibilityModeLimit": "0x118c30", + "daoRescueSoftFork": true + } + } + }, + "params": { + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x1" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388" + }, + "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 } } } } + } +} diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json index 3964d33ad..d12390eb9 100644 --- a/ethcore/res/ethereum/frontier_test.json +++ b/ethcore/res/ethereum/frontier_test.json @@ -9,7 +9,8 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "frontierCompatibilityModeLimit": "0xffffffffffffffff" + "frontierCompatibilityModeLimit": "0xffffffffffffffff", + "daoRescueSoftFork": false } } }, diff --git a/ethcore/res/ethereum/homestead_test.json b/ethcore/res/ethereum/homestead_test.json index a0e3df275..6d38c29c0 100644 --- a/ethcore/res/ethereum/homestead_test.json +++ b/ethcore/res/ethereum/homestead_test.json @@ -9,7 +9,8 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "frontierCompatibilityModeLimit": 0 + "frontierCompatibilityModeLimit": 0, + "daoRescueSoftFork": false } } }, diff --git a/ethcore/res/ethereum/homestead_test_dao_rescue.json b/ethcore/res/ethereum/homestead_test_dao_rescue.json new file mode 100644 index 000000000..7dbe4b321 --- /dev/null +++ b/ethcore/res/ethereum/homestead_test_dao_rescue.json @@ -0,0 +1,43 @@ +{ + "name": "Homestead (Test)", + "engine": { + "Ethash": { + "params": { + "gasLimitBoundDivisor": "0x0400", + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "frontierCompatibilityModeLimit": 0, + "daoRescueSoftFork": true + } + } + }, + "params": { + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x1" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388" + }, + "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 } } } } + } +} diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index 0cc88ac64..c7836bd91 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -9,7 +9,8 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar": "", - "frontierCompatibilityModeLimit": "0x789b0" + "frontierCompatibilityModeLimit": "0x789b0", + "daoRescueSoftFork": false } } }, diff --git a/ethcore/res/ethereum/olympic.json b/ethcore/res/ethereum/olympic.json index 1e0c210b5..86dfc15b7 100644 --- a/ethcore/res/ethereum/olympic.json +++ b/ethcore/res/ethereum/olympic.json @@ -9,7 +9,8 @@ "durationLimit": "0x08", "blockReward": "0x14D1120D7B160000", "registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050", - "frontierCompatibilityModeLimit": "0xffffffffffffffff" + "frontierCompatibilityModeLimit": "0xffffffffffffffff", + "daoRescueSoftFork": false } } }, From 08522eec37c0d76bc73b08b2cc405ac75de5c8e9 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 19 Jun 2016 14:51:51 +0200 Subject: [PATCH 085/239] --geth prevent getTransactionReceipt from using pending. (#1325) This mimics the fucntionality of Geth and the current unratified JSONRPC spec (but not the functionality of eth and the ratified spec). --- ethcore/src/miner/miner.rs | 10 +++++++--- ethcore/src/miner/transaction_queue.rs | 2 +- parity/cli.rs | 7 ++++--- parity/main.rs | 1 + parity/rpc_apis.rs | 3 ++- rpc/rpctest/src/main.rs | 2 +- rpc/src/v1/impls/eth.rs | 8 +++++--- rpc/src/v1/tests/eth.rs | 3 ++- rpc/src/v1/tests/mocked/eth.rs | 2 +- 9 files changed, 24 insertions(+), 14 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index ef59de1ec..c5dff80d0 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -385,9 +385,13 @@ impl MinerService for Miner { .collect() } - fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction, fetch_account: T) -> - Result - where T: Fn(&Address) -> AccountDetails { + fn import_own_transaction( + &self, + chain: &MiningBlockChainClient, + transaction: SignedTransaction, + fetch_account: T + ) -> Result where T: Fn(&Address) -> AccountDetails { + let hash = transaction.hash(); trace!(target: "own_tx", "Importing transaction: {:?}", transaction); diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 8f34d78d1..98aa492d1 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -425,7 +425,7 @@ impl TransactionQueue { /// Add signed transaction to queue to be verified and imported pub fn add(&mut self, tx: SignedTransaction, fetch_account: &T, origin: TransactionOrigin) -> Result - where T: Fn(&Address) -> AccountDetails { + where T: Fn(&Address) -> AccountDetails { trace!(target: "miner", "Importing: {:?}", tx.hash()); diff --git a/parity/cli.rs b/parity/cli.rs index 6fe38224a..38af6af4c 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -168,9 +168,10 @@ Virtual Machine Options: --jitvm Enable the JIT VM. Legacy Options: - --geth Run in Geth-compatibility mode. Currently just sets - the IPC path to be the same as Geth's. Overrides - the --ipc-path/--ipcpath options. + --geth Run in Geth-compatibility mode. Sets the IPC path + to be the same as Geth's. Overrides the --ipc-path + and --ipcpath options. Alters RPCs to reflect Geth + bugs. --testnet Geth-compatible testnet mode. Equivalent to --chain testnet --keys-path $HOME/parity/testnet-keys. Overrides the --keys-path option. diff --git a/parity/main.rs b/parity/main.rs index 973b1174f..cfa44f6ee 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -222,6 +222,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) external_miner: external_miner.clone(), logger: logger.clone(), settings: network_settings.clone(), + allow_pending_receipt_query: !conf.args.flag_geth, }); let dependencies = rpc::Dependencies { diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 016f347aa..feefc89c0 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -88,6 +88,7 @@ pub struct Dependencies { pub external_miner: Arc, pub logger: Arc, pub settings: Arc, + pub allow_pending_receipt_query: bool, } fn to_modules(apis: &[Api]) -> BTreeMap { @@ -143,7 +144,7 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet server.add_delegate(NetClient::new(&deps.sync).to_delegate()); }, Api::Eth => { - server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner).to_delegate()); + server.add_delegate(EthClient::new(&deps.client, &deps.sync, &deps.secret_store, &deps.miner, &deps.external_miner, deps.allow_pending_receipt_query).to_delegate()); server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); if deps.signer_port.is_some() { diff --git a/rpc/rpctest/src/main.rs b/rpc/rpctest/src/main.rs index 6cc747959..139514cb1 100644 --- a/rpc/rpctest/src/main.rs +++ b/rpc/rpctest/src/main.rs @@ -123,7 +123,7 @@ impl Configuration { accs.insert(Address::from(1), TestAccount::new("test")); let accounts = Arc::new(TestAccountProvider::new(accs)); let server = rpc::RpcServer::new(); - server.add_delegate(EthClient::new(&client, &sync, &accounts, &miner).to_delegate()); + server.add_delegate(EthClient::new(&client, &sync, &accounts, &miner, true).to_delegate()); server.add_delegate(EthFilterClient::new(&client, &miner).to_delegate()); let url = format!("{}:{}", self.args.flag_jsonrpc_addr, self.args.flag_jsonrpc_port); diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index bd9384dfe..2c070cab9 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -54,6 +54,7 @@ pub struct EthClient where miner: Weak, external_miner: Arc, seed_compute: Mutex, + allow_pending_receipt_query: bool, } impl EthClient where @@ -64,7 +65,7 @@ impl EthClient where EM: ExternalMinerService { /// Creates new EthClient. - pub fn new(client: &Arc, sync: &Arc, accounts: &Arc, miner: &Arc, em: &Arc) + pub fn new(client: &Arc, sync: &Arc, accounts: &Arc, miner: &Arc, em: &Arc, allow_pending_receipt_query: bool) -> EthClient { EthClient { client: Arc::downgrade(client), @@ -73,6 +74,7 @@ impl EthClient where accounts: Arc::downgrade(accounts), external_miner: em.clone(), seed_compute: Mutex::new(SeedHashCompute::new()), + allow_pending_receipt_query: allow_pending_receipt_query, } } @@ -423,8 +425,8 @@ impl Eth for EthClient where .and_then(|(hash,)| { let miner = take_weak!(self.miner); match miner.pending_receipts().get(&hash) { - Some(receipt) => to_value(&Receipt::from(receipt.clone())), - None => { + Some(receipt) if self.allow_pending_receipt_query => to_value(&Receipt::from(receipt.clone())), + _ => { let client = take_weak!(self.client); let receipt = client.transaction_receipt(TransactionID::Hash(hash)); to_value(&receipt.map(Receipt::from)) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index a7f7920ad..5d7c72ac0 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -107,7 +107,8 @@ impl EthTester { &sync_provider, &account_provider, &miner_service, - &external_miner + &external_miner, + true ); let eth_sign = EthSigningUnsafeClient::new( &client, diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 45f8bd366..2fcd8a266 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -71,7 +71,7 @@ impl Default for EthTester { let miner = miner_service(); let hashrates = Arc::new(RwLock::new(HashMap::new())); let external_miner = Arc::new(ExternalMiner::new(hashrates.clone())); - let eth = EthClient::new(&client, &sync, &ap, &miner, &external_miner).to_delegate(); + let eth = EthClient::new(&client, &sync, &ap, &miner, &external_miner, true).to_delegate(); let sign = EthSigningUnsafeClient::new(&client, &ap, &miner).to_delegate(); let io = IoHandler::new(); io.add_delegate(eth); From a4dacca262f289a6e5f73f471452f3fb8c7f77a0 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Sun, 19 Jun 2016 15:59:12 +0200 Subject: [PATCH 086/239] CLI option and network configuration --- parity/cli.rs | 4 ++++ parity/configuration.rs | 19 +++++++++++++++++++ util/src/network/host.rs | 2 ++ 3 files changed, 25 insertions(+) diff --git a/parity/cli.rs b/parity/cli.rs index 38af6af4c..8c6f2d72d 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -67,6 +67,9 @@ Networking Options: --no-discovery Disable new peer discovery. --node-key KEY Specify node secret key, either as 64-character hex string or input to SHA3 operation. + --reserved-peers FILE Provide a file containing enodes, one per line. + These nodes will always have a reserved slot on top + of the normal maximum peers. API and Console Options: --jsonrpc-off Disable the JSON-RPC API server. @@ -236,6 +239,7 @@ pub struct Args { pub flag_no_discovery: bool, pub flag_nat: String, pub flag_node_key: Option, + pub flag_reserved_peers: Option, pub flag_cache_pref_size: usize, pub flag_cache_max_size: usize, pub flag_queue_max_size: usize, diff --git a/parity/configuration.rs b/parity/configuration.rs index 3aff2ee27..666eabdda 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -153,6 +153,24 @@ impl Configuration { } } + pub fn init_reserved_nodes(&self) -> Vec { + use std::fs::File; + use std::io::BufRead; + + if let Some(ref path) = self.args.reserved_nodes { + let node_file = File::open(path).unwrap_or_else(|e| { + die!("Error opening reserved nodes file: {}", e); + }); + node_file.lines().map(|s| { + Self::normalize_enode(s).unwrap_or_else(|| { + die!("{}: Invalid node address format given for a reserved node.", s); + }) + }).collect() + } else { + Vec::new() + } + } + pub fn net_addresses(&self) -> (Option, Option) { let port = self.net_port(); let listen_address = Some(SocketAddr::new(IpAddr::from_str("0.0.0.0").unwrap(), port)); @@ -179,6 +197,7 @@ impl Configuration { let mut net_path = PathBuf::from(&self.path()); net_path.push("network"); ret.config_path = Some(net_path.to_str().unwrap().to_owned()); + ret.reserved_nodes = self.init_reserved_nodes(); ret } diff --git a/util/src/network/host.rs b/util/src/network/host.rs index aef56fc09..c6810abb7 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -73,6 +73,8 @@ pub struct NetworkConfiguration { pub use_secret: Option, /// Number of connected peers to maintain pub ideal_peers: u32, + /// List of reserved node addresses. + pub reserved_nodes: Vec, } impl Default for NetworkConfiguration { From d8fca91a2ff95ea8028b83e6ced4f2e1b50fd870 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Sun, 19 Jun 2016 16:59:43 +0200 Subject: [PATCH 087/239] add daoRescueSoftFork to failing rpc and json tests --- json/src/spec/engine.rs | 3 ++- json/src/spec/spec.rs | 3 ++- rpc/src/v1/tests/eth.rs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/json/src/spec/engine.rs b/json/src/spec/engine.rs index e877e37a8..9659d8af7 100644 --- a/json/src/spec/engine.rs +++ b/json/src/spec/engine.rs @@ -53,7 +53,8 @@ mod tests { "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "frontierCompatibilityModeLimit" : "0x" + "frontierCompatibilityModeLimit" : "0x", + "daoRescueSoftFork": true } } }"#; diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs index fbb206c40..08724ca56 100644 --- a/json/src/spec/spec.rs +++ b/json/src/spec/spec.rs @@ -63,7 +63,8 @@ mod tests { "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "frontierCompatibilityModeLimit" : "0x" + "frontierCompatibilityModeLimit" : "0x", + "daoRescueSoftFork": false } } }, diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index a7f7920ad..7bc34d306 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -187,7 +187,8 @@ const TRANSACTION_COUNT_SPEC: &'static [u8] = br#"{ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "frontierCompatibilityModeLimit": "0xffffffffffffffff" + "frontierCompatibilityModeLimit": "0xffffffffffffffff", + "daoRescueSoftFork": false } } }, From 2ea45134ab33f8cf87b2ba614b0e0d422e784ab5 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Sun, 19 Jun 2016 20:57:54 +0200 Subject: [PATCH 088/239] prefer pinned nodes when establishing peer connections. --- util/src/network/host.rs | 55 +++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/util/src/network/host.rs b/util/src/network/host.rs index c6810abb7..25b1629f8 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -97,6 +97,7 @@ impl NetworkConfiguration { boot_nodes: Vec::new(), use_secret: None, ideal_peers: 25, + reserved_nodes: Vec::new(), } } @@ -218,7 +219,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone pub fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec) -> Result<(), UtilError> { let session = self.resolve_session(peer); if let Some(session) = session { - try!(session.lock().unwrap().deref_mut().send_packet(self.io, self.protocol, packet_id as u8, &data)); + try!(session.lock().unwrap().send_packet(self.io, self.protocol, packet_id as u8, &data)); } else { trace!(target: "network", "Send: Peer no longer exist") } @@ -367,6 +368,9 @@ impl Host where Message: Send + Sync + Clone { let udp_port = config.udp_port.unwrap_or(listen_address.port()); let local_endpoint = NodeEndpoint { address: listen_address, udp_port: udp_port }; + let boot_nodes = config.boot_nodes.clone(); + let reserved_nodes = config.reserved_nodes.clone(); + let mut host = Host:: { info: RwLock::new(HostInfo { keys: keys, @@ -391,21 +395,26 @@ impl Host where Message: Send + Sync + Clone { stopping: AtomicBool::new(false), }; - let boot_nodes = host.info.read().unwrap().config.boot_nodes.clone(); for n in boot_nodes { - host.add_node(&n); + // don't pin boot nodes. + host.add_node(&n, false); + } + + for n in reserved_nodes { + host.add_node(&n, true); } Ok(host) } - pub fn add_node(&mut self, id: &str) { + pub fn add_node(&mut self, id: &str, pin: bool) { match Node::from_str(id) { Err(e) => { debug!(target: "network", "Could not add node {}: {:?}", id, e); }, Ok(n) => { let entry = NodeEntry { endpoint: n.endpoint.clone(), id: n.id.clone() }; - self.pinned_nodes.push(n.id.clone()); + if pin { self.pinned_nodes.push(n.id.clone()) } + self.nodes.write().unwrap().add_node(n); - if let Some(ref mut discovery) = *self.discovery.lock().unwrap().deref_mut() { + if let Some(ref mut discovery) = *self.discovery.lock().unwrap() { discovery.add_node(entry); } } @@ -484,7 +493,7 @@ impl Host where Message: Send + Sync + Clone { for n in self.nodes.read().unwrap().unordered_entries() { discovery.add_node(n.clone()); } - *self.discovery.lock().unwrap().deref_mut() = Some(discovery); + *self.discovery.lock().unwrap() = Some(discovery); io.register_stream(DISCOVERY).expect("Error registering UDP listener"); io.register_timer(DISCOVERY_REFRESH, 7200).expect("Error registering discovery timer"); io.register_timer(DISCOVERY_ROUND, 300).expect("Error registering discovery timer"); @@ -531,14 +540,17 @@ impl Host where Message: Send + Sync + Clone { } fn connect_peers(&self, io: &IoContext>) { - if self.info.read().unwrap().deref().capabilities.is_empty() { + if self.info.read().unwrap().capabilities.is_empty() { return; } - let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; - let pin = { self.info.read().unwrap().deref().config.pin }; + let ideal_peers = { self.info.read().unwrap().config.ideal_peers }; + let pin = { self.info.read().unwrap().config.pin }; let session_count = self.session_count(); - if session_count >= ideal_peers as usize { - return; + if session_count >= ideal_peers as usize + self.pinned_nodes.len() { + // check if all pinned nodes are connected. + if self.pinned_nodes.iter().all(|n| self.have_session(n) && self.connecting_to(n)) { + return; + } } let handshake_count = self.handshake_count(); @@ -548,9 +560,16 @@ impl Host where Message: Send + Sync + Clone { return; } - let nodes = if pin { self.pinned_nodes.clone() } else { self.nodes.read().unwrap().nodes() }; + // iterate over all nodes, reserved ones coming first. + // if we are pinned to only reserved nodes, ignore all others. + let nodes = self.pinned_nodes.iter().cloned().chain(if !pin { + self.nodes.read().unwrap().nodes() + } else { + Vec::new() + }); + let mut started: usize = 0; - for id in nodes.iter().filter(|ref id| !self.have_session(id) && !self.connecting_to(id)) + for id in nodes.filter(|ref id| !self.have_session(id) && !self.connecting_to(id)) .take(min(MAX_HANDSHAKES_PER_ROUND, handshake_limit - handshake_count)) { self.connect_peer(&id, io); started += 1; @@ -680,7 +699,7 @@ impl Host where Message: Send + Sync + Clone { self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); if !s.info.originated { let session_count = self.session_count(); - let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; + let ideal_peers = { self.info.read().unwrap().config.ideal_peers }; if session_count >= ideal_peers as usize { s.disconnect(io, DisconnectReason::TooManyPeers); return; @@ -902,7 +921,7 @@ impl IoHandler> for Host where Messa } => { let handler_token = { let mut timer_counter = self.timer_counter.write().unwrap(); - let counter = timer_counter.deref_mut(); + let counter = &mut *timer_counter; let handler_token = *counter; *counter += 1; handler_token @@ -946,7 +965,7 @@ impl IoHandler> for Host where Messa } } DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().register_socket(event_loop).expect("Error registering discovery socket"), - TCP_ACCEPT => event_loop.register(self.tcp_listener.lock().unwrap().deref(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error registering stream"), + TCP_ACCEPT => event_loop.register(&*self.tcp_listener.lock().unwrap(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error registering stream"), _ => warn!("Unexpected stream registration") } } @@ -974,7 +993,7 @@ impl IoHandler> for Host where Messa } } DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().update_registration(event_loop).expect("Error reregistering discovery socket"), - TCP_ACCEPT => event_loop.reregister(self.tcp_listener.lock().unwrap().deref(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error reregistering stream"), + TCP_ACCEPT => event_loop.reregister(&*self.tcp_listener.lock().unwrap(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error reregistering stream"), _ => warn!("Unexpected stream update") } } From ab4561b5bcfcd76ff1e1fa133fd4926fa52d9d14 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Sun, 19 Jun 2016 21:34:02 +0200 Subject: [PATCH 089/239] fix compilation errors --- parity/configuration.rs | 8 +++++--- parity/main.rs | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index 666eabdda..e2a8f94b6 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -157,11 +157,13 @@ impl Configuration { use std::fs::File; use std::io::BufRead; - if let Some(ref path) = self.args.reserved_nodes { - let node_file = File::open(path).unwrap_or_else(|e| { + if let Some(ref path) = self.args.flag_reserved_peers { + let mut buffer = String::new(); + let mut node_file = File::open(path).unwrap_or_else(|e| { die!("Error opening reserved nodes file: {}", e); }); - node_file.lines().map(|s| { + node_file.read_to_string(&mut buffer).expect("Error reading reserved node file"); + buffer.lines().map(|s| { Self::normalize_enode(s).unwrap_or_else(|| { die!("{}: Invalid node address format given for a reserved node.", s); }) diff --git a/parity/main.rs b/parity/main.rs index cfa44f6ee..d5e61a842 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -312,6 +312,7 @@ fn execute_export(conf: Configuration) { boot_nodes: Vec::new(), use_secret: None, ideal_peers: 0, + reserved_nodes: Vec::new(), }; let client_config = conf.client_config(&spec); @@ -383,6 +384,7 @@ fn execute_import(conf: Configuration) { boot_nodes: Vec::new(), use_secret: None, ideal_peers: 0, + reserved_nodes: Vec::new(), }; let client_config = conf.client_config(&spec); From 6b074e8fb2968a52b8c5ded9901e03df83de23b3 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 20 Jun 2016 00:10:34 +0200 Subject: [PATCH 090/239] secret store separated from util (#1304) * bump rust-crypto * initial version of account provider utilizing secret store * update lazy_static to latest version * AccountProvider accounts method * new AccountProvider tests in progress * basic tests for new AccountProvider * ethcore compiles with new account provider and secret store * ethcore-rpc build now compiling with new AccountProvider * most rpc tests passing with new accounts_provider * fixed basic_authority tests * fixed eth_transaction_count rpc test * fixed mocked/eth.rs tests * fixed personal tests * fixed personal signer rpc tests * removed warnings * parity compiling fine with new sstore * fixed import direction * do not unlock temporarily when we have the password * removed TODO in account import * display warning on auto account import failure * fixed compiling of ethstore on windows * ethstore as a part of parity repo * added ethkey --- Cargo.lock | 90 +- ethcore/Cargo.toml | 3 +- ethcore/src/account_provider.rs | 266 +++++ ethcore/src/basic_authority.rs | 50 +- ethcore/src/engine.rs | 2 +- ethcore/src/lib.rs | 4 +- ethcore/src/miner/miner.rs | 2 +- ethcore/src/types/transaction.rs | 9 +- ethkey/.gitignore | 2 + ethkey/.travis.yml | 23 + ethkey/Cargo.toml | 21 + ethkey/README.md | 150 +++ ethkey/src/bin/ethkey.rs | 274 +++++ ethkey/src/bin/main.rs | 5 + ethkey/src/brain.rs | 46 + ethkey/src/error.rs | 53 + ethkey/src/keccak.rs | 15 + ethkey/src/keypair.rs | 91 ++ ethkey/src/lib.rs | 33 + ethkey/src/prefix.rs | 41 + ethkey/src/primitive.rs | 122 ++ ethkey/src/random.rs | 16 + ethkey/src/signature.rs | 158 +++ ethstore/.editorconfig | 11 + ethstore/.gitignore | 2 + ethstore/.travis.yml | 23 + ethstore/Cargo.toml | 30 + ethstore/README.md | 162 +++ ethstore/build.rs | 29 + ethstore/src/account/cipher.rs | 43 + ethstore/src/account/kdf.rs | 109 ++ ethstore/src/account/mod.rs | 9 + ethstore/src/account/safe_account.rs | 200 ++++ ethstore/src/account/version.rs | 22 + ethstore/src/bin/ethstore.rs | 128 ++ ethstore/src/bin/main.rs | 5 + ethstore/src/crypto.rs | 69 ++ ethstore/src/dir/disk.rs | 109 ++ ethstore/src/dir/geth.rs | 79 ++ ethstore/src/dir/mod.rs | 21 + ethstore/src/dir/parity.rs | 58 + ethstore/src/error.rs | 42 + ethstore/src/ethkey.rs | 17 + ethstore/src/ethstore.rs | 92 ++ ethstore/src/import.rs | 12 + ethstore/src/json/cipher.rs | 75 ++ ethstore/src/json/crypto.rs | 184 +++ ethstore/src/json/error.rs | 34 + ethstore/src/json/hash.rs | 71 ++ ethstore/src/json/id.rs | 129 ++ ethstore/src/json/kdf.rs | 133 +++ ethstore/src/json/key_file.rs | 255 ++++ ethstore/src/json/mod.rs | 8 + ethstore/src/json/mod.rs.in | 18 + ethstore/src/json/version.rs | 38 + ethstore/src/lib.rs | 32 + ethstore/src/random.rs | 23 + ethstore/src/secret_store.rs | 15 + ethstore/tests/api.rs | 72 ++ ethstore/tests/cli.rs | 0 ethstore/tests/util/mod.rs | 3 + ethstore/tests/util/transient_dir.rs | 58 + parity/configuration.rs | 33 +- parity/io_handler.rs | 9 +- parity/main.rs | 21 +- parity/rpc_apis.rs | 4 +- rpc/src/v1/impls/eth.rs | 22 +- rpc/src/v1/impls/eth_signing.rs | 38 +- rpc/src/v1/impls/mod.rs | 58 +- rpc/src/v1/impls/personal.rs | 32 +- rpc/src/v1/impls/personal_signer.rs | 31 +- rpc/src/v1/tests/eth.rs | 24 +- rpc/src/v1/tests/mocked/eth.rs | 44 +- rpc/src/v1/tests/mocked/eth_signing.rs | 5 +- rpc/src/v1/tests/mocked/personal.rs | 51 +- rpc/src/v1/tests/mocked/personal_signer.rs | 27 +- sync/src/chain.rs | 5 +- util/Cargo.toml | 2 +- util/src/keys/directory.rs | 1247 -------------------- util/src/keys/geth_import.rs | 261 ---- util/src/keys/mod.rs | 26 - util/src/keys/store.rs | 754 ------------ util/src/keys/test_account_provider.rs | 118 -- util/src/lib.rs | 1 - 84 files changed, 4027 insertions(+), 2682 deletions(-) create mode 100644 ethcore/src/account_provider.rs create mode 100644 ethkey/.gitignore create mode 100644 ethkey/.travis.yml create mode 100644 ethkey/Cargo.toml create mode 100644 ethkey/README.md create mode 100644 ethkey/src/bin/ethkey.rs create mode 100644 ethkey/src/bin/main.rs create mode 100644 ethkey/src/brain.rs create mode 100644 ethkey/src/error.rs create mode 100644 ethkey/src/keccak.rs create mode 100644 ethkey/src/keypair.rs create mode 100644 ethkey/src/lib.rs create mode 100644 ethkey/src/prefix.rs create mode 100644 ethkey/src/primitive.rs create mode 100644 ethkey/src/random.rs create mode 100644 ethkey/src/signature.rs create mode 100644 ethstore/.editorconfig create mode 100644 ethstore/.gitignore create mode 100644 ethstore/.travis.yml create mode 100644 ethstore/Cargo.toml create mode 100644 ethstore/README.md create mode 100644 ethstore/build.rs create mode 100644 ethstore/src/account/cipher.rs create mode 100644 ethstore/src/account/kdf.rs create mode 100644 ethstore/src/account/mod.rs create mode 100644 ethstore/src/account/safe_account.rs create mode 100644 ethstore/src/account/version.rs create mode 100644 ethstore/src/bin/ethstore.rs create mode 100644 ethstore/src/bin/main.rs create mode 100644 ethstore/src/crypto.rs create mode 100644 ethstore/src/dir/disk.rs create mode 100644 ethstore/src/dir/geth.rs create mode 100644 ethstore/src/dir/mod.rs create mode 100644 ethstore/src/dir/parity.rs create mode 100644 ethstore/src/error.rs create mode 100644 ethstore/src/ethkey.rs create mode 100644 ethstore/src/ethstore.rs create mode 100644 ethstore/src/import.rs create mode 100644 ethstore/src/json/cipher.rs create mode 100644 ethstore/src/json/crypto.rs create mode 100644 ethstore/src/json/error.rs create mode 100644 ethstore/src/json/hash.rs create mode 100644 ethstore/src/json/id.rs create mode 100644 ethstore/src/json/kdf.rs create mode 100644 ethstore/src/json/key_file.rs create mode 100644 ethstore/src/json/mod.rs create mode 100644 ethstore/src/json/mod.rs.in create mode 100644 ethstore/src/json/version.rs create mode 100644 ethstore/src/lib.rs create mode 100644 ethstore/src/random.rs create mode 100644 ethstore/src/secret_store.rs create mode 100644 ethstore/tests/api.rs create mode 100644 ethstore/tests/cli.rs create mode 100644 ethstore/tests/util/mod.rs create mode 100644 ethstore/tests/util/transient_dir.rs delete mode 100644 util/src/keys/directory.rs delete mode 100644 util/src/keys/geth_import.rs delete mode 100644 util/src/keys/mod.rs delete mode 100644 util/src/keys/store.rs delete mode 100644 util/src/keys/test_account_provider.rs diff --git a/Cargo.lock b/Cargo.lock index 8bf4de9e6..2ac272e7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -180,7 +180,7 @@ version = "1.1.1" source = "git+https://github.com/ethcore/rust-ctrlc.git#f4927770f89eca80ec250911eea3adcbf579ac48" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -189,7 +189,7 @@ name = "daemonize" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -231,7 +231,7 @@ source = "git+https://github.com/ethcore/rust-secp256k1#b6fdd43bbcf6d46adb72a92d dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -261,8 +261,9 @@ dependencies = [ "ethcore-ipc-codegen 1.2.0", "ethcore-util 1.2.0", "ethjson 0.1.0", + "ethstore 0.1.0", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -390,8 +391,8 @@ dependencies = [ "igd 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "json-tests 0.1.0", - "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", "nix 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -421,6 +422,35 @@ dependencies = [ "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethkey" +version = "0.2.0" +dependencies = [ + "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", + "eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)", + "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethstore" +version = "0.1.0" +dependencies = [ + "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.2.0", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ethsync" version = "1.2.0" @@ -439,7 +469,7 @@ dependencies = [ name = "fdlimit" version = "0.1.0" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -570,12 +600,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "json-ipc-server" version = "0.2.3" -source = "git+https://github.com/ethcore/json-ipc-server.git#b224bdbcb53cab349c278484bd3e5e22390167c9" +source = "git+https://github.com/ethcore/json-ipc-server.git#bfe16b66b2e9412d153b1ea53bc078d74037da7f" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -632,12 +662,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "0.1.16" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -655,7 +685,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -692,7 +722,7 @@ version = "0.5.0" source = "git+https://github.com/carllerche/mio.git#f4aa49a9d2c4507fb33a4533d5238e0365f67c99" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -708,7 +738,7 @@ version = "0.5.1" source = "git+https://github.com/ethcore/mio?branch=v0.5.x#1fc881771fb8c2517317b4f805d7b88235be422b" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -724,7 +754,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", @@ -750,7 +780,7 @@ name = "nanomsg" version = "0.5.1" source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "nanomsg-sys 0.5.0 (git+https://github.com/ethcore/nanomsg.rs.git)", ] @@ -760,7 +790,7 @@ version = "0.5.0" source = "git+https://github.com/ethcore/nanomsg.rs.git#c40fe442c9afaea5b38009a3d992ca044dcceb00" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -770,7 +800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -781,7 +811,7 @@ version = "0.5.0-pre" source = "git+https://github.com/carllerche/nix-rust?rev=c4257f8a76#c4257f8a76b69b0d2e9a001d83e4bef67c03b23f" dependencies = [ "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -790,7 +820,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -877,7 +907,7 @@ name = "num_cpus" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1044,7 +1074,7 @@ name = "rand" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1079,7 +1109,7 @@ name = "rocksdb" version = "0.4.5" source = "git+https://github.com/ethcore/rust-rocksdb#9140e37ce0fdb748097f85653c01b0f7e3736ea9" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)", ] @@ -1089,7 +1119,7 @@ version = "0.3.0" source = "git+https://github.com/ethcore/rust-rocksdb#9140e37ce0fdb748097f85653c01b0f7e3736ea9" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1110,7 +1140,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1121,7 +1151,7 @@ version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1245,7 +1275,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1271,7 +1301,7 @@ name = "termios" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1280,7 +1310,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1297,7 +1327,7 @@ version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 889d759ae..294ad82c4 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -24,12 +24,13 @@ ethash = { path = "../ethash" } num_cpus = "0.2" clippy = { version = "0.0.76", optional = true} crossbeam = "0.2.9" -lazy_static = "0.1" +lazy_static = "0.2" ethcore-devtools = { path = "../devtools" } ethjson = { path = "../json" } bloomchain = "0.1" "ethcore-ipc" = { path = "../ipc/rpc" } rayon = "0.3.1" +ethstore = { path = "../ethstore" } [features] jit = ["evmjit"] diff --git a/ethcore/src/account_provider.rs b/ethcore/src/account_provider.rs new file mode 100644 index 000000000..3c79cfd52 --- /dev/null +++ b/ethcore/src/account_provider.rs @@ -0,0 +1,266 @@ +// Copyright 2015, 2016 Ethcore (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 . + +//! Account management. + +use std::fmt; +use std::sync::RwLock; +use std::collections::HashMap; +use util::{Address as H160, H256, H520}; +use ethstore::{SecretStore, Error as SSError, SafeAccount, EthStore}; +use ethstore::dir::{KeyDirectory}; +use ethstore::ethkey::{Address as SSAddress, Message as SSMessage, Secret as SSSecret, Random, Generator}; + +/// Type of unlock. +#[derive(Clone)] +enum Unlock { + /// If account is unlocked temporarily, it should be locked after first usage. + Temp, + /// Account unlocked permantently can always sign message. + /// Use with caution. + Perm, +} + +/// Data associated with account. +#[derive(Clone)] +struct AccountData { + unlock: Unlock, + password: String, +} + +/// `AccountProvider` errors. +#[derive(Debug)] +pub enum Error { + /// Returned when account is not unlocked. + NotUnlocked, + /// Returned when signing fails. + SStore(SSError), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Error::NotUnlocked => write!(f, "Account is locked"), + Error::SStore(ref e) => write!(f, "{}", e), + } + } +} + +impl From for Error { + fn from(e: SSError) -> Self { + Error::SStore(e) + } +} + +macro_rules! impl_bridge_type { + ($name: ident, $size: expr, $core: ident, $store: ident) => { + /// Primitive + pub struct $name([u8; $size]); + + impl From<[u8; $size]> for $name { + fn from(s: [u8; $size]) -> Self { + $name(s) + } + } + + impl From<$core> for $name { + fn from(s: $core) -> Self { + $name(s.0) + } + } + + impl From<$store> for $name { + fn from(s: $store) -> Self { + $name(s.into()) + } + } + + impl Into<$core> for $name { + fn into(self) -> $core { + $core(self.0) + } + } + + impl Into<$store> for $name { + fn into(self) -> $store { + $store::from(self.0) + } + } + } +} + +impl_bridge_type!(Secret, 32, H256, SSSecret); +impl_bridge_type!(Message, 32, H256, SSMessage); +impl_bridge_type!(Address, 20, H160, SSAddress); + + +struct NullDir; + +impl KeyDirectory for NullDir { + fn load(&self) -> Result, SSError> { + Ok(vec![]) + } + + fn insert(&self, _account: SafeAccount) -> Result<(), SSError> { + Ok(()) + } + + fn remove(&self, _address: &SSAddress) -> Result<(), SSError> { + Ok(()) + } +} + +/// Account management. +/// Responsible for unlocking accounts. +pub struct AccountProvider { + unlocked: RwLock>, + sstore: Box, +} + +impl AccountProvider { + /// Creates new account provider. + pub fn new(sstore: Box) -> Self { + AccountProvider { + unlocked: RwLock::new(HashMap::new()), + sstore: sstore, + } + } + + /// Creates not disk backed provider. + pub fn transient_provider() -> Self { + AccountProvider { + unlocked: RwLock::new(HashMap::new()), + sstore: Box::new(EthStore::open(Box::new(NullDir)).unwrap()) + } + } + + /// Creates new random account. + pub fn new_account(&self, password: &str) -> Result { + let secret = Random.generate().unwrap().secret().clone(); + let address = try!(self.sstore.insert_account(secret, password)); + Ok(Address::from(address).into()) + } + + /// Inserts new account into underlying store. + /// Does not unlock account! + pub fn insert_account(&self, secret: S, password: &str) -> Result where Secret: From { + let s = Secret::from(secret); + let address = try!(self.sstore.insert_account(s.into(), password)); + Ok(Address::from(address).into()) + } + + /// Returns addresses of all accounts. + pub fn accounts(&self) -> Vec { + self.sstore.accounts().into_iter().map(|a| H160(a.into())).collect() + } + + /// Helper method used for unlocking accounts. + fn unlock_account(&self, account: A, password: String, unlock: Unlock) -> Result<(), Error> where Address: From { + let a = Address::from(account); + let account = a.into(); + // verify password by signing dump message + // result may be discarded + let _ = try!(self.sstore.sign(&account, &password, &Default::default())); + + // check if account is already unlocked pernamently, if it is, do nothing + { + let unlocked = self.unlocked.read().unwrap(); + if let Some(data) = unlocked.get(&account) { + if let Unlock::Perm = data.unlock { + return Ok(()) + } + } + } + + let data = AccountData { + unlock: unlock, + password: password, + }; + + let mut unlocked = self.unlocked.write().unwrap(); + unlocked.insert(account, data); + Ok(()) + } + + /// Unlocks account permanently. + pub fn unlock_account_permanently(&self, account: A, password: String) -> Result<(), Error> where Address: From { + self.unlock_account(account, password, Unlock::Perm) + } + + /// Unlocks account temporarily (for one signing). + pub fn unlock_account_temporarily(&self, account: A, password: String) -> Result<(), Error> where Address: From { + self.unlock_account(account, password, Unlock::Temp) + } + + /// Signs the message. Account must be unlocked. + pub fn sign(&self, account: A, message: M) -> Result where Address: From, Message: From { + let account = Address::from(account).into(); + let message = Message::from(message).into(); + + let data = { + let unlocked = self.unlocked.read().unwrap(); + try!(unlocked.get(&account).ok_or(Error::NotUnlocked)).clone() + }; + + if let Unlock::Temp = data.unlock { + let mut unlocked = self.unlocked.write().unwrap(); + unlocked.remove(&account).expect("data exists: so key must exist: qed"); + } + + let signature = try!(self.sstore.sign(&account, &data.password, &message)); + Ok(H520(signature.into())) + } + + /// Unlocks an account, signs the message, and locks it again. + pub fn sign_with_password(&self, account: A, password: String, message: M) -> Result where Address: From, Message: From { + let account = Address::from(account).into(); + let message = Message::from(message).into(); + let signature = try!(self.sstore.sign(&account, &password, &message)); + Ok(H520(signature.into())) + } +} + +#[cfg(test)] +mod tests { + use super::AccountProvider; + use ethstore::SecretStore; + use ethstore::ethkey::{Generator, Random}; + + #[test] + fn unlock_account_temp() { + let kp = Random.generate().unwrap(); + let ap = AccountProvider::transient_provider(); + assert!(ap.insert_account(kp.secret().clone(), "test").is_ok()); + assert!(ap.unlock_account_temporarily(kp.address(), "test1".into()).is_err()); + assert!(ap.unlock_account_temporarily(kp.address(), "test".into()).is_ok()); + assert!(ap.sign(kp.address(), [0u8; 32]).is_ok()); + assert!(ap.sign(kp.address(), [0u8; 32]).is_err()); + } + + #[test] + fn unlock_account_perm() { + let kp = Random.generate().unwrap(); + let ap = AccountProvider::transient_provider(); + assert!(ap.insert_account(kp.secret().clone(), "test").is_ok()); + assert!(ap.unlock_account_permanently(kp.address(), "test1".into()).is_err()); + assert!(ap.unlock_account_permanently(kp.address(), "test".into()).is_ok()); + assert!(ap.sign(kp.address(), [0u8; 32]).is_ok()); + assert!(ap.sign(kp.address(), [0u8; 32]).is_ok()); + assert!(ap.unlock_account_temporarily(kp.address(), "test".into()).is_ok()); + assert!(ap.sign(kp.address(), [0u8; 32]).is_ok()); + assert!(ap.sign(kp.address(), [0u8; 32]).is_ok()); + } +} diff --git a/ethcore/src/basic_authority.rs b/ethcore/src/basic_authority.rs index c732ce711..e63f229cf 100644 --- a/ethcore/src/basic_authority.rs +++ b/ethcore/src/basic_authority.rs @@ -17,7 +17,7 @@ //! A blockchain engine that supports a basic, non-BFT proof-of-authority. use common::*; -use util::keys::store::AccountProvider; +use account_provider::AccountProvider; use block::*; use spec::{CommonParams, Spec}; use engine::*; @@ -105,15 +105,13 @@ impl Engine for BasicAuthority { /// be returned. fn generate_seal(&self, block: &ExecutedBlock, accounts: Option<&AccountProvider>) -> Option> { if let Some(ap) = accounts { - // check to see if author is contained in self.our_params.authorities - if self.our_params.authorities.contains(block.header().author()) { - if let Ok(secret) = ap.account_secret(block.header().author()) { - return Some(block.header().author_seal(&secret)); - } else { - trace!(target: "basicauthority", "generate_seal: FAIL: accounts secret key unavailable"); - } + let header = block.header(); + let message = header.bare_hash(); + // account should be pernamently unlocked, otherwise sealing will fail + if let Ok(signature) = ap.sign(*block.header().author(), message) { + return Some(vec![encode(&signature).to_vec()]); } else { - trace!(target: "basicauthority", "generate_seal: FAIL: block author {} isn't one of the authorized accounts {:?}", block.header().author(), self.our_params.authorities); + trace!(target: "basicauthority", "generate_seal: FAIL: accounts secret key unavailable"); } } else { trace!(target: "basicauthority", "generate_seal: FAIL: accounts not provided"); @@ -176,16 +174,6 @@ impl Header { pub fn signature(&self) -> H520 { decode(&self.seal()[0]) } - - /// Generate a seal for the block with the given `secret`. - pub fn author_seal(&self, secret: &Secret) -> Vec { - vec![encode(&ec::sign(secret, &self.bare_hash()).unwrap_or(Signature::new())).to_vec()] - } - - /// Set the nonce and mix hash fields of the header. - pub fn sign(&mut self, secret: &Secret) { - self.seal = self.author_seal(secret); - } } /// Create a new test chain spec with `BasicAuthority` consensus engine. @@ -197,7 +185,7 @@ mod tests { use common::*; use block::*; use tests::helpers::*; - use util::keys::{TestAccountProvider, TestAccount}; + use account_provider::AccountProvider; #[test] fn has_valid_metadata() { @@ -251,24 +239,11 @@ mod tests { } } - #[test] - fn can_do_signature_verification() { - let secret = "".sha3(); - let addr = KeyPair::from_secret("".sha3()).unwrap().address(); - - let engine = new_test_authority().engine; - let mut header: Header = Header::default(); - header.set_author(addr); - header.sign(&secret); - - assert!(engine.verify_block_unordered(&header, None).is_ok()); - } - #[test] fn can_generate_seal() { - let addr = KeyPair::from_secret("".sha3()).unwrap().address(); - let accounts = hash_map![addr => TestAccount{unlocked: true, password: Default::default(), secret: "".sha3()}]; - let tap = TestAccountProvider::new(accounts); + let tap = AccountProvider::transient_provider(); + let addr = tap.insert_account("".sha3(), "").unwrap(); + tap.unlock_account_permanently(addr, "".into()).unwrap(); let spec = new_test_authority(); let engine = &spec.engine; @@ -278,10 +253,9 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, addr.clone(), 3141562.into(), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, addr, 3141562.into(), vec![]).unwrap(); let b = b.close_and_lock(); let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap(); - assert!(b.try_seal(engine.deref(), seal).is_ok()); } } diff --git a/ethcore/src/engine.rs b/ethcore/src/engine.rs index ed482db89..98ebac40e 100644 --- a/ethcore/src/engine.rs +++ b/ethcore/src/engine.rs @@ -17,7 +17,7 @@ //! Consensus engine specification use common::*; -use util::keys::store::AccountProvider; +use account_provider::AccountProvider; use block::ExecutedBlock; use spec::CommonParams; use evm::Schedule; diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index f69048a95..9919ec62a 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -91,10 +91,12 @@ extern crate ethjson; extern crate bloomchain; #[macro_use] extern crate ethcore_ipc as ipc; extern crate rayon; +pub extern crate ethstore; #[cfg(test)] extern crate ethcore_devtools as devtools; #[cfg(feature = "jit" )] extern crate evmjit; +pub mod account_provider; pub mod basic_authority; pub mod block; pub mod block_queue; @@ -140,4 +142,4 @@ mod json_tests; pub use types::*; pub use evm::get_info; -pub use executive::contract_address; \ No newline at end of file +pub use executive::contract_address; diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index c5dff80d0..735ad5cf4 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -18,7 +18,7 @@ use rayon::prelude::*; use std::sync::atomic::AtomicBool; use util::*; -use util::keys::store::{AccountProvider}; +use account_provider::AccountProvider; use views::{BlockView, HeaderView}; use client::{MiningBlockChainClient, Executive, Executed, EnvInfo, TransactOptions, BlockID, CallAnalytics}; use block::{ClosedBlock, IsBlock}; diff --git a/ethcore/src/types/transaction.rs b/ethcore/src/types/transaction.rs index a6b4c1781..a8e1c66e4 100644 --- a/ethcore/src/types/transaction.rs +++ b/ethcore/src/types/transaction.rs @@ -140,8 +140,13 @@ impl Transaction { /// Signs the transaction as coming from `sender`. pub fn sign(self, secret: &Secret) -> SignedTransaction { - let sig = ec::sign(secret, &self.hash()); - let (r, s, v) = sig.unwrap().to_rsv(); + let sig = ec::sign(secret, &self.hash()).unwrap(); + self.with_signature(sig) + } + + /// Signs the transaction with signature. + pub fn with_signature(self, sig: H520) -> SignedTransaction { + let (r, s, v) = sig.to_rsv(); SignedTransaction { unsigned: self, r: r, diff --git a/ethkey/.gitignore b/ethkey/.gitignore new file mode 100644 index 000000000..c6262ea6a --- /dev/null +++ b/ethkey/.gitignore @@ -0,0 +1,2 @@ +target +*.swp diff --git a/ethkey/.travis.yml b/ethkey/.travis.yml new file mode 100644 index 000000000..e1d6f9b13 --- /dev/null +++ b/ethkey/.travis.yml @@ -0,0 +1,23 @@ +sudo: false +language: rust +branches: + only: + - master +matrix: + fast_finish: false + include: + - rust: stable + - rust: beta + - rust: nightly +after_success: | + [ $TRAVIS_BRANCH = master ] && + [ $TRAVIS_PULL_REQUEST = false ] && + [ $TRAVIS_RUST_VERSION = stable ] && + cargo doc --no-deps --verbose && + echo '' > target/doc/index.html && + pip install --user ghp-import && + /home/travis/.local/bin/ghp-import -n target/doc && + git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages +env: + global: + - secure: LBkFAH5fAhzHRP7kYQZnOCavOuPS2vEDv49KGfTsY/7MmW0De4c0sz0a3/0IdFqqIMLYLV2uMO86S0p6FBaq6/GIdobLsGZZ3cFReYFI+vb8sylYF/+D/aQ/UOjpEOD8HP6G3YmV5buSyL8uiPlmYbqwBAe4z6ELEbh/16gRuIqQLYQtpYPxMCD3tZzSux81b45K2khETZ7E+ap3LUG3rFTXxjEgx9leIZlVY+Qk4U5D9gFnJnjmxDPyIqzn2dORnw5jcpp3eSUEvSvSgjz4TAVg7Gw789jDl2dyr26U1wp1E5bB9AqZVYOb4l8vcQ6QiHrCvu7Wgl32O6XYkwMjDaDUB68bm5MTsUrwDWgKGx4xeurIBil5doHFlCGZ98RrzPxdgoCd6hCI459dA8jEwdXAfOkZ80RycZlryHCwn68x3dlnJoqVyg8viYo6H6G0GdH/dIhuwbnLDdWZsODehN8eJEy9KKQ4tPp+PjBcgKm1Wz5MzKFSIwfFInic7hjTVXGozHSvgvXJE0BI2bPbjVNCdZa5kGAAUAhBNXyTn7PbC7hYbmwAalzaOIjoYcdQLmUEz2J2gSOK8xW2gMU0Z2I+IylA0oh8xB/r2Q5sqLHT3LPLdzoETsyzaQjWFcFdXdsbbcG59DnFC9s2Jq7KqeODp6EJG4cw0ofKpBuDRes= diff --git a/ethkey/Cargo.toml b/ethkey/Cargo.toml new file mode 100644 index 000000000..08461e865 --- /dev/null +++ b/ethkey/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "ethkey" +version = "0.2.0" +authors = ["debris "] + +[dependencies] +rand = "0.3.14" +lazy_static = "0.2.1" +tiny-keccak = "1.0" +eth-secp256k1 = { git = "https://github.com/ethcore/rust-secp256k1" } +rustc-serialize = "0.3" +docopt = { version = "0.6", optional = true } + +[features] +default = ["cli"] +cli = ["docopt"] + +[[bin]] +name = "ethkey" +path = "src/bin/main.rs" +doc = false diff --git a/ethkey/README.md b/ethkey/README.md new file mode 100644 index 000000000..1a588cd48 --- /dev/null +++ b/ethkey/README.md @@ -0,0 +1,150 @@ +# ethkey + +[![Build Status][travis-image]][travis-url] + +[travis-image]: https://travis-ci.org/ethcore/ethkey.svg?branch=master +[travis-url]: https://travis-ci.org/ethcore/ethkey + +Ethereum keys generator. + +[Documentation](http://ethcore.github.io/ethkey/ethkey/index.html) + +### Usage + +``` +Ethereum keys generator. + Copyright 2016 Ethcore (UK) Limited + +Usage: + ethkey info [options] + ethkey generate random [options] + ethkey generate prefix [options] + ethkey generate brain [options] + ethkey sign + ethkey verify + ethkey [-h | --help] + +Options: + -h, --help Display this message and exit. + -s, --secret Display only the secret. + -p, --public Display only the public. + -a, --address Display only the address. + +Commands: + info Display public and address of the secret. + generate Generates new ethereum key. + random Random generation. + prefix Random generation, but address must start with a prefix + brain Generate new key from string seed. + sign Sign message using secret. + verify Verify signer of the signature. +``` + +### Examples + +#### `info ` +*Display info about private key.* + +- `` - ethereum secret, 32 bytes long + +``` +ethkey info 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55 +``` + +``` +secret: 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55 +public: 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124 +address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5 +``` + +-- + +#### `generate brain ` +*Generate new brain-wallet keypair using 16384 iterations.* + +- `` - brain-wallet seed, any string + + +``` +ethkey generate brain "this is sparta" +``` + +``` +secret: 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55 +public: 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124 +address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5 +``` + +-- + +#### `generate random` +*Generate new keypair randomly.* + +``` +ethkey generate random +``` + +``` +secret: 7d29fab185a33e2cd955812397354c472d2b84615b645aa135ff539f6b0d70d5 +public: 35f222d88b80151857a2877826d940104887376a94c1cbd2c8c7c192eb701df88a18a4ecb8b05b1466c5b3706042027b5e079fe3a3683e66d822b0e047aa3418 +address: a8fa5dd30a87bb9e3288d604eb74949c515ab66e +``` + +-- + +#### `generate prefix ` +*Generate new keypair randomly with address starting with prefix.* + +- `` - desired address prefix, 0 - 32 bytes long. +- `` - maximum number of tries before generation is assumed to be a failure. + +``` +ethkey generate prefix ff 1000 +``` + +``` +secret: 2075b1d9c124ea673de7273758ed6de14802a9da8a73ceb74533d7c312ff6acd +public: 48dbce4508566a05509980a5dd1335599fcdac6f9858ba67018cecb9f09b8c4066dc4c18ae2722112fd4d9ac36d626793fffffb26071dfeb0c2300df994bd173 +address: fff7e25dff2aa60f61f9d98130c8646a01f31649 +``` + +-- + +#### `sign ` +*Sign a message with a secret.* + +- `` - ethereum secret, 32 bytes long +- `` - message to sign, 32 bytes long + +``` +ethkey sign 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55 bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987 +``` + +``` +c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200 +``` + +-- + +#### `verify ` +*Verify the signature.* + +- `` - ethereum public, 64 bytes long +- `` - message signature, 65 bytes long +- `` - message, 32 bytes long + +``` +ethkey verify 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124 c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200 bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987 +``` + +``` +true +``` + + +# Ethcore toolchain +*this project is a part of the ethcore toolchain* + +- [**ethkey**](https://github.com/ethcore/ethkey) - Ethereum keys generator and signer. +- [**ethstore**](https://github.com/ethcore/ethstore) - Ethereum key management. +- [**ethabi**](https://github.com/ethcore/ethabi) - Ethereum function calls encoding. diff --git a/ethkey/src/bin/ethkey.rs b/ethkey/src/bin/ethkey.rs new file mode 100644 index 000000000..a7661c42f --- /dev/null +++ b/ethkey/src/bin/ethkey.rs @@ -0,0 +1,274 @@ +extern crate docopt; +extern crate rustc_serialize; +extern crate ethkey; + +use std::str::FromStr; +use std::{env, fmt, process}; +use std::num::ParseIntError; +use docopt::Docopt; +use rustc_serialize::hex::{FromHex, FromHexError}; +use ethkey::{KeyPair, Random, Brain, Prefix, Error as EthkeyError, Generator, Secret, Message, Public, Signature, sign, verify}; + +pub const USAGE: &'static str = r#" +Ethereum keys generator. + Copyright 2016 Ethcore (UK) Limited + +Usage: + ethkey info [options] + ethkey generate random [options] + ethkey generate prefix [options] + ethkey generate brain [options] + ethkey sign + ethkey verify + ethkey [-h | --help] + +Options: + -h, --help Display this message and exit. + -s, --secret Display only the secret. + -p, --public Display only the public. + -a, --address Display only the address. + +Commands: + info Display public and address of the secret. + generate Generates new ethereum key. + random Random generation. + prefix Random generation, but address must start with a prefix + brain Generate new key from string seed. + sign Sign message using secret. + verify Verify signer of the signature. +"#; + +#[derive(Debug, RustcDecodable)] +struct Args { + cmd_info: bool, + cmd_generate: bool, + cmd_random: bool, + cmd_prefix: bool, + cmd_brain: bool, + cmd_sign: bool, + cmd_verify: bool, + arg_prefix: String, + arg_iterations: String, + arg_seed: String, + arg_secret: String, + arg_message: String, + arg_public: String, + arg_signature: String, + flag_secret: bool, + flag_public: bool, + flag_address: bool, +} + +#[derive(Debug)] +enum Error { + Ethkey(EthkeyError), + FromHex(FromHexError), + ParseInt(ParseIntError), +} + +impl From for Error { + fn from(err: EthkeyError) -> Self { + Error::Ethkey(err) + } +} + +impl From for Error { + fn from(err: FromHexError) -> Self { + Error::FromHex(err) + } +} + +impl From for Error { + fn from(err: ParseIntError) -> Self { + Error::ParseInt(err) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Error::Ethkey(ref e) => write!(f, "{}", e), + Error::FromHex(ref e) => write!(f, "{}", e), + Error::ParseInt(ref e) => write!(f, "{}", e), + } + } +} + +enum DisplayMode { + KeyPair, + Secret, + Public, + Address, +} + +impl DisplayMode { + fn new(args: &Args) -> Self { + if args.flag_secret { + DisplayMode::Secret + } else if args.flag_public { + DisplayMode::Public + } else if args.flag_address { + DisplayMode::Address + } else { + DisplayMode::KeyPair + } + } +} + +fn main() { + match execute(env::args()) { + Ok(ok) => println!("{}", ok), + Err(err) => { + println!("{}", err); + process::exit(1); + }, + } +} + +fn display(keypair: KeyPair, mode: DisplayMode) -> String { + match mode { + DisplayMode::KeyPair => format!("{}", keypair), + DisplayMode::Secret => format!("{}", keypair.secret()), + DisplayMode::Public => format!("{}", keypair.public()), + DisplayMode::Address => format!("{}", keypair.address()), + } +} + +fn execute(command: I) -> Result where I: IntoIterator, S: AsRef { + let args: Args = Docopt::new(USAGE) + .and_then(|d| d.argv(command).decode()) + .unwrap_or_else(|e| e.exit()); + + return if args.cmd_info { + let display_mode = DisplayMode::new(&args); + let secret = try!(Secret::from_str(&args.arg_secret)); + let keypair = try!(KeyPair::from_secret(secret)); + Ok(display(keypair, display_mode)) + } else if args.cmd_generate { + let display_mode = DisplayMode::new(&args); + let keypair = if args.cmd_random { + Random.generate() + } else if args.cmd_prefix { + let prefix = try!(args.arg_prefix.from_hex()); + let iterations = try!(usize::from_str_radix(&args.arg_iterations, 10)); + Prefix::new(prefix, iterations).generate() + } else if args.cmd_brain { + Brain::new(args.arg_seed).generate() + } else { + unreachable!(); + }; + Ok(display(try!(keypair), display_mode)) + } else if args.cmd_sign { + let secret = try!(Secret::from_str(&args.arg_secret)); + let message = try!(Message::from_str(&args.arg_message)); + let signature = try!(sign(&secret, &message)); + Ok(format!("{}", signature)) + } else if args.cmd_verify { + let public = try!(Public::from_str(&args.arg_public)); + let signature = try!(Signature::from_str(&args.arg_signature)); + let message = try!(Message::from_str(&args.arg_message)); + let ok = try!(verify(&public, &signature, &message)); + Ok(format!("{}", ok)) + } else { + unreachable!(); + } +} + +#[cfg(test)] +mod tests { + use super::execute; + + #[test] + fn info() { + let command = vec!["ethkey", "info", "17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55"] + .into_iter() + .map(Into::into) + .collect::>(); + + let expected = +"secret: 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55 +public: 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124 +address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned(); + assert_eq!(execute(command).unwrap(), expected); + } + + #[test] + fn brain() { + let command = vec!["ethkey", "generate", "brain", "this is sparta"] + .into_iter() + .map(Into::into) + .collect::>(); + + let expected = +"secret: 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55 +public: 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124 +address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned(); + assert_eq!(execute(command).unwrap(), expected); + } + + #[test] + fn secret() { + let command = vec!["ethkey", "generate", "brain", "this is sparta", "--secret"] + .into_iter() + .map(Into::into) + .collect::>(); + + let expected = "17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55".to_owned(); + assert_eq!(execute(command).unwrap(), expected); + } + + #[test] + fn public() { + let command = vec!["ethkey", "generate", "brain", "this is sparta", "--public"] + .into_iter() + .map(Into::into) + .collect::>(); + + let expected = "689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124".to_owned(); + assert_eq!(execute(command).unwrap(), expected); + } + + #[test] + fn address() { + let command = vec!["ethkey", "generate", "brain", "this is sparta", "--address"] + .into_iter() + .map(Into::into) + .collect::>(); + + let expected = "26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned(); + assert_eq!(execute(command).unwrap(), expected); + } + + #[test] + fn sign() { + let command = vec!["ethkey", "sign", "17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987"] + .into_iter() + .map(Into::into) + .collect::>(); + + let expected = "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200".to_owned(); + assert_eq!(execute(command).unwrap(), expected); + } + + #[test] + fn verify_valid() { + let command = vec!["ethkey", "verify", "689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987"] + .into_iter() + .map(Into::into) + .collect::>(); + + let expected = "true".to_owned(); + assert_eq!(execute(command).unwrap(), expected); + } + + #[test] + fn verify_invalid() { + let command = vec!["ethkey", "verify", "689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec986"] + .into_iter() + .map(Into::into) + .collect::>(); + + let expected = "false".to_owned(); + assert_eq!(execute(command).unwrap(), expected); + } +} diff --git a/ethkey/src/bin/main.rs b/ethkey/src/bin/main.rs new file mode 100644 index 000000000..404136b62 --- /dev/null +++ b/ethkey/src/bin/main.rs @@ -0,0 +1,5 @@ +#[cfg(feature = "cli")] +include!("ethkey.rs"); + +#[cfg(not(feature = "cli"))] +fn main() {} diff --git a/ethkey/src/brain.rs b/ethkey/src/brain.rs new file mode 100644 index 000000000..c7fffe3bf --- /dev/null +++ b/ethkey/src/brain.rs @@ -0,0 +1,46 @@ +use keccak::Keccak256; +use super::{KeyPair, Error, Generator, Secret}; + +/// Simple brainwallet. +pub struct Brain(String); + +impl Brain { + pub fn new(s: String) -> Self { + Brain(s) + } +} + +impl Generator for Brain { + fn generate(self) -> Result { + let seed = self.0; + let mut secret = seed.bytes().collect::>().keccak256(); + + let mut i = 0; + loop { + secret = secret.keccak256(); + + match i > 16384 { + false => i += 1, + true => { + let result = KeyPair::from_secret(Secret::from(secret.clone())); + if result.is_ok() { + return result + } + }, + } + } + } +} + +#[cfg(test)] +mod tests { + use {Brain, Generator}; + + #[test] + fn test_brain() { + let words = "this is sparta!".to_owned(); + let first_keypair = Brain(words.clone()).generate().unwrap(); + let second_keypair = Brain(words.clone()).generate().unwrap(); + assert_eq!(first_keypair.secret(), second_keypair.secret()); + } +} diff --git a/ethkey/src/error.rs b/ethkey/src/error.rs new file mode 100644 index 000000000..f75f264f5 --- /dev/null +++ b/ethkey/src/error.rs @@ -0,0 +1,53 @@ +use std::fmt; + +#[derive(Debug)] +/// Crypto error +pub enum Error { + /// Invalid secret key + InvalidSecret, + /// Invalid public key + InvalidPublic, + /// Invalid address + InvalidAddress, + /// Invalid EC signature + InvalidSignature, + /// Invalid AES message + InvalidMessage, + /// IO Error + Io(::std::io::Error), + /// Custom + Custom(String), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let msg = match *self { + Error::InvalidSecret => "Invalid secret key".into(), + Error::InvalidPublic => "Invalid public key".into(), + Error::InvalidAddress => "Invalid address".into(), + Error::InvalidSignature => "Invalid EC signature".into(), + Error::InvalidMessage => "Invalid AES message".into(), + Error::Io(ref err) => format!("I/O error: {}", err), + Error::Custom(ref s) => s.clone(), + }; + + f.write_fmt(format_args!("Crypto error ({})", msg)) + } +} + +impl From<::secp256k1::Error> for Error { + fn from(e: ::secp256k1::Error) -> Error { + match e { + ::secp256k1::Error::InvalidMessage => Error::InvalidMessage, + ::secp256k1::Error::InvalidPublicKey => Error::InvalidPublic, + ::secp256k1::Error::InvalidSecretKey => Error::InvalidSecret, + _ => Error::InvalidSignature, + } + } +} + +impl From<::std::io::Error> for Error { + fn from(err: ::std::io::Error) -> Error { + Error::Io(err) + } +} diff --git a/ethkey/src/keccak.rs b/ethkey/src/keccak.rs new file mode 100644 index 000000000..3423f19fe --- /dev/null +++ b/ethkey/src/keccak.rs @@ -0,0 +1,15 @@ +use tiny_keccak::Keccak; + +pub trait Keccak256 { + fn keccak256(&self) -> T where T: Sized; +} + +impl Keccak256<[u8; 32]> for [u8] { + fn keccak256(&self) -> [u8; 32] { + let mut keccak = Keccak::new_keccak256(); + let mut result = [0u8; 32]; + keccak.update(self); + keccak.finalize(&mut result); + result + } +} diff --git a/ethkey/src/keypair.rs b/ethkey/src/keypair.rs new file mode 100644 index 000000000..dcfb67460 --- /dev/null +++ b/ethkey/src/keypair.rs @@ -0,0 +1,91 @@ +use std::fmt; +use secp256k1::key; +use rustc_serialize::hex::ToHex; +use keccak::Keccak256; +use super::{Secret, Public, Address, SECP256K1, Error}; + +/// secp256k1 key pair +pub struct KeyPair { + secret: Secret, + public: Public, +} + +impl fmt::Display for KeyPair { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + try!(writeln!(f, "secret: {}", self.secret.to_hex())); + try!(writeln!(f, "public: {}", self.public.to_hex())); + write!(f, "address: {}", self.address().to_hex()) + } +} + +impl KeyPair { + /// Create a pair from secret key + pub fn from_secret(secret: Secret) -> Result { + let context = &SECP256K1; + let s: key::SecretKey = try!(key::SecretKey::from_slice(context, &secret[..])); + let pub_key = try!(key::PublicKey::from_secret_key(context, &s)); + let serialized = pub_key.serialize_vec(context, false); + + let mut public = Public::default(); + public.copy_from_slice(&serialized[1..65]); + + let keypair = KeyPair { + secret: secret, + public: public, + }; + + Ok(keypair) + } + + pub fn from_keypair(sec: key::SecretKey, publ: key::PublicKey) -> Self { + let context = &SECP256K1; + let serialized = publ.serialize_vec(context, false); + let mut secret = Secret::default(); + secret.copy_from_slice(&sec[0..32]); + let mut public = Public::default(); + public.copy_from_slice(&serialized[1..65]); + + KeyPair { + secret: secret, + public: public, + } + } + + pub fn secret(&self) -> &Secret { + &self.secret + } + + pub fn public(&self) -> &Public { + &self.public + } + + pub fn address(&self) -> Address { + let hash = self.public.keccak256(); + let mut result = Address::default(); + result.copy_from_slice(&hash[12..]); + result + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use {KeyPair, Secret}; + + #[test] + fn from_secret() { + let secret = Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(); + let _ = KeyPair::from_secret(secret).unwrap(); + } + + #[test] + fn keypair_display() { + let expected = +"secret: a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65 +public: 8ce0db0b0359ffc5866ba61903cc2518c3675ef2cf380a7e54bde7ea20e6fa1ab45b7617346cd11b7610001ee6ae5b0155c41cad9527cbcdff44ec67848943a4 +address: 5b073e9233944b5e729e46d618f0d8edf3d9c34a".to_owned(); + let secret = Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(); + let kp = KeyPair::from_secret(secret).unwrap(); + assert_eq!(format!("{}", kp), expected); + } +} diff --git a/ethkey/src/lib.rs b/ethkey/src/lib.rs new file mode 100644 index 000000000..218abbbf3 --- /dev/null +++ b/ethkey/src/lib.rs @@ -0,0 +1,33 @@ +extern crate rand; +#[macro_use] +extern crate lazy_static; +extern crate tiny_keccak; +extern crate secp256k1; +extern crate rustc_serialize; + +mod brain; +mod error; +mod keypair; +mod keccak; +mod prefix; +mod primitive; +mod random; +mod signature; + +lazy_static! { + static ref SECP256K1: secp256k1::Secp256k1 = secp256k1::Secp256k1::new(); +} + +/// Generates new keypair. +pub trait Generator { + /// Should be called to generate new keypair. + fn generate(self) -> Result; +} + +pub use self::brain::Brain; +pub use self::error::Error; +pub use self::keypair::KeyPair; +pub use self::primitive::{Secret, Public, Address, Message}; +pub use self::prefix::Prefix; +pub use self::random::Random; +pub use self::signature::{sign, verify, Signature}; diff --git a/ethkey/src/prefix.rs b/ethkey/src/prefix.rs new file mode 100644 index 000000000..8d7f18cfa --- /dev/null +++ b/ethkey/src/prefix.rs @@ -0,0 +1,41 @@ +use super::{Random, Generator, KeyPair, Error}; + +/// Tries to find keypair with address starting with given prefix. +pub struct Prefix { + prefix: Vec, + iterations: usize, +} + +impl Prefix { + pub fn new(prefix: Vec, iterations: usize) -> Self { + Prefix { + prefix: prefix, + iterations: iterations, + } + } +} + +impl Generator for Prefix { + fn generate(self) -> Result { + for _ in 0..self.iterations { + let keypair = try!(Random.generate()); + if keypair.address().starts_with(&self.prefix) { + return Ok(keypair) + } + } + + Err(Error::Custom("Could not find keypair".into())) + } +} + +#[cfg(test)] +mod tests { + use {Generator, Prefix}; + + #[test] + fn prefix_generator() { + let prefix = vec![0xffu8]; + let keypair = Prefix::new(prefix.clone(), usize::max_value()).generate().unwrap(); + assert!(keypair.address().starts_with(&prefix)); + } +} diff --git a/ethkey/src/primitive.rs b/ethkey/src/primitive.rs new file mode 100644 index 000000000..11a614ded --- /dev/null +++ b/ethkey/src/primitive.rs @@ -0,0 +1,122 @@ +use std::ops::{Deref, DerefMut}; +use std::{fmt, cmp, hash}; +use std::str::FromStr; +use rustc_serialize::hex::{ToHex, FromHex}; +use Error; + +macro_rules! impl_primitive { + ($name: ident, $size: expr, $err: expr) => { + + #[repr(C)] + #[derive(Eq)] + pub struct $name([u8; $size]); + + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{}", self.to_hex()) + } + } + + impl fmt::Display for $name { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{}", self.to_hex()) + } + } + + impl FromStr for $name { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s.from_hex() { + Ok(ref hex) if hex.len() == $size => { + let mut res = $name::default(); + res.copy_from_slice(hex); + Ok(res) + }, + _ => Err($err) + } + } + } + + impl PartialEq for $name { + fn eq(&self, other: &Self) -> bool { + let self_ref: &[u8] = &self.0; + let other_ref: &[u8] = &other.0; + self_ref == other_ref + } + } + + impl PartialOrd for $name { + fn partial_cmp(&self, other: &Self) -> Option { + let self_ref: &[u8] = &self.0; + let other_ref: &[u8] = &other.0; + self_ref.partial_cmp(other_ref) + } + } + + impl Ord for $name { + fn cmp(&self, other: &Self) -> cmp::Ordering { + let self_ref: &[u8] = &self.0; + let other_ref: &[u8] = &other.0; + self_ref.cmp(other_ref) + } + } + + impl Clone for $name { + fn clone(&self) -> Self { + let mut res = Self::default(); + res.copy_from_slice(&self.0); + res + } + } + + impl Default for $name { + fn default() -> Self { + $name([0u8; $size]) + } + } + + impl From<[u8; $size]> for $name { + fn from(s: [u8; $size]) -> Self { + $name(s) + } + } + + impl Into<[u8; $size]> for $name { + fn into(self) -> [u8; $size] { + self.0 + } + } + + impl hash::Hash for $name { + fn hash(&self, state: &mut H) where H: hash::Hasher { + let self_ref: &[u8] = &self.0; + self_ref.hash(state) + } + } + + impl Deref for $name { + type Target = [u8; $size]; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + + impl DerefMut for $name { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + } +} + +impl_primitive!(Address, 20, Error::InvalidAddress); +impl_primitive!(Secret, 32, Error::InvalidSecret); +impl_primitive!(Message, 32, Error::InvalidMessage); +impl_primitive!(Public, 64, Error::InvalidPublic); + +#[cfg(test)] +mod tests { + +} diff --git a/ethkey/src/random.rs b/ethkey/src/random.rs new file mode 100644 index 000000000..aa3abb838 --- /dev/null +++ b/ethkey/src/random.rs @@ -0,0 +1,16 @@ +use rand::os::OsRng; +use super::{Generator, KeyPair, Error, SECP256K1}; + +/// Randomly generates new keypair. +pub struct Random; + +impl Generator for Random { + fn generate(self) -> Result { + let context = &SECP256K1; + let mut rng = try!(OsRng::new()); + let (sec, publ) = try!(context.generate_keypair(&mut rng)); + + Ok(KeyPair::from_keypair(sec, publ)) + } +} + diff --git a/ethkey/src/signature.rs b/ethkey/src/signature.rs new file mode 100644 index 000000000..f34baa04f --- /dev/null +++ b/ethkey/src/signature.rs @@ -0,0 +1,158 @@ +use std::ops::{Deref, DerefMut}; +use std::{mem, fmt}; +use std::str::FromStr; +use secp256k1::{Message as SecpMessage, RecoverableSignature, RecoveryId, Error as SecpError}; +use secp256k1::key::{SecretKey, PublicKey}; +use rustc_serialize::hex::{ToHex, FromHex}; +use {Secret, Public, SECP256K1, Error, Message}; + +#[repr(C)] +#[derive(Eq)] +pub struct Signature([u8; 65]); + +impl Signature { + /// Get a slice into the 'r' portion of the data. + pub fn r(&self) -> &[u8] { + &self.0[0..32] + } + + /// Get a slice into the 's' portion of the data. + pub fn s(&self) -> &[u8] { + &self.0[32..64] + } + + /// Get the recovery byte. + pub fn v(&self) -> u8 { + self.0[64] + } +} + +// manual implementation large arrays don't have trait impls by default. +// remove when integer generics exist +impl ::std::cmp::PartialEq for Signature { + fn eq(&self, other: &Self) -> bool { + &self.0[..] == &other.0[..] + } +} + +// also manual for the same reason, but the pretty printing might be useful. +impl fmt::Debug for Signature { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.debug_struct("Signature") + .field("r", &self.0[0..32].to_hex()) + .field("s", &self.0[32..64].to_hex()) + .field("v", &self.0[64..65].to_hex()) + .finish() + } +} + +impl fmt::Display for Signature { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "{}", self.to_hex()) + } +} + +impl FromStr for Signature { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s.from_hex() { + Ok(ref hex) if hex.len() == 65 => { + let mut data = [0; 65]; + data.copy_from_slice(&hex[0..65]); + Ok(Signature(data)) + }, + _ => Err(Error::InvalidSignature) + } + } +} + +impl Default for Signature { + fn default() -> Self { + Signature([0; 65]) + } +} + +impl From<[u8; 65]> for Signature { + fn from(s: [u8; 65]) -> Self { + Signature(s) + } +} + +impl Into<[u8; 65]> for Signature { + fn into(self) -> [u8; 65] { + self.0 + } +} + +impl Deref for Signature { + type Target = [u8; 65]; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Signature { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +pub fn sign(secret: &Secret, message: &Message) -> Result { + let context = &SECP256K1; + // no way to create from raw byte array. + let sec: &SecretKey = unsafe { mem::transmute(secret) }; + let s = try!(context.sign_recoverable(&try!(SecpMessage::from_slice(&message[..])), sec)); + let (rec_id, data) = s.serialize_compact(context); + let mut data_arr = [0; 65]; + + // no need to check if s is low, it always is + data_arr[0..64].copy_from_slice(&data[0..64]); + data_arr[64] = rec_id.to_i32() as u8; + Ok(Signature(data_arr)) +} + +pub fn verify(public: &Public, signature: &Signature, message: &Message) -> Result { + let context = &SECP256K1; + let rsig = try!(RecoverableSignature::from_compact(context, &signature[0..64], try!(RecoveryId::from_i32(signature[64] as i32)))); + let sig = rsig.to_standard(context); + + let pdata: [u8; 65] = { + let mut temp = [4u8; 65]; + temp[1..65].copy_from_slice(public.deref()); + temp + }; + + let publ = try!(PublicKey::from_slice(context, &pdata)); + match context.verify(&try!(SecpMessage::from_slice(&message[..])), &sig, &publ) { + Ok(_) => Ok(true), + Err(SecpError::IncorrectSignature) => Ok(false), + Err(x) => Err(Error::from(x)) + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use {Generator, Random, Message}; + use super::{sign, verify, Signature}; + + #[test] + fn signature_to_and_from_str() { + let keypair = Random.generate().unwrap(); + let message = Message::default(); + let signature = sign(keypair.secret(), &message).unwrap(); + let string = format!("{}", signature); + let deserialized = Signature::from_str(&string).unwrap(); + assert_eq!(signature, deserialized); + } + + #[test] + fn sign_and_verify() { + let keypair = Random.generate().unwrap(); + let message = Message::default(); + let signature = sign(keypair.secret(), &message).unwrap(); + assert!(verify(keypair.public(), &signature, &message).unwrap()); + } +} diff --git a/ethstore/.editorconfig b/ethstore/.editorconfig new file mode 100644 index 000000000..0ac22f073 --- /dev/null +++ b/ethstore/.editorconfig @@ -0,0 +1,11 @@ +root = true +[*] +indent_style=tab +indent_size=tab +tab_width=4 +end_of_line=lf +charset=utf-8 +trim_trailing_whitespace=true +max_line_length=120 +insert_final_newline=true + diff --git a/ethstore/.gitignore b/ethstore/.gitignore new file mode 100644 index 000000000..c6262ea6a --- /dev/null +++ b/ethstore/.gitignore @@ -0,0 +1,2 @@ +target +*.swp diff --git a/ethstore/.travis.yml b/ethstore/.travis.yml new file mode 100644 index 000000000..8113e488e --- /dev/null +++ b/ethstore/.travis.yml @@ -0,0 +1,23 @@ +sudo: false +language: rust +branches: + only: + - master +matrix: + fast_finish: false + include: + - rust: stable + - rust: beta + - rust: nightly +after_success: | + [ $TRAVIS_BRANCH = master ] && + [ $TRAVIS_PULL_REQUEST = false ] && + [ $TRAVIS_RUST_VERSION = stable ] && + cargo doc --no-deps --verbose && + echo '' > target/doc/index.html && + pip install --user ghp-import && + /home/travis/.local/bin/ghp-import -n target/doc && + git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages +env: + global: + - secure: C4l7WR0jS84WNmd3MvmpPXQz4wRh4CLDS6bP3BqSHXadz8FPKejtMJZscLYAk5kIkDcVsTAYb88RsEFRrYOA4wkS6vhZBtryYRaJ68MlkyEU/77SYwm86rkQINIDw65O73dUD5LbWWCUoYkenGu26u/UnfayHfJBAyKw5IHkVKf6eDqu7E8ojKSEOXbWgBHjq6uixI8IESb15UjIE0AQ1Od+6cqhsz/caPhTMT3CJGjoCoVGWChwWSQZ+Ppb+xB83C/1h58UVwE9sZEyIPKwVP6socnHPmtR+VEUI6a7YIsOk6ZadKLtyy4523w4HqHNx1/dYjmsknbGpkF4D0DRp5L3D4t4J6URCkJIHfSRrBF5l2QbLMMuSf+KWMWuFOrOF5DBryobRKAVmIL5AjfvFsxtBNzYLPyVBs0ntbPuN5WeUPhadam00za9Z1ZvOUJxfNfyy9R67u6FdD9xkw2m/9hO7KJLDeZ4TSCRFrzfl/7WQprfjCwhZ+reKPgHH0Ufy1/Kh/WEuEBfZDa+z3mWWHlslqH2uBPH3+pvhzdVQGLB/5GZdJNeg/nJYJDCqHyWUKxkw+OMSvI0J8W0GiHV4TuY9V3p+rYjU2Zj69u3/xO/IvKrFtB9xdeJMrLiFQ2cD5vgzQOLCKo80f53NitUjdVSoWrY/NcYopBU4VHZMlk= diff --git a/ethstore/Cargo.toml b/ethstore/Cargo.toml new file mode 100644 index 000000000..41504154d --- /dev/null +++ b/ethstore/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "ethstore" +version = "0.1.0" +authors = ["debris "] +build = "build.rs" + +[dependencies] +libc = "0.2.11" +rand = "0.3.14" +ethkey = { path = "../ethkey" } +serde = "0.7" +serde_json = "0.7" +serde_macros = { version = "0.7", optional = true } +rustc-serialize = "0.3" +rust-crypto = "0.2.36" +tiny-keccak = "1.0" +docopt = { version = "0.6", optional = true } + +[build-dependencies] +serde_codegen = { version = "0.7", optional = true } +syntex = "0.33.0" + +[features] +default = ["cli", "serde_codegen"] +nightly = ["serde_macros"] +cli = ["docopt"] + +[[bin]] +name = "ethstore" +doc = false diff --git a/ethstore/README.md b/ethstore/README.md new file mode 100644 index 000000000..aba4911bf --- /dev/null +++ b/ethstore/README.md @@ -0,0 +1,162 @@ +# ethstore + +[![Build Status][travis-image]][travis-url] + +[travis-image]: https://travis-ci.org/ethcore/ethstore.svg?branch=master +[travis-url]: https://travis-ci.org/ethcore/ethstore + +Ethereum key management. + +[Documentation](http://ethcore.github.io/ethstore/ethstore/index.html) + +### Usage + +``` +Ethereum key management. + Copyright 2016 Ethcore (UK) Limited + +Usage: + ethstore insert [--dir DIR] + ethstore change-pwd
[--dir DIR] + ethstore list [--dir DIR] + ethstore import [--src DIR] [--dir DIR] + ethstore remove
[--dir DIR] + ethstore sign
[--dir DIR] + ethstore [-h | --help] + +Options: + -h, --help Display this message and exit. + --dir DIR Specify the secret store directory. It may be either + parity, parity-test, geth, geth-test + or a path [default: parity]. + --src DIR Specify import source. It may be either + parity, parity-test, get, geth-test + or a path [default: geth]. + +Commands: + insert Save account with password. + change-pwd Change account password. + list List accounts. + import Import accounts from src. + remove Remove account. + sign Sign message. +``` + +### Examples + +#### `insert [--dir DIR]` +*Encrypt secret with a password and save it in secret store.* + +- `` - ethereum secret, 32 bytes long +- `` - account password, any string +- `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity + +``` +ethstore insert 7d29fab185a33e2cd955812397354c472d2b84615b645aa135ff539f6b0d70d5 "this is sparta" +``` + +``` +a8fa5dd30a87bb9e3288d604eb74949c515ab66e +``` + +-- + +``` +ethstore insert `ethkey generate random -s` "this is sparta" +``` + +``` +24edfff680d536a5f6fe862d36df6f8f6f40f115 +``` + +-- + +#### `change-pwd
[--dir DIR]` +*Change account password.* + +- `
` - ethereum address, 20 bytes long +- `` - old account password, any string +- `` - new account password, any string +- `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity + +``` +ethstore change-pwd a8fa5dd30a87bb9e3288d604eb74949c515ab66e "this is sparta" "hello world" +``` + +``` +true +``` + +-- + +#### `list [--dir DIR]` +*List secret store accounts.* + +- `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity + +``` +ethstore list +``` + +``` + 0: 24edfff680d536a5f6fe862d36df6f8f6f40f115 + 1: 6edddfc6349aff20bc6467ccf276c5b52487f7a8 + 2: e6a3d25a7cb7cd21cb720df5b5e8afd154af1bbb +``` + +-- + +#### `import [--src DIR] [--dir DIR]` +*Import accounts from src.* + +- `[--src DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: geth +- `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity + +``` + 0: e6a3d25a7cb7cd21cb720df5b5e8afd154af1bbb + 1: 6edddfc6349aff20bc6467ccf276c5b52487f7a8 +``` + +-- + +#### `remove
[--dir DIR]` +*Remove account from secret store.* + +- `
` - ethereum address, 20 bytes long +- `` - account password, any string +- `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity + +``` +ethstore remove a8fa5dd30a87bb9e3288d604eb74949c515ab66e "hello world" +``` + +``` +true +``` + +-- + +#### `sign
[--dir DIR]` +*Sign message with account's secret.* + +- `
` - ethereum address, 20 bytes long +- `` - account password, any string +- `` - message to sign, 32 bytes long +- `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity + +``` +ethstore sign 24edfff680d536a5f6fe862d36df6f8f6f40f115 "this is sparta" 7d29fab185a33e2cd955812397354c472d2b84615b645aa135ff539f6b0d70d5 +``` + +``` +c6649f9555232d90ff716d7e552a744c5af771574425a74860e12f763479eb1b708c1f3a7dc0a0a7f7a81e0a0ca88c6deacf469222bb3d9c5bf0847f98bae54901 +``` + +-- + +# Ethcore toolchain +*this project is a part of the ethcore toolchain* + +- [**ethkey**](https://github.com/ethcore/ethkey) - Ethereum keys generator and signer. +- [**ethstore**](https://github.com/ethcore/ethstore) - Ethereum key management. +- [**ethabi**](https://github.com/ethcore/ethabi) - Ethereum function calls encoding. diff --git a/ethstore/build.rs b/ethstore/build.rs new file mode 100644 index 000000000..9113e596d --- /dev/null +++ b/ethstore/build.rs @@ -0,0 +1,29 @@ +#[cfg(not(feature = "serde_macros"))] +mod inner { + extern crate syntex; + extern crate serde_codegen; + + use std::env; + use std::path::Path; + + pub fn main() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + + let src = Path::new("src/json/mod.rs.in"); + let dst = Path::new(&out_dir).join("mod.rs"); + + let mut registry = syntex::Registry::new(); + + serde_codegen::register(&mut registry); + registry.expand("", &src, &dst).unwrap(); + } +} + +#[cfg(feature = "serde_macros")] +mod inner { + pub fn main() {} +} + +fn main() { + inner::main(); +} diff --git a/ethstore/src/account/cipher.rs b/ethstore/src/account/cipher.rs new file mode 100644 index 000000000..55b3c1de8 --- /dev/null +++ b/ethstore/src/account/cipher.rs @@ -0,0 +1,43 @@ +use json; + +#[derive(Debug, PartialEq, Clone)] +pub struct Aes128Ctr { + pub iv: [u8; 16], +} + +#[derive(Debug, PartialEq, Clone)] +pub enum Cipher { + Aes128Ctr(Aes128Ctr), +} + +impl From for Aes128Ctr { + fn from(json: json::Aes128Ctr) -> Self { + Aes128Ctr { + iv: json.iv.into() + } + } +} + +impl Into for Aes128Ctr { + fn into(self) -> json::Aes128Ctr { + json::Aes128Ctr { + iv: From::from(self.iv) + } + } +} + +impl From for Cipher { + fn from(json: json::Cipher) -> Self { + match json { + json::Cipher::Aes128Ctr(params) => Cipher::Aes128Ctr(From::from(params)), + } + } +} + +impl Into for Cipher { + fn into(self) -> json::Cipher { + match self { + Cipher::Aes128Ctr(params) => json::Cipher::Aes128Ctr(params.into()), + } + } +} diff --git a/ethstore/src/account/kdf.rs b/ethstore/src/account/kdf.rs new file mode 100644 index 000000000..f8d67dac8 --- /dev/null +++ b/ethstore/src/account/kdf.rs @@ -0,0 +1,109 @@ +use json; + +#[derive(Debug, PartialEq, Clone)] +pub enum Prf { + HmacSha256, +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Pbkdf2 { + pub c: u32, + pub dklen: u32, + pub prf: Prf, + pub salt: [u8; 32], +} + +#[derive(Debug, PartialEq, Clone)] +pub struct Scrypt { + pub dklen: u32, + pub p: u32, + pub n: u32, + pub r: u32, + pub salt: [u8; 32], +} + +#[derive(Debug, PartialEq, Clone)] +pub enum Kdf { + Pbkdf2(Pbkdf2), + Scrypt(Scrypt), +} + +impl From for Prf { + fn from(json: json::Prf) -> Self { + match json { + json::Prf::HmacSha256 => Prf::HmacSha256, + } + } +} + +impl Into for Prf { + fn into(self) -> json::Prf { + match self { + Prf::HmacSha256 => json::Prf::HmacSha256, + } + } +} + +impl From for Pbkdf2 { + fn from(json: json::Pbkdf2) -> Self { + Pbkdf2 { + c: json.c, + dklen: json.dklen, + prf: From::from(json.prf), + salt: json.salt.into(), + } + } +} + +impl Into for Pbkdf2 { + fn into(self) -> json::Pbkdf2 { + json::Pbkdf2 { + c: self.c, + dklen: self.dklen, + prf: self.prf.into(), + salt: From::from(self.salt), + } + } +} + +impl From for Scrypt { + fn from(json: json::Scrypt) -> Self { + Scrypt { + dklen: json.dklen, + p: json.p, + n: json.n, + r: json.r, + salt: json.salt.into(), + } + } +} + +impl Into for Scrypt { + fn into(self) -> json::Scrypt { + json::Scrypt { + dklen: self.dklen, + p: self.p, + n: self.n, + r: self.r, + salt: From::from(self.salt), + } + } +} + +impl From for Kdf { + fn from(json: json::Kdf) -> Self { + match json { + json::Kdf::Pbkdf2(params) => Kdf::Pbkdf2(From::from(params)), + json::Kdf::Scrypt(params) => Kdf::Scrypt(From::from(params)), + } + } +} + +impl Into for Kdf { + fn into(self) -> json::Kdf { + match self { + Kdf::Pbkdf2(params) => json::Kdf::Pbkdf2(params.into()), + Kdf::Scrypt(params) => json::Kdf::Scrypt(params.into()), + } + } +} diff --git a/ethstore/src/account/mod.rs b/ethstore/src/account/mod.rs new file mode 100644 index 000000000..b97526991 --- /dev/null +++ b/ethstore/src/account/mod.rs @@ -0,0 +1,9 @@ +mod cipher; +mod kdf; +mod safe_account; +mod version; + +pub use self::cipher::{Cipher, Aes128Ctr}; +pub use self::kdf::{Kdf, Pbkdf2, Scrypt, Prf}; +pub use self::safe_account::{SafeAccount, Crypto}; +pub use self::version::Version; diff --git a/ethstore/src/account/safe_account.rs b/ethstore/src/account/safe_account.rs new file mode 100644 index 000000000..934bfd03d --- /dev/null +++ b/ethstore/src/account/safe_account.rs @@ -0,0 +1,200 @@ +use std::ops::{Deref, DerefMut}; +use ethkey::{KeyPair, sign, Address, Secret, Signature, Message}; +use {json, Error, crypto}; +use crypto::Keccak256; +use random::Random; +use account::{Version, Cipher, Kdf, Aes128Ctr, Pbkdf2, Prf}; + +#[derive(Debug, PartialEq, Clone)] +pub struct Crypto { + pub cipher: Cipher, + pub ciphertext: [u8; 32], + pub kdf: Kdf, + pub mac: [u8; 32], +} + +#[derive(Debug, PartialEq, Clone)] +pub struct SafeAccount { + pub id: [u8; 16], + pub version: Version, + pub address: Address, + pub crypto: Crypto, +} + +impl From for Crypto { + fn from(json: json::Crypto) -> Self { + Crypto { + cipher: From::from(json.cipher), + ciphertext: json.ciphertext.into(), + kdf: From::from(json.kdf), + mac: json.mac.into(), + } + } +} + +impl Into for Crypto { + fn into(self) -> json::Crypto { + json::Crypto { + cipher: self.cipher.into(), + ciphertext: From::from(self.ciphertext), + kdf: self.kdf.into(), + mac: From::from(self.mac), + } + } +} + +impl From for SafeAccount { + fn from(json: json::KeyFile) -> Self { + SafeAccount { + id: json.id.into(), + version: From::from(json.version), + address: From::from(json.address), //json.address.into(), + crypto: From::from(json.crypto), + } + } +} + +impl Into for SafeAccount { + fn into(self) -> json::KeyFile { + json::KeyFile { + id: From::from(self.id), + version: self.version.into(), + address: self.address.into(), //From::from(self.address), + crypto: self.crypto.into(), + } + } +} + +impl Crypto { + pub fn create(secret: &Secret, password: &str, iterations: u32) -> Self { + let salt: [u8; 32] = Random::random(); + let iv: [u8; 16] = Random::random(); + + // two parts of derived key + // DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits] + let (derived_left_bits, derived_right_bits) = crypto::derive_key_iterations(password, &salt, iterations); + + let mut ciphertext = [0u8; 32]; + + // aes-128-ctr with initial vector of iv + crypto::aes::encrypt(&derived_left_bits, &iv, secret.deref(), &mut ciphertext); + + // KECCAK(DK[16..31] ++ ), where DK[16..31] - derived_right_bits + let mac = crypto::derive_mac(&derived_right_bits, &ciphertext).keccak256(); + + Crypto { + cipher: Cipher::Aes128Ctr(Aes128Ctr { + iv: iv, + }), + ciphertext: ciphertext, + kdf: Kdf::Pbkdf2(Pbkdf2 { + dklen: crypto::KEY_LENGTH as u32, + salt: salt, + c: iterations, + prf: Prf::HmacSha256, + }), + mac: mac, + } + } + + pub fn secret(&self, password: &str) -> Result { + 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), + }; + + let mac = crypto::derive_mac(&derived_right_bits, &self.ciphertext).keccak256(); + + if mac != self.mac { + return Err(Error::InvalidPassword); + } + + let mut secret = Secret::default(); + + match self.cipher { + Cipher::Aes128Ctr(ref params) => { + crypto::aes::decrypt(&derived_left_bits, ¶ms.iv, &self.ciphertext, secret.deref_mut()) + }, + } + + Ok(secret) + } +} + +impl SafeAccount { + pub fn create(keypair: &KeyPair, id: [u8; 16], password: &str, iterations: u32) -> Self { + SafeAccount { + id: id, + version: Version::V3, + crypto: Crypto::create(keypair.secret(), password, iterations), + address: keypair.address(), + } + } + + pub fn sign(&self, password: &str, message: &Message) -> Result { + let secret = try!(self.crypto.secret(password)); + sign(&secret, message).map_err(From::from) + } + + pub fn change_password(&self, old_password: &str, new_password: &str, iterations: u32) -> Result { + let secret = try!(self.crypto.secret(old_password)); + let result = SafeAccount { + id: self.id.clone(), + version: self.version.clone(), + crypto: Crypto::create(&secret, new_password, iterations), + address: self.address.clone(), + }; + Ok(result) + } + + pub fn check_password(&self, password: &str) -> bool { + self.crypto.secret(password).is_ok() + } +} + +#[cfg(test)] +mod tests { + use ethkey::{Generator, Random, verify, Message}; + use super::{Crypto, SafeAccount}; + + #[test] + fn crypto_create() { + let keypair = Random.generate().unwrap(); + let crypto = Crypto::create(keypair.secret(), "this is sparta", 10240); + let secret = crypto.secret("this is sparta").unwrap(); + assert_eq!(keypair.secret(), &secret); + } + + #[test] + #[should_panic] + fn crypto_invalid_password() { + let keypair = Random.generate().unwrap(); + let crypto = Crypto::create(keypair.secret(), "this is sparta", 10240); + let _ = crypto.secret("this is sparta!").unwrap(); + } + + #[test] + fn sign_and_verify() { + let keypair = Random.generate().unwrap(); + let password = "hello world"; + let message = Message::default(); + let account = SafeAccount::create(&keypair, [0u8; 16], password, 10240); + let signature = account.sign(password, &message).unwrap(); + assert!(verify(keypair.public(), &signature, &message).unwrap()); + } + + #[test] + fn change_password() { + let keypair = Random.generate().unwrap(); + let first_password = "hello world"; + let sec_password = "this is sparta"; + let i = 10240; + let message = Message::default(); + let account = SafeAccount::create(&keypair, [0u8; 16], first_password, i); + 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()); + assert!(new_account.sign(first_password, &message).is_err()); + assert!(new_account.sign(sec_password, &message).is_ok()); + } +} diff --git a/ethstore/src/account/version.rs b/ethstore/src/account/version.rs new file mode 100644 index 000000000..570ebd981 --- /dev/null +++ b/ethstore/src/account/version.rs @@ -0,0 +1,22 @@ +use json; + +#[derive(Debug, PartialEq, Clone)] +pub enum Version { + V3, +} + +impl From for Version { + fn from(json: json::Version) -> Self { + match json { + json::Version::V3 => Version::V3, + } + } +} + +impl Into for Version { + fn into(self) -> json::Version { + match self { + Version::V3 => json::Version::V3, + } + } +} diff --git a/ethstore/src/bin/ethstore.rs b/ethstore/src/bin/ethstore.rs new file mode 100644 index 000000000..e53acfeb2 --- /dev/null +++ b/ethstore/src/bin/ethstore.rs @@ -0,0 +1,128 @@ +extern crate rustc_serialize; +extern crate docopt; +extern crate ethstore; + +use std::{env, process}; +use std::ops::Deref; +use std::str::FromStr; +use docopt::Docopt; +use ethstore::ethkey::{Secret, Address, Message}; +use ethstore::dir::{KeyDirectory, ParityDirectory, DiskDirectory, GethDirectory, DirectoryType}; +use ethstore::{EthStore, SecretStore, import_accounts, Error}; + +pub const USAGE: &'static str = r#" +Ethereum key management. + Copyright 2016 Ethcore (UK) Limited + +Usage: + ethstore insert [--dir DIR] + ethstore change-pwd
[--dir DIR] + ethstore list [--dir DIR] + ethstore import [--src DIR] [--dir DIR] + ethstore remove
[--dir DIR] + ethstore sign
[--dir DIR] + ethstore [-h | --help] + +Options: + -h, --help Display this message and exit. + --dir DIR Specify the secret store directory. It may be either + parity, parity-test, geth, geth-test + or a path [default: parity]. + --src DIR Specify import source. It may be either + parity, parity-test, get, geth-test + or a path [default: geth]. + +Commands: + insert Save account with password. + change-pwd Change password. + list List accounts. + import Import accounts from src. + remove Remove account. + sign Sign message. +"#; + +#[derive(Debug, RustcDecodable)] +struct Args { + cmd_insert: bool, + cmd_change_pwd: bool, + cmd_list: bool, + cmd_import: bool, + cmd_remove: bool, + cmd_sign: bool, + arg_secret: String, + arg_password: String, + arg_old_pwd: String, + arg_new_pwd: String, + arg_address: String, + arg_message: String, + flag_src: String, + flag_dir: String, +} + +fn main() { + match execute(env::args()) { + Ok(result) => println!("{}", result), + Err(err) => { + println!("{}", err); + process::exit(1); + } + } +} + +fn key_dir(location: &str) -> Result, Error> { + let dir: Box = match location { + "parity" => Box::new(try!(ParityDirectory::create(DirectoryType::Main))), + "parity-test" => Box::new(try!(ParityDirectory::create(DirectoryType::Testnet))), + "geth" => Box::new(try!(GethDirectory::create(DirectoryType::Main))), + "geth-test" => Box::new(try!(GethDirectory::create(DirectoryType::Testnet))), + path => Box::new(try!(DiskDirectory::create(path))), + }; + + Ok(dir) +} + +fn format_accounts(accounts: &[Address]) -> String { + accounts.iter() + .enumerate() + .map(|(i, a)| format!("{:2}: {}", i, a)) + .collect::>() + .join("\n") +} + +fn execute(command: I) -> Result where I: IntoIterator, S: AsRef { + let args: Args = Docopt::new(USAGE) + .and_then(|d| d.argv(command).decode()) + .unwrap_or_else(|e| e.exit()); + + let store = try!(EthStore::open(try!(key_dir(&args.flag_dir)))); + + return if args.cmd_insert { + let secret = try!(Secret::from_str(&args.arg_secret)); + let address = try!(store.insert_account(secret, &args.arg_password)); + Ok(format!("{}", address)) + } else if args.cmd_change_pwd { + let address = try!(Address::from_str(&args.arg_address)); + let ok = store.change_password(&address, &args.arg_old_pwd, &args.arg_new_pwd).is_ok(); + Ok(format!("{}", ok)) + } else if args.cmd_list { + let accounts = store.accounts(); + Ok(format_accounts(&accounts)) + } else if args.cmd_import { + let src = try!(key_dir(&args.flag_src)); + let dst = try!(key_dir(&args.flag_dir)); + let accounts = try!(import_accounts(src.deref(), dst.deref())); + Ok(format_accounts(&accounts)) + } else if args.cmd_remove { + let address = try!(Address::from_str(&args.arg_address)); + let ok = store.remove_account(&address, &args.arg_password).is_ok(); + Ok(format!("{}", ok)) + } else if args.cmd_sign { + let address = try!(Address::from_str(&args.arg_address)); + let message = try!(Message::from_str(&args.arg_message)); + let signature = try!(store.sign(&address, &args.arg_password, &message)); + Ok(format!("{}", signature)) + } else { + unreachable!(); + } +} + diff --git a/ethstore/src/bin/main.rs b/ethstore/src/bin/main.rs new file mode 100644 index 000000000..8bed9a946 --- /dev/null +++ b/ethstore/src/bin/main.rs @@ -0,0 +1,5 @@ +#[cfg(feature = "cli")] +include!("ethstore.rs"); + +#[cfg(not(feature = "cli"))] +fn main() {} diff --git a/ethstore/src/crypto.rs b/ethstore/src/crypto.rs new file mode 100644 index 000000000..05ebc4042 --- /dev/null +++ b/ethstore/src/crypto.rs @@ -0,0 +1,69 @@ +use tiny_keccak::Keccak; +use rcrypto::pbkdf2::pbkdf2; +use rcrypto::scrypt::{scrypt, ScryptParams}; +use rcrypto::sha2::Sha256; +use rcrypto::hmac::Hmac; + +pub const KEY_LENGTH: usize = 32; +pub const KEY_ITERATIONS: usize = 10240; +pub const KEY_LENGTH_AES: usize = KEY_LENGTH / 2; + +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 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) -> (Vec, Vec) { + let mut derived_key = vec![0u8; KEY_LENGTH]; + let scrypt_params = ScryptParams::new(n.trailing_zeros() as u8, 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]; + (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); + mac[KEY_LENGTH_AES..cipher_text.len() + KEY_LENGTH_AES].copy_from_slice(cipher_text); + mac +} + +pub trait Keccak256 { + fn keccak256(&self) -> T where T: Sized; +} + +impl Keccak256<[u8; 32]> for [u8] { + fn keccak256(&self) -> [u8; 32] { + let mut keccak = Keccak::new_keccak256(); + let mut result = [0u8; 32]; + keccak.update(self); + keccak.finalize(&mut result); + result + } +} + +/// AES encryption +pub mod aes { + use rcrypto::blockmodes::CtrMode; + use rcrypto::aessafe::AesSafe128Encryptor; + use rcrypto::symmetriccipher::{Encryptor, Decryptor}; + use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer}; + + /// Encrypt a message + 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 + 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"); + } +} + diff --git a/ethstore/src/dir/disk.rs b/ethstore/src/dir/disk.rs new file mode 100644 index 000000000..2f6f39657 --- /dev/null +++ b/ethstore/src/dir/disk.rs @@ -0,0 +1,109 @@ +use std::{fs, ffi, io}; +use std::path::{PathBuf, Path}; +use std::collections::HashMap; +use ethkey::Address; +use {libc, json, SafeAccount, Error}; +use super::KeyDirectory; + +#[cfg(not(windows))] +fn restrict_permissions_to_owner(file_path: &Path) -> Result<(), i32> { + let cstr = ffi::CString::new(file_path.to_str().unwrap()).unwrap(); + match unsafe { libc::chmod(cstr.as_ptr(), libc::S_IWUSR | libc::S_IRUSR) } { + 0 => Ok(()), + x => Err(x), + } +} + +#[cfg(windows)] +fn restrict_permissions_to_owner(file_path: &Path) -> Result<(), i32> { + Ok(()) +} + +pub struct DiskDirectory { + path: PathBuf, +} + +impl DiskDirectory { + pub fn create

(path: P) -> Result where P: AsRef { + try!(fs::create_dir_all(&path)); + Ok(Self::at(path)) + } + + pub fn at

(path: P) -> Self where P: AsRef { + DiskDirectory { + path: path.as_ref().to_path_buf(), + } + } + + /// all accounts found in keys directory + fn files(&self) -> Result, Error> { + // it's not done using one iterator cause + // there is an issue with rustc and it takes tooo much time to compile + let paths = try!(fs::read_dir(&self.path)) + .flat_map(Result::ok) + .filter(|entry| { + let metadata = entry.metadata(); + metadata.is_ok() && !metadata.unwrap().is_dir() + }) + .map(|entry| entry.path()) + .collect::>(); + + let files: Result, _> = paths.iter() + .map(fs::File::open) + .collect(); + + let files = try!(files); + + let accounts = files.into_iter() + .map(json::KeyFile::load) + .zip(paths.into_iter()) + .filter_map(|(file, path)| file.ok().map(|file| (path, SafeAccount::from(file)))) + .collect(); + + Ok(accounts) + } +} + +impl KeyDirectory for DiskDirectory { + fn load(&self) -> Result, Error> { + let accounts = try!(self.files()) + .into_iter() + .map(|(_, account)| account) + .collect(); + Ok(accounts) + } + + fn insert(&self, account: SafeAccount) -> Result<(), Error> { + // transform account into key file + let keyfile: json::KeyFile = account.into(); + + // build file path + let mut keyfile_path = self.path.clone(); + keyfile_path.push(format!("{}", keyfile.id)); + + // save the file + let mut file = try!(fs::File::create(&keyfile_path)); + try!(keyfile.write(&mut file).map_err(|e| Error::Custom(format!("{:?}", e)))); + + if let Err(_) = restrict_permissions_to_owner(&keyfile_path) { + fs::remove_file(&keyfile_path).expect("Expected to remove recently created file"); + return Err(Error::Io(io::Error::last_os_error())); + } + + Ok(()) + } + + fn remove(&self, address: &Address) -> Result<(), Error> { + // enumerate all entries in keystore + // and find entry with given address + let to_remove = try!(self.files()) + .into_iter() + .find(|&(_, ref account)| &account.address == address); + + // remove it + match to_remove { + None => Err(Error::InvalidAccount), + Some((path, _)) => fs::remove_file(path).map_err(From::from) + } + } +} diff --git a/ethstore/src/dir/geth.rs b/ethstore/src/dir/geth.rs new file mode 100644 index 000000000..9f8850aad --- /dev/null +++ b/ethstore/src/dir/geth.rs @@ -0,0 +1,79 @@ +use std::env; +use std::path::PathBuf; +use ethkey::Address; +use {SafeAccount, Error}; +use super::{KeyDirectory, DiskDirectory, DirectoryType}; + +#[cfg(target_os = "macos")] +fn geth_dir_path() -> PathBuf { + let mut home = env::home_dir().expect("Failed to get home dir"); + home.push("Library"); + home.push("Ethereum"); + home +} + +#[cfg(windows)] +/// Default path for ethereum installation on Windows +pub fn geth_dir_path() -> PathBuf { + let mut home = env::home_dir().expect("Failed to get home dir"); + home.push("AppData"); + home.push("Roaming"); + home.push("Ethereum"); + home +} + +#[cfg(not(any(target_os = "macos", windows)))] +/// Default path for ethereum installation on posix system which is not Mac OS +pub fn geth_dir_path() -> PathBuf { + let mut home = env::home_dir().expect("Failed to get home dir"); + home.push(".ethereum"); + home +} + +fn geth_keystore(t: DirectoryType) -> PathBuf { + let mut dir = geth_dir_path(); + match t { + DirectoryType::Testnet => { + dir.push("testnet"); + dir.push("keystore"); + }, + DirectoryType::Main => { + dir.push("keystore"); + } + } + dir +} + +pub struct GethDirectory { + dir: DiskDirectory, +} + +impl GethDirectory { + pub fn create(t: DirectoryType) -> Result { + let result = GethDirectory { + dir: try!(DiskDirectory::create(geth_keystore(t))), + }; + + Ok(result) + } + + pub fn open(t: DirectoryType) -> Self { + GethDirectory { + dir: DiskDirectory::at(geth_keystore(t)), + } + } +} + +impl KeyDirectory for GethDirectory { + fn load(&self) -> Result, Error> { + self.dir.load() + } + + fn insert(&self, account: SafeAccount) -> Result<(), Error> { + self.dir.insert(account) + } + + fn remove(&self, address: &Address) -> Result<(), Error> { + self.dir.remove(address) + } +} diff --git a/ethstore/src/dir/mod.rs b/ethstore/src/dir/mod.rs new file mode 100644 index 000000000..a5537b56c --- /dev/null +++ b/ethstore/src/dir/mod.rs @@ -0,0 +1,21 @@ +use ethkey::Address; +use {SafeAccount, Error}; + +mod disk; +mod geth; +mod parity; + +pub enum DirectoryType { + Testnet, + Main, +} + +pub trait KeyDirectory: Send + Sync { + fn load(&self) -> Result, Error>; + fn insert(&self, account: SafeAccount) -> Result<(), Error>; + fn remove(&self, address: &Address) -> Result<(), Error>; +} + +pub use self::disk::DiskDirectory; +pub use self::geth::GethDirectory; +pub use self::parity::ParityDirectory; diff --git a/ethstore/src/dir/parity.rs b/ethstore/src/dir/parity.rs new file mode 100644 index 000000000..6f11d5ae6 --- /dev/null +++ b/ethstore/src/dir/parity.rs @@ -0,0 +1,58 @@ +use std::env; +use std::path::PathBuf; +use ethkey::Address; +use {SafeAccount, Error}; +use super::{KeyDirectory, DiskDirectory, DirectoryType}; + +fn parity_dir_path() -> PathBuf { + let mut home = env::home_dir().expect("Failed to get home dir"); + home.push(".parity"); + home +} + +fn parity_keystore(t: DirectoryType) -> PathBuf { + let mut dir = parity_dir_path(); + match t { + DirectoryType::Testnet => { + dir.push("testnet_keys"); + }, + DirectoryType::Main => { + dir.push("keys"); + } + } + dir +} + +pub struct ParityDirectory { + dir: DiskDirectory, +} + +impl ParityDirectory { + pub fn create(t: DirectoryType) -> Result { + let result = ParityDirectory { + dir: try!(DiskDirectory::create(parity_keystore(t))), + }; + + Ok(result) + } + + pub fn open(t: DirectoryType) -> Self { + ParityDirectory { + dir: DiskDirectory::at(parity_keystore(t)), + } + } +} + +impl KeyDirectory for ParityDirectory { + fn load(&self) -> Result, Error> { + self.dir.load() + } + + fn insert(&self, account: SafeAccount) -> Result<(), Error> { + self.dir.insert(account) + } + + fn remove(&self, address: &Address) -> Result<(), Error> { + self.dir.remove(address) + } +} diff --git a/ethstore/src/error.rs b/ethstore/src/error.rs new file mode 100644 index 000000000..537bfe008 --- /dev/null +++ b/ethstore/src/error.rs @@ -0,0 +1,42 @@ +use std::fmt; +use std::io::Error as IoError; +use ethkey::Error as EthKeyError; + +#[derive(Debug)] +pub enum Error { + Io(IoError), + InvalidPassword, + InvalidSecret, + InvalidAccount, + CreationFailed, + EthKey(EthKeyError), + Custom(String), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let s = match *self { + Error::Io(ref err) => format!("{}", err), + Error::InvalidPassword => "Invalid password".into(), + Error::InvalidSecret => "Invalid secret".into(), + Error::InvalidAccount => "Invalid account".into(), + Error::CreationFailed => "Account creation failed".into(), + Error::EthKey(ref err) => format!("{}", err), + Error::Custom(ref s) => s.clone(), + }; + + write!(f, "{}", s) + } +} + +impl From for Error { + fn from(err: IoError) -> Self { + Error::Io(err) + } +} + +impl From for Error { + fn from(err: EthKeyError) -> Self { + Error::EthKey(err) + } +} diff --git a/ethstore/src/ethkey.rs b/ethstore/src/ethkey.rs new file mode 100644 index 000000000..d77fa7a52 --- /dev/null +++ b/ethstore/src/ethkey.rs @@ -0,0 +1,17 @@ +//! ethkey reexport to make documentation look pretty. +pub use _ethkey::{Address, Message, Signature, Public, Secret, Generator, sign, verify, Error, KeyPair, Random, Prefix}; +use json; + +impl Into for Address { + fn into(self) -> json::H160 { + let a: [u8; 20] = self.into(); + From::from(a) + } +} + +impl From for Address { + fn from(json: json::H160) -> Self { + let a: [u8; 20] = json.into(); + From::from(a) + } +} diff --git a/ethstore/src/ethstore.rs b/ethstore/src/ethstore.rs new file mode 100644 index 000000000..103ff179d --- /dev/null +++ b/ethstore/src/ethstore.rs @@ -0,0 +1,92 @@ +use std::collections::BTreeMap; +use std::sync::RwLock; +use ethkey::KeyPair; +use crypto::KEY_ITERATIONS; +use random::Random; +use ethkey::{Signature, Address, Message, Secret}; +use dir::KeyDirectory; +use account::SafeAccount; +use {Error, SecretStore}; + +pub struct EthStore { + dir: Box, + iterations: u32, + cache: RwLock>, +} + +impl EthStore { + pub fn open(directory: Box) -> Result { + Self::open_with_iterations(directory, KEY_ITERATIONS as u32) + } + + pub fn open_with_iterations(directory: Box, iterations: u32) -> Result { + let accounts = try!(directory.load()); + let cache = accounts.into_iter().map(|account| (account.address.clone(), account)).collect(); + let store = EthStore { + dir: directory, + iterations: iterations, + cache: RwLock::new(cache), + }; + Ok(store) + } + + fn save(&self, account: SafeAccount) -> Result<(), Error> { + // save to file + try!(self.dir.insert(account.clone())); + + // update cache + let mut cache = self.cache.write().unwrap(); + cache.insert(account.address.clone(), account); + Ok(()) + } +} + +impl SecretStore for EthStore { + fn insert_account(&self, secret: Secret, password: &str) -> Result { + let keypair = try!(KeyPair::from_secret(secret).map_err(|_| Error::CreationFailed)); + let id: [u8; 16] = Random::random(); + let account = SafeAccount::create(&keypair, id, password, self.iterations); + let address = account.address.clone(); + try!(self.save(account)); + Ok(address) + } + + fn accounts(&self) -> Vec

{ + self.cache.read().unwrap().keys().cloned().collect() + } + + fn change_password(&self, address: &Address, old_password: &str, new_password: &str) -> Result<(), Error> { + // change password + let account = { + let cache = self.cache.read().unwrap(); + let account = try!(cache.get(address).ok_or(Error::InvalidAccount)); + try!(account.change_password(old_password, new_password, self.iterations)) + }; + + // save to file + self.save(account) + } + + fn remove_account(&self, address: &Address, password: &str) -> Result<(), Error> { + let can_remove = { + let cache = self.cache.read().unwrap(); + let account = try!(cache.get(address).ok_or(Error::InvalidAccount)); + account.check_password(password) + }; + + if can_remove { + try!(self.dir.remove(address)); + let mut cache = self.cache.write().unwrap(); + cache.remove(address); + Ok(()) + } else { + Err(Error::InvalidPassword) + } + } + + fn sign(&self, account: &Address, password: &str, message: &Message) -> Result { + let cache = self.cache.read().unwrap(); + let account = try!(cache.get(account).ok_or(Error::InvalidAccount)); + account.sign(password, message) + } +} diff --git a/ethstore/src/import.rs b/ethstore/src/import.rs new file mode 100644 index 000000000..94bb37925 --- /dev/null +++ b/ethstore/src/import.rs @@ -0,0 +1,12 @@ +use ethkey::Address; +use dir::KeyDirectory; +use Error; + +pub fn import_accounts(src: &KeyDirectory, dst: &KeyDirectory) -> Result, Error> { + let accounts = try!(src.load()); + accounts.into_iter().map(|a| { + let address = a.address.clone(); + try!(dst.insert(a)); + Ok(address) + }).collect() +} diff --git a/ethstore/src/json/cipher.rs b/ethstore/src/json/cipher.rs new file mode 100644 index 000000000..22fed9ee0 --- /dev/null +++ b/ethstore/src/json/cipher.rs @@ -0,0 +1,75 @@ +use serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError}; +use serde::de::Visitor; +use super::{Error, H128}; + +#[derive(Debug, PartialEq)] +pub enum CipherSer { + Aes128Ctr, +} + +impl Serialize for CipherSer { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer { + match *self { + CipherSer::Aes128Ctr => serializer.serialize_str("aes-128-ctr"), + } + } +} + +impl Deserialize for CipherSer { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(CipherSerVisitor) + } +} + +struct CipherSerVisitor; + +impl Visitor for CipherSerVisitor { + type Value = CipherSer; + + fn visit_str(&mut self, value: &str) -> Result where E: SerdeError { + match value { + "aes-128-ctr" => Ok(CipherSer::Aes128Ctr), + _ => Err(SerdeError::custom(Error::UnsupportedCipher)) + } + } + + fn visit_string(&mut self, value: String) -> Result where E: SerdeError { + self.visit_str(value.as_ref()) + } +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct Aes128Ctr { + pub iv: H128, +} + +#[derive(Debug, PartialEq)] +pub enum CipherSerParams { + Aes128Ctr(Aes128Ctr), +} + +impl Serialize for CipherSerParams { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer { + match *self { + CipherSerParams::Aes128Ctr(ref params) => params.serialize(serializer), + } + } +} + +impl Deserialize for CipherSerParams { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + Aes128Ctr::deserialize(deserializer) + .map(CipherSerParams::Aes128Ctr) + .map_err(|_| Error::InvalidCipherParams) + .map_err(SerdeError::custom) + } +} + +#[derive(Debug, PartialEq)] +pub enum Cipher { + Aes128Ctr(Aes128Ctr), +} diff --git a/ethstore/src/json/crypto.rs b/ethstore/src/json/crypto.rs new file mode 100644 index 000000000..c11078e71 --- /dev/null +++ b/ethstore/src/json/crypto.rs @@ -0,0 +1,184 @@ +use serde::{Deserialize, Deserializer, Serialize, Serializer, Error}; +use serde::de::{Visitor, MapVisitor}; +use serde::ser; +use super::{Cipher, CipherSer, CipherSerParams, Kdf, KdfSer, KdfSerParams, H256}; + +#[derive(Debug, PartialEq)] +pub struct Crypto { + pub cipher: Cipher, + pub ciphertext: H256, + pub kdf: Kdf, + pub mac: H256, +} + +enum CryptoField { + Cipher, + CipherParams, + CipherText, + Kdf, + KdfParams, + Mac, +} + +impl Deserialize for CryptoField { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer + { + deserializer.deserialize(CryptoFieldVisitor) + } +} + +struct CryptoFieldVisitor; + +impl Visitor for CryptoFieldVisitor { + type Value = CryptoField; + + fn visit_str(&mut self, value: &str) -> Result + where E: Error + { + match value { + "cipher" => Ok(CryptoField::Cipher), + "cipherparams" => Ok(CryptoField::CipherParams), + "ciphertext" => Ok(CryptoField::CipherText), + "kdf" => Ok(CryptoField::Kdf), + "kdfparams" => Ok(CryptoField::KdfParams), + "mac" => Ok(CryptoField::Mac), + _ => Err(Error::custom(format!("Unknown field: '{}'", value))), + } + } +} + +impl Deserialize for Crypto { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer + { + static FIELDS: &'static [&'static str] = &["id", "version", "crypto", "Crypto", "address"]; + deserializer.deserialize_struct("Crypto", FIELDS, CryptoVisitor) + } +} + +struct CryptoVisitor; + +impl Visitor for CryptoVisitor { + type Value = Crypto; + + fn visit_map(&mut self, mut visitor: V) -> Result + where V: MapVisitor + { + let mut cipher = None; + let mut cipherparams = None; + let mut ciphertext = None; + let mut kdf = None; + let mut kdfparams = None; + let mut mac = None; + + loop { + match try!(visitor.visit_key()) { + Some(CryptoField::Cipher) => { cipher = Some(try!(visitor.visit_value())); } + Some(CryptoField::CipherParams) => { cipherparams = Some(try!(visitor.visit_value())); } + Some(CryptoField::CipherText) => { ciphertext = Some(try!(visitor.visit_value())); } + Some(CryptoField::Kdf) => { kdf = Some(try!(visitor.visit_value())); } + Some(CryptoField::KdfParams) => { kdfparams = Some(try!(visitor.visit_value())); } + Some(CryptoField::Mac) => { mac = Some(try!(visitor.visit_value())); } + None => { break; } + } + } + + let cipher = match (cipher, cipherparams) { + (Some(CipherSer::Aes128Ctr), Some(CipherSerParams::Aes128Ctr(params))) => Cipher::Aes128Ctr(params), + (None, _) => return Err(Error::missing_field("cipher")), + (Some(_), None) => return Err(Error::missing_field("cipherparams")), + }; + + let ciphertext = match ciphertext { + Some(ciphertext) => ciphertext, + None => try!(visitor.missing_field("ciphertext")), + }; + + let kdf = match (kdf, kdfparams) { + (Some(KdfSer::Pbkdf2), Some(KdfSerParams::Pbkdf2(params))) => Kdf::Pbkdf2(params), + (Some(KdfSer::Scrypt), Some(KdfSerParams::Scrypt(params))) => Kdf::Scrypt(params), + (Some(_), Some(_)) => return Err(Error::custom("Invalid cipherparams")), + (None, _) => return Err(Error::missing_field("kdf")), + (Some(_), None) => return Err(Error::missing_field("kdfparams")), + }; + + let mac = match mac { + Some(mac) => mac, + None => try!(visitor.missing_field("mac")), + }; + + try!(visitor.end()); + + let result = Crypto { + cipher: cipher, + ciphertext: ciphertext, + kdf: kdf, + mac: mac, + }; + + Ok(result) + } +} + +impl Serialize for Crypto { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer + { + serializer.serialize_struct("Crypto", CryptoMapVisitor { + value: self, + state: 0, + }) + } +} + +struct CryptoMapVisitor<'a> { + value: &'a Crypto, + state: u8, +} + +impl<'a> ser::MapVisitor for CryptoMapVisitor<'a> { + fn visit(&mut self, serializer: &mut S) -> Result, S::Error> + where S: Serializer + { + match self.state { + 0 => { + self.state += 1; + match self.value.cipher { + Cipher::Aes128Ctr(_) => Ok(Some(try!(serializer.serialize_struct_elt("cipher", &CipherSer::Aes128Ctr)))), + } + }, + 1 => { + self.state += 1; + match self.value.cipher { + Cipher::Aes128Ctr(ref params) => Ok(Some(try!(serializer.serialize_struct_elt("cipherparams", params)))), + } + }, + 2 => { + self.state += 1; + Ok(Some(try!(serializer.serialize_struct_elt("ciphertext", &self.value.ciphertext)))) + }, + 3 => { + self.state += 1; + match self.value.kdf { + Kdf::Pbkdf2(_) => Ok(Some(try!(serializer.serialize_struct_elt("kdf", &KdfSer::Pbkdf2)))), + Kdf::Scrypt(_) => Ok(Some(try!(serializer.serialize_struct_elt("kdf", &KdfSer::Scrypt)))), + } + }, + 4 => { + self.state += 1; + match self.value.kdf { + Kdf::Pbkdf2(ref params) => Ok(Some(try!(serializer.serialize_struct_elt("kdfparams", params)))), + Kdf::Scrypt(ref params) => Ok(Some(try!(serializer.serialize_struct_elt("kdfparams", params)))), + } + }, + 5 => { + self.state += 1; + Ok(Some(try!(serializer.serialize_struct_elt("mac", &self.value.mac)))) + }, + _ => { + Ok(None) + } + } + } +} diff --git a/ethstore/src/json/error.rs b/ethstore/src/json/error.rs new file mode 100644 index 000000000..6700ee103 --- /dev/null +++ b/ethstore/src/json/error.rs @@ -0,0 +1,34 @@ +use std::fmt; + +#[derive(Debug, PartialEq)] +pub enum Error { + UnsupportedCipher, + InvalidCipherParams, + UnsupportedKdf, + InvalidUUID, + UnsupportedVersion, + InvalidCiphertext, + InvalidH256, + InvalidPrf, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Error::InvalidUUID => write!(f, "Invalid UUID"), + Error::UnsupportedVersion => write!(f, "Unsupported version"), + Error::UnsupportedKdf => write!(f, "Unsupported kdf"), + Error::InvalidCiphertext => write!(f, "Invalid ciphertext"), + Error::UnsupportedCipher => write!(f, "Unsupported cipher"), + Error::InvalidCipherParams => write!(f, "Invalid cipher params"), + Error::InvalidH256 => write!(f, "Invalid hash"), + Error::InvalidPrf => write!(f, "Invalid prf"), + } + } +} + +impl Into for Error { + fn into(self) -> String { + format!("{}", self) + } +} diff --git a/ethstore/src/json/hash.rs b/ethstore/src/json/hash.rs new file mode 100644 index 000000000..32d8a974e --- /dev/null +++ b/ethstore/src/json/hash.rs @@ -0,0 +1,71 @@ +use std::str::FromStr; +use rustc_serialize::hex::{FromHex, ToHex}; +use serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError}; +use serde::de::Visitor; +use super::Error; + +macro_rules! impl_hash { + ($name: ident, $size: expr) => { + #[derive(Debug, PartialEq)] + pub struct $name([u8; $size]); + + impl Serialize for $name { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer { + serializer.serialize_str(&self.0.to_hex()) + } + } + + impl Deserialize for $name { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + struct HashVisitor; + + impl Visitor for HashVisitor { + type Value = $name; + + fn visit_str(&mut self, value: &str) -> Result where E: SerdeError { + FromStr::from_str(value).map_err(SerdeError::custom) + } + + fn visit_string(&mut self, value: String) -> Result where E: SerdeError { + self.visit_str(value.as_ref()) + } + } + + deserializer.deserialize(HashVisitor) + } + } + + impl FromStr for $name { + type Err = Error; + + fn from_str(value: &str) -> Result { + match value.from_hex() { + Ok(ref hex) if hex.len() == $size => { + let mut hash = [0u8; $size]; + hash.clone_from_slice(hex); + Ok($name(hash)) + } + _ => Err(Error::InvalidH256), + } + } + } + + impl From<[u8; $size]> for $name { + fn from(bytes: [u8; $size]) -> Self { + $name(bytes) + } + } + + impl Into<[u8; $size]> for $name { + fn into(self) -> [u8; $size] { + self.0 + } + } + } +} + +impl_hash!(H128, 16); +impl_hash!(H160, 20); +impl_hash!(H256, 32); diff --git a/ethstore/src/json/id.rs b/ethstore/src/json/id.rs new file mode 100644 index 000000000..e6020ddcb --- /dev/null +++ b/ethstore/src/json/id.rs @@ -0,0 +1,129 @@ +//! Universaly unique identifier. +use std::str::FromStr; +use std::fmt; +use rustc_serialize::hex::{ToHex, FromHex}; +use serde::{Deserialize, Serialize, Deserializer, Serializer, Error as SerdeError}; +use serde::de::Visitor; +use super::Error; + +/// Universaly unique identifier. +#[derive(Debug, PartialEq)] +pub struct UUID([u8; 16]); + +impl From<[u8; 16]> for UUID { + fn from(uuid: [u8; 16]) -> Self { + UUID(uuid) + } +} + +impl<'a> Into for &'a UUID { + fn into(self) -> String { + let d1 = &self.0[0..4]; + let d2 = &self.0[4..6]; + let d3 = &self.0[6..8]; + let d4 = &self.0[8..10]; + let d5 = &self.0[10..16]; + [d1, d2, d3, d4, d5].into_iter().map(|d| d.to_hex()).collect::>().join("-") + } +} + +impl Into for UUID { + fn into(self) -> String { + Into::into(&self) + } +} + +impl Into<[u8; 16]> for UUID { + fn into(self) -> [u8; 16] { + self.0 + } +} + +impl fmt::Display for UUID { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let s: String = (self as &UUID).into(); + write!(f, "{}", s) + } +} + +fn copy_into(from: &str, into: &mut [u8]) -> Result<(), Error> { + let from = try!(from.from_hex().map_err(|_| Error::InvalidUUID)); + + if from.len() != into.len() { + return Err(Error::InvalidUUID); + } + + into.copy_from_slice(&from); + Ok(()) +} + +impl FromStr for UUID { + type Err = Error; + + fn from_str(s: &str) -> Result { + let parts: Vec<&str> = s.split("-").collect(); + + if parts.len() != 5 { + return Err(Error::InvalidUUID); + } + + let mut uuid = [0u8; 16]; + + try!(copy_into(parts[0], &mut uuid[0..4])); + try!(copy_into(parts[1], &mut uuid[4..6])); + try!(copy_into(parts[2], &mut uuid[6..8])); + try!(copy_into(parts[3], &mut uuid[8..10])); + try!(copy_into(parts[4], &mut uuid[10..16])); + + Ok(UUID(uuid)) + } +} + +impl Serialize for UUID { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer { + let s: String = self.into(); + serializer.serialize_str(&s) + } +} + +impl Deserialize for UUID { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(UUIDVisitor) + } +} + +struct UUIDVisitor; + +impl Visitor for UUIDVisitor { + type Value = UUID; + + fn visit_str(&mut self, value: &str) -> Result where E: SerdeError { + UUID::from_str(value).map_err(SerdeError::custom) + } + + fn visit_string(&mut self, value: String) -> Result where E: SerdeError { + self.visit_str(value.as_ref()) + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use super::UUID; + + #[test] + fn uuid_from_str() { + let uuid = UUID::from_str("3198bc9c-6672-5ab3-d995-4942343ae5b6").unwrap(); + assert_eq!(uuid, UUID::from([0x31, 0x98, 0xbc, 0x9c, 0x66, 0x72, 0x5a, 0xb3, 0xd9, 0x95, 0x49, 0x42, 0x34, 0x3a, 0xe5, 0xb6])); + } + + #[test] + fn uuid_from_and_to_str() { + let from = "3198bc9c-6672-5ab3-d995-4942343ae5b6"; + let uuid = UUID::from_str(from).unwrap(); + let to: String = uuid.into(); + assert_eq!(from, &to); + } +} diff --git a/ethstore/src/json/kdf.rs b/ethstore/src/json/kdf.rs new file mode 100644 index 000000000..c00fc8bd3 --- /dev/null +++ b/ethstore/src/json/kdf.rs @@ -0,0 +1,133 @@ +use serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError}; +use serde::de::Visitor; +use serde_json::{Value, value}; +use super::{Error, H256}; + +#[derive(Debug, PartialEq)] +pub enum KdfSer { + Pbkdf2, + Scrypt, +} + +impl Serialize for KdfSer { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer { + match *self { + KdfSer::Pbkdf2 => serializer.serialize_str("pbkdf2"), + KdfSer::Scrypt => serializer.serialize_str("scrypt"), + } + } +} + +impl Deserialize for KdfSer { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(KdfSerVisitor) + } +} + +struct KdfSerVisitor; + +impl Visitor for KdfSerVisitor { + type Value = KdfSer; + + fn visit_str(&mut self, value: &str) -> Result where E: SerdeError { + match value { + "pbkdf2" => Ok(KdfSer::Pbkdf2), + "scrypt" => Ok(KdfSer::Scrypt), + _ => Err(SerdeError::custom(Error::UnsupportedKdf)) + } + } + + fn visit_string(&mut self, value: String) -> Result where E: SerdeError { + self.visit_str(value.as_ref()) + } +} + +#[derive(Debug, PartialEq)] +pub enum Prf { + HmacSha256, +} + +impl Serialize for Prf { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer { + match *self { + Prf::HmacSha256 => serializer.serialize_str("hmac-sha256"), + } + } +} + +impl Deserialize for Prf { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(PrfVisitor) + } +} + +struct PrfVisitor; + +impl Visitor for PrfVisitor { + type Value = Prf; + + fn visit_str(&mut self, value: &str) -> Result where E: SerdeError { + match value { + "hmac-sha256" => Ok(Prf::HmacSha256), + _ => Err(SerdeError::custom(Error::InvalidPrf)), + } + } + + fn visit_string(&mut self, value: String) -> Result where E: SerdeError { + self.visit_str(value.as_ref()) + } +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct Pbkdf2 { + pub c: u32, + pub dklen: u32, + pub prf: Prf, + pub salt: H256, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct Scrypt { + pub dklen: u32, + pub p: u32, + pub n: u32, + pub r: u32, + pub salt: H256, +} + +#[derive(Debug, PartialEq)] +pub enum KdfSerParams { + Pbkdf2(Pbkdf2), + Scrypt(Scrypt), +} + +impl Serialize for KdfSerParams { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer { + match *self { + KdfSerParams::Pbkdf2(ref params) => params.serialize(serializer), + KdfSerParams::Scrypt(ref params) => params.serialize(serializer), + } + } +} + +impl Deserialize for KdfSerParams { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + let v = try!(Value::deserialize(deserializer)); + + Deserialize::deserialize(&mut value::Deserializer::new(v.clone())).map(KdfSerParams::Pbkdf2) + .or_else(|_| Deserialize::deserialize(&mut value::Deserializer::new(v)).map(KdfSerParams::Scrypt)) + .map_err(|e| D::Error::custom(format!("{}", e))) + } +} + +#[derive(Debug, PartialEq)] +pub enum Kdf { + Pbkdf2(Pbkdf2), + Scrypt(Scrypt), +} diff --git a/ethstore/src/json/key_file.rs b/ethstore/src/json/key_file.rs new file mode 100644 index 000000000..eae5e58ae --- /dev/null +++ b/ethstore/src/json/key_file.rs @@ -0,0 +1,255 @@ +use std::io::{Read, Write}; +use serde::{Deserialize, Deserializer, Error}; +use serde::de::{Visitor, MapVisitor}; +use serde_json; +use super::{UUID, Version, Crypto, H160}; + +#[derive(Debug, PartialEq, Serialize)] +pub struct KeyFile { + pub id: UUID, + pub version: Version, + pub crypto: Crypto, + pub address: H160, +} + +enum KeyFileField { + ID, + Version, + Crypto, + Address, +} + +impl Deserialize for KeyFileField { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer + { + deserializer.deserialize(KeyFileFieldVisitor) + } +} + +struct KeyFileFieldVisitor; + +impl Visitor for KeyFileFieldVisitor { + type Value = KeyFileField; + + fn visit_str(&mut self, value: &str) -> Result + where E: Error + { + match value { + "id" => Ok(KeyFileField::ID), + "version" => Ok(KeyFileField::Version), + "crypto" => Ok(KeyFileField::Crypto), + "Crypto" => Ok(KeyFileField::Crypto), + "address" => Ok(KeyFileField::Address), + _ => Err(Error::custom(format!("Unknown field: '{}'", value))), + } + } +} + +impl Deserialize for KeyFile { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer + { + static FIELDS: &'static [&'static str] = &["id", "version", "crypto", "Crypto", "address"]; + deserializer.deserialize_struct("KeyFile", FIELDS, KeyFileVisitor) + } +} + +struct KeyFileVisitor; + +impl Visitor for KeyFileVisitor { + type Value = KeyFile; + + fn visit_map(&mut self, mut visitor: V) -> Result + where V: MapVisitor + { + let mut id = None; + let mut version = None; + let mut crypto = None; + let mut address = None; + + loop { + match try!(visitor.visit_key()) { + Some(KeyFileField::ID) => { id = Some(try!(visitor.visit_value())); } + Some(KeyFileField::Version) => { version = Some(try!(visitor.visit_value())); } + Some(KeyFileField::Crypto) => { crypto = Some(try!(visitor.visit_value())); } + Some(KeyFileField::Address) => { address = Some(try!(visitor.visit_value())); } + None => { break; } + } + } + + let id = match id { + Some(id) => id, + None => try!(visitor.missing_field("id")), + }; + + let version = match version { + Some(version) => version, + None => try!(visitor.missing_field("version")), + }; + + let crypto = match crypto { + Some(crypto) => crypto, + None => try!(visitor.missing_field("crypto")), + }; + + let address = match address { + Some(address) => address, + None => try!(visitor.missing_field("address")), + }; + + try!(visitor.end()); + + let result = KeyFile { + id: id, + version: version, + crypto: crypto, + address: address, + }; + + Ok(result) + } +} + +impl KeyFile { + pub fn load(reader: R) -> Result where R: Read { + serde_json::from_reader(reader) + } + + pub fn write(&self, writer: &mut W) -> Result<(), serde_json::Error> where W: Write { + serde_json::to_writer(writer, self) + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use serde_json; + use json::{KeyFile, UUID, Version, Crypto, Cipher, Aes128Ctr, Kdf, Scrypt, H128, H160, H256}; + + #[test] + fn basic_keyfile() { + let json = r#" + { + "address": "6edddfc6349aff20bc6467ccf276c5b52487f7a8", + "crypto": { + "cipher": "aes-128-ctr", + "ciphertext": "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc", + "cipherparams": { + "iv": "b5a7ec855ec9e2c405371356855fec83" + }, + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 262144, + "p": 1, + "r": 8, + "salt": "1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209" + }, + "mac": "46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f" + }, + "id": "8777d9f6-7860-4b9b-88b7-0b57ee6b3a73", + "version": 3 + }"#; + + let expected = KeyFile { + id: UUID::from_str("8777d9f6-7860-4b9b-88b7-0b57ee6b3a73").unwrap(), + version: Version::V3, + address: H160::from_str("6edddfc6349aff20bc6467ccf276c5b52487f7a8").unwrap(), + crypto: Crypto { + cipher: Cipher::Aes128Ctr(Aes128Ctr { + iv: H128::from_str("b5a7ec855ec9e2c405371356855fec83").unwrap(), + }), + ciphertext: H256::from_str("7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc").unwrap(), + kdf: Kdf::Scrypt(Scrypt { + n: 262144, + dklen: 32, + p: 1, + r: 8, + salt: H256::from_str("1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209").unwrap(), + }), + mac: H256::from_str("46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f").unwrap(), + }, + }; + + let keyfile: KeyFile = serde_json::from_str(json).unwrap(); + assert_eq!(keyfile, expected); + } + + #[test] + fn capital_crypto_keyfile() { + let json = r#" + { + "address": "6edddfc6349aff20bc6467ccf276c5b52487f7a8", + "Crypto": { + "cipher": "aes-128-ctr", + "ciphertext": "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc", + "cipherparams": { + "iv": "b5a7ec855ec9e2c405371356855fec83" + }, + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 262144, + "p": 1, + "r": 8, + "salt": "1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209" + }, + "mac": "46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f" + }, + "id": "8777d9f6-7860-4b9b-88b7-0b57ee6b3a73", + "version": 3 + }"#; + + let expected = KeyFile { + id: UUID::from_str("8777d9f6-7860-4b9b-88b7-0b57ee6b3a73").unwrap(), + version: Version::V3, + address: H160::from_str("6edddfc6349aff20bc6467ccf276c5b52487f7a8").unwrap(), + crypto: Crypto { + cipher: Cipher::Aes128Ctr(Aes128Ctr { + iv: H128::from_str("b5a7ec855ec9e2c405371356855fec83").unwrap(), + }), + ciphertext: H256::from_str("7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc").unwrap(), + kdf: Kdf::Scrypt(Scrypt { + n: 262144, + dklen: 32, + p: 1, + r: 8, + salt: H256::from_str("1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209").unwrap(), + }), + mac: H256::from_str("46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f").unwrap(), + }, + }; + + let keyfile: KeyFile = serde_json::from_str(json).unwrap(); + assert_eq!(keyfile, expected); + } + + #[test] + fn to_and_from_json() { + let file = KeyFile { + id: UUID::from_str("8777d9f6-7860-4b9b-88b7-0b57ee6b3a73").unwrap(), + version: Version::V3, + address: H160::from_str("6edddfc6349aff20bc6467ccf276c5b52487f7a8").unwrap(), + crypto: Crypto { + cipher: Cipher::Aes128Ctr(Aes128Ctr { + iv: H128::from_str("b5a7ec855ec9e2c405371356855fec83").unwrap(), + }), + ciphertext: H256::from_str("7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc").unwrap(), + kdf: Kdf::Scrypt(Scrypt { + n: 262144, + dklen: 32, + p: 1, + r: 8, + salt: H256::from_str("1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209").unwrap(), + }), + mac: H256::from_str("46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f").unwrap(), + }, + }; + + let serialized = serde_json::to_string(&file).unwrap(); + let deserialized = serde_json::from_str(&serialized).unwrap(); + + assert_eq!(file, deserialized); + } +} diff --git a/ethstore/src/json/mod.rs b/ethstore/src/json/mod.rs new file mode 100644 index 000000000..dd069332b --- /dev/null +++ b/ethstore/src/json/mod.rs @@ -0,0 +1,8 @@ +//! Contract interface specification. + +#[cfg(feature = "serde_macros")] +include!("mod.rs.in"); + +#[cfg(not(feature = "serde_macros"))] +include!(concat!(env!("OUT_DIR"), "/mod.rs")); + diff --git a/ethstore/src/json/mod.rs.in b/ethstore/src/json/mod.rs.in new file mode 100644 index 000000000..c4a67a287 --- /dev/null +++ b/ethstore/src/json/mod.rs.in @@ -0,0 +1,18 @@ +mod cipher; +mod crypto; +mod error; +mod hash; +mod id; +mod kdf; +mod key_file; +mod version; + +pub use self::cipher::{Cipher, CipherSer, CipherSerParams, Aes128Ctr}; +pub use self::crypto::Crypto; +pub use self::error::Error; +pub use self::hash::{H128, H160, H256}; +pub use self::id::UUID; +pub use self::kdf::{Kdf, KdfSer, Prf, Pbkdf2, Scrypt, KdfSerParams}; +pub use self::key_file::KeyFile; +pub use self::version::Version; + diff --git a/ethstore/src/json/version.rs b/ethstore/src/json/version.rs new file mode 100644 index 000000000..3b4105a79 --- /dev/null +++ b/ethstore/src/json/version.rs @@ -0,0 +1,38 @@ +use serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError}; +use serde::de::Visitor; +use super::Error; + +#[derive(Debug, PartialEq)] +pub enum Version { + V3, +} + +impl Serialize for Version { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: Serializer { + match *self { + Version::V3 => serializer.serialize_u64(3) + } + } +} + +impl Deserialize for Version { + fn deserialize(deserializer: &mut D) -> Result + where D: Deserializer { + deserializer.deserialize(VersionVisitor) + } +} + +struct VersionVisitor; + +impl Visitor for VersionVisitor { + type Value = Version; + + fn visit_u64(&mut self, value: u64) -> Result where E: SerdeError { + match value { + 3 => Ok(Version::V3), + _ => Err(SerdeError::custom(Error::UnsupportedVersion)) + } + } +} + diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs new file mode 100644 index 000000000..62932fc16 --- /dev/null +++ b/ethstore/src/lib.rs @@ -0,0 +1,32 @@ +#![cfg_attr(feature="nightly", feature(custom_derive, plugin))] +#![cfg_attr(feature="nightly", plugin(serde_macros))] + +extern crate libc; +extern crate rand; +extern crate serde; +extern crate serde_json; +extern crate rustc_serialize; +extern crate crypto as rcrypto; +extern crate tiny_keccak; +// reexport it nicely +extern crate ethkey as _ethkey; + +pub mod dir; +pub mod ethkey; + +mod account; +mod json; +mod crypto; + +mod error; +mod ethstore; +mod import; +mod random; +mod secret_store; + +pub use self::account::SafeAccount; +pub use self::error::Error; +pub use self::ethstore::EthStore; +pub use self::import::import_accounts; +pub use self::secret_store::SecretStore; + diff --git a/ethstore/src/random.rs b/ethstore/src/random.rs new file mode 100644 index 000000000..2693d4fcf --- /dev/null +++ b/ethstore/src/random.rs @@ -0,0 +1,23 @@ +use rand::{Rng, OsRng}; + +pub trait Random { + fn random() -> Self where Self: Sized; +} + +impl Random for [u8; 16] { + fn random() -> Self { + let mut result = [0u8; 16]; + let mut rng = OsRng::new().unwrap(); + rng.fill_bytes(&mut result); + result + } +} + +impl Random for [u8; 32] { + fn random() -> Self { + let mut result = [0u8; 32]; + let mut rng = OsRng::new().unwrap(); + rng.fill_bytes(&mut result); + result + } +} diff --git a/ethstore/src/secret_store.rs b/ethstore/src/secret_store.rs new file mode 100644 index 000000000..620b8d9b9 --- /dev/null +++ b/ethstore/src/secret_store.rs @@ -0,0 +1,15 @@ +use ethkey::{Address, Message, Signature, Secret}; +use Error; + +pub trait SecretStore: Send + Sync { + fn insert_account(&self, secret: Secret, password: &str) -> Result; + + fn accounts(&self) -> Vec
; + + fn change_password(&self, account: &Address, old_password: &str, new_password: &str) -> Result<(), Error>; + + fn remove_account(&self, account: &Address, password: &str) -> Result<(), Error>; + + fn sign(&self, account: &Address, password: &str, message: &Message) -> Result; +} + diff --git a/ethstore/tests/api.rs b/ethstore/tests/api.rs new file mode 100644 index 000000000..a29b143db --- /dev/null +++ b/ethstore/tests/api.rs @@ -0,0 +1,72 @@ +extern crate rand; +extern crate ethstore; + +mod util; + +use ethstore::{SecretStore, EthStore}; +use ethstore::ethkey::{Random, Generator, Secret}; +use util::TransientDir; + +#[test] +fn secret_store_create() { + let dir = TransientDir::create().unwrap(); + let _ = EthStore::open(Box::new(dir)).unwrap(); +} + +#[test] +#[should_panic] +fn secret_store_open_not_existing() { + let dir = TransientDir::open(); + let _ = EthStore::open(Box::new(dir)).unwrap(); +} + +fn random_secret() -> Secret { + Random.generate().unwrap().secret().clone() +} + +#[test] +fn secret_store_create_account() { + let dir = TransientDir::create().unwrap(); + let store = EthStore::open(Box::new(dir)).unwrap(); + assert_eq!(store.accounts().len(), 0); + assert!(store.insert_account(random_secret(), "").is_ok()); + assert_eq!(store.accounts().len(), 1); + assert!(store.insert_account(random_secret(), "").is_ok()); + assert_eq!(store.accounts().len(), 2); +} + +#[test] +fn secret_store_sign() { + let dir = TransientDir::create().unwrap(); + let store = EthStore::open(Box::new(dir)).unwrap(); + assert!(store.insert_account(random_secret(), "").is_ok()); + let accounts = store.accounts(); + assert_eq!(accounts.len(), 1); + assert!(store.sign(&accounts[0], "", &Default::default()).is_ok()); + assert!(store.sign(&accounts[0], "1", &Default::default()).is_err()); +} + +#[test] +fn secret_store_change_password() { + let dir = TransientDir::create().unwrap(); + let store = EthStore::open(Box::new(dir)).unwrap(); + assert!(store.insert_account(random_secret(), "").is_ok()); + let accounts = store.accounts(); + assert_eq!(accounts.len(), 1); + assert!(store.sign(&accounts[0], "", &Default::default()).is_ok()); + assert!(store.change_password(&accounts[0], "", "1").is_ok()); + assert!(store.sign(&accounts[0], "", &Default::default()).is_err()); + assert!(store.sign(&accounts[0], "1", &Default::default()).is_ok()); +} + +#[test] +fn secret_store_remove_account() { + let dir = TransientDir::create().unwrap(); + let store = EthStore::open(Box::new(dir)).unwrap(); + assert!(store.insert_account(random_secret(), "").is_ok()); + let accounts = store.accounts(); + assert_eq!(accounts.len(), 1); + assert!(store.remove_account(&accounts[0], "").is_ok()); + assert_eq!(store.accounts().len(), 0); + assert!(store.remove_account(&accounts[0], "").is_err()); +} diff --git a/ethstore/tests/cli.rs b/ethstore/tests/cli.rs new file mode 100644 index 000000000..e69de29bb diff --git a/ethstore/tests/util/mod.rs b/ethstore/tests/util/mod.rs new file mode 100644 index 000000000..03bdb8af1 --- /dev/null +++ b/ethstore/tests/util/mod.rs @@ -0,0 +1,3 @@ +mod transient_dir; + +pub use self::transient_dir::TransientDir; diff --git a/ethstore/tests/util/transient_dir.rs b/ethstore/tests/util/transient_dir.rs new file mode 100644 index 000000000..b29a5d775 --- /dev/null +++ b/ethstore/tests/util/transient_dir.rs @@ -0,0 +1,58 @@ +use std::path::PathBuf; +use std::{env, fs}; +use rand::{Rng, OsRng}; +use ethstore::dir::{KeyDirectory, DiskDirectory}; +use ethstore::ethkey::Address; +use ethstore::{Error, SafeAccount}; + +pub fn random_dir() -> PathBuf { + let mut rng = OsRng::new().unwrap(); + let mut dir = env::temp_dir(); + dir.push(format!("{:x}-{:x}", rng.next_u64(), rng.next_u64())); + dir +} + +pub struct TransientDir { + dir: DiskDirectory, + path: PathBuf, +} + +impl TransientDir { + pub fn create() -> Result { + let path = random_dir(); + let result = TransientDir { + dir: try!(DiskDirectory::create(&path)), + path: path, + }; + + Ok(result) + } + + pub fn open() -> Self { + let path = random_dir(); + TransientDir { + dir: DiskDirectory::at(&path), + path: path, + } + } +} + +impl Drop for TransientDir { + fn drop(&mut self) { + fs::remove_dir_all(&self.path).expect("Expected to remove temp dir"); + } +} + +impl KeyDirectory for TransientDir { + fn load(&self) -> Result, Error> { + self.dir.load() + } + + fn insert(&self, account: SafeAccount) -> Result<(), Error> { + self.dir.insert(account) + } + + fn remove(&self, address: &Address) -> Result<(), Error> { + self.dir.remove(address) + } +} diff --git a/parity/configuration.rs b/parity/configuration.rs index 3aff2ee27..7c42f06e1 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -24,7 +24,7 @@ use docopt::Docopt; use die::*; use util::*; -use util::keys::store::{ImportKeySet, AccountService}; +use ethcore::account_provider::AccountProvider; use util::network_settings::NetworkSettings; use ethcore::client::{append_path, get_db_path, ClientConfig, Switch, VMType}; use ethcore::ethereum; @@ -249,7 +249,10 @@ impl Configuration { sync_config } - pub fn account_service(&self) -> AccountService { + pub fn account_service(&self) -> AccountProvider { + use ethcore::ethstore::{import_accounts, EthStore}; + use ethcore::ethstore::dir::{GethDirectory, DirectoryType, DiskDirectory}; + // Secret Store let passwords = self.args.flag_password.iter().flat_map(|filename| { BufReader::new(&File::open(filename).unwrap_or_else(|_| die!("{} Unable to read password file. Ensure it exists and permissions are correct.", filename))) @@ -258,18 +261,30 @@ impl Configuration { .collect::>() .into_iter() }).collect::>(); - let import_keys = match (self.args.flag_no_import_keys, self.args.flag_testnet) { - (true, _) => ImportKeySet::None, - (false, false) => ImportKeySet::Legacy, - (false, true) => ImportKeySet::LegacyTestnet, - }; - let account_service = AccountService::with_security(Path::new(&self.keys_path()), self.keys_iterations(), import_keys); + + if !self.args.flag_no_import_keys { + let dir_type = match self.args.flag_testnet { + true => DirectoryType::Testnet, + false => DirectoryType::Main, + }; + + let from = GethDirectory::open(dir_type); + let to = DiskDirectory::create(self.keys_path()).unwrap(); + if let Err(e) = import_accounts(&from, &to) { + warn!("Could not import accounts {}", e); + } + } + + let dir = Box::new(DiskDirectory::create(self.keys_path()).unwrap()); + let iterations = self.keys_iterations(); + let account_service = AccountProvider::new(Box::new(EthStore::open_with_iterations(dir, iterations).unwrap())); + if let Some(ref unlocks) = self.args.flag_unlock { for d in unlocks.split(',') { let a = Address::from_str(clean_0x(d)).unwrap_or_else(|_| { die!("{}: Invalid address for --unlock. Must be 40 hex characters, without the 0x at the beginning.", d) }); - if passwords.iter().find(|p| account_service.unlock_account_no_expire(&a, p).is_ok()).is_none() { + if passwords.iter().find(|p| account_service.unlock_account_permanently(a, (*p).clone()).is_ok()).is_none() { die!("No password given to unlock account {}. Pass the password using `--password`.", a); } } diff --git a/parity/io_handler.rs b/parity/io_handler.rs index 2460cfec7..ee6d6130f 100644 --- a/parity/io_handler.rs +++ b/parity/io_handler.rs @@ -18,20 +18,17 @@ use std::sync::Arc; use ethcore::client::Client; use ethcore::service::{NetSyncMessage, SyncMessage}; use ethsync::EthSync; -use util::keys::store::AccountService; +use ethcore::account_provider::AccountProvider; use util::{TimerToken, IoHandler, IoContext, NetworkService, NetworkIoMessage}; use informant::Informant; const INFO_TIMER: TimerToken = 0; -const ACCOUNT_TICK_TIMER: TimerToken = 10; -const ACCOUNT_TICK_MS: u64 = 60000; - pub struct ClientIoHandler { pub client: Arc, pub sync: Arc, - pub accounts: Arc, + pub accounts: Arc, pub info: Informant, pub network: Arc>, } @@ -39,13 +36,11 @@ pub struct ClientIoHandler { impl IoHandler for ClientIoHandler { fn initialize(&self, io: &IoContext) { io.register_timer(INFO_TIMER, 5000).expect("Error registering timer"); - io.register_timer(ACCOUNT_TICK_TIMER, ACCOUNT_TICK_MS).expect("Error registering account timer"); } fn timeout(&self, _io: &IoContext, timer: TimerToken) { match timer { INFO_TIMER => { self.info.tick(&self.client, Some(&self.sync)); } - ACCOUNT_TICK_TIMER => { self.accounts.tick(); }, _ => {} } } diff --git a/parity/main.rs b/parity/main.rs index cfa44f6ee..9680f8a03 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -478,9 +478,15 @@ fn execute_signer(conf: Configuration) { } fn execute_account_cli(conf: Configuration) { - use util::keys::store::SecretStore; + use ethcore::ethstore::{SecretStore, EthStore, import_accounts}; + use ethcore::ethstore::dir::DiskDirectory; + use ethcore::account_provider::AccountProvider; use rpassword::read_password; - let mut secret_store = SecretStore::with_security(Path::new(&conf.keys_path()), conf.keys_iterations()); + + let dir = Box::new(DiskDirectory::create(conf.keys_path()).unwrap()); + let iterations = conf.keys_iterations(); + let secret_store = AccountProvider::new(Box::new(EthStore::open_with_iterations(dir, iterations).unwrap())); + if conf.args.cmd_new { println!("Please note that password is NOT RECOVERABLE."); print!("Type password: "); @@ -498,15 +504,22 @@ fn execute_account_cli(conf: Configuration) { println!("{:?}", new_address); return; } + if conf.args.cmd_list { println!("Known addresses:"); - for &(addr, _) in &secret_store.accounts().unwrap() { + for addr in &secret_store.accounts() { println!("{:?}", addr); } return; } + if conf.args.cmd_import { - let imported = util::keys::import_keys_paths(&mut secret_store, &conf.args.arg_path).unwrap(); + let to = DiskDirectory::create(conf.keys_path()).unwrap(); + let mut imported = 0; + for path in &conf.args.arg_path { + let from = DiskDirectory::at(path); + imported += import_accounts(&from, &to).unwrap_or_else(|e| die!("Could not import accounts {}", e)).len(); + } println!("Imported {} keys", imported); } } diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index feefc89c0..bf21181a1 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -23,7 +23,7 @@ use ethsync::EthSync; use ethcore::miner::{Miner, ExternalMiner}; use ethcore::client::Client; use util::RotatingLogger; -use util::keys::store::AccountService; +use ethcore::account_provider::AccountProvider; use util::network_settings::NetworkSettings; #[cfg(feature="rpc")] @@ -83,7 +83,7 @@ pub struct Dependencies { pub signer_queue: Arc, pub client: Arc, pub sync: Arc, - pub secret_store: Arc, + pub secret_store: Arc, pub miner: Arc, pub external_miner: Arc, pub logger: Arc, diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 2c070cab9..e1f1ba6df 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -26,7 +26,7 @@ use jsonrpc_core::*; use util::numbers::*; use util::sha3::*; use util::rlp::{encode, decode, UntrustedRlp, View}; -use util::keys::store::AccountProvider; +use ethcore::account_provider::AccountProvider; use ethcore::client::{MiningBlockChainClient, BlockID, TransactionID, UncleID}; use ethcore::block::IsBlock; use ethcore::views::*; @@ -41,32 +41,30 @@ use v1::impls::{dispatch_transaction, error_codes}; use serde; /// Eth rpc implementation. -pub struct EthClient where +pub struct EthClient where C: MiningBlockChainClient, S: SyncProvider, - A: AccountProvider, M: MinerService, EM: ExternalMinerService { client: Weak, sync: Weak, - accounts: Weak, + accounts: Weak, miner: Weak, external_miner: Arc, seed_compute: Mutex, allow_pending_receipt_query: bool, } -impl EthClient where +impl EthClient where C: MiningBlockChainClient, S: SyncProvider, - A: AccountProvider, M: MinerService, EM: ExternalMinerService { /// Creates new EthClient. - pub fn new(client: &Arc, sync: &Arc, accounts: &Arc, miner: &Arc, em: &Arc, allow_pending_receipt_query: bool) - -> EthClient { + pub fn new(client: &Arc, sync: &Arc, accounts: &Arc, miner: &Arc, em: &Arc, allow_pending_receipt_query: bool) + -> EthClient { EthClient { client: Arc::downgrade(client), sync: Arc::downgrade(sync), @@ -236,10 +234,9 @@ fn no_work_err() -> Error { } } -impl Eth for EthClient where +impl Eth for EthClient where C: MiningBlockChainClient + 'static, S: SyncProvider + 'static, - A: AccountProvider + 'static, M: MinerService + 'static, EM: ExternalMinerService + 'static { @@ -306,10 +303,7 @@ impl Eth for EthClient where fn accounts(&self, _: Params) -> Result { let store = take_weak!(self.accounts); - match store.accounts() { - Ok(account_list) => to_value(&account_list), - Err(_) => Err(Error::internal_error()) - } + to_value(&store.accounts()) } fn block_number(&self, params: Params) -> Result { diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index 9a045d7a1..ad0bb035a 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -21,12 +21,11 @@ use jsonrpc_core::*; use ethcore::miner::MinerService; use ethcore::client::MiningBlockChainClient; use util::numbers::*; -use util::keys::store::AccountProvider; +use ethcore::account_provider::AccountProvider; use v1::helpers::{SigningQueue, ConfirmationsQueue}; use v1::traits::EthSigning; use v1::types::{TransactionRequest, Bytes}; -use v1::impls::{sign_and_dispatch, error_codes}; - +use v1::impls::sign_and_dispatch; /// Implementation of functions that require signing when no trusted signer is used. pub struct EthSigningQueueClient { @@ -79,22 +78,20 @@ impl EthSigning for EthSigningQueueClient { } /// Implementation of functions that require signing when no trusted signer is used. -pub struct EthSigningUnsafeClient where +pub struct EthSigningUnsafeClient where C: MiningBlockChainClient, - A: AccountProvider, M: MinerService { client: Weak, - accounts: Weak, + accounts: Weak, miner: Weak, } -impl EthSigningUnsafeClient where +impl EthSigningUnsafeClient where C: MiningBlockChainClient, - A: AccountProvider, M: MinerService { /// Creates new EthClient. - pub fn new(client: &Arc, accounts: &Arc, miner: &Arc) + pub fn new(client: &Arc, accounts: &Arc, miner: &Arc) -> Self { EthSigningUnsafeClient { client: Arc::downgrade(client), @@ -104,35 +101,24 @@ impl EthSigningUnsafeClient where } } -impl EthSigning for EthSigningUnsafeClient where +impl EthSigning for EthSigningUnsafeClient where C: MiningBlockChainClient + 'static, - A: AccountProvider + 'static, M: MinerService + 'static { fn sign(&self, params: Params) -> Result { from_params::<(Address, H256)>(params).and_then(|(addr, msg)| { - take_weak!(self.accounts).sign(&addr, &msg) - .map(|v| to_value(&v)) - .unwrap_or_else(|e| Err(account_locked(format!("Error: {:?}", e)))) + to_value(&take_weak!(self.accounts).sign(addr, msg).unwrap_or(H520::zero())) }) } fn send_transaction(&self, params: Params) -> Result { from_params::<(TransactionRequest, )>(params) .and_then(|(request, )| { - let accounts = take_weak!(self.accounts); - match accounts.account_secret(&request.from) { - Ok(secret) => sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, secret), - Err(e) => Err(account_locked(format!("Error: {:?}", e))), + let sender = request.from; + match sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, &*take_weak!(self.accounts), sender) { + Ok(hash) => to_value(&hash), + _ => to_value(&H256::zero()), } }) } } - -fn account_locked(data: String) -> Error { - Error { - code: ErrorCode::ServerError(error_codes::ACCOUNT_LOCKED), - message: "Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.".into(), - data: Some(Value::String(data)), - } -} diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index f69fa25ce..efca09091 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -58,6 +58,7 @@ use ethcore::error::Error as EthcoreError; use ethcore::miner::{AccountDetails, MinerService}; use ethcore::client::MiningBlockChainClient; use ethcore::transaction::{Action, SignedTransaction, Transaction}; +use ethcore::account_provider::{AccountProvider, Error as AccountError}; use util::numbers::*; use util::rlp::encode; use util::bytes::ToPretty; @@ -88,29 +89,58 @@ fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedT .and_then(|_| to_value(&hash)) } -fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, secret: H256) -> Result +fn prepare_transaction(client: &C, miner: &M, request: TransactionRequest) -> Transaction where C: MiningBlockChainClient, M: MinerService { + Transaction { + nonce: request.nonce + .or_else(|| miner + .last_nonce(&request.from) + .map(|nonce| nonce + U256::one())) + .unwrap_or_else(|| client.latest_nonce(&request.from)), + + action: request.to.map_or(Action::Create, Action::Call), + gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()), + gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), + value: request.value.unwrap_or_else(U256::zero), + data: request.data.map_or_else(Vec::new, |b| b.to_vec()), + } +} + +fn unlock_sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, account_provider: &AccountProvider, address: Address, password: String) -> Result where C: MiningBlockChainClient, M: MinerService { let signed_transaction = { - Transaction { - nonce: request.nonce - .or_else(|| miner - .last_nonce(&request.from) - .map(|nonce| nonce + U256::one())) - .unwrap_or_else(|| client.latest_nonce(&request.from)), - - action: request.to.map_or(Action::Create, Action::Call), - gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()), - gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), - value: request.value.unwrap_or_else(U256::zero), - data: request.data.map_or_else(Vec::new, |b| b.to_vec()), - }.sign(&secret) + let t = prepare_transaction(client, miner, request); + let hash = t.hash(); + let signature = try!(account_provider.sign_with_password(address, password, hash).map_err(signing_error)); + t.with_signature(signature) }; trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty()); dispatch_transaction(&*client, &*miner, signed_transaction) } +fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, account_provider: &AccountProvider, address: Address) -> Result + where C: MiningBlockChainClient, M: MinerService { + + let signed_transaction = { + let t = prepare_transaction(client, miner, request); + let hash = t.hash(); + let signature = try!(account_provider.sign(address, hash).map_err(signing_error)); + t.with_signature(signature) + }; + + trace!(target: "miner", "send_transaction: dispatching tx: {}", encode(&signed_transaction).to_vec().pretty()); + dispatch_transaction(&*client, &*miner, signed_transaction) +} + +fn signing_error(error: AccountError) -> Error { + Error { + code: ErrorCode::ServerError(error_codes::ACCOUNT_LOCKED), + message: "Your account is locked. Unlock the account via CLI, personal_unlockAccount or use Trusted Signer.".into(), + data: Some(Value::String(format!("{:?}", error))), + } +} + fn transaction_error(error: EthcoreError) -> Error { use ethcore::error::TransactionError::*; diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index 4f9e307cb..38191ed90 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -19,25 +19,23 @@ use std::sync::{Arc, Weak}; use jsonrpc_core::*; use v1::traits::Personal; use v1::types::TransactionRequest; -use v1::impls::sign_and_dispatch; -use util::keys::store::AccountProvider; +use v1::impls::unlock_sign_and_dispatch; +use ethcore::account_provider::AccountProvider; use util::numbers::*; use ethcore::client::MiningBlockChainClient; use ethcore::miner::MinerService; /// Account management (personal) rpc implementation. -pub struct PersonalClient - where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { - accounts: Weak, +pub struct PersonalClient where C: MiningBlockChainClient, M: MinerService { + accounts: Weak, client: Weak, miner: Weak, signer_port: Option, } -impl PersonalClient - where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { +impl PersonalClient where C: MiningBlockChainClient, M: MinerService { /// Creates new PersonalClient - pub fn new(store: &Arc, client: &Arc, miner: &Arc, signer_port: Option) -> Self { + pub fn new(store: &Arc, client: &Arc, miner: &Arc, signer_port: Option) -> Self { PersonalClient { accounts: Arc::downgrade(store), client: Arc::downgrade(client), @@ -47,8 +45,7 @@ impl PersonalClient } } -impl Personal for PersonalClient - where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { +impl Personal for PersonalClient where C: MiningBlockChainClient, M: MinerService { fn signer_enabled(&self, _: Params) -> Result { self.signer_port @@ -58,10 +55,7 @@ impl Personal for PersonalClient fn accounts(&self, _: Params) -> Result { let store = take_weak!(self.accounts); - match store.accounts() { - Ok(account_list) => to_value(&account_list), - Err(_) => Err(Error::internal_error()) - } + to_value(&store.accounts()) } fn new_account(&self, params: Params) -> Result { @@ -80,7 +74,7 @@ impl Personal for PersonalClient from_params::<(Address, String, u64)>(params).and_then( |(account, account_pass, _)|{ let store = take_weak!(self.accounts); - match store.unlock_account_temp(&account, &account_pass) { + match store.unlock_account_temporarily(account, account_pass) { Ok(_) => Ok(Value::Bool(true)), Err(_) => Ok(Value::Bool(false)), } @@ -90,10 +84,12 @@ impl Personal for PersonalClient fn sign_and_send_transaction(&self, params: Params) -> Result { from_params::<(TransactionRequest, String)>(params) .and_then(|(request, password)| { + let sender = request.from; let accounts = take_weak!(self.accounts); - match accounts.locked_account_secret(&request.from, &password) { - Ok(secret) => sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, secret), - Err(_) => to_value(&H256::zero()), + + match unlock_sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), request, &*accounts, sender, password) { + Ok(hash) => to_value(&hash), + _ => to_value(&H256::zero()), } }) } diff --git a/rpc/src/v1/impls/personal_signer.rs b/rpc/src/v1/impls/personal_signer.rs index 0c1fcb7f1..89f15c787 100644 --- a/rpc/src/v1/impls/personal_signer.rs +++ b/rpc/src/v1/impls/personal_signer.rs @@ -20,27 +20,25 @@ use std::sync::{Arc, Weak}; use jsonrpc_core::*; use v1::traits::PersonalSigner; use v1::types::TransactionModification; -use v1::impls::sign_and_dispatch; +use v1::impls::unlock_sign_and_dispatch; use v1::helpers::{SigningQueue, ConfirmationsQueue}; -use util::keys::store::AccountProvider; +use ethcore::account_provider::AccountProvider; use util::numbers::*; use ethcore::client::MiningBlockChainClient; use ethcore::miner::MinerService; /// Transactions confirmation (personal) rpc implementation. -pub struct SignerClient - where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { +pub struct SignerClient where C: MiningBlockChainClient, M: MinerService { queue: Weak, - accounts: Weak, + accounts: Weak, client: Weak, miner: Weak, } -impl SignerClient - where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { +impl SignerClient where C: MiningBlockChainClient, M: MinerService { /// Create new instance of signer client. - pub fn new(store: &Arc, client: &Arc, miner: &Arc, queue: &Arc) -> Self { + pub fn new(store: &Arc, client: &Arc, miner: &Arc, queue: &Arc) -> Self { SignerClient { queue: Arc::downgrade(queue), accounts: Arc::downgrade(store), @@ -50,8 +48,7 @@ impl SignerClient } } -impl PersonalSigner for SignerClient - where A: AccountProvider, C: MiningBlockChainClient, M: MinerService { +impl PersonalSigner for SignerClient where C: MiningBlockChainClient, M: MinerService { fn transactions_to_confirm(&self, _params: Params) -> Result { let queue = take_weak!(self.queue); @@ -71,13 +68,15 @@ impl PersonalSigner for SignerClient { - let res = sign_and_dispatch(&*client, &*miner, request, secret); - queue.request_confirmed(id, res.clone()); - Some(res) + + let sender = request.from; + + match unlock_sign_and_dispatch(&*client, &*miner, request, &*accounts, sender, pass) { + Ok(hash) => { + queue.request_confirmed(id, Ok(hash.clone())); + Some(to_value(&hash)) }, - Err(_) => None + _ => None } }) .unwrap_or_else(|| { diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 5d7c72ac0..457a9164a 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -15,7 +15,6 @@ // along with Parity. If not, see . //! rpc integration tests. -use std::collections::HashMap; use std::sync::Arc; use std::str::FromStr; @@ -26,12 +25,11 @@ use ethcore::block::Block; use ethcore::views::BlockView; use ethcore::ethereum; use ethcore::miner::{MinerService, ExternalMiner, Miner}; +use ethcore::account_provider::AccountProvider; use devtools::RandomTempPath; use util::Hashable; use util::io::IoChannel; -use util::hash::{Address, H256}; -use util::numbers::U256; -use util::keys::{AccountProvider, TestAccount, TestAccountProvider}; +use util::{U256, H256}; use jsonrpc_core::IoHandler; use ethjson::blockchain::BlockChain; @@ -39,11 +37,8 @@ use v1::traits::eth::{Eth, EthSigning}; use v1::impls::{EthClient, EthSigningUnsafeClient}; use v1::tests::helpers::{TestSyncProvider, Config}; -fn account_provider() -> Arc { - let mut accounts = HashMap::new(); - accounts.insert(Address::from(1), TestAccount::new("test")); - let ap = TestAccountProvider::new(accounts); - Arc::new(ap) +fn account_provider() -> Arc { + Arc::new(AccountProvider::transient_provider()) } fn sync_provider() -> Arc { @@ -70,7 +65,7 @@ fn make_spec(chain: &BlockChain) -> Spec { struct EthTester { client: Arc, _miner: Arc, - accounts: Arc, + accounts: Arc, handler: IoHandler, } @@ -226,15 +221,10 @@ const TRANSACTION_COUNT_SPEC: &'static [u8] = br#"{ fn eth_transaction_count() { use util::crypto::Secret; - let address = Address::from_str("faa34835af5c2ea724333018a515fbb7d5bc0b33").unwrap(); let secret = Secret::from_str("8a283037bb19c4fed7b1c569e40c7dcff366165eb869110a1b11532963eb9cb2").unwrap(); - let tester = EthTester::from_spec_provider(|| Spec::load(TRANSACTION_COUNT_SPEC)); - tester.accounts.accounts.write().unwrap().insert(address, TestAccount { - unlocked: false, - password: "123".into(), - secret: secret - }); + let address = tester.accounts.insert_account(secret, "").unwrap(); + tester.accounts.unlock_account_permanently(address, "".into()).unwrap(); let req_before = r#"{ "jsonrpc": "2.0", diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 2fcd8a266..29c10a92b 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -20,7 +20,7 @@ use std::sync::{Arc, RwLock}; use jsonrpc_core::IoHandler; use util::hash::{Address, H256, FixedHash}; use util::numbers::{Uint, U256}; -use util::keys::{AccountProvider, TestAccount, TestAccountProvider}; +use ethcore::account_provider::AccountProvider; use ethcore::client::{TestBlockChainClient, EachBlockWith, Executed, TransactionID}; use ethcore::log_entry::{LocalizedLogEntry, LogEntry}; use ethcore::receipt::LocalizedReceipt; @@ -36,11 +36,8 @@ fn blockchain_client() -> Arc { Arc::new(client) } -fn accounts_provider() -> Arc { - let mut accounts = HashMap::new(); - accounts.insert(Address::from(1), TestAccount::new("test")); - let ap = TestAccountProvider::new(accounts); - Arc::new(ap) +fn accounts_provider() -> Arc { + Arc::new(AccountProvider::transient_provider()) } fn sync_provider() -> Arc { @@ -57,7 +54,7 @@ fn miner_service() -> Arc { struct EthTester { pub client: Arc, pub sync: Arc, - pub accounts_provider: Arc, + pub accounts_provider: Arc, miner: Arc, hashrates: Arc>>, pub io: IoHandler, @@ -169,8 +166,9 @@ fn rpc_eth_sign() { let tester = EthTester::default(); let account = tester.accounts_provider.new_account("abcd").unwrap(); + tester.accounts_provider.unlock_account_permanently(account, "abcd".into()).unwrap(); let message = H256::from("0x0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f"); - let signed = tester.accounts_provider.sign(&account, &message).unwrap(); + let signed = tester.accounts_provider.sign(account, message).unwrap(); let req = r#"{ "jsonrpc": "2.0", @@ -233,10 +231,13 @@ fn rpc_eth_gas_price() { #[test] fn rpc_eth_accounts() { - let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":["0x0000000000000000000000000000000000000001"],"id":1}"#; + let tester = EthTester::default(); + let address = tester.accounts_provider.new_account("").unwrap(); - assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned())); + let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() + &format!("0x{:?}", address) + r#""],"id":1}"#; + + assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); } #[test] @@ -558,12 +559,9 @@ fn rpc_eth_estimate_gas_default_block() { #[test] fn rpc_eth_send_transaction() { - let account = TestAccount::new("123"); - let address = account.address(); - let secret = account.secret.clone(); - let tester = EthTester::default(); - tester.accounts_provider.accounts.write().unwrap().insert(address.clone(), account); + let address = tester.accounts_provider.new_account("").unwrap(); + tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap(); let request = r#"{ "jsonrpc": "2.0", "method": "eth_sendTransaction", @@ -584,7 +582,9 @@ fn rpc_eth_send_transaction() { action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), value: U256::from(0x9184e72au64), data: vec![] - }.sign(&secret); + }; + let signature = tester.accounts_provider.sign(address, t.hash()).unwrap(); + let t = t.with_signature(signature); let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; @@ -599,7 +599,9 @@ fn rpc_eth_send_transaction() { action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), value: U256::from(0x9184e72au64), data: vec![] - }.sign(&secret); + }; + let signature = tester.accounts_provider.sign(address, t.hash()).unwrap(); + let t = t.with_signature(signature); let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; @@ -610,7 +612,7 @@ fn rpc_eth_send_transaction() { fn rpc_eth_send_raw_transaction() { let tester = EthTester::default(); let address = tester.accounts_provider.new_account("abcd").unwrap(); - let secret = tester.accounts_provider.account_secret(&address).unwrap(); + tester.accounts_provider.unlock_account_permanently(address, "abcd".into()).unwrap(); let t = Transaction { nonce: U256::zero(), @@ -619,7 +621,9 @@ fn rpc_eth_send_raw_transaction() { action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), value: U256::from(0x9184e72au64), data: vec![] - }.sign(&secret); + }; + let signature = tester.accounts_provider.sign(address, t.hash()).unwrap(); + let t = t.with_signature(signature); let rlp = ::util::rlp::encode(&t).to_vec().to_hex(); diff --git a/rpc/src/v1/tests/mocked/eth_signing.rs b/rpc/src/v1/tests/mocked/eth_signing.rs index a70a4cdaf..afa6886fe 100644 --- a/rpc/src/v1/tests/mocked/eth_signing.rs +++ b/rpc/src/v1/tests/mocked/eth_signing.rs @@ -20,7 +20,7 @@ use v1::impls::EthSigningQueueClient; use v1::traits::EthSigning; use v1::helpers::{ConfirmationsQueue, SigningQueue}; use v1::tests::helpers::TestMinerService; -use util::keys::TestAccount; +use util::{Address, FixedHash}; struct EthSigningTester { pub queue: Arc, @@ -52,8 +52,7 @@ fn eth_signing() -> EthSigningTester { fn should_add_transaction_to_queue() { // given let tester = eth_signing(); - let account = TestAccount::new("123"); - let address = account.address(); + let address = Address::random(); assert_eq!(tester.queue.requests().len(), 0); // when diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index 02b07abd3..cca58c1d7 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -16,17 +16,16 @@ use std::sync::Arc; use std::str::FromStr; -use std::collections::HashMap; use jsonrpc_core::IoHandler; use util::numbers::*; -use util::keys::{TestAccount, TestAccountProvider}; +use ethcore::account_provider::AccountProvider; use v1::{PersonalClient, Personal}; use v1::tests::helpers::TestMinerService; use ethcore::client::TestBlockChainClient; use ethcore::transaction::{Action, Transaction}; struct PersonalTester { - accounts: Arc, + accounts: Arc, io: IoHandler, miner: Arc, // these unused fields are necessary to keep the data alive @@ -39,10 +38,8 @@ fn blockchain_client() -> Arc { Arc::new(client) } -fn accounts_provider() -> Arc { - let accounts = HashMap::new(); - let ap = TestAccountProvider::new(accounts); - Arc::new(ap) +fn accounts_provider() -> Arc { + Arc::new(AccountProvider::transient_provider()) } fn miner_service() -> Arc { @@ -99,13 +96,9 @@ fn should_return_port_number_if_signer_is_enabled() { #[test] fn accounts() { let tester = setup(None); - tester.accounts.accounts - .write() - .unwrap() - .insert(Address::from(1), TestAccount::new("test")); - + let address = tester.accounts.new_account("").unwrap(); let request = r#"{"jsonrpc": "2.0", "method": "personal_listAccounts", "params": [], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":["0x0000000000000000000000000000000000000001"],"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() + &format!("0x{:?}", address) + r#""],"id":1}"#; assert_eq!(tester.io.handle_request(request), Some(response.to_owned())); } @@ -117,15 +110,9 @@ fn new_account() { let res = tester.io.handle_request(request); - let accounts = tester.accounts.accounts.read().unwrap(); + let accounts = tester.accounts.accounts(); assert_eq!(accounts.len(), 1); - - let address = accounts - .keys() - .nth(0) - .cloned() - .unwrap(); - + let address = accounts[0]; let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"","id":1}"#; assert_eq!(res, Some(response)); @@ -133,11 +120,8 @@ fn new_account() { #[test] fn sign_and_send_transaction_with_invalid_password() { - let account = TestAccount::new("password123"); - let address = account.address(); - let tester = setup(None); - tester.accounts.accounts.write().unwrap().insert(address.clone(), account); + let address = tester.accounts.new_account("password123").unwrap(); let request = r#"{ "jsonrpc": "2.0", "method": "personal_signAndSendTransaction", @@ -158,12 +142,9 @@ fn sign_and_send_transaction_with_invalid_password() { #[test] fn sign_and_send_transaction() { - let account = TestAccount::new("password123"); - let address = account.address(); - let secret = account.secret.clone(); - let tester = setup(None); - tester.accounts.accounts.write().unwrap().insert(address.clone(), account); + let address = tester.accounts.new_account("password123").unwrap(); + let request = r#"{ "jsonrpc": "2.0", "method": "personal_signAndSendTransaction", @@ -184,7 +165,10 @@ fn sign_and_send_transaction() { action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), value: U256::from(0x9184e72au64), data: vec![] - }.sign(&secret); + }; + tester.accounts.unlock_account_temporarily(address, "password123".into()).unwrap(); + let signature = tester.accounts.sign(address, t.hash()).unwrap(); + let t = t.with_signature(signature); let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; @@ -199,7 +183,10 @@ fn sign_and_send_transaction() { action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), value: U256::from(0x9184e72au64), data: vec![] - }.sign(&secret); + }; + tester.accounts.unlock_account_temporarily(address, "password123".into()).unwrap(); + let signature = tester.accounts.sign(address, t.hash()).unwrap(); + let t = t.with_signature(signature); let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; diff --git a/rpc/src/v1/tests/mocked/personal_signer.rs b/rpc/src/v1/tests/mocked/personal_signer.rs index cf7661331..6fa734cec 100644 --- a/rpc/src/v1/tests/mocked/personal_signer.rs +++ b/rpc/src/v1/tests/mocked/personal_signer.rs @@ -16,10 +16,9 @@ use std::sync::Arc; use std::str::FromStr; -use std::collections::HashMap; use jsonrpc_core::IoHandler; use util::numbers::*; -use util::keys::{TestAccount, TestAccountProvider}; +use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; use ethcore::transaction::{Transaction, Action}; use v1::{SignerClient, PersonalSigner}; @@ -30,7 +29,7 @@ use v1::types::TransactionRequest; struct PersonalSignerTester { queue: Arc, - accounts: Arc, + accounts: Arc, io: IoHandler, miner: Arc, // these unused fields are necessary to keep the data alive @@ -43,10 +42,8 @@ fn blockchain_client() -> Arc { Arc::new(client) } -fn accounts_provider() -> Arc { - let accounts = HashMap::new(); - let ap = TestAccountProvider::new(accounts); - Arc::new(ap) +fn accounts_provider() -> Arc { + Arc::new(AccountProvider::transient_provider()) } fn miner_service() -> Arc { @@ -146,16 +143,10 @@ fn should_not_remove_transaction_if_password_is_invalid() { #[test] fn should_confirm_transaction_and_dispatch() { - // given + //// given let tester = signer_tester(); - let account = TestAccount::new("test"); - let address = account.address(); - let secret = account.secret.clone(); + let address = tester.accounts.new_account("test").unwrap(); let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(); - tester.accounts.accounts - .write() - .unwrap() - .insert(address, account); tester.queue.add_request(TransactionRequest { from: address, to: Some(recipient), @@ -165,6 +156,7 @@ fn should_confirm_transaction_and_dispatch() { data: None, nonce: None, }); + let t = Transaction { nonce: U256::zero(), gas_price: U256::from(0x1000), @@ -172,7 +164,10 @@ fn should_confirm_transaction_and_dispatch() { action: Action::Call(recipient), value: U256::from(0x1), data: vec![] - }.sign(&secret); + }; + tester.accounts.unlock_account_temporarily(address, "test".into()).unwrap(); + let signature = tester.accounts.sign(address, t.hash()).unwrap(); + let t = t.with_signature(signature); assert_eq!(tester.queue.requests().len(), 1); diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 8f7367501..cb781ea22 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -458,12 +458,13 @@ impl ChainSync { // Disable the peer for this syncing round if it gives invalid chain if !valid_response { trace!(target: "sync", "{} Deactivated for invalid headers response", peer_id); - self.deactivate_peer(io, peer_id); + self.deactivate_peer(io, peer_id); } + if headers.is_empty() { // Peer does not have any new subchain heads, deactivate it nd try with another trace!(target: "sync", "{} Deactivated for no data", peer_id); - self.deactivate_peer(io, peer_id); + self.deactivate_peer(io, peer_id); } match self.state { SyncState::ChainHead => { diff --git a/util/Cargo.toml b/util/Cargo.toml index 05e05d4c1..8b213ad47 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -18,7 +18,7 @@ rand = "0.3.12" time = "0.1.34" tiny-keccak = "1.0" rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" } -lazy_static = "0.1" +lazy_static = "0.2" eth-secp256k1 = { git = "https://github.com/ethcore/rust-secp256k1" } rust-crypto = "0.2.34" elastic-array = "0.4" diff --git a/util/src/keys/directory.rs b/util/src/keys/directory.rs deleted file mode 100644 index 385a400c7..000000000 --- a/util/src/keys/directory.rs +++ /dev/null @@ -1,1247 +0,0 @@ -// Copyright 2015, 2016 Ethcore (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 . - -//! Keys Directory - -use common::*; -use std::path::{PathBuf}; -use path::restrict_permissions_owner; - -const CURRENT_DECLARED_VERSION: u64 = 3; -const MAX_KEY_FILE_LEN: u64 = 1024 * 80; -const MAX_CACHE_USAGE_TRACK: usize = 128; - -/// Cipher type (currently only aes-128-ctr) -#[derive(PartialEq, Debug, Clone)] -pub enum CryptoCipherType { - /// aes-128-ctr with 128-bit initialisation vector(iv) - Aes128Ctr(H128) -} - -#[derive(PartialEq, Debug, Clone)] -enum KeyFileVersion { - V3(u64) -} - -/// key generator function -#[derive(PartialEq, Debug, Clone)] -pub enum Pbkdf2CryptoFunction { - /// keyed-hash generator (HMAC-256) - HMacSha256 -} - -#[derive(Clone)] -/// Kdf of type `Pbkdf2` -/// https://en.wikipedia.org/wiki/PBKDF2 -pub struct KdfPbkdf2Params { - /// desired length of the derived key, in octets - pub dk_len: u32, - /// cryptographic salt - pub salt: H256, - /// number of iterations for derived key - pub c: u32, - /// pseudo-random 2-parameters function - pub prf: Pbkdf2CryptoFunction -} - -#[derive(Debug)] -enum Pbkdf2ParseError { - InvalidParameter(&'static str), - InvalidPrf(Mismatch), - InvalidSaltFormat(UtilError), - MissingParameter(&'static str), -} - -impl KdfPbkdf2Params { - fn from_json(json: &BTreeMap) -> Result { - Ok(KdfPbkdf2Params{ - salt: match try!(json.get("salt").ok_or(Pbkdf2ParseError::MissingParameter("salt"))).as_string() { - None => { return Err(Pbkdf2ParseError::InvalidParameter("salt")) }, - Some(salt_value) => match H256::from_str(salt_value) { - Ok(salt_hex_value) => salt_hex_value, - Err(from_hex_error) => { return Err(Pbkdf2ParseError::InvalidSaltFormat(from_hex_error)); }, - } - }, - prf: match try!(json.get("prf").ok_or(Pbkdf2ParseError::MissingParameter("prf"))).as_string() { - Some("hmac-sha256") => Pbkdf2CryptoFunction::HMacSha256, - Some(unexpected_prf) => { return Err(Pbkdf2ParseError::InvalidPrf(Mismatch { expected: "hmac-sha256".to_owned(), found: unexpected_prf.to_owned() })); }, - None => { return Err(Pbkdf2ParseError::InvalidParameter("prf")); }, - }, - dk_len: try!(try!(json.get("dklen").ok_or(Pbkdf2ParseError::MissingParameter("dklen"))).as_u64().ok_or(Pbkdf2ParseError::InvalidParameter("dkLen"))) as u32, - c: try!(try!(json.get("c").ok_or(Pbkdf2ParseError::MissingParameter("c"))).as_u64().ok_or(Pbkdf2ParseError::InvalidParameter("c"))) as u32, - }) - } - - fn to_json(&self) -> Json { - let mut map = BTreeMap::new(); - map.insert("dklen".to_owned(), json_from_u32(self.dk_len)); - map.insert("salt".to_owned(), Json::String(format!("{:?}", self.salt))); - map.insert("prf".to_owned(), Json::String("hmac-sha256".to_owned())); - map.insert("c".to_owned(), json_from_u32(self.c)); - Json::Object(map) - } -} - -#[derive(Clone)] -/// Kdf of type `Scrypt`. -/// https://en.wikipedia.org/wiki/Scrypt -pub struct KdfScryptParams { - /// Desired length of the derived key, in octets. - pub dk_len: u32, - /// Parallelization parameter. - pub p: u32, - /// CPU/memory cost parameter. - pub n: u32, - /// TODO: comment - pub r: u32, - /// Cryptographic salt. - pub salt: H256, -} - -#[derive(Debug)] -enum ScryptParseError { - InvalidParameter(&'static str), - InvalidSaltFormat(UtilError), - MissingParameter(&'static str), -} - -fn json_from_u32(number: u32) -> Json { Json::U64(number as u64) } - -impl KdfScryptParams { - fn from_json(json: &BTreeMap) -> Result { - Ok(KdfScryptParams{ - salt: match try!(json.get("salt").ok_or(ScryptParseError::MissingParameter("salt"))).as_string() { - None => { return Err(ScryptParseError::InvalidParameter("salt")) }, - Some(salt_value) => match H256::from_str(salt_value) { - Ok(salt_hex_value) => salt_hex_value, - Err(from_hex_error) => { return Err(ScryptParseError::InvalidSaltFormat(from_hex_error)); }, - } - }, - dk_len: try!(try!(json.get("dklen").ok_or(ScryptParseError::MissingParameter("dklen"))).as_u64().ok_or(ScryptParseError::InvalidParameter("dkLen"))) as u32, - p: try!(try!(json.get("p").ok_or(ScryptParseError::MissingParameter("p"))).as_u64().ok_or(ScryptParseError::InvalidParameter("p"))) as u32, - n: try!(try!(json.get("n").ok_or(ScryptParseError::MissingParameter("n"))).as_u64().ok_or(ScryptParseError::InvalidParameter("n"))) as u32, - r: try!(try!(json.get("r").ok_or(ScryptParseError::MissingParameter("r"))).as_u64().ok_or(ScryptParseError::InvalidParameter("r"))) as u32, - }) - } - - fn to_json(&self) -> Json { - let mut map = BTreeMap::new(); - map.insert("dklen".to_owned(), json_from_u32(self.dk_len)); - map.insert("salt".to_owned(), Json::String(format!("{:?}", self.salt))); - map.insert("p".to_owned(), json_from_u32(self.p)); - map.insert("n".to_owned(), json_from_u32(self.n)); - map.insert("r".to_owned(), json_from_u32(self.r)); - Json::Object(map) - } -} - -#[derive(Clone)] -/// Settings for password derived key geberator function. -pub enum KeyFileKdf { - /// Password-Based Key Derivation Function 2 (PBKDF2) type. - /// https://en.wikipedia.org/wiki/PBKDF2 - Pbkdf2(KdfPbkdf2Params), - /// Scrypt password-based key derivation function. - /// https://en.wikipedia.org/wiki/Scrypt - Scrypt(KdfScryptParams) -} - -#[derive(Clone)] -/// Encrypted password or other arbitrary message -/// with settings for password derived key generator for decrypting content. -pub struct KeyFileCrypto { - /// Cipher type. - pub cipher_type: CryptoCipherType, - /// Cipher text (encrypted message). - pub cipher_text: Bytes, - /// Password derived key generator function settings. - pub kdf: KeyFileKdf, - /// Mac - pub mac: H256 -} - -impl KeyFileCrypto { - fn from_json(json: &Json) -> Result { - let as_object = match json.as_object() { - None => { return Err(CryptoParseError::InvalidJsonFormat); } - Some(obj) => obj - }; - - let cipher_type = match try!(as_object.get("cipher").ok_or(CryptoParseError::NoCipherType)).as_string() { - None => { return Err(CryptoParseError::InvalidCipherType(Mismatch { expected: "aes-128-ctr".to_owned(), found: "not a json string".to_owned() })); } - Some("aes-128-ctr") => CryptoCipherType::Aes128Ctr( - match try!(as_object.get("cipherparams").ok_or(CryptoParseError::NoCipherParameters)).as_object() { - None => { return Err(CryptoParseError::NoCipherParameters); }, - Some(cipher_param) => match H128::from_str(match cipher_param["iv"].as_string() { - None => { return Err(CryptoParseError::NoInitialVector); }, - Some(iv_hex_string) => iv_hex_string - }) - { - Ok(iv_value) => iv_value, - Err(hex_error) => { return Err(CryptoParseError::InvalidInitialVector(hex_error)); } - } - } - ), - Some(other_cipher_type) => { - return Err(CryptoParseError::InvalidCipherType( - Mismatch { expected: "aes-128-ctr".to_owned(), found: other_cipher_type.to_owned() })); - } - }; - - let kdf = match (try!(as_object.get("kdf").ok_or(CryptoParseError::NoKdf)).as_string(), try!(as_object.get("kdfparams").ok_or(CryptoParseError::NoKdfType)).as_object()) { - (None, _) => { return Err(CryptoParseError::NoKdfType); }, - (Some("scrypt"), Some(kdf_params)) => - match KdfScryptParams::from_json(kdf_params) { - Err(scrypt_params_error) => { return Err(CryptoParseError::Scrypt(scrypt_params_error)); }, - Ok(scrypt_params) => KeyFileKdf::Scrypt(scrypt_params) - }, - (Some("pbkdf2"), Some(kdf_params)) => - match KdfPbkdf2Params::from_json(kdf_params) { - Err(pbkdf2_params_error) => { return Err(CryptoParseError::KdfPbkdf2(pbkdf2_params_error)); }, - Ok(pbkdf2_params) => KeyFileKdf::Pbkdf2(pbkdf2_params) - }, - (Some(other_kdf), _) => { - return Err(CryptoParseError::InvalidKdfType( - Mismatch { expected: "pbkdf2/scrypt".to_owned(), found: other_kdf.to_owned()})); - } - }; - - let cipher_text = match try!(as_object.get("ciphertext").ok_or(CryptoParseError::NoCipherText)).as_string() { - None => { return Err(CryptoParseError::InvalidCipherText); } - Some(text) => text - }; - - let mac: H256 = match try!(as_object.get("mac").ok_or(CryptoParseError::NoMac)).as_string() { - None => { return Err(CryptoParseError::InvalidMacFormat(None)) }, - Some(salt_value) => match H256::from_str(salt_value) { - Ok(salt_hex_value) => salt_hex_value, - Err(from_hex_error) => { return Err(CryptoParseError::InvalidMacFormat(Some(from_hex_error))); }, - } - }; - - Ok(KeyFileCrypto { - cipher_text: match FromHex::from_hex(cipher_text) { Ok(bytes) => bytes, Err(_) => { return Err(CryptoParseError::InvalidCipherText); } }, - cipher_type: cipher_type, - kdf: kdf, - mac: mac, - }) - } - - fn to_json(&self) -> Json { - let mut map = BTreeMap::new(); - match self.cipher_type { - CryptoCipherType::Aes128Ctr(ref iv) => { - map.insert("cipher".to_owned(), Json::String("aes-128-ctr".to_owned())); - let mut cipher_params = BTreeMap::new(); - cipher_params.insert("iv".to_owned(), Json::String(format!("{:?}", iv))); - map.insert("cipherparams".to_owned(), Json::Object(cipher_params)); - } - } - map.insert("ciphertext".to_owned(), Json::String( - self.cipher_text.iter().map(|b| format!("{:02x}", b)).collect::>().join(""))); - - map.insert("kdf".to_owned(), Json::String(match self.kdf { - KeyFileKdf::Pbkdf2(_) => "pbkdf2".to_owned(), - KeyFileKdf::Scrypt(_) => "scrypt".to_owned() - })); - - map.insert("kdfparams".to_owned(), match self.kdf { - KeyFileKdf::Pbkdf2(ref pbkdf2_params) => pbkdf2_params.to_json(), - KeyFileKdf::Scrypt(ref scrypt_params) => scrypt_params.to_json() - }); - - map.insert("mac".to_owned(), Json::String(format!("{:?}", self.mac))); - - Json::Object(map) - } - - /// New pbkdf2-type secret. - /// `cipher-text` - encrypted cipher text. - /// `dk-len` - desired length of the derived key, in octets. - /// `c` - number of iterations for derived key. - /// `salt` - cryptographic site, random 256-bit hash (ensure it's crypto-random). - /// `iv` - initialisation vector. - pub fn new_pbkdf2(cipher_text: Bytes, iv: H128, salt: H256, mac: H256, c: u32, dk_len: u32) -> KeyFileCrypto { - KeyFileCrypto { - cipher_type: CryptoCipherType::Aes128Ctr(iv), - cipher_text: cipher_text, - kdf: KeyFileKdf::Pbkdf2(KdfPbkdf2Params { - dk_len: dk_len, - salt: salt, - c: c, - prf: Pbkdf2CryptoFunction::HMacSha256 - }), - mac: mac, - } - } -} - -/// Universally unique identifier -pub type Uuid = H128; - -fn new_uuid() -> Uuid { - H128::random() -} - -fn uuid_to_string(uuid: &Uuid) -> String { - let d1 = &uuid.as_slice()[0..4]; - let d2 = &uuid.as_slice()[4..6]; - let d3 = &uuid.as_slice()[6..8]; - let d4 = &uuid.as_slice()[8..10]; - let d5 = &uuid.as_slice()[10..16]; - format!("{}-{}-{}-{}-{}", d1.to_hex(), d2.to_hex(), d3.to_hex(), d4.to_hex(), d5.to_hex()) -} - -fn uuid_from_string(s: &str) -> Result { - let parts: Vec<&str> = s.split('-').collect(); - if parts.len() != 5 { return Err(UtilError::BadSize); } - - let mut uuid = H128::zero(); - - if parts[0].len() != 8 { return Err(UtilError::BadSize); } - uuid[0..4].clone_from_slice(&try!(FromHex::from_hex(parts[0]))); - if parts[1].len() != 4 { return Err(UtilError::BadSize); } - uuid[4..6].clone_from_slice(&try!(FromHex::from_hex(parts[1]))); - if parts[2].len() != 4 { return Err(UtilError::BadSize); } - uuid[6..8].clone_from_slice(&try!(FromHex::from_hex(parts[2]))); - if parts[3].len() != 4 { return Err(UtilError::BadSize); } - uuid[8..10].clone_from_slice(&try!(FromHex::from_hex(parts[3]))); - if parts[4].len() != 12 { return Err(UtilError::BadSize); } - uuid[10..16].clone_from_slice(&try!(FromHex::from_hex(parts[4]))); - - Ok(uuid) -} - - -#[derive(Clone)] -/// Stored key file struct with encrypted message `(cipher_text)` -/// also contains password derivation function settings (PBKDF2/Scrypt) -pub struct KeyFileContent { - version: KeyFileVersion, - /// Holds cypher and decrypt function settings. - pub crypto: KeyFileCrypto, - /// The identifier. - pub id: Uuid, - /// Account (if present) - pub account: Option
, -} - -#[derive(Debug)] -enum CryptoParseError { - InvalidMacFormat(Option), - NoMac, - NoCipherText, - InvalidCipherText, - NoCipherType, - InvalidJsonFormat, - InvalidKdfType(Mismatch), - InvalidCipherType(Mismatch), - NoInitialVector, - NoCipherParameters, - InvalidInitialVector(UtilError), - NoKdf, - NoKdfType, - Scrypt(ScryptParseError), - KdfPbkdf2(Pbkdf2ParseError) -} - -#[derive(Debug)] -enum KeyFileParseError { - InvalidVersion, - UnsupportedVersion(OutOfBounds), - InvalidJsonFormat, - InvalidJson, - InvalidIdentifier, - NoCryptoSection, - Crypto(CryptoParseError), -} - -impl KeyFileContent { - /// New stored key file struct with encrypted message (`cipher_text`) - /// also contains password derivation function settings (PBKDF2/Scrypt) - /// to decrypt `cipher_text` given the password is provided. - pub fn new(crypto: KeyFileCrypto) -> KeyFileContent { - KeyFileContent { - id: new_uuid(), - version: KeyFileVersion::V3(3), - crypto: crypto, - account: None - } - } - - /// Loads key from valid json, returns error and records warning if key is malformed - pub fn load(json: &Json) -> Result { - match Self::from_json(json) { - Ok(key_file) => Ok(key_file), - Err(e) => { - warn!(target: "sstore", "Error parsing json for key: {:?}", e); - Err(()) - } - } - } - - /// Returns key file version if it is known. - pub fn version(&self) -> Option { - match self.version { - KeyFileVersion::V3(declared) => Some(declared) - } - } - - fn from_json(json: &Json) -> Result { - let as_object = match json.as_object() { - None => { return Err(KeyFileParseError::InvalidJsonFormat); }, - Some(obj) => obj - }; - - let version = match as_object["version"].as_u64() { - None => { return Err(KeyFileParseError::InvalidVersion); }, - Some(json_version) => { - if json_version <= 2 { - return Err(KeyFileParseError::UnsupportedVersion(OutOfBounds { min: Some(3), max: None, found: json_version })) - }; - KeyFileVersion::V3(json_version) - } - }; - - let id_text = try!(as_object.get("id").and_then(|json| json.as_string()).ok_or(KeyFileParseError::InvalidIdentifier)); - let id = match uuid_from_string(&id_text) { - Err(_) => { return Err(KeyFileParseError::InvalidIdentifier); }, - Ok(id) => id - }; - - let account = as_object.get("address").and_then(|json| json.as_string()).and_then( - |account_text| match Address::from_str(account_text) { Ok(account) => Some(account), Err(_) => None }); - - let crypto = match as_object.get("crypto") { - None => { return Err(KeyFileParseError::NoCryptoSection); } - Some(crypto_json) => match KeyFileCrypto::from_json(crypto_json) { - Ok(crypto) => crypto, - Err(crypto_error) => { return Err(KeyFileParseError::Crypto(crypto_error)); } - } - }; - - Ok(KeyFileContent { - version: version, - id: id.clone(), - crypto: crypto, - account: account - }) - } - - fn to_json(&self) -> Json { - let mut map = BTreeMap::new(); - map.insert("id".to_owned(), Json::String(uuid_to_string(&self.id))); - map.insert("version".to_owned(), Json::U64(CURRENT_DECLARED_VERSION)); - map.insert("crypto".to_owned(), self.crypto.to_json()); - if let Some(ref address) = self.account { map.insert("address".to_owned(), Json::String(format!("{:?}", address))); } - Json::Object(map) - } -} - -#[derive(Debug)] -enum KeyFileLoadError { - TooLarge(OutOfBounds), - ParseError(KeyFileParseError), - ReadError(::std::io::Error), -} - -/// Represents directory for saving/loading key files. -pub struct KeyDirectory { - /// Directory path for key management. - path: String, - cache: RwLock>, - cache_usage: RwLock>, -} - -impl KeyDirectory { - /// Initializes new cache directory context with a given `path` - pub fn new(path: &Path) -> KeyDirectory { - KeyDirectory { - cache: RwLock::new(HashMap::new()), - path: path.to_str().expect("Initialized key directory with empty path").to_owned(), - cache_usage: RwLock::new(VecDeque::new()), - } - } - - /// saves (inserts or updates) given key - pub fn save(&mut self, key_file: KeyFileContent) -> Result<(Uuid), ::std::io::Error> { - { - let mut file = try!(fs::File::create(self.key_path(&key_file.id))); - let json = key_file.to_json(); - let json_text = format!("{}", json.pretty()); - let json_bytes = json_text.into_bytes(); - try!(file.write(&json_bytes)); - } - if let Err(error_code) = restrict_permissions_owner(self.key_path(&key_file.id).as_path()) { - fs::remove_file(self.key_path(&key_file.id)).unwrap(); - warn!(target: "sstore", "fatal: failed to modify permissions of the file (chmod: {})", error_code); - return Err(::std::io::Error::last_os_error()); - } - let mut cache = self.cache.write().unwrap(); - let id = key_file.id.clone(); - cache.insert(id.clone(), key_file); - Ok(id.clone()) - } - - /// Returns key given by id if corresponding file exists and no load error occured. - /// Warns if any error occured during the key loading - pub fn get(&self, id: &Uuid) -> Option { - let path = self.key_path(id); - { - let mut usage = self.cache_usage.write().unwrap(); - usage.push_back(id.clone()); - } - - if !self.cache.read().unwrap().contains_key(id) { - match KeyDirectory::load_key(&path) { - Ok(loaded_key) => { - self.cache.write().unwrap().insert(id.to_owned(), loaded_key); - } - Err(error) => { - warn!(target: "sstore", "error loading key {:?}: {:?}", id, error); - return None; - } - } - } - - // todo: replace with Ref::map when it stabilized to avoid copies - Some(self.cache.read().unwrap().get(id) - .expect("Key should be there, we have just inserted or checked it.") - .clone()) - } - - /// Returns current path to the directory with keys - pub fn path(&self) -> &str { - &self.path - } - - /// Removes keys that never been requested during last `MAX_USAGE_TRACK` times - pub fn collect_garbage(&mut self) { - let mut cache_usage = self.cache_usage.write().unwrap(); - - let total_usages = cache_usage.len(); - let untracked_usages = max(total_usages as i64 - MAX_CACHE_USAGE_TRACK as i64, 0) as usize; - if untracked_usages > 0 { - cache_usage.drain(..untracked_usages); - } - - if self.cache.read().unwrap().len() <= MAX_CACHE_USAGE_TRACK { return; } - - let uniqs: HashSet<&Uuid> = cache_usage.iter().collect(); - let removes:Vec = { - let cache = self.cache.read().unwrap(); - cache.keys().cloned().filter(|key| !uniqs.contains(key)).collect() - }; - if removes.is_empty() { return; } - let mut cache = self.cache.write().unwrap(); - for key in removes { cache.remove(&key); } - - cache.shrink_to_fit(); - } - - /// Reports how many keys are currently cached. - pub fn cache_size(&self) -> usize { - self.cache.read().unwrap().len() - } - - /// Removes key file from key directory - pub fn delete(&mut self, id: &Uuid) -> Result<(), ::std::io::Error> { - let path = self.key_path(id); - - if !self.cache.read().unwrap().contains_key(id) { - return match fs::remove_file(&path) { - Ok(_) => { - self.cache.write().unwrap().remove(&id); - Ok(()) - }, - Err(e) => Err(e) - }; - } - Ok(()) - } - - /// Enumerates all keys in the directory - pub fn list(&self) -> Result, ::std::io::Error> { - let mut result = Vec::new(); - for entry in try!(fs::read_dir(&self.path)) { - let entry = try!(entry); - if !try!(fs::metadata(entry.path())).is_dir() { - match entry.file_name().to_str() { - Some(ref name) => { - if let Ok(uuid) = uuid_from_string(name) { result.push(uuid); } - }, - None => { continue; } - }; - - } - } - Ok(result) - } - - fn key_path(&self, id: &Uuid) -> PathBuf { - let mut path = PathBuf::new(); - path.push(self.path.clone()); - path.push(uuid_to_string(&id)); - path - } - - fn load_key(path: &PathBuf) -> Result { - match fs::File::open(path.clone()) { - Ok(mut open_file) => { - match open_file.metadata() { - Ok(metadata) => - if metadata.len() > MAX_KEY_FILE_LEN { Err(KeyFileLoadError::TooLarge(OutOfBounds { min: Some(2), max: Some(MAX_KEY_FILE_LEN), found: metadata.len() })) } - else { KeyDirectory::load_from_file(&mut open_file) }, - Err(read_error) => Err(KeyFileLoadError::ReadError(read_error)) - } - }, - Err(read_error) => Err(KeyFileLoadError::ReadError(read_error)) - } - } - - fn load_from_file(file: &mut fs::File) -> Result { - let mut buf = String::new(); - match file.read_to_string(&mut buf) { - Ok(_) => {}, - Err(read_error) => { return Err(KeyFileLoadError::ReadError(read_error)); } - } - match Json::from_str(&buf) { - Ok(json) => match KeyFileContent::from_json(&json) { - Ok(key_file_content) => Ok(key_file_content), - Err(parse_error) => Err(KeyFileLoadError::ParseError(parse_error)) - }, - Err(_) => Err(KeyFileLoadError::ParseError(KeyFileParseError::InvalidJson)) - } - } - - /// Checks if key exists - pub fn exists(&self, id: &Uuid) -> bool { - KeyDirectory::load_key(&self.key_path(id)).is_ok() - } -} - - -#[cfg(test)] -mod file_tests { - use super::{KeyFileContent, KeyFileVersion, KeyFileKdf, KeyFileParseError, CryptoParseError, uuid_from_string, uuid_to_string, KeyFileCrypto, KdfPbkdf2Params}; - use common::*; - - #[test] - fn uuid_parses() { - let uuid = uuid_from_string("3198bc9c-6672-5ab3-d995-4942343ae5b6").unwrap(); - assert!(uuid > H128::zero()); - } - - #[test] - fn uuid_serializes() { - let uuid = uuid_from_string("3198bc9c-6fff-5ab3-d995-4942343ae5b6").unwrap(); - assert_eq!(uuid_to_string(&uuid), "3198bc9c-6fff-5ab3-d995-4942343ae5b6"); - } - - #[test] - fn can_read_keyfile() { - let json = Json::from_str( - r#" - { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "6087dab2f9fdbbfaddc31a909735c1e6" - }, - "ciphertext" : "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46", - "kdf" : "pbkdf2", - "kdfparams" : { - "c" : 262144, - "dklen" : 32, - "prf" : "hmac-sha256", - "salt" : "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd" - }, - "mac" : "517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2" - }, - "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6", - "version" : 3 - } - "#).unwrap(); - - match KeyFileContent::from_json(&json) { - Ok(key_file) => { - assert_eq!(KeyFileVersion::V3(3), key_file.version) - }, - Err(e) => panic!("Error parsing valid file: {:?}", e) - } - } - - #[test] - fn can_read_scrypt_kdf() { - let json = Json::from_str( - r#" - { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "83dbcc02d8ccb40e466191a123791e0e" - }, - "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c", - "kdf" : "scrypt", - "kdfparams" : { - "dklen" : 32, - "n" : 262144, - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - }, - "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097" - }, - "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6", - "version" : 3 - } - "#).unwrap(); - - match KeyFileContent::from_json(&json) { - Ok(key_file) => { - match key_file.crypto.kdf { - KeyFileKdf::Scrypt(_) => {}, - _ => { panic!("expected kdf params of crypto to be of scrypt type" ); } - } - }, - Err(e) => panic!("Error parsing valid file: {:?}", e) - } - } - - #[test] - fn can_read_scrypt_kdf_params() { - let json = Json::from_str( - r#" - { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "83dbcc02d8ccb40e466191a123791e0e" - }, - "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c", - "kdf" : "scrypt", - "kdfparams" : { - "dklen" : 32, - "n" : 262144, - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - }, - "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097" - }, - "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6", - "version" : 3 - } - "#).unwrap(); - - match KeyFileContent::from_json(&json) { - Ok(key_file) => { - match key_file.crypto.kdf { - KeyFileKdf::Scrypt(scrypt_params) => { - assert_eq!(262144, scrypt_params.n); - assert_eq!(1, scrypt_params.r); - assert_eq!(8, scrypt_params.p); - }, - _ => { panic!("expected kdf params of crypto to be of scrypt type" ); } - } - }, - Err(e) => panic!("Error parsing valid file: {:?}", e) - } - } - - #[test] - fn can_return_error_no_id() { - let json = Json::from_str( - r#" - { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "83dbcc02d8ccb40e466191a123791e0e" - }, - "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c", - "kdf" : "scrypt", - "kdfparams" : { - "dklen" : 32, - "n" : 262144, - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - }, - "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097" - }, - "version" : 3 - } - "#).unwrap(); - - match KeyFileContent::from_json(&json) { - Ok(_) => { - panic!("Should be error of no crypto section, got ok"); - }, - Err(KeyFileParseError::InvalidIdentifier) => { }, - Err(other_error) => { panic!("should be error of no crypto section, got {:?}", other_error); } - } - } - - #[test] - fn can_return_error_no_crypto() { - let json = Json::from_str( - r#" - { - "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6", - "version" : 3 - } - "#).unwrap(); - - match KeyFileContent::from_json(&json) { - Ok(_) => { - panic!("Should be error of no identifier, got ok"); - }, - Err(KeyFileParseError::NoCryptoSection) => { }, - Err(other_error) => { panic!("should be error of no identifier, got {:?}", other_error); } - } - } - - #[test] - fn can_return_error_unsupported_version() { - let json = Json::from_str( - r#" - { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "83dbcc02d8ccb40e466191a123791e0e" - }, - "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c", - "kdf" : "scrypt", - "kdfparams" : { - "dklen" : 32, - "n" : 262144, - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - }, - "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097" - }, - "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6", - "version" : 1 - } - "#).unwrap(); - - match KeyFileContent::from_json(&json) { - Ok(_) => { - panic!("should be error of unsupported version, got ok"); - }, - Err(KeyFileParseError::UnsupportedVersion(_)) => { }, - Err(other_error) => { panic!("should be error of unsupported version, got {:?}", other_error); } - } - } - - - #[test] - fn can_return_error_initial_vector() { - let json = Json::from_str( - r#" - { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "83dbcc02d8ccb40e4______66191a123791e0e" - }, - "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c", - "kdf" : "scrypt", - "kdfparams" : { - "dklen" : 32, - "n" : 262144, - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - }, - "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097" - }, - "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6", - "version" : 3 - } - "#).unwrap(); - - match KeyFileContent::from_json(&json) { - Ok(_) => { - panic!("should be error of invalid initial vector, got ok"); - }, - Err(KeyFileParseError::Crypto(CryptoParseError::InvalidInitialVector(_))) => { }, - Err(other_error) => { panic!("should be error of invalid initial vector, got {:?}", other_error); } - } - } - - #[test] - fn can_return_error_for_invalid_scrypt_kdf() { - let json = Json::from_str( - r#" - { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "83dbcc02d8ccb40e466191a123791e0e" - }, - "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c", - "kdf" : "scrypt", - "kdfparams" : { - "dklen2" : 32, - "n5" : "xx", - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - }, - "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097" - }, - "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6", - "version" : 3 - } - "#).unwrap(); - - match KeyFileContent::from_json(&json) { - Ok(_) => { - panic!("Should be error of no identifier, got ok"); - }, - Err(KeyFileParseError::Crypto(CryptoParseError::Scrypt(_))) => { }, - Err(other_error) => { panic!("should be scrypt parse error, got {:?}", other_error); } - } - } - - #[test] - fn can_serialize_scrypt_back() { - let json = Json::from_str( - r#" - { - "crypto" : { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "83dbcc02d8ccb40e466191a123791e0e" - }, - "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c", - "kdf" : "scrypt", - "kdfparams" : { - "dklen" : 32, - "n" : 262144, - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - }, - "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097" - }, - "id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6", - "version" : 3 - } - "#).unwrap(); - - let key = KeyFileContent::from_json(&json).unwrap(); - let serialized = key.to_json(); - - assert!(serialized.as_object().is_some()); - } - - #[test] - fn can_create_key_with_new_id() { - let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap(); - let key = KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text, H128::zero(), H256::random(), H256::random(), 32, 32)); - assert!(!uuid_to_string(&key.id).is_empty()); - } - - #[test] - fn can_load_json_from_itself() { - let cipher_text: Bytes = FromHex::from_hex("aaaaaaaaaaaaaaaaaaaaaaaaaaa22222222222222222222222").unwrap(); - let key = KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text, H128::zero(), H256::random(), H256::random(), 32, 32)); - let json = key.to_json(); - - let loaded_key = KeyFileContent::from_json(&json).unwrap(); - - assert_eq!(loaded_key.id, key.id); - } - - #[test] - fn can_parse_kdf_params_fail() { - let json = Json::from_str( - r#" - { - "dklen" : 32, - "n" : 262144, - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - } - "#).unwrap(); - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.remove("dklen"); - let kdf = KdfPbkdf2Params::from_json(&invalid_json); - assert!(!kdf.is_ok()); - } - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.remove("n"); - let kdf = KdfPbkdf2Params::from_json(&invalid_json); - assert!(!kdf.is_ok()); - } - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.remove("r"); - let kdf = KdfPbkdf2Params::from_json(&invalid_json); - assert!(!kdf.is_ok()); - } - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.remove("p"); - let kdf = KdfPbkdf2Params::from_json(&invalid_json); - assert!(!kdf.is_ok()); - } - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.remove("salt"); - let kdf = KdfPbkdf2Params::from_json(&invalid_json); - assert!(!kdf.is_ok()); - } - - } - - #[test] - fn can_parse_kdf_params_scrypt_fail() { - let json = Json::from_str( - r#" - { - "dklen" : 32, - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - } - "#).unwrap(); - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.remove("dklen"); - let kdf = KdfPbkdf2Params::from_json(&invalid_json); - assert!(!kdf.is_ok()); - } - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.remove("r"); - let kdf = KdfPbkdf2Params::from_json(&invalid_json); - assert!(!kdf.is_ok()); - } - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.remove("p"); - let kdf = KdfPbkdf2Params::from_json(&invalid_json); - assert!(!kdf.is_ok()); - } - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.remove("salt"); - let kdf = KdfPbkdf2Params::from_json(&invalid_json); - assert!(!kdf.is_ok()); - } - } - - #[test] - fn can_parse_crypto_fails() { - let json = Json::from_str( - r#" - { - "cipher" : "aes-128-ctr", - "cipherparams" : { - "iv" : "83dbcc02d8ccb40e466191a123791e0e" - }, - "ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c", - "kdf" : "scrypt", - "kdfparams" : { - "dklen" : 32, - "n" : 262144, - "r" : 1, - "p" : 8, - "salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19" - }, - "mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097" - }"#).unwrap(); - - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.insert("cipher".to_owned(), Json::String("unknown".to_owned())); - let crypto = KeyFileCrypto::from_json(&Json::Object(invalid_json)); - assert!(!crypto.is_ok()); - } - - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.insert("kdfparams".to_owned(), Json::String("122".to_owned())); - let crypto = KeyFileCrypto::from_json(&Json::Object(invalid_json)); - assert!(!crypto.is_ok()); - } - - { - let mut invalid_json = json.as_object().unwrap().clone(); - invalid_json.insert("kdf".to_owned(), Json::String("15522".to_owned())); - let crypto = KeyFileCrypto::from_json(&Json::Object(invalid_json)); - assert!(!crypto.is_ok()); - } - - } - -} - -#[cfg(test)] -mod directory_tests { - use super::{KeyDirectory, new_uuid, uuid_to_string, KeyFileContent, KeyFileCrypto, MAX_CACHE_USAGE_TRACK}; - use common::*; - use devtools::*; - - #[test] - fn key_directory_locates_keys() { - let temp_path = RandomTempPath::create_dir(); - let directory = KeyDirectory::new(temp_path.as_path()); - let uuid = new_uuid(); - - let path = directory.key_path(&uuid); - - assert!(path.to_str().unwrap().contains(&uuid_to_string(&uuid))); - } - - #[test] - fn loads_key() { - let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap(); - let temp_path = RandomTempPath::create_dir(); - let mut directory = KeyDirectory::new(&temp_path.as_path()); - let uuid = directory.save(KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text, H128::zero(), H256::random(), H256::random(), 32, 32))).unwrap(); - let path = directory.key_path(&uuid); - - let key = KeyDirectory::load_key(&path).unwrap(); - - assert_eq!(key.id, uuid); - } - - #[test] - fn caches_keys() { - let temp_path = RandomTempPath::create_dir(); - let mut directory = KeyDirectory::new(&temp_path.as_path()); - - let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap(); - let mut keys = Vec::new(); - for _ in 0..1000 { - let key = KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text.clone(), H128::zero(), H256::random(), H256::random(), 32, 32)); - keys.push(directory.save(key).unwrap()); - } - - for key_id in keys { - directory.get(&key_id).unwrap(); - } - - assert_eq!(1000, directory.cache_size()) - - } - - #[test] - fn collects_garbage() { - let temp_path = RandomTempPath::create_dir(); - let mut directory = KeyDirectory::new(&temp_path.as_path()); - - let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap(); - let mut keys = Vec::new(); - for _ in 0..1000 { - let key = KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text.clone(), H128::zero(), H256::random(), H256::random(), 32, 32)); - keys.push(directory.save(key).unwrap()); - } - - for key_id in keys { - directory.get(&key_id).unwrap(); - } - - directory.collect_garbage(); - // since all keys are different, should be exactly MAX_CACHE_USAGE_TRACK - assert_eq!(MAX_CACHE_USAGE_TRACK, directory.cache_size()) - } - - #[test] - fn collects_garbage_on_empty() { - let temp_path = RandomTempPath::create_dir(); - let mut directory = KeyDirectory::new(&temp_path.as_path()); - directory.collect_garbage(); - assert_eq!(0, directory.cache_size()) - } -} - -#[cfg(test)] -mod specs { - use super::*; - use common::*; - use devtools::*; - - #[test] - fn can_initiate_key_directory() { - let temp_path = RandomTempPath::create_dir(); - let directory = KeyDirectory::new(&temp_path.as_path()); - assert!(directory.path().len() > 0); - } - - #[test] - fn can_save_key() { - let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap(); - let temp_path = RandomTempPath::create_dir(); - let mut directory = KeyDirectory::new(&temp_path.as_path()); - - let uuid = directory.save(KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text, H128::zero(), H256::random(), H256::random(), 32, 32))); - - assert!(uuid.is_ok()); - } - - #[test] - fn can_load_key() { - let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap(); - let temp_path = RandomTempPath::create_dir(); - let mut directory = KeyDirectory::new(&temp_path.as_path()); - let uuid = directory.save(KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text.clone(), H128::zero(), H256::random(), H256::random(), 32, 32))).unwrap(); - - let key = directory.get(&uuid).unwrap(); - - assert_eq!(key.crypto.cipher_text, cipher_text); - } - - #[test] - fn can_store_10_keys() { - let temp_path = RandomTempPath::create_dir(); - let mut directory = KeyDirectory::new(&temp_path.as_path()); - - let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap(); - let mut keys = Vec::new(); - for _ in 0..10 { - let key = KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text.clone(), H128::zero(), H256::random(), H256::random(), 32, 32)); - keys.push(directory.save(key).unwrap()); - } - - assert_eq!(10, keys.len()) - } - - #[test] - fn can_list_keys() { - let temp_path = RandomTempPath::create_dir(); - let mut directory = KeyDirectory::new(&temp_path.as_path()); - - let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap(); - let mut keys = Vec::new(); - for _ in 0..33 { - let key = KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text.clone(), H128::zero(), H256::random(), H256::random(), 32, 32)); - keys.push(directory.save(key).unwrap()); - } - - assert_eq!(33, directory.list().unwrap().len()); - } -} diff --git a/util/src/keys/geth_import.rs b/util/src/keys/geth_import.rs deleted file mode 100644 index 509ebc89f..000000000 --- a/util/src/keys/geth_import.rs +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2015, 2016 Ethcore (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 . - -//! Geth keys import/export tool - -use common::*; -use keys::store::SecretStore; -use keys::directory::KeyFileContent; -use std::path::PathBuf; -use path; - -/// Enumerates all geth keys in the directory and returns collection of tuples `(accountId, filename)` -pub fn enumerate_geth_keys(path: &Path) -> Result, ImportError> { - let mut entries = Vec::new(); - for entry in try!(fs::read_dir(path)) { - let entry = try!(entry); - if !try!(fs::metadata(entry.path())).is_dir() { - match entry.file_name().to_str() { - Some(name) => { - let parts: Vec<&str> = name.split("--").collect(); - if parts.len() != 3 { continue; } - let account_id = try!(Address::from_str(parts[2]).map_err(|_| ImportError::Format)); - entries.push((account_id, name.to_owned())); - }, - None => { continue; } - }; - } - } - Ok(entries) -} - -/// Geth import error -#[derive(Debug)] -pub enum ImportError { - /// Io error reading geth file - Io(io::Error), - /// format error - Format, -} - -impl From for ImportError { - fn from (err: io::Error) -> ImportError { - ImportError::Io(err) - } -} - -/// Imports one geth key to the store -pub fn import_geth_key(secret_store: &mut SecretStore, geth_keyfile_path: &Path) -> Result<(), ImportError> { - let mut file = try!(fs::File::open(geth_keyfile_path)); - let mut buf = String::new(); - try!(file.read_to_string(&mut buf)); - - let mut json_result = Json::from_str(&buf); - let mut json = match json_result { - Ok(ref mut parsed_json) => try!(parsed_json.as_object_mut().ok_or(ImportError::Format)), - Err(_) => { return Err(ImportError::Format); } - }; - if let Some(crypto_object) = json.get("Crypto").and_then(|crypto| crypto.as_object()).cloned() { - json.insert("crypto".to_owned(), Json::Object(crypto_object)); - json.remove("Crypto"); - } - match KeyFileContent::load(&Json::Object(json.clone())) { - Ok(key_file) => try!(secret_store.import_key(key_file)), - Err(_) => { return Err(ImportError::Format); } - }; - Ok(()) -} - -/// Imports all geth keys in the directory -pub fn import_geth_keys(secret_store: &mut SecretStore, geth_keyfiles_directory: &Path) -> Result { - use std::path::PathBuf; - let geth_files = try!(enumerate_geth_keys(geth_keyfiles_directory)); - let mut total = 0; - for &(ref address, ref file_path) in &geth_files { - let mut path = PathBuf::new(); - path.push(geth_keyfiles_directory); - path.push(file_path); - if let Err(e) = import_geth_key(secret_store, Path::new(&path)) { - warn!("Skipped geth address {}, error importing: {:?}", address, e) - } - else { total = total + 1} - } - Ok(total) -} - - -/// Gets the default geth keystore directory. -pub fn keystore_dir(is_testnet: bool) -> PathBuf { - path::ethereum::with_default(if is_testnet {"testnet/keystore"} else {"keystore"}) -} - -/// Imports key(s) from provided file/directory -pub fn import_keys_path(secret_store: &mut SecretStore, path: &str) -> Result { - // check if it is just one file or directory - if let Ok(meta) = fs::metadata(path) { - if meta.is_file() { - try!(import_geth_key(secret_store, Path::new(path))); - return Ok(1); - } - else if meta.is_dir() { - return Ok(try!(fs::read_dir(path)).fold( - 0, - |total, p| - total + - match p { - Ok(dir_entry) => import_keys_path(secret_store, dir_entry.path().to_str().unwrap()).unwrap_or_else(|_| 0), - Err(e) => { warn!("Error importing dir entry: {:?}", e); 0 }, - } - )) - } - } - Ok(0) -} - -/// Imports all keys from list of provided files/directories -pub fn import_keys_paths(secret_store: &mut SecretStore, path: &[String]) -> Result { - Ok(path.iter().fold(0, |total, ref p| total + import_keys_path(secret_store, &p).unwrap_or_else(|_| 0))) -} - -#[cfg(test)] -mod tests { - use super::*; - use common::*; - use keys::store::SecretStore; - - fn test_path() -> &'static str { - match ::std::fs::metadata("res") { - Ok(_) => "res/geth_keystore", - Err(_) => "util/res/geth_keystore" - } - } - - fn pat_path() -> &'static str { - match ::std::fs::metadata("res") { - Ok(_) => "res/pat", - Err(_) => "util/res/pat" - } - } - - fn test_path_param(param_val: &'static str) -> String { - test_path().to_owned() + param_val - } - - fn pat_path_param(param_val: &'static str) -> String { - pat_path().to_owned() + param_val - } - - #[test] - fn can_enumerate() { - let keys = enumerate_geth_keys(Path::new(test_path())).unwrap(); - assert_eq!(3, keys.len()); - } - - #[test] - fn can_import_geth_old() { - let temp = ::devtools::RandomTempPath::create_dir(); - let mut secret_store = SecretStore::new_in(temp.as_path()); - import_geth_key(&mut secret_store, Path::new(&test_path_param("/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9"))).unwrap(); - let key = secret_store.account(&Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap()); - assert!(key.is_some()); - } - - #[test] - fn can_import_geth140() { - let temp = ::devtools::RandomTempPath::create_dir(); - let mut secret_store = SecretStore::new_in(temp.as_path()); - import_geth_key(&mut secret_store, Path::new(&test_path_param("/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649"))).unwrap(); - let key = secret_store.account(&Address::from_str("63121b431a52f8043c16fcf0d1df9cb7b5f66649").unwrap()); - assert!(key.is_some()); - } - - #[test] - fn can_import_directory() { - let temp = ::devtools::RandomTempPath::create_dir(); - let mut secret_store = SecretStore::new_in(temp.as_path()); - import_geth_keys(&mut secret_store, Path::new(test_path())).unwrap(); - - let key = secret_store.account(&Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap()); - assert!(key.is_some()); - - let key = secret_store.account(&Address::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap()); - assert!(key.is_some()); - } - - #[test] - fn imports_as_scrypt_keys() { - use keys::directory::{KeyDirectory, KeyFileKdf}; - let temp = ::devtools::RandomTempPath::create_dir(); - { - let mut secret_store = SecretStore::new_in(temp.as_path()); - import_geth_keys(&mut secret_store, Path::new(test_path())).unwrap(); - } - - let key_directory = KeyDirectory::new(&temp.as_path()); - let key_file = key_directory.get(&H128::from_str("62a0ad73556d496a8e1c0783d30d3ace").unwrap()).unwrap(); - - match key_file.crypto.kdf { - KeyFileKdf::Scrypt(scrypt_params) => { - assert_eq!(262144, scrypt_params.n); - assert_eq!(8, scrypt_params.r); - assert_eq!(1, scrypt_params.p); - }, - _ => { panic!("expected kdf params of crypto to be of scrypt type" ); } - } - } - - #[test] - #[cfg(feature="heavy-tests")] - fn can_decrypt_with_imported() { - use keys::store::EncryptedHashMap; - - let temp = ::devtools::RandomTempPath::create_dir(); - let mut secret_store = SecretStore::new_in(temp.as_path()); - import_geth_keys(&mut secret_store, Path::new(test_path())).unwrap(); - - let val = secret_store.get::(&H128::from_str("62a0ad73556d496a8e1c0783d30d3ace").unwrap(), "123"); - assert!(val.is_ok()); - assert_eq!(32, val.unwrap().len()); - } - - #[test] - fn can_import_by_filename() { - let temp = ::devtools::RandomTempPath::create_dir(); - let mut secret_store = SecretStore::new_in(temp.as_path()); - - let amount = import_keys_path(&mut secret_store, &pat_path_param("/p1.json")).unwrap(); - assert_eq!(1, amount); - } - - #[test] - fn can_import_by_dir() { - let temp = ::devtools::RandomTempPath::create_dir(); - let mut secret_store = SecretStore::new_in(temp.as_path()); - - let amount = import_keys_path(&mut secret_store, pat_path()).unwrap(); - assert_eq!(2, amount); - } - - #[test] - fn can_import_mulitple() { - let temp = ::devtools::RandomTempPath::create_dir(); - let mut secret_store = SecretStore::new_in(temp.as_path()); - - let amount = import_keys_paths(&mut secret_store, &[pat_path_param("/p1.json"), pat_path_param("/p2.json")]).unwrap(); - assert_eq!(2, amount); - } - -} diff --git a/util/src/keys/mod.rs b/util/src/keys/mod.rs deleted file mode 100644 index 39c39aeef..000000000 --- a/util/src/keys/mod.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2015, 2016 Ethcore (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 . - -//! Key management module - -pub mod directory; -pub mod store; -mod geth_import; -mod test_account_provider; - -pub use self::store::AccountProvider; -pub use self::test_account_provider::{TestAccount, TestAccountProvider}; -pub use self::geth_import::import_keys_paths; diff --git a/util/src/keys/store.rs b/util/src/keys/store.rs deleted file mode 100644 index b8a1de272..000000000 --- a/util/src/keys/store.rs +++ /dev/null @@ -1,754 +0,0 @@ -// Copyright 2015, 2016 Ethcore (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 . - -//! Secret Store - -use keys::directory::*; -use common::*; -use rcrypto::pbkdf2::*; -use rcrypto::scrypt::*; -use rcrypto::hmac::*; -use crypto; -use chrono::*; - -const KEY_LENGTH: u32 = 32; -const KEY_ITERATIONS: u32 = 10240; -const KEY_LENGTH_AES: u32 = KEY_LENGTH/2; - -const KEY_LENGTH_USIZE: usize = KEY_LENGTH as usize; -const KEY_LENGTH_AES_USIZE: usize = KEY_LENGTH_AES as usize; - -// TODO: this file needs repotting into several separate files. - -/// Encrypted hash-map, each request should contain password -pub trait EncryptedHashMap { - /// Returns existing value for the key, if any - fn get(&self, key: &Key, password: &str) -> Result; - /// Insert new encrypted key-value and returns previous if there was any - fn insert(&mut self, key: Key, value: Value, password: &str) -> Option; - /// Removes key-value by key and returns the removed one, if any exists and password was provided - fn remove (&mut self, key: &Key, password: Option<&str>) -> Option; - /// Deletes key-value by key and returns if the key-value existed - fn delete(&mut self, key: &Key) -> bool { - self.remove::(key, None).is_some() - } -} - -/// Error retrieving value from encrypted hashmap -#[derive(Debug)] -pub enum EncryptedHashMapError { - /// Encryption failed - InvalidPassword, - /// No key in the hashmap - UnknownIdentifier, - /// Stored value is not well formed for the requested type - InvalidValueFormat(FromBytesError), -} - -/// Error while signing a message -#[derive(Debug)] -pub enum SigningError { - /// Account passed does not exist - NoAccount, - /// Account passed is not unlocked - AccountNotUnlocked, - /// Invalid passphrase - InvalidPassword, - /// Invalid secret in store - InvalidSecret -} - -/// Represent service for storing encrypted arbitrary data -pub struct SecretStore { - directory: KeyDirectory, - unlocks: RwLock>, - key_iterations: u32, -} - -struct AccountUnlock { - secret: H256, - /// expiration datetime (None - never) - expires: Option>, - /// Sccount should be relocked after first use. - relock_on_use: bool, -} - -/// Basic account management trait -pub trait AccountProvider: Send + Sync { - /// Lists all accounts - fn accounts(&self) -> Result, ::std::io::Error>; - /// Unlocks account with the password provided - fn unlock_account(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError>; - /// Unlocks account with the password provided; relocks it on the next call to `account_secret` or `sign`. - fn unlock_account_temp(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError>; - /// Creates account - fn new_account(&self, pass: &str) -> Result; - /// Returns secret for unlocked `account`. - fn account_secret(&self, account: &Address) -> Result; - /// Returns secret for locked account given passphrase. - fn locked_account_secret(&self, account: &Address, pass: &str) -> Result; - /// Returns signature when unlocked `account` signs `message`. - fn sign(&self, account: &Address, message: &H256) -> Result { - self.account_secret(account).and_then(|s| crypto::ec::sign(&s, message).map_err(|_| SigningError::InvalidSecret)) - } -} - -/// Thread-safe accounts management -pub struct AccountService { - secret_store: RwLock, -} - -impl AccountProvider for AccountService { - /// Lists all accounts - fn accounts(&self) -> Result, ::std::io::Error> { - Ok(try!(self.secret_store.read().unwrap().accounts()).iter().map(|&(addr, _)| addr).collect::>()) - } - /// Unlocks account with the password provided - fn unlock_account(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> { - self.secret_store.read().unwrap().unlock_account(account, pass) - } - fn unlock_account_temp(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> { - self.secret_store.read().unwrap().unlock_account_temp(account, pass) - } - /// Creates account - fn new_account(&self, pass: &str) -> Result { - self.secret_store.write().unwrap().new_account(pass) - } - /// Returns secret for unlocked account - fn account_secret(&self, account: &Address) -> Result { - self.secret_store.read().unwrap().account_secret(account) - } - /// Returns secret for locked account given passphrase. - fn locked_account_secret(&self, account: &Address, pass: &str) -> Result { - self.secret_store.read().unwrap().locked_account_secret(account, pass) - } - /// Signs a message using key of given unlocked account address. - fn sign(&self, account: &Address, message: &H256) -> Result { - self.secret_store.read().unwrap().sign(account, message) - } -} - -/// Which set of keys to import. -#[derive(PartialEq)] -pub enum ImportKeySet { - /// Empty set. - None, - /// Import legacy client's general keys. - Legacy, - /// Import legacy client's testnet keys. - LegacyTestnet, -} - -impl AccountService { - /// New account service with the keys store in specific location and configured security parameters. - pub fn with_security(path: &Path, key_iterations: u32, import_keys: ImportKeySet) -> Self { - let secret_store = RwLock::new(SecretStore::with_security(path, key_iterations)); - match import_keys { - ImportKeySet::None => {} - _ => { secret_store.write().unwrap().try_import_existing(import_keys == ImportKeySet::LegacyTestnet); } - } - AccountService { - secret_store: secret_store, - } - } - - #[cfg(test)] - fn new_test(temp: &::devtools::RandomTempPath) -> Self { - let secret_store = RwLock::new(SecretStore::new_test(temp)); - AccountService { - secret_store: secret_store - } - } - - /// Ticks the account service - pub fn tick(&self) { - self.secret_store.write().unwrap().collect_garbage(); - } - - /// Unlocks account for use (no expiration of unlock) - pub fn unlock_account_no_expire(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> { - self.secret_store.write().unwrap().unlock_account_with_expiration(account, pass, None, false) - } -} - -impl SecretStore { - /// new instance of Secret Store in specific directory - pub fn new_in(path: &Path) -> Self { - SecretStore::with_security(path, KEY_ITERATIONS) - } - - /// new instance of Secret Store in specific directory and configured security parameters - pub fn with_security(path: &Path, key_iterations: u32) -> Self { - ::std::fs::create_dir_all(&path).expect("Cannot access requested key directory - critical"); - SecretStore { - directory: KeyDirectory::new(path), - unlocks: RwLock::new(HashMap::new()), - key_iterations: key_iterations, - } - } - - /// trys to import keys in the known locations - pub fn try_import_existing(&mut self, is_testnet: bool) { - use keys::geth_import; - - let import_path = geth_import::keystore_dir(is_testnet); - if let Err(e) = geth_import::import_geth_keys(self, &import_path) { - trace!(target: "sstore", "Geth key not imported: {:?}", e); - } - } - - /// Lists all accounts and corresponding key ids - pub fn accounts(&self) -> Result, ::std::io::Error> { - let accounts = try!(self.directory.list()).iter().map(|key_id| self.directory.get(key_id)) - .filter(|key| key.is_some()) - .map(|key| { let some_key = key.unwrap(); (some_key.account, some_key.id) }) - .filter(|&(ref account, _)| account.is_some()) - .map(|(account, id)| (account.unwrap(), id)) - .collect::>(); - Ok(accounts) - } - - /// Resolves key_id by account address - pub fn account(&self, account: &Address) -> Option { - let mut accounts = match self.accounts() { - Ok(accounts) => accounts, - Err(e) => { warn!(target: "sstore", "Failed to load accounts: {}", e); return None; } - }; - accounts.retain(|&(ref store_account, _)| account == store_account); - accounts.first().and_then(|&(_, ref key_id)| Some(key_id.clone())) - } - - /// Imports pregenerated key, returns error if not saved correctly - pub fn import_key(&mut self, key_file: KeyFileContent) -> Result<(), ::std::io::Error> { - try!(self.directory.save(key_file)); - Ok(()) - } - - #[cfg(test)] - fn new_test(path: &::devtools::RandomTempPath) -> SecretStore { - SecretStore { - directory: KeyDirectory::new(path.as_path()), - unlocks: RwLock::new(HashMap::new()), - key_iterations: KEY_ITERATIONS, - } - } - - /// Unlocks account for use - pub fn unlock_account(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> { - self.unlock_account_with_expiration(account, pass, Some(UTC::now() + Duration::minutes(20)), false) - } - - /// Unlocks account for use (no expiration of unlock) - pub fn unlock_account_no_expire(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> { - self.unlock_account_with_expiration(account, pass, None, false) - } - - /// Unlocks account for use (no expiration of unlock) - pub fn unlock_account_temp(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> { - self.unlock_account_with_expiration(account, pass, None, true) - } - - fn unlock_account_with_expiration(&self, account: &Address, pass: &str, expiration: Option>, relock_on_use: bool) -> Result<(), EncryptedHashMapError> { - let secret_id = try!(self.account(&account).ok_or(EncryptedHashMapError::UnknownIdentifier)); - let secret = try!(self.get(&secret_id, pass)); - { - let mut write_lock = self.unlocks.write().unwrap(); - let mut unlock = write_lock.entry(*account) - .or_insert_with(|| AccountUnlock { secret: secret, expires: Some(UTC::now()), relock_on_use: relock_on_use }); - unlock.secret = secret; - unlock.expires = expiration; - } - Ok(()) - } - - /// Creates new account - pub fn new_account(&mut self, pass: &str) -> Result { - let key_pair = crypto::KeyPair::create().expect("Error creating key-pair. Something wrong with crypto libraries?"); - let address = Address::from(key_pair.public().sha3()); - let key_id = H128::random(); - self.insert(key_id.clone(), key_pair.secret().clone(), pass); - - let mut key_file = self.directory.get(&key_id).expect("the key was just inserted"); - key_file.account = Some(address); - try!(self.directory.save(key_file)); - Ok(address) - } - - /// Signs message with unlocked account. - pub fn sign(&self, account: &Address, message: &H256) -> Result { - let (relock, ret) = { - let read_lock = self.unlocks.read().unwrap(); - if let Some(unlock) = read_lock.get(account) { - (unlock.relock_on_use, match crypto::KeyPair::from_secret(unlock.secret) { - Ok(pair) => match pair.sign(message) { - Ok(signature) => Ok(signature), - Err(_) => Err(SigningError::InvalidSecret) - }, - Err(_) => Err(SigningError::InvalidSecret) - }) - } else { - (false, Err(SigningError::AccountNotUnlocked)) - } - }; - if relock { - self.unlocks.write().unwrap().remove(account); - } - ret - } - - /// Returns secret for unlocked account. - pub fn account_secret(&self, account: &Address) -> Result { - let (relock, ret) = { - let read_lock = self.unlocks.read().unwrap(); - if let Some(unlock) = read_lock.get(account) { - (unlock.relock_on_use, Ok(unlock.secret as crypto::Secret)) - } else { - (false, Err(SigningError::AccountNotUnlocked)) - } - }; - if relock { - self.unlocks.write().unwrap().remove(account); - } - ret - } - - /// Returns secret for locked account. - pub fn locked_account_secret(&self, account: &Address, pass: &str) -> Result { - let secret_id = try!(self.account(&account).ok_or(SigningError::NoAccount)); - self.get(&secret_id, pass).or_else(|e| Err(match e { - EncryptedHashMapError::InvalidPassword => SigningError::InvalidPassword, - EncryptedHashMapError::UnknownIdentifier => SigningError::NoAccount, - EncryptedHashMapError::InvalidValueFormat(_) => SigningError::InvalidSecret, - })) - } - - /// Makes account unlocks expire and removes unused key files from memory - pub fn collect_garbage(&mut self) { - let mut garbage_lock = self.unlocks.write().unwrap(); - self.directory.collect_garbage(); - let utc = UTC::now(); - let expired_addresses = garbage_lock.iter() - .filter(|&(_, unlock)| match unlock.expires { Some(ref expire_val) => expire_val < &utc, _ => false }) - .map(|(address, _)| address.clone()).collect::>(); - - for expired in expired_addresses { garbage_lock.remove(&expired); } - - garbage_lock.shrink_to_fit(); - } - - fn exists(&self, key: &H128) -> bool { - self.directory.exists(key) - } -} - -fn derive_key_iterations(password: &str, salt: &H256, c: u32) -> (Bytes, Bytes) { - let mut h_mac = Hmac::new(::rcrypto::sha2::Sha256::new(), password.as_bytes()); - let mut derived_key = vec![0u8; KEY_LENGTH_USIZE]; - pbkdf2(&mut h_mac, &salt.as_slice(), c, &mut derived_key); - let derived_right_bits = &derived_key[0..KEY_LENGTH_AES_USIZE]; - let derived_left_bits = &derived_key[KEY_LENGTH_AES_USIZE..KEY_LENGTH_USIZE]; - (derived_right_bits.to_vec(), derived_left_bits.to_vec()) -} - -fn derive_key(password: &str, salt: &H256, iterations: u32) -> (Bytes, Bytes) { - derive_key_iterations(password, salt, iterations) -} - -fn derive_key_scrypt(password: &str, salt: &H256, n: u32, p: u32, r: u32) -> (Bytes, Bytes) { - let mut derived_key = vec![0u8; KEY_LENGTH_USIZE]; - let scrypt_params = ScryptParams::new(n.trailing_zeros() as u8, r, p); - scrypt(password.as_bytes(), &salt.as_slice(), &scrypt_params, &mut derived_key); - let derived_right_bits = &derived_key[0..KEY_LENGTH_AES_USIZE]; - let derived_left_bits = &derived_key[KEY_LENGTH_AES_USIZE..KEY_LENGTH_USIZE]; - (derived_right_bits.to_vec(), derived_left_bits.to_vec()) -} - -fn derive_mac(derived_left_bits: &[u8], cipher_text: &[u8]) -> Bytes { - let mut mac = vec![0u8; KEY_LENGTH_AES_USIZE + cipher_text.len()]; - mac[0..KEY_LENGTH_AES_USIZE].clone_from_slice(derived_left_bits); - mac[KEY_LENGTH_AES_USIZE..cipher_text.len()+KEY_LENGTH_AES_USIZE].clone_from_slice(cipher_text); - mac -} - -impl EncryptedHashMap for SecretStore { - fn get(&self, key: &H128, password: &str) -> Result { - match self.directory.get(key) { - Some(key_file) => { - let (derived_left_bits, derived_right_bits) = match key_file.crypto.kdf { - KeyFileKdf::Pbkdf2(ref params) => derive_key_iterations(password, ¶ms.salt, params.c), - KeyFileKdf::Scrypt(ref params) => derive_key_scrypt(password, ¶ms.salt, params.n, params.p, params.r) - }; - - if derive_mac(&derived_right_bits, &key_file.crypto.cipher_text) - .sha3() != key_file.crypto.mac { return Err(EncryptedHashMapError::InvalidPassword); } - - let mut val = vec![0u8; key_file.crypto.cipher_text.len()]; - match key_file.crypto.cipher_type { - CryptoCipherType::Aes128Ctr(ref iv) => { - crypto::aes::decrypt(&derived_left_bits, &iv.as_slice(), &key_file.crypto.cipher_text, &mut val); - } - }; - - match Value::from_bytes_variable(&val) { - Ok(value) => Ok(value), - Err(bytes_error) => Err(EncryptedHashMapError::InvalidValueFormat(bytes_error)) - } - }, - None => Err(EncryptedHashMapError::UnknownIdentifier) - } - } - - fn insert(&mut self, key: H128, value: Value, password: &str) -> Option { - let previous = if !self.exists(&key) { None } else { self.get(&key, password).ok() }; - - // crypto random initiators - let salt = H256::random(); - let iv = H128::random(); - - // two parts of derived key - // DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits] - let (derived_left_bits, derived_right_bits) = derive_key(password, &salt, self.key_iterations); - - let mut cipher_text = vec![0u8; value.as_slice().len()]; - // aes-128-ctr with initial vector of iv - crypto::aes::encrypt(&derived_left_bits, &iv.clone(), &value.as_slice(), &mut cipher_text); - - // KECCAK(DK[16..31] ++ ), where DK[16..31] - derived_right_bits - let mac = derive_mac(&derived_right_bits, &cipher_text.clone()).sha3(); - - let mut key_file = KeyFileContent::new( - KeyFileCrypto::new_pbkdf2( - cipher_text, - iv, - salt, - mac, - self.key_iterations, - KEY_LENGTH)); - key_file.id = key; - if let Err(io_error) = self.directory.save(key_file) { - warn!("Error saving key file: {:?}", io_error); - } - previous - } - - fn remove(&mut self, key: &H128, password: Option<&str>) -> Option { - let previous = if let Some(pass) = password { - if let Ok(previous_value) = self.get(&key, pass) { Some(previous_value) } else { None } - } - else { None }; - - if let Err(io_error) = self.directory.delete(key) { - warn!("Error saving key file: {:?}", io_error); - } - previous - } - -} - -#[cfg(all(test, feature="heavy-tests"))] -mod vector_tests { - use super::{derive_mac,derive_key_iterations}; - use common::*; - - #[test] - fn mac_vector() { - let password = "testpassword"; - let salt = H256::from_str("ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd").unwrap(); - let cipher_text = FromHex::from_hex("5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46").unwrap(); - let iterations = 262144u32; - - let (derived_left_bits, derived_right_bits) = derive_key_iterations(password, &salt, iterations); - assert_eq!("f06d69cdc7da0faffb1008270bca38f5", derived_left_bits.to_hex()); - assert_eq!("e31891a3a773950e6d0fea48a7188551", derived_right_bits.to_hex()); - - let mac_body = derive_mac(&derived_right_bits, &cipher_text); - assert_eq!("e31891a3a773950e6d0fea48a71885515318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46", mac_body.to_hex()); - - let mac = mac_body.sha3(); - assert_eq!("517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2", format!("{:?}", mac)); - } -} - - -#[cfg(test)] -mod tests { - use super::*; - use devtools::*; - use common::*; - use crypto::KeyPair; - use chrono::*; - - #[test] - fn can_insert() { - let temp = RandomTempPath::create_dir(); - let mut sstore = SecretStore::new_test(&temp); - - let id = H128::random(); - sstore.insert(id.clone(), "Cat".to_owned(), "pass"); - - assert!(sstore.get::(&id, "pass").is_ok()); - } - - #[test] - fn can_get_fail() { - let temp = RandomTempPath::create_dir(); - { - use keys::directory::{KeyFileContent, KeyFileCrypto}; - let mut write_sstore = SecretStore::new_test(&temp); - write_sstore.directory.save( - KeyFileContent::new( - KeyFileCrypto::new_pbkdf2( - FromHex::from_hex("5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46").unwrap(), - H128::from_str("6087dab2f9fdbbfaddc31a909735c1e6").unwrap(), - H256::from_str("ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd").unwrap(), - H256::from_str("517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2").unwrap(), - 262144, - 32))) - .unwrap(); - } - let sstore = SecretStore::new_test(&temp); - if let Ok(_) = sstore.get::(&H128::from_str("3198bc9c66725ab3d9954942343ae5b6").unwrap(), "testpassword") { - panic!("should be error loading key, we requested the wrong key"); - } - } - - fn pregenerate_keys(temp: &RandomTempPath, count: usize) -> Vec { - use keys::directory::{KeyFileContent, KeyFileCrypto}; - let mut write_sstore = SecretStore::new_test(&temp); - let mut result = Vec::new(); - for _ in 0..count { - result.push(write_sstore.directory.save( - KeyFileContent::new( - KeyFileCrypto::new_pbkdf2( - FromHex::from_hex("5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46").unwrap(), - H128::from_str("6087dab2f9fdbbfaddc31a909735c1e6").unwrap(), - H256::from_str("ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd").unwrap(), - H256::from_str("517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2").unwrap(), - 262144, - 32))) - .unwrap()); - } - result - } - - fn pregenerate_accounts(temp: &RandomTempPath, count: usize) -> Vec { - use keys::directory::{KeyFileContent, KeyFileCrypto}; - let mut write_sstore = SecretStore::new_test(&temp); - let mut result = Vec::new(); - for i in 0..count { - let mut key_file = - KeyFileContent::new( - KeyFileCrypto::new_pbkdf2( - FromHex::from_hex("5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46").unwrap(), - H128::from_str("6087dab2f9fdbbfaddc31a909735c1e6").unwrap(), - H256::from_str("ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd").unwrap(), - H256::from_str("517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2").unwrap(), - 262144, - 32)); - key_file.account = Some((i as u64).into()); - result.push(key_file.id.clone()); - write_sstore.import_key(key_file).unwrap(); - } - result - } - - #[test] - #[cfg(feature="heavy-tests")] - fn can_get() { - let temp = RandomTempPath::create_dir(); - let key_id = { - use keys::directory::{KeyFileContent, KeyFileCrypto}; - let mut write_sstore = SecretStore::new_test(&temp); - write_sstore.directory.save( - KeyFileContent::new( - KeyFileCrypto::new_pbkdf2( - FromHex::from_hex("5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46").unwrap(), - H128::from_str("6087dab2f9fdbbfaddc31a909735c1e6").unwrap(), - H256::from_str("ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd").unwrap(), - H256::from_str("517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2").unwrap(), - 262144, - 32))) - .unwrap() - }; - let sstore = SecretStore::new_test(&temp); - if let Err(e) = sstore.get::(&key_id, "testpassword") { - panic!("got no key: {:?}", e); - } - } - - #[test] - fn can_delete() { - let temp = RandomTempPath::create_dir(); - let keys = pregenerate_keys(&temp, 5); - - let mut sstore = SecretStore::new_test(&temp); - sstore.delete(&keys[2]); - - assert_eq!(4, sstore.directory.list().unwrap().len()) - } - - #[test] - fn can_create_account() { - let temp = RandomTempPath::create_dir(); - let mut sstore = SecretStore::new_test(&temp); - sstore.new_account("123").unwrap(); - assert_eq!(1, sstore.accounts().unwrap().len()); - } - - #[test] - fn can_unlock_account() { - let temp = RandomTempPath::create_dir(); - let mut sstore = SecretStore::new_test(&temp); - let address = sstore.new_account("123").unwrap(); - - let secret = sstore.unlock_account(&address, "123"); - assert!(secret.is_ok()); - } - - #[test] - fn can_sign_data() { - let temp = RandomTempPath::create_dir(); - let address = { - let mut sstore = SecretStore::new_test(&temp); - sstore.new_account("334").unwrap() - }; - let signature = { - let sstore = SecretStore::new_test(&temp); - sstore.unlock_account(&address, "334").unwrap(); - sstore.sign(&address, &H256::random()).unwrap() - }; - - assert!(signature != 0.into()); - } - - #[test] - fn can_relock_temp_account() { - let temp = RandomTempPath::create_dir(); - let address = { - let mut sstore = SecretStore::new_test(&temp); - sstore.new_account("334").unwrap() - }; - let signature = { - let sstore = SecretStore::new_test(&temp); - sstore.unlock_account_temp(&address, "334").unwrap(); - sstore.sign(&address, &H256::random()).unwrap(); - sstore.sign(&address, &H256::random()) - }; - assert!(signature.is_err()); - - let secret = { - let sstore = SecretStore::new_test(&temp); - sstore.unlock_account_temp(&address, "334").unwrap(); - sstore.account_secret(&address).unwrap(); - sstore.account_secret(&address) - }; - assert!(secret.is_err()); - } - - #[test] - fn can_import_account() { - use keys::directory::{KeyFileContent, KeyFileCrypto}; - let temp = RandomTempPath::create_dir(); - let mut key_file = - KeyFileContent::new( - KeyFileCrypto::new_pbkdf2( - FromHex::from_hex("5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46").unwrap(), - H128::from_str("6087dab2f9fdbbfaddc31a909735c1e6").unwrap(), - H256::from_str("ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd").unwrap(), - H256::from_str("517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2").unwrap(), - 262144, - 32)); - key_file.account = Some(Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap()); - - let mut sstore = SecretStore::new_test(&temp); - - sstore.import_key(key_file).unwrap(); - - assert_eq!(1, sstore.accounts().unwrap().len()); - assert!(sstore.account(&Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap()).is_some()); - } - - #[test] - fn can_list_accounts() { - let temp = RandomTempPath::create_dir(); - pregenerate_accounts(&temp, 30); - let sstore = SecretStore::new_test(&temp); - let accounts = sstore.accounts().unwrap(); - assert_eq!(30, accounts.len()); - } - - #[test] - fn validate_generated_addresses() { - let temp = RandomTempPath::create_dir(); - let mut sstore = SecretStore::new_test(&temp); - let addr = sstore.new_account("test").unwrap(); - sstore.unlock_account(&addr, "test").unwrap(); - let secret = sstore.account_secret(&addr).unwrap(); - let kp = KeyPair::from_secret(secret).unwrap(); - assert_eq!(Address::from(kp.public().sha3()), addr); - } - - - #[test] - fn secret_for_locked_account() { - // given - let temp = RandomTempPath::create_dir(); - let mut sstore = SecretStore::new_test(&temp); - let addr = sstore.new_account("test-pass").unwrap(); - - // when - // Invalid pass - let secret1 = sstore.locked_account_secret(&addr, "test-pass123"); - // Valid pass - let secret2 = sstore.locked_account_secret(&addr, "test-pass"); - // Account not unlocked - let secret3 = sstore.account_secret(&addr); - - - assert!(secret1.is_err(), "Invalid password should not return secret."); - assert!(secret2.is_ok(), "Should return secret provided valid passphrase."); - assert!(secret3.is_err(), "Account should still be locked."); - } - - - #[test] - fn can_create_service() { - let temp = RandomTempPath::create_dir(); - let svc = AccountService::new_test(&temp); - assert!(svc.accounts().unwrap().is_empty()); - } - - #[test] - fn accounts_expire() { - use std::collections::hash_map::*; - - let temp = RandomTempPath::create_dir(); - let svc = AccountService::new_test(&temp); - let address = svc.new_account("pass").unwrap(); - svc.unlock_account(&address, "pass").unwrap(); - assert!(svc.account_secret(&address).is_ok()); - { - let ss_rw = svc.secret_store.write().unwrap(); - let mut ua_rw = ss_rw.unlocks.write().unwrap(); - let entry = ua_rw.entry(address); - if let Entry::Occupied(mut occupied) = entry { occupied.get_mut().expires = Some(UTC::now() - Duration::minutes(1)) } - } - - svc.tick(); - - assert!(svc.account_secret(&address).is_err()); - } -} diff --git a/util/src/keys/test_account_provider.rs b/util/src/keys/test_account_provider.rs deleted file mode 100644 index 148996172..000000000 --- a/util/src/keys/test_account_provider.rs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2015, 2016 Ethcore (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 . - -//! Test implementation of account provider. - -use std::sync::RwLock; -use std::collections::HashMap; -use std::io; -use hash::Address; -use crypto::{Secret, KeyPair}; -use super::store::{AccountProvider, SigningError, EncryptedHashMapError}; - -/// Account mock. -#[derive(Clone)] -pub struct TestAccount { - /// True if account is unlocked. - pub unlocked: bool, - /// Account's password. - pub password: String, - /// Account's secret. - pub secret: Secret, -} - -impl TestAccount { - /// Creates new test account. - pub fn new(password: &str) -> Self { - let pair = KeyPair::create().unwrap(); - TestAccount { - unlocked: false, - password: password.to_owned(), - secret: pair.secret().clone() - } - } - - /// Returns account address. - pub fn address(&self) -> Address { - KeyPair::from_secret(self.secret.clone()).unwrap().address() - } -} - -/// Test account provider. -pub struct TestAccountProvider { - /// Test provider accounts. - pub accounts: RwLock>, -} - -impl TestAccountProvider { - /// Basic constructor. - pub fn new(accounts: HashMap) -> Self { - TestAccountProvider { - accounts: RwLock::new(accounts), - } - } -} - -impl AccountProvider for TestAccountProvider { - fn accounts(&self) -> Result, io::Error> { - Ok(self.accounts.read().unwrap().keys().cloned().collect()) - } - - fn unlock_account(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> { - match self.accounts.write().unwrap().get_mut(account) { - Some(ref mut acc) if acc.password == pass => { - acc.unlocked = true; - Ok(()) - }, - Some(_) => Err(EncryptedHashMapError::InvalidPassword), - None => Err(EncryptedHashMapError::UnknownIdentifier), - } - } - - fn unlock_account_temp(&self, account: &Address, pass: &str) -> Result<(), EncryptedHashMapError> { - // TODO; actually make it relock on use - self.unlock_account(account, pass) - } - - fn new_account(&self, pass: &str) -> Result { - let account = TestAccount::new(pass); - let address = KeyPair::from_secret(account.secret.clone()).unwrap().address(); - self.accounts.write().unwrap().insert(address.clone(), account); - Ok(address) - } - - fn account_secret(&self, address: &Address) -> Result { - // todo: consider checking if account is unlock. some test may need alteration then. - self.accounts - .read() - .unwrap() - .get(address) - .ok_or(SigningError::NoAccount) - .map(|acc| acc.secret.clone()) - } - - fn locked_account_secret(&self, address: &Address, pass: &str) -> Result { - let accounts = self.accounts.read().unwrap(); - match accounts.get(address) { - Some(ref acc) if acc.password == pass => { - Ok(acc.secret.clone()) - }, - Some(ref _acc) => Err(SigningError::InvalidPassword), - _ => Err(SigningError::NoAccount), - } - } -} - diff --git a/util/src/lib.rs b/util/src/lib.rs index e1a3537f2..e43bbbab0 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -151,7 +151,6 @@ pub mod io; pub mod network; pub mod log; pub mod panics; -pub mod keys; pub mod table; pub mod network_settings; pub mod path; From bf6308312ed4601d4489490ebd84454759f64599 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 20 Jun 2016 00:40:11 +0200 Subject: [PATCH 091/239] Sync: Cache last sync round block parents (#1331) * Cache last sync round block parents * Limit incoming transactions and new hashes --- sync/src/chain.rs | 72 ++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index cb781ea22..caed95e0c 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -118,6 +118,9 @@ const MIN_PEERS_PROPAGATION: usize = 4; const MAX_PEERS_PROPAGATION: usize = 128; const MAX_PEER_LAG_PROPAGATION: BlockNumber = 20; const SUBCHAIN_SIZE: usize = 64; +const MAX_ROUND_PARENTS: usize = 32; +const MAX_NEW_HASHES: usize = 64; +const MAX_TX_TO_IMPORT: usize = 512; const STATUS_PACKET: u8 = 0x00; const NEW_BLOCK_HASHES_PACKET: u8 = 0x01; @@ -238,6 +241,8 @@ pub struct ChainSync { _max_download_ahead_blocks: usize, /// Number of blocks imported this round imported_this_round: Option, + /// Block parents imported this round (hash, parent) + round_parents: VecDeque<(H256, H256)>, /// Network ID network_id: U256, } @@ -260,6 +265,7 @@ impl ChainSync { syncing_difficulty: U256::from(0u64), last_sent_block_number: 0, imported_this_round: None, + round_parents: VecDeque::new(), _max_download_ahead_blocks: max(MAX_HEADERS_TO_REQUEST, config.max_download_ahead_blocks), network_id: config.network_id, }; @@ -281,11 +287,9 @@ impl ChainSync { num_peers: self.peers.len(), num_active_peers: self.peers.values().filter(|p| p.asking != PeerAsking::Nothing).count(), mem_used: - // TODO: https://github.com/servo/heapsize/pull/50 - //+ self.downloading_bodies.heap_size_of_children() - //+ self.downloading_headers.heap_size_of_children() self.blocks.heap_size() - + self.peers.heap_size_of_children(), + + self.peers.heap_size_of_children() + + self.round_parents.heap_size_of_children(), } } @@ -589,7 +593,7 @@ impl ChainSync { return Ok(()); } trace!(target: "sync", "{} -> NewHashes ({} entries)", peer_id, r.item_count()); - let hashes = r.iter().map(|item| (item.val_at::(0), item.val_at::(1))); + let hashes = r.iter().take(MAX_NEW_HASHES).map(|item| (item.val_at::(0), item.val_at::(1))); let mut max_height: BlockNumber = 0; let mut new_hashes = Vec::new(); for (rh, rd) in hashes { @@ -729,20 +733,28 @@ impl ChainSync { trace!(target: "sync", "Starting round (last imported count = {:?}, block = {:?}", self.imported_this_round, self.last_imported_block); // Check if need to retract to find the common block. The problem is that the peers still return headers by hash even // from the non-canonical part of the tree. So we also retract if nothing has been imported last round. - if self.imported_this_round.is_some() && self.imported_this_round.unwrap() == 0 && self.last_imported_block > 0 { - match io.chain().block_hash(BlockID::Number(self.last_imported_block - 1)) { - Some(h) => { + match self.imported_this_round { + Some(n) if n == 0 && self.last_imported_block > 0 => { + // nothing was imported last round, step back to a previous block + // search parent in last round known parents first + if let Some(&(_, p)) = self.round_parents.iter().find(|&&(h, _)| h == self.last_imported_hash) { self.last_imported_block -= 1; - self.last_imported_hash = h; - trace!(target: "sync", "Searching common header {} ({})", self.last_imported_block, self.last_imported_hash); + self.last_imported_hash = p.clone(); + trace!(target: "sync", "Searching common header from the last round {} ({})", self.last_imported_block, self.last_imported_hash); + } else { + match io.chain().block_hash(BlockID::Number(self.last_imported_block - 1)) { + Some(h) => { + self.last_imported_block -= 1; + self.last_imported_hash = h; + trace!(target: "sync", "Searching common header in the blockchain {} ({})", self.last_imported_block, self.last_imported_hash); + } + None => { + debug!(target: "sync", "Could not revert to previous block, last: {} ({})", self.last_imported_block, self.last_imported_hash); + } + } } - None => { - // TODO: get hash by number from the block queue - trace!(target: "sync", "Could not revert to previous block, last: {} ({})", self.last_imported_block, self.last_imported_hash); - // just wait for full sync to complete - self.pause_sync(); - } - } + }, + _ => (), } self.imported_this_round = None; } @@ -789,6 +801,15 @@ impl ChainSync { peer.asking_blocks.clear(); } + fn block_imported(&mut self, hash: &H256, number: BlockNumber, parent: &H256) { + self.last_imported_block = number; + self.last_imported_hash = hash.clone(); + self.round_parents.push_back((hash.clone(), parent.clone())); + if self.round_parents.len() > MAX_ROUND_PARENTS { + self.round_parents.pop_front(); + } + } + /// 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) { let mut restart = false; @@ -796,8 +817,10 @@ impl ChainSync { let blocks = self.blocks.drain(); let count = blocks.len(); for block in blocks { - let number = BlockView::new(&block).header_view().number(); - let h = BlockView::new(&block).header_view().sha3(); + let (h, number, parent) = { + let header = BlockView::new(&block).header_view(); + (header.sha3(), header.number(), header.parent_hash()) + }; // Perform basic block verification if !Block::is_good(&block) { @@ -808,20 +831,17 @@ impl ChainSync { match io.chain().import_block(block) { Err(Error::Import(ImportError::AlreadyInChain)) => { - self.last_imported_block = number; - self.last_imported_hash = h.clone(); trace!(target: "sync", "Block already in chain {:?}", h); + self.block_imported(&h, number, &parent); }, Err(Error::Import(ImportError::AlreadyQueued)) => { - self.last_imported_block = number; - self.last_imported_hash = h.clone(); trace!(target: "sync", "Block already queued {:?}", h); + self.block_imported(&h, number, &parent); }, Ok(_) => { trace!(target: "sync", "Block queued {:?}", h); - self.last_imported_block = number; - self.last_imported_hash = h.clone(); imported.insert(h.clone()); + self.block_imported(&h, number, &parent); }, Err(Error::Block(BlockError::UnknownParent(_))) if self.state == SyncState::NewBlocks => { trace!(target: "sync", "Unknown new block parent, restarting sync"); @@ -921,7 +941,7 @@ impl ChainSync { trace!(target: "sync", "{} -> Transactions ({} entries)", peer_id, item_count); let mut transactions = Vec::with_capacity(item_count); - for i in 0..item_count { + for i in 0 .. min(item_count, MAX_TX_TO_IMPORT) { let tx: SignedTransaction = try!(r.val_at(i)); transactions.push(tx); } From 4b3f23f0accb844c1a746e94fc829fdc72cf8e27 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 20 Jun 2016 01:06:00 +0200 Subject: [PATCH 092/239] Fixed network service dispose --- parity/io_handler.rs | 14 +++++++++----- parity/main.rs | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/parity/io_handler.rs b/parity/io_handler.rs index ee6d6130f..a94582b1d 100644 --- a/parity/io_handler.rs +++ b/parity/io_handler.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::sync::Arc; +use std::sync::{Arc, Weak}; use ethcore::client::Client; use ethcore::service::{NetSyncMessage, SyncMessage}; use ethsync::EthSync; @@ -30,7 +30,7 @@ pub struct ClientIoHandler { pub sync: Arc, pub accounts: Arc, pub info: Informant, - pub network: Arc>, + pub network: Weak>, } impl IoHandler for ClientIoHandler { @@ -49,12 +49,16 @@ impl IoHandler for ClientIoHandler { match *message { NetworkIoMessage::User(SyncMessage::StartNetwork) => { info!("Starting network"); - self.network.start().unwrap_or_else(|e| warn!("Error starting network: {:?}", e)); - EthSync::register(&*self.network, self.sync.clone()).unwrap_or_else(|e| warn!("Error registering eth protocol handler: {}", e)); + if let Some(network) = self.network.upgrade() { + network.start().unwrap_or_else(|e| warn!("Error starting network: {:?}", e)); + EthSync::register(&*network, self.sync.clone()).unwrap_or_else(|e| warn!("Error registering eth protocol handler: {}", e)); + } }, NetworkIoMessage::User(SyncMessage::StopNetwork) => { info!("Stopping network"); - self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e)); + if let Some(network) = self.network.upgrade() { + network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e)); + } }, _ => {/* Ignore other messages */}, } diff --git a/parity/main.rs b/parity/main.rs index 9680f8a03..5bc5f1b48 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -272,7 +272,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) info: Informant::new(conf.have_color()), sync: sync.clone(), accounts: account_service.clone(), - network: service.network(), + network: Arc::downgrade(&service.network()), }); service.register_io_handler(io_handler).expect("Error registering IO handler"); From 6d435d038f125069eed586ed30d42b880c7f0684 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 20 Jun 2016 01:26:40 +0200 Subject: [PATCH 093/239] Fixed empty block body composition --- sync/src/blocks.rs | 2 +- sync/src/chain.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sync/src/blocks.rs b/sync/src/blocks.rs index c1c6becde..feb9b0066 100644 --- a/sync/src/blocks.rs +++ b/sync/src/blocks.rs @@ -265,7 +265,7 @@ impl BlockCollection { if header_id.transactions_root == rlp::SHA3_NULL_RLP && header_id.uncles == rlp::SHA3_EMPTY_LIST_RLP { // empty body, just mark as downloaded let mut body_stream = RlpStream::new_list(2); - body_stream.append_raw(&rlp::NULL_RLP, 1); + body_stream.append_raw(&rlp::EMPTY_LIST_RLP, 1); body_stream.append_raw(&rlp::EMPTY_LIST_RLP, 1); block.body = Some(body_stream.out()); } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index caed95e0c..767c84786 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -361,12 +361,12 @@ impl ChainSync { trace!(target: "sync", "New peer {} (protocol: {}, network: {:?}, difficulty: {:?}, latest:{}, genesis:{})", peer_id, peer.protocol_version, peer.network_id, peer.difficulty, peer.latest_hash, peer.genesis); if io.is_expired() { - trace!("Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id)); + trace!(target: "sync", "Status packet from expired session {}:{}", peer_id, io.peer_info(peer_id)); return Ok(()); } if self.peers.contains_key(&peer_id) { - warn!("Unexpected status packet from {}:{}", peer_id, io.peer_info(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(); @@ -1243,7 +1243,7 @@ impl ChainSync { /// propagates latest block to lagging peers fn propagate_blocks(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo) -> usize { let lucky_peers = self.select_lagging_peers(chain_info, io); - trace!("Sending NewBlocks to {:?}", lucky_peers); + trace!(target: "sync", "Sending NewBlocks to {:?}", lucky_peers); let mut sent = 0; for (peer_id, _) in lucky_peers { let rlp = ChainSync::create_latest_block_rlp(io.chain()); @@ -1258,7 +1258,7 @@ impl ChainSync { /// propagates new known hashes to all peers fn propagate_new_hashes(&mut self, chain_info: &BlockChainInfo, io: &mut SyncIo) -> usize { let lucky_peers = self.select_lagging_peers(chain_info, io); - trace!("Sending NewHashes to {:?}", lucky_peers); + trace!(target: "sync", "Sending NewHashes to {:?}", lucky_peers); let mut sent = 0; let last_parent = HeaderView::new(&io.chain().block_header(BlockID::Hash(chain_info.best_block_hash.clone())).unwrap()).parent_hash(); for (peer_id, peer_number) in lucky_peers { From 074311d95bc05c42986178be63534e09e2e0e932 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 20 Jun 2016 10:02:02 +0200 Subject: [PATCH 094/239] Updated ethkey to the latest version --- ethkey/README.md | 26 ++++++++++++++--- ethkey/src/bin/ethkey.rs | 36 ++++++++++++++++++----- ethkey/src/keypair.rs | 12 +++++--- ethkey/src/lib.rs | 4 +-- ethkey/src/signature.rs | 43 ++++++++++++++++++++++++---- ethstore/src/account/safe_account.rs | 6 ++-- ethstore/src/ethkey.rs | 2 +- 7 files changed, 103 insertions(+), 26 deletions(-) diff --git a/ethkey/README.md b/ethkey/README.md index 1a588cd48..726047481 100644 --- a/ethkey/README.md +++ b/ethkey/README.md @@ -21,7 +21,8 @@ Usage: ethkey generate prefix [options] ethkey generate brain [options] ethkey sign - ethkey verify + ethkey verify public + ethkey verify address
ethkey [-h | --help] Options: @@ -126,15 +127,32 @@ c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8 -- -#### `verify ` +#### `verify public ` *Verify the signature.* -- `` - ethereum public, 64 bytes long +- `` - ethereum public, 64 bytes long - `` - message signature, 65 bytes long - `` - message, 32 bytes long ``` -ethkey verify 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124 c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200 bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987 +ethkey verify public 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124 c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200 bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987 +``` + +``` +true +``` + +-- + +#### `verify address
` +*Verify the signature.* + +- `
` - ethereum address, 20 bytes long +- `` - message signature, 65 bytes long +- `` - message, 32 bytes long + +``` +ethkey verify address 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124 c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200 bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987 ``` ``` diff --git a/ethkey/src/bin/ethkey.rs b/ethkey/src/bin/ethkey.rs index a7661c42f..9707ba4b2 100644 --- a/ethkey/src/bin/ethkey.rs +++ b/ethkey/src/bin/ethkey.rs @@ -7,7 +7,7 @@ use std::{env, fmt, process}; use std::num::ParseIntError; use docopt::Docopt; use rustc_serialize::hex::{FromHex, FromHexError}; -use ethkey::{KeyPair, Random, Brain, Prefix, Error as EthkeyError, Generator, Secret, Message, Public, Signature, sign, verify}; +use ethkey::{KeyPair, Random, Brain, Prefix, Error as EthkeyError, Generator, Secret, Message, Public, Signature, Address, sign, verify_public, verify_address}; pub const USAGE: &'static str = r#" Ethereum keys generator. @@ -19,7 +19,8 @@ Usage: ethkey generate prefix [options] ethkey generate brain [options] ethkey sign - ethkey verify + ethkey verify public + ethkey verify address
ethkey [-h | --help] Options: @@ -47,12 +48,15 @@ struct Args { cmd_brain: bool, cmd_sign: bool, cmd_verify: bool, + cmd_public: bool, + cmd_address: bool, arg_prefix: String, arg_iterations: String, arg_seed: String, arg_secret: String, arg_message: String, arg_public: String, + arg_address: String, arg_signature: String, flag_secret: bool, flag_public: bool, @@ -164,10 +168,17 @@ fn execute(command: I) -> Result where I: IntoIterator>(); + + let expected = "true".to_owned(); + assert_eq!(execute(command).unwrap(), expected); + } + + #[test] + fn verify_valid_address() { + let command = vec!["ethkey", "verify", "address", "26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987"] .into_iter() .map(Into::into) .collect::>(); @@ -263,7 +285,7 @@ address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned(); #[test] fn verify_invalid() { - let command = vec!["ethkey", "verify", "689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec986"] + let command = vec!["ethkey", "verify", "public", "689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec986"] .into_iter() .map(Into::into) .collect::>(); diff --git a/ethkey/src/keypair.rs b/ethkey/src/keypair.rs index dcfb67460..9d33dcdb3 100644 --- a/ethkey/src/keypair.rs +++ b/ethkey/src/keypair.rs @@ -4,6 +4,13 @@ use rustc_serialize::hex::ToHex; use keccak::Keccak256; use super::{Secret, Public, Address, SECP256K1, Error}; +pub fn public_to_address(public: &Public) -> Address { + let hash = public.keccak256(); + let mut result = Address::default(); + result.copy_from_slice(&hash[12..]); + result +} + /// secp256k1 key pair pub struct KeyPair { secret: Secret, @@ -60,10 +67,7 @@ impl KeyPair { } pub fn address(&self) -> Address { - let hash = self.public.keccak256(); - let mut result = Address::default(); - result.copy_from_slice(&hash[12..]); - result + public_to_address(&self.public) } } diff --git a/ethkey/src/lib.rs b/ethkey/src/lib.rs index 218abbbf3..b03ca544e 100644 --- a/ethkey/src/lib.rs +++ b/ethkey/src/lib.rs @@ -26,8 +26,8 @@ pub trait Generator { pub use self::brain::Brain; pub use self::error::Error; -pub use self::keypair::KeyPair; +pub use self::keypair::{KeyPair, public_to_address}; pub use self::primitive::{Secret, Public, Address, Message}; pub use self::prefix::Prefix; pub use self::random::Random; -pub use self::signature::{sign, verify, Signature}; +pub use self::signature::{sign, verify_public, verify_address, recover, Signature}; diff --git a/ethkey/src/signature.rs b/ethkey/src/signature.rs index f34baa04f..9c3ad2e27 100644 --- a/ethkey/src/signature.rs +++ b/ethkey/src/signature.rs @@ -4,7 +4,7 @@ use std::str::FromStr; use secp256k1::{Message as SecpMessage, RecoverableSignature, RecoveryId, Error as SecpError}; use secp256k1::key::{SecretKey, PublicKey}; use rustc_serialize::hex::{ToHex, FromHex}; -use {Secret, Public, SECP256K1, Error, Message}; +use {Secret, Public, SECP256K1, Error, Message, public_to_address, Address}; #[repr(C)] #[derive(Eq)] @@ -113,7 +113,7 @@ pub fn sign(secret: &Secret, message: &Message) -> Result { Ok(Signature(data_arr)) } -pub fn verify(public: &Public, signature: &Signature, message: &Message) -> Result { +pub fn verify_public(public: &Public, signature: &Signature, message: &Message) -> Result { let context = &SECP256K1; let rsig = try!(RecoverableSignature::from_compact(context, &signature[0..64], try!(RecoveryId::from_i32(signature[64] as i32)))); let sig = rsig.to_standard(context); @@ -132,11 +132,28 @@ pub fn verify(public: &Public, signature: &Signature, message: &Message) -> Resu } } +pub fn verify_address(address: &Address, signature: &Signature, message: &Message) -> Result { + let public = try!(recover(signature, message)); + let recovered_address = public_to_address(&public); + Ok(address == &recovered_address) +} + +pub fn recover(signature: &Signature, message: &Message) -> Result { + let context = &SECP256K1; + let rsig = try!(RecoverableSignature::from_compact(context, &signature[0..64], try!(RecoveryId::from_i32(signature[64] as i32)))); + let pubkey = try!(context.recover(&try!(SecpMessage::from_slice(&message[..])), &rsig)); + let serialized = pubkey.serialize_vec(context, false); + + let mut public = Public::default(); + public.copy_from_slice(&serialized[1..65]); + Ok(public) +} + #[cfg(test)] mod tests { use std::str::FromStr; use {Generator, Random, Message}; - use super::{sign, verify, Signature}; + use super::{sign, verify_public, verify_address, recover, Signature}; #[test] fn signature_to_and_from_str() { @@ -149,10 +166,26 @@ mod tests { } #[test] - fn sign_and_verify() { + fn sign_and_recover_public() { let keypair = Random.generate().unwrap(); let message = Message::default(); let signature = sign(keypair.secret(), &message).unwrap(); - assert!(verify(keypair.public(), &signature, &message).unwrap()); + assert_eq!(keypair.public(), &recover(&signature, &message).unwrap()); + } + + #[test] + fn sign_and_verify_public() { + let keypair = Random.generate().unwrap(); + let message = Message::default(); + let signature = sign(keypair.secret(), &message).unwrap(); + assert!(verify_public(keypair.public(), &signature, &message).unwrap()); + } + + #[test] + fn sign_and_verify_address() { + let keypair = Random.generate().unwrap(); + let message = Message::default(); + let signature = sign(keypair.secret(), &message).unwrap(); + assert!(verify_address(&keypair.address(), &signature, &message).unwrap()); } } diff --git a/ethstore/src/account/safe_account.rs b/ethstore/src/account/safe_account.rs index 934bfd03d..4b52d0397 100644 --- a/ethstore/src/account/safe_account.rs +++ b/ethstore/src/account/safe_account.rs @@ -154,7 +154,7 @@ impl SafeAccount { #[cfg(test)] mod tests { - use ethkey::{Generator, Random, verify, Message}; + use ethkey::{Generator, Random, verify_public, Message}; use super::{Crypto, SafeAccount}; #[test] @@ -174,13 +174,13 @@ mod tests { } #[test] - fn sign_and_verify() { + fn sign_and_verify_public() { let keypair = Random.generate().unwrap(); let password = "hello world"; let message = Message::default(); let account = SafeAccount::create(&keypair, [0u8; 16], password, 10240); let signature = account.sign(password, &message).unwrap(); - assert!(verify(keypair.public(), &signature, &message).unwrap()); + assert!(verify_public(keypair.public(), &signature, &message).unwrap()); } #[test] diff --git a/ethstore/src/ethkey.rs b/ethstore/src/ethkey.rs index d77fa7a52..2d0609106 100644 --- a/ethstore/src/ethkey.rs +++ b/ethstore/src/ethkey.rs @@ -1,5 +1,5 @@ //! ethkey reexport to make documentation look pretty. -pub use _ethkey::{Address, Message, Signature, Public, Secret, Generator, sign, verify, Error, KeyPair, Random, Prefix}; +pub use _ethkey::*; use json; impl Into for Address { From 03cd1c0494b16a1391e5f8463cd7a2880d0964b2 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 20 Jun 2016 10:06:49 +0200 Subject: [PATCH 095/239] added license headers to ethkey and ethstore --- ethkey/src/bin/ethkey.rs | 16 ++++++++++++++++ ethkey/src/bin/main.rs | 16 ++++++++++++++++ ethkey/src/brain.rs | 16 ++++++++++++++++ ethkey/src/error.rs | 16 ++++++++++++++++ ethkey/src/keccak.rs | 16 ++++++++++++++++ ethkey/src/keypair.rs | 16 ++++++++++++++++ ethkey/src/lib.rs | 16 ++++++++++++++++ ethkey/src/prefix.rs | 16 ++++++++++++++++ ethkey/src/primitive.rs | 16 ++++++++++++++++ ethkey/src/random.rs | 16 ++++++++++++++++ ethkey/src/signature.rs | 16 ++++++++++++++++ ethstore/build.rs | 16 ++++++++++++++++ ethstore/src/account/cipher.rs | 16 ++++++++++++++++ ethstore/src/account/kdf.rs | 16 ++++++++++++++++ ethstore/src/account/mod.rs | 16 ++++++++++++++++ ethstore/src/account/safe_account.rs | 16 ++++++++++++++++ ethstore/src/account/version.rs | 16 ++++++++++++++++ ethstore/src/bin/ethstore.rs | 16 ++++++++++++++++ ethstore/src/bin/main.rs | 16 ++++++++++++++++ ethstore/src/crypto.rs | 16 ++++++++++++++++ ethstore/src/dir/disk.rs | 16 ++++++++++++++++ ethstore/src/dir/geth.rs | 16 ++++++++++++++++ ethstore/src/dir/mod.rs | 16 ++++++++++++++++ ethstore/src/dir/parity.rs | 16 ++++++++++++++++ ethstore/src/error.rs | 16 ++++++++++++++++ ethstore/src/ethkey.rs | 16 ++++++++++++++++ ethstore/src/ethstore.rs | 16 ++++++++++++++++ ethstore/src/import.rs | 16 ++++++++++++++++ ethstore/src/json/cipher.rs | 16 ++++++++++++++++ ethstore/src/json/crypto.rs | 16 ++++++++++++++++ ethstore/src/json/error.rs | 16 ++++++++++++++++ ethstore/src/json/hash.rs | 16 ++++++++++++++++ ethstore/src/json/id.rs | 16 ++++++++++++++++ ethstore/src/json/kdf.rs | 16 ++++++++++++++++ ethstore/src/json/key_file.rs | 16 ++++++++++++++++ ethstore/src/json/mod.rs | 16 ++++++++++++++++ ethstore/src/json/version.rs | 16 ++++++++++++++++ ethstore/src/lib.rs | 16 ++++++++++++++++ ethstore/src/random.rs | 16 ++++++++++++++++ ethstore/src/secret_store.rs | 16 ++++++++++++++++ ethstore/tests/api.rs | 16 ++++++++++++++++ ethstore/tests/cli.rs | 16 ++++++++++++++++ ethstore/tests/util/mod.rs | 16 ++++++++++++++++ ethstore/tests/util/transient_dir.rs | 16 ++++++++++++++++ 44 files changed, 704 insertions(+) diff --git a/ethkey/src/bin/ethkey.rs b/ethkey/src/bin/ethkey.rs index 9707ba4b2..c7a7939fd 100644 --- a/ethkey/src/bin/ethkey.rs +++ b/ethkey/src/bin/ethkey.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + extern crate docopt; extern crate rustc_serialize; extern crate ethkey; diff --git a/ethkey/src/bin/main.rs b/ethkey/src/bin/main.rs index 404136b62..7c7512a97 100644 --- a/ethkey/src/bin/main.rs +++ b/ethkey/src/bin/main.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + #[cfg(feature = "cli")] include!("ethkey.rs"); diff --git a/ethkey/src/brain.rs b/ethkey/src/brain.rs index c7fffe3bf..f7f9322e0 100644 --- a/ethkey/src/brain.rs +++ b/ethkey/src/brain.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 keccak::Keccak256; use super::{KeyPair, Error, Generator, Secret}; diff --git a/ethkey/src/error.rs b/ethkey/src/error.rs index f75f264f5..328e85856 100644 --- a/ethkey/src/error.rs +++ b/ethkey/src/error.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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; #[derive(Debug)] diff --git a/ethkey/src/keccak.rs b/ethkey/src/keccak.rs index 3423f19fe..18b31a868 100644 --- a/ethkey/src/keccak.rs +++ b/ethkey/src/keccak.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 tiny_keccak::Keccak; pub trait Keccak256 { diff --git a/ethkey/src/keypair.rs b/ethkey/src/keypair.rs index 9d33dcdb3..fa7c1a85e 100644 --- a/ethkey/src/keypair.rs +++ b/ethkey/src/keypair.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 secp256k1::key; use rustc_serialize::hex::ToHex; diff --git a/ethkey/src/lib.rs b/ethkey/src/lib.rs index b03ca544e..045bbb520 100644 --- a/ethkey/src/lib.rs +++ b/ethkey/src/lib.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + extern crate rand; #[macro_use] extern crate lazy_static; diff --git a/ethkey/src/prefix.rs b/ethkey/src/prefix.rs index 8d7f18cfa..ad5e02c4a 100644 --- a/ethkey/src/prefix.rs +++ b/ethkey/src/prefix.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 super::{Random, Generator, KeyPair, Error}; /// Tries to find keypair with address starting with given prefix. diff --git a/ethkey/src/primitive.rs b/ethkey/src/primitive.rs index 11a614ded..761a3000f 100644 --- a/ethkey/src/primitive.rs +++ b/ethkey/src/primitive.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::ops::{Deref, DerefMut}; use std::{fmt, cmp, hash}; use std::str::FromStr; diff --git a/ethkey/src/random.rs b/ethkey/src/random.rs index aa3abb838..ea4cdaec6 100644 --- a/ethkey/src/random.rs +++ b/ethkey/src/random.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 rand::os::OsRng; use super::{Generator, KeyPair, Error, SECP256K1}; diff --git a/ethkey/src/signature.rs b/ethkey/src/signature.rs index 9c3ad2e27..616db7bc9 100644 --- a/ethkey/src/signature.rs +++ b/ethkey/src/signature.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::ops::{Deref, DerefMut}; use std::{mem, fmt}; use std::str::FromStr; diff --git a/ethstore/build.rs b/ethstore/build.rs index 9113e596d..1c4e05f84 100644 --- a/ethstore/build.rs +++ b/ethstore/build.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + #[cfg(not(feature = "serde_macros"))] mod inner { extern crate syntex; diff --git a/ethstore/src/account/cipher.rs b/ethstore/src/account/cipher.rs index 55b3c1de8..1b9d49b26 100644 --- a/ethstore/src/account/cipher.rs +++ b/ethstore/src/account/cipher.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 json; #[derive(Debug, PartialEq, Clone)] diff --git a/ethstore/src/account/kdf.rs b/ethstore/src/account/kdf.rs index f8d67dac8..0cabce625 100644 --- a/ethstore/src/account/kdf.rs +++ b/ethstore/src/account/kdf.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 json; #[derive(Debug, PartialEq, Clone)] diff --git a/ethstore/src/account/mod.rs b/ethstore/src/account/mod.rs index b97526991..b4c3e1113 100644 --- a/ethstore/src/account/mod.rs +++ b/ethstore/src/account/mod.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + mod cipher; mod kdf; mod safe_account; diff --git a/ethstore/src/account/safe_account.rs b/ethstore/src/account/safe_account.rs index 4b52d0397..eba2c41d3 100644 --- a/ethstore/src/account/safe_account.rs +++ b/ethstore/src/account/safe_account.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::ops::{Deref, DerefMut}; use ethkey::{KeyPair, sign, Address, Secret, Signature, Message}; use {json, Error, crypto}; diff --git a/ethstore/src/account/version.rs b/ethstore/src/account/version.rs index 570ebd981..465ce4e1b 100644 --- a/ethstore/src/account/version.rs +++ b/ethstore/src/account/version.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 json; #[derive(Debug, PartialEq, Clone)] diff --git a/ethstore/src/bin/ethstore.rs b/ethstore/src/bin/ethstore.rs index e53acfeb2..6020679d4 100644 --- a/ethstore/src/bin/ethstore.rs +++ b/ethstore/src/bin/ethstore.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + extern crate rustc_serialize; extern crate docopt; extern crate ethstore; diff --git a/ethstore/src/bin/main.rs b/ethstore/src/bin/main.rs index 8bed9a946..eee1fa39c 100644 --- a/ethstore/src/bin/main.rs +++ b/ethstore/src/bin/main.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + #[cfg(feature = "cli")] include!("ethstore.rs"); diff --git a/ethstore/src/crypto.rs b/ethstore/src/crypto.rs index 05ebc4042..2858808d7 100644 --- a/ethstore/src/crypto.rs +++ b/ethstore/src/crypto.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 tiny_keccak::Keccak; use rcrypto::pbkdf2::pbkdf2; use rcrypto::scrypt::{scrypt, ScryptParams}; diff --git a/ethstore/src/dir/disk.rs b/ethstore/src/dir/disk.rs index 2f6f39657..f63577361 100644 --- a/ethstore/src/dir/disk.rs +++ b/ethstore/src/dir/disk.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::{fs, ffi, io}; use std::path::{PathBuf, Path}; use std::collections::HashMap; diff --git a/ethstore/src/dir/geth.rs b/ethstore/src/dir/geth.rs index 9f8850aad..29c9f2dc3 100644 --- a/ethstore/src/dir/geth.rs +++ b/ethstore/src/dir/geth.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::env; use std::path::PathBuf; use ethkey::Address; diff --git a/ethstore/src/dir/mod.rs b/ethstore/src/dir/mod.rs index a5537b56c..68280f596 100644 --- a/ethstore/src/dir/mod.rs +++ b/ethstore/src/dir/mod.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 ethkey::Address; use {SafeAccount, Error}; diff --git a/ethstore/src/dir/parity.rs b/ethstore/src/dir/parity.rs index 6f11d5ae6..c1b812fe0 100644 --- a/ethstore/src/dir/parity.rs +++ b/ethstore/src/dir/parity.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::env; use std::path::PathBuf; use ethkey::Address; diff --git a/ethstore/src/error.rs b/ethstore/src/error.rs index 537bfe008..8066fe10c 100644 --- a/ethstore/src/error.rs +++ b/ethstore/src/error.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::io::Error as IoError; use ethkey::Error as EthKeyError; diff --git a/ethstore/src/ethkey.rs b/ethstore/src/ethkey.rs index 2d0609106..eba877397 100644 --- a/ethstore/src/ethkey.rs +++ b/ethstore/src/ethkey.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + //! ethkey reexport to make documentation look pretty. pub use _ethkey::*; use json; diff --git a/ethstore/src/ethstore.rs b/ethstore/src/ethstore.rs index 103ff179d..9ef84ebc2 100644 --- a/ethstore/src/ethstore.rs +++ b/ethstore/src/ethstore.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::collections::BTreeMap; use std::sync::RwLock; use ethkey::KeyPair; diff --git a/ethstore/src/import.rs b/ethstore/src/import.rs index 94bb37925..79785ae0f 100644 --- a/ethstore/src/import.rs +++ b/ethstore/src/import.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 ethkey::Address; use dir::KeyDirectory; use Error; diff --git a/ethstore/src/json/cipher.rs b/ethstore/src/json/cipher.rs index 22fed9ee0..119024437 100644 --- a/ethstore/src/json/cipher.rs +++ b/ethstore/src/json/cipher.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError}; use serde::de::Visitor; use super::{Error, H128}; diff --git a/ethstore/src/json/crypto.rs b/ethstore/src/json/crypto.rs index c11078e71..9ff8c1e44 100644 --- a/ethstore/src/json/crypto.rs +++ b/ethstore/src/json/crypto.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 serde::{Deserialize, Deserializer, Serialize, Serializer, Error}; use serde::de::{Visitor, MapVisitor}; use serde::ser; diff --git a/ethstore/src/json/error.rs b/ethstore/src/json/error.rs index 6700ee103..5e077cfad 100644 --- a/ethstore/src/json/error.rs +++ b/ethstore/src/json/error.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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; #[derive(Debug, PartialEq)] diff --git a/ethstore/src/json/hash.rs b/ethstore/src/json/hash.rs index 32d8a974e..f0fb91e7a 100644 --- a/ethstore/src/json/hash.rs +++ b/ethstore/src/json/hash.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::str::FromStr; use rustc_serialize::hex::{FromHex, ToHex}; use serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError}; diff --git a/ethstore/src/json/id.rs b/ethstore/src/json/id.rs index e6020ddcb..2e896458c 100644 --- a/ethstore/src/json/id.rs +++ b/ethstore/src/json/id.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + //! Universaly unique identifier. use std::str::FromStr; use std::fmt; diff --git a/ethstore/src/json/kdf.rs b/ethstore/src/json/kdf.rs index c00fc8bd3..676df1f95 100644 --- a/ethstore/src/json/kdf.rs +++ b/ethstore/src/json/kdf.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError}; use serde::de::Visitor; use serde_json::{Value, value}; diff --git a/ethstore/src/json/key_file.rs b/ethstore/src/json/key_file.rs index eae5e58ae..5d87745ef 100644 --- a/ethstore/src/json/key_file.rs +++ b/ethstore/src/json/key_file.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::io::{Read, Write}; use serde::{Deserialize, Deserializer, Error}; use serde::de::{Visitor, MapVisitor}; diff --git a/ethstore/src/json/mod.rs b/ethstore/src/json/mod.rs index dd069332b..208d474df 100644 --- a/ethstore/src/json/mod.rs +++ b/ethstore/src/json/mod.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + //! Contract interface specification. #[cfg(feature = "serde_macros")] diff --git a/ethstore/src/json/version.rs b/ethstore/src/json/version.rs index 3b4105a79..f394f61c2 100644 --- a/ethstore/src/json/version.rs +++ b/ethstore/src/json/version.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError}; use serde::de::Visitor; use super::Error; diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs index 62932fc16..19f1c4806 100644 --- a/ethstore/src/lib.rs +++ b/ethstore/src/lib.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + #![cfg_attr(feature="nightly", feature(custom_derive, plugin))] #![cfg_attr(feature="nightly", plugin(serde_macros))] diff --git a/ethstore/src/random.rs b/ethstore/src/random.rs index 2693d4fcf..e0a7f52c7 100644 --- a/ethstore/src/random.rs +++ b/ethstore/src/random.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 rand::{Rng, OsRng}; pub trait Random { diff --git a/ethstore/src/secret_store.rs b/ethstore/src/secret_store.rs index 620b8d9b9..5dab50ba7 100644 --- a/ethstore/src/secret_store.rs +++ b/ethstore/src/secret_store.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 ethkey::{Address, Message, Signature, Secret}; use Error; diff --git a/ethstore/tests/api.rs b/ethstore/tests/api.rs index a29b143db..037c5c46c 100644 --- a/ethstore/tests/api.rs +++ b/ethstore/tests/api.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + extern crate rand; extern crate ethstore; diff --git a/ethstore/tests/cli.rs b/ethstore/tests/cli.rs index e69de29bb..d4ebdc448 100644 --- a/ethstore/tests/cli.rs +++ b/ethstore/tests/cli.rs @@ -0,0 +1,16 @@ +// Copyright 2015, 2016 Ethcore (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 . + diff --git a/ethstore/tests/util/mod.rs b/ethstore/tests/util/mod.rs index 03bdb8af1..73c47ee61 100644 --- a/ethstore/tests/util/mod.rs +++ b/ethstore/tests/util/mod.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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 . + mod transient_dir; pub use self::transient_dir::TransientDir; diff --git a/ethstore/tests/util/transient_dir.rs b/ethstore/tests/util/transient_dir.rs index b29a5d775..f4998e124 100644 --- a/ethstore/tests/util/transient_dir.rs +++ b/ethstore/tests/util/transient_dir.rs @@ -1,3 +1,19 @@ +// Copyright 2015, 2016 Ethcore (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::path::PathBuf; use std::{env, fs}; use rand::{Rng, OsRng}; From ca35f116a69935cdbcf1cfe525e3bb10d0cc612a Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 20 Jun 2016 10:13:14 +0200 Subject: [PATCH 096/239] added new libraries: ethkey and ethstore to cov.sh, doc.sh and test.sh --- cov.sh | 6 +++++- doc.sh | 2 ++ test.sh | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cov.sh b/cov.sh index a13db50b9..8de2264c0 100755 --- a/cov.sh +++ b/cov.sh @@ -16,6 +16,8 @@ if ! type kcov > /dev/null; then fi cargo test \ + -p ethkey \ + -p ethstore \ -p ethash \ -p ethcore-util \ -p ethcore \ @@ -28,7 +30,9 @@ cargo test \ rm -rf target/coverage mkdir -p target/coverage -EXCLUDE="~/.multirust,rocksdb,secp256k1,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests" +EXCLUDE="~/.multirust,rocksdb,secp256k1,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests,ethstore/tests" +kcov --exclude-pattern $EXCLUDE --include-pattern src --verify target/coverage target/debug/deps/ethkey-* +kcov --exclude-pattern $EXCLUDE --include-pattern src --verify target/coverage target/debug/deps/ethstore-* kcov --exclude-pattern $EXCLUDE --include-pattern src --verify target/coverage target/debug/deps/ethcore-* kcov --exclude-pattern $EXCLUDE --include-pattern src --verify target/coverage target/debug/deps/ethash-* kcov --exclude-pattern $EXCLUDE --include-pattern src --verify target/coverage target/debug/deps/ethcore_util-* diff --git a/doc.sh b/doc.sh index fb39ef272..41251f7a8 100755 --- a/doc.sh +++ b/doc.sh @@ -2,6 +2,8 @@ # generate documentation only for partiy and ethcore libraries cargo doc --no-deps --verbose \ + -p ethkey \ + -p ethstore \ -p ethash \ -p ethcore-util \ -p ethcore \ diff --git a/test.sh b/test.sh index d89740aba..a62c835e8 100755 --- a/test.sh +++ b/test.sh @@ -2,6 +2,8 @@ # Running Parity Full Test Sute cargo test --features ethcore/json-tests $1 \ + -p ethkey \ + -p ethstore \ -p ethash \ -p ethcore-util \ -p ethcore \ From 91acb22bd4a99da63edcd6f6f93aae311eadae3c Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 20 Jun 2016 10:18:53 +0200 Subject: [PATCH 097/239] updated .travis.yml --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 230e7862f..b7124b2df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,10 +33,10 @@ env: global: # GH_TOKEN - secure: bumJASbZSU8bxJ0EyPUJmu16AiV9EXOpyOj86Jlq/Ty9CfwGqsSXt96uDyE+OUJf34RUFQMsw0nk37/zC4lcn6kqk2wpuH3N/o85Zo/cVZY/NusBWLQqtT5VbYWsV+u2Ua4Tmmsw8yVYQhYwU2ZOejNpflL+Cs9XGgORp1L+/gMRMC2y5Se6ZhwnKPQlRJ8LGsG1dzjQULxzADIt3/zuspNBS8a2urJwlHfGMkvHDoUWCviP/GXoSqw3TZR7FmKyxE19I8n9+iSvm9+oZZquvcgfUxMHn8Gq/b44UbPvjtFOg2yam4xdWXF/RyWCHdc/R9EHorSABeCbefIsm+zcUF3/YQxwpSxM4IZEeH2rTiC7dcrsKw3XsO16xFQz5YI5Bay+CT/wTdMmJd7DdYz7Dyf+pOvcM9WOf/zorxYWSBOMYy0uzbusU2iyIghQ82s7E/Ahg+WARtPgkuTLSB5aL1oCTBKHqQscMr7lo5Ti6RpWLxEdTQMBznc+bMr+6dEtkEcG9zqc6cE9XX+ox3wTU6+HVMfQ1ltCntJ4UKcw3A6INEbw9wgocQa812CIASQ2fE+SCAbz6JxBjIAlFUnD1lUB7S8PdMPwn9plfQgKQ2A5YZqg6FnBdf0rQXIJYxQWKHXj/rBHSUCT0tHACDlzTA+EwWggvkP5AGIxRxm8jhw= - - TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethjson -p ethcore-dapps -p ethcore-signer" + - TARGETS="-p ethkey -p ethstore -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethjson -p ethcore-dapps -p ethcore-signer" - ARCHIVE_SUFFIX="-${TRAVIS_OS_NAME}-${TRAVIS_TAG}" - KCOV_FEATURES="" - - KCOV_CMD="./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov" + - KCOV_CMD="./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests,ethstore/tests target/kcov" - RUN_TESTS="false" - RUN_COVERAGE="false" - RUN_BUILD="false" @@ -65,6 +65,8 @@ after_success: | wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && tar xzf master.tar.gz && mkdir kcov-master/build && cd kcov-master/build && cmake .. && make && make install DESTDIR=../tmp && cd ../.. && cargo test --no-run ${KCOV_FEATURES} ${TARGETS} && + $KCOV_CMD target/debug/deps/ethkey-* && + $KCOV_CMD target/debug/deps/ethstore-* && $KCOV_CMD target/debug/deps/ethcore_util-* && $KCOV_CMD target/debug/deps/ethash-* && $KCOV_CMD target/debug/deps/ethcore-* && From a2f24a0083caae0dcc1e37311dee190a1c347ac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 20 Jun 2016 10:28:38 +0200 Subject: [PATCH 098/239] Removing Default from Miner --- ethcore/src/client/test_client.rs | 3 ++- ethcore/src/json_tests/chain.rs | 2 +- ethcore/src/miner/miner.rs | 33 ++++++++----------------------- ethcore/src/miner/mod.rs | 3 ++- ethcore/src/service.rs | 2 +- ethcore/src/tests/client.rs | 6 +++--- ethcore/src/tests/helpers.rs | 4 ++-- parity/main.rs | 6 +++--- sync/src/lib.rs | 10 ++++++++-- 9 files changed, 30 insertions(+), 39 deletions(-) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index f1a7a6674..b3d0b5bde 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -29,6 +29,7 @@ use blockchain::extras::BlockReceipts; use error::{ImportResult}; use evm::Factory as EvmFactory; use miner::{Miner, MinerService}; +use spec::Spec; use block_queue::BlockQueueInfo; use block::OpenBlock; @@ -105,7 +106,7 @@ impl TestBlockChainClient { execution_result: RwLock::new(None), receipts: RwLock::new(HashMap::new()), queue_size: AtomicUsize::new(0), - miner: Arc::new(Miner::default()), + miner: Arc::new(Miner::with_spec(Spec::new_test())), }; client.add_blocks(1, EachBlockWith::Nothing); // add genesis block client.genesis_hash = client.last_hash.read().unwrap().clone(); diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 2bee5eb2a..a5f5e36c9 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -54,7 +54,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { let temp = RandomTempPath::new(); { - let client = Client::new(ClientConfig::default(), spec, temp.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), spec.clone(), temp.as_path(), Arc::new(Miner::with_spec(spec)), IoChannel::disconnected()).unwrap(); for b in &blockchain.blocks_rlp() { if Block::is_good(&b) { let _ = client.import_block(b.clone()); diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 735ad5cf4..d1d16cf84 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -47,8 +47,9 @@ pub struct Miner { accounts: Option>, } -impl Default for Miner { - fn default() -> Miner { +impl Miner { + /// Creates new instance of miner without accounts, but with given spec. + pub fn with_spec(spec: Spec) -> Miner { Miner { transaction_queue: Mutex::new(TransactionQueue::new()), force_sealing: false, @@ -59,14 +60,12 @@ impl Default for Miner { author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), accounts: None, - spec: Spec::new_test(), + spec: spec, } } -} -impl Miner { /// Creates new instance of miner - pub fn new(force_sealing: bool, spec: Spec) -> Arc { + pub fn new(force_sealing: bool, spec: Spec, accounts: Option>) -> Arc { Arc::new(Miner { transaction_queue: Mutex::new(TransactionQueue::new()), force_sealing: force_sealing, @@ -76,23 +75,7 @@ impl Miner { gas_floor_target: RwLock::new(U256::zero()), author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), - accounts: None, - spec: spec, - }) - } - - /// Creates new instance of miner - pub fn with_accounts(force_sealing: bool, spec: Spec, accounts: Arc) -> Arc { - Arc::new(Miner { - transaction_queue: Mutex::new(TransactionQueue::new()), - force_sealing: force_sealing, - sealing_enabled: AtomicBool::new(force_sealing), - sealing_block_last_request: Mutex::new(0), - sealing_work: Mutex::new(UsingQueue::new(5)), - gas_floor_target: RwLock::new(U256::zero()), - author: RwLock::new(Address::default()), - extra_data: RwLock::new(Vec::new()), - accounts: Some(accounts), + accounts: accounts, spec: spec, }) } @@ -610,7 +593,7 @@ mod tests { fn should_prepare_block_to_seal() { // given let client = TestBlockChainClient::default(); - let miner = Miner::default(); + let miner = Miner::with_spec(Spec::new_test()); // when let sealing_work = miner.map_sealing_work(&client, |_| ()); @@ -622,7 +605,7 @@ mod tests { fn should_still_work_after_a_couple_of_blocks() { // given let client = TestBlockChainClient::default(); - let miner = Miner::default(); + let miner = Miner::with_spec(Spec::new_test()); let res = miner.map_sealing_work(&client, |b| b.block().fields().header.hash()); assert!(res.is_some()); diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 71727f51d..4c3a679ce 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -28,11 +28,12 @@ //! extern crate ethcore; //! use std::env; //! use util::network::{NetworkService, NetworkConfiguration}; +//! use ethcore::ethereum; //! use ethcore::client::{Client, ClientConfig}; //! use ethcore::miner::{Miner, MinerService}; //! //! fn main() { -//! let miner: Miner = Miner::default(); +//! let miner: Miner = Miner::with_spec(ethereum::new_frontier()); //! // get status //! assert_eq!(miner.status().transactions_in_pending_queue, 0); //! diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index d9040113f..73f7423b0 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -156,7 +156,7 @@ mod tests { fn it_can_be_started() { let spec = get_test_spec(); let temp_path = RandomTempPath::new(); - let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_local(), &temp_path.as_path(), Arc::new(Miner::default()), false); + let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_local(), &temp_path.as_path(), Arc::new(Miner::with_spec(spec)), false); assert!(service.is_ok()); } } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index f2ab62840..98988e754 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -24,7 +24,7 @@ use miner::Miner; #[test] fn imports_from_empty() { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap(); client.import_verified_blocks(&IoChannel::disconnected()); client.flush_queue(); } @@ -42,7 +42,7 @@ fn returns_state_root_basic() { #[test] fn imports_good_block() { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap(); let good_block = get_good_dummy_block(); if let Err(_) = client.import_block(good_block) { panic!("error importing block being good by definition"); @@ -57,7 +57,7 @@ fn imports_good_block() { #[test] fn query_none_block() { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap(); let non_existant = client.block_header(BlockID::Number(188)); assert!(non_existant.is_none()); diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 48ca14bbf..84e3a0d26 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -151,7 +151,7 @@ pub fn generate_dummy_client_with_spec_and_data(get_test_spec: F, block_numbe let dir = RandomTempPath::new(); let test_spec = get_test_spec(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap(); let test_engine = &test_spec.engine; let mut db_result = get_temp_journal_db(); @@ -249,7 +249,7 @@ pub fn push_blocks_to_client(client: &Arc, timestamp_salt: u64, starting pub fn get_test_client_with_blocks(blocks: Vec) -> GuardedTempResult> { let dir = RandomTempPath::new(); - let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::default()), IoChannel::disconnected()).unwrap(); + let client = Client::new(ClientConfig::default(), get_test_spec(), dir.as_path(), Arc::new(Miner::with_spec(get_test_spec())), IoChannel::disconnected()).unwrap(); for block in &blocks { if let Err(_) = client.import_block(block.clone()) { panic!("panic importing block which is well-formed"); diff --git a/parity/main.rs b/parity/main.rs index 9680f8a03..e0465c1c6 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -190,7 +190,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) let account_service = Arc::new(conf.account_service()); // Miner - let miner = Miner::with_accounts(conf.args.flag_force_sealing, conf.spec(), account_service.clone()); + let miner = Miner::new(conf.args.flag_force_sealing, conf.spec(), Some(account_service.clone())); miner.set_author(conf.author()); miner.set_gas_floor_target(conf.gas_floor_target()); miner.set_extra_data(conf.extra_data()); @@ -317,7 +317,7 @@ fn execute_export(conf: Configuration) { // Build client let service = ClientService::start( - client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), false + client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::with_spec(conf.spec())), false ).unwrap_or_else(|e| die_with_error("Client", e)); panic_handler.forward_from(&service); @@ -388,7 +388,7 @@ fn execute_import(conf: Configuration) { // Build client let service = ClientService::start( - client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), false + client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::with_spec(conf.spec())), false ).unwrap_or_else(|e| die_with_error("Client", e)); panic_handler.forward_from(&service); diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 86f70ff0a..3a12b3880 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -44,8 +44,14 @@ //! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap(); //! service.start().unwrap(); //! let dir = env::temp_dir(); -//! let client = Client::new(ClientConfig::default(), ethereum::new_frontier(), &dir, Arc::new(Miner::default()), service.io().channel()).unwrap(); -//! let miner = Miner::new(false, ethereum::new_frontier()); +//! let client = Client::new( +//! ClientConfig::default(), +//! ethereum::new_frontier(), +//! &dir, +//! Arc::new(Miner::new(false, ethereum::new_frontier(), None)), +//! service.io().channel() +//! ).unwrap(); +//! let miner = Miner::new(false, ethereum::new_frontier(), None); //! let sync = EthSync::new(SyncConfig::default(), client); //! EthSync::register(&mut service, sync); //! } From d0b2df07db69026c9b07be4e1e2c366ceba69c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 20 Jun 2016 10:32:52 +0200 Subject: [PATCH 099/239] Removing priority on local transactions --- ethcore/src/miner/transaction_queue.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 98aa492d1..385b2e473 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -167,11 +167,6 @@ impl PartialOrd for TransactionOrder { impl Ord for TransactionOrder { fn cmp(&self, b: &TransactionOrder) -> Ordering { - // Local transactions should always have priority - if self.origin != b.origin { - return self.origin.cmp(&b.origin); - } - // First check nonce_height if self.nonce_height != b.nonce_height { return self.nonce_height.cmp(&b.nonce_height); @@ -1087,7 +1082,7 @@ mod test { } #[test] - fn should_prioritize_local_transactions() { + fn should_not_prioritize_local_transactions() { // given let mut txq = TransactionQueue::new(); let (tx, tx2) = new_txs(U256::from(1)); @@ -1098,8 +1093,8 @@ mod test { // then let top = txq.top_transactions(); - assert_eq!(top[0], tx2); - assert_eq!(top[1], tx); + assert_eq!(top[0], tx); + assert_eq!(top[1], tx2); assert_eq!(top.len(), 2); } From 1dd87a39f556f79602aaa7ce45407187fdfc690b Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 20 Jun 2016 10:44:15 +0200 Subject: [PATCH 100/239] Fixed tests --- ethcore/src/client/test_client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index f1a7a6674..a9f7f6300 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -187,7 +187,7 @@ impl TestBlockChainClient { txs.append(&signed_tx); txs.out() }, - _ => rlp::NULL_RLP.to_vec() + _ => rlp::EMPTY_LIST_RLP.to_vec() }; let mut rlp = RlpStream::new_list(3); From 7393de94f7efd87e76ed3e6fcb39f1efe6fba334 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 20 Jun 2016 11:02:31 +0200 Subject: [PATCH 101/239] docker uses rustup, fixes #1337 --- docker/ubuntu-arm/Dockerfile | 14 +++++++++----- docker/ubuntu-dev/Dockerfile | 8 ++++---- docker/ubuntu-jit/Dockerfile | 8 ++++---- docker/ubuntu/Dockerfile | 8 ++++---- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/docker/ubuntu-arm/Dockerfile b/docker/ubuntu-arm/Dockerfile index 9678912cb..fd77f182e 100644 --- a/docker/ubuntu-arm/Dockerfile +++ b/docker/ubuntu-arm/Dockerfile @@ -9,18 +9,22 @@ RUN apt-get -y update && \ && \ apt-get clean -# install multirust -RUN curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh -s -- --yes +# install rustup +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y + +# rustup directory +ENV PATH /root/.cargo/bin:$PATH + ENV RUST_TARGETS="arm-unknown-linux-gnueabihf" # multirust add arm--linux-gnuabhf toolchain -RUN multirust add-target stable arm-unknown-linux-gnueabihf +RUN rustup target add stable arm-unknown-linux-gnueabihf # show backtraces ENV RUST_BACKTRACE 1 # set compilers -ENV CXX arm-linux-gnueabihf-g++ -ENV CC arm-linux-gnueabihf-gcc +ENV CXX arm-linux-gnueabihf-g++ +ENV CC arm-linux-gnueabihf-gcc # build parity RUN git clone https://github.com/ethcore/parity && \ cd parity && \ diff --git a/docker/ubuntu-dev/Dockerfile b/docker/ubuntu-dev/Dockerfile index 05e8dfe8f..72b4bb08e 100644 --- a/docker/ubuntu-dev/Dockerfile +++ b/docker/ubuntu-dev/Dockerfile @@ -27,11 +27,11 @@ RUN git clone https://github.com/debris/evmjit && \ mkdir build && cd build && \ cmake .. && make && make install && cd -# install multirust -RUN curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh -s -- --yes +# install rustup +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y -# export rust LIBRARY_PATH -ENV LIBRARY_PATH /usr/local/lib +# rustup directory +ENV PATH /root/.cargo/bin:$PATH # show backtraces ENV RUST_BACKTRACE 1 diff --git a/docker/ubuntu-jit/Dockerfile b/docker/ubuntu-jit/Dockerfile index 138882d2b..37ef90d4e 100644 --- a/docker/ubuntu-jit/Dockerfile +++ b/docker/ubuntu-jit/Dockerfile @@ -27,11 +27,11 @@ RUN git clone https://github.com/debris/evmjit && \ mkdir build && cd build && \ cmake .. && make && make install && cd -# install multirust -RUN curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh -s -- --yes +# install rustup +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y -# export rust LIBRARY_PATH -ENV LIBRARY_PATH /usr/local/lib +# rustup directory +ENV PATH /root/.cargo/bin:$PATH # show backtraces ENV RUST_BACKTRACE 1 diff --git a/docker/ubuntu/Dockerfile b/docker/ubuntu/Dockerfile index 38c628d0e..10477e01f 100644 --- a/docker/ubuntu/Dockerfile +++ b/docker/ubuntu/Dockerfile @@ -8,11 +8,11 @@ RUN apt-get update && \ git \ make -# install multirust -RUN curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sh -s -- --yes +# install rustup +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y -# export rust LIBRARY_PATH -ENV LIBRARY_PATH /usr/local/lib +# rustup directory +ENV PATH /root/.cargo/bin:$PATH # show backtraces ENV RUST_BACKTRACE 1 From 5e9c8db4c9930c516bcb9dbdf00bc5e03246c74e Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 20 Jun 2016 11:07:22 +0200 Subject: [PATCH 102/239] Deactivate peers on invalid block bodies --- sync/src/blocks.rs | 21 ++++++++++++++++----- sync/src/chain.rs | 5 ++++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/sync/src/blocks.rs b/sync/src/blocks.rs index c1c6becde..17a97fe70 100644 --- a/sync/src/blocks.rs +++ b/sync/src/blocks.rs @@ -95,12 +95,17 @@ impl BlockCollection { } /// Insert a collection of block bodies for previously downloaded headers. - pub fn insert_bodies(&mut self, bodies: Vec) { + pub fn insert_bodies(&mut self, bodies: Vec) -> usize { + let mut inserted = 0; for b in bodies.into_iter() { if let Err(e) = self.insert_body(b) { trace!(target: "sync", "Ignored invalid body: {:?}", e); } + else { + inserted += 1; + } } + inserted } /// Returns a set of block hashes that require a body download. The returned set is marked as being downloaded. @@ -231,13 +236,19 @@ impl BlockCollection { Some(ref mut block) => { trace!(target: "sync", "Got body {}", h); block.body = Some(body.as_raw().to_vec()); + Ok(()) }, - None => warn!("Got body with no header {}", h) + None => { + warn!("Got body with no header {}", h); + Err(UtilError::Network(NetworkError::BadProtocol)) + } } } - None => trace!(target: "sync", "Ignored unknown/stale block body") - }; - Ok(()) + None => { + trace!(target: "sync", "Ignored unknown/stale block body"); + Err(UtilError::Network(NetworkError::BadProtocol)) + } + } } fn insert_header(&mut self, header: Bytes) -> Result { diff --git a/sync/src/chain.rs b/sync/src/chain.rs index caed95e0c..5b46978a2 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -517,7 +517,10 @@ impl ChainSync { for i in 0..item_count { bodies.push(try!(r.at(i)).as_raw().to_vec()); } - self.blocks.insert_bodies(bodies); + if self.blocks.insert_bodies(bodies) != item_count { + trace!(target: "sync", "Deactivating peer for giving invalid block bodies"); + self.deactivate_peer(io, peer_id); + } self.collect_blocks(io); } self.continue_sync(io); From edd43cd5c37cda1f0f1cc667f97e71319d952f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 20 Jun 2016 11:32:29 +0200 Subject: [PATCH 103/239] Fixing local transactions prioritization --- ethcore/src/miner/transaction_queue.rs | 29 +++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 385b2e473..74f996a98 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -172,6 +172,12 @@ impl Ord for TransactionOrder { return self.nonce_height.cmp(&b.nonce_height); } + // Local transactions should always have priority + // NOTE nonce has to be checked first, cause otherwise the order might be wrong. + if self.origin != b.origin { + return self.origin.cmp(&b.origin); + } + // Then compare gas_prices let a_gas = self.gas_price; let b_gas = b.gas_price; @@ -1082,7 +1088,28 @@ mod test { } #[test] - fn should_not_prioritize_local_transactions() { + fn should_prioritize_local_transactions_within_same_nonce_height() { + // given + let mut txq = TransactionQueue::new(); + let tx = new_tx(); + // the second one has same nonce but higher `gas_price` + let (_, tx2) = new_similar_txs(); + + // when + // first insert the one with higher gas price + txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External).unwrap(); + // then the one with lower gas price, but local + txq.add(tx.clone(), &default_nonce, TransactionOrigin::Local).unwrap(); + + // then + let top = txq.top_transactions(); + assert_eq!(top[0], tx); // local should be first + assert_eq!(top[1], tx2); + assert_eq!(top.len(), 2); + } + + #[test] + fn should_not_prioritize_local_transactions_with_different_nonce_height() { // given let mut txq = TransactionQueue::new(); let (tx, tx2) = new_txs(U256::from(1)); From 1bad0783fe593b9c237b19a57802a3bdd0073361 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 20 Jun 2016 11:36:18 +0200 Subject: [PATCH 104/239] ethkey and ethstore added to hook.sh --- hook.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hook.sh b/hook.sh index adb763f9d..9ce825f80 100755 --- a/hook.sh +++ b/hook.sh @@ -7,6 +7,6 @@ echo "set -e" >> $FILE echo "cargo build --features dev" >> $FILE # Build tests echo "cargo test --no-run --features dev \\" >> $FILE -echo " -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethcore-dapps -p ethcore-signer" >> $FILE +echo " -p ethkey -p ethstore -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethcore-dapps -p ethcore-signer" >> $FILE echo "" >> $FILE chmod +x $FILE From c348508b405fc50117e90c27b26cecfc34ec453f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 20 Jun 2016 12:13:10 +0200 Subject: [PATCH 105/239] Fixing future order and drops because of limit errors --- ethcore/src/miner/transaction_queue.rs | 40 +++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 98aa492d1..a17ff93b6 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -244,13 +244,12 @@ impl TransactionSet { /// Remove low priority transactions if there is more then specified by given `limit`. /// /// It drops transactions from this set but also removes associated `VerifiedTransaction`. - /// Returns addresses and highes nonces of transactions removed because of limit. + /// Returns addresses and lowest nonces of transactions removed because of limit. fn enforce_limit(&mut self, by_hash: &mut HashMap) -> Option> { let len = self.by_priority.len(); if len <= self.limit { return None; } - let to_drop : Vec<(Address, U256)> = { self.by_priority .iter() @@ -269,8 +268,8 @@ impl TransactionSet { by_hash.remove(&order.hash) .expect("Hash found in `by_priorty` matches the one dropped; so it is included in `by_hash`"); - let max = removed.get(&sender).map_or(nonce, |val| cmp::max(*val, nonce)); - removed.insert(sender, max); + let min = removed.get(&sender).map_or(nonce, |val| cmp::min(*val, nonce)); + removed.insert(sender, min); removed })) } @@ -666,8 +665,12 @@ impl TransactionQueue { // Check height if nonce > next_nonce { - // We have a gap - put to future - try!(check_too_cheap(Self::replace_transaction(tx, next_nonce, &mut self.future, &mut self.by_hash))); + // We have a gap - put to future. + // Update nonces of transactions in future (remove old transactions) + self.update_future(&address, state_nonce); + // Insert transaction (or replace old one with lower gas price) + try!(check_too_cheap(Self::replace_transaction(tx, state_nonce, &mut self.future, &mut self.by_hash))); + // Return an error if this transaction is not imported because of limit. try!(check_if_removed(&address, &nonce, self.future.enforce_limit(&mut self.by_hash))); return Ok(TransactionImportResult::Future); } else if nonce < state_nonce { @@ -703,9 +706,9 @@ impl TransactionQueue { } /// Updates - fn update_last_nonces(&mut self, removed_max_nonces: &Option>) { - if let Some(ref max_nonces) = *removed_max_nonces { - for (sender, nonce) in max_nonces.iter() { + fn update_last_nonces(&mut self, removed_min_nonces: &Option>) { + if let Some(ref min_nonces) = *removed_min_nonces { + for (sender, nonce) in min_nonces.iter() { if *nonce == U256::zero() { self.last_nonces.remove(sender); } else { @@ -762,7 +765,7 @@ fn check_too_cheap(is_in: bool) -> Result<(), TransactionError> { fn check_if_removed(sender: &Address, nonce: &U256, dropped: Option>) -> Result<(), TransactionError> { match dropped { Some(ref dropped) => match dropped.get(sender) { - Some(max) if nonce <= max => { + Some(min) if nonce >= min => { Err(TransactionError::LimitReached) }, _ => Ok(()), @@ -1555,4 +1558,21 @@ mod test { assert_eq!(txq.has_local_pending_transactions(), true); } + #[test] + fn should_keep_right_order_in_future() { + // given + let mut txq = TransactionQueue::with_limit(1); + let (tx1, tx2) = new_txs(U256::from(1)); + let prev_nonce = |a: &Address| AccountDetails { nonce: default_nonce(a).nonce - U256::one(), balance: + default_nonce(a).balance }; + + // when + assert_eq!(txq.add(tx2, &prev_nonce, TransactionOrigin::External).unwrap(), TransactionImportResult::Future); + assert_eq!(txq.add(tx1.clone(), &prev_nonce, TransactionOrigin::External).unwrap(), TransactionImportResult::Future); + + // then + assert_eq!(txq.future.by_priority.len(), 1); + assert_eq!(txq.future.by_priority.iter().next().unwrap().hash, tx1.hash()); + } + } From 06a3557e3e86d50c9f045618e5fd7c5e1e058f36 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 20 Jun 2016 12:17:06 +0200 Subject: [PATCH 106/239] reserved_only CLI flag --- parity/cli.rs | 2 ++ parity/configuration.rs | 1 + parity/main.rs | 4 ++-- rpc/src/v1/impls/ethcore_set.rs | 1 - util/src/network/host.rs | 10 +++++----- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 8c6f2d72d..8fa788108 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -70,6 +70,7 @@ Networking Options: --reserved-peers FILE Provide a file containing enodes, one per line. These nodes will always have a reserved slot on top of the normal maximum peers. + --reserved-only Connect only to reserved nodes. API and Console Options: --jsonrpc-off Disable the JSON-RPC API server. @@ -240,6 +241,7 @@ pub struct Args { pub flag_nat: String, pub flag_node_key: Option, pub flag_reserved_peers: Option, + pub flag_reserved_only: bool, pub flag_cache_pref_size: usize, pub flag_cache_max_size: usize, pub flag_queue_max_size: usize, diff --git a/parity/configuration.rs b/parity/configuration.rs index e2a8f94b6..f0c0a169c 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -200,6 +200,7 @@ impl Configuration { net_path.push("network"); ret.config_path = Some(net_path.to_str().unwrap().to_owned()); ret.reserved_nodes = self.init_reserved_nodes(); + ret.reserved_only = self.args.flag_reserved_only; ret } diff --git a/parity/main.rs b/parity/main.rs index d5e61a842..02d3ca271 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -308,7 +308,7 @@ fn execute_export(conf: Configuration) { udp_port: None, nat_enabled: false, discovery_enabled: false, - pin: true, + reserved_only: true, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 0, @@ -380,7 +380,7 @@ fn execute_import(conf: Configuration) { udp_port: None, nat_enabled: false, discovery_enabled: false, - pin: true, + reserved_only: true, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 0, diff --git a/rpc/src/v1/impls/ethcore_set.rs b/rpc/src/v1/impls/ethcore_set.rs index b07dcbf9e..cbd9c4309 100644 --- a/rpc/src/v1/impls/ethcore_set.rs +++ b/rpc/src/v1/impls/ethcore_set.rs @@ -74,5 +74,4 @@ impl EthcoreSet for EthcoreSetClient where M: MinerService + 'static { to_value(&true) }) } - } diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 25b1629f8..7e4b0c3a0 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -65,8 +65,8 @@ pub struct NetworkConfiguration { pub nat_enabled: bool, /// Enable discovery pub discovery_enabled: bool, - /// Pin to boot nodes only - pub pin: bool, + /// Pin to reserved nodes only + pub reserved_only: bool, /// List of initial node addresses pub boot_nodes: Vec, /// Use provided node key instead of default @@ -93,7 +93,7 @@ impl NetworkConfiguration { udp_port: None, nat_enabled: true, discovery_enabled: true, - pin: false, + reserved_only: false, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 25, @@ -483,7 +483,7 @@ impl Host where Message: Send + Sync + Clone { // Initialize discovery. let discovery = { let info = self.info.read().unwrap(); - if info.config.discovery_enabled && !info.config.pin { + if info.config.discovery_enabled && !info.config.reserved_only { Some(Discovery::new(&info.keys, public_endpoint.address.clone(), public_endpoint, DISCOVERY)) } else { None } }; @@ -544,7 +544,7 @@ impl Host where Message: Send + Sync + Clone { return; } let ideal_peers = { self.info.read().unwrap().config.ideal_peers }; - let pin = { self.info.read().unwrap().config.pin }; + let pin = { self.info.read().unwrap().config.reserved_only }; let session_count = self.session_count(); if session_count >= ideal_peers as usize + self.pinned_nodes.len() { // check if all pinned nodes are connected. From 7e452ab2e05792d934800edeeba674443f538069 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 20 Jun 2016 13:42:04 +0300 Subject: [PATCH 107/239] configurable cache size --- ethcore/src/blockchain/blockchain.rs | 14 ++++++++++-- ethcore/src/blockchain/config.rs | 3 +++ ethcore/src/client/client.rs | 5 ++++- ethcore/src/client/config.rs | 2 ++ ethcore/src/trace/config.rs | 5 ++++- ethcore/src/trace/db.rs | 9 ++++++-- parity/cli.rs | 2 ++ parity/configuration.rs | 9 +++++++- parity/migration.rs | 1 + util/src/journaldb/archivedb.rs | 3 ++- util/src/journaldb/earlymergedb.rs | 3 ++- util/src/journaldb/mod.rs | 10 ++++----- util/src/journaldb/overlayrecentdb.rs | 7 +++--- util/src/journaldb/refcounteddb.rs | 3 ++- util/src/kvdb.rs | 31 ++++++++++++++++++++++++++- 15 files changed, 88 insertions(+), 19 deletions(-) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 6fb9161d5..4b2246b21 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -253,12 +253,22 @@ impl BlockChain { // open extras db let mut extras_path = path.to_path_buf(); extras_path.push("extras"); - let extras_db = Database::open_default(extras_path.to_str().unwrap()).unwrap(); + let extras_db = match config.db_cache_size { + None => Database::open_default(extras_path.to_str().unwrap()).unwrap(), + Some(cache_size) => Database::open( + &DatabaseConfig::with_cache(cache_size/2), + extras_path.to_str().unwrap()).unwrap(), + }; // open blocks db let mut blocks_path = path.to_path_buf(); blocks_path.push("blocks"); - let blocks_db = Database::open_default(blocks_path.to_str().unwrap()).unwrap(); + let blocks_db = match config.db_cache_size { + None => Database::open_default(blocks_path.to_str().unwrap()).unwrap(), + Some(cache_size) => Database::open( + &DatabaseConfig::with_cache(cache_size/2), + blocks_path.to_str().unwrap()).unwrap(), + }; let mut cache_man = CacheManager{cache_usage: VecDeque::new(), in_use: HashSet::new()}; (0..COLLECTION_QUEUE_SIZE).foreach(|_| cache_man.cache_usage.push_back(HashSet::new())); diff --git a/ethcore/src/blockchain/config.rs b/ethcore/src/blockchain/config.rs index 9e70ff904..e063d4269 100644 --- a/ethcore/src/blockchain/config.rs +++ b/ethcore/src/blockchain/config.rs @@ -23,6 +23,8 @@ pub struct Config { pub pref_cache_size: usize, /// Maximum cache size in bytes. pub max_cache_size: usize, + /// Backing db cache_size + pub db_cache_size: Option, } impl Default for Config { @@ -30,6 +32,7 @@ impl Default for Config { Config { pref_cache_size: 1 << 14, max_cache_size: 1 << 20, + db_cache_size: None, } } } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 85a3d693d..c6fe14ecd 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -141,7 +141,10 @@ impl Client where V: Verifier { let chain = Arc::new(BlockChain::new(config.blockchain, &gb, &path)); let tracedb = Arc::new(try!(TraceDB::new(config.tracing, &path, chain.clone()))); - let mut state_db = journaldb::new(&append_path(&path, "state"), config.pruning); + let mut state_db = journaldb::new( + &append_path(&path, "state"), + config.pruning, + config.db_cache_size); if state_db.is_empty() && spec.ensure_db_good(state_db.as_hashdb_mut()) { state_db.commit(0, &spec.genesis_header().hash(), None).expect("Error commiting genesis state to state DB"); diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index e0b867903..6353e324f 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -35,4 +35,6 @@ pub struct ClientConfig { pub pruning: journaldb::Algorithm, /// The name of the client instance. pub name: String, + /// State db cache-size if not default + pub db_cache_size: Option, } diff --git a/ethcore/src/trace/config.rs b/ethcore/src/trace/config.rs index 76c62b43d..2876baa28 100644 --- a/ethcore/src/trace/config.rs +++ b/ethcore/src/trace/config.rs @@ -48,6 +48,8 @@ pub struct Config { pub enabled: Switch, /// Traces blooms configuration. pub blooms: BloomConfig, + /// Database cache-size if not default + pub db_cache_size: Option, } impl Default for Config { @@ -57,7 +59,8 @@ impl Default for Config { blooms: BloomConfig { levels: 3, elements_per_index: 16, - } + }, + db_cache_size: None, } } } diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index e40fa1b00..07f5f9c27 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -22,7 +22,7 @@ use std::sync::{RwLock, Arc}; use std::path::Path; use bloomchain::{Number, Config as BloomConfig}; use bloomchain::group::{BloomGroupDatabase, BloomGroupChain, GroupPosition, BloomGroup}; -use util::{H256, H264, Database, DBTransaction}; +use util::{H256, H264, Database, DatabaseConfig, DBTransaction}; use header::BlockNumber; use trace::{BlockTraces, LocalizedTrace, Config, Switch, Filter, Database as TraceDatabase, ImportRequest, DatabaseExtras, Error}; @@ -118,7 +118,12 @@ impl TraceDB where T: DatabaseExtras { pub fn new(config: Config, path: &Path, extras: Arc) -> Result { let mut tracedb_path = path.to_path_buf(); tracedb_path.push("tracedb"); - let tracesdb = Database::open_default(tracedb_path.to_str().unwrap()).unwrap(); + let tracesdb = match config.db_cache_size { + None => Database::open_default(tracedb_path.to_str().unwrap()).unwrap(), + Some(db_cache) => Database::open( + &DatabaseConfig::with_cache(db_cache), + tracedb_path.to_str().unwrap()).unwrap(), + }; // check if in previously tracing was enabled let old_tracing = match tracesdb.get(b"enabled").unwrap() { diff --git a/parity/cli.rs b/parity/cli.rs index 38af6af4c..a4983f231 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -155,6 +155,7 @@ Footprint Options: --cache MEGABYTES Set total amount of discretionary memory to use for the entire system, overrides other cache and queue options. + --db-cache-size MEGABYTE Database cache size. Import/Export Options: --from BLOCK Export from block BLOCK, which may be an index or @@ -292,6 +293,7 @@ pub struct Args { pub flag_ipcdisable: bool, pub flag_ipcpath: Option, pub flag_ipcapi: Option, + pub flag_db_cache_size: Option, } pub fn print_version() { diff --git a/parity/configuration.rs b/parity/configuration.rs index 7c42f06e1..067ff4ae6 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -187,7 +187,7 @@ impl Configuration { let mut latest_era = None; let jdb_types = [journaldb::Algorithm::Archive, journaldb::Algorithm::EarlyMerge, journaldb::Algorithm::OverlayRecent, journaldb::Algorithm::RefCounted]; for i in jdb_types.into_iter() { - let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i); + let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i, None); trace!(target: "parity", "Looking for best DB: {} at {:?}", i, db.latest_era()); match (latest_era, db.latest_era()) { (Some(best), Some(this)) if best >= this => {} @@ -214,6 +214,8 @@ impl Configuration { client_config.blockchain.max_cache_size = self.args.flag_cache_max_size; } } + // forced blockchain (blocks + extras) db cache size if provided + client_config.blockchain.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 2)); client_config.tracing.enabled = match self.args.flag_tracing.as_str() { "auto" => Switch::Auto, @@ -221,6 +223,8 @@ impl Configuration { "off" => Switch::Off, _ => { die!("Invalid tracing method given!") } }; + // forced trace db cache size if provided + client_config.tracing.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 4)); client_config.pruning = match self.args.flag_pruning.as_str() { "archive" => journaldb::Algorithm::Archive, @@ -231,6 +235,9 @@ impl Configuration { _ => { die!("Invalid pruning method given."); } }; + // forced state db cache size if provided + client_config.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 4)); + if self.args.flag_jitvm { client_config.vm_type = VMType::jit().unwrap_or_else(|| die!("Parity built without jit vm.")) } diff --git a/parity/migration.rs b/parity/migration.rs index acfd32ffd..72e2d46a4 100644 --- a/parity/migration.rs +++ b/parity/migration.rs @@ -163,6 +163,7 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) - let db_config = DatabaseConfig { prefix_size: None, max_open_files: 64, + cache_size: None, }; // open old database diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index e971711e0..c791f4740 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -43,11 +43,12 @@ const DB_VERSION : u32 = 0x103; impl ArchiveDB { /// Create a new instance from file - pub fn new(path: &str) -> ArchiveDB { + pub fn new(path: &str, cache_size: Option) -> ArchiveDB { let opts = DatabaseConfig { // this must match account_db prefix prefix_size: Some(DB_PREFIX_LEN), max_open_files: 256, + cache_size: cache_size, }; let backing = Database::open(&opts, path).unwrap_or_else(|e| { panic!("Error opening state db: {}", e); diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs index 4d897e3db..bd96a4f3a 100644 --- a/util/src/journaldb/earlymergedb.rs +++ b/util/src/journaldb/earlymergedb.rs @@ -73,11 +73,12 @@ const PADDING : [u8; 10] = [ 0u8; 10 ]; impl EarlyMergeDB { /// Create a new instance from file - pub fn new(path: &str) -> EarlyMergeDB { + pub fn new(path: &str, cache_size: Option) -> EarlyMergeDB { let opts = DatabaseConfig { // this must match account_db prefix prefix_size: Some(DB_PREFIX_LEN), max_open_files: 256, + cache_size: cache_size, }; let backing = Database::open(&opts, path).unwrap_or_else(|e| { panic!("Error opening state db: {}", e); diff --git a/util/src/journaldb/mod.rs b/util/src/journaldb/mod.rs index 9f242e950..973dd9eb0 100644 --- a/util/src/journaldb/mod.rs +++ b/util/src/journaldb/mod.rs @@ -71,12 +71,12 @@ impl fmt::Display for Algorithm { } /// Create a new `JournalDB` trait object. -pub fn new(path: &str, algorithm: Algorithm) -> Box { +pub fn new(path: &str, algorithm: Algorithm, cache_size: Option) -> Box { match algorithm { - Algorithm::Archive => Box::new(archivedb::ArchiveDB::new(path)), - Algorithm::EarlyMerge => Box::new(earlymergedb::EarlyMergeDB::new(path)), - Algorithm::OverlayRecent => Box::new(overlayrecentdb::OverlayRecentDB::new(path)), - Algorithm::RefCounted => Box::new(refcounteddb::RefCountedDB::new(path)), + Algorithm::Archive => Box::new(archivedb::ArchiveDB::new(path, cache_size)), + Algorithm::EarlyMerge => Box::new(earlymergedb::EarlyMergeDB::new(path, cache_size)), + Algorithm::OverlayRecent => Box::new(overlayrecentdb::OverlayRecentDB::new(path, cache_size)), + Algorithm::RefCounted => Box::new(refcounteddb::RefCountedDB::new(path, cache_size)), } } diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs index 435dd7880..e88f34588 100644 --- a/util/src/journaldb/overlayrecentdb.rs +++ b/util/src/journaldb/overlayrecentdb.rs @@ -98,16 +98,17 @@ const PADDING : [u8; 10] = [ 0u8; 10 ]; impl OverlayRecentDB { /// Create a new instance from file - pub fn new(path: &str) -> OverlayRecentDB { - Self::from_prefs(path) + pub fn new(path: &str, cache_size: Option) -> OverlayRecentDB { + Self::from_prefs(path, cache_size) } /// Create a new instance from file - pub fn from_prefs(path: &str) -> OverlayRecentDB { + pub fn from_prefs(path: &str, cache_size: Option) -> OverlayRecentDB { let opts = DatabaseConfig { // this must match account_db prefix prefix_size: Some(DB_PREFIX_LEN), max_open_files: 256, + cache_size: cache_size, }; let backing = Database::open(&opts, path).unwrap_or_else(|e| { panic!("Error opening state db: {}", e); diff --git a/util/src/journaldb/refcounteddb.rs b/util/src/journaldb/refcounteddb.rs index 3bcb0faaf..eac7cd558 100644 --- a/util/src/journaldb/refcounteddb.rs +++ b/util/src/journaldb/refcounteddb.rs @@ -46,11 +46,12 @@ const PADDING : [u8; 10] = [ 0u8; 10 ]; impl RefCountedDB { /// Create a new instance given a `backing` database. - pub fn new(path: &str) -> RefCountedDB { + pub fn new(path: &str, cache_size: Option) -> RefCountedDB { let opts = DatabaseConfig { // this must match account_db prefix prefix_size: Some(DB_PREFIX_LEN), max_open_files: 256, + cache_size: cache_size, }; let backing = Database::open(&opts, path).unwrap_or_else(|e| { panic!("Error opening state db: {}", e); diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 40b7ef090..128304841 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -54,6 +54,29 @@ pub struct DatabaseConfig { pub prefix_size: Option, /// Max number of open files. pub max_open_files: i32, + /// Cache-size + pub cache_size: Option, +} + +impl DatabaseConfig { + /// Database with default settings and specified cache size + pub fn with_cache(cache_size: usize) -> DatabaseConfig { + DatabaseConfig { + cache_size: Some(cache_size), + prefix_size: None, + max_open_files: 256 + } + } +} + +impl Default for DatabaseConfig { + fn default() -> DatabaseConfig { + DatabaseConfig { + cache_size: None, + prefix_size: None, + max_open_files: 256 + } + } } /// Database iterator @@ -77,7 +100,7 @@ pub struct Database { impl Database { /// Open database with default settings. pub fn open_default(path: &str) -> Result { - Database::open(&DatabaseConfig { prefix_size: None, max_open_files: 256 }, path) + Database::open(&DatabaseConfig::default(), path) } /// Open database file. Creates if it does not exist. @@ -87,6 +110,12 @@ impl Database { opts.create_if_missing(true); opts.set_use_fsync(false); opts.set_compaction_style(DBCompactionStyle::DBUniversalCompaction); + if let Some(cache_size) = config.cache_size { + // half goes to read cache + opts.set_block_cache_size_mb(cache_size as u64 / 2); + // quarter goes to each of the two write buffers + opts.set_write_buffer_size(cache_size * 1024 * 256); + } /* opts.set_bytes_per_sync(8388608); opts.set_disable_data_sync(false); From 8d61c0298c849d03e45afd3acb33c7f532826b4a Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 20 Jun 2016 12:46:57 +0200 Subject: [PATCH 108/239] indentation fix [ci skip] --- parity/cli.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 8fa788108..018a50bb1 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -240,8 +240,8 @@ pub struct Args { pub flag_no_discovery: bool, pub flag_nat: String, pub flag_node_key: Option, - pub flag_reserved_peers: Option, - pub flag_reserved_only: bool, + pub flag_reserved_peers: Option, + pub flag_reserved_only: bool, pub flag_cache_pref_size: usize, pub flag_cache_max_size: usize, pub flag_queue_max_size: usize, From deb20c62495a12f9908e9c475b51e5238a46e3c4 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 20 Jun 2016 14:02:09 +0300 Subject: [PATCH 109/239] fix docopt --- parity/cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/cli.rs b/parity/cli.rs index a4983f231..08470b174 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -155,7 +155,7 @@ Footprint Options: --cache MEGABYTES Set total amount of discretionary memory to use for the entire system, overrides other cache and queue options. - --db-cache-size MEGABYTE Database cache size. + --db-cache-size MB Database cache size. Import/Export Options: --from BLOCK Export from block BLOCK, which may be an index or From c6616431b02b91528409a2df0e3c718c9862a8b2 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 20 Jun 2016 14:20:13 +0300 Subject: [PATCH 110/239] fix tests --- ethcore/src/tests/helpers.rs | 4 ++-- util/src/journaldb/archivedb.rs | 20 ++++++++-------- util/src/journaldb/earlymergedb.rs | 34 +++++++++++++-------------- util/src/journaldb/overlayrecentdb.rs | 34 +++++++++++++-------------- util/src/journaldb/refcounteddb.rs | 2 +- util/src/kvdb.rs | 8 +++---- 6 files changed, 51 insertions(+), 51 deletions(-) diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 48ca14bbf..14c4c09a2 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -302,7 +302,7 @@ pub fn generate_dummy_empty_blockchain() -> GuardedTempResult { pub fn get_temp_journal_db() -> GuardedTempResult> { let temp = RandomTempPath::new(); - let journal_db = journaldb::new(temp.as_str(), journaldb::Algorithm::EarlyMerge); + let journal_db = journaldb::new(temp.as_str(), journaldb::Algorithm::EarlyMerge, None); GuardedTempResult { _temp: temp, result: Some(journal_db) @@ -319,7 +319,7 @@ pub fn get_temp_state() -> GuardedTempResult { } pub fn get_temp_journal_db_in(path: &Path) -> Box { - journaldb::new(path.to_str().unwrap(), journaldb::Algorithm::EarlyMerge) + journaldb::new(path.to_str().unwrap(), journaldb::Algorithm::EarlyMerge, None) } pub fn get_temp_state_in(path: &Path) -> State { diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index c791f4740..0381c08ea 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -75,7 +75,7 @@ impl ArchiveDB { fn new_temp() -> ArchiveDB { let mut dir = env::temp_dir(); dir.push(H32::random().hex()); - Self::new(dir.to_str().unwrap()) + Self::new(dir.to_str().unwrap(), None) } fn payload(&self, key: &H256) -> Option { @@ -328,7 +328,7 @@ mod tests { let bar = H256::random(); let foo = { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap()); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); // history is 1 let foo = jdb.insert(b"foo"); jdb.emplace(bar.clone(), b"bar".to_vec()); @@ -337,13 +337,13 @@ mod tests { }; { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap()); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); jdb.remove(&foo); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); } { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap()); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); assert!(jdb.exists(&foo)); assert!(jdb.exists(&bar)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); @@ -356,7 +356,7 @@ mod tests { dir.push(H32::random().hex()); let foo = { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap()); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); // history is 1 let foo = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); @@ -370,7 +370,7 @@ mod tests { }; { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap()); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); jdb.remove(&foo); jdb.commit(3, &b"3".sha3(), Some((2, b"2".sha3()))).unwrap(); assert!(jdb.exists(&foo)); @@ -385,7 +385,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); let (foo, _, _) = { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap()); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); // history is 1 let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); @@ -400,7 +400,7 @@ mod tests { }; { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap()); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.exists(&foo)); } @@ -411,14 +411,14 @@ mod tests { let temp = ::devtools::RandomTempPath::new(); let key = { - let mut jdb = ArchiveDB::new(temp.as_str()); + let mut jdb = ArchiveDB::new(temp.as_str(), None); let key = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); key }; { - let jdb = ArchiveDB::new(temp.as_str()); + let jdb = ArchiveDB::new(temp.as_str(), None); let state = jdb.state(&key); assert!(state.is_some()); } diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs index bd96a4f3a..e495b9d03 100644 --- a/util/src/journaldb/earlymergedb.rs +++ b/util/src/journaldb/earlymergedb.rs @@ -107,7 +107,7 @@ impl EarlyMergeDB { fn new_temp() -> EarlyMergeDB { let mut dir = env::temp_dir(); dir.push(H32::random().hex()); - Self::new(dir.to_str().unwrap()) + Self::new(dir.to_str().unwrap(), None) } fn morph_key(key: &H256, index: u8) -> Bytes { @@ -714,7 +714,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -742,7 +742,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -770,7 +770,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -808,7 +808,7 @@ mod tests { let bar = H256::random(); let foo = { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); // history is 1 let foo = jdb.insert(b"foo"); jdb.emplace(bar.clone(), b"bar".to_vec()); @@ -818,14 +818,14 @@ mod tests { }; { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.remove(&foo); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); } { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); assert!(jdb.exists(&foo)); assert!(jdb.exists(&bar)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); @@ -840,7 +840,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); // history is 4 let foo = jdb.insert(b"foo"); @@ -869,7 +869,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); // history is 4 let foo = jdb.insert(b"foo"); @@ -918,7 +918,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); // history is 1 let foo = jdb.insert(b"foo"); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); @@ -949,7 +949,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); // history is 4 let foo = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); @@ -989,7 +989,7 @@ mod tests { let foo = b"foo".sha3(); { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); // history is 1 jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); @@ -1010,7 +1010,7 @@ mod tests { assert!(jdb.exists(&foo)); // incantation to reopen the db - }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.remove(&foo); jdb.commit(4, &b"4".sha3(), Some((2, b"2".sha3()))).unwrap(); @@ -1018,14 +1018,14 @@ mod tests { assert!(jdb.exists(&foo)); // incantation to reopen the db - }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.commit(5, &b"5".sha3(), Some((3, b"3".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.exists(&foo)); // incantation to reopen the db - }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.commit(6, &b"6".sha3(), Some((4, b"4".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -1038,7 +1038,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); let (foo, bar, baz) = { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); // history is 1 let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); @@ -1056,7 +1056,7 @@ mod tests { }; { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap()); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.exists(&foo)); diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs index e88f34588..709a8fe5f 100644 --- a/util/src/journaldb/overlayrecentdb.rs +++ b/util/src/journaldb/overlayrecentdb.rs @@ -135,7 +135,7 @@ impl OverlayRecentDB { pub fn new_temp() -> OverlayRecentDB { let mut dir = env::temp_dir(); dir.push(H32::random().hex()); - Self::new(dir.to_str().unwrap()) + Self::new(dir.to_str().unwrap(), None) } #[cfg(test)] @@ -526,7 +526,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -554,7 +554,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -582,7 +582,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -620,7 +620,7 @@ mod tests { let bar = H256::random(); let foo = { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); // history is 1 let foo = jdb.insert(b"foo"); jdb.emplace(bar.clone(), b"bar".to_vec()); @@ -630,14 +630,14 @@ mod tests { }; { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.remove(&foo); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); } { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); assert!(jdb.exists(&foo)); assert!(jdb.exists(&bar)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); @@ -652,7 +652,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); // history is 4 let foo = jdb.insert(b"foo"); @@ -681,7 +681,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); // history is 4 let foo = jdb.insert(b"foo"); @@ -730,7 +730,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); // history is 1 let foo = jdb.insert(b"foo"); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); @@ -761,7 +761,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); // history is 4 let foo = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); @@ -801,7 +801,7 @@ mod tests { let foo = b"foo".sha3(); { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); // history is 1 jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); @@ -822,7 +822,7 @@ mod tests { assert!(jdb.exists(&foo)); // incantation to reopen the db - }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.remove(&foo); jdb.commit(4, &b"4".sha3(), Some((2, b"2".sha3()))).unwrap(); @@ -830,14 +830,14 @@ mod tests { assert!(jdb.exists(&foo)); // incantation to reopen the db - }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.commit(5, &b"5".sha3(), Some((3, b"3".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.exists(&foo)); // incantation to reopen the db - }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.commit(6, &b"6".sha3(), Some((4, b"4".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -850,7 +850,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); let (foo, bar, baz) = { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); // history is 1 let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); @@ -868,7 +868,7 @@ mod tests { }; { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap()); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.exists(&foo)); diff --git a/util/src/journaldb/refcounteddb.rs b/util/src/journaldb/refcounteddb.rs index eac7cd558..31f31f654 100644 --- a/util/src/journaldb/refcounteddb.rs +++ b/util/src/journaldb/refcounteddb.rs @@ -82,7 +82,7 @@ impl RefCountedDB { fn new_temp() -> RefCountedDB { let mut dir = env::temp_dir(); dir.push(H32::random().hex()); - Self::new(dir.to_str().unwrap()) + Self::new(dir.to_str().unwrap(), None) } } diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 128304841..7d581fdbc 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -234,10 +234,10 @@ mod tests { let path = RandomTempPath::create_dir(); let smoke = Database::open_default(path.as_path().to_str().unwrap()).unwrap(); assert!(smoke.is_empty()); - test_db(&DatabaseConfig { prefix_size: None, max_open_files: 256 }); - test_db(&DatabaseConfig { prefix_size: Some(1), max_open_files: 256 }); - test_db(&DatabaseConfig { prefix_size: Some(8), max_open_files: 256 }); - test_db(&DatabaseConfig { prefix_size: Some(32), max_open_files: 256 }); + test_db(&DatabaseConfig { prefix_size: None, max_open_files: 256, cache_size: None, }); + test_db(&DatabaseConfig { prefix_size: Some(1), max_open_files: 256, cache_size: None, }); + test_db(&DatabaseConfig { prefix_size: Some(8), max_open_files: 256, cache_size: None, }); + test_db(&DatabaseConfig { prefix_size: Some(32), max_open_files: 256, cache_size: None, }); } } From 3d3041d418cec560d40753ebc24ee3f2b06ebdbf Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 20 Jun 2016 14:09:41 +0200 Subject: [PATCH 111/239] Revert "Reserved peers, reserved-only flag" --- parity/cli.rs | 6 --- parity/configuration.rs | 22 ----------- parity/main.rs | 6 +-- rpc/src/v1/impls/ethcore_set.rs | 1 + util/src/network/host.rs | 65 +++++++++++---------------------- 5 files changed, 25 insertions(+), 75 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 1e1014cb7..b826b7eb5 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -67,10 +67,6 @@ Networking Options: --no-discovery Disable new peer discovery. --node-key KEY Specify node secret key, either as 64-character hex string or input to SHA3 operation. - --reserved-peers FILE Provide a file containing enodes, one per line. - These nodes will always have a reserved slot on top - of the normal maximum peers. - --reserved-only Connect only to reserved nodes. API and Console Options: --jsonrpc-off Disable the JSON-RPC API server. @@ -242,8 +238,6 @@ pub struct Args { pub flag_no_discovery: bool, pub flag_nat: String, pub flag_node_key: Option, - pub flag_reserved_peers: Option, - pub flag_reserved_only: bool, pub flag_cache_pref_size: usize, pub flag_cache_max_size: usize, pub flag_queue_max_size: usize, diff --git a/parity/configuration.rs b/parity/configuration.rs index e3693d66e..7c42f06e1 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -153,26 +153,6 @@ impl Configuration { } } - pub fn init_reserved_nodes(&self) -> Vec { - use std::fs::File; - use std::io::BufRead; - - if let Some(ref path) = self.args.flag_reserved_peers { - let mut buffer = String::new(); - let mut node_file = File::open(path).unwrap_or_else(|e| { - die!("Error opening reserved nodes file: {}", e); - }); - node_file.read_to_string(&mut buffer).expect("Error reading reserved node file"); - buffer.lines().map(|s| { - Self::normalize_enode(s).unwrap_or_else(|| { - die!("{}: Invalid node address format given for a reserved node.", s); - }) - }).collect() - } else { - Vec::new() - } - } - pub fn net_addresses(&self) -> (Option, Option) { let port = self.net_port(); let listen_address = Some(SocketAddr::new(IpAddr::from_str("0.0.0.0").unwrap(), port)); @@ -199,8 +179,6 @@ impl Configuration { let mut net_path = PathBuf::from(&self.path()); net_path.push("network"); ret.config_path = Some(net_path.to_str().unwrap().to_owned()); - ret.reserved_nodes = self.init_reserved_nodes(); - ret.reserved_only = self.args.flag_reserved_only; ret } diff --git a/parity/main.rs b/parity/main.rs index 3ccb7e430..9b3698c5c 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -315,11 +315,10 @@ fn execute_export(conf: Configuration) { udp_port: None, nat_enabled: false, discovery_enabled: false, - reserved_only: true, + pin: true, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 0, - reserved_nodes: Vec::new(), }; let client_config = conf.client_config(&spec); @@ -387,11 +386,10 @@ fn execute_import(conf: Configuration) { udp_port: None, nat_enabled: false, discovery_enabled: false, - reserved_only: true, + pin: true, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 0, - reserved_nodes: Vec::new(), }; let client_config = conf.client_config(&spec); diff --git a/rpc/src/v1/impls/ethcore_set.rs b/rpc/src/v1/impls/ethcore_set.rs index cbd9c4309..b07dcbf9e 100644 --- a/rpc/src/v1/impls/ethcore_set.rs +++ b/rpc/src/v1/impls/ethcore_set.rs @@ -74,4 +74,5 @@ impl EthcoreSet for EthcoreSetClient where M: MinerService + 'static { to_value(&true) }) } + } diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 7e4b0c3a0..aef56fc09 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -65,16 +65,14 @@ pub struct NetworkConfiguration { pub nat_enabled: bool, /// Enable discovery pub discovery_enabled: bool, - /// Pin to reserved nodes only - pub reserved_only: bool, + /// Pin to boot nodes only + pub pin: bool, /// List of initial node addresses pub boot_nodes: Vec, /// Use provided node key instead of default pub use_secret: Option, /// Number of connected peers to maintain pub ideal_peers: u32, - /// List of reserved node addresses. - pub reserved_nodes: Vec, } impl Default for NetworkConfiguration { @@ -93,11 +91,10 @@ impl NetworkConfiguration { udp_port: None, nat_enabled: true, discovery_enabled: true, - reserved_only: false, + pin: false, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 25, - reserved_nodes: Vec::new(), } } @@ -219,7 +216,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone pub fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec) -> Result<(), UtilError> { let session = self.resolve_session(peer); if let Some(session) = session { - try!(session.lock().unwrap().send_packet(self.io, self.protocol, packet_id as u8, &data)); + try!(session.lock().unwrap().deref_mut().send_packet(self.io, self.protocol, packet_id as u8, &data)); } else { trace!(target: "network", "Send: Peer no longer exist") } @@ -368,9 +365,6 @@ impl Host where Message: Send + Sync + Clone { let udp_port = config.udp_port.unwrap_or(listen_address.port()); let local_endpoint = NodeEndpoint { address: listen_address, udp_port: udp_port }; - let boot_nodes = config.boot_nodes.clone(); - let reserved_nodes = config.reserved_nodes.clone(); - let mut host = Host:: { info: RwLock::new(HostInfo { keys: keys, @@ -395,26 +389,21 @@ impl Host where Message: Send + Sync + Clone { stopping: AtomicBool::new(false), }; + let boot_nodes = host.info.read().unwrap().config.boot_nodes.clone(); for n in boot_nodes { - // don't pin boot nodes. - host.add_node(&n, false); - } - - for n in reserved_nodes { - host.add_node(&n, true); + host.add_node(&n); } Ok(host) } - pub fn add_node(&mut self, id: &str, pin: bool) { + pub fn add_node(&mut self, id: &str) { match Node::from_str(id) { Err(e) => { debug!(target: "network", "Could not add node {}: {:?}", id, e); }, Ok(n) => { let entry = NodeEntry { endpoint: n.endpoint.clone(), id: n.id.clone() }; - if pin { self.pinned_nodes.push(n.id.clone()) } - + self.pinned_nodes.push(n.id.clone()); self.nodes.write().unwrap().add_node(n); - if let Some(ref mut discovery) = *self.discovery.lock().unwrap() { + if let Some(ref mut discovery) = *self.discovery.lock().unwrap().deref_mut() { discovery.add_node(entry); } } @@ -483,7 +472,7 @@ impl Host where Message: Send + Sync + Clone { // Initialize discovery. let discovery = { let info = self.info.read().unwrap(); - if info.config.discovery_enabled && !info.config.reserved_only { + if info.config.discovery_enabled && !info.config.pin { Some(Discovery::new(&info.keys, public_endpoint.address.clone(), public_endpoint, DISCOVERY)) } else { None } }; @@ -493,7 +482,7 @@ impl Host where Message: Send + Sync + Clone { for n in self.nodes.read().unwrap().unordered_entries() { discovery.add_node(n.clone()); } - *self.discovery.lock().unwrap() = Some(discovery); + *self.discovery.lock().unwrap().deref_mut() = Some(discovery); io.register_stream(DISCOVERY).expect("Error registering UDP listener"); io.register_timer(DISCOVERY_REFRESH, 7200).expect("Error registering discovery timer"); io.register_timer(DISCOVERY_ROUND, 300).expect("Error registering discovery timer"); @@ -540,17 +529,14 @@ impl Host where Message: Send + Sync + Clone { } fn connect_peers(&self, io: &IoContext>) { - if self.info.read().unwrap().capabilities.is_empty() { + if self.info.read().unwrap().deref().capabilities.is_empty() { return; } - let ideal_peers = { self.info.read().unwrap().config.ideal_peers }; - let pin = { self.info.read().unwrap().config.reserved_only }; + let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; + let pin = { self.info.read().unwrap().deref().config.pin }; let session_count = self.session_count(); - if session_count >= ideal_peers as usize + self.pinned_nodes.len() { - // check if all pinned nodes are connected. - if self.pinned_nodes.iter().all(|n| self.have_session(n) && self.connecting_to(n)) { - return; - } + if session_count >= ideal_peers as usize { + return; } let handshake_count = self.handshake_count(); @@ -560,16 +546,9 @@ impl Host where Message: Send + Sync + Clone { return; } - // iterate over all nodes, reserved ones coming first. - // if we are pinned to only reserved nodes, ignore all others. - let nodes = self.pinned_nodes.iter().cloned().chain(if !pin { - self.nodes.read().unwrap().nodes() - } else { - Vec::new() - }); - + let nodes = if pin { self.pinned_nodes.clone() } else { self.nodes.read().unwrap().nodes() }; let mut started: usize = 0; - for id in nodes.filter(|ref id| !self.have_session(id) && !self.connecting_to(id)) + for id in nodes.iter().filter(|ref id| !self.have_session(id) && !self.connecting_to(id)) .take(min(MAX_HANDSHAKES_PER_ROUND, handshake_limit - handshake_count)) { self.connect_peer(&id, io); started += 1; @@ -699,7 +678,7 @@ impl Host where Message: Send + Sync + Clone { self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); if !s.info.originated { let session_count = self.session_count(); - let ideal_peers = { self.info.read().unwrap().config.ideal_peers }; + let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; if session_count >= ideal_peers as usize { s.disconnect(io, DisconnectReason::TooManyPeers); return; @@ -921,7 +900,7 @@ impl IoHandler> for Host where Messa } => { let handler_token = { let mut timer_counter = self.timer_counter.write().unwrap(); - let counter = &mut *timer_counter; + let counter = timer_counter.deref_mut(); let handler_token = *counter; *counter += 1; handler_token @@ -965,7 +944,7 @@ impl IoHandler> for Host where Messa } } DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().register_socket(event_loop).expect("Error registering discovery socket"), - TCP_ACCEPT => event_loop.register(&*self.tcp_listener.lock().unwrap(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error registering stream"), + TCP_ACCEPT => event_loop.register(self.tcp_listener.lock().unwrap().deref(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error registering stream"), _ => warn!("Unexpected stream registration") } } @@ -993,7 +972,7 @@ impl IoHandler> for Host where Messa } } DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().update_registration(event_loop).expect("Error reregistering discovery socket"), - TCP_ACCEPT => event_loop.reregister(&*self.tcp_listener.lock().unwrap(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error reregistering stream"), + TCP_ACCEPT => event_loop.reregister(self.tcp_listener.lock().unwrap().deref(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error reregistering stream"), _ => warn!("Unexpected stream update") } } From 7a6fa97d98133d03755da626f52e78fb58a0247b Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 20 Jun 2016 14:13:33 +0200 Subject: [PATCH 112/239] Revert "Revert "Reserved peers, reserved-only flag"" --- parity/cli.rs | 6 +++ parity/configuration.rs | 22 +++++++++++ parity/main.rs | 6 ++- rpc/src/v1/impls/ethcore_set.rs | 1 - util/src/network/host.rs | 65 ++++++++++++++++++++++----------- 5 files changed, 75 insertions(+), 25 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index b826b7eb5..1e1014cb7 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -67,6 +67,10 @@ Networking Options: --no-discovery Disable new peer discovery. --node-key KEY Specify node secret key, either as 64-character hex string or input to SHA3 operation. + --reserved-peers FILE Provide a file containing enodes, one per line. + These nodes will always have a reserved slot on top + of the normal maximum peers. + --reserved-only Connect only to reserved nodes. API and Console Options: --jsonrpc-off Disable the JSON-RPC API server. @@ -238,6 +242,8 @@ pub struct Args { pub flag_no_discovery: bool, pub flag_nat: String, pub flag_node_key: Option, + pub flag_reserved_peers: Option, + pub flag_reserved_only: bool, pub flag_cache_pref_size: usize, pub flag_cache_max_size: usize, pub flag_queue_max_size: usize, diff --git a/parity/configuration.rs b/parity/configuration.rs index 7c42f06e1..e3693d66e 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -153,6 +153,26 @@ impl Configuration { } } + pub fn init_reserved_nodes(&self) -> Vec { + use std::fs::File; + use std::io::BufRead; + + if let Some(ref path) = self.args.flag_reserved_peers { + let mut buffer = String::new(); + let mut node_file = File::open(path).unwrap_or_else(|e| { + die!("Error opening reserved nodes file: {}", e); + }); + node_file.read_to_string(&mut buffer).expect("Error reading reserved node file"); + buffer.lines().map(|s| { + Self::normalize_enode(s).unwrap_or_else(|| { + die!("{}: Invalid node address format given for a reserved node.", s); + }) + }).collect() + } else { + Vec::new() + } + } + pub fn net_addresses(&self) -> (Option, Option) { let port = self.net_port(); let listen_address = Some(SocketAddr::new(IpAddr::from_str("0.0.0.0").unwrap(), port)); @@ -179,6 +199,8 @@ impl Configuration { let mut net_path = PathBuf::from(&self.path()); net_path.push("network"); ret.config_path = Some(net_path.to_str().unwrap().to_owned()); + ret.reserved_nodes = self.init_reserved_nodes(); + ret.reserved_only = self.args.flag_reserved_only; ret } diff --git a/parity/main.rs b/parity/main.rs index 9b3698c5c..3ccb7e430 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -315,10 +315,11 @@ fn execute_export(conf: Configuration) { udp_port: None, nat_enabled: false, discovery_enabled: false, - pin: true, + reserved_only: true, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 0, + reserved_nodes: Vec::new(), }; let client_config = conf.client_config(&spec); @@ -386,10 +387,11 @@ fn execute_import(conf: Configuration) { udp_port: None, nat_enabled: false, discovery_enabled: false, - pin: true, + reserved_only: true, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 0, + reserved_nodes: Vec::new(), }; let client_config = conf.client_config(&spec); diff --git a/rpc/src/v1/impls/ethcore_set.rs b/rpc/src/v1/impls/ethcore_set.rs index b07dcbf9e..cbd9c4309 100644 --- a/rpc/src/v1/impls/ethcore_set.rs +++ b/rpc/src/v1/impls/ethcore_set.rs @@ -74,5 +74,4 @@ impl EthcoreSet for EthcoreSetClient where M: MinerService + 'static { to_value(&true) }) } - } diff --git a/util/src/network/host.rs b/util/src/network/host.rs index aef56fc09..7e4b0c3a0 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -65,14 +65,16 @@ pub struct NetworkConfiguration { pub nat_enabled: bool, /// Enable discovery pub discovery_enabled: bool, - /// Pin to boot nodes only - pub pin: bool, + /// Pin to reserved nodes only + pub reserved_only: bool, /// List of initial node addresses pub boot_nodes: Vec, /// Use provided node key instead of default pub use_secret: Option, /// Number of connected peers to maintain pub ideal_peers: u32, + /// List of reserved node addresses. + pub reserved_nodes: Vec, } impl Default for NetworkConfiguration { @@ -91,10 +93,11 @@ impl NetworkConfiguration { udp_port: None, nat_enabled: true, discovery_enabled: true, - pin: false, + reserved_only: false, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 25, + reserved_nodes: Vec::new(), } } @@ -216,7 +219,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone pub fn send(&self, peer: PeerId, packet_id: PacketId, data: Vec) -> Result<(), UtilError> { let session = self.resolve_session(peer); if let Some(session) = session { - try!(session.lock().unwrap().deref_mut().send_packet(self.io, self.protocol, packet_id as u8, &data)); + try!(session.lock().unwrap().send_packet(self.io, self.protocol, packet_id as u8, &data)); } else { trace!(target: "network", "Send: Peer no longer exist") } @@ -365,6 +368,9 @@ impl Host where Message: Send + Sync + Clone { let udp_port = config.udp_port.unwrap_or(listen_address.port()); let local_endpoint = NodeEndpoint { address: listen_address, udp_port: udp_port }; + let boot_nodes = config.boot_nodes.clone(); + let reserved_nodes = config.reserved_nodes.clone(); + let mut host = Host:: { info: RwLock::new(HostInfo { keys: keys, @@ -389,21 +395,26 @@ impl Host where Message: Send + Sync + Clone { stopping: AtomicBool::new(false), }; - let boot_nodes = host.info.read().unwrap().config.boot_nodes.clone(); for n in boot_nodes { - host.add_node(&n); + // don't pin boot nodes. + host.add_node(&n, false); + } + + for n in reserved_nodes { + host.add_node(&n, true); } Ok(host) } - pub fn add_node(&mut self, id: &str) { + pub fn add_node(&mut self, id: &str, pin: bool) { match Node::from_str(id) { Err(e) => { debug!(target: "network", "Could not add node {}: {:?}", id, e); }, Ok(n) => { let entry = NodeEntry { endpoint: n.endpoint.clone(), id: n.id.clone() }; - self.pinned_nodes.push(n.id.clone()); + if pin { self.pinned_nodes.push(n.id.clone()) } + self.nodes.write().unwrap().add_node(n); - if let Some(ref mut discovery) = *self.discovery.lock().unwrap().deref_mut() { + if let Some(ref mut discovery) = *self.discovery.lock().unwrap() { discovery.add_node(entry); } } @@ -472,7 +483,7 @@ impl Host where Message: Send + Sync + Clone { // Initialize discovery. let discovery = { let info = self.info.read().unwrap(); - if info.config.discovery_enabled && !info.config.pin { + if info.config.discovery_enabled && !info.config.reserved_only { Some(Discovery::new(&info.keys, public_endpoint.address.clone(), public_endpoint, DISCOVERY)) } else { None } }; @@ -482,7 +493,7 @@ impl Host where Message: Send + Sync + Clone { for n in self.nodes.read().unwrap().unordered_entries() { discovery.add_node(n.clone()); } - *self.discovery.lock().unwrap().deref_mut() = Some(discovery); + *self.discovery.lock().unwrap() = Some(discovery); io.register_stream(DISCOVERY).expect("Error registering UDP listener"); io.register_timer(DISCOVERY_REFRESH, 7200).expect("Error registering discovery timer"); io.register_timer(DISCOVERY_ROUND, 300).expect("Error registering discovery timer"); @@ -529,14 +540,17 @@ impl Host where Message: Send + Sync + Clone { } fn connect_peers(&self, io: &IoContext>) { - if self.info.read().unwrap().deref().capabilities.is_empty() { + if self.info.read().unwrap().capabilities.is_empty() { return; } - let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; - let pin = { self.info.read().unwrap().deref().config.pin }; + let ideal_peers = { self.info.read().unwrap().config.ideal_peers }; + let pin = { self.info.read().unwrap().config.reserved_only }; let session_count = self.session_count(); - if session_count >= ideal_peers as usize { - return; + if session_count >= ideal_peers as usize + self.pinned_nodes.len() { + // check if all pinned nodes are connected. + if self.pinned_nodes.iter().all(|n| self.have_session(n) && self.connecting_to(n)) { + return; + } } let handshake_count = self.handshake_count(); @@ -546,9 +560,16 @@ impl Host where Message: Send + Sync + Clone { return; } - let nodes = if pin { self.pinned_nodes.clone() } else { self.nodes.read().unwrap().nodes() }; + // iterate over all nodes, reserved ones coming first. + // if we are pinned to only reserved nodes, ignore all others. + let nodes = self.pinned_nodes.iter().cloned().chain(if !pin { + self.nodes.read().unwrap().nodes() + } else { + Vec::new() + }); + let mut started: usize = 0; - for id in nodes.iter().filter(|ref id| !self.have_session(id) && !self.connecting_to(id)) + for id in nodes.filter(|ref id| !self.have_session(id) && !self.connecting_to(id)) .take(min(MAX_HANDSHAKES_PER_ROUND, handshake_limit - handshake_count)) { self.connect_peer(&id, io); started += 1; @@ -678,7 +699,7 @@ impl Host where Message: Send + Sync + Clone { self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); if !s.info.originated { let session_count = self.session_count(); - let ideal_peers = { self.info.read().unwrap().deref().config.ideal_peers }; + let ideal_peers = { self.info.read().unwrap().config.ideal_peers }; if session_count >= ideal_peers as usize { s.disconnect(io, DisconnectReason::TooManyPeers); return; @@ -900,7 +921,7 @@ impl IoHandler> for Host where Messa } => { let handler_token = { let mut timer_counter = self.timer_counter.write().unwrap(); - let counter = timer_counter.deref_mut(); + let counter = &mut *timer_counter; let handler_token = *counter; *counter += 1; handler_token @@ -944,7 +965,7 @@ impl IoHandler> for Host where Messa } } DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().register_socket(event_loop).expect("Error registering discovery socket"), - TCP_ACCEPT => event_loop.register(self.tcp_listener.lock().unwrap().deref(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error registering stream"), + TCP_ACCEPT => event_loop.register(&*self.tcp_listener.lock().unwrap(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error registering stream"), _ => warn!("Unexpected stream registration") } } @@ -972,7 +993,7 @@ impl IoHandler> for Host where Messa } } DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().update_registration(event_loop).expect("Error reregistering discovery socket"), - TCP_ACCEPT => event_loop.reregister(self.tcp_listener.lock().unwrap().deref(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error reregistering stream"), + TCP_ACCEPT => event_loop.reregister(&*self.tcp_listener.lock().unwrap(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error reregistering stream"), _ => warn!("Unexpected stream update") } } From 71c49eaaa276248a1008b743b2ce32e5e4bb2be4 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 20 Jun 2016 14:19:02 +0200 Subject: [PATCH 113/239] removed redundant bigint deps --- Cargo.lock | 2 -- util/bigint/Cargo.toml | 2 -- 2 files changed, 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2ac272e7c..03ea96029 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,9 +67,7 @@ dependencies = [ name = "bigint" version = "0.1.0" dependencies = [ - "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/util/bigint/Cargo.toml b/util/bigint/Cargo.toml index 1bd2b994e..fe9101df7 100644 --- a/util/bigint/Cargo.toml +++ b/util/bigint/Cargo.toml @@ -12,8 +12,6 @@ rustc_version = "0.1" [dependencies] rustc-serialize = "0.3" -arrayvec = "0.3" -rand = "0.3.12" serde = "0.7.0" heapsize = "0.3" From da7b30628b310e4247481e03170bb9a46c4e0d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 20 Jun 2016 15:20:55 +0200 Subject: [PATCH 114/239] Fixing warnings --- ethcore/src/account_provider.rs | 1 - parity/configuration.rs | 7 ++++--- parity/io_handler.rs | 5 ++--- parity/main.rs | 2 +- util/src/network/host.rs | 9 +++------ 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/ethcore/src/account_provider.rs b/ethcore/src/account_provider.rs index 3c79cfd52..6744c6bd2 100644 --- a/ethcore/src/account_provider.rs +++ b/ethcore/src/account_provider.rs @@ -236,7 +236,6 @@ impl AccountProvider { #[cfg(test)] mod tests { use super::AccountProvider; - use ethstore::SecretStore; use ethstore::ethkey::{Generator, Random}; #[test] diff --git a/parity/configuration.rs b/parity/configuration.rs index 7c42f06e1..967a07a07 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -263,9 +263,10 @@ impl Configuration { }).collect::>(); if !self.args.flag_no_import_keys { - let dir_type = match self.args.flag_testnet { - true => DirectoryType::Testnet, - false => DirectoryType::Main, + let dir_type = if self.args.flag_testnet { + DirectoryType::Testnet + } else { + DirectoryType::Main }; let from = GethDirectory::open(dir_type); diff --git a/parity/io_handler.rs b/parity/io_handler.rs index a94582b1d..3f0c04fbd 100644 --- a/parity/io_handler.rs +++ b/parity/io_handler.rs @@ -39,9 +39,8 @@ impl IoHandler for ClientIoHandler { } fn timeout(&self, _io: &IoContext, timer: TimerToken) { - match timer { - INFO_TIMER => { self.info.tick(&self.client, Some(&self.sync)); } - _ => {} + if let INFO_TIMER = timer { + self.info.tick(&self.client, Some(&self.sync)); } } diff --git a/parity/main.rs b/parity/main.rs index 9b3698c5c..1397de8c7 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -485,7 +485,7 @@ fn execute_signer(conf: Configuration) { } fn execute_account_cli(conf: Configuration) { - use ethcore::ethstore::{SecretStore, EthStore, import_accounts}; + use ethcore::ethstore::{EthStore, import_accounts}; use ethcore::ethstore::dir::DiskDirectory; use ethcore::account_provider::AccountProvider; use rpassword::read_password; diff --git a/util/src/network/host.rs b/util/src/network/host.rs index aef56fc09..92d6a77ae 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -663,13 +663,10 @@ impl Host where Message: Send + Sync + Clone { match s.readable(io, &self.info.read().unwrap()) { Err(e) => { trace!(target: "network", "Session read error: {}:{:?} ({:?}) {:?}", token, s.id(), s.remote_addr(), e); - match e { - UtilError::Network(NetworkError::Disconnect(DisconnectReason::IncompatibleProtocol)) => { - if let Some(id) = s.id() { - self.nodes.write().unwrap().mark_as_useless(id); - } + if let UtilError::Network(NetworkError::Disconnect(DisconnectReason::IncompatibleProtocol)) = e { + if let Some(id) = s.id() { + self.nodes.write().unwrap().mark_as_useless(id); } - _ => (), } kill = true; break; From 7b9db37d84dfe34e209dd5c0489b7ace08b413d7 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 20 Jun 2016 16:29:04 +0200 Subject: [PATCH 115/239] removed unnecessary logs --- parity/configuration.rs | 5 ++--- parity/migration.rs | 12 ++++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index 7c42f06e1..a20d6cdd2 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -270,9 +270,8 @@ impl Configuration { let from = GethDirectory::open(dir_type); let to = DiskDirectory::create(self.keys_path()).unwrap(); - if let Err(e) = import_accounts(&from, &to) { - warn!("Could not import accounts {}", e); - } + // ignore error, cause geth may not exist + let _ = import_accounts(&from, &to); } let dir = Box::new(DiskDirectory::create(self.keys_path()).unwrap()); diff --git a/parity/migration.rs b/parity/migration.rs index acfd32ffd..e2a25723f 100644 --- a/parity/migration.rs +++ b/parity/migration.rs @@ -151,8 +151,6 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) - return Ok(()) } - println!("Migrating database {} from version {} to {}", path.to_string_lossy(), version, CURRENT_VERSION); - let temp_path = temp_database_path(&path); let backup_path = backup_database_path(&path); // remote the dir if it exists @@ -187,20 +185,26 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) - // remove backup try!(fs::remove_dir_all(&backup_path)); - println!("Migration finished"); Ok(()) } +fn exists(path: &PathBuf) -> bool { + fs::metadata(path).is_ok() +} + /// Migrates the database. pub fn migrate(path: &PathBuf) -> Result<(), Error> { // read version file. let version = try!(current_version(path)); // migrate the databases. - if version != CURRENT_VERSION { + // main db directory may already exists, so let's check if we have blocks dir + if version != CURRENT_VERSION && exists(&blocks_database_path(path)) { + println!("Migrating database from version {} to {}", version, CURRENT_VERSION); try!(migrate_database(version, blocks_database_path(path), try!(blocks_database_migrations()))); try!(migrate_database(version, extras_database_path(path), try!(extras_database_migrations()))); + println!("Migration finished"); } // update version file. From 1ffe0c185cc3b2ac9a7cf158ef861ee87dcfda85 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 20 Jun 2016 17:28:48 +0200 Subject: [PATCH 116/239] Reduce locking --- sync/src/chain.rs | 58 +++++++++++++++++++++++---------------- sync/src/lib.rs | 2 +- sync/src/tests/chain.rs | 6 ++-- sync/src/tests/helpers.rs | 16 +++++------ 4 files changed, 47 insertions(+), 35 deletions(-) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 6ec0884b5..3b608610d 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1097,7 +1097,7 @@ impl ChainSync { Ok(Some((RECEIPTS_PACKET, rlp_result))) } - fn return_rlp(&self, io: &mut SyncIo, rlp: &UntrustedRlp, peer: PeerId, rlp_func: FRlp, error_func: FError) -> Result<(), PacketDecodeError> + fn return_rlp(io: &mut SyncIo, rlp: &UntrustedRlp, peer: PeerId, rlp_func: FRlp, error_func: FError) -> Result<(), PacketDecodeError> where FRlp : Fn(&SyncIo, &UntrustedRlp, PeerId) -> RlpResponseResult, FError : FnOnce(UtilError) -> String { @@ -1114,13 +1114,41 @@ impl ChainSync { } /// Dispatch incoming requests and responses - pub fn on_packet(&mut self, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { + pub fn dispatch_packet(sync: &RwLock, io: &mut SyncIo, peer: PeerId, packet_id: u8, data: &[u8]) { let rlp = UntrustedRlp::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)), + + _ => { + sync.write().unwrap().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]) { if packet_id != STATUS_PACKET && !self.peers.contains_key(&peer) { debug!(target:"sync", "Unexpected packet from unregistered peer: {}:{}", peer, io.peer_info(peer)); return; } + let rlp = UntrustedRlp::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), @@ -1128,23 +1156,6 @@ impl ChainSync { BLOCK_BODIES_PACKET => self.on_peer_block_bodies(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), - - GET_BLOCK_BODIES_PACKET => self.return_rlp(io, &rlp, peer, - ChainSync::return_block_bodies, - |e| format!("Error sending block bodies: {:?}", e)), - - GET_BLOCK_HEADERS_PACKET => self.return_rlp(io, &rlp, peer, - ChainSync::return_block_headers, - |e| format!("Error sending block headers: {:?}", e)), - - GET_RECEIPTS_PACKET => self.return_rlp(io, &rlp, peer, - ChainSync::return_receipts, - |e| format!("Error sending receipts: {:?}", e)), - - GET_NODE_DATA_PACKET => self.return_rlp(io, &rlp, peer, - ChainSync::return_node_data, - |e| format!("Error sending nodes: {:?}", e)), - _ => { debug!(target: "sync", "Unknown packet {}", packet_id); Ok(()) @@ -1424,7 +1435,7 @@ mod tests { fn return_receipts() { let mut client = TestBlockChainClient::new(); let mut queue = VecDeque::new(); - let mut sync = dummy_sync_with_peer(H256::new(), &client); + let sync = dummy_sync_with_peer(H256::new(), &client); let mut io = TestIo::new(&mut client, &mut queue, None); let mut receipt_list = RlpStream::new_list(4); @@ -1445,7 +1456,7 @@ mod tests { assert_eq!(603, rlp_result.unwrap().1.out().len()); io.sender = Some(2usize); - sync.on_packet(&mut io, 0usize, super::GET_RECEIPTS_PACKET, &receipts_request); + ChainSync::dispatch_packet(&RwLock::new(sync), &mut io, 0usize, super::GET_RECEIPTS_PACKET, &receipts_request); assert_eq!(1, io.queue.len()); } @@ -1517,7 +1528,7 @@ mod tests { fn return_nodes() { let mut client = TestBlockChainClient::new(); let mut queue = VecDeque::new(); - let mut sync = dummy_sync_with_peer(H256::new(), &client); + let sync = dummy_sync_with_peer(H256::new(), &client); let mut io = TestIo::new(&mut client, &mut queue, None); let mut node_list = RlpStream::new_list(3); @@ -1537,7 +1548,8 @@ mod tests { assert_eq!(34, rlp_result.unwrap().1.out().len()); io.sender = Some(2usize); - sync.on_packet(&mut io, 0usize, super::GET_NODE_DATA_PACKET, &node_request); + + ChainSync::dispatch_packet(&RwLock::new(sync), &mut io, 0usize, super::GET_NODE_DATA_PACKET, &node_request); assert_eq!(1, io.queue.len()); } diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 86f70ff0a..27961e867 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -169,7 +169,7 @@ impl NetworkProtocolHandler for EthSync { } fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) { - self.sync.write().unwrap().on_packet(&mut NetSyncIo::new(io, self.chain.deref()) , *peer, packet_id, data); + ChainSync::dispatch_packet(&self.sync, &mut NetSyncIo::new(io, self.chain.deref()) , *peer, packet_id, data); } fn connected(&self, io: &NetworkContext, peer: &PeerId) { diff --git a/sync/src/tests/chain.rs b/sync/src/tests/chain.rs index 7c7d70dde..2f2bde171 100644 --- a/sync/src/tests/chain.rs +++ b/sync/src/tests/chain.rs @@ -47,7 +47,7 @@ fn status_after_sync() { net.peer_mut(1).chain.add_blocks(1000, EachBlockWith::Uncle); net.peer_mut(2).chain.add_blocks(1000, EachBlockWith::Uncle); net.sync(); - let status = net.peer(0).sync.status(); + let status = net.peer(0).sync.read().unwrap().status(); assert_eq!(status.state, SyncState::Idle); } @@ -107,14 +107,14 @@ fn restart() { assert!(net.peer(0).chain.chain_info().best_block_number > 100); net.restart_peer(0); - let status = net.peer(0).sync.status(); + let status = net.peer(0).sync.read().unwrap().status(); assert_eq!(status.state, SyncState::ChainHead); } #[test] fn status_empty() { let net = TestNet::new(2); - assert_eq!(net.peer(0).sync.status().state, SyncState::Idle); + assert_eq!(net.peer(0).sync.read().unwrap().status().state, SyncState::Idle); } #[test] diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index 6496a43d5..831976048 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -78,7 +78,7 @@ pub struct TestPacket { pub struct TestPeer { pub chain: TestBlockChainClient, - pub sync: ChainSync, + pub sync: RwLock, pub queue: VecDeque, } @@ -97,7 +97,7 @@ impl TestNet { let chain = TestBlockChainClient::new(); let sync = ChainSync::new(SyncConfig::default(), &chain); net.peers.push(TestPeer { - sync: sync, + sync: RwLock::new(sync), chain: chain, queue: VecDeque::new(), }); @@ -118,7 +118,7 @@ impl TestNet { for client in 0..self.peers.len() { if peer != client { let mut p = self.peers.get_mut(peer).unwrap(); - p.sync.on_peer_connected(&mut TestIo::new(&mut p.chain, &mut p.queue, Some(client as PeerId)), client as PeerId); + p.sync.write().unwrap().on_peer_connected(&mut TestIo::new(&mut p.chain, &mut p.queue, Some(client as PeerId)), client as PeerId); } } } @@ -129,22 +129,22 @@ impl TestNet { if let Some(packet) = self.peers[peer].queue.pop_front() { let mut p = self.peers.get_mut(packet.recipient).unwrap(); trace!("--- {} -> {} ---", peer, packet.recipient); - p.sync.on_packet(&mut TestIo::new(&mut p.chain, &mut p.queue, Some(peer as PeerId)), peer as PeerId, packet.packet_id, &packet.data); + ChainSync::dispatch_packet(&p.sync, &mut TestIo::new(&mut p.chain, &mut p.queue, Some(peer as PeerId)), peer as PeerId, packet.packet_id, &packet.data); trace!("----------------"); } let mut p = self.peers.get_mut(peer).unwrap(); - p.sync.maintain_sync(&mut TestIo::new(&mut p.chain, &mut p.queue, None)); + p.sync.write().unwrap().maintain_sync(&mut TestIo::new(&mut p.chain, &mut p.queue, None)); } } pub fn sync_step_peer(&mut self, peer_num: usize) { let mut peer = self.peer_mut(peer_num); - peer.sync.maintain_sync(&mut TestIo::new(&mut peer.chain, &mut peer.queue, None)); + peer.sync.write().unwrap().maintain_sync(&mut TestIo::new(&mut peer.chain, &mut peer.queue, None)); } pub fn restart_peer(&mut self, i: usize) { let peer = self.peer_mut(i); - peer.sync.restart(&mut TestIo::new(&mut peer.chain, &mut peer.queue, None)); + peer.sync.write().unwrap().restart(&mut TestIo::new(&mut peer.chain, &mut peer.queue, None)); } pub fn sync(&mut self) -> u32 { @@ -173,6 +173,6 @@ impl TestNet { pub fn trigger_chain_new_blocks(&mut self, peer_id: usize) { let mut peer = self.peer_mut(peer_id); - peer.sync.chain_new_blocks(&mut TestIo::new(&mut peer.chain, &mut peer.queue, None), &[], &[], &[], &[]); + peer.sync.write().unwrap().chain_new_blocks(&mut TestIo::new(&mut peer.chain, &mut peer.queue, None), &[], &[], &[], &[]); } } From 0716eaa036c451b01bcb936037518ce9865d62bd Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 20 Jun 2016 17:50:38 +0200 Subject: [PATCH 117/239] docopt is an optional dependency of ethkey and ethstore --- Cargo.lock | 2 -- ethkey/Cargo.toml | 2 +- ethstore/Cargo.toml | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2ac272e7c..0b1e73cae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -426,7 +426,6 @@ dependencies = [ name = "ethkey" version = "0.2.0" dependencies = [ - "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", "eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -438,7 +437,6 @@ dependencies = [ name = "ethstore" version = "0.1.0" dependencies = [ - "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.2.0", "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ethkey/Cargo.toml b/ethkey/Cargo.toml index 08461e865..c7b99e45c 100644 --- a/ethkey/Cargo.toml +++ b/ethkey/Cargo.toml @@ -12,7 +12,7 @@ rustc-serialize = "0.3" docopt = { version = "0.6", optional = true } [features] -default = ["cli"] +default = [] cli = ["docopt"] [[bin]] diff --git a/ethstore/Cargo.toml b/ethstore/Cargo.toml index 41504154d..cfb5b9fbc 100644 --- a/ethstore/Cargo.toml +++ b/ethstore/Cargo.toml @@ -21,7 +21,7 @@ serde_codegen = { version = "0.7", optional = true } syntex = "0.33.0" [features] -default = ["cli", "serde_codegen"] +default = ["serde_codegen"] nightly = ["serde_macros"] cli = ["docopt"] From 8fa9a240ccfe1e4b32ef611939f1bf8d1cfcf66e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 20 Jun 2016 18:33:08 +0200 Subject: [PATCH 118/239] Fixing last nonce values in case transaction is replaced --- ethcore/src/miner/transaction_queue.rs | 53 +++++++++++++++++++------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 30ebc133f..cc8430b42 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -236,8 +236,8 @@ impl TransactionSet { self.by_priority.insert(order.clone()); let r = self.by_address.insert(sender, nonce, order); // If transaction was replaced remove it from priority queue - if let Some(ref order) = r { - self.by_priority.remove(order); + if let Some(ref old_order) = r { + self.by_priority.remove(old_order); } r } @@ -517,16 +517,9 @@ impl TransactionQueue { // Remove from current let order = self.current.drop(&sender, &nonce); if order.is_some() { - // We will either move transaction to future or remove it completely - // so there will be no transactions from this sender in current - self.last_nonces.remove(&sender); - // First update height of transactions in future to avoid collisions - self.update_future(&sender, current_nonce); - // This should move all current transactions to future and remove old transactions - self.move_all_to_future(&sender, current_nonce); - // And now lets check if there is some chain of transactions in future - // that should be placed in current. It should also update last_nonces. - self.move_matching_future_to_current(sender, current_nonce, current_nonce); + // This will keep consistency in queue + // Moves all to future and then promotes a batch from current: + self.remove_all(sender, current_nonce); return; } } @@ -682,7 +675,8 @@ impl TransactionQueue { try!(check_too_cheap(Self::replace_transaction(tx, state_nonce, &mut self.current, &mut self.by_hash))); // Keep track of highest nonce stored in current - self.last_nonces.insert(address, nonce); + let new_max = self.last_nonces.get(&address).map_or(nonce, |n| cmp::max(nonce, *n)); + self.last_nonces.insert(address, new_max); // Update nonces of transactions in future self.update_future(&address, state_nonce); // Maybe there are some more items waiting in future? @@ -1597,4 +1591,37 @@ mod test { assert_eq!(txq.future.by_priority.iter().next().unwrap().hash, tx1.hash()); } + #[test] + fn should_return_correct_last_nonce() { + // given + let mut txq = TransactionQueue::new(); + let (tx1, tx2, tx2_2, tx3) = { + let keypair = KeyPair::create().unwrap(); + let secret = &keypair.secret(); + let nonce = U256::from(123); + let tx = new_unsigned_tx(nonce); + let tx2 = new_unsigned_tx(nonce + 1.into()); + let mut tx2_2 = new_unsigned_tx(nonce + 1.into()); + tx2_2.gas_price = U256::from(5); + let tx3 = new_unsigned_tx(nonce + 2.into()); + + + (tx.sign(secret), tx2.sign(secret), tx2_2.sign(secret), tx3.sign(secret)) + }; + let sender = tx1.sender().unwrap(); + txq.add(tx1, &default_nonce, TransactionOrigin::Local).unwrap(); + txq.add(tx2, &default_nonce, TransactionOrigin::Local).unwrap(); + txq.add(tx3, &default_nonce, TransactionOrigin::Local).unwrap(); + assert_eq!(txq.future.by_priority.len(), 0); + assert_eq!(txq.current.by_priority.len(), 3); + + // when + let res = txq.add(tx2_2, &default_nonce, TransactionOrigin::Local); + + // then + assert_eq!(txq.last_nonce(&sender).unwrap(), 125.into()); + assert_eq!(res.unwrap(), TransactionImportResult::Current); + assert_eq!(txq.current.by_priority.len(), 3); + } + } From 09b8116cde1610384b5bf3f05f1e6794ec4f5654 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sun, 19 Jun 2016 14:35:42 +0200 Subject: [PATCH 119/239] TX processing queue --- ethcore/src/client/client.rs | 39 ++++++++++++++++++++++- ethcore/src/client/mod.rs | 3 ++ ethcore/src/client/test_client.rs | 6 ++++ ethcore/src/service.rs | 5 +++ sync/src/chain.rs | 11 +++---- util/src/lib.rs | 2 ++ util/src/timer.rs | 51 +++++++++++++++++++++++++++++++ 7 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 util/src/timer.rs diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 85a3d693d..afba6a893 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -18,6 +18,7 @@ use std::marker::PhantomData; use std::path::PathBuf; +use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use util::*; use util::panics::*; use views::BlockView; @@ -50,6 +51,8 @@ pub use types::block_status::BlockStatus; use evm::Factory as EvmFactory; use miner::{Miner, MinerService, TransactionImportResult, AccountDetails}; +const MAX_TX_QUEUE_SIZE: usize = 4096; + impl fmt::Display for BlockChainInfo { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "#{}.{}", self.best_block_number, self.best_block_hash) @@ -92,6 +95,8 @@ pub struct Client where V: Verifier { verifier: PhantomData, vm_factory: Arc, miner: Arc, + io_channel: IoChannel, + queue_transactions: AtomicUsize, } const HISTORY: u64 = 1200; @@ -149,7 +154,7 @@ impl Client where V: Verifier { let engine = Arc::new(spec.engine); - let block_queue = BlockQueue::new(config.queue, engine.clone(), message_channel); + let block_queue = BlockQueue::new(config.queue, engine.clone(), message_channel.clone()); let panic_handler = PanicHandler::new_in_arc(); panic_handler.forward_from(&block_queue); @@ -165,6 +170,8 @@ impl Client where V: Verifier { verifier: PhantomData, vm_factory: Arc::new(EvmFactory::new(config.vm_type)), miner: miner, + io_channel: message_channel, + queue_transactions: AtomicUsize::new(0), }; Ok(Arc::new(client)) @@ -271,6 +278,7 @@ impl Client where V: Verifier { let mut import_results = Vec::with_capacity(max_blocks_to_import); let _import_lock = self.import_lock.lock(); + let _timer = PerfTimer::new("import_verified_blocks"); let blocks = self.block_queue.drain(max_blocks_to_import); let original_best = self.chain_info().best_block_hash; @@ -361,6 +369,19 @@ impl Client where V: Verifier { imported } + /// Import transactions from the IO queue + pub fn import_queued_transactions(&self, transactions: &[Bytes]) -> usize { + let _timer = PerfTimer::new("import_queued_transactions"); + self.queue_transactions.fetch_sub(transactions.len(), AtomicOrdering::SeqCst); + let fetch_account = |a: &Address| AccountDetails { + nonce: self.latest_nonce(a), + balance: self.latest_balance(a), + }; + let tx = transactions.iter().filter_map(|bytes| UntrustedRlp::new(&bytes).as_val().ok()).collect(); + let results = self.miner.import_transactions(tx, fetch_account); + results.len() + } + /// Attempt to get a copy of a specific block's state. /// /// This will not fail if given BlockID::Latest. @@ -750,6 +771,22 @@ impl BlockChainClient for Client where V: Verifier { self.miner.import_transactions(transactions, fetch_account) } + fn queue_transactions(&self, transactions: Vec) { + if self.queue_transactions.load(AtomicOrdering::Relaxed) > MAX_TX_QUEUE_SIZE { + debug!("Ignoring {} transactions: queue is full", transactions.len()); + } else { + let len = transactions.len(); + match self.io_channel.send(NetworkIoMessage::User(SyncMessage::NewTransactions(transactions))) { + Ok(_) => { + self.queue_transactions.fetch_add(len, AtomicOrdering::SeqCst); + } + Err(e) => { + debug!("Ignoring {} transactions: error queueing: {}", len, e); + } + } + } + } + fn all_transactions(&self) -> Vec { self.miner.all_transactions() } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 3fec68815..9318e0185 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -193,6 +193,9 @@ pub trait BlockChainClient : Sync + Send { /// import transactions from network/other 3rd party fn import_transactions(&self, transactions: Vec) -> Vec>; + /// Queue transactions for importing. + fn queue_transactions(&self, transactions: Vec); + /// list all transactions fn all_transactions(&self) -> Vec; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index a9f7f6300..b6cc946fc 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -493,6 +493,12 @@ impl BlockChainClient for TestBlockChainClient { self.miner.import_transactions(transactions, &fetch_account) } + fn queue_transactions(&self, transactions: Vec) { + // import right here + let tx = transactions.into_iter().filter_map(|bytes| UntrustedRlp::new(&bytes).as_val().ok()).collect(); + self.import_transactions(tx); + } + fn all_transactions(&self) -> Vec { self.miner.all_transactions() } diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index d9040113f..03a85ce13 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -41,6 +41,8 @@ pub enum SyncMessage { NewChainHead, /// A block is ready BlockVerified, + /// New transaction RLPs are ready to be imported + NewTransactions(Vec), /// Start network command. StartNetwork, /// Stop network command. @@ -136,6 +138,9 @@ impl IoHandler for ClientIoHandler { SyncMessage::BlockVerified => { self.client.import_verified_blocks(&io.channel()); }, + SyncMessage::NewTransactions(ref transactions) => { + self.client.import_queued_transactions(&transactions); + }, _ => {}, // ignore other messages } } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 6ec0884b5..167b9df40 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -95,7 +95,6 @@ use ethcore::views::{HeaderView, BlockView}; use ethcore::header::{BlockNumber, Header as BlockHeader}; use ethcore::client::{BlockChainClient, BlockStatus, BlockID, BlockChainInfo}; use ethcore::error::*; -use ethcore::transaction::SignedTransaction; use ethcore::block::Block; use io::SyncIo; use time; @@ -940,15 +939,15 @@ impl ChainSync { return Ok(()); } - let item_count = r.item_count(); + let mut item_count = r.item_count(); trace!(target: "sync", "{} -> Transactions ({} entries)", peer_id, item_count); - + item_count = min(item_count, MAX_TX_TO_IMPORT); let mut transactions = Vec::with_capacity(item_count); - for i in 0 .. min(item_count, MAX_TX_TO_IMPORT) { - let tx: SignedTransaction = try!(r.val_at(i)); + for i in 0 .. item_count { + let tx = try!(r.at(i)).as_raw().to_vec(); transactions.push(tx); } - let _ = io.chain().import_transactions(transactions); + let _ = io.chain().queue_transactions(transactions); Ok(()) } diff --git a/util/src/lib.rs b/util/src/lib.rs index e43bbbab0..adaf08e77 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -154,6 +154,7 @@ pub mod panics; pub mod table; pub mod network_settings; pub mod path; +mod timer; pub use common::*; pub use misc::*; @@ -175,6 +176,7 @@ pub use network::*; pub use io::*; pub use log::*; pub use kvdb::*; +pub use timer::*; #[cfg(test)] mod tests { diff --git a/util/src/timer.rs b/util/src/timer.rs new file mode 100644 index 000000000..5d95ff7de --- /dev/null +++ b/util/src/timer.rs @@ -0,0 +1,51 @@ +// Copyright 2015, 2016 Ethcore (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 . + +//! Performance timer with logging +use time::precise_time_ns; + +/// Performance timer with logging. Starts measuring time in the constructor, prints +/// elapsed time in the destructor or when `stop` is called. +pub struct PerfTimer { + name: &'static str, + start: u64, + stopped: bool, +} + +impl PerfTimer { + /// Create an instance with given name. + pub fn new(name: &'static str) -> PerfTimer { + PerfTimer { + name: name, + start: precise_time_ns(), + stopped: false, + } + } + + /// Stop the timer and print elapsed time on trace level with `perf` target. + pub fn stop(&mut self) { + if !self.stopped { + trace!(target: "perf", "{}: {:.2}ms", self.name, (precise_time_ns() - self.start) as f32 / 1000_000.0); + self.stopped = true; + } + } +} + +impl Drop for PerfTimer { + fn drop(&mut self) { + self.stop() + } +} From 71bfda3534c76ffdb6429ee1eabce476c9d7c56f Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Mon, 20 Jun 2016 18:51:11 +0200 Subject: [PATCH 120/239] moved keystore tests files from util to ethstore (#1352) --- ethstore/tests/api.rs | 41 ++++++++++++++++++- ...--3f49624084b67849c7b4e805c5988c21a430f9d9 | 0 ...--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf | 0 ...--63121b431a52f8043c16fcf0d1df9cb7b5f66649 | 2 +- {util => ethstore/tests}/res/pat/p1.json | 0 {util => ethstore/tests}/res/pat/p2.json | 0 6 files changed, 41 insertions(+), 2 deletions(-) rename {util => ethstore/tests}/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 (100%) rename {util => ethstore/tests}/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf (100%) rename {util => ethstore/tests}/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 (91%) rename {util => ethstore/tests}/res/pat/p1.json (100%) rename {util => ethstore/tests}/res/pat/p2.json (100%) diff --git a/ethstore/tests/api.rs b/ethstore/tests/api.rs index 037c5c46c..3b6a9f784 100644 --- a/ethstore/tests/api.rs +++ b/ethstore/tests/api.rs @@ -19,8 +19,10 @@ extern crate ethstore; mod util; +use std::str::FromStr; use ethstore::{SecretStore, EthStore}; -use ethstore::ethkey::{Random, Generator, Secret}; +use ethstore::ethkey::{Random, Generator, Secret, Address}; +use ethstore::dir::DiskDirectory; use util::TransientDir; #[test] @@ -86,3 +88,40 @@ fn secret_store_remove_account() { assert_eq!(store.accounts().len(), 0); assert!(store.remove_account(&accounts[0], "").is_err()); } + +fn test_path() -> &'static str { + match ::std::fs::metadata("ethstore") { + Ok(_) => "ethstore/tests/res/geth_keystore", + Err(_) => "tests/res/geth_keystore", + } +} + +fn pat_path() -> &'static str { + match ::std::fs::metadata("ethstore") { + Ok(_) => "ethstore/tests/res/pat", + Err(_) => "tests/res/pat", + } +} + +#[test] +fn secret_store_laod_geth_files() { + let dir = DiskDirectory::at(test_path()); + let store = EthStore::open(Box::new(dir)).unwrap(); + assert_eq!(store.accounts(), vec![ + Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap(), + Address::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap(), + Address::from_str("63121b431a52f8043c16fcf0d1df9cb7b5f66649").unwrap(), + ]); +} + +#[test] +fn secret_store_load_pat_files() { + let dir = DiskDirectory::at(pat_path()); + let store = EthStore::open(Box::new(dir)).unwrap(); + assert_eq!(store.accounts(), vec![ + Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap(), + Address::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap(), + ]); +} + + diff --git a/util/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 b/ethstore/tests/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 similarity index 100% rename from util/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 rename to ethstore/tests/res/geth_keystore/UTC--2016-02-17T09-20-45.721400158Z--3f49624084b67849c7b4e805c5988c21a430f9d9 diff --git a/util/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf b/ethstore/tests/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf similarity index 100% rename from util/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf rename to ethstore/tests/res/geth_keystore/UTC--2016-02-20T09-33-03.984382741Z--5ba4dcf897e97c2bdf8315b9ef26c13c085988cf diff --git a/util/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 b/ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 similarity index 91% rename from util/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 rename to ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 index 08272d43b..a3253e29a 100644 --- a/util/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 +++ b/ethstore/tests/res/geth_keystore/UTC--2016-04-03T08-58-49.834202900Z--63121b431a52f8043c16fcf0d1df9cb7b5f66649 @@ -1 +1 @@ -{"address":"63121b431a52f8043c16fcf0d1df9cb7b5f66649","crypto":{"cipher":"aes-128-ctr","ciphertext":"1dd21926c644b9983916d646f3a4f2c7f9362f7e1c9fb1abcb42494dae06fa01","cipherparams":{"iv":"c52c6ee66d89a7aa8c6839f4b6ed29c8"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"96f17c17bbf48db2dc4da00b3e7decce8e21f44a5d7963dadeeff70e1d38ad75"},"mac":"f279f3444585c2817701225e2196c1176386ad549ebaec2bcc4f94f309727fe6"},"id":"15e49cd2-51fb-4316-ba46-c3cf8db4ae44","version":3} \ No newline at end of file +{"address":"63121b431a52f8043c16fcf0d1df9cb7b5f66649","crypto":{"cipher":"aes-128-ctr","ciphertext":"1dd21926c644b9983916d646f3a4f2c7f9362f7e1c9fb1abcb42494dae06fa01","cipherparams":{"iv":"c52c6ee66d89a7aa8c6839f4b6ed29c8"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"96f17c17bbf48db2dc4da00b3e7decce8e21f44a5d7963dadeeff70e1d38ad75"},"mac":"f279f3444585c2817701225e2196c1176386ad549ebaec2bcc4f94f309727fe6"},"id":"15e49cd2-51fb-4316-ba46-c3cf8db4ae44","version":3} diff --git a/util/res/pat/p1.json b/ethstore/tests/res/pat/p1.json similarity index 100% rename from util/res/pat/p1.json rename to ethstore/tests/res/pat/p1.json diff --git a/util/res/pat/p2.json b/ethstore/tests/res/pat/p2.json similarity index 100% rename from util/res/pat/p2.json rename to ethstore/tests/res/pat/p2.json From 69c29fce84c13d2298588fc18464573aa7cf317c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 20 Jun 2016 18:51:36 +0200 Subject: [PATCH 121/239] Updating parity-dapps (#1353) --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 03ea96029..f62ed5cae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -924,7 +924,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "parity-dapps" version = "0.3.0" -source = "git+https://github.com/ethcore/parity-dapps-rs.git#1f065d93aa49338e4a453c77c839957f2db78895" +source = "git+https://github.com/ethcore/parity-dapps-rs.git#8cc812c26c903cf5764ce0f4cc3f2a7c3ddb0dc2" dependencies = [ "aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", From 72debeebcfda85fd6a4a6d6e6ad3edc986a355b0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 20 Jun 2016 20:47:07 +0200 Subject: [PATCH 122/239] Update code hash. --- ethcore/src/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index c5bfe09cd..30856a975 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -222,7 +222,7 @@ impl State { let options = TransactOptions { tracing: tracing, vm_tracing: false, check_nonce: true }; let e = try!(Executive::new(self, env_info, engine, vm_factory).transact(t, options)); - let broken_dao = H256::from("7278d050619a624f84f51987149ddb439cdaadfba5966f7cfaea7ad44340a4ba"); + let broken_dao = H256::from("6a5d24750f78441e56fec050dc52fe8e911976485b7472faac7464a176a67caa"); // dao attack soft fork if engine.schedule(&env_info).reject_dao_transactions { From d874555310db1708ee2e9475b808ccb85b2cf61b Mon Sep 17 00:00:00 2001 From: NikVolf Date: Mon, 20 Jun 2016 22:45:24 +0300 Subject: [PATCH 123/239] make default 100mb file size --- Cargo.lock | 4 ++-- util/src/kvdb.rs | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03ea96029..1bae73b40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1105,7 +1105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rocksdb" version = "0.4.5" -source = "git+https://github.com/ethcore/rust-rocksdb#9140e37ce0fdb748097f85653c01b0f7e3736ea9" +source = "git+https://github.com/ethcore/rust-rocksdb#8f6e43b2d8799578a378648bcb17c01fb431dbec" dependencies = [ "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)", @@ -1114,7 +1114,7 @@ dependencies = [ [[package]] name = "rocksdb-sys" version = "0.3.0" -source = "git+https://github.com/ethcore/rust-rocksdb#9140e37ce0fdb748097f85653c01b0f7e3736ea9" +source = "git+https://github.com/ethcore/rust-rocksdb#8f6e43b2d8799578a378648bcb17c01fb431dbec" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 7d581fdbc..c71934cc3 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -20,6 +20,9 @@ use std::default::Default; use rocksdb::{DB, Writable, WriteBatch, IteratorMode, DBVector, DBIterator, IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; +const DB_FILE_SIZE_BASE: u64 = 100 * 1024 * 1024; +const DB_FILE_SIZE_MULTIPLIER: usize = 10; + /// Write transaction. Batches a sequence of put/delete operations for efficiency. pub struct DBTransaction { batch: WriteBatch, @@ -110,6 +113,8 @@ impl Database { opts.create_if_missing(true); opts.set_use_fsync(false); opts.set_compaction_style(DBCompactionStyle::DBUniversalCompaction); + opts.set_target_file_size_base(DB_FILE_SIZE_BASE); + opts.set_target_file_size_multiplier(DB_FILE_SIZE_MULTIPLIER); if let Some(cache_size) = config.cache_size { // half goes to read cache opts.set_block_cache_size_mb(cache_size as u64 / 2); From f4f842f48e51b9f4bb534d613cce843bc6e54020 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Mon, 20 Jun 2016 22:52:31 +0300 Subject: [PATCH 124/239] update again --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1bae73b40..7f901eb45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1105,7 +1105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rocksdb" version = "0.4.5" -source = "git+https://github.com/ethcore/rust-rocksdb#8f6e43b2d8799578a378648bcb17c01fb431dbec" +source = "git+https://github.com/ethcore/rust-rocksdb#e0e6c099d8cd156fe446009fce241d57b00cd8f4" dependencies = [ "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)", @@ -1114,7 +1114,7 @@ dependencies = [ [[package]] name = "rocksdb-sys" version = "0.3.0" -source = "git+https://github.com/ethcore/rust-rocksdb#8f6e43b2d8799578a378648bcb17c01fb431dbec" +source = "git+https://github.com/ethcore/rust-rocksdb#e0e6c099d8cd156fe446009fce241d57b00cd8f4" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", From 1f599ac6f9814c7fd65920ac89a3cddd7345a695 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Mon, 20 Jun 2016 23:01:09 +0300 Subject: [PATCH 125/239] fix type --- util/src/kvdb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index c71934cc3..1633a6f88 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -21,7 +21,7 @@ use rocksdb::{DB, Writable, WriteBatch, IteratorMode, DBVector, DBIterator, IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; const DB_FILE_SIZE_BASE: u64 = 100 * 1024 * 1024; -const DB_FILE_SIZE_MULTIPLIER: usize = 10; +const DB_FILE_SIZE_MULTIPLIER: i32 = 10; /// Write transaction. Batches a sequence of put/delete operations for efficiency. pub struct DBTransaction { From 7aa73f300a5265ab8384b7e9969aa55b072a1ed3 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 20 Jun 2016 22:35:59 +0200 Subject: [PATCH 126/239] fixed migration of empty pruning dir --- parity/migration.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/parity/migration.rs b/parity/migration.rs index 9f1c4c52e..4198f7ed0 100644 --- a/parity/migration.rs +++ b/parity/migration.rs @@ -89,6 +89,7 @@ fn current_version(path: &PathBuf) -> Result { /// Writes current database version to the file. /// Creates a new file if the version file does not exist yet. fn update_version(path: &PathBuf) -> Result<(), Error> { + try!(fs::create_dir_all(path)); let mut file = try!(File::create(version_file_path(path))); try!(file.write_all(format!("{}", CURRENT_VERSION).as_bytes())); Ok(()) From c912bb8c171d3e5fa0414d73fdd98c15fe208327 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 20 Jun 2016 23:48:47 +0200 Subject: [PATCH 127/239] Fix lock order --- ethcore/src/miner/miner.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 735ad5cf4..f548d8a74 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -106,7 +106,8 @@ impl Miner { #[cfg_attr(feature="dev", allow(cyclomatic_complexity))] fn prepare_sealing(&self, chain: &MiningBlockChainClient) { trace!(target: "miner", "prepare_sealing: entering"); - let transactions = self.transaction_queue.lock().unwrap().top_transactions(); + let mut queue = self.transaction_queue.lock().unwrap(); + let transactions = queue.top_transactions(); let mut sealing_work = self.sealing_work.lock().unwrap(); let best_hash = chain.best_block_header().sha3(); @@ -163,7 +164,6 @@ impl Miner { let block = open_block.close(); - let mut queue = self.transaction_queue.lock().unwrap(); let fetch_account = |a: &Address| AccountDetails { nonce: chain.latest_nonce(a), balance: chain.latest_balance(a), From d42f8eac1e980961a94924970df0044b6258fb26 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 21 Jun 2016 12:07:07 +0300 Subject: [PATCH 128/239] little less extreme file sizes --- util/src/kvdb.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 1633a6f88..0911b3471 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -20,8 +20,8 @@ use std::default::Default; use rocksdb::{DB, Writable, WriteBatch, IteratorMode, DBVector, DBIterator, IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; -const DB_FILE_SIZE_BASE: u64 = 100 * 1024 * 1024; -const DB_FILE_SIZE_MULTIPLIER: i32 = 10; +const DB_FILE_SIZE_BASE: u64 = 10 * 1024 * 1024; +const DB_FILE_SIZE_MULTIPLIER: i32 = 5; /// Write transaction. Batches a sequence of put/delete operations for efficiency. pub struct DBTransaction { @@ -67,7 +67,7 @@ impl DatabaseConfig { DatabaseConfig { cache_size: Some(cache_size), prefix_size: None, - max_open_files: 256 + max_open_files: -1, } } } @@ -77,7 +77,7 @@ impl Default for DatabaseConfig { DatabaseConfig { cache_size: None, prefix_size: None, - max_open_files: 256 + max_open_files: -1, } } } From b6673788202123b47ef6a4fc42e15c1a1070fc97 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 21 Jun 2016 11:26:43 +0200 Subject: [PATCH 129/239] Release lock while pushing transactions --- ethcore/src/miner/miner.rs | 64 +++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index f548d8a74..e559306c0 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -106,35 +106,38 @@ impl Miner { #[cfg_attr(feature="dev", allow(cyclomatic_complexity))] fn prepare_sealing(&self, chain: &MiningBlockChainClient) { trace!(target: "miner", "prepare_sealing: entering"); - let mut queue = self.transaction_queue.lock().unwrap(); - let transactions = queue.top_transactions(); - let mut sealing_work = self.sealing_work.lock().unwrap(); - let best_hash = chain.best_block_header().sha3(); + let (transactions, mut open_block) = { + let queue = self.transaction_queue.lock().unwrap(); + let transactions = queue.top_transactions(); + let mut sealing_work = self.sealing_work.lock().unwrap(); + let best_hash = chain.best_block_header().sha3(); /* - // check to see if last ClosedBlock in would_seals is actually same parent block. - // if so - // duplicate, re-open and push any new transactions. - // if at least one was pushed successfully, close and enqueue new ClosedBlock; - // otherwise, leave everything alone. - // otherwise, author a fresh block. + // check to see if last ClosedBlock in would_seals is actually same parent block. + // if so + // duplicate, re-open and push any new transactions. + // if at least one was pushed successfully, close and enqueue new ClosedBlock; + // otherwise, leave everything alone. + // otherwise, author a fresh block. */ - let mut open_block = match sealing_work.pop_if(|b| b.block().fields().header.parent_hash() == &best_hash) { - Some(old_block) => { - trace!(target: "miner", "Already have previous work; updating and returning"); - // add transactions to old_block - let e = self.engine(); - old_block.reopen(e, chain.vm_factory()) - } - None => { - // block not found - create it. - trace!(target: "miner", "No existing work - making new block"); - chain.prepare_open_block( - self.author(), - self.gas_floor_target(), - self.extra_data() - ) - } + let open_block = match sealing_work.pop_if(|b| b.block().fields().header.parent_hash() == &best_hash) { + Some(old_block) => { + trace!(target: "miner", "Already have previous work; updating and returning"); + // add transactions to old_block + let e = self.engine(); + old_block.reopen(e, chain.vm_factory()) + } + None => { + // block not found - create it. + trace!(target: "miner", "No existing work - making new block"); + chain.prepare_open_block( + self.author(), + self.gas_floor_target(), + self.extra_data() + ) + } + }; + (transactions, open_block) }; let mut invalid_transactions = HashSet::new(); @@ -169,8 +172,11 @@ impl Miner { balance: chain.latest_balance(a), }; - for hash in invalid_transactions.into_iter() { - queue.remove_invalid(&hash, &fetch_account); + { + let mut queue = self.transaction_queue.lock().unwrap(); + for hash in invalid_transactions.into_iter() { + queue.remove_invalid(&hash, &fetch_account); + } } if !block.transactions().is_empty() { @@ -196,6 +202,8 @@ impl Miner { trace!(target: "miner", "prepare_sealing: unable to generate seal internally"); } } + + let mut sealing_work = self.sealing_work.lock().unwrap(); if sealing_work.peek_last_ref().map_or(true, |pb| pb.block().fields().header.hash() != block.block().fields().header.hash()) { trace!(target: "miner", "Pushing a new, refreshed or borrowed pending {}...", block.block().fields().header.hash()); sealing_work.push(block); From d2057a3f72fd69ae4be22b26ea6001eb13c586d0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 21 Jun 2016 11:30:30 +0200 Subject: [PATCH 130/239] Make names slightly less contentious. --- parity/cli.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index fd01f1bcb..fab325477 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -43,8 +43,8 @@ Protocol Options: --identity NAME Specify your node's name. DAO-Rescue Soft-fork Options: - --rescue-my-ether Does nothing - on by default. - --assist-dao-attack Votes against the DAO-rescue soft-fork, but supports + --help-rescue-dao Does nothing - on by default. + --dont-help-rescue-dao Votes against the DAO-rescue soft-fork, but supports it if it is triggered anyway. Equivalent to --gas-floor-target=3141592. --dogmatic Ignores all DAO-rescue soft-fork behaviour. Even if From 3de482a43115611510af41f79f10baa922bab247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 21 Jun 2016 12:31:50 +0200 Subject: [PATCH 131/239] Additional assertions for internal state of queue --- ethcore/src/miner/transaction_queue.rs | 27 +++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index cc8430b42..146fa77e3 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -239,6 +239,7 @@ impl TransactionSet { if let Some(ref old_order) = r { self.by_priority.remove(old_order); } + assert_eq!(self.by_priority.len(), self.by_address.len()); r } @@ -279,8 +280,10 @@ impl TransactionSet { fn drop(&mut self, sender: &Address, nonce: &U256) -> Option { if let Some(tx_order) = self.by_address.remove(sender, nonce) { self.by_priority.remove(&tx_order); + assert_eq!(self.by_priority.len(), self.by_address.len()); return Some(tx_order); } + assert_eq!(self.by_priority.len(), self.by_address.len()); None } @@ -468,7 +471,9 @@ impl TransactionQueue { })); } - self.import_tx(vtx, client_account.nonce).map_err(Error::Transaction) + let r = self.import_tx(vtx, client_account.nonce).map_err(Error::Transaction); + assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len()); + r } /// Removes all transactions from particular sender up to (excluding) given client (state) nonce. @@ -484,6 +489,7 @@ impl TransactionQueue { // And now lets check if there is some batch of transactions in future // that should be placed in current. It should also update last_nonces. self.move_matching_future_to_current(sender, client_nonce, client_nonce); + assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len()); } /// Removes invalid transaction identified by hash from queue. @@ -493,6 +499,8 @@ impl TransactionQueue { /// If gap is introduced marks subsequent transactions as future pub fn remove_invalid(&mut self, transaction_hash: &H256, fetch_account: &T) where T: Fn(&Address) -> AccountDetails { + + assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len()); let transaction = self.by_hash.remove(transaction_hash); if transaction.is_none() { // We don't know this transaction @@ -511,6 +519,7 @@ impl TransactionQueue { // And now lets check if there is some chain of transactions in future // that should be placed in current self.move_matching_future_to_current(sender, current_nonce, current_nonce); + assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len()); return; } @@ -520,6 +529,7 @@ impl TransactionQueue { // This will keep consistency in queue // Moves all to future and then promotes a batch from current: self.remove_all(sender, current_nonce); + assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len()); return; } } @@ -538,7 +548,7 @@ impl TransactionQueue { } else { trace!(target: "miner", "Removing old transaction: {:?} (nonce: {} < {})", order.hash, k, current_nonce); // Remove the transaction completely - self.by_hash.remove(&order.hash); + self.by_hash.remove(&order.hash).expect("All transactions in `future` are also in `by_hash`"); } } } @@ -558,7 +568,7 @@ impl TransactionQueue { self.future.insert(*sender, k, order.update_height(k, current_nonce)); } else { trace!(target: "miner", "Removing old transaction: {:?} (nonce: {} < {})", order.hash, k, current_nonce); - self.by_hash.remove(&order.hash); + self.by_hash.remove(&order.hash).expect("All transactions in `future` are also in `by_hash`"); } } self.future.enforce_limit(&mut self.by_hash); @@ -685,7 +695,8 @@ impl TransactionQueue { // same (sender, nonce), but above function would not move it. if let Some(order) = self.future.drop(&address, &nonce) { // Let's insert that transaction to current (if it has higher gas_price) - let future_tx = self.by_hash.remove(&order.hash).unwrap(); + let future_tx = self.by_hash.remove(&order.hash).expect("All transactions in `future` are always in `by_hash`."); + // if transaction in `current` (then one we are importing) is replaced it means that it has to low gas_price try!(check_too_cheap(Self::replace_transaction(future_tx, state_nonce, &mut self.current, &mut self.by_hash))); } @@ -726,7 +737,9 @@ impl TransactionQueue { let address = tx.sender(); let nonce = tx.nonce(); - by_hash.insert(hash, tx); + let old_hash = by_hash.insert(hash, tx); + assert!(old_hash.is_none(), "Each hash has to be inserted exactly once."); + if let Some(old) = set.insert(address, nonce, order.clone()) { // There was already transaction in queue. Let's check which one should stay @@ -736,11 +749,11 @@ impl TransactionQueue { // Put back old transaction since it has greater priority (higher gas_price) set.insert(address, nonce, old); // and remove new one - by_hash.remove(&hash); + by_hash.remove(&hash).expect("The hash has been just inserted and no other line is altering `by_hash`."); false } else { // Make sure we remove old transaction entirely - by_hash.remove(&old.hash); + by_hash.remove(&old.hash).expect("The hash is coming from `future` so it has to be in `by_hash`."); true } } else { From c2ffa904789f27d1a4982494489c481c87b3e829 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 21 Jun 2016 13:09:27 +0200 Subject: [PATCH 132/239] importing presale wallet in progress --- ethstore/src/crypto.rs | 11 ++++++-- ethstore/src/ethkey.rs | 8 ++++++ ethstore/src/json/hash.rs | 27 +++++++++++++++++- ethstore/src/json/mod.rs.in | 4 ++- ethstore/src/json/presale.rs | 42 ++++++++++++++++++++++++++++ ethstore/src/lib.rs | 1 + ethstore/src/presale.rs | 53 ++++++++++++++++++++++++++++++++++++ 7 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 ethstore/src/json/presale.rs create mode 100644 ethstore/src/presale.rs diff --git a/ethstore/src/crypto.rs b/ethstore/src/crypto.rs index 2858808d7..2733fa720 100644 --- a/ethstore/src/crypto.rs +++ b/ethstore/src/crypto.rs @@ -65,8 +65,8 @@ impl Keccak256<[u8; 32]> for [u8] { /// AES encryption pub mod aes { - use rcrypto::blockmodes::CtrMode; - use rcrypto::aessafe::AesSafe128Encryptor; + use rcrypto::blockmodes::{CtrMode, CbcDecryptor, PkcsPadding}; + use rcrypto::aessafe::{AesSafe128Encryptor, AesSafe128Decryptor}; use rcrypto::symmetriccipher::{Encryptor, Decryptor}; use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer}; @@ -81,5 +81,12 @@ pub mod aes { 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]) { + let mut encryptor = CbcDecryptor::new(AesSafe128Decryptor::new(k), PkcsPadding, iv.to_vec()); + encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding"); + } + } diff --git a/ethstore/src/ethkey.rs b/ethstore/src/ethkey.rs index eba877397..9d8858b79 100644 --- a/ethstore/src/ethkey.rs +++ b/ethstore/src/ethkey.rs @@ -31,3 +31,11 @@ impl From for Address { From::from(a) } } + +impl<'a> From<&'a json::H160> for Address { + fn from(json: &'a json::H160) -> Self { + let mut a = [0u8; 20]; + a.copy_from_slice(json); + From::from(a) + } +} diff --git a/ethstore/src/json/hash.rs b/ethstore/src/json/hash.rs index f0fb91e7a..2edc7b80b 100644 --- a/ethstore/src/json/hash.rs +++ b/ethstore/src/json/hash.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use std::fmt; +use std::ops; use std::str::FromStr; use rustc_serialize::hex::{FromHex, ToHex}; use serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError}; @@ -22,9 +24,31 @@ use super::Error; macro_rules! impl_hash { ($name: ident, $size: expr) => { - #[derive(Debug, PartialEq)] pub struct $name([u8; $size]); + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let self_ref: &[u8] = &self.0; + write!(f, "{:?}", self_ref) + } + } + + impl PartialEq for $name { + fn eq(&self, other: &Self) -> bool { + let self_ref: &[u8] = &self.0; + let other_ref: &[u8] = &other.0; + self_ref == other_ref + } + } + + impl ops::Deref for $name { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl Serialize for $name { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { @@ -85,3 +109,4 @@ macro_rules! impl_hash { impl_hash!(H128, 16); impl_hash!(H160, 20); impl_hash!(H256, 32); +impl_hash!(H768, 96); diff --git a/ethstore/src/json/mod.rs.in b/ethstore/src/json/mod.rs.in index c4a67a287..7272d7e2e 100644 --- a/ethstore/src/json/mod.rs.in +++ b/ethstore/src/json/mod.rs.in @@ -5,14 +5,16 @@ mod hash; mod id; mod kdf; mod key_file; +mod presale; mod version; pub use self::cipher::{Cipher, CipherSer, CipherSerParams, Aes128Ctr}; pub use self::crypto::Crypto; pub use self::error::Error; -pub use self::hash::{H128, H160, H256}; +pub use self::hash::{H128, H160, H256, H768}; pub use self::id::UUID; pub use self::kdf::{Kdf, KdfSer, Prf, Pbkdf2, Scrypt, KdfSerParams}; pub use self::key_file::KeyFile; +pub use self::presale::PresaleWallet; pub use self::version::Version; diff --git a/ethstore/src/json/presale.rs b/ethstore/src/json/presale.rs new file mode 100644 index 000000000..cba50695f --- /dev/null +++ b/ethstore/src/json/presale.rs @@ -0,0 +1,42 @@ +use std::io::Read; +use serde_json; +use super::{H160, H768}; + +#[derive(Debug, PartialEq, Deserialize)] +pub struct PresaleWallet { + pub encseed: H768, + #[serde(rename = "ethaddr")] + pub address: H160, +} + +impl PresaleWallet { + pub fn load(reader: R) -> Result where R: Read { + serde_json::from_reader(reader) + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use serde_json; + use json::{PresaleWallet, H160, H768}; + + #[test] + fn presale_wallet() { + let json = r#" + { + "encseed": "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066", + "ethaddr": "ede84640d1a1d3e06902048e67aa7db8d52c2ce1", + "email": "123@gmail.com", + "btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH" + } "#; + + let expected = PresaleWallet { + encseed: H768::from_str("137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066").unwrap(), + address: H160::from_str("ede84640d1a1d3e06902048e67aa7db8d52c2ce1").unwrap(), + }; + + let wallet: PresaleWallet = serde_json::from_str(json).unwrap(); + assert_eq!(expected, wallet); + } +} diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs index 19f1c4806..90bb367fa 100644 --- a/ethstore/src/lib.rs +++ b/ethstore/src/lib.rs @@ -37,6 +37,7 @@ mod crypto; mod error; mod ethstore; mod import; +mod presale; mod random; mod secret_store; diff --git a/ethstore/src/presale.rs b/ethstore/src/presale.rs new file mode 100644 index 000000000..aad19b15c --- /dev/null +++ b/ethstore/src/presale.rs @@ -0,0 +1,53 @@ +use rcrypto::pbkdf2::pbkdf2; +use rcrypto::sha2::Sha256; +use rcrypto::hmac::Hmac; +use json::PresaleWallet; +use ethkey::{Address, Secret, KeyPair}; +use crypto::Keccak256; +use {crypto, Error}; + +fn decrypt_presale_wallet(wallet: &PresaleWallet, password: &str) -> Result { + let mut iv = [0u8; 16]; + iv.copy_from_slice(&wallet.encseed[..16]); + + let mut ciphertext = [0u8; 80]; + ciphertext.copy_from_slice(&wallet.encseed[16..]); + + 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 key = [0u8; 64]; + crypto::aes::decrypt_cbc(&derived_key, &iv, &ciphertext, &mut key); + + let secret = Secret::from(key.keccak256()); + if let Ok(kp) = KeyPair::from_secret(secret) { + if kp.address() == Address::from(&wallet.address) { + return Ok(kp) + } + } + + Err(Error::InvalidPassword) +} + +#[cfg(test)] +mod tests { + use ethkey::{KeyPair, Address}; + use super::decrypt_presale_wallet; + use json::PresaleWallet; + + #[test] + fn test() { + let json = r#" + { + "encseed": "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066", + "ethaddr": "ede84640d1a1d3e06902048e67aa7db8d52c2ce1", + "email": "123@gmail.com", + "btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH" + } "#; + + let wallet = PresaleWallet::load(json.as_bytes()).unwrap(); + let kp = decrypt_presale_wallet(&wallet, "123").unwrap(); + assert_eq!(kp.address(), Address::from(wallet.address)); + } +} From 70db48961ad147ca5232762c30c5b38b076c1ca9 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 21 Jun 2016 13:18:07 +0200 Subject: [PATCH 133/239] Fix up flag struct. --- parity/cli.rs | 2 +- parity/configuration.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index fab325477..692518f45 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -229,7 +229,7 @@ pub struct Args { pub flag_chain: String, pub flag_db_path: String, pub flag_identity: String, - pub flag_assist_dao_attack: bool, + pub flag_dont_help_rescue_dao: bool, pub flag_dogmatic: bool, pub flag_unlock: Option, pub flag_password: Vec, diff --git a/parity/configuration.rs b/parity/configuration.rs index dcce3df25..1d3dc608c 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -75,7 +75,7 @@ impl Configuration { } pub fn gas_floor_target(&self) -> U256 { - if self.args.flag_assist_dao_attack || self.args.flag_dogmatic { + if self.args.dont_help_rescue_dao || self.args.flag_dogmatic { 4_700_000.into() } else { let d = &self.args.flag_gas_floor_target; From a8a731ba11fee703516bc3aaaac1cfa9776873f5 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 21 Jun 2016 13:30:32 +0200 Subject: [PATCH 134/239] PresaleWallet data structure --- ethstore/src/lib.rs | 1 + ethstore/src/presale.rs | 71 ++++++++++++++++++++++++++++------------- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs index 90bb367fa..96d860db4 100644 --- a/ethstore/src/lib.rs +++ b/ethstore/src/lib.rs @@ -45,5 +45,6 @@ pub use self::account::SafeAccount; pub use self::error::Error; pub use self::ethstore::EthStore; pub use self::import::import_accounts; +pub use self::presale::PresaleWallet; pub use self::secret_store::SecretStore; diff --git a/ethstore/src/presale.rs b/ethstore/src/presale.rs index aad19b15c..5ba57b8d4 100644 --- a/ethstore/src/presale.rs +++ b/ethstore/src/presale.rs @@ -1,40 +1,66 @@ +use std::fs; +use std::path::Path; use rcrypto::pbkdf2::pbkdf2; use rcrypto::sha2::Sha256; use rcrypto::hmac::Hmac; -use json::PresaleWallet; +use json; use ethkey::{Address, Secret, KeyPair}; use crypto::Keccak256; use {crypto, Error}; -fn decrypt_presale_wallet(wallet: &PresaleWallet, password: &str) -> Result { - let mut iv = [0u8; 16]; - iv.copy_from_slice(&wallet.encseed[..16]); +pub struct PresaleWallet { + iv: [u8; 16], + ciphertext: [u8; 80], + address: Address, +} - let mut ciphertext = [0u8; 80]; - ciphertext.copy_from_slice(&wallet.encseed[16..]); +impl From for PresaleWallet { + fn from(wallet: json::PresaleWallet) -> Self { + let mut iv = [0u8; 16]; + iv.copy_from_slice(&wallet.encseed[..16]); - 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 ciphertext = [0u8; 80]; + ciphertext.copy_from_slice(&wallet.encseed[16..]); - let mut key = [0u8; 64]; - crypto::aes::decrypt_cbc(&derived_key, &iv, &ciphertext, &mut key); - - let secret = Secret::from(key.keccak256()); - if let Ok(kp) = KeyPair::from_secret(secret) { - if kp.address() == Address::from(&wallet.address) { - return Ok(kp) + PresaleWallet { + iv: iv, + ciphertext: ciphertext, + address: Address::from(wallet.address), } } +} - Err(Error::InvalidPassword) +impl PresaleWallet { + pub fn open

(path: P) -> Result where P: AsRef { + let file = try!(fs::File::open(path)); + let presale = json::PresaleWallet::load(file).unwrap(); + Ok(PresaleWallet::from(presale)) + } + + 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 key = [0u8; 64]; + crypto::aes::decrypt_cbc(&derived_key, &self.iv, &self.ciphertext, &mut key); + + let secret = Secret::from(key.keccak256()); + if let Ok(kp) = KeyPair::from_secret(secret) { + if kp.address() == self.address { + return Ok(kp) + } + } + + Err(Error::InvalidPassword) + } } #[cfg(test)] mod tests { - use ethkey::{KeyPair, Address}; - use super::decrypt_presale_wallet; - use json::PresaleWallet; + use ethkey::Address; + use super::PresaleWallet; + use json; #[test] fn test() { @@ -46,8 +72,9 @@ mod tests { "btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH" } "#; - let wallet = PresaleWallet::load(json.as_bytes()).unwrap(); - let kp = decrypt_presale_wallet(&wallet, "123").unwrap(); + let wallet = json::PresaleWallet::load(json.as_bytes()).unwrap(); + let wallet = PresaleWallet::from(wallet); + let kp = wallet.decrypt("123").unwrap(); assert_eq!(kp.address(), Address::from(wallet.address)); } } From e0b4eab8191c1215af98e893490694f07ce153eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 21 Jun 2016 13:55:26 +0200 Subject: [PATCH 135/239] Fixing replacing transaction with lower gas_price in one of the edge cases (#1343) --- ethcore/src/miner/transaction_queue.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index cc8430b42..06aa07880 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -686,14 +686,15 @@ impl TransactionQueue { if let Some(order) = self.future.drop(&address, &nonce) { // Let's insert that transaction to current (if it has higher gas_price) let future_tx = self.by_hash.remove(&order.hash).unwrap(); - try!(check_too_cheap(Self::replace_transaction(future_tx, state_nonce, &mut self.current, &mut self.by_hash))); + // if transaction in `current` (then one we are importing) is replaced it means that it has to low gas_price + try!(check_too_cheap(!Self::replace_transaction(future_tx, state_nonce, &mut self.current, &mut self.by_hash))); } // Also enforce the limit let removed = self.current.enforce_limit(&mut self.by_hash); // If some transaction were removed because of limit we need to update last_nonces also. self.update_last_nonces(&removed); - // Trigger error if we were removed. + // Trigger error if the transaction we are importing was removed. try!(check_if_removed(&address, &nonce, removed)); trace!(target: "miner", "status: {:?}", self.status()); @@ -937,7 +938,7 @@ mod test { let res = txq.add(tx2.clone(), &default_nonce, TransactionOrigin::External); // and then there should be only one transaction in current (the one with higher gas_price) - assert_eq!(unwrap_tx_err(res), TransactionError::TooCheapToReplace); + assert_eq!(res.unwrap(), TransactionImportResult::Current); assert_eq!(txq.status().pending, 1); assert_eq!(txq.status().future, 0); assert_eq!(txq.current.by_priority.len(), 1); From 878298f061873ef8d43effdf876d42ee412acf7d Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 21 Jun 2016 13:55:02 +0200 Subject: [PATCH 136/239] bump jsonrpc-http-server --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index dc97ce0ca..a69ab8c2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -630,7 +630,7 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "5.1.0" -source = "git+https://github.com/ethcore/jsonrpc-http-server.git#6117b1d77b5a60d6fa2dc884f12aa7f5fd4585ca" +source = "git+https://github.com/ethcore/jsonrpc-http-server.git#0c99d308bc15e8fae50642eff77a3e1fd7610652" dependencies = [ "hyper 0.9.3 (git+https://github.com/ethcore/hyper)", "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", From 951512f9c9f5fd5cabd2594c6cf2b6b4e2b5760b Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 21 Jun 2016 13:56:33 +0200 Subject: [PATCH 137/239] Reserved peers rpc API (#1360) * reserved peers: lock them, use a hashset, and provide to networkcontext * adding and removing reserved peer service API * add NonReservedPeerMode, and setters in host * setting non reserved mode, restriction accepted connections * implement RPC apis * fix deadlock * fix rpc tests --- parity/configuration.rs | 5 +- parity/main.rs | 5 +- parity/rpc_apis.rs | 4 +- rpc/src/v1/impls/ethcore_set.rs | 34 ++++++- rpc/src/v1/tests/mocked/ethcore.rs | 61 +++++++---- rpc/src/v1/traits/ethcore_set.rs | 16 +++ util/src/network/host.rs | 158 ++++++++++++++++++++++------- util/src/network/mod.rs | 23 ++++- util/src/network/service.rs | 33 +++++- 9 files changed, 272 insertions(+), 67 deletions(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index 3f8202021..e6e6e36a1 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -200,7 +200,10 @@ impl Configuration { net_path.push("network"); ret.config_path = Some(net_path.to_str().unwrap().to_owned()); ret.reserved_nodes = self.init_reserved_nodes(); - ret.reserved_only = self.args.flag_reserved_only; + + if self.args.flag_reserved_only { + ret.non_reserved_mode = ::util::network::NonReservedPeerMode::Deny; + } ret } diff --git a/parity/main.rs b/parity/main.rs index dc5457aa1..a44cdf6d3 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -230,6 +230,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) logger: logger.clone(), settings: network_settings.clone(), allow_pending_receipt_query: !conf.args.flag_geth, + net_service: service.network(), }); let dependencies = rpc::Dependencies { @@ -315,11 +316,11 @@ fn execute_export(conf: Configuration) { udp_port: None, nat_enabled: false, discovery_enabled: false, - reserved_only: true, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 0, reserved_nodes: Vec::new(), + non_reserved_mode: ::util::network::NonReservedPeerMode::Accept, }; let client_config = conf.client_config(&spec); @@ -387,11 +388,11 @@ fn execute_import(conf: Configuration) { udp_port: None, nat_enabled: false, discovery_enabled: false, - reserved_only: true, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 0, reserved_nodes: Vec::new(), + non_reserved_mode: ::util::network::NonReservedPeerMode::Accept, }; let client_config = conf.client_config(&spec); diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index bf21181a1..251c24d85 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -25,6 +25,7 @@ use ethcore::client::Client; use util::RotatingLogger; use ethcore::account_provider::AccountProvider; use util::network_settings::NetworkSettings; +use util::network::NetworkService; #[cfg(feature="rpc")] pub use ethcore_rpc::ConfirmationsQueue; @@ -89,6 +90,7 @@ pub struct Dependencies { pub logger: Arc, pub settings: Arc, pub allow_pending_receipt_query: bool, + pub net_service: Arc>, } fn to_modules(apis: &[Api]) -> BTreeMap { @@ -163,7 +165,7 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet server.add_delegate(EthcoreClient::new(&deps.client, &deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate()) }, Api::EthcoreSet => { - server.add_delegate(EthcoreSetClient::new(&deps.miner).to_delegate()) + server.add_delegate(EthcoreSetClient::new(&deps.miner, &deps.net_service).to_delegate()) }, Api::Traces => { server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate()) diff --git a/rpc/src/v1/impls/ethcore_set.rs b/rpc/src/v1/impls/ethcore_set.rs index cbd9c4309..66f1a34aa 100644 --- a/rpc/src/v1/impls/ethcore_set.rs +++ b/rpc/src/v1/impls/ethcore_set.rs @@ -16,9 +16,11 @@ /// Ethcore-specific rpc interface for operations altering the settings. use util::{U256, Address}; +use util::network::{NetworkService, NonReservedPeerMode}; use std::sync::{Arc, Weak}; use jsonrpc_core::*; use ethcore::miner::MinerService; +use ethcore::service::SyncMessage; use v1::traits::EthcoreSet; use v1::types::{Bytes}; @@ -27,13 +29,15 @@ pub struct EthcoreSetClient where M: MinerService { miner: Weak, + net: Weak>, } impl EthcoreSetClient where M: MinerService { /// Creates new `EthcoreSetClient`. - pub fn new(miner: &Arc) -> Self { + pub fn new(miner: &Arc, net: &Arc>) -> Self { EthcoreSetClient { miner: Arc::downgrade(miner), + net: Arc::downgrade(net), } } } @@ -74,4 +78,32 @@ impl EthcoreSet for EthcoreSetClient where M: MinerService + 'static { to_value(&true) }) } + + fn add_reserved_peer(&self, params: Params) -> Result { + from_params::<(String,)>(params).and_then(|(peer,)| { + match take_weak!(self.net).add_reserved_peer(&peer) { + Ok(()) => to_value(&true), + Err(_) => Err(Error::invalid_params()), + } + }) + } + + fn remove_reserved_peer(&self, params: Params) -> Result { + from_params::<(String,)>(params).and_then(|(peer,)| { + match take_weak!(self.net).remove_reserved_peer(&peer) { + Ok(()) => to_value(&true), + Err(_) => Err(Error::invalid_params()), + } + }) + } + + fn drop_non_reserved_peers(&self, _: Params) -> Result { + take_weak!(self.net).set_non_reserved_mode(NonReservedPeerMode::Deny); + to_value(&true) + } + + fn accept_non_reserved_peers(&self, _: Params) -> Result { + take_weak!(self.net).set_non_reserved_mode(NonReservedPeerMode::Accept); + to_value(&true) + } } diff --git a/rpc/src/v1/tests/mocked/ethcore.rs b/rpc/src/v1/tests/mocked/ethcore.rs index 68c33ecce..a096543e3 100644 --- a/rpc/src/v1/tests/mocked/ethcore.rs +++ b/rpc/src/v1/tests/mocked/ethcore.rs @@ -19,11 +19,13 @@ use std::str::FromStr; use jsonrpc_core::IoHandler; use v1::{Ethcore, EthcoreClient, EthcoreSet, EthcoreSetClient}; use ethcore::miner::MinerService; +use ethcore::service::SyncMessage; use v1::tests::helpers::TestMinerService; use ethcore::client::{TestBlockChainClient}; use util::numbers::*; use rustc_serialize::hex::FromHex; use util::log::RotatingLogger; +use util::network::{NetworkConfiguration, NetworkService}; use util::network_settings::NetworkSettings; fn miner_service() -> Arc { @@ -50,21 +52,26 @@ fn settings() -> Arc { }) } +fn network_service() -> Arc> { + Arc::new(NetworkService::new(NetworkConfiguration::new()).unwrap()) +} + fn ethcore_client(client: &Arc, miner: &Arc) -> EthcoreClient { EthcoreClient::new(client, miner, logger(), settings()) } -fn ethcore_set_client(miner: &Arc) -> EthcoreSetClient { - EthcoreSetClient::new(miner) +fn ethcore_set_client(miner: &Arc, net: &Arc>) -> EthcoreSetClient { + EthcoreSetClient::new(miner, net) } #[test] fn rpc_ethcore_extra_data() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_extraData", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x01020304","id":1}"#; @@ -79,9 +86,10 @@ fn rpc_ethcore_default_extra_data() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_defaultExtraData", "params": [], "id": 1}"#; let response = format!(r#"{{"jsonrpc":"2.0","result":"0x{}","id":1}}"#, misc::version_data().to_hex()); @@ -93,9 +101,10 @@ fn rpc_ethcore_default_extra_data() { fn rpc_ethcore_gas_floor_target() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_gasFloorTarget", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x3039","id":1}"#; @@ -107,9 +116,10 @@ fn rpc_ethcore_gas_floor_target() { fn rpc_ethcore_min_gas_price() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_minGasPrice", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x01312d00","id":1}"#; @@ -121,9 +131,10 @@ fn rpc_ethcore_min_gas_price() { fn rpc_ethcore_set_min_gas_price() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -136,9 +147,10 @@ fn rpc_ethcore_set_min_gas_price() { fn rpc_ethcore_set_gas_floor_target() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -151,9 +163,10 @@ fn rpc_ethcore_set_gas_floor_target() { fn rpc_ethcore_set_extra_data() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -166,9 +179,10 @@ fn rpc_ethcore_set_extra_data() { fn rpc_ethcore_set_author() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -181,13 +195,14 @@ fn rpc_ethcore_set_author() { fn rpc_ethcore_dev_logs() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let logger = logger(); logger.append("a".to_owned()); logger.append("b".to_owned()); let ethcore = EthcoreClient::new(&client, &miner, logger.clone(), settings()).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogs", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":["b","a"],"id":1}"#; @@ -199,9 +214,10 @@ fn rpc_ethcore_dev_logs() { fn rpc_ethcore_dev_logs_levels() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogsLevels", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"rpc=trace","id":1}"#; @@ -212,9 +228,10 @@ fn rpc_ethcore_dev_logs_levels() { fn rpc_ethcore_set_transactions_limit() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setTransactionsLimit", "params":[10240240], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -227,9 +244,10 @@ fn rpc_ethcore_set_transactions_limit() { fn rpc_ethcore_transactions_limit() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_transactionsLimit", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":1024,"id":1}"#; @@ -241,9 +259,10 @@ fn rpc_ethcore_transactions_limit() { fn rpc_ethcore_net_chain() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netChain", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"testchain","id":1}"#; @@ -255,9 +274,10 @@ fn rpc_ethcore_net_chain() { fn rpc_ethcore_net_max_peers() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netMaxPeers", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":25,"id":1}"#; @@ -269,9 +289,10 @@ fn rpc_ethcore_net_max_peers() { fn rpc_ethcore_net_port() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPort", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":30303,"id":1}"#; @@ -283,9 +304,10 @@ fn rpc_ethcore_net_port() { fn rpc_ethcore_rpc_settings() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_rpcSettings", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":{"enabled":true,"interface":"all","port":8545},"id":1}"#; @@ -297,9 +319,10 @@ fn rpc_ethcore_rpc_settings() { fn rpc_ethcore_node_name() { let miner = miner_service(); let client = client_service(); + let network = network_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); + io.add_delegate(ethcore_set_client(&miner, &network).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_nodeName", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"mynode","id":1}"#; diff --git a/rpc/src/v1/traits/ethcore_set.rs b/rpc/src/v1/traits/ethcore_set.rs index 332c505b6..ed4303be1 100644 --- a/rpc/src/v1/traits/ethcore_set.rs +++ b/rpc/src/v1/traits/ethcore_set.rs @@ -37,6 +37,18 @@ pub trait EthcoreSet: Sized + Send + Sync + 'static { /// Sets the limits for transaction queue. fn set_transactions_limit(&self, _: Params) -> Result; + /// Add a reserved peer. + fn add_reserved_peer(&self, _: Params) -> Result; + + /// Remove a reserved peer. + fn remove_reserved_peer(&self, _: Params) -> Result; + + /// Drop all non-reserved peers. + fn drop_non_reserved_peers(&self, _: Params) -> Result; + + /// Accept non-reserved peers (default behavior) + fn accept_non_reserved_peers(&self, _: Params) -> Result; + /// Should be used to convert object to io delegate. fn to_delegate(self) -> IoDelegate { let mut delegate = IoDelegate::new(Arc::new(self)); @@ -45,6 +57,10 @@ pub trait EthcoreSet: Sized + Send + Sync + 'static { delegate.add_method("ethcore_setExtraData", EthcoreSet::set_extra_data); delegate.add_method("ethcore_setAuthor", EthcoreSet::set_author); delegate.add_method("ethcore_setTransactionsLimit", EthcoreSet::set_transactions_limit); + delegate.add_method("ethcore_addReservedPeer", EthcoreSet::add_reserved_peer); + delegate.add_method("ethcore_removeReservedPeer", EthcoreSet::remove_reserved_peer); + delegate.add_method("ethcore_dropNonReservedPeers", EthcoreSet::drop_non_reserved_peers); + delegate.add_method("ethcore_acceptNonReservedPeers", EthcoreSet::accept_non_reserved_peers); delegate } diff --git a/util/src/network/host.rs b/util/src/network/host.rs index aacfc3fcb..03ba07544 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::net::{SocketAddr}; -use std::collections::{HashMap}; -use std::str::{FromStr}; +use std::net::SocketAddr; +use std::collections::{HashMap, HashSet}; +use std::str::FromStr; use std::sync::*; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::ops::*; @@ -35,7 +35,7 @@ use rlp::*; use network::session::{Session, SessionData}; use error::*; use io::*; -use network::{NetworkProtocolHandler, PROTOCOL_VERSION}; +use network::{NetworkProtocolHandler, NonReservedPeerMode, PROTOCOL_VERSION}; use network::node_table::*; use network::stats::NetworkStats; use network::error::{NetworkError, DisconnectReason}; @@ -65,8 +65,6 @@ pub struct NetworkConfiguration { pub nat_enabled: bool, /// Enable discovery pub discovery_enabled: bool, - /// Pin to reserved nodes only - pub reserved_only: bool, /// List of initial node addresses pub boot_nodes: Vec, /// Use provided node key instead of default @@ -75,6 +73,8 @@ pub struct NetworkConfiguration { pub ideal_peers: u32, /// List of reserved node addresses. pub reserved_nodes: Vec, + /// The non-reserved peer mode. + pub non_reserved_mode: NonReservedPeerMode, } impl Default for NetworkConfiguration { @@ -93,11 +93,11 @@ impl NetworkConfiguration { udp_port: None, nat_enabled: true, discovery_enabled: true, - reserved_only: false, boot_nodes: Vec::new(), use_secret: None, ideal_peers: 25, reserved_nodes: Vec::new(), + non_reserved_mode: NonReservedPeerMode::Accept, } } @@ -191,13 +191,15 @@ pub struct NetworkContext<'s, Message> where Message: Send + Sync + Clone + 'sta sessions: Arc>>, session: Option, session_id: Option, + reserved_peers: &'s HashSet, } impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone + 'static, { /// 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>, protocol: ProtocolId, - session: Option, sessions: Arc>>) -> NetworkContext<'s, Message> { + session: Option, sessions: Arc>>, + reserved_peers: &'s HashSet) -> NetworkContext<'s, Message> { let id = session.as_ref().map(|s| s.lock().unwrap().token()); NetworkContext { io: io, @@ -205,6 +207,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone session_id: id, session: session, sessions: sessions, + reserved_peers: reserved_peers, } } @@ -237,7 +240,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone self.io.message(NetworkIoMessage::User(msg)); } - /// Send an IO message + /// Get an IoChannel. pub fn io_channel(&self) -> IoChannel> { self.io.channel() } @@ -335,7 +338,7 @@ pub struct Host where Message: Send + Sync + Clone { timers: RwLock>, timer_counter: RwLock, stats: Arc, - pinned_nodes: Vec, + reserved_nodes: RwLock>, num_sessions: AtomicUsize, stopping: AtomicBool, } @@ -390,28 +393,28 @@ impl Host where Message: Send + Sync + Clone { timers: RwLock::new(HashMap::new()), timer_counter: RwLock::new(USER_TIMER), stats: stats, - pinned_nodes: Vec::new(), + reserved_nodes: RwLock::new(HashSet::new()), num_sessions: AtomicUsize::new(0), stopping: AtomicBool::new(false), }; for n in boot_nodes { - // don't pin boot nodes. - host.add_node(&n, false); + host.add_node(&n); } for n in reserved_nodes { - host.add_node(&n, true); + if let Err(e) = host.add_reserved_node(&n) { + debug!(target: "network", "Error parsing node id: {}: {:?}", n, e); + } } Ok(host) } - pub fn add_node(&mut self, id: &str, pin: bool) { + pub fn add_node(&mut self, id: &str) { match Node::from_str(id) { Err(e) => { debug!(target: "network", "Could not add node {}: {:?}", id, e); }, Ok(n) => { let entry = NodeEntry { endpoint: n.endpoint.clone(), id: n.id.clone() }; - if pin { self.pinned_nodes.push(n.id.clone()) } self.nodes.write().unwrap().add_node(n); if let Some(ref mut discovery) = *self.discovery.lock().unwrap() { @@ -421,6 +424,56 @@ impl Host where Message: Send + Sync + Clone { } } + pub fn add_reserved_node(&self, id: &str) -> Result<(), UtilError> { + let n = try!(Node::from_str(id)); + + let entry = NodeEntry { endpoint: n.endpoint.clone(), id: n.id.clone() }; + self.reserved_nodes.write().unwrap().insert(n.id.clone()); + + if let Some(ref mut discovery) = *self.discovery.lock().unwrap() { + discovery.add_node(entry); + } + + Ok(()) + } + + pub fn set_non_reserved_mode(&self, mode: NonReservedPeerMode, io: &IoContext>) { + let mut info = self.info.write().unwrap(); + + if info.config.non_reserved_mode != mode { + info.config.non_reserved_mode = mode.clone(); + drop(info); + if let NonReservedPeerMode::Deny = mode { + // disconnect all non-reserved peers here. + let reserved: HashSet = self.reserved_nodes.read().unwrap().clone(); + let mut to_kill = Vec::new(); + for e in self.sessions.write().unwrap().iter_mut() { + let mut s = e.lock().unwrap(); + { + let id = s.id(); + if id.is_some() && reserved.contains(id.unwrap()) { + continue; + } + } + + s.disconnect(io, DisconnectReason::ClientQuit); + to_kill.push(s.token()); + } + for p in to_kill { + trace!(target: "network", "Disconnecting on reserved-only mode: {}", p); + self.kill_connection(p, io, false); + } + } + } + } + + pub fn remove_reserved_node(&self, id: &str) -> Result<(), UtilError> { + let n = try!(Node::from_str(id)); + self.reserved_nodes.write().unwrap().remove(&n.id); + + Ok(()) + } + pub fn client_version() -> String { version() } @@ -483,7 +536,7 @@ impl Host where Message: Send + Sync + Clone { // Initialize discovery. let discovery = { let info = self.info.read().unwrap(); - if info.config.discovery_enabled && !info.config.reserved_only { + if info.config.discovery_enabled && info.config.non_reserved_mode == NonReservedPeerMode::Accept { Some(Discovery::new(&info.keys, public_endpoint.address.clone(), public_endpoint, DISCOVERY)) } else { None } }; @@ -540,17 +593,26 @@ impl Host where Message: Send + Sync + Clone { } fn connect_peers(&self, io: &IoContext>) { - if self.info.read().unwrap().capabilities.is_empty() { - return; - } - let ideal_peers = { self.info.read().unwrap().config.ideal_peers }; - let pin = { self.info.read().unwrap().config.reserved_only }; - let session_count = self.session_count(); - if session_count >= ideal_peers as usize + self.pinned_nodes.len() { - // check if all pinned nodes are connected. - if self.pinned_nodes.iter().all(|n| self.have_session(n) && self.connecting_to(n)) { + let (ideal_peers, mut pin) = { + let info = self.info.read().unwrap(); + if info.capabilities.is_empty() { return; } + let config = &info.config; + + (config.ideal_peers, config.non_reserved_mode == NonReservedPeerMode::Deny) + }; + + let session_count = self.session_count(); + let reserved_nodes = self.reserved_nodes.read().unwrap(); + if session_count >= ideal_peers as usize + reserved_nodes.len() { + // check if all pinned nodes are connected. + if reserved_nodes.iter().all(|n| self.have_session(n) && self.connecting_to(n)) { + return; + } + + // if not, only attempt connect to reserved peers + pin = true; } let handshake_count = self.handshake_count(); @@ -562,7 +624,7 @@ impl Host where Message: Send + Sync + Clone { // iterate over all nodes, reserved ones coming first. // if we are pinned to only reserved nodes, ignore all others. - let nodes = self.pinned_nodes.iter().cloned().chain(if !pin { + let nodes = reserved_nodes.iter().cloned().chain(if !pin { self.nodes.read().unwrap().nodes() } else { Vec::new() @@ -696,11 +758,20 @@ impl Host where Message: Send + Sync + Clone { self.num_sessions.fetch_add(1, AtomicOrdering::SeqCst); if !s.info.originated { let session_count = self.session_count(); - let ideal_peers = { self.info.read().unwrap().config.ideal_peers }; - if session_count >= ideal_peers as usize { - s.disconnect(io, DisconnectReason::TooManyPeers); - return; + let reserved_nodes = self.reserved_nodes.read().unwrap(); + let (ideal_peers, reserved_only) = { + let info = self.info.read().unwrap(); + (info.config.ideal_peers, info.config.non_reserved_mode == NonReservedPeerMode::Deny) + }; + + if session_count >= ideal_peers as usize || reserved_only { + // only proceed if the connecting peer is reserved. + if !reserved_nodes.contains(s.id().unwrap()) { + s.disconnect(io, DisconnectReason::TooManyPeers); + return; + } } + // Add it no node table if let Ok(address) = s.remote_addr() { let entry = NodeEntry { id: s.id().unwrap().clone(), endpoint: NodeEndpoint { address: address, udp_port: address.port() } }; @@ -735,14 +806,17 @@ impl Host where Message: Send + Sync + Clone { if kill { self.kill_connection(token, io, true); } + let handlers = self.handlers.read().unwrap(); for p in ready_data { - let h = self.handlers.read().unwrap().get(p).unwrap().clone(); + let h = handlers.get(p).unwrap().clone(); self.stats.inc_sessions(); - h.connected(&NetworkContext::new(io, p, session.clone(), self.sessions.clone()), &token); + let reserved = self.reserved_nodes.read().unwrap(); + h.connected(&NetworkContext::new(io, p, session.clone(), self.sessions.clone(), &reserved), &token); } for (p, packet_id, data) in packet_data { - let h = self.handlers.read().unwrap().get(p).unwrap().clone(); - h.read(&NetworkContext::new(io, p, session.clone(), self.sessions.clone()), &token, packet_id, &data[1..]); + let h = handlers.get(p).unwrap().clone(); + let reserved = self.reserved_nodes.read().unwrap(); + h.read(&NetworkContext::new(io, p, session.clone(), self.sessions.clone(), &reserved), &token, packet_id, &data[1..]); } } @@ -783,7 +857,8 @@ impl Host where Message: Send + Sync + Clone { } for p in to_disconnect { let h = self.handlers.read().unwrap().get(p).unwrap().clone(); - h.disconnected(&NetworkContext::new(io, p, expired_session.clone(), self.sessions.clone()), &token); + let reserved = self.reserved_nodes.read().unwrap(); + h.disconnected(&NetworkContext::new(io, p, expired_session.clone(), self.sessions.clone(), &reserved), &token); } if deregister { io.deregister_stream(token).unwrap_or_else(|e| debug!("Error deregistering stream: {:?}", e)); @@ -886,7 +961,10 @@ impl IoHandler> for Host where Messa _ => match self.timers.read().unwrap().get(&token).cloned() { Some(timer) => match self.handlers.read().unwrap().get(timer.protocol).cloned() { None => { warn!(target: "network", "No handler found for protocol: {:?}", timer.protocol) }, - Some(h) => { h.timeout(&NetworkContext::new(io, timer.protocol, None, self.sessions.clone()), timer.token); } + Some(h) => { + let reserved = self.reserved_nodes.read().unwrap(); + h.timeout(&NetworkContext::new(io, timer.protocol, None, self.sessions.clone(), &reserved), timer.token); + } }, None => { warn!("Unknown timer token: {}", token); } // timer is not registerd through us } @@ -904,7 +982,8 @@ impl IoHandler> for Host where Messa ref versions } => { let h = handler.clone(); - h.initialize(&NetworkContext::new(io, protocol, None, self.sessions.clone())); + let reserved = self.reserved_nodes.read().unwrap(); + h.initialize(&NetworkContext::new(io, protocol, None, self.sessions.clone(), &reserved)); self.handlers.write().unwrap().insert(protocol, h); let mut info = self.info.write().unwrap(); for v in versions { @@ -946,8 +1025,9 @@ impl IoHandler> for Host where Messa self.kill_connection(*peer, io, false); }, NetworkIoMessage::User(ref message) => { + let reserved = self.reserved_nodes.read().unwrap(); for (p, h) in self.handlers.read().unwrap().iter() { - h.message(&NetworkContext::new(io, p, None, self.sessions.clone()), &message); + h.message(&NetworkContext::new(io, p, None, self.sessions.clone(), &reserved), &message); } } } diff --git a/util/src/network/mod.rs b/util/src/network/mod.rs index d074e6631..d59ab63b1 100644 --- a/util/src/network/mod.rs +++ b/util/src/network/mod.rs @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Network and general IO module. -//! +//! Network and general IO module. +//! //! Example usage for craeting a network service and adding an IO handler: //! //! ```rust @@ -112,3 +112,22 @@ pub trait NetworkProtocolHandler: Sync + Send where Message: Send + Syn fn message(&self, _io: &NetworkContext, _message: &Message) {} } +/// Non-reserved peer modes. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum NonReservedPeerMode { + /// Accept them. This is the default. + Accept, + /// Deny them. + Deny, +} + +impl NonReservedPeerMode { + /// Attempt to parse the peer mode from a string. + pub fn parse(s: &str) -> Option { + match s { + "accept" => Some(NonReservedPeerMode::Accept), + "deny" => Some(NonReservedPeerMode::Deny), + _ => None, + } + } +} \ No newline at end of file diff --git a/util/src/network/service.rs b/util/src/network/service.rs index e8db354d4..353a24bbe 100644 --- a/util/src/network/service.rs +++ b/util/src/network/service.rs @@ -18,9 +18,9 @@ use std::sync::*; use error::*; use panics::*; use network::{NetworkProtocolHandler, NetworkConfiguration}; -use network::error::{NetworkError}; +use network::error::NetworkError; use network::host::{Host, NetworkIoMessage, ProtocolId}; -use network::stats::{NetworkStats}; +use network::stats::NetworkStats; use io::*; /// IO Service with networking @@ -111,6 +111,35 @@ impl NetworkService where Message: Send + Sync + Clone + 'stat *host = None; Ok(()) } + + /// Try to add a reserved peer. + pub fn add_reserved_peer(&self, peer: &str) -> Result<(), UtilError> { + let host = self.host.read().unwrap(); + if let Some(ref host) = *host { + host.add_reserved_node(peer) + } else { + Ok(()) + } + } + + /// Try to remove a reserved peer. + pub fn remove_reserved_peer(&self, peer: &str) -> Result<(), UtilError> { + let host = self.host.read().unwrap(); + if let Some(ref host) = *host { + host.remove_reserved_node(peer) + } else { + Ok(()) + } + } + + /// Set the non-reserved peer mode. + pub fn set_non_reserved_mode(&self, mode: ::network::NonReservedPeerMode) { + let host = self.host.read().unwrap(); + if let Some(ref host) = *host { + let io_ctxt = IoContext::new(self.io_service.channel(), 0); + host.set_non_reserved_mode(mode, &io_ctxt); + } + } } impl MayPanic for NetworkService where Message: Send + Sync + Clone + 'static { From c5f6250668540dbd474540eb3b1abc77334c504c Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 21 Jun 2016 14:57:06 +0300 Subject: [PATCH 138/239] Set default database file size large enough (#1363) * make default 100mb file size * update again * fix type * little less extreme file sizes --- Cargo.lock | 4 ++-- util/src/kvdb.rs | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc97ce0ca..1f41ea021 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1103,7 +1103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rocksdb" version = "0.4.5" -source = "git+https://github.com/ethcore/rust-rocksdb#9140e37ce0fdb748097f85653c01b0f7e3736ea9" +source = "git+https://github.com/ethcore/rust-rocksdb#e0e6c099d8cd156fe446009fce241d57b00cd8f4" dependencies = [ "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)", @@ -1112,7 +1112,7 @@ dependencies = [ [[package]] name = "rocksdb-sys" version = "0.3.0" -source = "git+https://github.com/ethcore/rust-rocksdb#9140e37ce0fdb748097f85653c01b0f7e3736ea9" +source = "git+https://github.com/ethcore/rust-rocksdb#e0e6c099d8cd156fe446009fce241d57b00cd8f4" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 7d581fdbc..0911b3471 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -20,6 +20,9 @@ use std::default::Default; use rocksdb::{DB, Writable, WriteBatch, IteratorMode, DBVector, DBIterator, IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; +const DB_FILE_SIZE_BASE: u64 = 10 * 1024 * 1024; +const DB_FILE_SIZE_MULTIPLIER: i32 = 5; + /// Write transaction. Batches a sequence of put/delete operations for efficiency. pub struct DBTransaction { batch: WriteBatch, @@ -64,7 +67,7 @@ impl DatabaseConfig { DatabaseConfig { cache_size: Some(cache_size), prefix_size: None, - max_open_files: 256 + max_open_files: -1, } } } @@ -74,7 +77,7 @@ impl Default for DatabaseConfig { DatabaseConfig { cache_size: None, prefix_size: None, - max_open_files: 256 + max_open_files: -1, } } } @@ -110,6 +113,8 @@ impl Database { opts.create_if_missing(true); opts.set_use_fsync(false); opts.set_compaction_style(DBCompactionStyle::DBUniversalCompaction); + opts.set_target_file_size_base(DB_FILE_SIZE_BASE); + opts.set_target_file_size_multiplier(DB_FILE_SIZE_MULTIPLIER); if let Some(cache_size) = config.cache_size { // half goes to read cache opts.set_block_cache_size_mb(cache_size as u64 / 2); From 840f961dc29d0642d21394576a2e21006c6c8c2e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 21 Jun 2016 14:34:22 +0200 Subject: [PATCH 139/239] don't bother assigning queue. --- ethcore/src/miner/miner.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index e559306c0..563eb0eed 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -108,8 +108,7 @@ impl Miner { trace!(target: "miner", "prepare_sealing: entering"); let (transactions, mut open_block) = { - let queue = self.transaction_queue.lock().unwrap(); - let transactions = queue.top_transactions(); + let transactions = {self.transaction_queue.lock().unwrap().top_transactions()}; let mut sealing_work = self.sealing_work.lock().unwrap(); let best_hash = chain.best_block_header().sha3(); /* From 57e9ed3f085eafdc753c43cfe7022bd3b94ecf99 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 21 Jun 2016 14:42:27 +0200 Subject: [PATCH 140/239] importing presale wallet (#1368) * importing presale wallet in progress * PresaleWallet data structure --- ethstore/src/crypto.rs | 11 ++++- ethstore/src/ethkey.rs | 8 ++++ ethstore/src/json/hash.rs | 27 +++++++++++- ethstore/src/json/mod.rs.in | 4 +- ethstore/src/json/presale.rs | 42 +++++++++++++++++++ ethstore/src/lib.rs | 2 + ethstore/src/presale.rs | 80 ++++++++++++++++++++++++++++++++++++ 7 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 ethstore/src/json/presale.rs create mode 100644 ethstore/src/presale.rs diff --git a/ethstore/src/crypto.rs b/ethstore/src/crypto.rs index 2858808d7..2733fa720 100644 --- a/ethstore/src/crypto.rs +++ b/ethstore/src/crypto.rs @@ -65,8 +65,8 @@ impl Keccak256<[u8; 32]> for [u8] { /// AES encryption pub mod aes { - use rcrypto::blockmodes::CtrMode; - use rcrypto::aessafe::AesSafe128Encryptor; + use rcrypto::blockmodes::{CtrMode, CbcDecryptor, PkcsPadding}; + use rcrypto::aessafe::{AesSafe128Encryptor, AesSafe128Decryptor}; use rcrypto::symmetriccipher::{Encryptor, Decryptor}; use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer}; @@ -81,5 +81,12 @@ pub mod aes { 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]) { + let mut encryptor = CbcDecryptor::new(AesSafe128Decryptor::new(k), PkcsPadding, iv.to_vec()); + encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding"); + } + } diff --git a/ethstore/src/ethkey.rs b/ethstore/src/ethkey.rs index eba877397..9d8858b79 100644 --- a/ethstore/src/ethkey.rs +++ b/ethstore/src/ethkey.rs @@ -31,3 +31,11 @@ impl From for Address { From::from(a) } } + +impl<'a> From<&'a json::H160> for Address { + fn from(json: &'a json::H160) -> Self { + let mut a = [0u8; 20]; + a.copy_from_slice(json); + From::from(a) + } +} diff --git a/ethstore/src/json/hash.rs b/ethstore/src/json/hash.rs index f0fb91e7a..2edc7b80b 100644 --- a/ethstore/src/json/hash.rs +++ b/ethstore/src/json/hash.rs @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use std::fmt; +use std::ops; use std::str::FromStr; use rustc_serialize::hex::{FromHex, ToHex}; use serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError}; @@ -22,9 +24,31 @@ use super::Error; macro_rules! impl_hash { ($name: ident, $size: expr) => { - #[derive(Debug, PartialEq)] pub struct $name([u8; $size]); + impl fmt::Debug for $name { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let self_ref: &[u8] = &self.0; + write!(f, "{:?}", self_ref) + } + } + + impl PartialEq for $name { + fn eq(&self, other: &Self) -> bool { + let self_ref: &[u8] = &self.0; + let other_ref: &[u8] = &other.0; + self_ref == other_ref + } + } + + impl ops::Deref for $name { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl Serialize for $name { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { @@ -85,3 +109,4 @@ macro_rules! impl_hash { impl_hash!(H128, 16); impl_hash!(H160, 20); impl_hash!(H256, 32); +impl_hash!(H768, 96); diff --git a/ethstore/src/json/mod.rs.in b/ethstore/src/json/mod.rs.in index c4a67a287..7272d7e2e 100644 --- a/ethstore/src/json/mod.rs.in +++ b/ethstore/src/json/mod.rs.in @@ -5,14 +5,16 @@ mod hash; mod id; mod kdf; mod key_file; +mod presale; mod version; pub use self::cipher::{Cipher, CipherSer, CipherSerParams, Aes128Ctr}; pub use self::crypto::Crypto; pub use self::error::Error; -pub use self::hash::{H128, H160, H256}; +pub use self::hash::{H128, H160, H256, H768}; pub use self::id::UUID; pub use self::kdf::{Kdf, KdfSer, Prf, Pbkdf2, Scrypt, KdfSerParams}; pub use self::key_file::KeyFile; +pub use self::presale::PresaleWallet; pub use self::version::Version; diff --git a/ethstore/src/json/presale.rs b/ethstore/src/json/presale.rs new file mode 100644 index 000000000..cba50695f --- /dev/null +++ b/ethstore/src/json/presale.rs @@ -0,0 +1,42 @@ +use std::io::Read; +use serde_json; +use super::{H160, H768}; + +#[derive(Debug, PartialEq, Deserialize)] +pub struct PresaleWallet { + pub encseed: H768, + #[serde(rename = "ethaddr")] + pub address: H160, +} + +impl PresaleWallet { + pub fn load(reader: R) -> Result where R: Read { + serde_json::from_reader(reader) + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use serde_json; + use json::{PresaleWallet, H160, H768}; + + #[test] + fn presale_wallet() { + let json = r#" + { + "encseed": "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066", + "ethaddr": "ede84640d1a1d3e06902048e67aa7db8d52c2ce1", + "email": "123@gmail.com", + "btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH" + } "#; + + let expected = PresaleWallet { + encseed: H768::from_str("137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066").unwrap(), + address: H160::from_str("ede84640d1a1d3e06902048e67aa7db8d52c2ce1").unwrap(), + }; + + let wallet: PresaleWallet = serde_json::from_str(json).unwrap(); + assert_eq!(expected, wallet); + } +} diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs index 19f1c4806..96d860db4 100644 --- a/ethstore/src/lib.rs +++ b/ethstore/src/lib.rs @@ -37,6 +37,7 @@ mod crypto; mod error; mod ethstore; mod import; +mod presale; mod random; mod secret_store; @@ -44,5 +45,6 @@ pub use self::account::SafeAccount; pub use self::error::Error; pub use self::ethstore::EthStore; pub use self::import::import_accounts; +pub use self::presale::PresaleWallet; pub use self::secret_store::SecretStore; diff --git a/ethstore/src/presale.rs b/ethstore/src/presale.rs new file mode 100644 index 000000000..5ba57b8d4 --- /dev/null +++ b/ethstore/src/presale.rs @@ -0,0 +1,80 @@ +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, Error}; + +pub struct PresaleWallet { + iv: [u8; 16], + ciphertext: [u8; 80], + address: Address, +} + +impl From for PresaleWallet { + fn from(wallet: json::PresaleWallet) -> Self { + let mut iv = [0u8; 16]; + iv.copy_from_slice(&wallet.encseed[..16]); + + let mut ciphertext = [0u8; 80]; + ciphertext.copy_from_slice(&wallet.encseed[16..]); + + PresaleWallet { + iv: iv, + ciphertext: ciphertext, + address: Address::from(wallet.address), + } + } +} + +impl PresaleWallet { + pub fn open

(path: P) -> Result where P: AsRef { + let file = try!(fs::File::open(path)); + let presale = json::PresaleWallet::load(file).unwrap(); + Ok(PresaleWallet::from(presale)) + } + + 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 key = [0u8; 64]; + crypto::aes::decrypt_cbc(&derived_key, &self.iv, &self.ciphertext, &mut key); + + let secret = Secret::from(key.keccak256()); + if let Ok(kp) = KeyPair::from_secret(secret) { + if kp.address() == self.address { + return Ok(kp) + } + } + + Err(Error::InvalidPassword) + } +} + +#[cfg(test)] +mod tests { + use ethkey::Address; + use super::PresaleWallet; + use json; + + #[test] + fn test() { + let json = r#" + { + "encseed": "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066", + "ethaddr": "ede84640d1a1d3e06902048e67aa7db8d52c2ce1", + "email": "123@gmail.com", + "btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH" + } "#; + + let wallet = json::PresaleWallet::load(json.as_bytes()).unwrap(); + let wallet = PresaleWallet::from(wallet); + let kp = wallet.decrypt("123").unwrap(); + assert_eq!(kp.address(), Address::from(wallet.address)); + } +} From 7cfb9a2b0bd43f1aff74e5f82693d17bba910a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 21 Jun 2016 14:55:25 +0200 Subject: [PATCH 141/239] RPC for number of unconfirmed transactions --- parity/configuration.rs | 1 - parity/rpc_apis.rs | 3 +- rpc/src/v1/helpers/signing_queue.rs | 16 +++ rpc/src/v1/impls/ethcore.rs | 17 +++- rpc/src/v1/impls/mod.rs | 1 + rpc/src/v1/tests/mocked/ethcore.rs | 130 ++++++------------------- rpc/src/v1/tests/mocked/ethcore_set.rs | 96 ++++++++++++++++++ rpc/src/v1/tests/mocked/mod.rs | 1 + rpc/src/v1/traits/ethcore.rs | 5 + 9 files changed, 169 insertions(+), 101 deletions(-) create mode 100644 rpc/src/v1/tests/mocked/ethcore_set.rs diff --git a/parity/configuration.rs b/parity/configuration.rs index 3f8202021..21a8569d5 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -155,7 +155,6 @@ impl Configuration { pub fn init_reserved_nodes(&self) -> Vec { use std::fs::File; - use std::io::BufRead; if let Some(ref path) = self.args.flag_reserved_peers { let mut buffer = String::new(); diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index bf21181a1..3497f21a7 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -160,7 +160,8 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_queue).to_delegate()); }, Api::Ethcore => { - server.add_delegate(EthcoreClient::new(&deps.client, &deps.miner, deps.logger.clone(), deps.settings.clone()).to_delegate()) + let queue = deps.signer_port.map(|_| deps.signer_queue.clone()); + server.add_delegate(EthcoreClient::new(&deps.client, &deps.miner, deps.logger.clone(), deps.settings.clone(), queue).to_delegate()) }, Api::EthcoreSet => { server.add_delegate(EthcoreSetClient::new(&deps.miner).to_delegate()) diff --git a/rpc/src/v1/helpers/signing_queue.rs b/rpc/src/v1/helpers/signing_queue.rs index dd59ce967..3d7f9e35b 100644 --- a/rpc/src/v1/helpers/signing_queue.rs +++ b/rpc/src/v1/helpers/signing_queue.rs @@ -69,6 +69,12 @@ pub trait SigningQueue: Send + Sync { /// Return copy of all the requests in the queue. fn requests(&self) -> Vec; + + /// Returns number of transactions awaiting confirmation. + fn len(&self) -> usize; + + /// Returns true if there are no transactions awaiting confirmation. + fn is_empty(&self) -> bool; } #[derive(Debug, PartialEq)] @@ -277,6 +283,16 @@ impl SigningQueue for ConfirmationsQueue { let queue = self.queue.read().unwrap(); queue.values().map(|token| token.request.clone()).collect() } + + fn len(&self) -> usize { + let queue = self.queue.read().unwrap(); + queue.len() + } + + fn is_empty(&self) -> bool { + let queue = self.queue.read().unwrap(); + queue.is_empty() + } } diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/ethcore.rs index e77f46f5d..3a8b8a4a0 100644 --- a/rpc/src/v1/impls/ethcore.rs +++ b/rpc/src/v1/impls/ethcore.rs @@ -26,6 +26,8 @@ use jsonrpc_core::*; use ethcore::miner::MinerService; use v1::traits::Ethcore; use v1::types::{Bytes}; +use v1::helpers::{SigningQueue, ConfirmationsQueue}; +use v1::impls::error_codes; /// Ethcore implementation. pub struct EthcoreClient where @@ -36,16 +38,18 @@ pub struct EthcoreClient where miner: Weak, logger: Arc, settings: Arc, + confirmations_queue: Option>, } impl EthcoreClient where C: MiningBlockChainClient, M: MinerService { /// Creates new `EthcoreClient`. - pub fn new(client: &Arc, miner: &Arc, logger: Arc, settings: Arc) -> Self { + pub fn new(client: &Arc, miner: &Arc, logger: Arc, settings: Arc, queue: Option>) -> Self { EthcoreClient { client: Arc::downgrade(client), miner: Arc::downgrade(miner), logger: logger, settings: settings, + confirmations_queue: queue, } } } @@ -120,4 +124,15 @@ impl Ethcore for EthcoreClient where M: MinerService + 'static, C: M _ => Err(Error::invalid_params()), } } + + fn unsigned_transactions_count(&self, _params: Params) -> Result { + match self.confirmations_queue { + None => Err(Error { + code: ErrorCode::ServerError(error_codes::SIGNER_DISABLED), + message: "Trusted Signer is disabled. This API is not available.".into(), + data: None + }), + Some(ref queue) => to_value(&queue.len()), + } + } } diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index efca09091..099585f60 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -71,6 +71,7 @@ mod error_codes { pub const UNKNOWN_ERROR: i64 = -32002; pub const TRANSACTION_ERROR: i64 = -32010; pub const ACCOUNT_LOCKED: i64 = -32020; + pub const SIGNER_DISABLED: i64 = -32030; } fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result diff --git a/rpc/src/v1/tests/mocked/ethcore.rs b/rpc/src/v1/tests/mocked/ethcore.rs index 68c33ecce..2ac7bc66d 100644 --- a/rpc/src/v1/tests/mocked/ethcore.rs +++ b/rpc/src/v1/tests/mocked/ethcore.rs @@ -15,14 +15,11 @@ // along with Parity. If not, see . use std::sync::Arc; -use std::str::FromStr; use jsonrpc_core::IoHandler; -use v1::{Ethcore, EthcoreClient, EthcoreSet, EthcoreSetClient}; -use ethcore::miner::MinerService; +use v1::{Ethcore, EthcoreClient}; use v1::tests::helpers::TestMinerService; +use v1::helpers::ConfirmationsQueue; use ethcore::client::{TestBlockChainClient}; -use util::numbers::*; -use rustc_serialize::hex::FromHex; use util::log::RotatingLogger; use util::network_settings::NetworkSettings; @@ -51,11 +48,7 @@ fn settings() -> Arc { } fn ethcore_client(client: &Arc, miner: &Arc) -> EthcoreClient { - EthcoreClient::new(client, miner, logger(), settings()) -} - -fn ethcore_set_client(miner: &Arc) -> EthcoreSetClient { - EthcoreSetClient::new(miner) + EthcoreClient::new(client, miner, logger(), settings(), None) } #[test] @@ -64,7 +57,6 @@ fn rpc_ethcore_extra_data() { let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_extraData", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x01020304","id":1}"#; @@ -81,7 +73,6 @@ fn rpc_ethcore_default_extra_data() { let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_defaultExtraData", "params": [], "id": 1}"#; let response = format!(r#"{{"jsonrpc":"2.0","result":"0x{}","id":1}}"#, misc::version_data().to_hex()); @@ -95,7 +86,6 @@ fn rpc_ethcore_gas_floor_target() { let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_gasFloorTarget", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x3039","id":1}"#; @@ -109,7 +99,6 @@ fn rpc_ethcore_min_gas_price() { let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_minGasPrice", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"0x01312d00","id":1}"#; @@ -117,66 +106,6 @@ fn rpc_ethcore_min_gas_price() { assert_eq!(io.handle_request(request), Some(response.to_owned())); } -#[test] -fn rpc_ethcore_set_min_gas_price() { - let miner = miner_service(); - let client = client_service(); - let io = IoHandler::new(); - io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); - - let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - - assert_eq!(io.handle_request(request), Some(response.to_owned())); - assert_eq!(miner.minimal_gas_price(), U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); -} - -#[test] -fn rpc_ethcore_set_gas_floor_target() { - let miner = miner_service(); - let client = client_service(); - let io = IoHandler::new(); - io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); - - let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - - assert_eq!(io.handle_request(request), Some(response.to_owned())); - assert_eq!(miner.gas_floor_target(), U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); -} - -#[test] -fn rpc_ethcore_set_extra_data() { - let miner = miner_service(); - let client = client_service(); - let io = IoHandler::new(); - io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); - - let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - - assert_eq!(io.handle_request(request), Some(response.to_owned())); - assert_eq!(miner.extra_data(), "cd1722f3947def4cf144679da39c4c32bdc35681".from_hex().unwrap()); -} - -#[test] -fn rpc_ethcore_set_author() { - let miner = miner_service(); - let client = client_service(); - let io = IoHandler::new(); - io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); - - let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - - assert_eq!(io.handle_request(request), Some(response.to_owned())); - assert_eq!(miner.author(), Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); -} - #[test] fn rpc_ethcore_dev_logs() { let miner = miner_service(); @@ -184,10 +113,9 @@ fn rpc_ethcore_dev_logs() { let logger = logger(); logger.append("a".to_owned()); logger.append("b".to_owned()); - let ethcore = EthcoreClient::new(&client, &miner, logger.clone(), settings()).to_delegate(); + let ethcore = EthcoreClient::new(&client, &miner, logger.clone(), settings(), None).to_delegate(); let io = IoHandler::new(); io.add_delegate(ethcore); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogs", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":["b","a"],"id":1}"#; @@ -201,35 +129,18 @@ fn rpc_ethcore_dev_logs_levels() { let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogsLevels", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"rpc=trace","id":1}"#; assert_eq!(io.handle_request(request), Some(response.to_owned())); } -#[test] -fn rpc_ethcore_set_transactions_limit() { - let miner = miner_service(); - let client = client_service(); - let io = IoHandler::new(); - io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); - - let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setTransactionsLimit", "params":[10240240], "id": 1}"#; - let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; - - assert_eq!(io.handle_request(request), Some(response.to_owned())); - assert_eq!(miner.transactions_limit(), 10_240_240); -} - #[test] fn rpc_ethcore_transactions_limit() { let miner = miner_service(); let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_transactionsLimit", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":1024,"id":1}"#; @@ -243,7 +154,6 @@ fn rpc_ethcore_net_chain() { let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netChain", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"testchain","id":1}"#; @@ -257,7 +167,6 @@ fn rpc_ethcore_net_max_peers() { let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netMaxPeers", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":25,"id":1}"#; @@ -271,7 +180,6 @@ fn rpc_ethcore_net_port() { let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPort", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":30303,"id":1}"#; @@ -285,7 +193,6 @@ fn rpc_ethcore_rpc_settings() { let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_rpcSettings", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":{"enabled":true,"interface":"all","port":8545},"id":1}"#; @@ -299,10 +206,37 @@ fn rpc_ethcore_node_name() { let client = client_service(); let io = IoHandler::new(); io.add_delegate(ethcore_client(&client, &miner).to_delegate()); - io.add_delegate(ethcore_set_client(&miner).to_delegate()); let request = r#"{"jsonrpc": "2.0", "method": "ethcore_nodeName", "params":[], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":"mynode","id":1}"#; assert_eq!(io.handle_request(request), Some(response.to_owned())); } + +#[test] +fn rpc_ethcore_unsigned_transactions_count() { + let miner = miner_service(); + let client = client_service(); + let io = IoHandler::new(); + let queue = Arc::new(ConfirmationsQueue::default()); + let ethcore = EthcoreClient::new(&client, &miner, logger(), settings(), Some(queue)).to_delegate(); + io.add_delegate(ethcore); + + let request = r#"{"jsonrpc": "2.0", "method": "ethcore_unsignedTransactionsCount", "params":[], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":0,"id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); +} + +#[test] +fn rpc_ethcore_unsigned_transactions_count_when_signer_disabled() { + let miner = miner_service(); + let client = client_service(); + let io = IoHandler::new(); + io.add_delegate(ethcore_client(&client, &miner).to_delegate()); + + let request = r#"{"jsonrpc": "2.0", "method": "ethcore_unsignedTransactionsCount", "params":[], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); +} diff --git a/rpc/src/v1/tests/mocked/ethcore_set.rs b/rpc/src/v1/tests/mocked/ethcore_set.rs new file mode 100644 index 000000000..9602eeeda --- /dev/null +++ b/rpc/src/v1/tests/mocked/ethcore_set.rs @@ -0,0 +1,96 @@ +// Copyright 2015, 2016 Ethcore (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 std::str::FromStr; +use jsonrpc_core::IoHandler; +use v1::{EthcoreSet, EthcoreSetClient}; +use ethcore::miner::MinerService; +use v1::tests::helpers::TestMinerService; +use util::numbers::*; +use rustc_serialize::hex::FromHex; + +fn miner_service() -> Arc { + Arc::new(TestMinerService::default()) +} + +fn ethcore_set_client(miner: &Arc) -> EthcoreSetClient { + EthcoreSetClient::new(miner) +} + +#[test] +fn rpc_ethcore_set_min_gas_price() { + let miner = miner_service(); + let io = IoHandler::new(); + io.add_delegate(ethcore_set_client(&miner).to_delegate()); + + let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(miner.minimal_gas_price(), U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); +} +#[test] +fn rpc_ethcore_set_gas_floor_target() { + let miner = miner_service(); + let io = IoHandler::new(); + io.add_delegate(ethcore_set_client(&miner).to_delegate()); + + let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(miner.gas_floor_target(), U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); +} + +#[test] +fn rpc_ethcore_set_extra_data() { + let miner = miner_service(); + let io = IoHandler::new(); + io.add_delegate(ethcore_set_client(&miner).to_delegate()); + + let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(miner.extra_data(), "cd1722f3947def4cf144679da39c4c32bdc35681".from_hex().unwrap()); +} + +#[test] +fn rpc_ethcore_set_author() { + let miner = miner_service(); + let io = IoHandler::new(); + io.add_delegate(ethcore_set_client(&miner).to_delegate()); + + let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(miner.author(), Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); +} + +#[test] +fn rpc_ethcore_set_transactions_limit() { + let miner = miner_service(); + let io = IoHandler::new(); + io.add_delegate(ethcore_set_client(&miner).to_delegate()); + + let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setTransactionsLimit", "params":[10240240], "id": 1}"#; + let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; + + assert_eq!(io.handle_request(request), Some(response.to_owned())); + assert_eq!(miner.transactions_limit(), 10_240_240); +} diff --git a/rpc/src/v1/tests/mocked/mod.rs b/rpc/src/v1/tests/mocked/mod.rs index 986dbfdef..503c75c12 100644 --- a/rpc/src/v1/tests/mocked/mod.rs +++ b/rpc/src/v1/tests/mocked/mod.rs @@ -24,4 +24,5 @@ mod web3; mod personal; mod personal_signer; mod ethcore; +mod ethcore_set; mod rpc; diff --git a/rpc/src/v1/traits/ethcore.rs b/rpc/src/v1/traits/ethcore.rs index 1dd00ff73..32855727f 100644 --- a/rpc/src/v1/traits/ethcore.rs +++ b/rpc/src/v1/traits/ethcore.rs @@ -60,6 +60,10 @@ pub trait Ethcore: Sized + Send + Sync + 'static { /// Returns distribution of gas price in latest blocks. fn gas_price_statistics(&self, _: Params) -> Result; + /// Returns number of unsigned transactions waiting in the signer queue (if signer enabled) + /// Returns error when signer is disabled + fn unsigned_transactions_count(&self, _: Params) -> Result; + /// Should be used to convert object to io delegate. fn to_delegate(self) -> IoDelegate { let mut delegate = IoDelegate::new(Arc::new(self)); @@ -77,6 +81,7 @@ pub trait Ethcore: Sized + Send + Sync + 'static { delegate.add_method("ethcore_nodeName", Ethcore::node_name); delegate.add_method("ethcore_defaultExtraData", Ethcore::default_extra_data); delegate.add_method("ethcore_gasPriceStatistics", Ethcore::gas_price_statistics); + delegate.add_method("ethcore_unsignedTransactionsCount", Ethcore::unsigned_transactions_count); delegate } From be03a6acbdaa58d884c6fb454e38178af68a8ed8 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 21 Jun 2016 15:04:36 +0200 Subject: [PATCH 142/239] import-wallet option for ethstore executable --- ethstore/README.md | 15 +++++++++++++++ ethstore/src/bin/ethstore.rs | 11 ++++++++++- ethstore/src/crypto.rs | 7 ++++--- ethstore/src/ethkey.rs | 8 -------- ethstore/src/presale.rs | 2 +- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/ethstore/README.md b/ethstore/README.md index aba4911bf..0cf50f454 100644 --- a/ethstore/README.md +++ b/ethstore/README.md @@ -20,6 +20,7 @@ Usage: ethstore change-pwd

[--dir DIR] ethstore list [--dir DIR] ethstore import [--src DIR] [--dir DIR] + ethstore import-wallet [--dir DIR] ethstore remove
[--dir DIR] ethstore sign
[--dir DIR] ethstore [-h | --help] @@ -38,6 +39,7 @@ Commands: change-pwd Change account password. list List accounts. import Import accounts from src. + import-wallet Import presale wallet. remove Remove account. sign Sign message. ``` @@ -119,6 +121,19 @@ ethstore list -- +#### `import-wallet [--dir DIR]` +*Import account from presale wallet.* + +- `` - presale wallet path +- `` - account password, any string +- `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity + +``` +e6a3d25a7cb7cd21cb720df5b5e8afd154af1bbb +``` + +-- + #### `remove
[--dir DIR]` *Remove account from secret store.* diff --git a/ethstore/src/bin/ethstore.rs b/ethstore/src/bin/ethstore.rs index 6020679d4..948d7a76e 100644 --- a/ethstore/src/bin/ethstore.rs +++ b/ethstore/src/bin/ethstore.rs @@ -24,7 +24,7 @@ use std::str::FromStr; use docopt::Docopt; use ethstore::ethkey::{Secret, Address, Message}; use ethstore::dir::{KeyDirectory, ParityDirectory, DiskDirectory, GethDirectory, DirectoryType}; -use ethstore::{EthStore, SecretStore, import_accounts, Error}; +use ethstore::{EthStore, SecretStore, import_accounts, Error, PresaleWallet}; pub const USAGE: &'static str = r#" Ethereum key management. @@ -35,6 +35,7 @@ Usage: ethstore change-pwd
[--dir DIR] ethstore list [--dir DIR] ethstore import [--src DIR] [--dir DIR] + ethstore import-wallet [--dir DIR] ethstore remove
[--dir DIR] ethstore sign
[--dir DIR] ethstore [-h | --help] @@ -53,6 +54,7 @@ Commands: change-pwd Change password. list List accounts. import Import accounts from src. + import-wallet Import presale wallet. remove Remove account. sign Sign message. "#; @@ -63,6 +65,7 @@ struct Args { cmd_change_pwd: bool, cmd_list: bool, cmd_import: bool, + cmd_import_wallet: bool, cmd_remove: bool, cmd_sign: bool, arg_secret: String, @@ -71,6 +74,7 @@ struct Args { arg_new_pwd: String, arg_address: String, arg_message: String, + arg_path: String, flag_src: String, flag_dir: String, } @@ -128,6 +132,11 @@ fn execute(command: I) -> Result where I: IntoIterator for [u8] { pub mod aes { use rcrypto::blockmodes::{CtrMode, CbcDecryptor, PkcsPadding}; use rcrypto::aessafe::{AesSafe128Encryptor, AesSafe128Decryptor}; - use rcrypto::symmetriccipher::{Encryptor, Decryptor}; + use rcrypto::symmetriccipher::{Encryptor, Decryptor, SymmetricCipherError}; use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer}; /// Encrypt a message @@ -83,9 +83,10 @@ pub mod aes { } /// Decrypt a message using cbc mode - pub fn decrypt_cbc(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) { + pub fn decrypt_cbc(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) -> Result<(), SymmetricCipherError> { let mut encryptor = CbcDecryptor::new(AesSafe128Decryptor::new(k), PkcsPadding, iv.to_vec()); - encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding"); + try!(encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true)); + Ok(()) } } diff --git a/ethstore/src/ethkey.rs b/ethstore/src/ethkey.rs index 9d8858b79..eba877397 100644 --- a/ethstore/src/ethkey.rs +++ b/ethstore/src/ethkey.rs @@ -31,11 +31,3 @@ impl From for Address { From::from(a) } } - -impl<'a> From<&'a json::H160> for Address { - fn from(json: &'a json::H160) -> Self { - let mut a = [0u8; 20]; - a.copy_from_slice(json); - From::from(a) - } -} diff --git a/ethstore/src/presale.rs b/ethstore/src/presale.rs index 5ba57b8d4..8c8172473 100644 --- a/ethstore/src/presale.rs +++ b/ethstore/src/presale.rs @@ -43,7 +43,7 @@ impl PresaleWallet { pbkdf2(&mut h_mac, password.as_bytes(), 2000, &mut derived_key); let mut key = [0u8; 64]; - crypto::aes::decrypt_cbc(&derived_key, &self.iv, &self.ciphertext, &mut key); + try!(crypto::aes::decrypt_cbc(&derived_key, &self.iv, &self.ciphertext, &mut key).map_err(|_| Error::InvalidPassword)); let secret = Secret::from(key.keccak256()); if let Ok(kp) = KeyPair::from_secret(secret) { From 7136cd7057b2ea42910fd24fc718c1e2c91073f4 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 21 Jun 2016 15:07:15 +0200 Subject: [PATCH 143/239] improved import wallet test --- ethstore/src/presale.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ethstore/src/presale.rs b/ethstore/src/presale.rs index 8c8172473..09c86abea 100644 --- a/ethstore/src/presale.rs +++ b/ethstore/src/presale.rs @@ -58,7 +58,6 @@ impl PresaleWallet { #[cfg(test)] mod tests { - use ethkey::Address; use super::PresaleWallet; use json; @@ -74,7 +73,7 @@ mod tests { let wallet = json::PresaleWallet::load(json.as_bytes()).unwrap(); let wallet = PresaleWallet::from(wallet); - let kp = wallet.decrypt("123").unwrap(); - assert_eq!(kp.address(), Address::from(wallet.address)); + assert!(wallet.decrypt("123").is_ok()); + assert!(wallet.decrypt("124").is_err()); } } From 3aaf938add35b5cc49edc8516b6e5fbf6ee99005 Mon Sep 17 00:00:00 2001 From: arkpar Date: Tue, 21 Jun 2016 15:24:17 +0200 Subject: [PATCH 144/239] Fixed build --- parity/configuration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index 1d3dc608c..b0ad3a475 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -75,7 +75,7 @@ impl Configuration { } pub fn gas_floor_target(&self) -> U256 { - if self.args.dont_help_rescue_dao || self.args.flag_dogmatic { + if self.args.flag_dont_help_rescue_dao || self.args.flag_dogmatic { 4_700_000.into() } else { let d = &self.args.flag_gas_floor_target; From bca4e23df691e0284539efceda98d66cc5611f0d Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Tue, 21 Jun 2016 15:56:00 +0200 Subject: [PATCH 145/239] Fixed panic on aborted connection (#1370) --- ethcore/src/block_queue.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ethcore/src/block_queue.rs b/ethcore/src/block_queue.rs index 5e89641c0..ce99dcccd 100644 --- a/ethcore/src/block_queue.rs +++ b/ethcore/src/block_queue.rs @@ -130,7 +130,9 @@ impl QueueSignal { } if self.signalled.compare_and_swap(false, true, AtomicOrdering::Relaxed) == false { - self.message_channel.send(UserMessage(SyncMessage::BlockVerified)).expect("Error sending BlockVerified message"); + if let Err(e) = self.message_channel.send(UserMessage(SyncMessage::BlockVerified)) { + debug!("Error sending BlockVerified message: {:?}", e); + } } } From b2891fcdda0de9128772f10c684f90d9fb5df310 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Tue, 21 Jun 2016 16:00:34 +0200 Subject: [PATCH 146/239] Update sealing on new transactions (#1365) --- ethcore/src/client/client.rs | 4 ++-- ethcore/src/client/test_client.rs | 2 +- ethcore/src/miner/miner.rs | 18 ++++++++++++------ ethcore/src/miner/mod.rs | 2 +- rpc/src/v1/tests/helpers/miner_service.rs | 2 +- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index bf67a8772..25e61a986 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -381,7 +381,7 @@ impl Client where V: Verifier { balance: self.latest_balance(a), }; let tx = transactions.iter().filter_map(|bytes| UntrustedRlp::new(&bytes).as_val().ok()).collect(); - let results = self.miner.import_transactions(tx, fetch_account); + let results = self.miner.import_transactions(self, tx, fetch_account); results.len() } @@ -771,7 +771,7 @@ impl BlockChainClient for Client where V: Verifier { nonce: self.latest_nonce(a), balance: self.latest_balance(a), }; - self.miner.import_transactions(transactions, fetch_account) + self.miner.import_transactions(self, transactions, fetch_account) } fn queue_transactions(&self, transactions: Vec) { diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index b6cc946fc..29f91a1d6 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -490,7 +490,7 @@ impl BlockChainClient for TestBlockChainClient { balance: balances[a], }; - self.miner.import_transactions(transactions, &fetch_account) + self.miner.import_transactions(self, transactions, &fetch_account) } fn queue_transactions(&self, transactions: Vec) { diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 735ad5cf4..9840a682e 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -376,13 +376,19 @@ impl MinerService for Miner { *self.gas_floor_target.read().unwrap() } - fn import_transactions(&self, transactions: Vec, fetch_account: T) -> + fn import_transactions(&self, chain: &MiningBlockChainClient, transactions: Vec, fetch_account: T) -> Vec> where T: Fn(&Address) -> AccountDetails { - let mut transaction_queue = self.transaction_queue.lock().unwrap(); - transactions.into_iter() - .map(|tx| transaction_queue.add(tx, &fetch_account, TransactionOrigin::External)) - .collect() + let results: Vec> = { + let mut transaction_queue = self.transaction_queue.lock().unwrap(); + transactions.into_iter() + .map(|tx| transaction_queue.add(tx, &fetch_account, TransactionOrigin::External)) + .collect() + }; + if !results.is_empty() { + self.update_sealing(chain); + } + results } fn import_own_transaction( @@ -564,7 +570,7 @@ impl MinerService for Miner { for tx in &txs { let _sender = tx.sender(); } - let _ = self.import_transactions(txs, |a| AccountDetails { + let _ = self.import_transactions(chain, txs, |a| AccountDetails { nonce: chain.latest_nonce(a), balance: chain.latest_balance(a), }); diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 71727f51d..697f7513f 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -94,7 +94,7 @@ pub trait MinerService : Send + Sync { fn set_transactions_limit(&self, limit: usize); /// Imports transactions to transaction queue. - fn import_transactions(&self, transactions: Vec, fetch_account: T) -> + fn import_transactions(&self, chain: &MiningBlockChainClient, transactions: Vec, fetch_account: T) -> Vec> where T: Fn(&Address) -> AccountDetails, Self: Sized; diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index daa5c9497..7ec7fc1cc 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -115,7 +115,7 @@ impl MinerService for TestMinerService { } /// Imports transactions to transaction queue. - fn import_transactions(&self, transactions: Vec, fetch_account: T) -> + fn import_transactions(&self, _chain: &MiningBlockChainClient, transactions: Vec, fetch_account: T) -> Vec> where T: Fn(&Address) -> AccountDetails { // lets assume that all txs are valid From 9132895d0e0cbd3180ed68a34b94ba5c635449d7 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 21 Jun 2016 17:20:47 +0300 Subject: [PATCH 147/239] limit flush rate --- Cargo.lock | 4 ++-- util/src/kvdb.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7f901eb45..1902f076b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1105,7 +1105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rocksdb" version = "0.4.5" -source = "git+https://github.com/ethcore/rust-rocksdb#e0e6c099d8cd156fe446009fce241d57b00cd8f4" +source = "git+https://github.com/ethcore/rust-rocksdb#6f3c68f5f075433d206be4af6a620651cd9f8541" dependencies = [ "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)", @@ -1114,7 +1114,7 @@ dependencies = [ [[package]] name = "rocksdb-sys" version = "0.3.0" -source = "git+https://github.com/ethcore/rust-rocksdb#e0e6c099d8cd156fe446009fce241d57b00cd8f4" +source = "git+https://github.com/ethcore/rust-rocksdb#6f3c68f5f075433d206be4af6a620651cd9f8541" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 0911b3471..66a4a02ee 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -109,6 +109,7 @@ impl Database { /// Open database file. Creates if it does not exist. pub fn open(config: &DatabaseConfig, path: &str) -> Result { let mut opts = Options::new(); + try!(opts.set_parsed_options("rate_limiter_bytes_per_sec=256000000")); opts.set_max_open_files(config.max_open_files); opts.create_if_missing(true); opts.set_use_fsync(false); From bbe5cd001a1663e544237b83c7528eb7be5e9b3b Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 21 Jun 2016 17:50:22 +0200 Subject: [PATCH 148/239] presale wallet cli for parity --- parity/cli.rs | 2 ++ parity/main.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/parity/cli.rs b/parity/cli.rs index 507137f8b..d8effec88 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -25,6 +25,7 @@ Usage: parity daemon [options] parity account (new | list ) [options] parity account import ... [options] + parity wallet import --password FILE [options] parity import [ ] [options] parity export [ ] [options] parity signer new-token [options] @@ -215,6 +216,7 @@ Miscellaneous Options: pub struct Args { pub cmd_daemon: bool, pub cmd_account: bool, + pub cmd_wallet: bool, pub cmd_new: bool, pub cmd_list: bool, pub cmd_export: bool, diff --git a/parity/main.rs b/parity/main.rs index a44cdf6d3..b610e3025 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -129,6 +129,11 @@ fn execute(conf: Configuration) { return; } + if conf.args.cmd_wallet { + execute_wallet_cli(conf); + return; + } + if conf.args.cmd_export { execute_export(conf); return; @@ -534,6 +539,30 @@ fn execute_account_cli(conf: Configuration) { } } +fn execute_wallet_cli(conf: Configuration) { + use ethcore::ethstore::{PresaleWallet, SecretStore, EthStore}; + use ethcore::ethstore::dir::DiskDirectory; + use ethcore::account_provider::AccountProvider; + + let wallet_path = conf.args.arg_path.first().unwrap(); + let filename = conf.args.flag_password.first().unwrap(); + let mut file = File::open(filename).unwrap_or_else(|_| die!("{} Unable to read password file.", filename)); + let mut file_content = String::new(); + file.read_to_string(&mut file_content).unwrap_or_else(|_| die!("{} Unable to read password file.", filename)); + + let dir = Box::new(DiskDirectory::create(conf.keys_path()).unwrap()); + let iterations = conf.keys_iterations(); + let store = AccountProvider::new(Box::new(EthStore::open_with_iterations(dir, iterations).unwrap())); + + // remove eof + let pass = &file_content[..file_content.len() - 1]; + let wallet = PresaleWallet::open(wallet_path).unwrap_or_else(|_| die!("Unable to open presale wallet.")); + let kp = wallet.decrypt(pass).unwrap_or_else(|_| die!("Invalid password")); + let address = store.insert_account(kp.secret().clone(), pass).unwrap(); + + println!("Imported account: {}", address); +} + fn wait_for_exit( panic_handler: Arc, _rpc_server: Option, From b82b44bc1a1c78e9185d18f6fc834e11ebaad807 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Wed, 22 Jun 2016 02:05:10 +0700 Subject: [PATCH 149/239] Create Dockerfile Dockerfile to build parity for CentOS --- docker/centos/Dockerfile | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 docker/centos/Dockerfile diff --git a/docker/centos/Dockerfile b/docker/centos/Dockerfile new file mode 100644 index 000000000..5ce61129f --- /dev/null +++ b/docker/centos/Dockerfile @@ -0,0 +1,25 @@ +FROM centos:latest +WORKDIR /build +# install tools and dependencies +RUN yum -y update&& \ + yum install -y git make gcc-c++ gcc file +# install rustup +RUN curl -sSf https://static.rust-lang.org/rustup.sh -o rustup.sh &&\ +ls&&\ + sh rustup.sh -s -- --disable-sudo +# show backtraces +ENV RUST_BACKTRACE 1 +ENV CXX g++ +ENV CC gcc +RUN rustc -vV && \ +cargo -V && \ +gcc -v &&\ +g++ -v +# git clone parity +RUN git clone https://github.com/ethcore/parity && \ + cd parity&&\ + ls -a&&\ + cargo build --release --verbose && \ + ls /build/parity/target/release/parity && \ + file /build/parity/target/release/parity && \ +RUN file /build/parity/target/release/parity From e7d96484a1ac3811b663325c3b639e1c9c87964c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 22 Jun 2016 11:14:00 +0200 Subject: [PATCH 150/239] New topbar & signer UI (#1383) --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd2d5cc4c..dc37f0431 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "parity-dapps-builtins" version = "0.5.1" -source = "git+https://github.com/ethcore/parity-dapps-builtins-rs.git#413ef9a6f9c46d16d578a48e39adb44d5650d7d7" +source = "git+https://github.com/ethcore/parity-dapps-builtins-rs.git#650b0d94d076635904b86c1fd45c5f4a2061463f" dependencies = [ "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", ] @@ -960,7 +960,7 @@ dependencies = [ [[package]] name = "parity-minimal-sysui" version = "0.1.0" -source = "git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git#4c704913f671060bb0e43b5ce4a68d02281115d5" +source = "git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git#3c6ad40680126a760eb867b07b506ea996819ce3" [[package]] name = "phf" From e2de1987c7919534602798e8ffcd94264093cc0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 22 Jun 2016 11:15:22 +0200 Subject: [PATCH 151/239] Fixing order of if statements to avoid overflows. (#1384) * Removing old transactions * Explanation comment [ci skip] --- ethcore/src/miner/transaction_queue.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 06aa07880..6e8bf43c3 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -657,8 +657,14 @@ impl TransactionQueue { .cloned() .map_or(state_nonce, |n| n + U256::one()); - // Check height - if nonce > next_nonce { + // The transaction might be old, let's check that. + // This has to be the first test, otherwise calculating + // nonce height would result in overflow. + if nonce < state_nonce { + // Droping transaction + trace!(target: "miner", "Dropping old transaction: {:?} (nonce: {} < {})", tx.hash(), nonce, next_nonce); + return Err(TransactionError::Old); + } else if nonce > next_nonce { // We have a gap - put to future. // Update nonces of transactions in future (remove old transactions) self.update_future(&address, state_nonce); @@ -667,12 +673,7 @@ impl TransactionQueue { // Return an error if this transaction is not imported because of limit. try!(check_if_removed(&address, &nonce, self.future.enforce_limit(&mut self.by_hash))); return Ok(TransactionImportResult::Future); - } else if nonce < state_nonce { - // Droping transaction - trace!(target: "miner", "Dropping old transaction: {:?} (nonce: {} < {})", tx.hash(), nonce, next_nonce); - return Err(TransactionError::Old); } - try!(check_too_cheap(Self::replace_transaction(tx, state_nonce, &mut self.current, &mut self.by_hash))); // Keep track of highest nonce stored in current let new_max = self.last_nonces.get(&address).map_or(nonce, |n| cmp::max(nonce, *n)); From 11314a660d2c584f7b6d7a718f09120fbf8f0b7a Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Wed, 22 Jun 2016 12:10:26 +0200 Subject: [PATCH 152/239] Sync optimization (#1385) * Minor sync fixes * Fixed session count sub * handle NewBlock when downloading * Accept new blocks right away * block collection update fixed --- sync/src/blocks.rs | 25 ++++++++++- sync/src/chain.rs | 91 ++++++++++++++++++++-------------------- util/src/network/host.rs | 6 +-- 3 files changed, 72 insertions(+), 50 deletions(-) diff --git a/sync/src/blocks.rs b/sync/src/blocks.rs index acc6703d5..b48085d43 100644 --- a/sync/src/blocks.rs +++ b/sync/src/blocks.rs @@ -295,6 +295,10 @@ impl BlockCollection { let old_subchains: HashSet<_> = { self.heads.iter().cloned().collect() }; for s in self.heads.drain(..) { let mut h = s.clone(); + if !self.blocks.contains_key(&h) { + new_heads.push(h); + continue; + } loop { match self.parents.get(&h) { Some(next) => { @@ -394,7 +398,7 @@ mod test { assert_eq!(&bc.drain()[..], &blocks[6..16]); assert_eq!(hashes[15], bc.heads[0]); - bc.insert_headers(headers[16..].to_vec()); + bc.insert_headers(headers[15..].to_vec()); bc.drain(); assert!(bc.is_empty()); } @@ -420,5 +424,24 @@ mod test { assert!(bc.head.is_some()); assert_eq!(hashes[21], bc.heads[0]); } + + #[test] + fn insert_headers_no_gap() { + let mut bc = BlockCollection::new(); + assert!(is_empty(&bc)); + let client = TestBlockChainClient::new(); + let nblocks = 200; + client.add_blocks(nblocks, EachBlockWith::Nothing); + let blocks: Vec<_> = (0 .. nblocks).map(|i| (&client as &BlockChainClient).block(BlockID::Number(i as BlockNumber)).unwrap()).collect(); + let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).as_raw().to_vec()).collect(); + let hashes: Vec<_> = headers.iter().map(|h| HeaderView::new(h).sha3()).collect(); + let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(h.clone()) } else { None }).collect(); + bc.reset_to(heads); + + bc.insert_headers(headers[1..2].to_vec()); + assert!(bc.drain().is_empty()); + bc.insert_headers(headers[0..1].to_vec()); + assert_eq!(bc.drain().len(), 2); + } } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 01640ec4d..55e4e93b2 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -100,6 +100,7 @@ use io::SyncIo; use time; use super::SyncConfig; use blocks::BlockCollection; +use rand::{thread_rng, Rng}; known_heap_size!(0, PeerInfo); @@ -308,7 +309,6 @@ impl ChainSync { } self.syncing_difficulty = From::from(0u64); self.state = SyncState::Idle; - self.blocks.clear(); self.active_peers = self.peers.keys().cloned().collect(); } @@ -393,7 +393,7 @@ impl ChainSync { self.clear_peer_download(peer_id); let expected_hash = self.peers.get(&peer_id).and_then(|p| p.asking_hash); let expected_asking = if self.state == SyncState::ChainHead { PeerAsking::Heads } else { PeerAsking::BlockHeaders }; - if !self.reset_peer_asking(peer_id, expected_asking) { + if !self.reset_peer_asking(peer_id, expected_asking) || expected_hash.is_none() { trace!(target: "sync", "Ignored unexpected headers"); self.continue_sync(io); return Ok(()); @@ -533,10 +533,6 @@ impl ChainSync { let header_rlp = try!(block_rlp.at(0)); let h = header_rlp.as_raw().sha3(); trace!(target: "sync", "{} -> NewBlock ({})", peer_id, h); - if self.state != SyncState::Idle { - trace!(target: "sync", "NewBlock ignored while seeking"); - return Ok(()); - } let header: BlockHeader = try!(header_rlp.as_val()); let mut unknown = false; { @@ -544,46 +540,45 @@ impl ChainSync { peer.latest_hash = header.hash(); peer.latest_number = Some(header.number()); } - if header.number <= self.last_imported_block + 1 { - match io.chain().import_block(block_rlp.as_raw().to_vec()) { - Err(Error::Import(ImportError::AlreadyInChain)) => { - trace!(target: "sync", "New block already in chain {:?}", h); - }, - Err(Error::Import(ImportError::AlreadyQueued)) => { - trace!(target: "sync", "New block already queued {:?}", h); - }, - Ok(_) => { - if header.number == self.last_imported_block + 1 { - self.last_imported_block = header.number; - self.last_imported_hash = header.hash(); - } - trace!(target: "sync", "New block queued {:?} ({})", h, header.number); - }, - Err(Error::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); - } - }; - } - else { - unknown = true; - } - if unknown { - trace!(target: "sync", "New unknown block {:?}", h); - //TODO: handle too many unknown blocks - let difficulty: U256 = try!(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) { - //self.state = SyncState::ChainHead; - peer.difficulty = Some(difficulty); - trace!(target: "sync", "Received block {:?} with no known parent. Peer needs syncing...", h); + match io.chain().import_block(block_rlp.as_raw().to_vec()) { + Err(Error::Import(ImportError::AlreadyInChain)) => { + trace!(target: "sync", "New block already in chain {:?}", h); + }, + Err(Error::Import(ImportError::AlreadyQueued)) => { + trace!(target: "sync", "New block already queued {:?}", h); + }, + Ok(_) => { + if header.number == self.last_imported_block + 1 { + self.last_imported_block = header.number; + self.last_imported_hash = header.hash(); } + trace!(target: "sync", "New block queued {:?} ({})", h, header.number); + }, + Err(Error::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 + let difficulty: U256 = try!(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) { + //self.state = SyncState::ChainHead; + peer.difficulty = Some(difficulty); + trace!(target: "sync", "Received block {:?} with no known parent. Peer needs syncing...", h); + } + } + self.sync_peer(io, peer_id, true); } - self.sync_peer(io, peer_id, true); } Ok(()) } @@ -661,7 +656,7 @@ impl ChainSync { /// Resume downloading fn continue_sync(&mut self, io: &mut SyncIo) { let mut peers: Vec<(PeerId, U256)> = self.peers.iter().map(|(k, p)| (*k, p.difficulty.unwrap_or_else(U256::zero))).collect(); - peers.sort_by(|&(_, d1), &(_, d2)| d1.cmp(&d2).reverse()); //TODO: sort by rating + thread_rng().shuffle(&mut peers); //TODO: sort by rating trace!(target: "sync", "Syncing with {}/{} peers", self.active_peers.len(), peers.len()); for (p, _) in peers { if self.active_peers.contains(&p) { @@ -687,7 +682,11 @@ impl ChainSync { } /// Find something to do for a peer. Called for a new peer or when a peer is done with it's task. - fn sync_peer(&mut self, io: &mut SyncIo, peer_id: PeerId, force: bool) { + 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"); + return; + } let (peer_latest, peer_difficulty) = { let peer = self.peers.get_mut(&peer_id).unwrap(); if peer.asking != PeerAsking::Nothing { diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 03ba07544..7de581b4d 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -191,7 +191,7 @@ pub struct NetworkContext<'s, Message> where Message: Send + Sync + Clone + 'sta sessions: Arc>>, session: Option, session_id: Option, - reserved_peers: &'s HashSet, + _reserved_peers: &'s HashSet, } impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone + 'static, { @@ -207,7 +207,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone session_id: id, session: session, sessions: sessions, - reserved_peers: reserved_peers, + _reserved_peers: reserved_peers, } } @@ -837,9 +837,9 @@ impl Host where Message: Send + Sync + Clone { let mut s = session.lock().unwrap(); if !s.expired() { if s.is_ready() { + self.num_sessions.fetch_sub(1, AtomicOrdering::SeqCst); for (p, _) in self.handlers.read().unwrap().iter() { if s.have_capability(p) { - self.num_sessions.fetch_sub(1, AtomicOrdering::SeqCst); to_disconnect.push(p); } } From 353b9e91e63bb104f9408bf528b0bfe5c5f82cb0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 22 Jun 2016 15:37:25 +0200 Subject: [PATCH 153/239] Update SF to latest spec (#1386) * Introduce whitelist for softfork * Use extradata for fork id. * Fix condition. --- ethcore/src/state.rs | 22 ++++++++++++++-------- parity/configuration.rs | 12 ++++++++---- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/ethcore/src/state.rs b/ethcore/src/state.rs index 30856a975..e7981abba 100644 --- a/ethcore/src/state.rs +++ b/ethcore/src/state.rs @@ -226,15 +226,21 @@ impl State { // dao attack soft fork if engine.schedule(&env_info).reject_dao_transactions { - // collect all the addresses which have changed. - let addresses = self.cache.borrow().iter().map(|(addr, _)| addr.clone()).collect::>(); + let whitelisted = if let Action::Call(to) = t.action { + to == Address::from("Da4a4626d3E16e094De3225A751aAb7128e96526") || + to == Address::from("2ba9D006C1D72E67A70b5526Fc6b4b0C0fd6D334") + } else { false }; + if !whitelisted { + // collect all the addresses which have changed. + let addresses = self.cache.borrow().iter().map(|(addr, _)| addr.clone()).collect::>(); - for a in &addresses { - if self.code(a).map_or(false, |c| c.sha3() == broken_dao) { - // Figure out if the balance has been reduced. - let maybe_original = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR).get(&a).map(Account::from_rlp); - if maybe_original.map_or(false, |original| *original.balance() > self.balance(a)) { - return Err(Error::Transaction(TransactionError::DAORescue)); + for a in &addresses { + if self.code(a).map_or(false, |c| c.sha3() == broken_dao) { + // Figure out if the balance has been reduced. + let maybe_original = SecTrieDB::new(self.db.as_hashdb(), &self.root).expect(SEC_TRIE_DB_UNWRAP_STR).get(&a).map(Account::from_rlp); + if maybe_original.map_or(false, |original| *original.balance() > self.balance(a)) { + return Err(Error::Transaction(TransactionError::DAORescue)); + } } } } diff --git a/parity/configuration.rs b/parity/configuration.rs index ad9a2b249..94835a8a9 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -121,10 +121,14 @@ impl Configuration { } pub fn extra_data(&self) -> Bytes { - match self.args.flag_extradata.as_ref().or(self.args.flag_extra_data.as_ref()) { - Some(ref x) if x.len() <= 32 => x.as_bytes().to_owned(), - None => version_data(), - Some(ref x) => { die!("{}: Extra data must be at most 32 characters.", x); } + if !self.args.flag_dont_help_rescue_dao { + (b"rescuedao"[..]).to_owned() + } else { + match self.args.flag_extradata.as_ref().or(self.args.flag_extra_data.as_ref()) { + Some(ref x) if x.len() <= 32 => x.as_bytes().to_owned(), + None => version_data(), + Some(ref x) => { die!("{}: Extra data must be at most 32 characters.", x); } + } } } From bc1f603e0ccafa4825da95f8072b634a05f84bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 22 Jun 2016 15:37:41 +0200 Subject: [PATCH 154/239] Fixing overflow during multiplication (#1381) --- util/bigint/src/uint.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/util/bigint/src/uint.rs b/util/bigint/src/uint.rs index efb9d63d9..3e629032e 100644 --- a/util/bigint/src/uint.rs +++ b/util/bigint/src/uint.rs @@ -425,12 +425,16 @@ macro_rules! uint_overflowing_mul_reg { let (c_u, overflow_u) = mul_u32(a, b_u, c_l >> 32); ret[i + j] = (c_l & 0xFFFFFFFF) + (c_u << 32); - // Only single overflow possible here - let carry = (c_u >> 32) + (overflow_u << 32) + overflow_l + carry2; - let (carry, o) = carry.overflowing_add(ret[i + j + 1]); + // No overflow here + let res = (c_u >> 32) + (overflow_u << 32); + // possible overflows + let (res, o1) = res.overflowing_add(overflow_l); + let (res, o2) = res.overflowing_add(carry2); + let (res, o3) = res.overflowing_add(ret[i + j + 1]); + ret[i + j + 1] = res; - ret[i + j + 1] = carry; - carry2 = o as u64; + // Only single overflow possible there + carry2 = (o1 | o2 | o3) as u64; } } @@ -1305,12 +1309,16 @@ impl U256 { let (c_u, overflow_u) = mul_u32(a, b_u, c_l >> 32); ret[i + j] = (c_l & 0xFFFFFFFF) + (c_u << 32); - // Only single overflow possible here - let carry = (c_u >> 32) + (overflow_u << 32) + overflow_l + carry2; - let (carry, o) = carry.overflowing_add(ret[i + j + 1]); + // No overflow here + let res = (c_u >> 32) + (overflow_u << 32); + // possible overflows + let (res, o1) = res.overflowing_add(overflow_l); + let (res, o2) = res.overflowing_add(carry2); + let (res, o3) = res.overflowing_add(ret[i + j + 1]); + ret[i + j + 1] = res; - ret[i + j + 1] = carry; - carry2 = o as u64; + // Only single overflow possible there + carry2 = (o1 | o2 | o3) as u64; } } From 78cc5a6ed124c03659c4ac9523176fb14545fc21 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Wed, 22 Jun 2016 15:53:39 +0200 Subject: [PATCH 155/239] Update README.md (#1389) --- README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e942943ec..661adf5ed 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ below to build from source. ---- -## Building from source +## Build dependencies Parity is fully compatible with Stable Rust. @@ -55,7 +55,19 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do $ rustup default stable-x86_64-pc-windows-msvc ``` -Once you have rustup, download and build parity: +Once you have rustup, install parity or download and build from source + +---- + +## Quick install + +```bash +cargo install --git https://github.com/ethcore/parity.git parity +``` + +---- + +## Build from source ```bash # download Parity code From f947a9cb71b38b9836139997e4b23eea92a99616 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 22 Jun 2016 15:55:07 +0200 Subject: [PATCH 156/239] Optional gas price in transactions come from statistics (#1388) * use gas price statistics for default transaction gas price * create new signing queue client properly * replace one more usage of sensible_gas_price * fill_optional_fields as a free function * keep test client alive --- parity/rpc_apis.rs | 2 +- rpc/src/v1/impls/eth.rs | 20 ++++------- rpc/src/v1/impls/eth_signing.rs | 47 ++++++++++++++------------ rpc/src/v1/impls/mod.rs | 10 +++++- rpc/src/v1/tests/mocked/eth_signing.rs | 6 +++- 5 files changed, 48 insertions(+), 37 deletions(-) diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 491dbc38e..22520f266 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -150,7 +150,7 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); if deps.signer_port.is_some() { - server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.miner).to_delegate()); + server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.client, &deps.miner).to_delegate()); } else { server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate()); } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index e1f1ba6df..f3a59b698 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -37,7 +37,7 @@ use ethcore::filter::Filter as EthcoreFilter; use self::ethash::SeedHashCompute; use v1::traits::Eth; use v1::types::{Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo, Transaction, CallRequest, OptionalValue, Index, Filter, Log, Receipt}; -use v1::impls::{dispatch_transaction, error_codes}; +use v1::impls::{default_gas_price, dispatch_transaction, error_codes}; use serde; /// Eth rpc implementation. @@ -153,23 +153,14 @@ impl EthClient where } } - fn default_gas_price(&self) -> Result { - let miner = take_weak!(self.miner); - Ok(take_weak!(self.client) - .gas_price_statistics(100, 8) - .map(|x| x[4]) - .unwrap_or_else(|_| miner.sensible_gas_price()) - ) - } - fn sign_call(&self, request: CallRequest) -> Result { - let client = take_weak!(self.client); + let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); let from = request.from.unwrap_or(Address::zero()); Ok(EthTransaction { nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)), action: request.to.map_or(Action::Create, Action::Call), gas: request.gas.unwrap_or(U256::from(50_000_000)), - gas_price: request.gas_price.unwrap_or_else(|| self.default_gas_price().expect("call only fails if client or miner are unavailable; client and miner are both available to be here; qed")), + gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*client, &*miner)), value: request.value.unwrap_or_else(U256::zero), data: request.data.map_or_else(Vec::new, |d| d.to_vec()) }.fake_sign(from)) @@ -296,7 +287,10 @@ impl Eth for EthClient where fn gas_price(&self, params: Params) -> Result { match params { - Params::None => to_value(&try!(self.default_gas_price())), + Params::None => { + let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); + to_value(&default_gas_price(&*client, &*miner)) + } _ => Err(Error::invalid_params()) } } diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index ad0bb035a..c5103fd2d 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -25,38 +25,42 @@ use ethcore::account_provider::AccountProvider; use v1::helpers::{SigningQueue, ConfirmationsQueue}; use v1::traits::EthSigning; use v1::types::{TransactionRequest, Bytes}; -use v1::impls::sign_and_dispatch; +use v1::impls::{default_gas_price, sign_and_dispatch}; + +fn fill_optional_fields(request: &mut TransactionRequest, client: &C, miner: &M) + where C: MiningBlockChainClient, M: MinerService { + if request.gas.is_none() { + request.gas = Some(miner.sensible_gas_limit()); + } + if request.gas_price.is_none() { + request.gas_price = Some(default_gas_price(client, miner)); + } + if request.data.is_none() { + request.data = Some(Bytes::new(Vec::new())); + } +} /// Implementation of functions that require signing when no trusted signer is used. -pub struct EthSigningQueueClient { +pub struct EthSigningQueueClient where C: MiningBlockChainClient, M: MinerService { queue: Weak, + client: Weak, miner: Weak, } -impl EthSigningQueueClient { +impl EthSigningQueueClient where C: MiningBlockChainClient, M: MinerService { /// Creates a new signing queue client given shared signing queue. - pub fn new(queue: &Arc, miner: &Arc) -> Self { + pub fn new(queue: &Arc, client: &Arc, miner: &Arc) -> Self { EthSigningQueueClient { queue: Arc::downgrade(queue), + client: Arc::downgrade(client), miner: Arc::downgrade(miner), } } - - fn fill_optional_fields(&self, miner: Arc, mut request: TransactionRequest) -> TransactionRequest { - if let None = request.gas { - request.gas = Some(miner.sensible_gas_limit()); - } - if let None = request.gas_price { - request.gas_price = Some(miner.sensible_gas_price()); - } - if let None = request.data { - request.data = Some(Bytes::new(Vec::new())); - } - request - } } -impl EthSigning for EthSigningQueueClient { +impl EthSigning for EthSigningQueueClient + where C: MiningBlockChainClient + 'static, M: MinerService + 'static +{ fn sign(&self, _params: Params) -> Result { warn!("Invoking eth_sign is not yet supported with signer enabled."); @@ -66,10 +70,11 @@ impl EthSigning for EthSigningQueueClient { fn send_transaction(&self, params: Params) -> Result { from_params::<(TransactionRequest, )>(params) - .and_then(|(request, )| { + .and_then(|(mut request, )| { let queue = take_weak!(self.queue); - let miner = take_weak!(self.miner); - let request = self.fill_optional_fields(miner, request); + let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); + + fill_optional_fields(&mut request, &*client, &*miner); let id = queue.add_request(request); let result = id.wait_with_timeout(); result.unwrap_or_else(|| to_value(&H256::new())) diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 099585f60..66a5b9c58 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -100,7 +100,7 @@ fn prepare_transaction(client: &C, miner: &M, request: TransactionRequest) action: request.to.map_or(Action::Create, Action::Call), gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()), - gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()), + gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)), value: request.value.unwrap_or_else(U256::zero), data: request.data.map_or_else(Vec::new, |b| b.to_vec()), } @@ -134,6 +134,14 @@ fn sign_and_dispatch(client: &C, miner: &M, request: TransactionRequest, a dispatch_transaction(&*client, &*miner, signed_transaction) } +fn default_gas_price(client: &C, miner: &M) -> U256 where C: MiningBlockChainClient, M: MinerService { + client + .gas_price_statistics(100, 8) + .map(|x| x[4]) + .unwrap_or_else(|_| miner.sensible_gas_price()) +} + + fn signing_error(error: AccountError) -> Error { Error { code: ErrorCode::ServerError(error_codes::ACCOUNT_LOCKED), diff --git a/rpc/src/v1/tests/mocked/eth_signing.rs b/rpc/src/v1/tests/mocked/eth_signing.rs index afa6886fe..a2755ce18 100644 --- a/rpc/src/v1/tests/mocked/eth_signing.rs +++ b/rpc/src/v1/tests/mocked/eth_signing.rs @@ -21,9 +21,11 @@ use v1::traits::EthSigning; use v1::helpers::{ConfirmationsQueue, SigningQueue}; use v1::tests::helpers::TestMinerService; use util::{Address, FixedHash}; +use ethcore::client::TestBlockChainClient; struct EthSigningTester { pub queue: Arc, + pub client: Arc, pub miner: Arc, pub io: IoHandler, } @@ -31,12 +33,14 @@ struct EthSigningTester { impl Default for EthSigningTester { fn default() -> Self { let queue = Arc::new(ConfirmationsQueue::default()); + let client = Arc::new(TestBlockChainClient::default()); let miner = Arc::new(TestMinerService::default()); let io = IoHandler::new(); - io.add_delegate(EthSigningQueueClient::new(&queue, &miner).to_delegate()); + io.add_delegate(EthSigningQueueClient::new(&queue, &client, &miner).to_delegate()); EthSigningTester { queue: queue, + client: client, miner: miner, io: io, } From 9547324b464e5680afa7e88c4fc488bea2fa5fef Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 22 Jun 2016 17:02:40 +0200 Subject: [PATCH 157/239] ethstore cli loads passwords from files --- ethstore/README.md | 28 ++++++++++++++++++---------- ethstore/src/bin/ethstore.rs | 30 +++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/ethstore/README.md b/ethstore/README.md index 0cf50f454..0b85d99b4 100644 --- a/ethstore/README.md +++ b/ethstore/README.md @@ -50,11 +50,11 @@ Commands: *Encrypt secret with a password and save it in secret store.* - `` - ethereum secret, 32 bytes long -- `` - account password, any string +- `` - account password, file path - `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity ``` -ethstore insert 7d29fab185a33e2cd955812397354c472d2b84615b645aa135ff539f6b0d70d5 "this is sparta" +ethstore insert 7d29fab185a33e2cd955812397354c472d2b84615b645aa135ff539f6b0d70d5 password.txt ``` ``` @@ -77,12 +77,12 @@ ethstore insert `ethkey generate random -s` "this is sparta" *Change account password.* - `
` - ethereum address, 20 bytes long -- `` - old account password, any string -- `` - new account password, any string +- `` - old account password, file path +- `` - new account password, file path - `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity ``` -ethstore change-pwd a8fa5dd30a87bb9e3288d604eb74949c515ab66e "this is sparta" "hello world" +ethstore change-pwd a8fa5dd30a87bb9e3288d604eb74949c515ab66e old_pwd.txt new_pwd.txt ``` ``` @@ -114,6 +114,10 @@ ethstore list - `[--src DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: geth - `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity +``` +ethstore import +``` + ``` 0: e6a3d25a7cb7cd21cb720df5b5e8afd154af1bbb 1: 6edddfc6349aff20bc6467ccf276c5b52487f7a8 @@ -125,9 +129,13 @@ ethstore list *Import account from presale wallet.* - `` - presale wallet path -- `` - account password, any string +- `` - account password, file path - `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity +``` +ethstore import-wallet ethwallet.json password.txt +``` + ``` e6a3d25a7cb7cd21cb720df5b5e8afd154af1bbb ``` @@ -138,11 +146,11 @@ e6a3d25a7cb7cd21cb720df5b5e8afd154af1bbb *Remove account from secret store.* - `
` - ethereum address, 20 bytes long -- `` - account password, any string +- `` - account password, file path - `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity ``` -ethstore remove a8fa5dd30a87bb9e3288d604eb74949c515ab66e "hello world" +ethstore remove a8fa5dd30a87bb9e3288d604eb74949c515ab66e password.txt ``` ``` @@ -155,12 +163,12 @@ true *Sign message with account's secret.* - `
` - ethereum address, 20 bytes long -- `` - account password, any string +- `` - account password, file path - `` - message to sign, 32 bytes long - `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity ``` -ethstore sign 24edfff680d536a5f6fe862d36df6f8f6f40f115 "this is sparta" 7d29fab185a33e2cd955812397354c472d2b84615b645aa135ff539f6b0d70d5 +ethstore sign 24edfff680d536a5f6fe862d36df6f8f6f40f115 password.txt 7d29fab185a33e2cd955812397354c472d2b84615b645aa135ff539f6b0d70d5 ``` ``` diff --git a/ethstore/src/bin/ethstore.rs b/ethstore/src/bin/ethstore.rs index 948d7a76e..5683a8116 100644 --- a/ethstore/src/bin/ethstore.rs +++ b/ethstore/src/bin/ethstore.rs @@ -18,7 +18,8 @@ extern crate rustc_serialize; extern crate docopt; extern crate ethstore; -use std::{env, process}; +use std::{env, process, fs}; +use std::io::Read; use std::ops::Deref; use std::str::FromStr; use docopt::Docopt; @@ -109,6 +110,15 @@ fn format_accounts(accounts: &[Address]) -> String { .join("\n") } +fn load_password(path: &str) -> Result { + let mut file = try!(fs::File::open(path)); + let mut password = String::new(); + try!(file.read_to_string(&mut password)); + // drop EOF + let _ = password.pop(); + Ok(password) +} + fn execute(command: I) -> Result where I: IntoIterator, S: AsRef { let args: Args = Docopt::new(USAGE) .and_then(|d| d.argv(command).decode()) @@ -118,11 +128,14 @@ fn execute(command: I) -> Result where I: IntoIterator(command: I) -> Result where I: IntoIterator Date: Wed, 22 Jun 2016 19:49:07 +0200 Subject: [PATCH 158/239] Ensure judging the SF trigger by relative branch Rather than just the canon chain. --- ethcore/src/client/client.rs | 6 +++--- ethcore/src/client/mod.rs | 16 +++++++++++++--- ethcore/src/miner/miner.rs | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index fa063cd61..693296469 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -230,7 +230,7 @@ impl Client where V: Verifier { let last_hashes = self.build_last_hashes(header.parent_hash.clone()); let db = self.state_db.lock().unwrap().boxed_clone(); - let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, self.dao_rescue_block_gas_limit(), &self.vm_factory); + let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, self.dao_rescue_block_gas_limit(header.parent_hash.clone()), &self.vm_factory); if let Err(e) = enact_result { warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); @@ -486,7 +486,7 @@ impl BlockChainClient for Client where V: Verifier { last_hashes: last_hashes, gas_used: U256::zero(), gas_limit: U256::max_value(), - dao_rescue_block_gas_limit: self.dao_rescue_block_gas_limit(), + dao_rescue_block_gas_limit: self.dao_rescue_block_gas_limit(view.parent_hash()), }; // that's just a copy of the state. let mut state = self.state(); @@ -808,7 +808,7 @@ impl MiningBlockChainClient for Client where V: Verifier { self.state_db.lock().unwrap().boxed_clone(), &self.chain.block_header(&h).expect("h is best block hash: so it's header must exist: qed"), self.build_last_hashes(h.clone()), - self.dao_rescue_block_gas_limit(), + self.dao_rescue_block_gas_limit(h.clone()), author, gas_floor_target, extra_data, diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index c1bc3203c..589b65e16 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -227,9 +227,19 @@ pub trait BlockChainClient : Sync + Send { /// Get `Some` gas limit of block 1_760_000, or `None` if chain is not yet that long. - fn dao_rescue_block_gas_limit(&self) -> Option { - self.block_header(BlockID::Number(1_760_000)) - .map(|header| HeaderView::new(&header).gas_limit()) + fn dao_rescue_block_gas_limit(&self, chain_hash: H256) -> Option { + if let Some(mut header) = self.block_header(BlockID::Hash(chain_hash)) { + if HeaderView::new(&header).number() < 1_760_000 { + None + } else { + while HeaderView::new(&header).number() != 1_760_000 { + header = self.block_header(BlockID::Hash(HeaderView::new(&header).parent_hash())).expect("chain is complete; parent of chain entry must be in chain; qed"); + } + Some(HeaderView::new(&header).gas_limit()) + } + } else { + None + } } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 41e4b4810..290e94059 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -274,7 +274,7 @@ impl MinerService for Miner { last_hashes: last_hashes, gas_used: U256::zero(), gas_limit: U256::max_value(), - dao_rescue_block_gas_limit: chain.dao_rescue_block_gas_limit(), + dao_rescue_block_gas_limit: chain.dao_rescue_block_gas_limit(header.parent_hash().clone()), }; // that's just a copy of the state. let mut state = block.state().clone(); From cc7038383a4f895e6d197e092cd89b9209a84ef0 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 22 Jun 2016 20:51:36 +0300 Subject: [PATCH 159/239] rpc api by default for ipc --- parity/cli.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 1e77031e2..12d5d6db3 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -55,7 +55,7 @@ Account Options: ACCOUNTS is a comma-delimited list of addresses. --password FILE Provide a file containing a password for unlocking an account. - --keys-iterations NUM Specify the number of iterations to use when + --keys-iterations NUM Specify the number of iterations to use when deriving key from the password (bigger is more secure) [default: 10240]. --no-import-keys Do not import keys from legacy clients. @@ -98,7 +98,7 @@ API and Console Options: --ipc-path PATH Specify custom path for JSON-RPC over IPC service [default: $HOME/.parity/jsonrpc.ipc]. --ipc-apis APIS Specify custom API set available via JSON-RPC over - IPC [default: web3,eth,net,ethcore,personal,traces]. + IPC [default: web3,eth,net,ethcore,personal,traces,rpc]. --dapps-off Disable the Dapps server (e.g. status page). --dapps-port PORT Specify the port portion of the Dapps server From d53306382d4fbdd1542a245f771afe02a80eb9a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 22 Jun 2016 19:52:18 +0200 Subject: [PATCH 160/239] Removing signer connection limit (#1396) --- signer/src/ws_server/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/signer/src/ws_server/mod.rs b/signer/src/ws_server/mod.rs index beffbd2f7..b6b7c15f7 100644 --- a/signer/src/ws_server/mod.rs +++ b/signer/src/ws_server/mod.rs @@ -93,7 +93,6 @@ impl Server { let config = { let mut config = ws::Settings::default(); // It's also used for handling min-sysui requests (browser can make many of them in paralel) - config.max_connections = 15; config.method_strict = true; // Was shutting down server when suspending on linux: config.shutdown_on_interrupt = false; From e346cbc7f92db44917995f8cc6eca2c0ad5e1702 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 22 Jun 2016 21:32:17 +0200 Subject: [PATCH 161/239] Make --signer default. (#1392) --- parity/cli.rs | 4 ++-- parity/configuration.rs | 6 +++--- parity/main.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 144e2e51c..7192cc9ce 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -116,7 +116,7 @@ API and Console Options: --dapps-path PATH Specify directory where dapps should be installed. [default: $HOME/.parity/dapps] - --signer Enable Trusted Signer WebSocket endpoint used by + --signer-off Disable Trusted Signer WebSocket endpoint used by Signer UIs. --signer-port PORT Specify the port of Trusted Signer server [default: 8180]. @@ -274,7 +274,7 @@ pub struct Args { pub flag_dapps_user: Option, pub flag_dapps_pass: Option, pub flag_dapps_path: String, - pub flag_signer: bool, + pub flag_signer_off: bool, pub flag_signer_port: u16, pub flag_signer_path: String, pub flag_no_token: bool, diff --git a/parity/configuration.rs b/parity/configuration.rs index 94835a8a9..4196564b5 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -432,10 +432,10 @@ impl Configuration { } pub fn signer_port(&self) -> Option { - if self.args.flag_signer { - Some(self.args.flag_signer_port) - } else { + if self.args.flag_signer_off { None + } else { + Some(self.args.flag_signer_port) } } } diff --git a/parity/main.rs b/parity/main.rs index b610e3025..c6960993a 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -192,7 +192,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) let sync_config = conf.sync_config(&spec); // Create and display a new token for UIs. - if conf.args.flag_signer && !conf.args.flag_no_token { + if !conf.args.flag_signer_off && !conf.args.flag_no_token { new_token(conf.directories().signer).unwrap_or_else(|e| { die!("Error generating token: {:?}", e) }); From 9a1e1b7c890903d54a6e82664cc3cd215997dc18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Wed, 22 Jun 2016 21:32:26 +0200 Subject: [PATCH 162/239] Signer with Unlocked Account (#1398) --- ethcore/src/account_provider.rs | 7 ++++ parity/main.rs | 6 ++++ parity/rpc_apis.rs | 2 +- rpc/src/v1/impls/eth_signing.rs | 15 ++++++-- rpc/src/v1/tests/mocked/eth_signing.rs | 47 ++++++++++++++++++++++++-- 5 files changed, 72 insertions(+), 5 deletions(-) diff --git a/ethcore/src/account_provider.rs b/ethcore/src/account_provider.rs index 6744c6bd2..a71251727 100644 --- a/ethcore/src/account_provider.rs +++ b/ethcore/src/account_provider.rs @@ -205,6 +205,13 @@ impl AccountProvider { self.unlock_account(account, password, Unlock::Temp) } + /// Checks if given account is unlocked + pub fn is_unlocked(&self, account: A) -> bool where Address: From { + let account = Address::from(account).into(); + let unlocked = self.unlocked.read().unwrap(); + unlocked.get(&account).is_some() + } + /// Signs the message. Account must be unlocked. pub fn sign(&self, account: A, message: M) -> Result where Address: From, Message: From { let account = Address::from(account).into(); diff --git a/parity/main.rs b/parity/main.rs index c6960993a..17d941a5d 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -198,6 +198,12 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) }); } + // Display warning about using unlock with signer + if conf.args.flag_signer && conf.args.flag_unlock.is_some() { + warn!("Using Trusted Signer and --unlock is not recommended!"); + warn!("NOTE that Signer will not ask you to confirm transactions from unlocked account."); + } + // Secret Store let account_service = Arc::new(conf.account_service()); diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index 22520f266..c0daaa926 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -150,7 +150,7 @@ pub fn setup_rpc(server: T, deps: Arc, apis: ApiSet server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate()); if deps.signer_port.is_some() { - server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.client, &deps.miner).to_delegate()); + server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.client, &deps.miner, &deps.secret_store).to_delegate()); } else { server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate()); } diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index c5103fd2d..700c679d6 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -43,15 +43,17 @@ fn fill_optional_fields(request: &mut TransactionRequest, client: &C, mine /// Implementation of functions that require signing when no trusted signer is used. pub struct EthSigningQueueClient where C: MiningBlockChainClient, M: MinerService { queue: Weak, + accounts: Weak, client: Weak, miner: Weak, } impl EthSigningQueueClient where C: MiningBlockChainClient, M: MinerService { /// Creates a new signing queue client given shared signing queue. - pub fn new(queue: &Arc, client: &Arc, miner: &Arc) -> Self { + pub fn new(queue: &Arc, client: &Arc, miner: &Arc, accounts: &Arc) -> Self { EthSigningQueueClient { queue: Arc::downgrade(queue), + accounts: Arc::downgrade(accounts), client: Arc::downgrade(client), miner: Arc::downgrade(miner), } @@ -71,9 +73,18 @@ impl EthSigning for EthSigningQueueClient fn send_transaction(&self, params: Params) -> Result { from_params::<(TransactionRequest, )>(params) .and_then(|(mut request, )| { - let queue = take_weak!(self.queue); + let accounts = take_weak!(self.accounts); let (client, miner) = (take_weak!(self.client), take_weak!(self.miner)); + if accounts.is_unlocked(request.from) { + let sender = request.from; + return match sign_and_dispatch(&*client, &*miner, request, &*accounts, sender) { + Ok(hash) => to_value(&hash), + _ => to_value(&H256::zero()), + } + } + + let queue = take_weak!(self.queue); fill_optional_fields(&mut request, &*client, &*miner); let id = queue.add_request(request); let result = id.wait_with_timeout(); diff --git a/rpc/src/v1/tests/mocked/eth_signing.rs b/rpc/src/v1/tests/mocked/eth_signing.rs index a2755ce18..5f3e75d35 100644 --- a/rpc/src/v1/tests/mocked/eth_signing.rs +++ b/rpc/src/v1/tests/mocked/eth_signing.rs @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use std::str::FromStr; use std::sync::Arc; use jsonrpc_core::IoHandler; use v1::impls::EthSigningQueueClient; @@ -21,12 +22,16 @@ use v1::traits::EthSigning; use v1::helpers::{ConfirmationsQueue, SigningQueue}; use v1::tests::helpers::TestMinerService; use util::{Address, FixedHash}; +use util::numbers::{Uint, U256}; +use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; +use ethcore::transaction::{Transaction, Action}; struct EthSigningTester { pub queue: Arc, pub client: Arc, pub miner: Arc, + pub accounts: Arc, pub io: IoHandler, } @@ -35,13 +40,15 @@ impl Default for EthSigningTester { let queue = Arc::new(ConfirmationsQueue::default()); let client = Arc::new(TestBlockChainClient::default()); let miner = Arc::new(TestMinerService::default()); + let accounts = Arc::new(AccountProvider::transient_provider()); let io = IoHandler::new(); - io.add_delegate(EthSigningQueueClient::new(&queue, &client, &miner).to_delegate()); + io.add_delegate(EthSigningQueueClient::new(&queue, &client, &miner, &accounts).to_delegate()); EthSigningTester { queue: queue, client: client, miner: miner, + accounts: accounts, io: io, } } @@ -78,5 +85,41 @@ fn should_add_transaction_to_queue() { // then assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); assert_eq!(tester.queue.requests().len(), 1); - +} + +#[test] +fn should_dispatch_transaction_if_account_is_unlocked() { + // given + let tester = eth_signing(); + let acc = tester.accounts.new_account("test").unwrap(); + tester.accounts.unlock_account_permanently(acc, "test".into()).unwrap(); + + let t = Transaction { + nonce: U256::zero(), + gas_price: U256::from(0x9184e72a000u64), + gas: U256::from(0x76c0), + action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()), + value: U256::from(0x9184e72au64), + data: vec![] + }; + let signature = tester.accounts.sign(acc, t.hash()).unwrap(); + let t = t.with_signature(signature); + + // when + let request = r#"{ + "jsonrpc": "2.0", + "method": "eth_sendTransaction", + "params": [{ + "from": ""#.to_owned() + format!("0x{:?}", acc).as_ref() + r#"", + "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567", + "gas": "0x76c0", + "gasPrice": "0x9184e72a000", + "value": "0x9184e72a" + }], + "id": 1 + }"#; + let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#; + + // then + assert_eq!(tester.io.handle_request(&request), Some(response.to_owned())); } From 230c6c889ab34b7f874be852eb64e5055d65bda7 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 22 Jun 2016 21:33:10 +0200 Subject: [PATCH 163/239] Ensure judging the SF trigger by relative branch (#1399) Rather than just the canon chain. --- ethcore/src/client/client.rs | 6 +++--- ethcore/src/client/mod.rs | 16 +++++++++++++--- ethcore/src/miner/miner.rs | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index fa063cd61..693296469 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -230,7 +230,7 @@ impl Client where V: Verifier { let last_hashes = self.build_last_hashes(header.parent_hash.clone()); let db = self.state_db.lock().unwrap().boxed_clone(); - let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, self.dao_rescue_block_gas_limit(), &self.vm_factory); + let enact_result = enact_verified(&block, engine, self.tracedb.tracing_enabled(), db, &parent, last_hashes, self.dao_rescue_block_gas_limit(header.parent_hash.clone()), &self.vm_factory); if let Err(e) = enact_result { warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); @@ -486,7 +486,7 @@ impl BlockChainClient for Client where V: Verifier { last_hashes: last_hashes, gas_used: U256::zero(), gas_limit: U256::max_value(), - dao_rescue_block_gas_limit: self.dao_rescue_block_gas_limit(), + dao_rescue_block_gas_limit: self.dao_rescue_block_gas_limit(view.parent_hash()), }; // that's just a copy of the state. let mut state = self.state(); @@ -808,7 +808,7 @@ impl MiningBlockChainClient for Client where V: Verifier { self.state_db.lock().unwrap().boxed_clone(), &self.chain.block_header(&h).expect("h is best block hash: so it's header must exist: qed"), self.build_last_hashes(h.clone()), - self.dao_rescue_block_gas_limit(), + self.dao_rescue_block_gas_limit(h.clone()), author, gas_floor_target, extra_data, diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index c1bc3203c..589b65e16 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -227,9 +227,19 @@ pub trait BlockChainClient : Sync + Send { /// Get `Some` gas limit of block 1_760_000, or `None` if chain is not yet that long. - fn dao_rescue_block_gas_limit(&self) -> Option { - self.block_header(BlockID::Number(1_760_000)) - .map(|header| HeaderView::new(&header).gas_limit()) + fn dao_rescue_block_gas_limit(&self, chain_hash: H256) -> Option { + if let Some(mut header) = self.block_header(BlockID::Hash(chain_hash)) { + if HeaderView::new(&header).number() < 1_760_000 { + None + } else { + while HeaderView::new(&header).number() != 1_760_000 { + header = self.block_header(BlockID::Hash(HeaderView::new(&header).parent_hash())).expect("chain is complete; parent of chain entry must be in chain; qed"); + } + Some(HeaderView::new(&header).gas_limit()) + } + } else { + None + } } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 41e4b4810..290e94059 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -274,7 +274,7 @@ impl MinerService for Miner { last_hashes: last_hashes, gas_used: U256::zero(), gas_limit: U256::max_value(), - dao_rescue_block_gas_limit: chain.dao_rescue_block_gas_limit(), + dao_rescue_block_gas_limit: chain.dao_rescue_block_gas_limit(header.parent_hash().clone()), }; // that's just a copy of the state. let mut state = block.state().clone(); From 1602906b565aecbebbb3b221255663ad68ffb7d9 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 22 Jun 2016 21:37:29 +0200 Subject: [PATCH 164/239] Shortcut SF condition when canon known --- ethcore/src/client/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 589b65e16..3ed56573a 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -228,6 +228,11 @@ pub trait BlockChainClient : Sync + Send { /// Get `Some` gas limit of block 1_760_000, or `None` if chain is not yet that long. fn dao_rescue_block_gas_limit(&self, chain_hash: H256) -> Option { + // shortcut if the canon chain is already known. + if self.chain_info().best_block_number > 1_761_000 { + return self.block_header(BlockID::Number(1_760_000)).map(|header| HeaderView::new(&header).gas_limit()); + } + // otherwise check according to `chain_hash`. if let Some(mut header) = self.block_header(BlockID::Hash(chain_hash)) { if HeaderView::new(&header).number() < 1_760_000 { None From 8a867262ad41d3381e7ffadb26a17673ac390a87 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 23 Jun 2016 02:42:56 +0200 Subject: [PATCH 165/239] Build fix. --- parity/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/main.rs b/parity/main.rs index 17d941a5d..0b64d0644 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -199,7 +199,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) } // Display warning about using unlock with signer - if conf.args.flag_signer && conf.args.flag_unlock.is_some() { + if !conf.args.flag_signer_off && conf.args.flag_unlock.is_some() { warn!("Using Trusted Signer and --unlock is not recommended!"); warn!("NOTE that Signer will not ask you to confirm transactions from unlocked account."); } From a76e3a134f880e6fd0b43321bdaf579a0fad1ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 23 Jun 2016 10:54:25 +0200 Subject: [PATCH 166/239] Bumping clippy --- Cargo.toml | 2 +- dapps/Cargo.toml | 2 +- db/Cargo.toml | 2 +- ethcore/Cargo.toml | 2 +- hook.sh | 2 +- json/Cargo.toml | 2 +- rpc/Cargo.toml | 2 +- signer/Cargo.toml | 2 +- sync/Cargo.toml | 2 +- util/Cargo.toml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9f4c34c0b..6c4b54d46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ fdlimit = { path = "util/fdlimit" } num_cpus = "0.2" number_prefix = "0.2" rpassword = "0.2.1" -clippy = { version = "0.0.76", optional = true} +clippy = { version = "0.0.77", optional = true} ethcore = { path = "ethcore" } ethcore-util = { path = "util" } ethsync = { path = "sync" } diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index dc45085d5..4cc4bc472 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -28,7 +28,7 @@ parity-dapps-wallet = { git = "https://github.com/ethcore/parity-dapps-wallet-rs parity-dapps-dao = { git = "https://github.com/ethcore/parity-dapps-dao-rs.git", version = "0.4.0", optional = true } parity-dapps-makerotc = { git = "https://github.com/ethcore/parity-dapps-makerotc-rs.git", version = "0.3.0", optional = true } mime_guess = { version = "1.6.1" } -clippy = { version = "0.0.76", optional = true} +clippy = { version = "0.0.77", optional = true} [build-dependencies] serde_codegen = { version = "0.7.0", optional = true } diff --git a/db/Cargo.toml b/db/Cargo.toml index b77840d02..a51bf9ab9 100644 --- a/db/Cargo.toml +++ b/db/Cargo.toml @@ -12,7 +12,7 @@ syntex = "*" ethcore-ipc-codegen = { path = "../ipc/codegen" } [dependencies] -clippy = { version = "0.0.67", optional = true} +clippy = { version = "0.0.77", optional = true} ethcore-devtools = { path = "../devtools" } ethcore-ipc = { path = "../ipc/rpc" } rocksdb = { git = "https://github.com/ethcore/rust-rocksdb" } diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 294ad82c4..515091a16 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -22,7 +22,7 @@ ethcore-util = { path = "../util" } evmjit = { path = "../evmjit", optional = true } ethash = { path = "../ethash" } num_cpus = "0.2" -clippy = { version = "0.0.76", optional = true} +clippy = { version = "0.0.77", optional = true} crossbeam = "0.2.9" lazy_static = "0.2" ethcore-devtools = { path = "../devtools" } diff --git a/hook.sh b/hook.sh index 9ce825f80..1b15aafa8 100755 --- a/hook.sh +++ b/hook.sh @@ -7,6 +7,6 @@ echo "set -e" >> $FILE echo "cargo build --features dev" >> $FILE # Build tests echo "cargo test --no-run --features dev \\" >> $FILE -echo " -p ethkey -p ethstore -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethcore-dapps -p ethcore-signer" >> $FILE +echo " -p ethkey -p ethstore -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethcore-dapps -p ethcore-signer -p ethcore-db" >> $FILE echo "" >> $FILE chmod +x $FILE diff --git a/json/Cargo.toml b/json/Cargo.toml index a2a560c43..e93f493e1 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -10,7 +10,7 @@ rustc-serialize = "0.3" serde = "0.7.0" serde_json = "0.7.0" serde_macros = { version = "0.7.0", optional = true } -clippy = { version = "0.0.76", optional = true} +clippy = { version = "0.0.77", optional = true} [build-dependencies] serde_codegen = { version = "0.7.0", optional = true } diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index b1369c88d..60b8236e1 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -23,7 +23,7 @@ ethcore-devtools = { path = "../devtools" } rustc-serialize = "0.3" transient-hashmap = "0.1" serde_macros = { version = "0.7.0", optional = true } -clippy = { version = "0.0.76", optional = true} +clippy = { version = "0.0.77", optional = true} json-ipc-server = { git = "https://github.com/ethcore/json-ipc-server.git" } [build-dependencies] diff --git a/signer/Cargo.toml b/signer/Cargo.toml index 82160d55a..0cae9b0a5 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -20,7 +20,7 @@ ethcore-util = { path = "../util" } ethcore-rpc = { path = "../rpc" } parity-minimal-sysui = { git = "https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git" } -clippy = { version = "0.0.76", optional = true} +clippy = { version = "0.0.77", optional = true} [features] dev = ["clippy"] diff --git a/sync/Cargo.toml b/sync/Cargo.toml index c77749c39..8bb0d37c9 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -10,7 +10,7 @@ authors = ["Ethcore Date: Thu, 23 Jun 2016 10:16:11 +0100 Subject: [PATCH 167/239] Replace deprecated hashdb trait names (#1394) * replace deprecated hashdb method names * spaces -> tabs --- ethcore/src/account.rs | 6 +- ethcore/src/account_db.rs | 22 ++--- util/src/hashdb.rs | 24 +++-- util/src/journaldb/archivedb.rs | 68 +++++++------- util/src/journaldb/earlymergedb.rs | 130 +++++++++++++------------- util/src/journaldb/overlayrecentdb.rs | 118 +++++++++++------------ util/src/journaldb/refcounteddb.rs | 60 ++++++------ util/src/memorydb.rs | 6 +- util/src/overlaydb.rs | 22 ++--- util/src/trie/triedb.rs | 8 +- util/src/trie/triedbmut.rs | 18 ++-- 11 files changed, 240 insertions(+), 242 deletions(-) diff --git a/ethcore/src/account.rs b/ethcore/src/account.rs index 29922dda5..d0628436d 100644 --- a/ethcore/src/account.rs +++ b/ethcore/src/account.rs @@ -166,16 +166,16 @@ impl Account { !self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == Some(SHA3_EMPTY)) } - /// Provide a database to lookup `code_hash`. Should not be called if it is a contract without code. + /// Provide a database to get `code_hash`. Should not be called if it is a contract without code. pub fn cache_code(&mut self, db: &AccountDB) -> bool { // TODO: fill out self.code_cache; trace!("Account::cache_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty()); self.is_cached() || match self.code_hash { - Some(ref h) => match db.lookup(h) { + Some(ref h) => match db.get(h) { Some(x) => { self.code_cache = x.to_vec(); true }, _ => { - warn!("Failed reverse lookup of {}", h); + warn!("Failed reverse get of {}", h); false }, }, diff --git a/ethcore/src/account_db.rs b/ethcore/src/account_db.rs index c21ea2993..7337940da 100644 --- a/ethcore/src/account_db.rs +++ b/ethcore/src/account_db.rs @@ -30,18 +30,18 @@ impl<'db> HashDB for AccountDB<'db>{ unimplemented!() } - fn lookup(&self, key: &H256) -> Option<&[u8]> { + fn get(&self, key: &H256) -> Option<&[u8]> { if key == &SHA3_NULL_RLP { return Some(&NULL_RLP_STATIC); } - self.db.lookup(&combine_key(&self.address, key)) + self.db.get(&combine_key(&self.address, key)) } - fn exists(&self, key: &H256) -> bool { + fn contains(&self, key: &H256) -> bool { if key == &SHA3_NULL_RLP { return true; } - self.db.exists(&combine_key(&self.address, key)) + self.db.contains(&combine_key(&self.address, key)) } fn insert(&mut self, _value: &[u8]) -> H256 { @@ -52,7 +52,7 @@ impl<'db> HashDB for AccountDB<'db>{ unimplemented!() } - fn kill(&mut self, _key: &H256) { + fn remove(&mut self, _key: &H256) { unimplemented!() } } @@ -82,18 +82,18 @@ impl<'db> HashDB for AccountDBMut<'db>{ unimplemented!() } - fn lookup(&self, key: &H256) -> Option<&[u8]> { + fn get(&self, key: &H256) -> Option<&[u8]> { if key == &SHA3_NULL_RLP { return Some(&NULL_RLP_STATIC); } - self.db.lookup(&combine_key(&self.address, key)) + self.db.get(&combine_key(&self.address, key)) } - fn exists(&self, key: &H256) -> bool { + fn contains(&self, key: &H256) -> bool { if key == &SHA3_NULL_RLP { return true; } - self.db.exists(&combine_key(&self.address, key)) + self.db.contains(&combine_key(&self.address, key)) } fn insert(&mut self, value: &[u8]) -> H256 { @@ -114,12 +114,12 @@ impl<'db> HashDB for AccountDBMut<'db>{ self.db.emplace(key, value.to_vec()) } - fn kill(&mut self, key: &H256) { + fn remove(&mut self, key: &H256) { if key == &SHA3_NULL_RLP { return; } let key = combine_key(&self.address, key); - self.db.kill(&key) + self.db.remove(&key) } } diff --git a/util/src/hashdb.rs b/util/src/hashdb.rs index 0a5f13d52..1ec3069d8 100644 --- a/util/src/hashdb.rs +++ b/util/src/hashdb.rs @@ -20,12 +20,10 @@ use bytes::*; use std::collections::HashMap; /// Trait modelling datastore keyed by a 32-byte Keccak hash. -pub trait HashDB : AsHashDB { +pub trait HashDB: AsHashDB { /// Get the keys in the database together with number of underlying references. fn keys(&self) -> HashMap; - /// Deprecated. use `get`. - fn lookup(&self, key: &H256) -> Option<&[u8]>; // TODO: rename to get. /// Look up a given hash into the bytes that hash to it, returning None if the /// hash is not known. /// @@ -41,10 +39,8 @@ pub trait HashDB : AsHashDB { /// assert_eq!(m.get(&hash).unwrap(), hello_bytes); /// } /// ``` - fn get(&self, key: &H256) -> Option<&[u8]> { self.lookup(key) } + fn get(&self, key: &H256) -> Option<&[u8]>; - /// Deprecated. Use `contains`. - fn exists(&self, key: &H256) -> bool; // TODO: rename to contains. /// Check for the existance of a hash-key. /// /// # Examples @@ -63,10 +59,10 @@ pub trait HashDB : AsHashDB { /// assert!(!m.contains(&key)); /// } /// ``` - fn contains(&self, key: &H256) -> bool { self.exists(key) } + fn contains(&self, key: &H256) -> bool; /// Insert a datum item into the DB and return the datum's hash for a later lookup. Insertions - /// are counted and the equivalent number of `kill()`s must be performed before the data + /// are counted and the equivalent number of `remove()`s must be performed before the data /// is considered dead. /// /// # Examples @@ -86,8 +82,6 @@ pub trait HashDB : AsHashDB { /// Like `insert()` , except you provide the key and the data is all moved. fn emplace(&mut self, key: H256, value: Bytes); - /// Deprecated - use `remove`. - fn kill(&mut self, key: &H256); // TODO: rename to remove. /// Remove a datum previously inserted. Insertions can be "owed" such that the same number of `insert()`s may /// happen without the data being eventually being inserted into the DB. /// @@ -109,7 +103,7 @@ pub trait HashDB : AsHashDB { /// assert_eq!(m.get(key).unwrap(), d); /// } /// ``` - fn remove(&mut self, key: &H256) { self.kill(key) } + fn remove(&mut self, key: &H256); } /// Upcast trait. @@ -121,6 +115,10 @@ pub trait AsHashDB { } impl AsHashDB for T { - fn as_hashdb(&self) -> &HashDB { self } - fn as_hashdb_mut(&mut self) -> &mut HashDB { self } + fn as_hashdb(&self) -> &HashDB { + self + } + fn as_hashdb_mut(&mut self) -> &mut HashDB { + self + } } diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index 0381c08ea..c7f6b92fa 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -98,7 +98,7 @@ impl HashDB for ArchiveDB { ret } - fn lookup(&self, key: &H256) -> Option<&[u8]> { + fn get(&self, key: &H256) -> Option<&[u8]> { let k = self.overlay.raw(key); match k { Some(&(ref d, rc)) if rc > 0 => Some(d), @@ -113,8 +113,8 @@ impl HashDB for ArchiveDB { } } - fn exists(&self, key: &H256) -> bool { - self.lookup(key).is_some() + fn contains(&self, key: &H256) -> bool { + self.get(key).is_some() } fn insert(&mut self, value: &[u8]) -> H256 { @@ -123,8 +123,8 @@ impl HashDB for ArchiveDB { fn emplace(&mut self, key: H256, value: Bytes) { self.overlay.emplace(key, value); } - fn kill(&mut self, key: &H256) { - self.overlay.kill(key); + fn remove(&mut self, key: &H256) { + self.overlay.remove(key); } } @@ -207,7 +207,7 @@ mod tests { jdb.commit(5, &b"1004a".sha3(), Some((3, b"1002a".sha3()))).unwrap(); jdb.commit(6, &b"1005a".sha3(), Some((4, b"1003a".sha3()))).unwrap(); - assert!(jdb.exists(&x)); + assert!(jdb.contains(&x)); } #[test] @@ -216,14 +216,14 @@ mod tests { let mut jdb = ArchiveDB::new_temp(); let h = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.remove(&h); jdb.commit(1, &b"1".sha3(), None).unwrap(); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(2, &b"2".sha3(), None).unwrap(); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(3, &b"3".sha3(), Some((0, b"0".sha3()))).unwrap(); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(4, &b"4".sha3(), Some((1, b"1".sha3()))).unwrap(); } @@ -235,26 +235,26 @@ mod tests { let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); jdb.commit(0, &b"0".sha3(), None).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.remove(&foo); jdb.remove(&bar); let baz = jdb.insert(b"baz"); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); + assert!(jdb.contains(&baz)); let foo = jdb.insert(b"foo"); jdb.remove(&baz); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&baz)); jdb.remove(&foo); jdb.commit(3, &b"3".sha3(), Some((2, b"2".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(4, &b"4".sha3(), Some((3, b"3".sha3()))).unwrap(); } @@ -267,8 +267,8 @@ mod tests { let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); jdb.commit(0, &b"0".sha3(), None).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.remove(&foo); let baz = jdb.insert(b"baz"); @@ -277,12 +277,12 @@ mod tests { jdb.remove(&bar); jdb.commit(1, &b"1b".sha3(), Some((0, b"0".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); + assert!(jdb.contains(&baz)); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); } #[test] @@ -292,16 +292,16 @@ mod tests { let foo = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.remove(&foo); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); jdb.insert(b"foo"); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(3, &b"2".sha3(), Some((0, b"2".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); } #[test] @@ -315,10 +315,10 @@ mod tests { jdb.insert(b"foo"); jdb.commit(1, &b"1b".sha3(), Some((0, b"0".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(2, &b"2a".sha3(), Some((1, b"1a".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); } #[test] @@ -344,8 +344,8 @@ mod tests { { let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); } } @@ -373,7 +373,7 @@ mod tests { let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); jdb.remove(&foo); jdb.commit(3, &b"3".sha3(), Some((2, b"2".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.remove(&foo); jdb.commit(4, &b"4".sha3(), Some((3, b"3".sha3()))).unwrap(); jdb.commit(5, &b"5".sha3(), Some((4, b"4".sha3()))).unwrap(); @@ -402,7 +402,7 @@ mod tests { { let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); } } diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs index e495b9d03..71959fa35 100644 --- a/util/src/journaldb/earlymergedb.rs +++ b/util/src/journaldb/earlymergedb.rs @@ -172,8 +172,8 @@ impl EarlyMergeDB { trace!(target: "jdb.fine", "replay_keys: (end) refs={:?}", refs); } - fn kill_keys(deletes: &[H256], refs: &mut HashMap, batch: &DBTransaction, from: RemoveFrom, trace: bool) { - // with a kill on {queue_refs: 1, in_archive: true}, we have two options: + fn remove_keys(deletes: &[H256], refs: &mut HashMap, batch: &DBTransaction, from: RemoveFrom, trace: bool) { + // with a remove on {queue_refs: 1, in_archive: true}, we have two options: // - convert to {queue_refs: 1, in_archive: false} (i.e. remove it from the conceptual archive) // - convert to {queue_refs: 0, in_archive: true} (i.e. remove it from the conceptual queue) // (the latter option would then mean removing the RefInfo, since it would no longer be counted in the queue.) @@ -186,13 +186,13 @@ impl EarlyMergeDB { c.in_archive = false; Self::reset_already_in(batch, h); if trace { - trace!(target: "jdb.fine", " kill({}): In archive, 1 in queue: Reducing to queue only and recording", h); + trace!(target: "jdb.fine", " remove({}): In archive, 1 in queue: Reducing to queue only and recording", h); } continue; } else if c.queue_refs > 1 { c.queue_refs -= 1; if trace { - trace!(target: "jdb.fine", " kill({}): In queue > 1 refs: Decrementing ref count to {}", h, c.queue_refs); + trace!(target: "jdb.fine", " remove({}): In queue > 1 refs: Decrementing ref count to {}", h, c.queue_refs); } continue; } else { @@ -204,14 +204,14 @@ impl EarlyMergeDB { refs.remove(h); Self::reset_already_in(batch, h); if trace { - trace!(target: "jdb.fine", " kill({}): In archive, 1 in queue: Removing from queue and leaving in archive", h); + trace!(target: "jdb.fine", " remove({}): In archive, 1 in queue: Removing from queue and leaving in archive", h); } } Some(RefInfo{queue_refs: 1, in_archive: false}) => { refs.remove(h); batch.delete(&h.bytes()).expect("Low-level database error. Some issue with your hard disk?"); if trace { - trace!(target: "jdb.fine", " kill({}): Not in archive, only 1 ref in queue: Removing from queue and DB", h); + trace!(target: "jdb.fine", " remove({}): Not in archive, only 1 ref in queue: Removing from queue and DB", h); } } None => { @@ -219,7 +219,7 @@ impl EarlyMergeDB { //assert!(!Self::is_already_in(db, &h)); batch.delete(&h.bytes()).expect("Low-level database error. Some issue with your hard disk?"); if trace { - trace!(target: "jdb.fine", " kill({}): Not in queue - MUST BE IN ARCHIVE: Removing from DB", h); + trace!(target: "jdb.fine", " remove({}): Not in queue - MUST BE IN ARCHIVE: Removing from DB", h); } } _ => panic!("Invalid value in refs: {:?}", n), @@ -290,7 +290,7 @@ impl HashDB for EarlyMergeDB { ret } - fn lookup(&self, key: &H256) -> Option<&[u8]> { + fn get(&self, key: &H256) -> Option<&[u8]> { let k = self.overlay.raw(key); match k { Some(&(ref d, rc)) if rc > 0 => Some(d), @@ -305,8 +305,8 @@ impl HashDB for EarlyMergeDB { } } - fn exists(&self, key: &H256) -> bool { - self.lookup(key).is_some() + fn contains(&self, key: &H256) -> bool { + self.get(key).is_some() } fn insert(&mut self, value: &[u8]) -> H256 { @@ -315,8 +315,8 @@ impl HashDB for EarlyMergeDB { fn emplace(&mut self, key: H256, value: Bytes) { self.overlay.emplace(key, value); } - fn kill(&mut self, key: &H256) { - self.overlay.kill(key); + fn remove(&mut self, key: &H256) { + self.overlay.remove(key); } } @@ -472,7 +472,7 @@ impl JournalDB for EarlyMergeDB { if trace { trace!(target: "jdb.ops", " Expunging: {:?}", deletes); } - Self::kill_keys(&deletes, &mut refs, &batch, RemoveFrom::Archive, trace); + Self::remove_keys(&deletes, &mut refs, &batch, RemoveFrom::Archive, trace); if trace { trace!(target: "jdb.ops", " Finalising: {:?}", inserts); @@ -504,7 +504,7 @@ impl JournalDB for EarlyMergeDB { if trace { trace!(target: "jdb.ops", " Reverting: {:?}", inserts); } - Self::kill_keys(&inserts, &mut refs, &batch, RemoveFrom::Queue, trace); + Self::remove_keys(&inserts, &mut refs, &batch, RemoveFrom::Queue, trace); } try!(batch.delete(&last)); @@ -565,7 +565,7 @@ mod tests { jdb.commit(6, &b"1005a".sha3(), Some((4, b"1003a".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&x)); + assert!(jdb.contains(&x)); } #[test] @@ -584,8 +584,8 @@ mod tests { assert!(jdb.can_reconstruct_refs()); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); } #[test] @@ -595,20 +595,20 @@ mod tests { let h = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.remove(&h); jdb.commit(1, &b"1".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(2, &b"2".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(3, &b"3".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(4, &b"4".sha3(), Some((1, b"1".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(!jdb.exists(&h)); + assert!(!jdb.contains(&h)); } #[test] @@ -620,38 +620,38 @@ mod tests { let bar = jdb.insert(b"bar"); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.remove(&foo); jdb.remove(&bar); let baz = jdb.insert(b"baz"); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); + assert!(jdb.contains(&baz)); let foo = jdb.insert(b"foo"); jdb.remove(&baz); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&bar)); + assert!(jdb.contains(&baz)); jdb.remove(&foo); jdb.commit(3, &b"3".sha3(), Some((2, b"2".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&bar)); - assert!(!jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&bar)); + assert!(!jdb.contains(&baz)); jdb.commit(4, &b"4".sha3(), Some((3, b"3".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(!jdb.exists(&foo)); - assert!(!jdb.exists(&bar)); - assert!(!jdb.exists(&baz)); + assert!(!jdb.contains(&foo)); + assert!(!jdb.contains(&bar)); + assert!(!jdb.contains(&baz)); } #[test] @@ -663,8 +663,8 @@ mod tests { let bar = jdb.insert(b"bar"); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.remove(&foo); let baz = jdb.insert(b"baz"); @@ -675,15 +675,15 @@ mod tests { jdb.commit(1, &b"1b".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); + assert!(jdb.contains(&baz)); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&baz)); - assert!(!jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&baz)); + assert!(!jdb.contains(&bar)); } #[test] @@ -694,19 +694,19 @@ mod tests { let foo = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.remove(&foo); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(b"foo"); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(3, &b"2".sha3(), Some((0, b"2".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); } #[test] @@ -730,11 +730,11 @@ mod tests { jdb.commit(1, &b"1c".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(2, &b"2a".sha3(), Some((1, b"1a".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); } #[test] @@ -758,11 +758,11 @@ mod tests { jdb.commit(1, &b"1c".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); } #[test] @@ -826,11 +826,11 @@ mod tests { { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(!jdb.exists(&foo)); + assert!(!jdb.contains(&foo)); } } @@ -933,7 +933,7 @@ mod tests { jdb.insert(b"foo"); jdb.commit(3, &b"3".sha3(), Some((2, b"2".sha3()))).unwrap(); // BROKEN assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.remove(&foo); jdb.commit(4, &b"4".sha3(), Some((3, b"3".sha3()))).unwrap(); @@ -941,7 +941,7 @@ mod tests { jdb.commit(5, &b"5".sha3(), Some((4, b"4".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(!jdb.exists(&foo)); + assert!(!jdb.contains(&foo)); } #[test] @@ -1002,12 +1002,12 @@ mod tests { jdb.remove(&foo); jdb.commit(2, &b"2".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.insert(b"foo"); jdb.commit(3, &b"3".sha3(), Some((1, b"1".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); // incantation to reopen the db }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); @@ -1015,21 +1015,21 @@ mod tests { jdb.remove(&foo); jdb.commit(4, &b"4".sha3(), Some((2, b"2".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); // incantation to reopen the db }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.commit(5, &b"5".sha3(), Some((3, b"3".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); // incantation to reopen the db }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.commit(6, &b"6".sha3(), Some((4, b"4".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(!jdb.exists(&foo)); + assert!(!jdb.contains(&foo)); } } @@ -1059,9 +1059,9 @@ mod tests { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&baz)); - assert!(!jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&baz)); + assert!(!jdb.contains(&bar)); } } } diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs index 709a8fe5f..158b771fb 100644 --- a/util/src/journaldb/overlayrecentdb.rs +++ b/util/src/journaldb/overlayrecentdb.rs @@ -288,11 +288,11 @@ impl JournalDB for OverlayRecentDB { } // update the overlay for k in overlay_deletions { - journal_overlay.backing_overlay.kill(&k); + journal_overlay.backing_overlay.remove(&k); } // apply canon deletions for k in canon_deletions { - if !journal_overlay.backing_overlay.exists(&k) { + if !journal_overlay.backing_overlay.contains(&k) { try!(batch.delete(&k)); } } @@ -321,12 +321,12 @@ impl HashDB for OverlayRecentDB { ret } - fn lookup(&self, key: &H256) -> Option<&[u8]> { + fn get(&self, key: &H256) -> Option<&[u8]> { let k = self.transaction_overlay.raw(key); match k { Some(&(ref d, rc)) if rc > 0 => Some(d), _ => { - let v = self.journal_overlay.read().unwrap().backing_overlay.lookup(key).map(|v| v.to_vec()); + let v = self.journal_overlay.read().unwrap().backing_overlay.get(key).map(|v| v.to_vec()); match v { Some(x) => { Some(&self.transaction_overlay.denote(key, x).0) @@ -344,8 +344,8 @@ impl HashDB for OverlayRecentDB { } } - fn exists(&self, key: &H256) -> bool { - self.lookup(key).is_some() + fn contains(&self, key: &H256) -> bool { + self.get(key).is_some() } fn insert(&mut self, value: &[u8]) -> H256 { @@ -354,8 +354,8 @@ impl HashDB for OverlayRecentDB { fn emplace(&mut self, key: H256, value: Bytes) { self.transaction_overlay.emplace(key, value); } - fn kill(&mut self, key: &H256) { - self.transaction_overlay.kill(key); + fn remove(&mut self, key: &H256) { + self.transaction_overlay.remove(key); } } @@ -397,7 +397,7 @@ mod tests { jdb.commit(6, &b"1005a".sha3(), Some((4, b"1003a".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&x)); + assert!(jdb.contains(&x)); } #[test] @@ -407,20 +407,20 @@ mod tests { let h = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.remove(&h); jdb.commit(1, &b"1".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(2, &b"2".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(3, &b"3".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(4, &b"4".sha3(), Some((1, b"1".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(!jdb.exists(&h)); + assert!(!jdb.contains(&h)); } #[test] @@ -432,38 +432,38 @@ mod tests { let bar = jdb.insert(b"bar"); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.remove(&foo); jdb.remove(&bar); let baz = jdb.insert(b"baz"); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); + assert!(jdb.contains(&baz)); let foo = jdb.insert(b"foo"); jdb.remove(&baz); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&bar)); + assert!(jdb.contains(&baz)); jdb.remove(&foo); jdb.commit(3, &b"3".sha3(), Some((2, b"2".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&bar)); - assert!(!jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&bar)); + assert!(!jdb.contains(&baz)); jdb.commit(4, &b"4".sha3(), Some((3, b"3".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(!jdb.exists(&foo)); - assert!(!jdb.exists(&bar)); - assert!(!jdb.exists(&baz)); + assert!(!jdb.contains(&foo)); + assert!(!jdb.contains(&bar)); + assert!(!jdb.contains(&baz)); } #[test] @@ -475,8 +475,8 @@ mod tests { let bar = jdb.insert(b"bar"); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.remove(&foo); let baz = jdb.insert(b"baz"); @@ -487,15 +487,15 @@ mod tests { jdb.commit(1, &b"1b".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); + assert!(jdb.contains(&baz)); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&baz)); - assert!(!jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&baz)); + assert!(!jdb.contains(&bar)); } #[test] @@ -506,19 +506,19 @@ mod tests { let foo = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.remove(&foo); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); jdb.insert(b"foo"); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(3, &b"2".sha3(), Some((0, b"2".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); } #[test] @@ -542,11 +542,11 @@ mod tests { jdb.commit(1, &b"1c".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(2, &b"2a".sha3(), Some((1, b"1a".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); } #[test] @@ -570,11 +570,11 @@ mod tests { jdb.commit(1, &b"1c".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); } #[test] @@ -638,11 +638,11 @@ mod tests { { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(!jdb.exists(&foo)); + assert!(!jdb.contains(&foo)); } } @@ -745,7 +745,7 @@ mod tests { jdb.insert(b"foo"); jdb.commit(3, &b"3".sha3(), Some((2, b"2".sha3()))).unwrap(); // BROKEN assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.remove(&foo); jdb.commit(4, &b"4".sha3(), Some((3, b"3".sha3()))).unwrap(); @@ -753,7 +753,7 @@ mod tests { jdb.commit(5, &b"5".sha3(), Some((4, b"4".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(!jdb.exists(&foo)); + assert!(!jdb.contains(&foo)); } #[test] @@ -814,12 +814,12 @@ mod tests { jdb.remove(&foo); jdb.commit(2, &b"2".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); jdb.insert(b"foo"); jdb.commit(3, &b"3".sha3(), Some((1, b"1".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); // incantation to reopen the db }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); @@ -827,21 +827,21 @@ mod tests { jdb.remove(&foo); jdb.commit(4, &b"4".sha3(), Some((2, b"2".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); // incantation to reopen the db }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.commit(5, &b"5".sha3(), Some((3, b"3".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); + assert!(jdb.contains(&foo)); // incantation to reopen the db }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.commit(6, &b"6".sha3(), Some((4, b"4".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(!jdb.exists(&foo)); + assert!(!jdb.contains(&foo)); } } @@ -871,9 +871,9 @@ mod tests { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&baz)); - assert!(!jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&baz)); + assert!(!jdb.contains(&bar)); } } @@ -893,7 +893,7 @@ mod tests { assert!(jdb.can_reconstruct_refs()); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); } } diff --git a/util/src/journaldb/refcounteddb.rs b/util/src/journaldb/refcounteddb.rs index 31f31f654..fc7da1541 100644 --- a/util/src/journaldb/refcounteddb.rs +++ b/util/src/journaldb/refcounteddb.rs @@ -88,11 +88,11 @@ impl RefCountedDB { impl HashDB for RefCountedDB { fn keys(&self) -> HashMap { self.forward.keys() } - fn lookup(&self, key: &H256) -> Option<&[u8]> { self.forward.lookup(key) } - fn exists(&self, key: &H256) -> bool { self.forward.exists(key) } + fn get(&self, key: &H256) -> Option<&[u8]> { self.forward.get(key) } + fn contains(&self, key: &H256) -> bool { self.forward.contains(key) } fn insert(&mut self, value: &[u8]) -> H256 { let r = self.forward.insert(value); self.inserts.push(r.clone()); r } fn emplace(&mut self, key: H256, value: Bytes) { self.inserts.push(key.clone()); self.forward.emplace(key, value); } - fn kill(&mut self, key: &H256) { self.removes.push(key.clone()); } + fn remove(&mut self, key: &H256) { self.removes.push(key.clone()); } } impl JournalDB for RefCountedDB { @@ -212,16 +212,16 @@ mod tests { let mut jdb = RefCountedDB::new_temp(); let h = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.remove(&h); jdb.commit(1, &b"1".sha3(), None).unwrap(); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(2, &b"2".sha3(), None).unwrap(); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(3, &b"3".sha3(), Some((0, b"0".sha3()))).unwrap(); - assert!(jdb.exists(&h)); + assert!(jdb.contains(&h)); jdb.commit(4, &b"4".sha3(), Some((1, b"1".sha3()))).unwrap(); - assert!(!jdb.exists(&h)); + assert!(!jdb.contains(&h)); } #[test] @@ -251,34 +251,34 @@ mod tests { let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); jdb.commit(0, &b"0".sha3(), None).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.remove(&foo); jdb.remove(&bar); let baz = jdb.insert(b"baz"); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); + assert!(jdb.contains(&baz)); let foo = jdb.insert(b"foo"); jdb.remove(&baz); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&bar)); + assert!(jdb.contains(&baz)); jdb.remove(&foo); jdb.commit(3, &b"3".sha3(), Some((2, b"2".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&bar)); - assert!(!jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&bar)); + assert!(!jdb.contains(&baz)); jdb.commit(4, &b"4".sha3(), Some((3, b"3".sha3()))).unwrap(); - assert!(!jdb.exists(&foo)); - assert!(!jdb.exists(&bar)); - assert!(!jdb.exists(&baz)); + assert!(!jdb.contains(&foo)); + assert!(!jdb.contains(&bar)); + assert!(!jdb.contains(&baz)); } #[test] @@ -289,8 +289,8 @@ mod tests { let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); jdb.commit(0, &b"0".sha3(), None).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); jdb.remove(&foo); let baz = jdb.insert(b"baz"); @@ -299,13 +299,13 @@ mod tests { jdb.remove(&bar); jdb.commit(1, &b"1b".sha3(), Some((0, b"0".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); - assert!(jdb.exists(&bar)); - assert!(jdb.exists(&baz)); + assert!(jdb.contains(&foo)); + assert!(jdb.contains(&bar)); + assert!(jdb.contains(&baz)); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); - assert!(jdb.exists(&foo)); - assert!(!jdb.exists(&baz)); - assert!(!jdb.exists(&bar)); + assert!(jdb.contains(&foo)); + assert!(!jdb.contains(&baz)); + assert!(!jdb.contains(&bar)); } } diff --git a/util/src/memorydb.rs b/util/src/memorydb.rs index cfd7237e6..ea77f4aa2 100644 --- a/util/src/memorydb.rs +++ b/util/src/memorydb.rs @@ -162,7 +162,7 @@ impl MemoryDB { static NULL_RLP_STATIC: [u8; 1] = [0x80; 1]; impl HashDB for MemoryDB { - fn lookup(&self, key: &H256) -> Option<&[u8]> { + fn get(&self, key: &H256) -> Option<&[u8]> { if key == &SHA3_NULL_RLP { return Some(&NULL_RLP_STATIC); } @@ -176,7 +176,7 @@ impl HashDB for MemoryDB { self.data.iter().filter_map(|(k, v)| if v.1 != 0 {Some((k.clone(), v.1))} else {None}).collect() } - fn exists(&self, key: &H256) -> bool { + fn contains(&self, key: &H256) -> bool { if key == &SHA3_NULL_RLP { return true; } @@ -222,7 +222,7 @@ impl HashDB for MemoryDB { self.data.insert(key, (value, 1)); } - fn kill(&mut self, key: &H256) { + fn remove(&mut self, key: &H256) { if key == &SHA3_NULL_RLP { return; } diff --git a/util/src/overlaydb.rs b/util/src/overlaydb.rs index ce4e894c8..b1ea44dac 100644 --- a/util/src/overlaydb.rs +++ b/util/src/overlaydb.rs @@ -92,7 +92,7 @@ impl OverlayDB { /// /// Returns either an error or the number of items changed in the backing database. /// - /// Will return an error if the number of `kill()`s ever exceeds the number of + /// Will return an error if the number of `remove()`s ever exceeds the number of /// `insert()`s for any key. This will leave the database in an undeterminate /// state. Don't ever let it happen. /// @@ -104,15 +104,15 @@ impl OverlayDB { /// fn main() { /// let mut m = OverlayDB::new_temp(); /// let key = m.insert(b"foo"); // insert item. - /// assert!(m.exists(&key)); // key exists (in memory). + /// assert!(m.contains(&key)); // key exists (in memory). /// assert_eq!(m.commit().unwrap(), 1); // 1 item changed. - /// assert!(m.exists(&key)); // key still exists (in backing). - /// m.kill(&key); // delete item. - /// assert!(!m.exists(&key)); // key "doesn't exist" (though still does in backing). - /// m.kill(&key); // oh dear... more kills than inserts for the key... + /// assert!(m.contains(&key)); // key still exists (in backing). + /// m.remove(&key); // delete item. + /// assert!(!m.contains(&key)); // key "doesn't exist" (though still does in backing). + /// m.remove(&key); // oh dear... more removes than inserts for the key... /// //m.commit().unwrap(); // this commit/unwrap would cause a panic. - /// m.revert(); // revert both kills. - /// assert!(m.exists(&key)); // key now still exists. + /// m.revert(); // revert both removes. + /// assert!(m.contains(&key)); // key now still exists. /// } /// ``` pub fn commit(&mut self) -> Result { @@ -224,7 +224,7 @@ impl HashDB for OverlayDB { } ret } - fn lookup(&self, key: &H256) -> Option<&[u8]> { + fn get(&self, key: &H256) -> Option<&[u8]> { // return ok if positive; if negative, check backing - might be enough references there to make // it positive again. let k = self.overlay.raw(key); @@ -249,7 +249,7 @@ impl HashDB for OverlayDB { } } } - fn exists(&self, key: &H256) -> bool { + fn contains(&self, key: &H256) -> bool { // return ok if positive; if negative, check backing - might be enough references there to make // it positive again. let k = self.overlay.raw(key); @@ -271,7 +271,7 @@ impl HashDB for OverlayDB { } fn insert(&mut self, value: &[u8]) -> H256 { self.overlay.insert(value) } fn emplace(&mut self, key: H256, value: Bytes) { self.overlay.emplace(key, value); } - fn kill(&mut self, key: &H256) { self.overlay.kill(key); } + fn remove(&mut self, key: &H256) { self.overlay.remove(key); } } #[test] diff --git a/util/src/trie/triedb.rs b/util/src/trie/triedb.rs index fccd5da90..9cd3a8c41 100644 --- a/util/src/trie/triedb.rs +++ b/util/src/trie/triedb.rs @@ -133,7 +133,7 @@ impl<'db> TrieDB<'db> { /// Get the data of the root node. fn root_data(&self) -> &[u8] { - self.db.lookup(&self.root).expect("Trie root not found!") + self.db.get(&self.root).expect("Trie root not found!") } /// Get the root node as a `Node`. @@ -184,7 +184,7 @@ impl<'db> TrieDB<'db> { /// Return optional data for a key given as a `NibbleSlice`. Returns `None` if no data exists. fn do_lookup<'a, 'key>(&'a self, key: &NibbleSlice<'key>) -> Option<&'a [u8]> where 'a: 'key { - let root_rlp = self.db.lookup(&self.root).expect("Trie root not found!"); + let root_rlp = self.db.get(&self.root).expect("Trie root not found!"); self.get_from_node(&root_rlp, key) } @@ -213,7 +213,7 @@ impl<'db> TrieDB<'db> { // check if its sha3 + len let r = Rlp::new(node); match r.is_data() && r.size() == 32 { - true => self.db.lookup(&r.as_val::()).unwrap_or_else(|| panic!("Not found! {:?}", r.as_val::())), + true => self.db.get(&r.as_val::()).unwrap_or_else(|| panic!("Not found! {:?}", r.as_val::())), false => node } } @@ -349,7 +349,7 @@ impl<'db> Trie for TrieDB<'db> { impl<'db> fmt::Debug for TrieDB<'db> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(writeln!(f, "c={:?} [", self.hash_count)); - let root_rlp = self.db.lookup(&self.root).expect("Trie root not found!"); + let root_rlp = self.db.get(&self.root).expect("Trie root not found!"); try!(self.fmt_all(Node::decoded(root_rlp), f, 0)); writeln!(f, "]") } diff --git a/util/src/trie/triedbmut.rs b/util/src/trie/triedbmut.rs index afabd6437..65d5bbd2b 100644 --- a/util/src/trie/triedbmut.rs +++ b/util/src/trie/triedbmut.rs @@ -87,7 +87,7 @@ impl<'db> TrieDBMut<'db> { /// Create a new trie with the backing database `db` and `root`. /// Returns an error if `root` does not exist. pub fn from_existing(db: &'db mut HashDB, root: &'db mut H256) -> Result { - if !db.exists(root) { + if !db.contains(root) { Err(TrieError::InvalidStateRoot) } else { Ok(TrieDBMut { @@ -143,7 +143,7 @@ impl<'db> TrieDBMut<'db> { /// Set the trie to a new root node's RLP, inserting the new RLP into the backing database /// and removing the old. fn set_root_rlp(&mut self, root_data: &[u8]) { - self.db.kill(&self.root); + self.db.remove(&self.root); *self.root = self.db.insert(root_data); self.hash_count += 1; trace!("set_root_rlp {:?} {:?}", root_data.pretty(), self.root); @@ -174,7 +174,7 @@ impl<'db> TrieDBMut<'db> { /// Get the root node's RLP. fn root_node(&self) -> Node { - Node::decoded(self.db.lookup(&self.root).expect("Trie root not found!")) + Node::decoded(self.db.get(&self.root).expect("Trie root not found!")) } /// Get the root node as a `Node`. @@ -225,7 +225,7 @@ impl<'db> TrieDBMut<'db> { /// Return optional data for a key given as a `NibbleSlice`. Returns `None` if no data exists. fn do_lookup<'a, 'key>(&'a self, key: &NibbleSlice<'key>) -> Option<&'a [u8]> where 'a: 'key { - let root_rlp = self.db.lookup(&self.root).expect("Trie root not found!"); + let root_rlp = self.db.get(&self.root).expect("Trie root not found!"); self.get_from_node(&root_rlp, key) } @@ -254,7 +254,7 @@ impl<'db> TrieDBMut<'db> { // check if its sha3 + len let r = Rlp::new(node); match r.is_data() && r.size() == 32 { - true => self.db.lookup(&r.as_val::()).expect("Not found!"), + true => self.db.get(&r.as_val::()).expect("Not found!"), false => node } } @@ -266,7 +266,7 @@ impl<'db> TrieDBMut<'db> { trace!("ADD: {:?} {:?}", key, value.pretty()); // determine what the new root is, insert new nodes and remove old as necessary. let mut todo: Journal = Journal::new(); - let root_rlp = self.augmented(self.db.lookup(&self.root).expect("Trie root not found!"), key, value, &mut todo); + let root_rlp = self.augmented(self.db.get(&self.root).expect("Trie root not found!"), key, value, &mut todo); self.apply(todo); self.set_root_rlp(&root_rlp); trace!("/"); @@ -279,7 +279,7 @@ impl<'db> TrieDBMut<'db> { trace!("DELETE: {:?}", key); // determine what the new root is, insert new nodes and remove old as necessary. let mut todo: Journal = Journal::new(); - match self.cleared_from_slice(self.db.lookup(&self.root).expect("Trie root not found!"), key, &mut todo) { + match self.cleared_from_slice(self.db.get(&self.root).expect("Trie root not found!"), key, &mut todo) { Some(root_rlp) => { self.apply(todo); self.set_root_rlp(&root_rlp); @@ -335,7 +335,7 @@ impl<'db> TrieDBMut<'db> { } else if rlp.is_data() && rlp.size() == 32 { let h = rlp.as_val(); - let r = self.db.lookup(&h).unwrap_or_else(||{ + let r = self.db.get(&h).unwrap_or_else(||{ println!("Node not found! rlp={:?}, node_hash={:?}", rlp.as_raw().pretty(), h); println!("Journal: {:?}", journal); panic!(); @@ -670,7 +670,7 @@ impl<'db> TrieMut for TrieDBMut<'db> { impl<'db> fmt::Debug for TrieDBMut<'db> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(writeln!(f, "c={:?} [", self.hash_count)); - let root_rlp = self.db.lookup(&self.root).expect("Trie root not found!"); + let root_rlp = self.db.get(&self.root).expect("Trie root not found!"); try!(self.fmt_all(Node::decoded(root_rlp), f, 0)); writeln!(f, "]") } From 129ce97ad57f21021873ea2e8651724d997cba1f Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 23 Jun 2016 11:30:48 +0200 Subject: [PATCH 168/239] Constants for SF# and update. --- ethcore/src/block.rs | 3 ++- ethcore/src/client/mod.rs | 12 ++++++------ ethcore/src/env_info.rs | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index ff05b5af1..f7288c85b 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -288,6 +288,7 @@ impl<'x> OpenBlock<'x> { /// Get the environment info concerning this block. pub fn env_info(&self) -> EnvInfo { // TODO: memoise. + const SOFT_FORK_BLOCK: u64 = 1775000; EnvInfo { number: self.block.base.header.number, author: self.block.base.header.author.clone(), @@ -296,7 +297,7 @@ impl<'x> OpenBlock<'x> { last_hashes: self.last_hashes.clone(), // TODO: should be a reference. gas_used: self.block.receipts.last().map_or(U256::zero(), |r| r.gas_used), gas_limit: self.block.base.header.gas_limit.clone(), - dao_rescue_block_gas_limit: if self.block.base.header.number == 1760000 { Some(self.block.base.header.gas_limit) } else { self.dao_rescue_block_gas_limit }, + dao_rescue_block_gas_limit: if self.block.base.header.number == SOFT_FORK_BLOCK { Some(self.block.base.header.gas_limit) } else { self.dao_rescue_block_gas_limit }, } } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 3ed56573a..86686cb4c 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -225,19 +225,19 @@ pub trait BlockChainClient : Sync + Send { } } - - /// Get `Some` gas limit of block 1_760_000, or `None` if chain is not yet that long. + /// Get `Some` gas limit of SOFT_FORK_BLOCK, or `None` if chain is not yet that long. fn dao_rescue_block_gas_limit(&self, chain_hash: H256) -> Option { + const SOFT_FORK_BLOCK: u64 = 1775000; // shortcut if the canon chain is already known. - if self.chain_info().best_block_number > 1_761_000 { - return self.block_header(BlockID::Number(1_760_000)).map(|header| HeaderView::new(&header).gas_limit()); + if self.chain_info().best_block_number > SOFT_FORK_BLOCK + 1000 { + return self.block_header(BlockID::Number(SOFT_FORK_BLOCK)).map(|header| HeaderView::new(&header).gas_limit()); } // otherwise check according to `chain_hash`. if let Some(mut header) = self.block_header(BlockID::Hash(chain_hash)) { - if HeaderView::new(&header).number() < 1_760_000 { + if HeaderView::new(&header).number() < SOFT_FORK_BLOCK { None } else { - while HeaderView::new(&header).number() != 1_760_000 { + while HeaderView::new(&header).number() != SOFT_FORK_BLOCK { header = self.block_header(BlockID::Hash(HeaderView::new(&header).parent_hash())).expect("chain is complete; parent of chain entry must be in chain; qed"); } Some(HeaderView::new(&header).gas_limit()) diff --git a/ethcore/src/env_info.rs b/ethcore/src/env_info.rs index a38a31ff7..8304fcc03 100644 --- a/ethcore/src/env_info.rs +++ b/ethcore/src/env_info.rs @@ -40,7 +40,7 @@ pub struct EnvInfo { /// The gas used. pub gas_used: U256, - /// Block gas limit at DAO rescue block #1760000 or None if not yet there. + /// Block gas limit at DAO rescue block SOFT_FORK_BLOCK or None if not yet there. pub dao_rescue_block_gas_limit: Option, } From 5bf906625bb584d9c213097b6fd19bd5d8809d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 23 Jun 2016 12:04:54 +0200 Subject: [PATCH 169/239] Fixing warnings --- Cargo.lock | 20 ++++++++++---------- ethcore/src/block.rs | 3 +++ ethcore/src/error.rs | 6 +++--- ethcore/src/ethereum/ethash.rs | 2 +- hook.sh | 2 +- parity/main.rs | 2 +- sync/src/chain.rs | 2 +- util/src/network/host.rs | 1 + 8 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc37f0431..f735f0e54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,7 +3,7 @@ name = "parity" version = "1.2.0" dependencies = [ "ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 1.1.1 (git+https://github.com/ethcore/rust-ctrlc.git)", "daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", @@ -129,15 +129,15 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.76" +version = "0.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clippy_lints 0.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy_lints 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clippy_lints" -version = "0.0.76" +version = "0.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -250,7 +250,7 @@ name = "ethcore" version = "1.2.0" dependencies = [ "bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.2.0", @@ -275,7 +275,7 @@ dependencies = [ name = "ethcore-dapps" version = "1.2.0" dependencies = [ - "clippy 0.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-rpc 1.2.0", "ethcore-util 1.2.0", "hyper 0.9.3 (git+https://github.com/ethcore/hyper)", @@ -337,7 +337,7 @@ dependencies = [ name = "ethcore-rpc" version = "1.2.0" dependencies = [ - "clippy 0.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.2.0", "ethcore 1.2.0", "ethcore-devtools 1.2.0", @@ -360,7 +360,7 @@ dependencies = [ name = "ethcore-signer" version = "1.2.0" dependencies = [ - "clippy 0.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-rpc 1.2.0", "ethcore-util 1.2.0", @@ -379,7 +379,7 @@ dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "bigint 0.1.0", "chrono 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -451,7 +451,7 @@ dependencies = [ name = "ethsync" version = "1.2.0" dependencies = [ - "clippy 0.0.76 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.2.0", "ethcore-util 1.2.0", diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index ff05b5af1..a5f1d6df9 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -489,6 +489,7 @@ pub fn enact( } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header +#[cfg_attr(feature="dev", allow(too_many_arguments))] pub fn enact_bytes( block_bytes: &[u8], engine: &Engine, @@ -505,6 +506,7 @@ pub fn enact_bytes( } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header +#[cfg_attr(feature="dev", allow(too_many_arguments))] pub fn enact_verified( block: &PreverifiedBlock, engine: &Engine, @@ -520,6 +522,7 @@ pub fn enact_verified( } /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards +#[cfg_attr(feature="dev", allow(too_many_arguments))] pub fn enact_and_seal( block_bytes: &[u8], engine: &Engine, diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 9be800e13..92d3cbe6b 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -228,7 +228,7 @@ pub enum Error { /// The value of the nonce or mishash is invalid. PowInvalid, /// Error concerning TrieDBs - TrieError(TrieError), + Trie(TrieError), } impl fmt::Display for Error { @@ -244,7 +244,7 @@ impl fmt::Display for Error { f.write_fmt(format_args!("Unknown engine name ({})", name)), Error::PowHashInvalid => f.write_str("Invalid or out of date PoW hash."), Error::PowInvalid => f.write_str("Invalid nonce or mishash"), - Error::TrieError(ref err) => f.write_fmt(format_args!("{}", err)), + Error::Trie(ref err) => f.write_fmt(format_args!("{}", err)), } } } @@ -308,7 +308,7 @@ impl From for Error { impl From for Error { fn from(err: TrieError) -> Error { - Error::TrieError(err) + Error::Trie(err) } } diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 0e90e3867..700458934 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -106,7 +106,7 @@ impl Engine for Ethash { } else { let mut s = Schedule::new_homestead(); if self.ethash_params.dao_rescue_soft_fork { - s.reject_dao_transactions = env_info.dao_rescue_block_gas_limit.map(|x| x <= 4_000_000.into()).unwrap_or(false); + s.reject_dao_transactions = env_info.dao_rescue_block_gas_limit.map_or(false, |x| x <= 4_000_000.into()); } s } diff --git a/hook.sh b/hook.sh index 1b15aafa8..9ce825f80 100755 --- a/hook.sh +++ b/hook.sh @@ -7,6 +7,6 @@ echo "set -e" >> $FILE echo "cargo build --features dev" >> $FILE # Build tests echo "cargo test --no-run --features dev \\" >> $FILE -echo " -p ethkey -p ethstore -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethcore-dapps -p ethcore-signer -p ethcore-db" >> $FILE +echo " -p ethkey -p ethstore -p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethcore-dapps -p ethcore-signer" >> $FILE echo "" >> $FILE chmod +x $FILE diff --git a/parity/main.rs b/parity/main.rs index 0b64d0644..f73711e93 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -546,7 +546,7 @@ fn execute_account_cli(conf: Configuration) { } fn execute_wallet_cli(conf: Configuration) { - use ethcore::ethstore::{PresaleWallet, SecretStore, EthStore}; + use ethcore::ethstore::{PresaleWallet, EthStore}; use ethcore::ethstore::dir::DiskDirectory; use ethcore::account_provider::AccountProvider; diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 55e4e93b2..33b04eca0 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -946,7 +946,7 @@ impl ChainSync { let tx = try!(r.at(i)).as_raw().to_vec(); transactions.push(tx); } - let _ = io.chain().queue_transactions(transactions); + io.chain().queue_transactions(transactions); Ok(()) } diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 7de581b4d..03f37fa61 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -735,6 +735,7 @@ impl Host where Message: Send + Sync + Clone { self.kill_connection(token, io, true); } + #[cfg_attr(feature="dev", allow(collapsible_if))] fn session_readable(&self, token: StreamToken, io: &IoContext>) { let mut ready_data: Vec = Vec::new(); let mut packet_data: Vec<(ProtocolId, PacketId, Vec)> = Vec::new(); From 8fcec203982b7c60fc30187a19f1ac6dd14c9bf0 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 23 Jun 2016 14:29:16 +0200 Subject: [PATCH 170/239] Gas limit ceiling option. --- ethcore/src/basic_authority.rs | 2 +- ethcore/src/block.rs | 6 +++--- ethcore/src/client/client.rs | 4 ++-- ethcore/src/client/mod.rs | 2 +- ethcore/src/client/test_client.rs | 2 +- ethcore/src/engine.rs | 2 +- ethcore/src/ethereum/ethash.rs | 12 +++++++---- ethcore/src/miner/miner.rs | 25 +++++++++++++++-------- ethcore/src/miner/mod.rs | 11 ++++++++-- parity/cli.rs | 3 +++ parity/configuration.rs | 11 +++++++++- parity/main.rs | 1 + rpc/src/v1/impls/ethcore.rs | 4 ++++ rpc/src/v1/impls/ethcore_set.rs | 11 ++++++++-- rpc/src/v1/tests/helpers/miner_service.rs | 19 ++++++++++++----- rpc/src/v1/traits/ethcore.rs | 4 ++++ rpc/src/v1/traits/ethcore_set.rs | 4 ++++ 17 files changed, 92 insertions(+), 31 deletions(-) diff --git a/ethcore/src/basic_authority.rs b/ethcore/src/basic_authority.rs index bac3ea5ac..40898e509 100644 --- a/ethcore/src/basic_authority.rs +++ b/ethcore/src/basic_authority.rs @@ -80,7 +80,7 @@ impl Engine for BasicAuthority { Schedule::new_homestead() } - fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256) { + fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { header.difficulty = parent.difficulty; header.gas_limit = { let gas_limit = parent.gas_limit; diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index f7288c85b..989a3075b 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -222,7 +222,7 @@ impl<'x> OpenBlock<'x> { last_hashes: LastHashes, dao_rescue_block_gas_limit: Option, author: Address, - gas_floor_target: U256, + gas_range_target: (U256, U256), extra_data: Bytes, ) -> Result { let state = try!(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce())); @@ -241,7 +241,7 @@ impl<'x> OpenBlock<'x> { r.block.base.header.extra_data = extra_data; r.block.base.header.note_dirty(); - engine.populate_from_parent(&mut r.block.base.header, parent, gas_floor_target); + engine.populate_from_parent(&mut r.block.base.header, parent, gas_range_target.0, gas_range_target.1); engine.on_new_block(&mut r.block); Ok(r) } @@ -480,7 +480,7 @@ pub fn enact( } } - let mut b = try!(OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, header.author().clone(), 3141562.into(), header.extra_data().clone())); + let mut b = try!(OpenBlock::new(engine, vm_factory, tracing, db, parent, last_hashes, dao_rescue_block_gas_limit, header.author().clone(), (3141562.into(), 31415620.into()), header.extra_data().clone())); b.set_difficulty(*header.difficulty()); b.set_gas_limit(*header.gas_limit()); b.set_timestamp(header.timestamp()); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 693296469..4ccfb7360 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -797,7 +797,7 @@ impl BlockChainClient for Client where V: Verifier { } impl MiningBlockChainClient for Client where V: Verifier { - fn prepare_open_block(&self, author: Address, gas_floor_target: U256, extra_data: Bytes) -> OpenBlock { + fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock { let engine = self.engine.deref().deref(); let h = self.chain.best_block_hash(); @@ -810,7 +810,7 @@ impl MiningBlockChainClient for Client where V: Verifier { self.build_last_hashes(h.clone()), self.dao_rescue_block_gas_limit(h.clone()), author, - gas_floor_target, + gas_range_target, extra_data, ).expect("OpenBlock::new only fails if parent state root invalid; state root of best block's header is never invalid; qed"); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 86686cb4c..433881e9a 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -251,6 +251,6 @@ pub trait BlockChainClient : Sync + Send { /// Extended client interface used for mining pub trait MiningBlockChainClient : BlockChainClient { /// Returns OpenBlock prepared for closing. - fn prepare_open_block(&self, author: Address, gas_floor_target: U256, extra_data: Bytes) + fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock; } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 29f91a1d6..621f880c5 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -240,7 +240,7 @@ impl TestBlockChainClient { } impl MiningBlockChainClient for TestBlockChainClient { - fn prepare_open_block(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes) -> OpenBlock { + fn prepare_open_block(&self, _author: Address, _gas_range_target: (U256, U256), _extra_data: Bytes) -> OpenBlock { unimplemented!(); } } diff --git a/ethcore/src/engine.rs b/ethcore/src/engine.rs index 98ebac40e..e78f84c13 100644 --- a/ethcore/src/engine.rs +++ b/ethcore/src/engine.rs @@ -96,7 +96,7 @@ pub trait Engine : Sync + Send { /// Don't forget to call Super::populate_from_parent when subclassing & overriding. // TODO: consider including State in the params. - fn populate_from_parent(&self, header: &mut Header, parent: &Header, _gas_floor_target: U256) { + fn populate_from_parent(&self, header: &mut Header, parent: &Header, _gas_floor_target: U256, _gas_ceil_target: U256) { header.difficulty = parent.difficulty; header.gas_limit = parent.gas_limit; header.note_dirty(); diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 0e90e3867..34918993a 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -112,15 +112,20 @@ impl Engine for Ethash { } } - fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256) { + fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, gas_ceil_target: U256) { header.difficulty = self.calculate_difficuty(header, parent); header.gas_limit = { let gas_limit = parent.gas_limit; let bound_divisor = self.ethash_params.gas_limit_bound_divisor; if gas_limit < gas_floor_target { min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) + } else if gas_limit > gas_ceil_target { + max(gas_ceil_target, gas_limit - gas_limit / bound_divisor + 1.into()) } else { - max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into() + (header.gas_used * 6.into() / 5.into()) / bound_divisor) + max(gas_ceil_target, + max(gas_floor_target, + gas_limit - gas_limit / bound_divisor + 1.into() + + (header.gas_used * 6.into() / 5.into()) / bound_divisor)) } }; header.note_dirty(); @@ -237,8 +242,7 @@ impl Ethash { let mut target = if header.number < frontier_limit { if header.timestamp >= parent.timestamp + duration_limit { parent.difficulty - (parent.difficulty / difficulty_bound_divisor) - } - else { + } else { parent.difficulty + (parent.difficulty / difficulty_bound_divisor) } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 290e94059..709a32482 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -39,7 +39,7 @@ pub struct Miner { force_sealing: bool, sealing_enabled: AtomicBool, sealing_block_last_request: Mutex, - gas_floor_target: RwLock, + gas_range_target: RwLock<(U256, U256)>, author: RwLock
, extra_data: RwLock, spec: Spec, @@ -55,7 +55,7 @@ impl Default for Miner { sealing_enabled: AtomicBool::new(false), sealing_block_last_request: Mutex::new(0), sealing_work: Mutex::new(UsingQueue::new(5)), - gas_floor_target: RwLock::new(U256::zero()), + gas_range_target: RwLock::new((U256::zero(), U256::zero())), author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), accounts: None, @@ -73,7 +73,7 @@ impl Miner { sealing_enabled: AtomicBool::new(force_sealing), sealing_block_last_request: Mutex::new(0), sealing_work: Mutex::new(UsingQueue::new(5)), - gas_floor_target: RwLock::new(U256::zero()), + gas_range_target: RwLock::new((U256::zero(), U256::zero())), author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), accounts: None, @@ -89,7 +89,7 @@ impl Miner { sealing_enabled: AtomicBool::new(force_sealing), sealing_block_last_request: Mutex::new(0), sealing_work: Mutex::new(UsingQueue::new(5)), - gas_floor_target: RwLock::new(U256::zero()), + gas_range_target: RwLock::new((U256::zero(), U256::zero())), author: RwLock::new(Address::default()), extra_data: RwLock::new(Vec::new()), accounts: Some(accounts), @@ -131,7 +131,7 @@ impl Miner { trace!(target: "miner", "No existing work - making new block"); chain.prepare_open_block( self.author(), - self.gas_floor_target(), + (self.gas_floor_target(), self.gas_ceil_target()), self.extra_data() ) } @@ -341,7 +341,11 @@ impl MinerService for Miner { /// Set the gas limit we wish to target when sealing a new block. fn set_gas_floor_target(&self, target: U256) { - *self.gas_floor_target.write().unwrap() = target; + self.gas_range_target.write().unwrap().0 = target; + } + + fn set_gas_ceil_target(&self, target: U256) { + self.gas_range_target.write().unwrap().1 = target; } fn set_minimal_gas_price(&self, min_gas_price: U256) { @@ -358,7 +362,7 @@ impl MinerService for Miner { } fn sensible_gas_limit(&self) -> U256 { - *self.gas_floor_target.read().unwrap() / 5.into() + self.gas_range_target.read().unwrap().0 / 5.into() } fn transactions_limit(&self) -> usize { @@ -381,7 +385,12 @@ impl MinerService for Miner { /// Get the gas limit we wish to target when sealing a new block. fn gas_floor_target(&self) -> U256 { - *self.gas_floor_target.read().unwrap() + self.gas_range_target.read().unwrap().0 + } + + /// Get the gas limit we wish to target when sealing a new block. + fn gas_ceil_target(&self) -> U256 { + self.gas_range_target.read().unwrap().1 } fn import_transactions(&self, chain: &MiningBlockChainClient, transactions: Vec, fetch_account: T) -> diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 697f7513f..b28dcbe8d 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -81,12 +81,19 @@ pub trait MinerService : Send + Sync { /// Set minimal gas price of transaction to be accepted for mining. fn set_minimal_gas_price(&self, min_gas_price: U256); - /// Get the gas limit we wish to target when sealing a new block. + /// Get the lower bound of the gas limit we wish to target when sealing a new block. fn gas_floor_target(&self) -> U256; - /// Set the gas limit we wish to target when sealing a new block. + /// Get the upper bound of the gas limit we wish to target when sealing a new block. + fn gas_ceil_target(&self) -> U256; + + // TODO: coalesce into single set_range function. + /// Set the lower bound of gas limit we wish to target when sealing a new block. fn set_gas_floor_target(&self, target: U256); + /// Set the upper bound of gas limit we wish to target when sealing a new block. + fn set_gas_ceil_target(&self, target: U256); + /// Get current transactions limit in queue. fn transactions_limit(&self) -> usize; diff --git a/parity/cli.rs b/parity/cli.rs index 7fd8d6482..9e9671c69 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -137,6 +137,8 @@ Sealing/Mining Options: good value [default: auto]. --gas-floor-target GAS Amount of gas per block to target when sealing a new block [default: 3141592]. + --gas-cap GAS A cap on how large we will raise the gas limit per + block due to transaction volume [default: 3141592]. --author ADDRESS Specify the block author (aka "coinbase") address for sending block rewards from sealed blocks [default: 0037a6b811ffeb6e072da21179d11b1406371c63]. @@ -283,6 +285,7 @@ pub struct Args { pub flag_usd_per_tx: String, pub flag_usd_per_eth: String, pub flag_gas_floor_target: String, + pub flag_gas_cap: String, pub flag_extra_data: Option, pub flag_tx_limit: usize, pub flag_logging: Option, diff --git a/parity/configuration.rs b/parity/configuration.rs index 4196564b5..3800e3dc8 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -85,7 +85,16 @@ impl Configuration { } } - + pub fn gas_ceil_target(&self) -> U256 { + if self.args.flag_dont_help_rescue_dao || self.args.flag_dogmatic { + 10_000_000.into() + } else { + let d = &self.args.flag_gas_cap; + U256::from_dec_str(d).unwrap_or_else(|_| { + die!("{}: Invalid target gas ceiling given. Must be a decimal unsigned 256-bit number.", d) + }) + } + } pub fn gas_price(&self) -> U256 { match self.args.flag_gasprice.as_ref() { diff --git a/parity/main.rs b/parity/main.rs index 0b64d0644..1fd77caa7 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -211,6 +211,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) let miner = Miner::with_accounts(conf.args.flag_force_sealing, conf.spec(), account_service.clone()); miner.set_author(conf.author()); miner.set_gas_floor_target(conf.gas_floor_target()); + miner.set_gas_ceil_target(conf.gas_ceil_target()); miner.set_extra_data(conf.extra_data()); miner.set_minimal_gas_price(conf.gas_price()); miner.set_transactions_limit(conf.args.flag_tx_limit); diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/ethcore.rs index 3a8b8a4a0..3a58d8672 100644 --- a/rpc/src/v1/impls/ethcore.rs +++ b/rpc/src/v1/impls/ethcore.rs @@ -72,6 +72,10 @@ impl Ethcore for EthcoreClient where M: MinerService + 'static, C: M to_value(&take_weak!(self.miner).gas_floor_target()) } + fn gas_ceil_target(&self, _: Params) -> Result { + to_value(&take_weak!(self.miner).gas_ceil_target()) + } + fn dev_logs(&self, _params: Params) -> Result { let logs = self.logger.logs(); to_value(&logs.deref().as_slice()) diff --git a/rpc/src/v1/impls/ethcore_set.rs b/rpc/src/v1/impls/ethcore_set.rs index 66f1a34aa..55164217c 100644 --- a/rpc/src/v1/impls/ethcore_set.rs +++ b/rpc/src/v1/impls/ethcore_set.rs @@ -52,8 +52,15 @@ impl EthcoreSet for EthcoreSetClient where M: MinerService + 'static { } fn set_gas_floor_target(&self, params: Params) -> Result { - from_params::<(U256,)>(params).and_then(|(gas_floor_target,)| { - take_weak!(self.miner).set_gas_floor_target(gas_floor_target); + from_params::<(U256,)>(params).and_then(|(target,)| { + take_weak!(self.miner).set_gas_floor_target(target); + to_value(&true) + }) + } + + fn set_gas_ceil_target(&self, params: Params) -> Result { + from_params::<(U256,)>(params).and_then(|(target,)| { + take_weak!(self.miner).set_gas_ceil_target(target); to_value(&true) }) } diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 7ec7fc1cc..b87b650e1 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -39,7 +39,7 @@ pub struct TestMinerService { pub last_nonces: RwLock>, min_gas_price: RwLock, - gas_floor_target: RwLock, + gas_range_target: RwLock<(U256, U256)>, author: RwLock
, extra_data: RwLock, limit: RwLock, @@ -54,7 +54,7 @@ impl Default for TestMinerService { pending_receipts: Mutex::new(BTreeMap::new()), last_nonces: RwLock::new(HashMap::new()), min_gas_price: RwLock::new(U256::from(20_000_000)), - gas_floor_target: RwLock::new(U256::from(12345)), + gas_range_target: RwLock::new((U256::from(12345), U256::from(54321))), author: RwLock::new(Address::zero()), extra_data: RwLock::new(vec![1, 2, 3, 4]), limit: RwLock::new(1024), @@ -81,9 +81,14 @@ impl MinerService for TestMinerService { *self.extra_data.write().unwrap() = extra_data; } - /// Set the gas limit we wish to target when sealing a new block. + /// Set the lower gas limit we wish to target when sealing a new block. fn set_gas_floor_target(&self, target: U256) { - *self.gas_floor_target.write().unwrap() = target; + self.gas_range_target.write().unwrap().0 = target; + } + + /// Set the upper gas limit we wish to target when sealing a new block. + fn set_gas_ceil_target(&self, target: U256) { + self.gas_range_target.write().unwrap().1 = target; } fn set_minimal_gas_price(&self, min_gas_price: U256) { @@ -111,7 +116,11 @@ impl MinerService for TestMinerService { } fn gas_floor_target(&self) -> U256 { - *self.gas_floor_target.read().unwrap() + self.gas_range_target.read().unwrap().0 + } + + fn gas_ceil_target(&self) -> U256 { + self.gas_range_target.read().unwrap().1 } /// Imports transactions to transaction queue. diff --git a/rpc/src/v1/traits/ethcore.rs b/rpc/src/v1/traits/ethcore.rs index 32855727f..a5032d3e2 100644 --- a/rpc/src/v1/traits/ethcore.rs +++ b/rpc/src/v1/traits/ethcore.rs @@ -30,6 +30,9 @@ pub trait Ethcore: Sized + Send + Sync + 'static { /// Returns mining gas floor target. fn gas_floor_target(&self, _: Params) -> Result; + /// Returns mining gas floor cap. + fn gas_ceil_target(&self, _: Params) -> Result; + /// Returns minimal gas price for transaction to be included in queue. fn min_gas_price(&self, _: Params) -> Result; @@ -70,6 +73,7 @@ pub trait Ethcore: Sized + Send + Sync + 'static { delegate.add_method("ethcore_extraData", Ethcore::extra_data); delegate.add_method("ethcore_gasFloorTarget", Ethcore::gas_floor_target); + delegate.add_method("ethcore_gasCeilTarget", Ethcore::gas_ceil_target); delegate.add_method("ethcore_minGasPrice", Ethcore::min_gas_price); delegate.add_method("ethcore_transactionsLimit", Ethcore::transactions_limit); delegate.add_method("ethcore_devLogs", Ethcore::dev_logs); diff --git a/rpc/src/v1/traits/ethcore_set.rs b/rpc/src/v1/traits/ethcore_set.rs index ed4303be1..d00295036 100644 --- a/rpc/src/v1/traits/ethcore_set.rs +++ b/rpc/src/v1/traits/ethcore_set.rs @@ -28,6 +28,9 @@ pub trait EthcoreSet: Sized + Send + Sync + 'static { /// Sets new gas floor target for mined blocks. fn set_gas_floor_target(&self, _: Params) -> Result; + /// Sets new gas ceiling target for mined blocks. + fn set_gas_ceil_target(&self, _: Params) -> Result; + /// Sets new extra data for mined blocks. fn set_extra_data(&self, _: Params) -> Result; @@ -54,6 +57,7 @@ pub trait EthcoreSet: Sized + Send + Sync + 'static { let mut delegate = IoDelegate::new(Arc::new(self)); delegate.add_method("ethcore_setMinGasPrice", EthcoreSet::set_min_gas_price); delegate.add_method("ethcore_setGasFloorTarget", EthcoreSet::set_gas_floor_target); + delegate.add_method("ethcore_setGasCeilTarget", EthcoreSet::set_gas_ceil_target); delegate.add_method("ethcore_setExtraData", EthcoreSet::set_extra_data); delegate.add_method("ethcore_setAuthor", EthcoreSet::set_author); delegate.add_method("ethcore_setTransactionsLimit", EthcoreSet::set_transactions_limit); From 41e0769e63348e2c0acf385481974878803bae54 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Thu, 23 Jun 2016 14:43:20 +0200 Subject: [PATCH 171/239] Fix tests, --- ethcore/src/basic_authority.rs | 2 +- ethcore/src/block.rs | 6 +++--- ethcore/src/ethereum/ethash.rs | 4 ++-- ethcore/src/tests/client.rs | 2 +- ethcore/src/tests/helpers.rs | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ethcore/src/basic_authority.rs b/ethcore/src/basic_authority.rs index 40898e509..4426d3059 100644 --- a/ethcore/src/basic_authority.rs +++ b/ethcore/src/basic_authority.rs @@ -254,7 +254,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, addr, 3141562.into(), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, addr, (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close_and_lock(); let seal = engine.generate_seal(b.block(), Some(&tap)).unwrap(); assert!(b.try_seal(engine.deref(), seal).is_ok()); diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 989a3075b..9c522baed 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -552,7 +552,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), 3141562.into(), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close_and_lock(); let _ = b.seal(engine.deref(), vec![]); } @@ -568,7 +568,7 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), 3141562.into(), vec![]).unwrap() + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap() .close_and_lock().seal(engine.deref(), vec![]).unwrap(); let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); @@ -596,7 +596,7 @@ mod tests { let mut db = db_result.take(); spec.ensure_db_good(db.as_hashdb_mut()); let vm_factory = Default::default(); - let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), 3141562.into(), vec![]).unwrap(); + let mut open_block = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, vec![genesis_header.hash()], None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let mut uncle1_header = Header::new(); uncle1_header.extra_data = b"uncle1".to_vec(); let mut uncle2_header = Header::new(); diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 34918993a..83a2fc9bc 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -327,7 +327,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), 3141562.into(), vec![]).unwrap(); + let b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close(); assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap()); } @@ -342,7 +342,7 @@ mod tests { spec.ensure_db_good(db.as_hashdb_mut()); let last_hashes = vec![genesis_header.hash()]; let vm_factory = Default::default(); - let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), 3141562.into(), vec![]).unwrap(); + let mut b = OpenBlock::new(engine.deref(), &vm_factory, false, db, &genesis_header, last_hashes, None, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let mut uncle = Header::new(); let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106"); uncle.author = uncle_author.clone(); diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index f2ab62840..79ffa7147 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -150,7 +150,7 @@ fn can_mine() { let client_result = get_test_client_with_blocks(vec![dummy_blocks[0].clone()]); let client = client_result.reference(); - let b = client.prepare_open_block(Address::default(), 31415926.into(), vec![]).close(); + let b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]).close(); assert_eq!(*b.block().header().parent_hash(), BlockView::new(&dummy_blocks[0]).header_view().sha3()); } diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index ce204f647..ab538922c 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -181,7 +181,7 @@ pub fn generate_dummy_client_with_spec_and_data(get_test_spec: F, block_numbe last_hashes.clone(), None, author.clone(), - 3141562.into(), + (3141562.into(), 31415620.into()), vec![] ).unwrap(); b.set_difficulty(U256::from(0x20000)); From 19585947a5194ddbd38cd87f693fca5c013081b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 23 Jun 2016 14:46:31 +0200 Subject: [PATCH 172/239] Fixing jit compilation --- ethcore/src/evm/jit.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ethcore/src/evm/jit.rs b/ethcore/src/evm/jit.rs index d46ad917f..4f43d327b 100644 --- a/ethcore/src/evm/jit.rs +++ b/ethcore/src/evm/jit.rs @@ -16,9 +16,8 @@ //! Just in time compiler execution environment. use common::*; -use trace::VMTracer; use evmjit; -use evm::{self, Error, GasLeft}; +use evm::{self, GasLeft}; /// Should be used to convert jit types to ethcore trait FromJit: Sized { @@ -303,7 +302,7 @@ impl<'a> evmjit::Ext for ExtAdapter<'a> { #[derive(Default)] pub struct JitEvm { - ctxt: Option, + context: Option, } impl evm::Evm for JitEvm { @@ -347,7 +346,7 @@ impl evm::Evm for JitEvm { data.timestamp = ext.env_info().timestamp as i64; self.context = Some(unsafe { evmjit::ContextHandle::new(data, schedule, &mut ext_handle) }); - let context = self.context.as_ref_mut().unwrap(); + let mut context = self.context.as_mut().unwrap(); let res = context.exec(); match res { From 27b18df3dd12aa3850e4e1e05faac48675e498b4 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Thu, 23 Jun 2016 19:56:43 +0300 Subject: [PATCH 173/239] further rocksdb tuning (#1409) --- util/src/kvdb.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 66a4a02ee..c1be5c691 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -20,8 +20,10 @@ use std::default::Default; use rocksdb::{DB, Writable, WriteBatch, IteratorMode, DBVector, DBIterator, IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; -const DB_FILE_SIZE_BASE: u64 = 10 * 1024 * 1024; -const DB_FILE_SIZE_MULTIPLIER: i32 = 5; +const DB_FILE_SIZE_BASE: u64 = 128 * 1024 * 1024; +const DB_FILE_SIZE_MULTIPLIER: i32 = 1; +const DB_BACKGROUND_FLUSHES: i32 = 4; +const DB_BACKGROUND_COMPACTIONS: i32 = 4; /// Write transaction. Batches a sequence of put/delete operations for efficiency. pub struct DBTransaction { @@ -116,6 +118,8 @@ impl Database { opts.set_compaction_style(DBCompactionStyle::DBUniversalCompaction); opts.set_target_file_size_base(DB_FILE_SIZE_BASE); opts.set_target_file_size_multiplier(DB_FILE_SIZE_MULTIPLIER); + opts.set_max_background_flushes(DB_BACKGROUND_FLUSHES); + opts.set_max_background_compactions(DB_BACKGROUND_COMPACTIONS); if let Some(cache_size) = config.cache_size { // half goes to read cache opts.set_block_cache_size_mb(cache_size as u64 / 2); From 416781a8d4a9e4e88937949b23f91aa54613d6e5 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Thu, 23 Jun 2016 18:57:42 +0200 Subject: [PATCH 174/239] Tweaked cli options (#1407) --- parity/cli.rs | 26 ++++++++++++++++---------- parity/configuration.rs | 8 ++++---- parity/main.rs | 6 +++--- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 7fd8d6482..cc68a8d4d 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -82,7 +82,7 @@ Networking Options: --reserved-only Connect only to reserved nodes. API and Console Options: - --jsonrpc-off Disable the JSON-RPC API server. + --no-jsonrpc Disable the JSON-RPC API server. --jsonrpc-port PORT Specify the port portion of the JSONRPC API server [default: 8545]. --jsonrpc-interface IP Specify the hostname portion of the JSONRPC API @@ -95,13 +95,13 @@ API and Console Options: ethcore, ethcore_set, traces. [default: web3,eth,net,ethcore,personal,traces]. - --ipc-off Disable JSON-RPC over IPC service. + --no-ipc Disable JSON-RPC over IPC service. --ipc-path PATH Specify custom path for JSON-RPC over IPC service [default: $HOME/.parity/jsonrpc.ipc]. --ipc-apis APIS Specify custom API set available via JSON-RPC over IPC [default: web3,eth,net,ethcore,personal,traces,rpc]. - --dapps-off Disable the Dapps server (e.g. status page). + --no-dapps Disable the Dapps server (e.g. status page). --dapps-port PORT Specify the port portion of the Dapps server [default: 8080]. --dapps-interface IP Specify the hostname portion of the Dapps @@ -116,7 +116,7 @@ API and Console Options: --dapps-path PATH Specify directory where dapps should be installed. [default: $HOME/.parity/dapps] - --signer-off Disable Trusted Signer WebSocket endpoint used by + --signer Enable Trusted Signer WebSocket endpoint used by Signer UIs. --signer-port PORT Specify the port of Trusted Signer server [default: 8180]. @@ -160,7 +160,7 @@ Footprint Options: light - early merges with partial tracking. Fast, light, and experimental! auto - use the method most recently synced or - default to archive if none synced [default: auto]. + default to fast if none synced [default: auto]. --cache-pref-size BYTES Specify the prefered size of the blockchain cache in bytes [default: 16384]. --cache-max-size BYTES Specify the maximum size of the blockchain cache in @@ -197,13 +197,16 @@ Legacy Options: --nodekey KEY Equivalent to --node-key KEY. --nodiscover Equivalent to --no-discovery. -j --jsonrpc Does nothing; JSON-RPC is on by default now. + --jsonrpc-off Equivalent to --no-jsonrpc. -w --webapp Does nothing; dapps server is on by default now. + --dapps-off Equivalent to --no-dapps. --rpc Does nothing; JSON-RPC is on by default now. --rpcaddr IP Equivalent to --jsonrpc-interface IP. --rpcport PORT Equivalent to --jsonrpc-port PORT. --rpcapi APIS Equivalent to --jsonrpc-apis APIS. --rpccorsdomain URL Equivalent to --jsonrpc-cors URL. - --ipcdisable Equivalent to --ipc-off. + --ipcdisable Equivalent to --no-ipc. + --ipc-off Equivalent to --no-ipc. --ipcapi APIS Equivalent to --ipc-apis APIS. --ipcpath PATH Equivalent to --ipc-path PATH. --gasprice WEI Minimum amount of Wei per GAS to be paid for a @@ -260,21 +263,21 @@ pub struct Args { pub flag_cache_pref_size: usize, pub flag_cache_max_size: usize, pub flag_queue_max_size: usize, - pub flag_jsonrpc_off: bool, + pub flag_no_jsonrpc: bool, pub flag_jsonrpc_interface: String, pub flag_jsonrpc_port: u16, pub flag_jsonrpc_cors: Option, pub flag_jsonrpc_apis: String, - pub flag_ipc_off: bool, + pub flag_no_ipc: bool, pub flag_ipc_path: String, pub flag_ipc_apis: String, - pub flag_dapps_off: bool, + pub flag_no_dapps: bool, pub flag_dapps_port: u16, pub flag_dapps_interface: String, pub flag_dapps_user: Option, pub flag_dapps_pass: Option, pub flag_dapps_path: String, - pub flag_signer_off: bool, + pub flag_signer: bool, pub flag_signer_port: u16, pub flag_signer_path: String, pub flag_no_token: bool, @@ -312,6 +315,9 @@ pub struct Args { pub flag_testnet: bool, pub flag_networkid: Option, pub flag_ipcdisable: bool, + pub flag_ipc_off: bool, + pub flag_jsonrpc_off: bool, + pub flag_dapps_off: bool, pub flag_ipcpath: Option, pub flag_ipcapi: Option, pub flag_db_cache_size: Option, diff --git a/parity/configuration.rs b/parity/configuration.rs index 4196564b5..4560324d3 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -265,7 +265,7 @@ impl Configuration { "light" => journaldb::Algorithm::EarlyMerge, "fast" => journaldb::Algorithm::OverlayRecent, "basic" => journaldb::Algorithm::RefCounted, - "auto" => self.find_best_db(spec).unwrap_or(journaldb::Algorithm::Archive), + "auto" => self.find_best_db(spec).unwrap_or(journaldb::Algorithm::OverlayRecent), _ => { die!("Invalid pruning method given."); } }; @@ -359,7 +359,7 @@ impl Configuration { pub fn ipc_settings(&self) -> IpcConfiguration { IpcConfiguration { - enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off), + enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off || self.args.flag_no_ipc), socket_addr: self.ipc_path(), apis: self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone()), } @@ -372,7 +372,7 @@ impl Configuration { chain: self.chain(), max_peers: self.max_peers(), network_port: self.net_port(), - rpc_enabled: !self.args.flag_jsonrpc_off, + rpc_enabled: !self.args.flag_jsonrpc_off && !self.args.flag_no_jsonrpc, rpc_interface: self.args.flag_rpcaddr.clone().unwrap_or(self.args.flag_jsonrpc_interface.clone()), rpc_port: self.args.flag_rpcport.unwrap_or(self.args.flag_jsonrpc_port), } @@ -432,7 +432,7 @@ impl Configuration { } pub fn signer_port(&self) -> Option { - if self.args.flag_signer_off { + if !self.args.flag_signer { None } else { Some(self.args.flag_signer_port) diff --git a/parity/main.rs b/parity/main.rs index f73711e93..8beba61b5 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -192,14 +192,14 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) let sync_config = conf.sync_config(&spec); // Create and display a new token for UIs. - if !conf.args.flag_signer_off && !conf.args.flag_no_token { + if conf.args.flag_signer && !conf.args.flag_no_token { new_token(conf.directories().signer).unwrap_or_else(|e| { die!("Error generating token: {:?}", e) }); } // Display warning about using unlock with signer - if !conf.args.flag_signer_off && conf.args.flag_unlock.is_some() { + if conf.args.flag_signer && conf.args.flag_unlock.is_some() { warn!("Using Trusted Signer and --unlock is not recommended!"); warn!("NOTE that Signer will not ask you to confirm transactions from unlocked account."); } @@ -264,7 +264,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) if conf.args.flag_webapp { println!("WARNING: Flag -w/--webapp is deprecated. Dapps server is now on by default. Ignoring."); } let dapps_server = dapps::new(dapps::Configuration { - enabled: !conf.args.flag_dapps_off, + enabled: !conf.args.flag_dapps_off && !conf.args.flag_no_dapps, interface: conf.args.flag_dapps_interface.clone(), port: conf.args.flag_dapps_port, user: conf.args.flag_dapps_user.clone(), From e77cce66a1f49851eff42f8b1299667c8ffb4ffc Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 23 Jun 2016 22:40:44 +0200 Subject: [PATCH 175/239] Update highest block progress --- sync/src/chain.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 33b04eca0..5d0976aac 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -534,6 +534,9 @@ impl ChainSync { let h = header_rlp.as_raw().sha3(); trace!(target: "sync", "{} -> NewBlock ({})", peer_id, h); let header: BlockHeader = try!(header_rlp.as_val()); + if header.number() > self.highest_block.unwrap_or(0) { + self.highest_block = Some(header.number()); + } let mut unknown = false; { let peer = self.peers.get_mut(&peer_id).unwrap(); @@ -587,6 +590,10 @@ impl ChainSync { fn on_peer_new_hashes(&mut self, io: &mut SyncIo, peer_id: PeerId, r: &UntrustedRlp) -> Result<(), PacketDecodeError> { 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, max); + if max > self.highest_block.unwrap_or(0) { + self.highest_block = Some(max); + } return Ok(()); } trace!(target: "sync", "{} -> NewHashes ({} entries)", peer_id, r.item_count()); @@ -596,6 +603,9 @@ impl ChainSync { for (rh, rd) in hashes { let h = try!(rh); let d = try!(rd); + if d > self.highest_block.unwrap_or(0) { + self.highest_block = Some(d); + } if self.blocks.is_downloading(&h) { continue; } From 34c89e58410c52fa8d6cbc3506a000e3a7efb4a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 24 Jun 2016 10:49:13 +0200 Subject: [PATCH 176/239] fixing json_tests --- ethcore/src/json_tests/chain.rs | 28 ++++++++++++++++++---------- ethcore/src/miner/mod.rs | 2 +- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index a5f5e36c9..2e538322c 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -41,20 +41,28 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { flush!(" - {}...", name); - let mut spec = match era { - ChainEra::Frontier => ethereum::new_frontier_test(), - ChainEra::Homestead => ethereum::new_homestead_test(), + let spec = || { + let genesis = Genesis::from(blockchain.genesis()); + let state = From::from(blockchain.pre_state.clone()); + let mut spec = match era { + ChainEra::Frontier => ethereum::new_frontier_test(), + ChainEra::Homestead => ethereum::new_homestead_test(), + }; + spec.set_genesis_state(state); + spec.overwrite_genesis_params(genesis); + assert!(spec.is_state_root_valid()); + spec }; - let genesis = Genesis::from(blockchain.genesis()); - let state = From::from(blockchain.pre_state.clone()); - spec.set_genesis_state(state); - spec.overwrite_genesis_params(genesis); - assert!(spec.is_state_root_valid()); - let temp = RandomTempPath::new(); { - let client = Client::new(ClientConfig::default(), spec.clone(), temp.as_path(), Arc::new(Miner::with_spec(spec)), IoChannel::disconnected()).unwrap(); + let client = Client::new( + ClientConfig::default(), + spec(), + temp.as_path(), + Arc::new(Miner::with_spec(spec())), + IoChannel::disconnected() + ).unwrap(); for b in &blockchain.blocks_rlp() { if Block::is_good(&b) { let _ = client.import_block(b.clone()); diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 91905ff4c..c9e725a4e 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -33,7 +33,7 @@ //! use ethcore::miner::{Miner, MinerService}; //! //! fn main() { -//! let miner: Miner = Miner::with_spec(ethereum::new_frontier()); +//! let miner: Miner = Miner::with_spec(ethereum::new_frontier(true)); //! // get status //! assert_eq!(miner.status().transactions_in_pending_queue, 0); //! From dc7c53d59ae4dd841be3f240d61bdadef1af23fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 24 Jun 2016 10:57:44 +0200 Subject: [PATCH 177/239] Fixing json tests --- ethcore/src/json_tests/chain.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 2e538322c..c8e967d76 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -22,6 +22,7 @@ use tests::helpers::*; use devtools::*; use spec::Genesis; use ethjson; +use ethjson::blockchain::BlockChain; use miner::Miner; pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { @@ -41,7 +42,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { flush!(" - {}...", name); - let spec = || { + let spec = |blockchain: &BlockChain| { let genesis = Genesis::from(blockchain.genesis()); let state = From::from(blockchain.pre_state.clone()); let mut spec = match era { @@ -58,9 +59,9 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { { let client = Client::new( ClientConfig::default(), - spec(), + spec(&blockchain), temp.as_path(), - Arc::new(Miner::with_spec(spec())), + Arc::new(Miner::with_spec(spec(&blockchain))), IoChannel::disconnected() ).unwrap(); for b in &blockchain.blocks_rlp() { From e3e10335f92aec9043a9ebe422de2bb75f815eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 24 Jun 2016 11:26:04 +0200 Subject: [PATCH 178/239] Bumping TopBar, Minimal SignerUI and wallet --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f735f0e54..a4c9c4171 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -936,7 +936,7 @@ dependencies = [ [[package]] name = "parity-dapps-builtins" version = "0.5.1" -source = "git+https://github.com/ethcore/parity-dapps-builtins-rs.git#650b0d94d076635904b86c1fd45c5f4a2061463f" +source = "git+https://github.com/ethcore/parity-dapps-builtins-rs.git#7408838e8ca3b57c6b0cf5da2e31e0e275959955" dependencies = [ "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", ] @@ -952,7 +952,7 @@ dependencies = [ [[package]] name = "parity-dapps-wallet" version = "0.6.1" -source = "git+https://github.com/ethcore/parity-dapps-wallet-rs.git#8923d4c73359c75ce04f0639bbcde46adb846b81" +source = "git+https://github.com/ethcore/parity-dapps-wallet-rs.git#867994fe25038f000f1cc09cd024a83700a03930" dependencies = [ "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", ] @@ -960,7 +960,7 @@ dependencies = [ [[package]] name = "parity-minimal-sysui" version = "0.1.0" -source = "git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git#3c6ad40680126a760eb867b07b506ea996819ce3" +source = "git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git#cc5ea4bd786982f0509a8d3d5deb4217c659af85" [[package]] name = "phf" From 84ce5af2b0bc4d1247c947690ef6bd4fbbeafd6a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 24 Jun 2016 11:40:25 +0200 Subject: [PATCH 179/239] max/min incorrect --- ethcore/src/ethereum/ethash.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index dc8dd5482..3400220db 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -122,7 +122,7 @@ impl Engine for Ethash { } else if gas_limit > gas_ceil_target { max(gas_ceil_target, gas_limit - gas_limit / bound_divisor + 1.into()) } else { - max(gas_ceil_target, + min(gas_ceil_target, max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into() + (header.gas_used * 6.into() / 5.into()) / bound_divisor)) From 23732fa5167f82d82d001671e271cf206ed68a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 24 Jun 2016 12:10:36 +0200 Subject: [PATCH 180/239] Fixing interface and port for parity ui --- parity/configuration.rs | 16 ++++++++++++++++ parity/dapps.rs | 7 +------ parity/main.rs | 9 ++++++--- parity/rpc.rs | 7 +------ 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index 4560324d3..4d201ffa8 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -438,6 +438,22 @@ impl Configuration { Some(self.args.flag_signer_port) } } + + pub fn rpc_interface(&self) -> String { + match self.network_settings().rpc_interface.as_str() { + "all" => "0.0.0.0", + "local" => "127.0.0.1", + x => x, + }.into() + } + + pub fn dapps_interface(&self) -> String { + match self.args.flag_dapps_interface.as_str() { + "all" => "0.0.0.0", + "local" => "127.0.0.1", + x => x, + }.into() + } } #[cfg(test)] diff --git a/parity/dapps.rs b/parity/dapps.rs index 59a9ee552..917c59fc6 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -45,12 +45,7 @@ pub fn new(configuration: Configuration, deps: Dependencies) -> Option "0.0.0.0", - "local" => "127.0.0.1", - x => x, - }; - let url = format!("{}:{}", interface, configuration.port); + let url = format!("{}:{}", configuration.interface, configuration.port); let addr = SocketAddr::from_str(&url).unwrap_or_else(|_| die!("{}: Invalid Webapps listen host/port given.", url)); let auth = configuration.user.as_ref().map(|username| { diff --git a/parity/main.rs b/parity/main.rs index 8beba61b5..de1d81b0b 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -252,7 +252,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // Setup http rpc let rpc_server = rpc::new_http(rpc::HttpConfiguration { enabled: network_settings.rpc_enabled, - interface: network_settings.rpc_interface.clone(), + interface: conf.rpc_interface(), port: network_settings.rpc_port, apis: conf.rpc_apis(), cors: conf.rpc_cors(), @@ -265,7 +265,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) if conf.args.flag_webapp { println!("WARNING: Flag -w/--webapp is deprecated. Dapps server is now on by default. Ignoring."); } let dapps_server = dapps::new(dapps::Configuration { enabled: !conf.args.flag_dapps_off && !conf.args.flag_no_dapps, - interface: conf.args.flag_dapps_interface.clone(), + interface: conf.dapps_interface(), port: conf.args.flag_dapps_port, user: conf.args.flag_dapps_user.clone(), pass: conf.args.flag_dapps_pass.clone(), @@ -296,7 +296,10 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) service.register_io_handler(io_handler).expect("Error registering IO handler"); if conf.args.cmd_ui { - url::open("http://localhost:8080/") + if conf.args.flag_dapps_off { + die_with_message("Cannot use UI command with Dapps turned off."); + } + url::open(&format!("http://{}:{}/", conf.dapps_interface(), conf.args.flag_dapps_port)); } // Handle exit diff --git a/parity/rpc.rs b/parity/rpc.rs index c10635889..df1e14524 100644 --- a/parity/rpc.rs +++ b/parity/rpc.rs @@ -66,13 +66,8 @@ pub fn new_http(conf: HttpConfiguration, deps: &Dependencies) -> Option "0.0.0.0", - "local" => "127.0.0.1", - x => x, - }; let apis = conf.apis.split(',').collect(); - let url = format!("{}:{}", interface, conf.port); + let url = format!("{}:{}", conf.interface, conf.port); let addr = SocketAddr::from_str(&url).unwrap_or_else(|_| die!("{}: Invalid JSONRPC listen host/port given.", url)); Some(setup_http_rpc_server(deps, &addr, conf.cors, apis)) From 566bb030ec48ef2ee7f1e3281fd3340df81b41b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 24 Jun 2016 12:14:46 +0200 Subject: [PATCH 181/239] Fixing detecting if dapps are off --- parity/configuration.rs | 4 ++++ parity/main.rs | 4 ++-- parity/url.rs | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index 4d201ffa8..e27ad3f2a 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -454,6 +454,10 @@ impl Configuration { x => x, }.into() } + + pub fn dapps_enabled(&self) -> bool { + !self.args.flag_dapps_off && !self.args.flag_no_dapps + } } #[cfg(test)] diff --git a/parity/main.rs b/parity/main.rs index de1d81b0b..26f7b45ac 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -264,7 +264,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) if conf.args.flag_webapp { println!("WARNING: Flag -w/--webapp is deprecated. Dapps server is now on by default. Ignoring."); } let dapps_server = dapps::new(dapps::Configuration { - enabled: !conf.args.flag_dapps_off && !conf.args.flag_no_dapps, + enabled: conf.dapps_enabled(), interface: conf.dapps_interface(), port: conf.args.flag_dapps_port, user: conf.args.flag_dapps_user.clone(), @@ -296,7 +296,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) service.register_io_handler(io_handler).expect("Error registering IO handler"); if conf.args.cmd_ui { - if conf.args.flag_dapps_off { + if !conf.dapps_enabled() { die_with_message("Cannot use UI command with Dapps turned off."); } url::open(&format!("http://{}:{}/", conf.dapps_interface(), conf.args.flag_dapps_port)); diff --git a/parity/url.rs b/parity/url.rs index 8ab6a2eda..4ba866241 100644 --- a/parity/url.rs +++ b/parity/url.rs @@ -55,5 +55,5 @@ pub fn open(url: &str) { #[cfg(target_os="linux")] pub fn open(url: &str) { use std; - let _ = std::process::Command::new("xdg-open").arg(url).output(); + let _ = std::process::Command::new("xdg-open").arg(url).spawn(); } From 653a36878392399c84017a003b95ce278d833a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 24 Jun 2016 12:30:54 +0200 Subject: [PATCH 182/239] Changing macos impl --- parity/url.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/url.rs b/parity/url.rs index 4ba866241..129812387 100644 --- a/parity/url.rs +++ b/parity/url.rs @@ -49,7 +49,7 @@ pub fn open(url: &str) { #[cfg(target_os="macos")] pub fn open(url: &str) { use std; - let _ = std::process::Command::new("open").arg(url).output(); + let _ = std::process::Command::new("open").arg(url).spawn(); } #[cfg(target_os="linux")] From 4ece68349c0ab2fbe38da473def5af857191c07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 24 Jun 2016 12:41:48 +0200 Subject: [PATCH 183/239] Fixing sync doctests --- sync/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sync/src/lib.rs b/sync/src/lib.rs index def7775d3..3f899c261 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -44,12 +44,12 @@ //! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap(); //! service.start().unwrap(); //! let dir = env::temp_dir(); -//! let miner = Miner::new(false, ethereum::new_frontier(), None); +//! let miner = Miner::new(false, ethereum::new_frontier(true), None); //! let client = Client::new( //! ClientConfig::default(), //! ethereum::new_frontier(true), //! &dir, -//! Arc::new(miner), +//! miner, //! service.io().channel() //! ).unwrap(); //! let sync = EthSync::new(SyncConfig::default(), client); From 44d6e1f443e0d55c181d66f18dbaa58298c14919 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 24 Jun 2016 13:32:43 +0200 Subject: [PATCH 184/239] Remove experimental pruning options. --- parity/cli.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index cc68a8d4d..a612d0877 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -155,10 +155,6 @@ Footprint Options: may be one of auto, archive, fast, basic, light: archive - keep all state trie data. No pruning. fast - maintain journal overlay. Fast but 50MB used. - basic - reference count in disk DB. Slow, light, and - experimental! - light - early merges with partial tracking. Fast, - light, and experimental! auto - use the method most recently synced or default to fast if none synced [default: auto]. --cache-pref-size BYTES Specify the prefered size of the blockchain cache in From 568dc907693f92c14df4f10db41d30edb338d96a Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 24 Jun 2016 14:20:39 +0200 Subject: [PATCH 185/239] Signer enabled by default for UI --- parity/cli.rs | 5 ++++- parity/configuration.rs | 5 +++++ parity/main.rs | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 8a4e050af..0133ca0fb 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -117,7 +117,9 @@ API and Console Options: [default: $HOME/.parity/dapps] --signer Enable Trusted Signer WebSocket endpoint used by - Signer UIs. + Signer UIs. Default if no command is specified. + --no-signer Disable Trusted Signer WebSocket endpoint used by + Signer UIs. Default if run with ui command. --signer-port PORT Specify the port of Trusted Signer server [default: 8180]. --signer-path PATH Specify directory where Signer UIs tokens should @@ -280,6 +282,7 @@ pub struct Args { pub flag_dapps_pass: Option, pub flag_dapps_path: String, pub flag_signer: bool, + pub flag_no_signer: bool, pub flag_signer_port: u16, pub flag_signer_path: String, pub flag_no_token: bool, diff --git a/parity/configuration.rs b/parity/configuration.rs index f0cbebdb4..925d2041c 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -467,6 +467,11 @@ impl Configuration { pub fn dapps_enabled(&self) -> bool { !self.args.flag_dapps_off && !self.args.flag_no_dapps } + + pub fn signer_enabled(&self) -> bool { + (self.args.cmd_ui && !self.args.flag_no_signer) || + (!self.args.cmd_ui && self.args.flag_signer) + } } #[cfg(test)] diff --git a/parity/main.rs b/parity/main.rs index fd7e8a437..84f144396 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -192,14 +192,14 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) let sync_config = conf.sync_config(&spec); // Create and display a new token for UIs. - if conf.args.flag_signer && !conf.args.flag_no_token { + if conf.signer_enabled() && !conf.args.flag_no_token { new_token(conf.directories().signer).unwrap_or_else(|e| { die!("Error generating token: {:?}", e) }); } // Display warning about using unlock with signer - if conf.args.flag_signer && conf.args.flag_unlock.is_some() { + if conf.signer_enabled() && conf.args.flag_unlock.is_some() { warn!("Using Trusted Signer and --unlock is not recommended!"); warn!("NOTE that Signer will not ask you to confirm transactions from unlocked account."); } From 60d259c9d5e882578ddf876457f144f13b462373 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 24 Jun 2016 14:20:50 +0200 Subject: [PATCH 186/239] Update SF blocknumber to 1800000. --- ethcore/src/block.rs | 2 +- ethcore/src/client/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index b6e5ba46d..f72eaa32a 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -288,7 +288,7 @@ impl<'x> OpenBlock<'x> { /// Get the environment info concerning this block. pub fn env_info(&self) -> EnvInfo { // TODO: memoise. - const SOFT_FORK_BLOCK: u64 = 1775000; + const SOFT_FORK_BLOCK: u64 = 1_800_000; EnvInfo { number: self.block.base.header.number, author: self.block.base.header.author.clone(), diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 86686cb4c..b5c5d5c0e 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -227,7 +227,7 @@ pub trait BlockChainClient : Sync + Send { /// Get `Some` gas limit of SOFT_FORK_BLOCK, or `None` if chain is not yet that long. fn dao_rescue_block_gas_limit(&self, chain_hash: H256) -> Option { - const SOFT_FORK_BLOCK: u64 = 1775000; + const SOFT_FORK_BLOCK: u64 = 1800000; // shortcut if the canon chain is already known. if self.chain_info().best_block_number > SOFT_FORK_BLOCK + 1000 { return self.block_header(BlockID::Number(SOFT_FORK_BLOCK)).map(|header| HeaderView::new(&header).gas_limit()); From 3e7edb2665363f482ab909b54c49219d5104a897 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 24 Jun 2016 14:29:15 +0200 Subject: [PATCH 187/239] More cases --- parity/cli.rs | 4 ++-- parity/configuration.rs | 2 +- parity/main.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 0133ca0fb..12ec8344f 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -117,9 +117,9 @@ API and Console Options: [default: $HOME/.parity/dapps] --signer Enable Trusted Signer WebSocket endpoint used by - Signer UIs. Default if no command is specified. - --no-signer Disable Trusted Signer WebSocket endpoint used by Signer UIs. Default if run with ui command. + --no-signer Disable Trusted Signer WebSocket endpoint used by + Signer UIs. Default if no command is specified. --signer-port PORT Specify the port of Trusted Signer server [default: 8180]. --signer-path PATH Specify directory where Signer UIs tokens should diff --git a/parity/configuration.rs b/parity/configuration.rs index 925d2041c..d92e50a41 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -441,7 +441,7 @@ impl Configuration { } pub fn signer_port(&self) -> Option { - if !self.args.flag_signer { + if !self.signer_enabled() { None } else { Some(self.args.flag_signer_port) diff --git a/parity/main.rs b/parity/main.rs index 84f144396..7d39143cb 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -278,7 +278,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // Set up a signer let signer_server = signer::start(signer::Configuration { - enabled: deps_for_rpc_apis.signer_port.is_some(), + enabled: conf.signer_enabled(), port: conf.args.flag_signer_port, signer_path: conf.directories().signer, }, signer::Dependencies { From bf11fb66334a07082e01a5bebe142416f0d29a21 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 24 Jun 2016 16:12:15 +0200 Subject: [PATCH 188/239] Fix up selection. --- parity/cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/cli.rs b/parity/cli.rs index a612d0877..98fb6eac0 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -152,7 +152,7 @@ Footprint Options: off. auto uses last used value of this option (off if it does not exist) [default: auto]. --pruning METHOD Configure pruning of the state/storage trie. METHOD - may be one of auto, archive, fast, basic, light: + may be one of auto, archive, fast: archive - keep all state trie data. No pruning. fast - maintain journal overlay. Fast but 50MB used. auto - use the method most recently synced or From 92bc21ba9c4442ce882422ead048f2799b9109fc Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Fri, 24 Jun 2016 17:04:40 +0200 Subject: [PATCH 189/239] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 661adf5ed..53212b229 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ In a near-future release, it will be easy to install Dapps and use them through If you run into an issue while using parity, feel free to file one in this repository or hop on our [gitter chat room]([gitter-url]) to ask a question. We are glad to help! -Parity's current release is 1.1. You can download it at https://ethcore.io/parity.html or follow the instructions +Parity's current release is 1.2. You can download it at https://ethcore.io/parity.html or follow the instructions below to build from source. ---- From a9b757a75cb0cdb256c4cac48a3083ab26ad0a25 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Fri, 24 Jun 2016 17:27:43 +0200 Subject: [PATCH 190/239] Update install-parity.sh --- install-parity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install-parity.sh b/install-parity.sh index 7f165f450..eadf698db 100755 --- a/install-parity.sh +++ b/install-parity.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -PARITY_DEB_URL=https://github.com/ethcore/parity/releases/download/v1.1.0/parity_linux_1.1.0-0_amd64.deb +PARITY_DEB_URL=https://github.com/ethcore/parity/releases/download/v1.2.0/parity_linux_1.2.0-0_amd64.deb function run_installer() From 8cc349bcb035969de99d29cc9b37014ba31ebc7a Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Sat, 25 Jun 2016 00:59:03 +0700 Subject: [PATCH 191/239] Update Dockerfile Update CentOS Dockerfile [ci skip] --- docker/centos/Dockerfile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docker/centos/Dockerfile b/docker/centos/Dockerfile index 5ce61129f..56015422c 100644 --- a/docker/centos/Dockerfile +++ b/docker/centos/Dockerfile @@ -2,24 +2,26 @@ FROM centos:latest WORKDIR /build # install tools and dependencies RUN yum -y update&& \ - yum install -y git make gcc-c++ gcc file + yum install -y git make gcc-c++ gcc file binutils # install rustup RUN curl -sSf https://static.rust-lang.org/rustup.sh -o rustup.sh &&\ ls&&\ sh rustup.sh -s -- --disable-sudo # show backtraces ENV RUST_BACKTRACE 1 +# set compiler ENV CXX g++ ENV CC gcc +# show tools RUN rustc -vV && \ cargo -V && \ gcc -v &&\ g++ -v -# git clone parity +# build parity RUN git clone https://github.com/ethcore/parity && \ cd parity&&\ ls -a&&\ cargo build --release --verbose && \ ls /build/parity/target/release/parity && \ - file /build/parity/target/release/parity && \ + strip /build/parity/target/release/parity RUN file /build/parity/target/release/parity From 102626f2c253c3346ad12cceaa80b01c24b6e2c6 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Sat, 25 Jun 2016 01:57:29 +0700 Subject: [PATCH 192/239] Update Ubuntu Dockerfile Update Ubuntu Dockerfile [ci skip] --- docker/ubuntu/Dockerfile | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/docker/ubuntu/Dockerfile b/docker/ubuntu/Dockerfile index 10477e01f..9999909c3 100644 --- a/docker/ubuntu/Dockerfile +++ b/docker/ubuntu/Dockerfile @@ -1,12 +1,13 @@ FROM ubuntu:14.04 - +WORKDIR /build # install tools and dependencies RUN apt-get update && \ - apt-get install -y \ - g++ \ - curl \ - git \ - make + apt-get install -y \ + g++ \ + curl \ + git \ + file \ + binutils # install rustup RUN curl https://sh.rustup.rs -sSf | sh -s -- -y @@ -17,7 +18,16 @@ ENV PATH /root/.cargo/bin:$PATH # show backtraces ENV RUST_BACKTRACE 1 +# show tools +RUN rustc -vV && \ +cargo -V && \ +gcc -v &&\ +g++ -v + # build parity RUN git clone https://github.com/ethcore/parity && \ - cd parity && \ - cargo build --release + 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 From a109a4a72baec509c47f7ed1e055639de4893dba Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Sat, 25 Jun 2016 02:03:36 +0700 Subject: [PATCH 193/239] Update Ubuntu-jit Dockerfile Update Ubuntu-jit Dockerfile [ci skip] --- docker/ubuntu-jit/Dockerfile | 55 +++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/docker/ubuntu-jit/Dockerfile b/docker/ubuntu-jit/Dockerfile index 37ef90d4e..89c38cee7 100644 --- a/docker/ubuntu-jit/Dockerfile +++ b/docker/ubuntu-jit/Dockerfile @@ -1,31 +1,33 @@ FROM ubuntu:14.04 - +WORKDIR /build # install tools and dependencies RUN apt-get update && \ - apt-get install -y \ - # make - build-essential \ - # add-apt-repository - software-properties-common \ - curl \ - wget \ - git \ - g++ \ - # evmjit dependencies - zlib1g-dev \ - libedit-dev + apt-get install -y \ + # make + build-essential \ + # add-apt-repository + software-properties-common \ + curl \ + wget \ + git \ + g++ \ + binutils \ + file \ + # evmjit dependencies + zlib1g-dev \ + libedit-dev -# cmake, llvm and rocksdb ppas. then update ppas +# cmake and llvm ppas. then update ppas RUN add-apt-repository -y "ppa:george-edison55/cmake-3.x" && \ - add-apt-repository "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main" && \ - apt-get update && \ - apt-get install -y --force-yes cmake llvm-3.7-dev + add-apt-repository "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.7 main" && \ + apt-get update && \ + apt-get install -y --force-yes cmake llvm-3.7-dev # install evmjit RUN git clone https://github.com/debris/evmjit && \ - cd evmjit && \ - mkdir build && cd build && \ - cmake .. && make && make install && cd + cd evmjit && \ + mkdir build && cd build && \ + cmake .. && make && make install && cd # install rustup RUN curl https://sh.rustup.rs -sSf | sh -s -- -y @@ -36,7 +38,16 @@ ENV PATH /root/.cargo/bin:$PATH # show backtraces ENV RUST_BACKTRACE 1 +# show tools +RUN rustc -vV && \ +cargo -V && \ +gcc -v &&\ +g++ -v + # build parity RUN git clone https://github.com/ethcore/parity && \ - cd parity && \ - cargo build --release --features ethcore/jit + cd parity && \ + cargo build --release --features ethcore/jit --verbose && \ + ls /build/parity/target/release/parity && \ + strip /build/parity/target/release/parity +RUN file /build/parity/target/release/parity From 4fd0a951127bfbcc4471c3b5288251702b28d4ad Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Sat, 25 Jun 2016 02:58:06 +0700 Subject: [PATCH 194/239] Update Ubuntu-arm Dockerfile Update Ubuntu-arm Dockerfile [ci skip] --- docker/ubuntu-arm/Dockerfile | 51 +++++++++++++++++------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/docker/ubuntu-arm/Dockerfile b/docker/ubuntu-arm/Dockerfile index fd77f182e..fab325e5e 100644 --- a/docker/ubuntu-arm/Dockerfile +++ b/docker/ubuntu-arm/Dockerfile @@ -2,11 +2,11 @@ FROM ubuntu:14.04 WORKDIR /build # install tools and dependencies RUN apt-get -y update && \ - apt-get install -y --force-yes --no-install-recommends \ - curl git make g++ gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf \ - libc6-dev-armhf-cross wget file ca-certificates \ - binutils-arm-linux-gnueabihf \ - && \ + apt-get install -y --force-yes --no-install-recommends \ + curl git make g++ gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf \ + libc6-dev-armhf-cross wget file ca-certificates \ + binutils-arm-linux-gnueabihf \ + && \ apt-get clean # install rustup @@ -18,33 +18,30 @@ ENV PATH /root/.cargo/bin:$PATH ENV RUST_TARGETS="arm-unknown-linux-gnueabihf" # multirust add arm--linux-gnuabhf toolchain -RUN rustup target add stable arm-unknown-linux-gnueabihf +RUN rustup target add armv7-unknown-linux-gnueabihf # show backtraces ENV RUST_BACKTRACE 1 + # set compilers ENV CXX arm-linux-gnueabihf-g++ ENV CC arm-linux-gnueabihf-gcc + +# show tools + RUN rustc -vV && \ + cargo -V && \ + gcc -v &&\ + g++ -v + # build parity RUN git clone https://github.com/ethcore/parity && \ - cd parity && \ - git checkout master && \ - wget https://github.com/nix-rust/nix/archive/v0.5.0.tar.gz && \ - tar -xf v0.5.0.tar.gz && \ - rm -rf v0.5.0.tar.gz && \ - wget https://github.com/thkaw/mio/archive/v0.5.x.tar.gz && \ - tar -xf v0.5.x.tar.gz && \ - rm -rf v0.5.x.tar.gz && \ - mkdir -p .cargo && \ - echo 'paths = ["nix-0.5.0","mio-0.5.x"]\n\ - [target.arm-unknown-linux-gnueabihf]\n\ - linker = "arm-linux-gnueabihf-gcc"\n'\ - >>.cargo/config && \ - cat .cargo/config && \ - rustc -vV && \ - cargo -V && \ - cargo build --target arm-unknown-linux-gnueabihf --release --verbose && \ - ls /build/parity/target/arm-unknown-linux-gnueabihf/release/parity && \ - file /build/parity/target/arm-unknown-linux-gnueabihf/release/parity && \ - /usr/bin/arm-linux-gnueabihf-strip /build/parity/target/arm-unknown-linux-gnueabihf/release/parity -RUN file /build/parity/target/arm-unknown-linux-gnueabihf/release/parity + cd parity && \ + mkdir -p .cargo && \ + echo '[target.armv7-unknown-linux-gnueabihf]\n\ + linker = "arm-linux-gnueabihf-gcc"\n'\ + >>.cargo/config && \ + cat .cargo/config && \ + cargo build --target armv7-unknown-linux-gnueabihf --release --verbose && \ + ls /build/parity/target/armv7-unknown-linux-gnueabihf/release/parity && \ + /usr/bin/arm-linux-gnueabihf-strip /build/parity/target/armv7-unknown-linux-gnueabihf/release/parity +RUN file /build/parity/target/armv7-unknown-linux-gnueabihf/release/parity From ab0d280232d34864b5653866e975d77fad41ddb6 Mon Sep 17 00:00:00 2001 From: "Denis S. Soldatov aka General-Beck" Date: Sat, 25 Jun 2016 03:51:05 +0700 Subject: [PATCH 195/239] Create Dockerfile ubuntu-aarch64 Create Dockerfile ubuntu-aarch64 [ci skip] --- docker/ubuntu-aarch64/Dockerfile | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 docker/ubuntu-aarch64/Dockerfile diff --git a/docker/ubuntu-aarch64/Dockerfile b/docker/ubuntu-aarch64/Dockerfile new file mode 100644 index 000000000..3212f84d0 --- /dev/null +++ b/docker/ubuntu-aarch64/Dockerfile @@ -0,0 +1,47 @@ +FROM ubuntu:14.04 +WORKDIR /build +# install tools and dependencies +RUN apt-get -y update && \ + apt-get install -y --force-yes --no-install-recommends \ + curl git make g++ gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \ + libc6-arm64-cross libc6-dev-arm64-cross wget file ca-certificates \ + binutils-aarch64-linux-gnu \ + && \ + apt-get clean + +# install rustup +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y + +# rustup directory +ENV PATH /root/.cargo/bin:$PATH + +ENV RUST_TARGETS="aarch64-unknown-linux-gnu" + +# multirust add arm--linux-gnuabhf toolchain +RUN rustup target add aarch64-unknown-linux-gnu + +# show backtraces +ENV RUST_BACKTRACE 1 + +# set compilers +ENV CXX aarch64-linux-gnu-g++ +ENV CC aarch64-linux-gnu-gcc + +# show tools + RUN rustc -vV && \ + cargo -V && \ + gcc -v &&\ + g++ -v + +# build parity +RUN git clone https://github.com/ethcore/parity && \ + cd parity && \ + mkdir -p .cargo && \ + echo '[target.aarch64-unknown-linux-gnu]\n\ + linker = "aarch64-linux-gnu-gcc"\n'\ + >>.cargo/config && \ + cat .cargo/config && \ + cargo build --target aarch64-unknown-linux-gnu --release --verbose && \ + ls /build/parity/target/aarch64-unknown-linux-gnu/release/parity && \ + /usr/bin/aarch64-linux-gnu-strip /build/parity/target/aarch64-unknown-linux-gnu/release/parity +RUN file /build/parity/target/aarch64-unknown-linux-gnu/release/parity From a72d8ee0e7659c2f604be2530e9ca70dbf3b4341 Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Sat, 25 Jun 2016 10:32:05 +0200 Subject: [PATCH 196/239] v1.3.0 (#1421) --- Cargo.lock | 86 +++++++++++++++++++++--------------------- Cargo.toml | 2 +- dapps/Cargo.toml | 2 +- db/Cargo.toml | 2 +- devtools/Cargo.toml | 2 +- ethash/Cargo.toml | 2 +- ethcore/Cargo.toml | 2 +- evmjit/Cargo.toml | 2 +- ipc/codegen/Cargo.toml | 2 +- ipc/nano/Cargo.toml | 2 +- ipc/rpc/Cargo.toml | 2 +- nsis/installer.nsi | 2 +- rpc/Cargo.toml | 2 +- rpc/rpctest/Cargo.toml | 2 +- signer/Cargo.toml | 2 +- sync/Cargo.toml | 2 +- util/Cargo.toml | 2 +- 17 files changed, 59 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4c9c4171..e75e1bc76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "parity" -version = "1.2.0" +version = "1.3.0" dependencies = [ "ansi_term 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", @@ -8,16 +8,16 @@ dependencies = [ "daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.6.80 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.2.0", - "ethcore-dapps 1.2.0", - "ethcore-devtools 1.2.0", - "ethcore-ipc 1.2.0", - "ethcore-ipc-codegen 1.2.0", - "ethcore-ipc-nano 1.2.0", - "ethcore-rpc 1.2.0", - "ethcore-signer 1.2.0", - "ethcore-util 1.2.0", - "ethsync 1.2.0", + "ethcore 1.3.0", + "ethcore-dapps 1.3.0", + "ethcore-devtools 1.3.0", + "ethcore-ipc 1.3.0", + "ethcore-ipc-codegen 1.3.0", + "ethcore-ipc-nano 1.3.0", + "ethcore-rpc 1.3.0", + "ethcore-signer 1.3.0", + "ethcore-util 1.3.0", + "ethsync 1.3.0", "fdlimit 0.1.0", "hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "json-ipc-server 0.2.3 (git+https://github.com/ethcore/json-ipc-server.git)", @@ -238,7 +238,7 @@ dependencies = [ [[package]] name = "ethash" -version = "1.2.0" +version = "1.3.0" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -247,17 +247,17 @@ dependencies = [ [[package]] name = "ethcore" -version = "1.2.0" +version = "1.3.0" dependencies = [ "bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 1.2.0", - "ethcore-devtools 1.2.0", - "ethcore-ipc 1.2.0", - "ethcore-ipc-codegen 1.2.0", - "ethcore-util 1.2.0", + "ethash 1.3.0", + "ethcore-devtools 1.3.0", + "ethcore-ipc 1.3.0", + "ethcore-ipc-codegen 1.3.0", + "ethcore-util 1.3.0", "ethjson 0.1.0", "ethstore 0.1.0", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -273,11 +273,11 @@ dependencies = [ [[package]] name = "ethcore-dapps" -version = "1.2.0" +version = "1.3.0" dependencies = [ "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-rpc 1.2.0", - "ethcore-util 1.2.0", + "ethcore-rpc 1.3.0", + "ethcore-util 1.3.0", "hyper 0.9.3 (git+https://github.com/ethcore/hyper)", "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", @@ -297,24 +297,24 @@ dependencies = [ [[package]] name = "ethcore-devtools" -version = "1.2.0" +version = "1.3.0" dependencies = [ "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethcore-ipc" -version = "1.2.0" +version = "1.3.0" dependencies = [ - "ethcore-devtools 1.2.0", - "ethcore-util 1.2.0", + "ethcore-devtools 1.3.0", + "ethcore-util 1.3.0", "nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)", "semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethcore-ipc-codegen" -version = "1.2.0" +version = "1.3.0" dependencies = [ "aster 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "quasi 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -325,9 +325,9 @@ dependencies = [ [[package]] name = "ethcore-ipc-nano" -version = "1.2.0" +version = "1.3.0" dependencies = [ - "ethcore-ipc 1.2.0", + "ethcore-ipc 1.3.0", "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "nanomsg 0.5.1 (git+https://github.com/ethcore/nanomsg.rs.git)", @@ -335,15 +335,15 @@ dependencies = [ [[package]] name = "ethcore-rpc" -version = "1.2.0" +version = "1.3.0" dependencies = [ "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 1.2.0", - "ethcore 1.2.0", - "ethcore-devtools 1.2.0", - "ethcore-util 1.2.0", + "ethash 1.3.0", + "ethcore 1.3.0", + "ethcore-devtools 1.3.0", + "ethcore-util 1.3.0", "ethjson 0.1.0", - "ethsync 1.2.0", + "ethsync 1.3.0", "json-ipc-server 0.2.3 (git+https://github.com/ethcore/json-ipc-server.git)", "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", @@ -358,12 +358,12 @@ dependencies = [ [[package]] name = "ethcore-signer" -version = "1.2.0" +version = "1.3.0" dependencies = [ "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-rpc 1.2.0", - "ethcore-util 1.2.0", + "ethcore-rpc 1.3.0", + "ethcore-util 1.3.0", "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "parity-minimal-sysui 0.1.0 (git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git)", @@ -374,7 +374,7 @@ dependencies = [ [[package]] name = "ethcore-util" -version = "1.2.0" +version = "1.3.0" dependencies = [ "arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "bigint 0.1.0", @@ -384,7 +384,7 @@ dependencies = [ "elastic-array 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)", - "ethcore-devtools 1.2.0", + "ethcore-devtools 1.3.0", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "igd 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -412,7 +412,7 @@ dependencies = [ name = "ethjson" version = "0.1.0" dependencies = [ - "ethcore-util 1.2.0", + "ethcore-util 1.3.0", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -449,12 +449,12 @@ dependencies = [ [[package]] name = "ethsync" -version = "1.2.0" +version = "1.3.0" dependencies = [ "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.2.0", - "ethcore-util 1.2.0", + "ethcore 1.3.0", + "ethcore-util 1.3.0", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 6c4b54d46..9493af006 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore client." name = "parity" -version = "1.2.0" +version = "1.3.0" license = "GPL-3.0" authors = ["Ethcore "] build = "build.rs" diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index 4cc4bc472..0476e9919 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity Dapps crate" name = "ethcore-dapps" -version = "1.2.0" +version = "1.3.0" license = "GPL-3.0" authors = ["Ethcore "] build = "build.rs" diff --git a/devtools/Cargo.toml b/devtools/Cargo.toml index 1bccfc9d0..c82a4bb6a 100644 --- a/devtools/Cargo.toml +++ b/devtools/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore development/test/build tools" homepage = "http://ethcore.io" license = "GPL-3.0" name = "ethcore-devtools" -version = "1.2.0" +version = "1.3.0" authors = ["Ethcore "] [dependencies] diff --git a/ethash/Cargo.toml b/ethash/Cargo.toml index cfa1fa9b7..94a714d55 100644 --- a/ethash/Cargo.toml +++ b/ethash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethash" -version = "1.2.0" +version = "1.3.0" authors = ["arkpar "] build = "build.rs" diff --git a/evmjit/Cargo.toml b/evmjit/Cargo.toml index 39725a0de..001656f1b 100644 --- a/evmjit/Cargo.toml +++ b/evmjit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "evmjit" -version = "1.2.0" +version = "1.3.0" authors = ["debris "] [lib] diff --git a/ipc/codegen/Cargo.toml b/ipc/codegen/Cargo.toml index b7111c4af..4d83b65e1 100644 --- a/ipc/codegen/Cargo.toml +++ b/ipc/codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethcore-ipc-codegen" -version = "1.2.0" +version = "1.3.0" authors = ["Nikolay Volf"] license = "GPL-3.0" description = "Macros to auto-generate implementations for ipc call" diff --git a/ipc/nano/Cargo.toml b/ipc/nano/Cargo.toml index fc229d393..4096ed443 100644 --- a/ipc/nano/Cargo.toml +++ b/ipc/nano/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethcore-ipc-nano" -version = "1.2.0" +version = "1.3.0" authors = ["Nikolay Volf "] license = "GPL-3.0" diff --git a/ipc/rpc/Cargo.toml b/ipc/rpc/Cargo.toml index 0bc9b05ef..ab00523de 100644 --- a/ipc/rpc/Cargo.toml +++ b/ipc/rpc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ethcore-ipc" -version = "1.2.0" +version = "1.3.0" authors = ["Nikolay Volf "] license = "GPL-3.0" diff --git a/nsis/installer.nsi b/nsis/installer.nsi index fffcc1dd9..c93234850 100644 --- a/nsis/installer.nsi +++ b/nsis/installer.nsi @@ -3,7 +3,7 @@ !define COMPANYNAME "Ethcore" !define DESCRIPTION "Fast, light, robust Ethereum implementation" !define VERSIONMAJOR 1 -!define VERSIONMINOR 2 +!define VERSIONMINOR 3 !define VERSIONBUILD 0 !addplugindir .\ diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 60b8236e1..21a59ad50 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore jsonrpc" name = "ethcore-rpc" -version = "1.2.0" +version = "1.3.0" license = "GPL-3.0" authors = ["Ethcore "] diff --git a/signer/Cargo.toml b/signer/Cargo.toml index 0cae9b0a5..e7d6dcd27 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -3,7 +3,7 @@ description = "Ethcore Trusted Signer" homepage = "http://ethcore.io" license = "GPL-3.0" name = "ethcore-signer" -version = "1.2.0" +version = "1.3.0" authors = ["Ethcore "] build = "build.rs" diff --git a/sync/Cargo.toml b/sync/Cargo.toml index 8bb0d37c9..10edcd0ed 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Ethcore blockchain sync" name = "ethsync" -version = "1.2.0" +version = "1.3.0" license = "GPL-3.0" authors = ["Ethcore "] build = "build.rs" From 2574d000a3950d4038b6d18c1f7fa17d919c6f7e Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 25 Jun 2016 14:35:43 +0200 Subject: [PATCH 197/239] Revert the rescuedao extradata. --- parity/configuration.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index d92e50a41..012e41a53 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -130,14 +130,10 @@ impl Configuration { } pub fn extra_data(&self) -> Bytes { - if !self.args.flag_dont_help_rescue_dao { - (b"rescuedao"[..]).to_owned() - } else { - match self.args.flag_extradata.as_ref().or(self.args.flag_extra_data.as_ref()) { - Some(ref x) if x.len() <= 32 => x.as_bytes().to_owned(), - None => version_data(), - Some(ref x) => { die!("{}: Extra data must be at most 32 characters.", x); } - } + match self.args.flag_extradata.as_ref().or(self.args.flag_extra_data.as_ref()) { + Some(ref x) if x.len() <= 32 => x.as_bytes().to_owned(), + None => version_data(), + Some(ref x) => { die!("{}: Extra data must be at most 32 characters.", x); } } } From 24000016759cf19f046e1182bd3949d0ab23cd91 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sat, 25 Jun 2016 23:13:34 +0200 Subject: [PATCH 198/239] More conservative settings for rocksdb. (#1440) --- util/src/kvdb.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index c1be5c691..67a7243de 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -20,10 +20,10 @@ use std::default::Default; use rocksdb::{DB, Writable, WriteBatch, IteratorMode, DBVector, DBIterator, IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; -const DB_FILE_SIZE_BASE: u64 = 128 * 1024 * 1024; -const DB_FILE_SIZE_MULTIPLIER: i32 = 1; -const DB_BACKGROUND_FLUSHES: i32 = 4; -const DB_BACKGROUND_COMPACTIONS: i32 = 4; +const DB_FILE_SIZE_BASE: u64 = 16 * 1024 * 1024; +const DB_FILE_SIZE_MULTIPLIER: i32 = 5; +const DB_BACKGROUND_FLUSHES: i32 = 2; +const DB_BACKGROUND_COMPACTIONS: i32 = 2; /// Write transaction. Batches a sequence of put/delete operations for efficiency. pub struct DBTransaction { From 516b01532594db9af1a7a3532532b8af8b6b2c13 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Sun, 26 Jun 2016 22:02:17 +0200 Subject: [PATCH 199/239] Don't mine without --author (#1436) Requires --author to be set before mining is allowed to happen. --- parity/cli.rs | 8 ++++---- parity/configuration.rs | 11 ++++++----- parity/main.rs | 2 +- rpc/src/v1/impls/eth.rs | 12 ++++++++++++ rpc/src/v1/impls/mod.rs | 3 ++- 5 files changed, 25 insertions(+), 11 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index b5d16e92b..29333fe9a 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -128,6 +128,9 @@ API and Console Options: output on start up. This will prevent it. Sealing/Mining Options: + --author ADDRESS Specify the block author (aka "coinbase") address + for sending block rewards from sealed blocks. + NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION. --force-sealing Force the node to author new blocks as if it were always sealing/mining. --usd-per-tx USD Amount of USD to be paid for a basic transaction @@ -141,9 +144,6 @@ Sealing/Mining Options: block [default: 3141592]. --gas-cap GAS A cap on how large we will raise the gas limit per block due to transaction volume [default: 3141592]. - --author ADDRESS Specify the block author (aka "coinbase") address - for sending block rewards from sealed blocks - [default: 0037a6b811ffeb6e072da21179d11b1406371c63]. --extra-data STRING Specify a custom extra-data for authored blocks, no more than 32 characters. --tx-limit LIMIT Limit of transactions kept in the queue (waiting to @@ -283,7 +283,7 @@ pub struct Args { pub flag_signer_path: String, pub flag_no_token: bool, pub flag_force_sealing: bool, - pub flag_author: String, + pub flag_author: Option, pub flag_usd_per_tx: String, pub flag_usd_per_eth: String, pub flag_gas_floor_target: String, diff --git a/parity/configuration.rs b/parity/configuration.rs index 012e41a53..43a7fcd3c 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -67,11 +67,12 @@ impl Configuration { self.args.flag_maxpeers.unwrap_or(self.args.flag_peers) as u32 } - pub fn author(&self) -> Address { - let d = self.args.flag_etherbase.as_ref().unwrap_or(&self.args.flag_author); - Address::from_str(clean_0x(d)).unwrap_or_else(|_| { - die!("{}: Invalid address for --author. Must be 40 hex characters, with or without the 0x at the beginning.", d) - }) + pub fn author(&self) -> Option
{ + self.args.flag_etherbase.as_ref() + .or(self.args.flag_author.as_ref()) + .map(|d| Address::from_str(clean_0x(d)).unwrap_or_else(|_| { + die!("{}: Invalid address for --author. Must be 40 hex characters, with or without the 0x at the beginning.", d) + })) } pub fn gas_floor_target(&self) -> U256 { diff --git a/parity/main.rs b/parity/main.rs index 7d39143cb..cecb0e0a1 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -209,7 +209,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // Miner let miner = Miner::with_accounts(conf.args.flag_force_sealing, conf.spec(), account_service.clone()); - miner.set_author(conf.author()); + miner.set_author(conf.author().unwrap_or(Default::default())); miner.set_gas_floor_target(conf.gas_floor_target()); miner.set_gas_ceil_target(conf.gas_ceil_target()); miner.set_extra_data(conf.extra_data()); diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index f3a59b698..9b1f06416 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -225,6 +225,14 @@ fn no_work_err() -> Error { } } +fn no_author_err() -> Error { + Error { + code: ErrorCode::ServerError(error_codes::NO_AUTHOR_CODE), + message: "Author not configured. Run parity with --author to configure.".into(), + data: None + } +} + impl Eth for EthClient where C: MiningBlockChainClient + 'static, S: SyncProvider + 'static, @@ -474,6 +482,10 @@ impl Eth for EthClient where } let miner = take_weak!(self.miner); + if miner.author().is_zero() { + warn!(target: "miner", "Cannot give work package - no author is configured. Use --author to configure!"); + return Err(no_author_err()) + } miner.map_sealing_work(client.deref(), |b| { let pow_hash = b.hash(); let target = Ethash::difficulty_to_boundary(b.block().header().difficulty()); diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index 66a5b9c58..fdd2de8fa 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -68,7 +68,8 @@ mod error_codes { // NOTE [ToDr] Codes from [-32099, -32000] pub const UNSUPPORTED_REQUEST_CODE: i64 = -32000; pub const NO_WORK_CODE: i64 = -32001; - pub const UNKNOWN_ERROR: i64 = -32002; + pub const NO_AUTHOR_CODE: i64 = -32002; + pub const UNKNOWN_ERROR: i64 = -32009; pub const TRANSACTION_ERROR: i64 = -32010; pub const ACCOUNT_LOCKED: i64 = -32020; pub const SIGNER_DISABLED: i64 = -32030; From 2bd0c5ebcbc797d03ed21cb59f65555631295638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 26 Jun 2016 22:48:09 +0200 Subject: [PATCH 200/239] Unwrap or default --- parity/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/main.rs b/parity/main.rs index b5468ede9..62262758d 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -209,7 +209,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) // Miner let miner = Miner::new(conf.args.flag_force_sealing, conf.spec(), Some(account_service.clone())); - miner.set_author(conf.author().unwrap_or(Default::default())); + miner.set_author(conf.author().unwrap_or_default()); miner.set_gas_floor_target(conf.gas_floor_target()); miner.set_gas_ceil_target(conf.gas_ceil_target()); miner.set_extra_data(conf.extra_data()); From 593d947fcdb771903965f94f3b289166bbc0db23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 26 Jun 2016 23:41:31 +0200 Subject: [PATCH 201/239] Using stable version of ws-rs --- Cargo.lock | 44 +++++++++----------------------------------- signer/Cargo.toml | 2 +- 2 files changed, 10 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e75e1bc76..3984098be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -164,7 +164,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -292,7 +292,7 @@ dependencies = [ "serde_codegen 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "syntex 0.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -369,7 +369,7 @@ dependencies = [ "parity-minimal-sysui 0.1.0 (git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.5.1 (git+https://github.com/ethcore/ws-rs.git)", + "ws 0.5.0 (git+https://github.com/ethcore/ws-rs.git?branch=stable)", ] [[package]] @@ -562,7 +562,7 @@ dependencies = [ "traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -712,22 +712,6 @@ dependencies = [ "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "mio" -version = "0.5.0" -source = "git+https://github.com/carllerche/mio.git#f4aa49a9d2c4507fb33a4533d5238e0365f67c99" -dependencies = [ - "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.5.0-pre (git+https://github.com/carllerche/nix-rust?rev=c4257f8a76)", - "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "mio" version = "0.5.1" @@ -801,15 +785,6 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "nix" -version = "0.5.0-pre" -source = "git+https://github.com/carllerche/nix-rust?rev=c4257f8a76#c4257f8a76b69b0d2e9a001d83e4bef67c03b23f" -dependencies = [ - "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nix" version = "0.5.0" @@ -1408,7 +1383,7 @@ dependencies = [ [[package]] name = "url" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1472,16 +1447,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ws" -version = "0.5.1" -source = "git+https://github.com/ethcore/ws-rs.git#d5745df8ea1ab82cd2b844f15ca1ac759e7aa9f5" +version = "0.5.0" +source = "git+https://github.com/ethcore/ws-rs.git?branch=stable#abd219709b9dd504a7101d9ba772e0df523fe534" dependencies = [ "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.0 (git+https://github.com/carllerche/mio.git)", + "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/signer/Cargo.toml b/signer/Cargo.toml index e7d6dcd27..912b10875 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -15,7 +15,7 @@ rand = "0.3.14" jsonrpc-core = "2.0" log = "0.3" env_logger = "0.3" -ws = { git = "https://github.com/ethcore/ws-rs.git" } +ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "stable" } ethcore-util = { path = "../util" } ethcore-rpc = { path = "../rpc" } parity-minimal-sysui = { git = "https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git" } From 4f1f33d1b88468be7824800e29f9bc0c2b6fb3db Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Jun 2016 09:20:38 +0200 Subject: [PATCH 202/239] Retweak BASE and MULTIPLIER in rocksdb config. (#1445) --- util/src/kvdb.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 67a7243de..e472305a7 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -20,8 +20,8 @@ use std::default::Default; use rocksdb::{DB, Writable, WriteBatch, IteratorMode, DBVector, DBIterator, IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; -const DB_FILE_SIZE_BASE: u64 = 16 * 1024 * 1024; -const DB_FILE_SIZE_MULTIPLIER: i32 = 5; +const DB_FILE_SIZE_BASE: u64 = 32 * 1024 * 1024; +const DB_FILE_SIZE_MULTIPLIER: i32 = 2; const DB_BACKGROUND_FLUSHES: i32 = 2; const DB_BACKGROUND_COMPACTIONS: i32 = 2; From c21550a6638f233149cfa9932cb856108aacf865 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 27 Jun 2016 10:39:37 +0200 Subject: [PATCH 203/239] Updated to latest hyper with patched mio --- Cargo.lock | 24 +++++++++++------------- dapps/src/endpoint.rs | 6 +++--- dapps/src/lib.rs | 13 ++++++++++--- dapps/src/page/handler.rs | 2 +- dapps/src/router/auth.rs | 14 +++++++------- dapps/src/router/mod.rs | 6 +++--- dapps/src/router/redirect.rs | 2 +- 7 files changed, 36 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e75e1bc76..5ce00b4b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -278,7 +278,7 @@ dependencies = [ "clippy 0.0.77 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-rpc 1.3.0", "ethcore-util 1.3.0", - "hyper 0.9.3 (git+https://github.com/ethcore/hyper)", + "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -546,16 +546,15 @@ dependencies = [ [[package]] name = "hyper" -version = "0.9.3" -source = "git+https://github.com/ethcore/hyper#dbb4cf160ebf242f7f0459d547c40e9e6877ccf4" +version = "0.9.4" +source = "git+https://github.com/ethcore/hyper#7ccfcb2aa7e6aa6300efa8cebd6a0e6ce55582ea" dependencies = [ "cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rotor 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rotor 0.6.3 (git+https://github.com/ethcore/rotor)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "spmc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -630,9 +629,9 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "5.1.0" -source = "git+https://github.com/ethcore/jsonrpc-http-server.git#0c99d308bc15e8fae50642eff77a3e1fd7610652" +source = "git+https://github.com/ethcore/jsonrpc-http-server.git#e59c2fbaca499620874023755cb91f05b858ffe7" dependencies = [ - "hyper 0.9.3 (git+https://github.com/ethcore/hyper)", + "hyper 0.9.4 (git+https://github.com/ethcore/hyper)", "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -731,7 +730,7 @@ dependencies = [ [[package]] name = "mio" version = "0.5.1" -source = "git+https://github.com/ethcore/mio?branch=v0.5.x#1fc881771fb8c2517317b4f805d7b88235be422b" +source = "git+https://github.com/ethcore/mio?branch=v0.5.x#3842d3b250ffd7bd9b16f9586b875ddcbac2b0dd" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1057,7 +1056,7 @@ dependencies = [ [[package]] name = "quick-error" -version = "0.2.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1121,12 +1120,11 @@ dependencies = [ [[package]] name = "rotor" version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/ethcore/rotor#e63d45137b2eb66d1e085a7c6321a5db8b187576" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", + "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/dapps/src/endpoint.rs b/dapps/src/endpoint.rs index 592bc7f8f..075211e58 100644 --- a/dapps/src/endpoint.rs +++ b/dapps/src/endpoint.rs @@ -42,11 +42,11 @@ pub struct EndpointInfo { pub trait Endpoint : Send + Sync { fn info(&self) -> Option<&EndpointInfo> { None } - fn to_handler(&self, path: EndpointPath) -> Box>; + fn to_handler(&self, path: EndpointPath) -> Box + Send>; } pub type Endpoints = BTreeMap>; -pub type Handler = server::Handler; +pub type Handler = server::Handler + Send; pub struct ContentHandler { content: String, @@ -65,7 +65,7 @@ impl ContentHandler { } impl server::Handler for ContentHandler { - fn on_request(&mut self, _request: server::Request) -> Next { + fn on_request(&mut self, _request: server::Request) -> Next { Next::write() } diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index a7fbd5963..22b075afd 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -132,9 +132,16 @@ impl Server { special.clone(), authorization.clone(), )) - .map(|l| Server { - server: Some(l), - panic_handler: panic_handler, + .map(|(l, srv)| { + + ::std::thread::spawn(move || { + srv.run(); + }); + + Server { + server: Some(l), + panic_handler: panic_handler, + } }) .map_err(ServerError::from) } diff --git a/dapps/src/page/handler.rs b/dapps/src/page/handler.rs index 5167c85c8..c3ec354e0 100644 --- a/dapps/src/page/handler.rs +++ b/dapps/src/page/handler.rs @@ -86,7 +86,7 @@ impl PageHandler { } impl server::Handler for PageHandler { - fn on_request(&mut self, req: server::Request) -> Next { + fn on_request(&mut self, req: server::Request) -> Next { self.file = match *req.uri() { RequestUri::AbsolutePath(ref path) => { self.app.file(&self.extract_path(path)) diff --git a/dapps/src/router/auth.rs b/dapps/src/router/auth.rs index d9933b51c..9459d0719 100644 --- a/dapps/src/router/auth.rs +++ b/dapps/src/router/auth.rs @@ -27,13 +27,13 @@ pub enum Authorized { /// Authorization was successful. Yes, /// Unsuccessful authorization. Handler for further work is returned. - No(Box>), + No(Box + Send>), } /// Authorization interface pub trait Authorization : Send + Sync { /// Checks if authorization is valid. - fn is_authorized(&self, req: &server::Request)-> Authorized; + fn is_authorized(&self, req: &server::Request)-> Authorized; } /// HTTP Basic Authorization handler @@ -45,13 +45,13 @@ pub struct HttpBasicAuth { pub struct NoAuth; impl Authorization for NoAuth { - fn is_authorized(&self, _req: &server::Request)-> Authorized { + fn is_authorized(&self, _req: &server::Request)-> Authorized { Authorized::Yes } } impl Authorization for HttpBasicAuth { - fn is_authorized(&self, req: &server::Request) -> Authorized { + fn is_authorized(&self, req: &server::Request) -> Authorized { let auth = self.check_auth(&req); match auth { @@ -89,7 +89,7 @@ impl HttpBasicAuth { self.users.get(&username.to_owned()).map_or(false, |pass| pass == password) } - fn check_auth(&self, req: &server::Request) -> Access { + fn check_auth(&self, req: &server::Request) -> Access { match req.headers().get::>() { Some(&header::Authorization( header::Basic { ref username, password: Some(ref password) } @@ -105,7 +105,7 @@ pub struct UnauthorizedHandler { } impl server::Handler for UnauthorizedHandler { - fn on_request(&mut self, _request: server::Request) -> Next { + fn on_request(&mut self, _request: server::Request) -> Next { Next::write() } @@ -141,7 +141,7 @@ impl server::Handler for UnauthorizedHandler { pub struct AuthRequiredHandler; impl server::Handler for AuthRequiredHandler { - fn on_request(&mut self, _request: server::Request) -> Next { + fn on_request(&mut self, _request: server::Request) -> Next { Next::write() } diff --git a/dapps/src/router/mod.rs b/dapps/src/router/mod.rs index 12738d79d..0cb0d38d0 100644 --- a/dapps/src/router/mod.rs +++ b/dapps/src/router/mod.rs @@ -49,12 +49,12 @@ pub struct Router { endpoints: Arc, special: Arc>>, authorization: Arc, - handler: Box>, + handler: Box + Send>, } impl server::Handler for Router { - fn on_request(&mut self, req: server::Request) -> Next { + fn on_request(&mut self, req: server::Request) -> Next { // Check authorization let auth = self.authorization.is_authorized(&req); @@ -124,7 +124,7 @@ impl Router { } } -fn extract_url(req: &server::Request) -> Option { +fn extract_url(req: &server::Request) -> Option { match *req.uri() { uri::RequestUri::AbsoluteUri(ref url) => { match Url::from_generic_url(url.clone()) { diff --git a/dapps/src/router/redirect.rs b/dapps/src/router/redirect.rs index 6faf9d0c8..6d738115d 100644 --- a/dapps/src/router/redirect.rs +++ b/dapps/src/router/redirect.rs @@ -33,7 +33,7 @@ impl Redirection { } impl server::Handler for Redirection { - fn on_request(&mut self, _request: server::Request) -> Next { + fn on_request(&mut self, _request: server::Request) -> Next { Next::write() } From e4763e90bc16f46ecfa81c438e95616460eb22e2 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 27 Jun 2016 13:03:34 +0200 Subject: [PATCH 204/239] compaction struct and helpers --- util/src/kvdb.rs | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index e472305a7..5d82dd6d6 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -20,8 +20,6 @@ use std::default::Default; use rocksdb::{DB, Writable, WriteBatch, IteratorMode, DBVector, DBIterator, IndexType, Options, DBCompactionStyle, BlockBasedOptions, Direction}; -const DB_FILE_SIZE_BASE: u64 = 32 * 1024 * 1024; -const DB_FILE_SIZE_MULTIPLIER: i32 = 2; const DB_BACKGROUND_FLUSHES: i32 = 2; const DB_BACKGROUND_COMPACTIONS: i32 = 2; @@ -53,6 +51,36 @@ impl DBTransaction { } } +/// Compaction profile for the database settings +pub struct CompactionProfile { + /// L0-L1 target file size + pub initial_file_size: u64, + /// L2-LN target file size multiplier + pub file_size_multiplier: i32, + /// rate limiter for background flushes and compactions, bytes/sec, if any + pub write_rate_limit: Option, +} + +impl CompactionProfile { + /// Default profile suitable for most storage + pub fn default() -> CompactionProfile { + CompactionProfile { + initial_file_size: 32 * 1024 * 1024, + file_size_multiplier: 2, + write_rate_limit: None, + } + } + + /// Slow hdd compaction profile + pub fn hdd(&self) -> CompactionProfile { + CompactionProfile { + initial_file_size: 192 * 1024 * 1024, + file_size_multiplier: 1, + write_rate_limit: Some(128 * 1024 * 1024), + } + } +} + /// Database configuration pub struct DatabaseConfig { /// Optional prefix size in bytes. Allows lookup by partial key. @@ -61,6 +89,8 @@ pub struct DatabaseConfig { pub max_open_files: i32, /// Cache-size pub cache_size: Option, + /// Compaction profile + pub compaction: CompactionProfile, } impl DatabaseConfig { @@ -72,6 +102,11 @@ impl DatabaseConfig { max_open_files: -1, } } + + pub fn compaction(mut self, profile: CompactionProfile) -> Self { + self.compaction = profile; + self + } } impl Default for DatabaseConfig { From 07098fd16fdc0c9e09dfcee9472e2b71fd5ad1ef Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 27 Jun 2016 13:14:40 +0200 Subject: [PATCH 205/239] extra helpers for prefix --- util/src/kvdb.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 5d82dd6d6..10c7a3276 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -76,7 +76,7 @@ impl CompactionProfile { CompactionProfile { initial_file_size: 192 * 1024 * 1024, file_size_multiplier: 1, - write_rate_limit: Some(128 * 1024 * 1024), + write_rate_limit: Some(8 * 1024 * 1024), } } } @@ -100,6 +100,7 @@ impl DatabaseConfig { cache_size: Some(cache_size), prefix_size: None, max_open_files: -1, + compaction: CompactionProfile::default(), } } @@ -107,6 +108,11 @@ impl DatabaseConfig { self.compaction = profile; self } + + pub fn prefix(mut self, prefix_size: usize) -> Self { + self.prefix_size = Some(prefix_size); + self + } } impl Default for DatabaseConfig { @@ -115,6 +121,7 @@ impl Default for DatabaseConfig { cache_size: None, prefix_size: None, max_open_files: -1, + compaction: CompactionProfile::default(), } } } @@ -146,13 +153,18 @@ impl Database { /// Open database file. Creates if it does not exist. pub fn open(config: &DatabaseConfig, path: &str) -> Result { let mut opts = Options::new(); - try!(opts.set_parsed_options("rate_limiter_bytes_per_sec=256000000")); + if let Some(rate_limit) = config.compaction.write_rate_limit { + try!(opts.set_parsed_options(&format!("rate_limiter_bytes_per_sec={}", rate_limit))); + } opts.set_max_open_files(config.max_open_files); opts.create_if_missing(true); opts.set_use_fsync(false); + + // compaction settings opts.set_compaction_style(DBCompactionStyle::DBUniversalCompaction); - opts.set_target_file_size_base(DB_FILE_SIZE_BASE); - opts.set_target_file_size_multiplier(DB_FILE_SIZE_MULTIPLIER); + opts.set_target_file_size_base(config.compaction.initial_file_size); + opts.set_target_file_size_multiplier(config.compaction.file_size_multiplier); + opts.set_max_background_flushes(DB_BACKGROUND_FLUSHES); opts.set_max_background_compactions(DB_BACKGROUND_COMPACTIONS); if let Some(cache_size) = config.cache_size { From 627b67db0acdeafbc1041036a6e32f7f067dd226 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 27 Jun 2016 13:23:50 +0200 Subject: [PATCH 206/239] jdb to new settings config --- util/src/journaldb/archivedb.rs | 9 ++------- util/src/journaldb/earlymergedb.rs | 9 ++------- util/src/journaldb/mod.rs | 11 ++++++----- util/src/journaldb/overlayrecentdb.rs | 13 ++++--------- util/src/journaldb/refcounteddb.rs | 9 ++------- util/src/kvdb.rs | 2 ++ 6 files changed, 18 insertions(+), 35 deletions(-) diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index c7f6b92fa..8372f99de 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -43,13 +43,8 @@ const DB_VERSION : u32 = 0x103; impl ArchiveDB { /// Create a new instance from file - pub fn new(path: &str, cache_size: Option) -> ArchiveDB { - let opts = DatabaseConfig { - // this must match account_db prefix - prefix_size: Some(DB_PREFIX_LEN), - max_open_files: 256, - cache_size: cache_size, - }; + pub fn new(path: &str, config: DatabaseConfig) -> ArchiveDB { + let opts = config.prefix(DB_PREFIX_LEN); let backing = Database::open(&opts, path).unwrap_or_else(|e| { panic!("Error opening state db: {}", e); }); diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs index 71959fa35..5c267679b 100644 --- a/util/src/journaldb/earlymergedb.rs +++ b/util/src/journaldb/earlymergedb.rs @@ -73,13 +73,8 @@ const PADDING : [u8; 10] = [ 0u8; 10 ]; impl EarlyMergeDB { /// Create a new instance from file - pub fn new(path: &str, cache_size: Option) -> EarlyMergeDB { - let opts = DatabaseConfig { - // this must match account_db prefix - prefix_size: Some(DB_PREFIX_LEN), - max_open_files: 256, - cache_size: cache_size, - }; + pub fn new(path: &str, config: DatabaseConfig) -> EarlyMergeDB { + let opts = config.prefix(DB_PREFIX_LEN); let backing = Database::open(&opts, path).unwrap_or_else(|e| { panic!("Error opening state db: {}", e); }); diff --git a/util/src/journaldb/mod.rs b/util/src/journaldb/mod.rs index 973dd9eb0..4715273dd 100644 --- a/util/src/journaldb/mod.rs +++ b/util/src/journaldb/mod.rs @@ -17,6 +17,7 @@ //! `JournalDB` interface and implementation. use common::*; +use kvdb::DatabaseConfig; /// Export the journaldb module. pub mod traits; @@ -71,12 +72,12 @@ impl fmt::Display for Algorithm { } /// Create a new `JournalDB` trait object. -pub fn new(path: &str, algorithm: Algorithm, cache_size: Option) -> Box { +pub fn new(path: &str, algorithm: Algorithm, config: DatabaseConfig) -> Box { match algorithm { - Algorithm::Archive => Box::new(archivedb::ArchiveDB::new(path, cache_size)), - Algorithm::EarlyMerge => Box::new(earlymergedb::EarlyMergeDB::new(path, cache_size)), - Algorithm::OverlayRecent => Box::new(overlayrecentdb::OverlayRecentDB::new(path, cache_size)), - Algorithm::RefCounted => Box::new(refcounteddb::RefCountedDB::new(path, cache_size)), + Algorithm::Archive => Box::new(archivedb::ArchiveDB::new(path, config)), + Algorithm::EarlyMerge => Box::new(earlymergedb::EarlyMergeDB::new(path, config)), + Algorithm::OverlayRecent => Box::new(overlayrecentdb::OverlayRecentDB::new(path, config)), + Algorithm::RefCounted => Box::new(refcounteddb::RefCountedDB::new(path, config)), } } diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs index 158b771fb..09ec3da88 100644 --- a/util/src/journaldb/overlayrecentdb.rs +++ b/util/src/journaldb/overlayrecentdb.rs @@ -98,18 +98,13 @@ const PADDING : [u8; 10] = [ 0u8; 10 ]; impl OverlayRecentDB { /// Create a new instance from file - pub fn new(path: &str, cache_size: Option) -> OverlayRecentDB { - Self::from_prefs(path, cache_size) + pub fn new(path: &str, config: DatabaseConfig) -> OverlayRecentDB { + Self::from_prefs(path, config) } /// Create a new instance from file - pub fn from_prefs(path: &str, cache_size: Option) -> OverlayRecentDB { - let opts = DatabaseConfig { - // this must match account_db prefix - prefix_size: Some(DB_PREFIX_LEN), - max_open_files: 256, - cache_size: cache_size, - }; + pub fn from_prefs(path: &str, config: DatabaseConfig) -> OverlayRecentDB { + let opts = config.prefix(DB_PREFIX_LEN); let backing = Database::open(&opts, path).unwrap_or_else(|e| { panic!("Error opening state db: {}", e); }); diff --git a/util/src/journaldb/refcounteddb.rs b/util/src/journaldb/refcounteddb.rs index fc7da1541..d2092b2a6 100644 --- a/util/src/journaldb/refcounteddb.rs +++ b/util/src/journaldb/refcounteddb.rs @@ -46,13 +46,8 @@ const PADDING : [u8; 10] = [ 0u8; 10 ]; impl RefCountedDB { /// Create a new instance given a `backing` database. - pub fn new(path: &str, cache_size: Option) -> RefCountedDB { - let opts = DatabaseConfig { - // this must match account_db prefix - prefix_size: Some(DB_PREFIX_LEN), - max_open_files: 256, - cache_size: cache_size, - }; + pub fn new(path: &str, config: DatabaseConfig) -> RefCountedDB { + let opts = config.prefix(DB_PREFIX_LEN); let backing = Database::open(&opts, path).unwrap_or_else(|e| { panic!("Error opening state db: {}", e); }); diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 10c7a3276..9cf4313f2 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -104,11 +104,13 @@ impl DatabaseConfig { } } + /// Modify the compaction profile pub fn compaction(mut self, profile: CompactionProfile) -> Self { self.compaction = profile; self } + /// Modify the prefix of the db pub fn prefix(mut self, prefix_size: usize) -> Self { self.prefix_size = Some(prefix_size); self From 2e5d5f12dd68cdb1f3f8702d905af33fd95346a6 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 27 Jun 2016 13:58:12 +0200 Subject: [PATCH 207/239] ethcore client config --- ethcore/src/client/client.rs | 13 +++++++++++-- ethcore/src/client/config.rs | 15 +++++++++++++++ ethcore/src/client/mod.rs | 4 ++-- parity/cli.rs | 9 ++++++++- parity/configuration.rs | 7 +++++++ util/src/kvdb.rs | 2 +- 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 4ccfb7360..b69558d52 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -38,7 +38,7 @@ use filter::Filter; use log_entry::LocalizedLogEntry; use block_queue::{BlockQueue, BlockQueueInfo}; use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; -use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, MiningBlockChainClient, TraceFilter, CallAnalytics}; +use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, DatabaseCompactionProfile, BlockChainClient, MiningBlockChainClient, TraceFilter, CallAnalytics}; use client::Error as ClientError; use env_info::EnvInfo; use executive::{Executive, Executed, TransactOptions, contract_address}; @@ -146,10 +146,19 @@ impl Client where V: Verifier { let chain = Arc::new(BlockChain::new(config.blockchain, &gb, &path)); let tracedb = Arc::new(try!(TraceDB::new(config.tracing, &path, chain.clone()))); + let mut state_db_config = match config.db_cache_size { + None => DatabaseConfig::default(), + Some(cache_size) => DatabaseConfig::with_cache(cache_size), + }; + + if config.db_compaction == DatabaseCompactionProfile::HDD { + state_db_config = state_db_config.compaction(CompactionProfile::hdd()); + } + let mut state_db = journaldb::new( &append_path(&path, "state"), config.pruning, - config.db_cache_size); + state_db_config); if state_db.is_empty() && spec.ensure_db_good(state_db.as_hashdb_mut()) { state_db.commit(0, &spec.genesis_header().hash(), None).expect("Error commiting genesis state to state DB"); diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index 6353e324f..7d7f8e524 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -20,6 +20,19 @@ pub use trace::{Config as TraceConfig, Switch}; pub use evm::VMType; use util::journaldb; +/// Client state db compaction profile +#[derive(Debug, PartialEq)] +pub enum DatabaseCompactionProfile { + /// Default compaction profile + Default, + /// HDD or other slow storage io compaction profile + HDD, +} + +impl Default for DatabaseCompactionProfile { + fn default() -> Self { DatabaseCompactionProfile::Default } +} + /// Client configuration. Includes configs for all sub-systems. #[derive(Debug, Default)] pub struct ClientConfig { @@ -37,4 +50,6 @@ pub struct ClientConfig { pub name: String, /// State db cache-size if not default pub db_cache_size: Option, + /// State db compaction profile + pub db_compaction: DatabaseCompactionProfile, } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 80625ad85..4ba22c1ed 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -23,7 +23,7 @@ mod test_client; mod trace; pub use self::client::*; -pub use self::config::{ClientConfig, BlockQueueConfig, BlockChainConfig, Switch, VMType}; +pub use self::config::{ClientConfig, DatabaseCompactionProfile, BlockQueueConfig, BlockChainConfig, Switch, VMType}; pub use self::error::Error; pub use types::ids::*; pub use self::test_client::{TestBlockChainClient, EachBlockWith}; @@ -245,7 +245,7 @@ pub trait BlockChainClient : Sync + Send { } else { None } - } + } } /// Extended client interface used for mining diff --git a/parity/cli.rs b/parity/cli.rs index 29333fe9a..c42719cc6 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -170,7 +170,13 @@ Footprint Options: --cache MEGABYTES Set total amount of discretionary memory to use for the entire system, overrides other cache and queue options. - --db-cache-size MB Database cache size. + +Database Options: + --db-cache-size MB Database cache size. Default if not specified. + --db-compaction TYPE Database compaction type. TYPE may be one of default, hdd + default - suitable for ssd backing storage/fast hdd + hdd - sutable for slow storage + [default: default]. Import/Export Options: --from BLOCK Export from block BLOCK, which may be an index or @@ -323,6 +329,7 @@ pub struct Args { pub flag_ipcpath: Option, pub flag_ipcapi: Option, pub flag_db_cache_size: Option, + pub flag_db_compaction: String, } pub fn print_version() { diff --git a/parity/configuration.rs b/parity/configuration.rs index 43a7fcd3c..8a11ebf4d 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -278,6 +278,13 @@ impl Configuration { // forced state db cache size if provided client_config.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 4)); + // compaction profile + client_config.db_compaction_profile = match self.args.flag_db_compaction.as_str() { + "default" => DatabaseCompactionProfile::Default, + "hdd" => DatabaseCompactionProfile::HDD, + _ => { die!("Invalid compaction profile given (--db-compaction argument), expected hdd/default."); } + }; + if self.args.flag_jitvm { client_config.vm_type = VMType::jit().unwrap_or_else(|| die!("Parity built without jit vm.")) } diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 9cf4313f2..4e7bdb26c 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -72,7 +72,7 @@ impl CompactionProfile { } /// Slow hdd compaction profile - pub fn hdd(&self) -> CompactionProfile { + pub fn hdd() -> CompactionProfile { CompactionProfile { initial_file_size: 192 * 1024 * 1024, file_size_multiplier: 1, From f9f25fd14767491b4ff888313b257f7b25d44467 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 27 Jun 2016 14:25:50 +0200 Subject: [PATCH 208/239] cli config --- parity/configuration.rs | 6 +++--- parity/migration.rs | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index 8a11ebf4d..ad2578478 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -26,7 +26,7 @@ use die::*; use util::*; use ethcore::account_provider::AccountProvider; use util::network_settings::NetworkSettings; -use ethcore::client::{append_path, get_db_path, ClientConfig, Switch, VMType}; +use ethcore::client::{append_path, get_db_path, ClientConfig, DatabaseCompactionProfile, Switch, VMType}; use ethcore::ethereum; use ethcore::spec::Spec; use ethsync::SyncConfig; @@ -227,7 +227,7 @@ impl Configuration { let mut latest_era = None; let jdb_types = [journaldb::Algorithm::Archive, journaldb::Algorithm::EarlyMerge, journaldb::Algorithm::OverlayRecent, journaldb::Algorithm::RefCounted]; for i in jdb_types.into_iter() { - let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i, None); + let db = journaldb::new(&append_path(&get_db_path(Path::new(&self.path()), *i, spec.genesis_header().hash()), "state"), *i, kvdb::DatabaseConfig::default()); trace!(target: "parity", "Looking for best DB: {} at {:?}", i, db.latest_era()); match (latest_era, db.latest_era()) { (Some(best), Some(this)) if best >= this => {} @@ -279,7 +279,7 @@ impl Configuration { client_config.db_cache_size = self.args.flag_db_cache_size.and_then(|cs| Some(cs / 4)); // compaction profile - client_config.db_compaction_profile = match self.args.flag_db_compaction.as_str() { + client_config.db_compaction = match self.args.flag_db_compaction.as_str() { "default" => DatabaseCompactionProfile::Default, "hdd" => DatabaseCompactionProfile::HDD, _ => { die!("Invalid compaction profile given (--db-compaction argument), expected hdd/default."); } diff --git a/parity/migration.rs b/parity/migration.rs index 4198f7ed0..df2c2116f 100644 --- a/parity/migration.rs +++ b/parity/migration.rs @@ -20,7 +20,7 @@ use std::io::{Read, Write, Error as IoError, ErrorKind}; use std::path::PathBuf; use std::fmt::{Display, Formatter, Error as FmtError}; use util::migration::{Manager as MigrationManager, Config as MigrationConfig, MigrationIterator}; -use util::kvdb::{Database, DatabaseConfig}; +use util::kvdb::{Database, DatabaseConfig, CompactionProfile}; use ethcore::migrations; /// Database is assumed to be at default version, when no version file is found. @@ -163,6 +163,7 @@ fn migrate_database(version: u32, path: PathBuf, migrations: MigrationManager) - prefix_size: None, max_open_files: 64, cache_size: None, + compaction: CompactionProfile::default(), }; // open old database From 6859152c212fdd26d11e45e9a8bb6593767530fa Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 27 Jun 2016 15:59:45 +0200 Subject: [PATCH 209/239] Fixed losing queued blocks on ancient block error (#1453) --- ethcore/src/client/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 4ccfb7360..16422250a 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -296,7 +296,7 @@ impl Client where V: Verifier { let closed_block = self.check_and_close_block(&block); if let Err(_) = closed_block { invalid_blocks.insert(header.hash()); - break; + continue; } imported_blocks.push(header.hash()); From 1fdbfa14adfa4c80888fb58ce0f41c42efb846db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 27 Jun 2016 16:00:16 +0200 Subject: [PATCH 210/239] Handle errors when starting parity (#1451) --- signer/src/ws_server/mod.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/signer/src/ws_server/mod.rs b/signer/src/ws_server/mod.rs index b6b7c15f7..d2d838b2c 100644 --- a/signer/src/ws_server/mod.rs +++ b/signer/src/ws_server/mod.rs @@ -110,7 +110,17 @@ impl Server { // Spawn a thread with event loop let handle = thread::spawn(move || { ph.catch_panic(move || { - ws.listen(addr).unwrap() + match ws.listen(addr).map_err(ServerError::from) { + Err(ServerError::IoError(io)) => die(format!( + "Signer: Could not start listening on specified address. Make sure that no other instance is running on Signer's port. Details: {:?}", + io + )), + Err(any_error) => die(format!( + "Signer: Unknown error occured when starting Signer. Details: {:?}", + any_error + )), + Ok(server) => server, + } }).unwrap() }); @@ -123,7 +133,11 @@ impl Server { // TODO [ToDr] Some better structure here for messages. broadcaster.send("new_message").unwrap(); }).expect("It's the only place we are running start_listening. It shouldn't fail."); - broadcaster.shutdown().expect("Broadcaster should close gently.") + let res = broadcaster.shutdown(); + + if let Err(e) = res { + warn!("Signer: Broadcaster was not closed cleanly. Details: {:?}", e); + } }).unwrap() }); @@ -148,5 +162,11 @@ impl Drop for Server { self.queue.finish(); self.broadcaster_handle.take().unwrap().join().unwrap(); self.handle.take().unwrap().join().unwrap(); + } } + +fn die(msg: String) -> ! { + println!("ERROR: {}", msg); + std::process::exit(1); +} From 044bf5511a200cc405fdd3662ac979847f5090fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 27 Jun 2016 10:56:26 +0200 Subject: [PATCH 211/239] Fixing HTTP file serving on ws-rs --- Cargo.lock | 10 ++++----- signer/Cargo.toml | 4 ++-- signer/src/ws_server/session.rs | 36 ++++++++++++++++----------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3984098be..db7632f3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -366,10 +366,10 @@ dependencies = [ "ethcore-util 1.3.0", "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-minimal-sysui 0.1.0 (git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git)", + "parity-minimal-sysui 0.2.0 (git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.5.0 (git+https://github.com/ethcore/ws-rs.git?branch=stable)", + "ws 0.5.0 (git+https://github.com/ethcore/ws-rs.git?branch=testing)", ] [[package]] @@ -934,8 +934,8 @@ dependencies = [ [[package]] name = "parity-minimal-sysui" -version = "0.1.0" -source = "git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git#cc5ea4bd786982f0509a8d3d5deb4217c659af85" +version = "0.2.0" +source = "git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git#996c9f3f0ebedc727aecb4ece191154e956ae292" [[package]] name = "phf" @@ -1448,7 +1448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ws" version = "0.5.0" -source = "git+https://github.com/ethcore/ws-rs.git?branch=stable#abd219709b9dd504a7101d9ba772e0df523fe534" +source = "git+https://github.com/ethcore/ws-rs.git?branch=testing#4623c51aedaea1ca0ecb34bd1a1aacb651760954" dependencies = [ "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/signer/Cargo.toml b/signer/Cargo.toml index 912b10875..e26ffd99e 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -15,10 +15,10 @@ rand = "0.3.14" jsonrpc-core = "2.0" log = "0.3" env_logger = "0.3" -ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "stable" } +ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "testing" } ethcore-util = { path = "../util" } ethcore-rpc = { path = "../rpc" } -parity-minimal-sysui = { git = "https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git" } +parity-minimal-sysui = { git = "https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git", version = "0.2.0" } clippy = { version = "0.0.77", optional = true} diff --git a/signer/src/ws_server/session.rs b/signer/src/ws_server/session.rs index b635f1524..4b2eb808c 100644 --- a/signer/src/ws_server/session.rs +++ b/signer/src/ws_server/session.rs @@ -62,6 +62,19 @@ fn auth_is_valid(codes: &Path, protocols: ws::Result>) -> bool { } } +fn add_headers(mut response: ws::Response, mime: &str) -> ws::Response { + let content_len = format!("{}", response.len()); + { + let mut headers = response.headers_mut(); + headers.push(("X-Frame-Options".into(), b"SAMEORIGIN".to_vec())); + headers.push(("Server".into(), b"Parity/SignerUI".to_vec())); + headers.push(("Content-Length".into(), content_len.as_bytes().to_vec())); + headers.push(("Content-Type".into(), mime.as_bytes().to_vec())); + headers.push(("Connection".into(), b"close".to_vec())); + } + response +} + pub struct Session { out: ws::Sender, self_origin: String, @@ -98,26 +111,13 @@ impl ws::Handler for Session { } // Otherwise try to serve a page. - sysui::handle(req.resource()) + Ok(sysui::handle(req.resource()) .map_or_else( - // return error - || Ok(ws::Response::not_found("Page not found".into())), + // return 404 not found + || add_headers(ws::Response::not_found("Not found".into()), "text/plain"), // or serve the file - |f| { - let content_len = format!("{}", f.content.as_bytes().len()); - let mut res = ws::Response::ok(f.content.into()); - { - let mut headers = res.headers_mut(); - headers.push(("Server".into(), b"Parity/SignerUI".to_vec())); - headers.push(("Connection".into(), b"Closed".to_vec())); - headers.push(("Content-Length".into(), content_len.as_bytes().to_vec())); - headers.push(("Content-Type".into(), f.mime.as_bytes().to_vec())); - if !f.safe_to_embed { - headers.push(("X-Frame-Options".into(), b"SAMEORIGIN".to_vec())); - } - } - Ok(res) - }) + |f| add_headers(ws::Response::ok(f.content.into()), &f.mime) + )) } fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> { From 222404f801dabc4518699e269fe66f236dd0f877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 27 Jun 2016 16:10:37 +0200 Subject: [PATCH 212/239] Updating WS version --- Cargo.lock | 6 +++--- signer/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db7632f3f..d67177173 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -369,7 +369,7 @@ dependencies = [ "parity-minimal-sysui 0.2.0 (git+https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.5.0 (git+https://github.com/ethcore/ws-rs.git?branch=testing)", + "ws 0.5.0 (git+https://github.com/ethcore/ws-rs.git?branch=stable)", ] [[package]] @@ -1448,11 +1448,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ws" version = "0.5.0" -source = "git+https://github.com/ethcore/ws-rs.git?branch=testing#4623c51aedaea1ca0ecb34bd1a1aacb651760954" +source = "git+https://github.com/ethcore/ws-rs.git?branch=stable#e2452450c830618aed30db02e63f3a68710cc40e" dependencies = [ "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.5.1 (git+https://github.com/ethcore/mio?branch=v0.5.x)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/signer/Cargo.toml b/signer/Cargo.toml index e26ffd99e..4ef8bb03e 100644 --- a/signer/Cargo.toml +++ b/signer/Cargo.toml @@ -15,7 +15,7 @@ rand = "0.3.14" jsonrpc-core = "2.0" log = "0.3" env_logger = "0.3" -ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "testing" } +ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "stable" } ethcore-util = { path = "../util" } ethcore-rpc = { path = "../rpc" } parity-minimal-sysui = { git = "https://github.com/ethcore/parity-dapps-minimal-sysui-rs.git", version = "0.2.0" } From 6c1802e412ab8de8bf9f0001a3a4280fce9c226a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Jun 2016 17:23:54 +0200 Subject: [PATCH 213/239] Allow configuration of when to reseal blocks. --- ethcore/src/miner/miner.rs | 37 +++++++++++++++++++++++++++++-------- ethcore/src/miner/mod.rs | 2 +- parity/cli.rs | 7 +++++++ parity/configuration.rs | 16 ++++++++++++++++ parity/main.rs | 2 +- rpc/src/v1/tests/eth.rs | 12 ++++++++++-- sync/src/lib.rs | 2 +- 7 files changed, 65 insertions(+), 13 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 401a5314a..1e76e6288 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -29,6 +29,27 @@ use spec::Spec; use engine::Engine; use miner::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; +/// Configures the behaviour of the miner. +#[derive(Debug)] +pub struct MinerOptions { + /// Force the miner to reseal, even when nobody has asked for work. + pub force_sealing: bool, + /// Reseal on receipt of new external transactions. + pub reseal_on_external_tx: bool, + /// Reseal on receipt of new local transactions. + pub reseal_on_own_tx: bool, +} + +impl Default for MinerOptions { + fn default() -> Self { + MinerOptions { + force_sealing: false, + reseal_on_external_tx: true, + reseal_on_own_tx: true, + } + } +} + /// Keeps track of transactions using priority queue and holds currently mined block. pub struct Miner { // NOTE [ToDr] When locking always lock in this order! @@ -36,7 +57,7 @@ pub struct Miner { sealing_work: Mutex>, // for sealing... - force_sealing: bool, + options: MinerOptions, sealing_enabled: AtomicBool, sealing_block_last_request: Mutex, gas_range_target: RwLock<(U256, U256)>, @@ -52,7 +73,7 @@ impl Miner { pub fn with_spec(spec: Spec) -> Miner { Miner { transaction_queue: Mutex::new(TransactionQueue::new()), - force_sealing: false, + options: Default::default(), sealing_enabled: AtomicBool::new(false), sealing_block_last_request: Mutex::new(0), sealing_work: Mutex::new(UsingQueue::new(5)), @@ -65,11 +86,11 @@ impl Miner { } /// Creates new instance of miner - pub fn new(force_sealing: bool, spec: Spec, accounts: Option>) -> Arc { + pub fn new(options: MinerOptions, spec: Spec, accounts: Option>) -> Arc { Arc::new(Miner { transaction_queue: Mutex::new(TransactionQueue::new()), - force_sealing: force_sealing, - sealing_enabled: AtomicBool::new(force_sealing), + sealing_enabled: AtomicBool::new(options.force_sealing), + options: options, sealing_block_last_request: Mutex::new(0), sealing_work: Mutex::new(UsingQueue::new(5)), gas_range_target: RwLock::new((U256::zero(), U256::zero())), @@ -385,7 +406,7 @@ impl MinerService for Miner { .map(|tx| transaction_queue.add(tx, &fetch_account, TransactionOrigin::External)) .collect() }; - if !results.is_empty() { + if !results.is_empty() && self.options.reseal_on_external_tx { self.update_sealing(chain); } results @@ -420,7 +441,7 @@ impl MinerService for Miner { import }; - if imported.is_ok() { + if imported.is_ok() && self.options.reseal_on_own_tx { // Make sure to do it after transaction is imported and lock is droped. // We need to create pending block and enable sealing let prepared = self.enable_and_prepare_sealing(chain); @@ -494,7 +515,7 @@ impl MinerService for Miner { let current_no = chain.chain_info().best_block_number; let has_local_transactions = self.transaction_queue.lock().unwrap().has_local_pending_transactions(); let last_request = *self.sealing_block_last_request.lock().unwrap(); - let should_disable_sealing = !self.force_sealing + let should_disable_sealing = !self.options.force_sealing && !has_local_transactions && current_no > last_request && current_no - last_request > SEALING_TIMEOUT_IN_BLOCKS; diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 6e415a602..8a282490c 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -47,7 +47,7 @@ mod external; mod transaction_queue; pub use self::transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; -pub use self::miner::{Miner}; +pub use self::miner::{Miner, MinerOptions}; pub use self::external::{ExternalMiner, ExternalMinerService}; use std::collections::BTreeMap; diff --git a/parity/cli.rs b/parity/cli.rs index 29333fe9a..a3b3bb5df 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -133,6 +133,12 @@ Sealing/Mining Options: NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION. --force-sealing Force the node to author new blocks as if it were always sealing/mining. + --reseal-on-txs Specify which transactions should force the node + to reseal a block. One of: + none - never reseal on new transactions; + own - reseal only on a new local transaction; + ext - reseal only on a new external transaction; + all - reseal on all new transactions [default: all]. --usd-per-tx USD Amount of USD to be paid for a basic transaction [default: 0.005]. The minimum gas price is set accordingly. @@ -283,6 +289,7 @@ pub struct Args { pub flag_signer_path: String, pub flag_no_token: bool, pub flag_force_sealing: bool, + pub flag_reseal_on_txs: String, pub flag_author: Option, pub flag_usd_per_tx: String, pub flag_usd_per_eth: String, diff --git a/parity/configuration.rs b/parity/configuration.rs index 43a7fcd3c..39893622a 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -27,6 +27,7 @@ use util::*; use ethcore::account_provider::AccountProvider; use util::network_settings::NetworkSettings; use ethcore::client::{append_path, get_db_path, ClientConfig, Switch, VMType}; +use ethcore::miner::MinerOptions; use ethcore::ethereum; use ethcore::spec::Spec; use ethsync::SyncConfig; @@ -67,6 +68,21 @@ impl Configuration { self.args.flag_maxpeers.unwrap_or(self.args.flag_peers) as u32 } + pub fn miner_options(&self) -> MinerOptions { + let (own, ext) = match self.args.flag_reseal_on_txs.as_str() { + "none" => (false, false), + "own" => (true, false), + "ext" => (false, true), + "all" => (true, true), + x => die!("{}: Invalid value for --reseal option. Use --help for more information.", x) + }; + MinerOptions { + force_sealing: self.args.flag_force_sealing, + reseal_on_external_tx: ext, + reseal_on_own_tx: own, + } + } + pub fn author(&self) -> Option
{ self.args.flag_etherbase.as_ref() .or(self.args.flag_author.as_ref()) diff --git a/parity/main.rs b/parity/main.rs index 62262758d..e3c20caf4 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -208,7 +208,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) let account_service = Arc::new(conf.account_service()); // Miner - let miner = Miner::new(conf.args.flag_force_sealing, conf.spec(), Some(account_service.clone())); + let miner = Miner::new(conf.miner_options(), conf.spec(), Some(account_service.clone())); miner.set_author(conf.author().unwrap_or_default()); miner.set_gas_floor_target(conf.gas_floor_target()); miner.set_gas_ceil_target(conf.gas_ceil_target()); diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 6e2256e24..2ce482a90 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -24,7 +24,7 @@ use ethcore::spec::{Genesis, Spec}; use ethcore::block::Block; use ethcore::views::BlockView; use ethcore::ethereum; -use ethcore::miner::{MinerService, ExternalMiner, Miner}; +use ethcore::miner::{MinerOptions, MinerService, ExternalMiner, Miner}; use ethcore::account_provider::AccountProvider; use devtools::RandomTempPath; use util::Hashable; @@ -49,7 +49,15 @@ fn sync_provider() -> Arc { } fn miner_service(spec: Spec, accounts: Arc) -> Arc { - Miner::new(true, spec, Some(accounts)) + Miner::new( + MinerOptions { + force_sealing: true, + reseal_on_external_tx: true, + reseal_on_own_tx: true, + }, + spec, + Some(accounts) + ) } fn make_spec(chain: &BlockChain) -> Spec { diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 3f899c261..928496326 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -44,7 +44,7 @@ //! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap(); //! service.start().unwrap(); //! let dir = env::temp_dir(); -//! let miner = Miner::new(false, ethereum::new_frontier(true), None); +//! let miner = Miner::new(MinerOptions::default(), ethereum::new_frontier(true), None); //! let client = Client::new( //! ClientConfig::default(), //! ethereum::new_frontier(true), From 1667808ecb67dc0c45f51f83b3a95369b075643a Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Jun 2016 18:27:06 +0200 Subject: [PATCH 214/239] More miner options. - Optional limit for the amount of gas transactions may have; - option to restruct transactions returned/queried to only those which have been executed. --- ethcore/src/client/client.rs | 3 ++- ethcore/src/miner/miner.rs | 24 ++++++++++++++---------- ethcore/src/miner/transaction_queue.rs | 16 ++++++++++++++++ parity/cli.rs | 13 ++++++++++--- parity/configuration.rs | 14 ++++++++++++++ parity/main.rs | 2 +- 6 files changed, 57 insertions(+), 15 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 16422250a..2c4499e57 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -149,7 +149,8 @@ impl Client where V: Verifier { let mut state_db = journaldb::new( &append_path(&path, "state"), config.pruning, - config.db_cache_size); + config.db_cache_size + ); if state_db.is_empty() && spec.ensure_db_good(state_db.as_hashdb_mut()) { state_db.commit(0, &spec.genesis_header().hash(), None).expect("Error commiting genesis state to state DB"); diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 1e76e6288..e5ecff8c4 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -38,6 +38,11 @@ pub struct MinerOptions { pub reseal_on_external_tx: bool, /// Reseal on receipt of new local transactions. pub reseal_on_own_tx: bool, + /// Specify maximum amount of gas to bother considering for block insertion. + /// If `None`, then no limit. + pub max_tx_gas: Option, + /// Whether we should fallback to providing all the queue's transactions or just pending. + pub strict_valid_pending: bool, } impl Default for MinerOptions { @@ -46,6 +51,8 @@ impl Default for MinerOptions { force_sealing: false, reseal_on_external_tx: true, reseal_on_own_tx: true, + max_tx_gas: None, + strict_valid_pending: false, } } } @@ -112,7 +119,7 @@ impl Miner { trace!(target: "miner", "prepare_sealing: entering"); let (transactions, mut open_block) = { - let transactions = {self.transaction_queue.lock().unwrap().top_transactions()}; + let transactions = {self.transaction_queue.lock().unwrap().top_transactions_maybe_limit(&self.options.max_tx_gas)}; let mut sealing_work = self.sealing_work.lock().unwrap(); let best_hash = chain.best_block_header().sha3(); /* @@ -459,9 +466,8 @@ impl MinerService for Miner { let queue = self.transaction_queue.lock().unwrap(); match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { (true, Some(pending)) => pending.transactions().iter().map(|t| t.hash()).collect(), - _ => { - queue.pending_hashes() - } + _ if self.options.strict_valid_pending => Vec::new(), + _ => queue.pending_hashes(), } } @@ -469,9 +475,8 @@ impl MinerService for Miner { let queue = self.transaction_queue.lock().unwrap(); match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { (true, Some(pending)) => pending.transactions().iter().find(|t| &t.hash() == hash).cloned(), - _ => { - queue.find(hash) - } + _ if self.options.strict_valid_pending => None, + _ => queue.find(hash), } } @@ -485,9 +490,8 @@ impl MinerService for Miner { // TODO: should only use the sealing_work when it's current (it could be an old block) match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { (true, Some(pending)) => pending.transactions().clone(), - _ => { - queue.top_transactions() - } + _ if self.options.strict_valid_pending => Vec::new(), + _ => queue.top_transactions(), } } diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index b2ca31e0d..9159cc6b3 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -583,6 +583,22 @@ impl TransactionQueue { .collect() } + /// Returns top transactions from the queue ordered by priority with a maximum gas limit. + pub fn top_transactions_with_limit(&self, max_tx_gas: &U256) -> Vec { + self.current.by_priority + .iter() + .map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`")) + .filter_map(|t| if &t.transaction.gas <= max_tx_gas { Some(t.transaction.clone()) } else { None }) + .collect() + } + + /// Returns top transactions from the queue ordered by priority with a maximum gas limit. + pub fn top_transactions_maybe_limit(&self, max_tx_gas: &Option) -> Vec { + match *max_tx_gas { + None => self.top_transactions(), + Some(ref m) => self.top_transactions_with_limit(m), + } + } /// Returns hashes of all transactions from current, ordered by priority. pub fn pending_hashes(&self) -> Vec { self.current.by_priority diff --git a/parity/cli.rs b/parity/cli.rs index a3b3bb5df..3090e83c5 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -139,6 +139,11 @@ Sealing/Mining Options: own - reseal only on a new local transaction; ext - reseal only on a new external transaction; all - reseal on all new transactions [default: all]. + --max-tx-gas GAS Apply a limit of GAS as the maximum amount of gas + a single transaction may have for it to be mined. + --relay-validity REQ Requirements for relaying. REQ may be: + cheap - Relay only after cheap checks; + strict - Relay only once executed [default: cheap]. --usd-per-tx USD Amount of USD to be paid for a basic transaction [default: 0.005]. The minimum gas price is set accordingly. @@ -152,8 +157,8 @@ Sealing/Mining Options: block due to transaction volume [default: 3141592]. --extra-data STRING Specify a custom extra-data for authored blocks, no more than 32 characters. - --tx-limit LIMIT Limit of transactions kept in the queue (waiting to - be included in next block) [default: 1024]. + --tx-queue-size LIMIT Maxmimum amount of transactions in the queue (waiting + to be included in next block) [default: 1024]. Footprint Options: --tracing BOOL Indicates if full transaction tracing should be @@ -290,13 +295,15 @@ pub struct Args { pub flag_no_token: bool, pub flag_force_sealing: bool, pub flag_reseal_on_txs: String, + pub flag_max_tx_gas: Option, + pub flag_relay_validity: String, pub flag_author: Option, pub flag_usd_per_tx: String, pub flag_usd_per_eth: String, pub flag_gas_floor_target: String, pub flag_gas_cap: String, pub flag_extra_data: Option, - pub flag_tx_limit: usize, + pub flag_tx_queue_size: usize, pub flag_logging: Option, pub flag_version: bool, pub flag_from: String, diff --git a/parity/configuration.rs b/parity/configuration.rs index 39893622a..57c62f839 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -68,6 +68,14 @@ impl Configuration { self.args.flag_maxpeers.unwrap_or(self.args.flag_peers) as u32 } + fn decode_u256(d: &str, argument: &str) -> U256 { + U256::from_dec_str(d).unwrap_or_else(|_| + U256::from_str(clean_0x(d)).unwrap_or_else(|_| + die!("{}: Invalid numeric value for {}. Must be either a decimal or a hex number.", d, argument) + ) + ) + } + pub fn miner_options(&self) -> MinerOptions { let (own, ext) = match self.args.flag_reseal_on_txs.as_str() { "none" => (false, false), @@ -80,6 +88,12 @@ impl Configuration { force_sealing: self.args.flag_force_sealing, reseal_on_external_tx: ext, reseal_on_own_tx: own, + max_tx_gas: self.args.flag_max_tx_gas.as_ref().map(|d| Self::decode_u256(d, "--max-tx-gas")), + strict_valid_pending: match self.args.flag_relay_validity.as_str() { + "cheap" => false, + "strict" => true, + x => die!("{}: Invalid value for --relay-validity option. Use --help for more information.", x) + }, } } diff --git a/parity/main.rs b/parity/main.rs index e3c20caf4..047338bc8 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -214,7 +214,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig) miner.set_gas_ceil_target(conf.gas_ceil_target()); miner.set_extra_data(conf.extra_data()); miner.set_minimal_gas_price(conf.gas_price()); - miner.set_transactions_limit(conf.args.flag_tx_limit); + miner.set_transactions_limit(conf.args.flag_tx_queue_size); // Build client let mut service = ClientService::start( From 9f4bfd9e7a7a14b0873310810d105102d3c3b0ae Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Mon, 27 Jun 2016 18:47:50 +0200 Subject: [PATCH 215/239] fix tests --- ethcore/src/tests/helpers.rs | 4 +-- util/src/journaldb/archivedb.rs | 21 ++++++++-------- util/src/journaldb/earlymergedb.rs | 35 ++++++++++++++------------- util/src/journaldb/overlayrecentdb.rs | 35 ++++++++++++++------------- util/src/journaldb/refcounteddb.rs | 2 +- util/src/kvdb.rs | 8 +++--- 6 files changed, 54 insertions(+), 51 deletions(-) diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 1fefd5830..15b346919 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -303,7 +303,7 @@ pub fn generate_dummy_empty_blockchain() -> GuardedTempResult { pub fn get_temp_journal_db() -> GuardedTempResult> { let temp = RandomTempPath::new(); - let journal_db = journaldb::new(temp.as_str(), journaldb::Algorithm::EarlyMerge, None); + let journal_db = journaldb::new(temp.as_str(), journaldb::Algorithm::EarlyMerge, DatabaseConfig::default()); GuardedTempResult { _temp: temp, result: Some(journal_db) @@ -320,7 +320,7 @@ pub fn get_temp_state() -> GuardedTempResult { } pub fn get_temp_journal_db_in(path: &Path) -> Box { - journaldb::new(path.to_str().unwrap(), journaldb::Algorithm::EarlyMerge, None) + journaldb::new(path.to_str().unwrap(), journaldb::Algorithm::EarlyMerge, DatabaseConfig::default()) } pub fn get_temp_state_in(path: &Path) -> State { diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index 8372f99de..a01ed807f 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -70,7 +70,7 @@ impl ArchiveDB { fn new_temp() -> ArchiveDB { let mut dir = env::temp_dir(); dir.push(H32::random().hex()); - Self::new(dir.to_str().unwrap(), None) + Self::new(dir.to_str().unwrap(), DatabaseConfig::default()) } fn payload(&self, key: &H256) -> Option { @@ -182,6 +182,7 @@ mod tests { use super::*; use hashdb::*; use journaldb::traits::JournalDB; + use kvdb::DatabaseConfig; #[test] fn insert_same_in_fork() { @@ -323,7 +324,7 @@ mod tests { let bar = H256::random(); let foo = { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 let foo = jdb.insert(b"foo"); jdb.emplace(bar.clone(), b"bar".to_vec()); @@ -332,13 +333,13 @@ mod tests { }; { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.remove(&foo); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); } { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); assert!(jdb.contains(&foo)); assert!(jdb.contains(&bar)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); @@ -351,7 +352,7 @@ mod tests { dir.push(H32::random().hex()); let foo = { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 let foo = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); @@ -365,7 +366,7 @@ mod tests { }; { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.remove(&foo); jdb.commit(3, &b"3".sha3(), Some((2, b"2".sha3()))).unwrap(); assert!(jdb.contains(&foo)); @@ -380,7 +381,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); let (foo, _, _) = { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); @@ -395,7 +396,7 @@ mod tests { }; { - let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), None); + let mut jdb = ArchiveDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.contains(&foo)); } @@ -406,14 +407,14 @@ mod tests { let temp = ::devtools::RandomTempPath::new(); let key = { - let mut jdb = ArchiveDB::new(temp.as_str(), None); + let mut jdb = ArchiveDB::new(temp.as_str(), DatabaseConfig::default()); let key = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); key }; { - let jdb = ArchiveDB::new(temp.as_str(), None); + let jdb = ArchiveDB::new(temp.as_str(), DatabaseConfig::default()); let state = jdb.state(&key); assert!(state.is_some()); } diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs index 5c267679b..2b87f8345 100644 --- a/util/src/journaldb/earlymergedb.rs +++ b/util/src/journaldb/earlymergedb.rs @@ -102,7 +102,7 @@ impl EarlyMergeDB { fn new_temp() -> EarlyMergeDB { let mut dir = env::temp_dir(); dir.push(H32::random().hex()); - Self::new(dir.to_str().unwrap(), None) + Self::new(dir.to_str().unwrap(), DatabaseConfig::default()) } fn morph_key(key: &H256, index: u8) -> Bytes { @@ -532,6 +532,7 @@ mod tests { use super::super::traits::JournalDB; use hashdb::*; use log::init_log; + use kvdb::DatabaseConfig; #[test] fn insert_same_in_fork() { @@ -709,7 +710,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -737,7 +738,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -765,7 +766,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -803,7 +804,7 @@ mod tests { let bar = H256::random(); let foo = { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 let foo = jdb.insert(b"foo"); jdb.emplace(bar.clone(), b"bar".to_vec()); @@ -813,14 +814,14 @@ mod tests { }; { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.remove(&foo); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); } { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); assert!(jdb.contains(&foo)); assert!(jdb.contains(&bar)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); @@ -835,7 +836,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 4 let foo = jdb.insert(b"foo"); @@ -864,7 +865,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 4 let foo = jdb.insert(b"foo"); @@ -913,7 +914,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 let foo = jdb.insert(b"foo"); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); @@ -944,7 +945,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 4 let foo = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); @@ -984,7 +985,7 @@ mod tests { let foo = b"foo".sha3(); { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); @@ -1005,7 +1006,7 @@ mod tests { assert!(jdb.contains(&foo)); // incantation to reopen the db - }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.remove(&foo); jdb.commit(4, &b"4".sha3(), Some((2, b"2".sha3()))).unwrap(); @@ -1013,14 +1014,14 @@ mod tests { assert!(jdb.contains(&foo)); // incantation to reopen the db - }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(5, &b"5".sha3(), Some((3, b"3".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo)); // incantation to reopen the db - }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + }; { let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(6, &b"6".sha3(), Some((4, b"4".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -1033,7 +1034,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); let (foo, bar, baz) = { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); @@ -1051,7 +1052,7 @@ mod tests { }; { - let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), None); + let mut jdb = EarlyMergeDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo)); diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs index 09ec3da88..0ffea308b 100644 --- a/util/src/journaldb/overlayrecentdb.rs +++ b/util/src/journaldb/overlayrecentdb.rs @@ -130,7 +130,7 @@ impl OverlayRecentDB { pub fn new_temp() -> OverlayRecentDB { let mut dir = env::temp_dir(); dir.push(H32::random().hex()); - Self::new(dir.to_str().unwrap(), None) + Self::new(dir.to_str().unwrap(), DatabaseConfig::default()) } #[cfg(test)] @@ -364,6 +364,7 @@ mod tests { use hashdb::*; use log::init_log; use journaldb::JournalDB; + use kvdb::DatabaseConfig; #[test] fn insert_same_in_fork() { @@ -521,7 +522,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -549,7 +550,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -577,7 +578,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(0, &b"0".sha3(), None).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -615,7 +616,7 @@ mod tests { let bar = H256::random(); let foo = { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 let foo = jdb.insert(b"foo"); jdb.emplace(bar.clone(), b"bar".to_vec()); @@ -625,14 +626,14 @@ mod tests { }; { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.remove(&foo); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); } { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); assert!(jdb.contains(&foo)); assert!(jdb.contains(&bar)); jdb.commit(2, &b"2".sha3(), Some((1, b"1".sha3()))).unwrap(); @@ -647,7 +648,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 4 let foo = jdb.insert(b"foo"); @@ -676,7 +677,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 4 let foo = jdb.insert(b"foo"); @@ -725,7 +726,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 let foo = jdb.insert(b"foo"); jdb.commit(1, &b"1".sha3(), Some((0, b"0".sha3()))).unwrap(); @@ -756,7 +757,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 4 let foo = jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); @@ -796,7 +797,7 @@ mod tests { let foo = b"foo".sha3(); { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 jdb.insert(b"foo"); jdb.commit(0, &b"0".sha3(), None).unwrap(); @@ -817,7 +818,7 @@ mod tests { assert!(jdb.contains(&foo)); // incantation to reopen the db - }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.remove(&foo); jdb.commit(4, &b"4".sha3(), Some((2, b"2".sha3()))).unwrap(); @@ -825,14 +826,14 @@ mod tests { assert!(jdb.contains(&foo)); // incantation to reopen the db - }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(5, &b"5".sha3(), Some((3, b"3".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo)); // incantation to reopen the db - }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + }; { let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(6, &b"6".sha3(), Some((4, b"4".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); @@ -845,7 +846,7 @@ mod tests { let mut dir = ::std::env::temp_dir(); dir.push(H32::random().hex()); let (foo, bar, baz) = { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); // history is 1 let foo = jdb.insert(b"foo"); let bar = jdb.insert(b"bar"); @@ -863,7 +864,7 @@ mod tests { }; { - let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), None); + let mut jdb = OverlayRecentDB::new(dir.to_str().unwrap(), DatabaseConfig::default()); jdb.commit(2, &b"2b".sha3(), Some((1, b"1b".sha3()))).unwrap(); assert!(jdb.can_reconstruct_refs()); assert!(jdb.contains(&foo)); diff --git a/util/src/journaldb/refcounteddb.rs b/util/src/journaldb/refcounteddb.rs index d2092b2a6..4be6a1eda 100644 --- a/util/src/journaldb/refcounteddb.rs +++ b/util/src/journaldb/refcounteddb.rs @@ -77,7 +77,7 @@ impl RefCountedDB { fn new_temp() -> RefCountedDB { let mut dir = env::temp_dir(); dir.push(H32::random().hex()); - Self::new(dir.to_str().unwrap(), None) + Self::new(dir.to_str().unwrap(), DatabaseConfig::default()) } } diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 4e7bdb26c..bc0acc2dd 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -293,10 +293,10 @@ mod tests { let path = RandomTempPath::create_dir(); let smoke = Database::open_default(path.as_path().to_str().unwrap()).unwrap(); assert!(smoke.is_empty()); - test_db(&DatabaseConfig { prefix_size: None, max_open_files: 256, cache_size: None, }); - test_db(&DatabaseConfig { prefix_size: Some(1), max_open_files: 256, cache_size: None, }); - test_db(&DatabaseConfig { prefix_size: Some(8), max_open_files: 256, cache_size: None, }); - test_db(&DatabaseConfig { prefix_size: Some(32), max_open_files: 256, cache_size: None, }); + test_db(&DatabaseConfig::default()); + test_db(&DatabaseConfig::default().prefix(12)); + test_db(&DatabaseConfig::default().prefix(22)); + test_db(&DatabaseConfig::default().prefix(8)); } } From 2a51a30d41ca4c1361b5398400ed2eb60f7f011b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Jun 2016 19:06:54 +0200 Subject: [PATCH 216/239] Fix up the pending set stuff. --- ethcore/src/client/client.rs | 4 +- ethcore/src/client/mod.rs | 2 +- ethcore/src/client/test_client.rs | 4 +- ethcore/src/miner/miner.rs | 72 ++++++++++++++++++++----------- ethcore/src/miner/mod.rs | 2 +- parity/cli.rs | 13 ++++-- parity/configuration.rs | 11 ++--- sync/src/chain.rs | 2 +- 8 files changed, 70 insertions(+), 40 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 2c4499e57..0082aa4c5 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -792,8 +792,8 @@ impl BlockChainClient for Client where V: Verifier { } } - fn all_transactions(&self) -> Vec { - self.miner.all_transactions() + fn pending_transactions(&self) -> Vec { + self.miner.pending_transactions() } } diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 80625ad85..c05874e64 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -197,7 +197,7 @@ pub trait BlockChainClient : Sync + Send { fn queue_transactions(&self, transactions: Vec); /// list all transactions - fn all_transactions(&self) -> Vec; + fn pending_transactions(&self) -> Vec; /// Get the gas price distribution. fn gas_price_statistics(&self, sample_size: usize, distribution_size: usize) -> Result, ()> { diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 812c15655..a7f508a51 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -500,7 +500,7 @@ impl BlockChainClient for TestBlockChainClient { self.import_transactions(tx); } - fn all_transactions(&self) -> Vec { - self.miner.all_transactions() + fn pending_transactions(&self) -> Vec { + self.miner.pending_transactions() } } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index e5ecff8c4..72228a959 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -29,6 +29,18 @@ use spec::Spec; use engine::Engine; use miner::{MinerService, MinerStatus, TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; +/// Different possible definitions for pending transaction set. +#[derive(Debug)] +pub enum PendingSet { + /// Always just the transactions in the queue. These have had only cheap checks. + AlwaysQueue, + /// Always just the transactions in the sealing block. These have had full checks but + /// may be empty if the node is not actively mining or has force_sealing enabled. + AlwaysSealing, + /// Try the sealing block, but if it is not currently sealing, fallback to the queue. + SealingOrElseQueue, +} + /// Configures the behaviour of the miner. #[derive(Debug)] pub struct MinerOptions { @@ -42,7 +54,7 @@ pub struct MinerOptions { /// If `None`, then no limit. pub max_tx_gas: Option, /// Whether we should fallback to providing all the queue's transactions or just pending. - pub strict_valid_pending: bool, + pub pending_set: PendingSet, } impl Default for MinerOptions { @@ -52,7 +64,7 @@ impl Default for MinerOptions { reseal_on_external_tx: true, reseal_on_own_tx: true, max_tx_gas: None, - strict_valid_pending: false, + pending_set: PendingSet::AlwaysQueue, } } } @@ -462,24 +474,6 @@ impl MinerService for Miner { imported } - fn pending_transactions_hashes(&self) -> Vec { - let queue = self.transaction_queue.lock().unwrap(); - match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { - (true, Some(pending)) => pending.transactions().iter().map(|t| t.hash()).collect(), - _ if self.options.strict_valid_pending => Vec::new(), - _ => queue.pending_hashes(), - } - } - - fn transaction(&self, hash: &H256) -> Option { - let queue = self.transaction_queue.lock().unwrap(); - match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { - (true, Some(pending)) => pending.transactions().iter().find(|t| &t.hash() == hash).cloned(), - _ if self.options.strict_valid_pending => None, - _ => queue.find(hash), - } - } - fn all_transactions(&self) -> Vec { let queue = self.transaction_queue.lock().unwrap(); queue.top_transactions() @@ -487,11 +481,41 @@ impl MinerService for Miner { fn pending_transactions(&self) -> Vec { let queue = self.transaction_queue.lock().unwrap(); + let sw = self.sealing_work.lock().unwrap(); // TODO: should only use the sealing_work when it's current (it could be an old block) - match (self.sealing_enabled.load(atomic::Ordering::Relaxed), self.sealing_work.lock().unwrap().peek_last_ref()) { - (true, Some(pending)) => pending.transactions().clone(), - _ if self.options.strict_valid_pending => Vec::new(), - _ => queue.top_transactions(), + let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) { + true => sw.peek_last_ref(), + false => None, + }; + match (&self.options.pending_set, sealing_set) { + (&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.top_transactions(), + (_, sealing) => sealing.map(|s| s.transactions().clone()).unwrap_or(Vec::new()), + } + } + + fn pending_transactions_hashes(&self) -> Vec { + let queue = self.transaction_queue.lock().unwrap(); + let sw = self.sealing_work.lock().unwrap(); + let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) { + true => sw.peek_last_ref(), + false => None, + }; + match (&self.options.pending_set, sealing_set) { + (&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.pending_hashes(), + (_, sealing) => sealing.map(|s| s.transactions().iter().map(|t| t.hash()).collect()).unwrap_or(Vec::new()), + } + } + + fn transaction(&self, hash: &H256) -> Option { + let queue = self.transaction_queue.lock().unwrap(); + let sw = self.sealing_work.lock().unwrap(); + let sealing_set = match self.sealing_enabled.load(atomic::Ordering::Relaxed) { + true => sw.peek_last_ref(), + false => None, + }; + match (&self.options.pending_set, sealing_set) { + (&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.find(hash), + (_, sealing) => sealing.and_then(|s| s.transactions().iter().find(|t| &t.hash() == hash).cloned()), } } diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 8a282490c..f02925438 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -47,7 +47,7 @@ mod external; mod transaction_queue; pub use self::transaction_queue::{TransactionQueue, AccountDetails, TransactionImportResult, TransactionOrigin}; -pub use self::miner::{Miner, MinerOptions}; +pub use self::miner::{Miner, MinerOptions, PendingSet}; pub use self::external::{ExternalMiner, ExternalMinerService}; use std::collections::BTreeMap; diff --git a/parity/cli.rs b/parity/cli.rs index 3090e83c5..2fe9186f5 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -141,9 +141,14 @@ Sealing/Mining Options: all - reseal on all new transactions [default: all]. --max-tx-gas GAS Apply a limit of GAS as the maximum amount of gas a single transaction may have for it to be mined. - --relay-validity REQ Requirements for relaying. REQ may be: - cheap - Relay only after cheap checks; - strict - Relay only once executed [default: cheap]. + --relay-set SET Set of transactions to relay. SET may be: + cheap - Relay any transaction in the queue (this + may include invalid transactions); + strict - Relay only executed transactions (this + guarantees we don't relay invalid transactions, but + means we relay nothing if not mining); + lenient - Same as struct when mining, and cheap + when not [default: cheap]. --usd-per-tx USD Amount of USD to be paid for a basic transaction [default: 0.005]. The minimum gas price is set accordingly. @@ -296,7 +301,7 @@ pub struct Args { pub flag_force_sealing: bool, pub flag_reseal_on_txs: String, pub flag_max_tx_gas: Option, - pub flag_relay_validity: String, + pub flag_relay_set: String, pub flag_author: Option, pub flag_usd_per_tx: String, pub flag_usd_per_eth: String, diff --git a/parity/configuration.rs b/parity/configuration.rs index 57c62f839..501cc68cb 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -27,7 +27,7 @@ use util::*; use ethcore::account_provider::AccountProvider; use util::network_settings::NetworkSettings; use ethcore::client::{append_path, get_db_path, ClientConfig, Switch, VMType}; -use ethcore::miner::MinerOptions; +use ethcore::miner::{MinerOptions, PendingSet}; use ethcore::ethereum; use ethcore::spec::Spec; use ethsync::SyncConfig; @@ -89,10 +89,11 @@ impl Configuration { reseal_on_external_tx: ext, reseal_on_own_tx: own, max_tx_gas: self.args.flag_max_tx_gas.as_ref().map(|d| Self::decode_u256(d, "--max-tx-gas")), - strict_valid_pending: match self.args.flag_relay_validity.as_str() { - "cheap" => false, - "strict" => true, - x => die!("{}: Invalid value for --relay-validity option. Use --help for more information.", x) + pending_set: match self.args.flag_relay_set.as_str() { + "cheap" => PendingSet::AlwaysQueue, + "strict" => PendingSet::AlwaysSealing, + "lenient" => PendingSet::SealingOrElseQueue, + x => die!("{}: Invalid value for --relay-set option. Use --help for more information.", x) }, } } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 5d0976aac..aa3657419 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1314,7 +1314,7 @@ impl ChainSync { return 0; } - let mut transactions = io.chain().all_transactions(); + let mut transactions = io.chain().pending_transactions(); if transactions.is_empty() { return 0; } From a102015ecf253a80f7431f46177c1846e712cc61 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Jun 2016 19:16:26 +0200 Subject: [PATCH 217/239] Fix doc test. --- parity/cli.rs | 4 ++-- rpc/src/v1/tests/eth.rs | 4 +++- sync/src/lib.rs | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 2fe9186f5..86ab2037d 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -133,8 +133,8 @@ Sealing/Mining Options: NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION. --force-sealing Force the node to author new blocks as if it were always sealing/mining. - --reseal-on-txs Specify which transactions should force the node - to reseal a block. One of: + --reseal-on-txs SET Specify which transactions should force the node + to reseal a block. SET is one of: none - never reseal on new transactions; own - reseal only on a new local transaction; ext - reseal only on a new external transaction; diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 2ce482a90..1a0cc26c8 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -24,7 +24,7 @@ use ethcore::spec::{Genesis, Spec}; use ethcore::block::Block; use ethcore::views::BlockView; use ethcore::ethereum; -use ethcore::miner::{MinerOptions, MinerService, ExternalMiner, Miner}; +use ethcore::miner::{MinerOptions, MinerService, ExternalMiner, Miner, PendingSet}; use ethcore::account_provider::AccountProvider; use devtools::RandomTempPath; use util::Hashable; @@ -54,6 +54,8 @@ fn miner_service(spec: Spec, accounts: Arc) -> Arc { force_sealing: true, reseal_on_external_tx: true, reseal_on_own_tx: true, + max_tx_gas: None, + pending_set: PendingSet::SealingOrElseQueue, }, spec, Some(accounts) diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 928496326..ced1bf6a2 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -44,7 +44,7 @@ //! let mut service = NetworkService::new(NetworkConfiguration::new()).unwrap(); //! service.start().unwrap(); //! let dir = env::temp_dir(); -//! let miner = Miner::new(MinerOptions::default(), ethereum::new_frontier(true), None); +//! let miner = Miner::new(Default::default(), ethereum::new_frontier(true), None); //! let client = Client::new( //! ClientConfig::default(), //! ethereum::new_frontier(true), From 7b5eeb1dd71d9a7b086b9c9934a9d80f2d86ee59 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Jun 2016 19:22:28 +0200 Subject: [PATCH 218/239] Update cli.rs [ci:skip] --- parity/cli.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index c42719cc6..0761962a0 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -172,11 +172,10 @@ Footprint Options: options. Database Options: - --db-cache-size MB Database cache size. Default if not specified. - --db-compaction TYPE Database compaction type. TYPE may be one of default, hdd - default - suitable for ssd backing storage/fast hdd - hdd - sutable for slow storage - [default: default]. + --db-cache-size MB Override RocksDB database cache size. + --db-compaction TYPE Database compaction type. TYPE may be one of: + ssd - suitable for SSDs and fast HDDs; + hdd - suitable for slow HDDs [default: ssd]. Import/Export Options: --from BLOCK Export from block BLOCK, which may be an index or From dc79e63db734f4baf08ddbbeced8d293c0480e21 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Jun 2016 19:22:54 +0200 Subject: [PATCH 219/239] Update configuration.rs --- parity/configuration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/configuration.rs b/parity/configuration.rs index ad2578478..6b145095d 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -280,7 +280,7 @@ impl Configuration { // compaction profile client_config.db_compaction = match self.args.flag_db_compaction.as_str() { - "default" => DatabaseCompactionProfile::Default, + "ssd" => DatabaseCompactionProfile::Default, "hdd" => DatabaseCompactionProfile::HDD, _ => { die!("Invalid compaction profile given (--db-compaction argument), expected hdd/default."); } }; From 60b70dada143d4231c21595b58015b0828642bdd Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Mon, 27 Jun 2016 19:30:13 +0200 Subject: [PATCH 220/239] Reduced IO messages; removed panics on IO notifications (#1457) --- ethcore/src/client/client.rs | 2 +- sync/src/lib.rs | 6 ++++-- util/src/io/service.rs | 11 +++++++---- util/src/network/discovery.rs | 15 +++++++++++---- util/src/network/host.rs | 25 ++++++++++++------------- 5 files changed, 35 insertions(+), 24 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 16422250a..11e137230 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -359,7 +359,7 @@ impl Client where V: Verifier { invalid: invalid_blocks, enacted: enacted, retracted: retracted, - })).unwrap(); + })).unwrap_or_else(|e| warn!("Error sending IO notification: {:?}", e)); } } diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 3f899c261..462d4783e 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -160,11 +160,13 @@ impl SyncProvider for EthSync { } fn start_network(&self) { - self.io_channel.read().unwrap().send(NetworkIoMessage::User(SyncMessage::StartNetwork)).expect("Error sending IO notification"); + self.io_channel.read().unwrap().send(NetworkIoMessage::User(SyncMessage::StartNetwork)) + .unwrap_or_else(|e| warn!("Error sending IO notification: {:?}", e)); } fn stop_network(&self) { - self.io_channel.read().unwrap().send(NetworkIoMessage::User(SyncMessage::StopNetwork)).expect("Error sending IO notification"); + self.io_channel.read().unwrap().send(NetworkIoMessage::User(SyncMessage::StopNetwork)) + .unwrap_or_else(|e| warn!("Error sending IO notification: {:?}", e)); } } diff --git a/util/src/io/service.rs b/util/src/io/service.rs index 65be55540..07e60f766 100644 --- a/util/src/io/service.rs +++ b/util/src/io/service.rs @@ -135,8 +135,9 @@ impl IoContext where Message: Send + Clone + 'static { } /// Broadcast a message to other IO clients - pub fn message(&self, message: Message) { - self.channel.send(message).expect("Error seding message"); + pub fn message(&self, message: Message) -> Result<(), UtilError> { + try!(self.channel.send(message)); + Ok(()) } /// Get message channel @@ -351,7 +352,9 @@ impl IoService where Message: Send + Sync + Clone + 'static { /// Starts IO event loop pub fn start() -> Result, UtilError> { let panic_handler = PanicHandler::new_in_arc(); - let mut event_loop = EventLoop::new().unwrap(); + let mut config = EventLoopConfig::new(); + config.messages_per_tick(1024); + let mut event_loop = EventLoop::configured(config).expect("Error creating event loop"); let channel = event_loop.channel(); let panic = panic_handler.clone(); let thread = thread::spawn(move || { @@ -390,7 +393,7 @@ impl IoService where Message: Send + Sync + Clone + 'static { impl Drop for IoService where Message: Send + Sync + Clone { fn drop(&mut self) { trace!(target: "shutdown", "[IoService] Closing..."); - self.host_channel.send(IoMessage::Shutdown).unwrap(); + self.host_channel.send(IoMessage::Shutdown).unwrap_or_else(|e| warn!("Error on IO service shutdown: {:?}", e)); self.thread.take().unwrap().join().ok(); trace!(target: "shutdown", "[IoService] Closed."); } diff --git a/util/src/network/discovery.rs b/util/src/network/discovery.rs index b67110538..d4f895702 100644 --- a/util/src/network/discovery.rs +++ b/util/src/network/discovery.rs @@ -28,7 +28,7 @@ use crypto::*; use rlp::*; use network::node_table::*; use network::error::NetworkError; -use io::StreamToken; +use io::{StreamToken, IoContext}; use network::PROTOCOL_VERSION; @@ -283,7 +283,7 @@ impl Discovery { ret } - pub fn writable(&mut self) { + pub fn writable(&mut self, io: &IoContext) where Message: Send + Sync + Clone { while !self.send_queue.is_empty() { let data = self.send_queue.pop_front().unwrap(); match self.udp_socket.send_to(&data.payload, &data.address) { @@ -302,15 +302,17 @@ impl Discovery { } } } + io.update_registration(self.token).unwrap_or_else(|e| debug!("Error updating discovery registration: {:?}", e)); } fn send_to(&mut self, payload: Bytes, address: SocketAddr) { self.send_queue.push_back(Datagramm { payload: payload, address: address }); } - pub fn readable(&mut self) -> Option { + pub fn readable(&mut self, io: &IoContext) -> Option where Message: Send + Sync + Clone { let mut buf: [u8; MAX_DATAGRAM_SIZE] = unsafe { mem::uninitialized() }; - match self.udp_socket.recv_from(&mut buf) { + let writable = !self.send_queue.is_empty(); + let res = match self.udp_socket.recv_from(&mut buf) { Ok(Some((len, address))) => self.on_packet(&buf[0..len], address).unwrap_or_else(|e| { debug!("Error processing UDP packet: {:?}", e); None @@ -320,7 +322,12 @@ impl Discovery { debug!("Error reading UPD socket: {:?}", e); None } + }; + let new_writable = !self.send_queue.is_empty(); + if writable != new_writable { + io.update_registration(self.token).unwrap_or_else(|e| debug!("Error updating discovery registration: {:?}", e)); } + res } fn on_packet(&mut self, packet: &[u8], from: SocketAddr) -> Result, NetworkError> { diff --git a/util/src/network/host.rs b/util/src/network/host.rs index 03f37fa61..46185482f 100644 --- a/util/src/network/host.rs +++ b/util/src/network/host.rs @@ -236,8 +236,8 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone } /// Send an IO message - pub fn message(&self, msg: Message) { - self.io.message(NetworkIoMessage::User(msg)); + pub fn message(&self, msg: Message) -> Result<(), UtilError> { + self.io.message(NetworkIoMessage::User(msg)) } /// Get an IoChannel. @@ -248,12 +248,14 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone /// Disable current protocol capability for given peer. If no capabilities left peer gets disconnected. pub fn disable_peer(&self, peer: PeerId) { //TODO: remove capability, disconnect if no capabilities left - self.io.message(NetworkIoMessage::DisablePeer(peer)); + self.io.message(NetworkIoMessage::DisablePeer(peer)) + .unwrap_or_else(|e| warn!("Error sending network IO message: {:?}", e)); } /// Disconnect peer. Reconnect can be attempted later. pub fn disconnect_peer(&self, peer: PeerId) { - self.io.message(NetworkIoMessage::Disconnect(peer)); + self.io.message(NetworkIoMessage::Disconnect(peer)) + .unwrap_or_else(|e| warn!("Error sending network IO message: {:?}", e)); } /// Check if the session is still active. @@ -267,7 +269,7 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone token: token, delay: ms, protocol: self.protocol, - }); + }).unwrap_or_else(|e| warn!("Error sending network IO message: {:?}", e)); Ok(()) } @@ -714,7 +716,6 @@ impl Host where Message: Send + Sync + Clone { debug!(target: "network", "Can't accept connection: {:?}", e); } } - io.update_registration(TCP_ACCEPT).expect("Error registering TCP listener"); } fn session_writable(&self, token: StreamToken, io: &IoContext>) { @@ -910,11 +911,10 @@ impl IoHandler> for Host where Messa match stream { FIRST_SESSION ... LAST_SESSION => self.session_readable(stream, io), DISCOVERY => { - let node_changes = { self.discovery.lock().unwrap().as_mut().unwrap().readable() }; + let node_changes = { self.discovery.lock().unwrap().as_mut().unwrap().readable(io) }; if let Some(node_changes) = node_changes { self.update_nodes(io, node_changes); } - io.update_registration(DISCOVERY).expect("Error updating discovery registration"); }, TCP_ACCEPT => self.accept(io), _ => panic!("Received unknown readable token"), @@ -928,8 +928,7 @@ impl IoHandler> for Host where Messa match stream { FIRST_SESSION ... LAST_SESSION => self.session_writable(stream, io), DISCOVERY => { - self.discovery.lock().unwrap().as_mut().unwrap().writable(); - io.update_registration(DISCOVERY).expect("Error updating discovery registration"); + self.discovery.lock().unwrap().as_mut().unwrap().writable(io); } _ => panic!("Received unknown writable token"), } @@ -946,14 +945,14 @@ impl IoHandler> for Host where Messa FIRST_SESSION ... LAST_SESSION => self.connection_timeout(token, io), DISCOVERY_REFRESH => { self.discovery.lock().unwrap().as_mut().unwrap().refresh(); - io.update_registration(DISCOVERY).expect("Error updating discovery registration"); + io.update_registration(DISCOVERY).unwrap_or_else(|e| debug!("Error updating discovery registration: {:?}", e)); }, DISCOVERY_ROUND => { let node_changes = { self.discovery.lock().unwrap().as_mut().unwrap().round() }; if let Some(node_changes) = node_changes { self.update_nodes(io, node_changes); } - io.update_registration(DISCOVERY).expect("Error updating discovery registration"); + io.update_registration(DISCOVERY).unwrap_or_else(|e| debug!("Error updating discovery registration: {:?}", e)); }, NODE_TABLE => { trace!(target: "network", "Refreshing node table"); @@ -1004,7 +1003,7 @@ impl IoHandler> for Host where Messa handler_token }; self.timers.write().unwrap().insert(handler_token, ProtocolTimer { protocol: protocol, token: *token }); - io.register_timer(handler_token, *delay).expect("Error registering timer"); + io.register_timer(handler_token, *delay).unwrap_or_else(|e| debug!("Error registering timer {}: {:?}", token, e)); }, NetworkIoMessage::Disconnect(ref peer) => { let session = { self.sessions.read().unwrap().get(*peer).cloned() }; From 10aa32b0f5eda6a96995558db5dc8ef22e672a46 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Jun 2016 20:19:01 +0200 Subject: [PATCH 221/239] Include RPC configurability for max tx gas limit. Also Move the gas limit into the transaction queue from the miner. --- ethcore/src/miner/miner.rs | 9 ++++- ethcore/src/miner/mod.rs | 3 ++ ethcore/src/miner/transaction_queue.rs | 40 ++++++++++++++++------- parity/configuration.rs | 1 + rpc/src/v1/impls/ethcore_set.rs | 9 ++++- rpc/src/v1/tests/helpers/miner_service.rs | 6 ++++ rpc/src/v1/traits/ethcore_set.rs | 4 +++ rpc/src/v1/types/optionals.rs | 26 +++++++++++++-- 8 files changed, 82 insertions(+), 16 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 72228a959..42971850a 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -53,6 +53,8 @@ pub struct MinerOptions { /// Specify maximum amount of gas to bother considering for block insertion. /// If `None`, then no limit. pub max_tx_gas: Option, + /// Maximum size of the transaction queue. + pub tx_queue_size: usize, /// Whether we should fallback to providing all the queue's transactions or just pending. pub pending_set: PendingSet, } @@ -64,6 +66,7 @@ impl Default for MinerOptions { reseal_on_external_tx: true, reseal_on_own_tx: true, max_tx_gas: None, + tx_queue_size: 1024, pending_set: PendingSet::AlwaysQueue, } } @@ -107,7 +110,7 @@ impl Miner { /// Creates new instance of miner pub fn new(options: MinerOptions, spec: Spec, accounts: Option>) -> Arc { Arc::new(Miner { - transaction_queue: Mutex::new(TransactionQueue::new()), + transaction_queue: Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, options.max_tx_gas)), sealing_enabled: AtomicBool::new(options.force_sealing), options: options, sealing_block_last_request: Mutex::new(0), @@ -396,6 +399,10 @@ impl MinerService for Miner { self.transaction_queue.lock().unwrap().set_limit(limit) } + fn set_tx_gas_limit(&self, limit: Option) { + self.transaction_queue.lock().unwrap().set_tx_gas_limit(limit) + } + /// Get the author that we will seal blocks as. fn author(&self) -> Address { *self.author.read().unwrap() diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index f02925438..a56f881a4 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -101,6 +101,9 @@ pub trait MinerService : Send + Sync { /// Set maximal number of transactions kept in the queue (both current and future). fn set_transactions_limit(&self, limit: usize); + /// Set maximum amount of gas allowed for any single transaction to mine. + fn set_tx_gas_limit(&self, limit: Option); + /// Imports transactions to transaction queue. fn import_transactions(&self, chain: &MiningBlockChainClient, transactions: Vec, fetch_account: T) -> Vec> diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 9159cc6b3..26ec441fe 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -334,6 +334,8 @@ const GAS_LIMIT_HYSTERESIS: usize = 10; // % pub struct TransactionQueue { /// Gas Price threshold for transactions that can be imported to this queue (defaults to 0) minimal_gas_price: U256, + /// If `Some`, then the maximum amount of gas any individual transaction may use. + tx_gas_limit: Option, /// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0) gas_limit: U256, /// Priority queue for transactions that can go to block @@ -355,11 +357,11 @@ impl Default for TransactionQueue { impl TransactionQueue { /// Creates new instance of this Queue pub fn new() -> Self { - Self::with_limit(1024) + Self::with_limits(1024, None) } /// Create new instance of this Queue with specified limits - pub fn with_limit(limit: usize) -> Self { + pub fn with_limits(limit: usize, tx_gas_limit: Option) -> Self { let current = TransactionSet { by_priority: BTreeSet::new(), by_address: Table::new(), @@ -374,6 +376,7 @@ impl TransactionQueue { TransactionQueue { minimal_gas_price: U256::zero(), + tx_gas_limit: tx_gas_limit, gas_limit: !U256::zero(), current: current, future: future, @@ -418,6 +421,12 @@ impl TransactionQueue { }; } + /// Set the new limit for the amount of gas any individual transaction may have. + /// Any transaction already imported to the queue is not affected. + pub fn set_tx_gas_limit(&mut self, limit: Option) { + self.tx_gas_limit = limit; + } + /// Returns current status for this queue pub fn status(&self) -> TransactionQueueStatus { TransactionQueueStatus { @@ -435,7 +444,9 @@ impl TransactionQueue { if tx.gas_price < self.minimal_gas_price { trace!(target: "miner", "Dropping transaction below minimal gas price threshold: {:?} (gp: {} < {})", - tx.hash(), tx.gas_price, self.minimal_gas_price + tx.hash(), + tx.gas_price, + self.minimal_gas_price ); return Err(Error::Transaction(TransactionError::InsufficientGasPrice { @@ -446,10 +457,12 @@ impl TransactionQueue { try!(tx.check_low_s()); - if tx.gas > self.gas_limit { + if tx.gas > self.gas_limit || self.tx_gas_limit.map(|l| tx.gas > l).unwrap_or(false) { trace!(target: "miner", "Dropping transaction above gas limit: {:?} ({} > {})", - tx.hash(), tx.gas, self.gas_limit + tx.hash(), + tx.gas, + self.gas_limit ); return Err(Error::Transaction(TransactionError::GasLimitExceeded { @@ -463,8 +476,13 @@ impl TransactionQueue { let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas; if client_account.balance < cost { - trace!(target: "miner", "Dropping transaction without sufficient balance: {:?} ({} < {})", - vtx.hash(), client_account.balance, cost); + trace!(target: "miner", + "Dropping transaction without sufficient balance: {:?} ({} < {})", + vtx.hash(), + client_account.balance, + cost + ); + return Err(Error::Transaction(TransactionError::InsufficientBalance { cost: cost, balance: client_account.balance @@ -1304,7 +1322,7 @@ mod test { #[test] fn should_drop_old_transactions_when_hitting_the_limit() { // given - let mut txq = TransactionQueue::with_limit(1); + let mut txq = TransactionQueue::with_limit(1, None); let (tx, tx2) = new_txs(U256::one()); let sender = tx.sender().unwrap(); let nonce = tx.nonce; @@ -1326,7 +1344,7 @@ mod test { #[test] fn should_return_correct_nonces_when_dropped_because_of_limit() { // given - let mut txq = TransactionQueue::with_limit(2); + let mut txq = TransactionQueue::with_limit(2, None); let tx = new_tx(); let (tx1, tx2) = new_txs(U256::one()); let sender = tx1.sender().unwrap(); @@ -1347,7 +1365,7 @@ mod test { #[test] fn should_limit_future_transactions() { - let mut txq = TransactionQueue::with_limit(1); + let mut txq = TransactionQueue::with_limit(1, None); txq.current.set_limit(10); let (tx1, tx2) = new_txs_with_gas_price_diff(U256::from(4), U256::from(1)); let (tx3, tx4) = new_txs_with_gas_price_diff(U256::from(4), U256::from(2)); @@ -1607,7 +1625,7 @@ mod test { #[test] fn should_keep_right_order_in_future() { // given - let mut txq = TransactionQueue::with_limit(1); + let mut txq = TransactionQueue::with_limit(1, None); let (tx1, tx2) = new_txs(U256::from(1)); let prev_nonce = |a: &Address| AccountDetails { nonce: default_nonce(a).nonce - U256::one(), balance: default_nonce(a).balance }; diff --git a/parity/configuration.rs b/parity/configuration.rs index 501cc68cb..4469eefaf 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -89,6 +89,7 @@ impl Configuration { reseal_on_external_tx: ext, reseal_on_own_tx: own, max_tx_gas: self.args.flag_max_tx_gas.as_ref().map(|d| Self::decode_u256(d, "--max-tx-gas")), + tx_queue_size: self.args.flag_tx_queue_size, pending_set: match self.args.flag_relay_set.as_str() { "cheap" => PendingSet::AlwaysQueue, "strict" => PendingSet::AlwaysSealing, diff --git a/rpc/src/v1/impls/ethcore_set.rs b/rpc/src/v1/impls/ethcore_set.rs index 55164217c..d7624442a 100644 --- a/rpc/src/v1/impls/ethcore_set.rs +++ b/rpc/src/v1/impls/ethcore_set.rs @@ -22,7 +22,7 @@ use jsonrpc_core::*; use ethcore::miner::MinerService; use ethcore::service::SyncMessage; use v1::traits::EthcoreSet; -use v1::types::{Bytes}; +use v1::types::{OptionalValue, Bytes}; /// Ethcore-specific rpc interface for operations altering the settings. pub struct EthcoreSetClient where @@ -86,6 +86,13 @@ impl EthcoreSet for EthcoreSetClient where M: MinerService + 'static { }) } + fn set_tx_gas_limit(&self, params: Params) -> Result { + from_params::<(OptionalValue,)>(params).and_then(|(limit,)| { + take_weak!(self.miner).set_tx_gas_limit(limit.into()); + to_value(&true) + }) + } + fn add_reserved_peer(&self, params: Params) -> Result { from_params::<(String,)>(params).and_then(|(peer,)| { match take_weak!(self.net).add_reserved_peer(&peer) { diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index b87b650e1..4a9b22f42 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -43,6 +43,7 @@ pub struct TestMinerService { author: RwLock
, extra_data: RwLock, limit: RwLock, + tx_gas_limit: RwLock>, } impl Default for TestMinerService { @@ -58,6 +59,7 @@ impl Default for TestMinerService { author: RwLock::new(Address::zero()), extra_data: RwLock::new(vec![1, 2, 3, 4]), limit: RwLock::new(1024), + tx_gas_limit: RwLock::new(None), } } } @@ -99,6 +101,10 @@ impl MinerService for TestMinerService { *self.limit.write().unwrap() = limit; } + fn set_tx_gas_limit(&self, limit: Option) { + *self.tx_gas_limit.write().unwrap() = limit; + } + fn transactions_limit(&self) -> usize { *self.limit.read().unwrap() } diff --git a/rpc/src/v1/traits/ethcore_set.rs b/rpc/src/v1/traits/ethcore_set.rs index d00295036..8afbcdab9 100644 --- a/rpc/src/v1/traits/ethcore_set.rs +++ b/rpc/src/v1/traits/ethcore_set.rs @@ -40,6 +40,9 @@ pub trait EthcoreSet: Sized + Send + Sync + 'static { /// Sets the limits for transaction queue. fn set_transactions_limit(&self, _: Params) -> Result; + /// Sets the maximum amount of gas a single transaction may consume. + fn set_tx_gas_limit(&self, _: Params) -> Result; + /// Add a reserved peer. fn add_reserved_peer(&self, _: Params) -> Result; @@ -60,6 +63,7 @@ pub trait EthcoreSet: Sized + Send + Sync + 'static { delegate.add_method("ethcore_setGasCeilTarget", EthcoreSet::set_gas_ceil_target); delegate.add_method("ethcore_setExtraData", EthcoreSet::set_extra_data); delegate.add_method("ethcore_setAuthor", EthcoreSet::set_author); + delegate.add_method("ethcore_setMaxTransactionGas", EthcoreSet::set_tx_gas_limit); delegate.add_method("ethcore_setTransactionsLimit", EthcoreSet::set_transactions_limit); delegate.add_method("ethcore_addReservedPeer", EthcoreSet::add_reserved_peer); delegate.add_method("ethcore_removeReservedPeer", EthcoreSet::remove_reserved_peer); diff --git a/rpc/src/v1/types/optionals.rs b/rpc/src/v1/types/optionals.rs index 2ed272ade..5f62dc4a0 100644 --- a/rpc/src/v1/types/optionals.rs +++ b/rpc/src/v1/types/optionals.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use serde::{Serialize, Serializer}; +use serde::{Serialize, Serializer, Deserialize, Deserializer}; use serde_json::Value; /// Optional value @@ -26,13 +26,22 @@ pub enum OptionalValue where T: Serialize { Null } -impl Default for OptionalValue where T: Serialize { +impl Default for OptionalValue where T: Serialize + Deserialize { fn default() -> Self { OptionalValue::Null } } -impl Serialize for OptionalValue where T: Serialize { +impl Into> for OptionalValue where T: Serialize + Deserialize { + fn into(self) -> Option { + match self { + OptionalValue::Null => None, + OptionalValue::Value(t) => Some(t), + } + } +} + +impl Serialize for OptionalValue where T: Serialize + Deserialize { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { match *self { @@ -42,6 +51,17 @@ impl Serialize for OptionalValue where T: Serialize { } } +impl Deserialize for OptionalValue where T: Serialize + Deserialize { + fn deserialize(deserializer: &mut D) -> Result, D::Error> + where D: Deserializer { + let deser_result: Result = Deserialize::deserialize(deserializer); + match deser_result { + Ok(t) => Ok(OptionalValue::Value(t)), + Err(_) => Ok(OptionalValue::Null), + } + } +} + #[cfg(test)] mod tests { use serde_json; From ed153995f9580c67bddb908d333ebae97786c5f1 Mon Sep 17 00:00:00 2001 From: arkpar Date: Mon, 27 Jun 2016 18:46:50 +0200 Subject: [PATCH 222/239] Attempt DB repair if corrupted --- Cargo.lock | 4 ++-- util/src/kvdb.rs | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f47ee5cf..5e2bc6e13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1077,7 +1077,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rocksdb" version = "0.4.5" -source = "git+https://github.com/ethcore/rust-rocksdb#6f3c68f5f075433d206be4af6a620651cd9f8541" +source = "git+https://github.com/ethcore/rust-rocksdb#9be41e05923616dfa28741c58b22776d479751e6" dependencies = [ "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb-sys 0.3.0 (git+https://github.com/ethcore/rust-rocksdb)", @@ -1086,7 +1086,7 @@ dependencies = [ [[package]] name = "rocksdb-sys" version = "0.3.0" -source = "git+https://github.com/ethcore/rust-rocksdb#6f3c68f5f075433d206be4af6a620651cd9f8541" +source = "git+https://github.com/ethcore/rust-rocksdb#9be41e05923616dfa28741c58b22776d479751e6" dependencies = [ "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index e472305a7..bc75825fb 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -150,7 +150,16 @@ impl Database { opts.set_block_based_table_factory(&block_opts); opts.set_prefix_extractor_fixed_size(size); } - let db = try!(DB::open(&opts, path)); + let db = match DB::open(&opts, path) { + Ok(db) => db, + Err(ref s) if s.starts_with("Corruption:") => { + info!("{}", s); + info!("Attempting DB repair for {}", path); + try!(DB::repair(&opts, path)); + try!(DB::open(&opts, path)) + }, + Err(s) => { return Err(s); } + }; Ok(Database { db: db }) } From 5919c660e570d79f3029589db230ba358d774c08 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Jun 2016 21:06:10 +0200 Subject: [PATCH 223/239] Fix typo [ci:skip] --- parity/cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/cli.rs b/parity/cli.rs index 86ab2037d..3fd802658 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -147,7 +147,7 @@ Sealing/Mining Options: strict - Relay only executed transactions (this guarantees we don't relay invalid transactions, but means we relay nothing if not mining); - lenient - Same as struct when mining, and cheap + lenient - Same as strict when mining, and cheap when not [default: cheap]. --usd-per-tx USD Amount of USD to be paid for a basic transaction [default: 0.005]. The minimum gas price is set From ff788e4199d4143a55aafeea27757a73e1808c7d Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Mon, 27 Jun 2016 21:06:40 +0200 Subject: [PATCH 224/239] Fix another typo [ci:skip] --- parity/cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parity/cli.rs b/parity/cli.rs index 3fd802658..3eeae7fae 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -162,7 +162,7 @@ Sealing/Mining Options: block due to transaction volume [default: 3141592]. --extra-data STRING Specify a custom extra-data for authored blocks, no more than 32 characters. - --tx-queue-size LIMIT Maxmimum amount of transactions in the queue (waiting + --tx-queue-size LIMIT Maximum amount of transactions in the queue (waiting to be included in next block) [default: 1024]. Footprint Options: From c221f69ccdf2f811fa0f593ee77d52ae6b400d25 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 28 Jun 2016 10:00:28 +0200 Subject: [PATCH 225/239] Clean up some of the FP stuff. --- ethcore/src/miner/miner.rs | 4 ++-- ethcore/src/miner/transaction_queue.rs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 42971850a..20c9af3f7 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -496,7 +496,7 @@ impl MinerService for Miner { }; match (&self.options.pending_set, sealing_set) { (&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.top_transactions(), - (_, sealing) => sealing.map(|s| s.transactions().clone()).unwrap_or(Vec::new()), + (_, sealing) => sealing.map_or_else(Vec::new, |s| s.transactions().clone()), } } @@ -509,7 +509,7 @@ impl MinerService for Miner { }; match (&self.options.pending_set, sealing_set) { (&PendingSet::AlwaysQueue, _) | (&PendingSet::SealingOrElseQueue, None) => queue.pending_hashes(), - (_, sealing) => sealing.map(|s| s.transactions().iter().map(|t| t.hash()).collect()).unwrap_or(Vec::new()), + (_, sealing) => sealing.map_or_else(Vec::new, |s| s.transactions().iter().map(|t| t.hash()).collect()), } } diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 26ec441fe..6ebbf0f6a 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -459,10 +459,11 @@ impl TransactionQueue { if tx.gas > self.gas_limit || self.tx_gas_limit.map(|l| tx.gas > l).unwrap_or(false) { trace!(target: "miner", - "Dropping transaction above gas limit: {:?} ({} > {})", + "Dropping transaction above gas limit: {:?} ({} > min({}, {:?}))", tx.hash(), tx.gas, - self.gas_limit + self.gas_limit, + self.tx_gas_limit ); return Err(Error::Transaction(TransactionError::GasLimitExceeded { @@ -606,7 +607,7 @@ impl TransactionQueue { self.current.by_priority .iter() .map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`")) - .filter_map(|t| if &t.transaction.gas <= max_tx_gas { Some(t.transaction.clone()) } else { None }) + .map(|t| &t.transaction).filter(|t| t.gas <= *max_tx_gas).cloned() .collect() } From 31de739122d4ee86ba6b1b186cf03d3eb6105f72 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 28 Jun 2016 10:21:29 +0200 Subject: [PATCH 226/239] U256 instead of Option. Fix up tests. --- ethcore/src/miner/miner.rs | 11 +++---- ethcore/src/miner/mod.rs | 2 +- ethcore/src/miner/transaction_queue.rs | 38 +++++++---------------- parity/configuration.rs | 2 +- rpc/src/v1/impls/ethcore_set.rs | 4 +-- rpc/src/v1/tests/eth.rs | 5 +-- rpc/src/v1/tests/helpers/miner_service.rs | 6 ++-- 7 files changed, 26 insertions(+), 42 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 20c9af3f7..2623ce3d9 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -50,9 +50,8 @@ pub struct MinerOptions { pub reseal_on_external_tx: bool, /// Reseal on receipt of new local transactions. pub reseal_on_own_tx: bool, - /// Specify maximum amount of gas to bother considering for block insertion. - /// If `None`, then no limit. - pub max_tx_gas: Option, + /// Maximum amount of gas to bother considering for block insertion. + pub max_tx_gas: U256, /// Maximum size of the transaction queue. pub tx_queue_size: usize, /// Whether we should fallback to providing all the queue's transactions or just pending. @@ -65,7 +64,7 @@ impl Default for MinerOptions { force_sealing: false, reseal_on_external_tx: true, reseal_on_own_tx: true, - max_tx_gas: None, + max_tx_gas: !U256::zero(), tx_queue_size: 1024, pending_set: PendingSet::AlwaysQueue, } @@ -134,7 +133,7 @@ impl Miner { trace!(target: "miner", "prepare_sealing: entering"); let (transactions, mut open_block) = { - let transactions = {self.transaction_queue.lock().unwrap().top_transactions_maybe_limit(&self.options.max_tx_gas)}; + let transactions = {self.transaction_queue.lock().unwrap().top_transactions()}; let mut sealing_work = self.sealing_work.lock().unwrap(); let best_hash = chain.best_block_header().sha3(); /* @@ -399,7 +398,7 @@ impl MinerService for Miner { self.transaction_queue.lock().unwrap().set_limit(limit) } - fn set_tx_gas_limit(&self, limit: Option) { + fn set_tx_gas_limit(&self, limit: U256) { self.transaction_queue.lock().unwrap().set_tx_gas_limit(limit) } diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index a56f881a4..e65d6048a 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -102,7 +102,7 @@ pub trait MinerService : Send + Sync { fn set_transactions_limit(&self, limit: usize); /// Set maximum amount of gas allowed for any single transaction to mine. - fn set_tx_gas_limit(&self, limit: Option); + fn set_tx_gas_limit(&self, limit: U256); /// Imports transactions to transaction queue. fn import_transactions(&self, chain: &MiningBlockChainClient, transactions: Vec, fetch_account: T) -> diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 6ebbf0f6a..17ca18272 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -334,8 +334,8 @@ const GAS_LIMIT_HYSTERESIS: usize = 10; // % pub struct TransactionQueue { /// Gas Price threshold for transactions that can be imported to this queue (defaults to 0) minimal_gas_price: U256, - /// If `Some`, then the maximum amount of gas any individual transaction may use. - tx_gas_limit: Option, + /// The maximum amount of gas any individual transaction may use. + tx_gas_limit: U256, /// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0) gas_limit: U256, /// Priority queue for transactions that can go to block @@ -357,11 +357,11 @@ impl Default for TransactionQueue { impl TransactionQueue { /// Creates new instance of this Queue pub fn new() -> Self { - Self::with_limits(1024, None) + Self::with_limits(1024, !U256::zero()) } /// Create new instance of this Queue with specified limits - pub fn with_limits(limit: usize, tx_gas_limit: Option) -> Self { + pub fn with_limits(limit: usize, tx_gas_limit: U256) -> Self { let current = TransactionSet { by_priority: BTreeSet::new(), by_address: Table::new(), @@ -423,7 +423,7 @@ impl TransactionQueue { /// Set the new limit for the amount of gas any individual transaction may have. /// Any transaction already imported to the queue is not affected. - pub fn set_tx_gas_limit(&mut self, limit: Option) { + pub fn set_tx_gas_limit(&mut self, limit: U256) { self.tx_gas_limit = limit; } @@ -457,9 +457,9 @@ impl TransactionQueue { try!(tx.check_low_s()); - if tx.gas > self.gas_limit || self.tx_gas_limit.map(|l| tx.gas > l).unwrap_or(false) { + if tx.gas > self.gas_limit || tx.gas > self.tx_gas_limit { trace!(target: "miner", - "Dropping transaction above gas limit: {:?} ({} > min({}, {:?}))", + "Dropping transaction above gas limit: {:?} ({} > min({}, {}))", tx.hash(), tx.gas, self.gas_limit, @@ -602,22 +602,6 @@ impl TransactionQueue { .collect() } - /// Returns top transactions from the queue ordered by priority with a maximum gas limit. - pub fn top_transactions_with_limit(&self, max_tx_gas: &U256) -> Vec { - self.current.by_priority - .iter() - .map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`")) - .map(|t| &t.transaction).filter(|t| t.gas <= *max_tx_gas).cloned() - .collect() - } - - /// Returns top transactions from the queue ordered by priority with a maximum gas limit. - pub fn top_transactions_maybe_limit(&self, max_tx_gas: &Option) -> Vec { - match *max_tx_gas { - None => self.top_transactions(), - Some(ref m) => self.top_transactions_with_limit(m), - } - } /// Returns hashes of all transactions from current, ordered by priority. pub fn pending_hashes(&self) -> Vec { self.current.by_priority @@ -1323,7 +1307,7 @@ mod test { #[test] fn should_drop_old_transactions_when_hitting_the_limit() { // given - let mut txq = TransactionQueue::with_limit(1, None); + let mut txq = TransactionQueue::with_limits(1, !U256::zero()); let (tx, tx2) = new_txs(U256::one()); let sender = tx.sender().unwrap(); let nonce = tx.nonce; @@ -1345,7 +1329,7 @@ mod test { #[test] fn should_return_correct_nonces_when_dropped_because_of_limit() { // given - let mut txq = TransactionQueue::with_limit(2, None); + let mut txq = TransactionQueue::with_limits(2, !U256::zero()); let tx = new_tx(); let (tx1, tx2) = new_txs(U256::one()); let sender = tx1.sender().unwrap(); @@ -1366,7 +1350,7 @@ mod test { #[test] fn should_limit_future_transactions() { - let mut txq = TransactionQueue::with_limit(1, None); + let mut txq = TransactionQueue::with_limits(1, !U256::zero()); txq.current.set_limit(10); let (tx1, tx2) = new_txs_with_gas_price_diff(U256::from(4), U256::from(1)); let (tx3, tx4) = new_txs_with_gas_price_diff(U256::from(4), U256::from(2)); @@ -1626,7 +1610,7 @@ mod test { #[test] fn should_keep_right_order_in_future() { // given - let mut txq = TransactionQueue::with_limit(1, None); + let mut txq = TransactionQueue::with_limits(1, !U256::zero()); let (tx1, tx2) = new_txs(U256::from(1)); let prev_nonce = |a: &Address| AccountDetails { nonce: default_nonce(a).nonce - U256::one(), balance: default_nonce(a).balance }; diff --git a/parity/configuration.rs b/parity/configuration.rs index d5f41c471..acae3b5f4 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -88,7 +88,7 @@ impl Configuration { force_sealing: self.args.flag_force_sealing, reseal_on_external_tx: ext, reseal_on_own_tx: own, - max_tx_gas: self.args.flag_max_tx_gas.as_ref().map(|d| Self::decode_u256(d, "--max-tx-gas")), + max_tx_gas: self.args.flag_max_tx_gas.as_ref().map_or(!U256::zero(), |d| Self::decode_u256(d, "--max-tx-gas")), tx_queue_size: self.args.flag_tx_queue_size, pending_set: match self.args.flag_relay_set.as_str() { "cheap" => PendingSet::AlwaysQueue, diff --git a/rpc/src/v1/impls/ethcore_set.rs b/rpc/src/v1/impls/ethcore_set.rs index d7624442a..baf5bf134 100644 --- a/rpc/src/v1/impls/ethcore_set.rs +++ b/rpc/src/v1/impls/ethcore_set.rs @@ -22,7 +22,7 @@ use jsonrpc_core::*; use ethcore::miner::MinerService; use ethcore::service::SyncMessage; use v1::traits::EthcoreSet; -use v1::types::{OptionalValue, Bytes}; +use v1::types::Bytes; /// Ethcore-specific rpc interface for operations altering the settings. pub struct EthcoreSetClient where @@ -87,7 +87,7 @@ impl EthcoreSet for EthcoreSetClient where M: MinerService + 'static { } fn set_tx_gas_limit(&self, params: Params) -> Result { - from_params::<(OptionalValue,)>(params).and_then(|(limit,)| { + from_params::<(U256,)>(params).and_then(|(limit,)| { take_weak!(self.miner).set_tx_gas_limit(limit.into()); to_value(&true) }) diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 1a0cc26c8..e3aed553f 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -29,7 +29,7 @@ use ethcore::account_provider::AccountProvider; use devtools::RandomTempPath; use util::Hashable; use util::io::IoChannel; -use util::{U256, H256}; +use util::{U256, H256, Uint}; use jsonrpc_core::IoHandler; use ethjson::blockchain::BlockChain; @@ -54,7 +54,8 @@ fn miner_service(spec: Spec, accounts: Arc) -> Arc { force_sealing: true, reseal_on_external_tx: true, reseal_on_own_tx: true, - max_tx_gas: None, + tx_queue_size: 1024, + max_tx_gas: !U256::zero(), pending_set: PendingSet::SealingOrElseQueue, }, spec, diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 4a9b22f42..6329be7bd 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -43,7 +43,7 @@ pub struct TestMinerService { author: RwLock
, extra_data: RwLock, limit: RwLock, - tx_gas_limit: RwLock>, + tx_gas_limit: RwLock, } impl Default for TestMinerService { @@ -59,7 +59,7 @@ impl Default for TestMinerService { author: RwLock::new(Address::zero()), extra_data: RwLock::new(vec![1, 2, 3, 4]), limit: RwLock::new(1024), - tx_gas_limit: RwLock::new(None), + tx_gas_limit: RwLock::new(!U256::zero()), } } } @@ -101,7 +101,7 @@ impl MinerService for TestMinerService { *self.limit.write().unwrap() = limit; } - fn set_tx_gas_limit(&self, limit: Option) { + fn set_tx_gas_limit(&self, limit: U256) { *self.tx_gas_limit.write().unwrap() = limit; } From 599a6104b7fd794a132316466995720976f163bd Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 28 Jun 2016 10:40:35 +0200 Subject: [PATCH 227/239] Minor renaming. --- ethcore/src/miner/miner.rs | 6 +++--- parity/cli.rs | 4 ++-- parity/configuration.rs | 2 +- rpc/src/v1/tests/eth.rs | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 2623ce3d9..803706c56 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -51,7 +51,7 @@ pub struct MinerOptions { /// Reseal on receipt of new local transactions. pub reseal_on_own_tx: bool, /// Maximum amount of gas to bother considering for block insertion. - pub max_tx_gas: U256, + pub tx_gas_limit: U256, /// Maximum size of the transaction queue. pub tx_queue_size: usize, /// Whether we should fallback to providing all the queue's transactions or just pending. @@ -64,7 +64,7 @@ impl Default for MinerOptions { force_sealing: false, reseal_on_external_tx: true, reseal_on_own_tx: true, - max_tx_gas: !U256::zero(), + tx_gas_limit: !U256::zero(), tx_queue_size: 1024, pending_set: PendingSet::AlwaysQueue, } @@ -109,7 +109,7 @@ impl Miner { /// Creates new instance of miner pub fn new(options: MinerOptions, spec: Spec, accounts: Option>) -> Arc { Arc::new(Miner { - transaction_queue: Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, options.max_tx_gas)), + transaction_queue: Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, options.tx_gas_limit)), sealing_enabled: AtomicBool::new(options.force_sealing), options: options, sealing_block_last_request: Mutex::new(0), diff --git a/parity/cli.rs b/parity/cli.rs index 4999caf65..3ee6f31c8 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -139,7 +139,7 @@ Sealing/Mining Options: own - reseal only on a new local transaction; ext - reseal only on a new external transaction; all - reseal on all new transactions [default: all]. - --max-tx-gas GAS Apply a limit of GAS as the maximum amount of gas + --tx-gas-limit GAS Apply a limit of GAS as the maximum amount of gas a single transaction may have for it to be mined. --relay-set SET Set of transactions to relay. SET may be: cheap - Relay any transaction in the queue (this @@ -305,7 +305,7 @@ pub struct Args { pub flag_no_token: bool, pub flag_force_sealing: bool, pub flag_reseal_on_txs: String, - pub flag_max_tx_gas: Option, + pub flag_tx_gas_limit: Option, pub flag_relay_set: String, pub flag_author: Option, pub flag_usd_per_tx: String, diff --git a/parity/configuration.rs b/parity/configuration.rs index acae3b5f4..4bd0cd493 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -88,7 +88,7 @@ impl Configuration { force_sealing: self.args.flag_force_sealing, reseal_on_external_tx: ext, reseal_on_own_tx: own, - max_tx_gas: self.args.flag_max_tx_gas.as_ref().map_or(!U256::zero(), |d| Self::decode_u256(d, "--max-tx-gas")), + tx_gas_limit: self.args.flag_tx_gas_limit.as_ref().map_or(!U256::zero(), |d| Self::decode_u256(d, "--tx-gas-limit")), tx_queue_size: self.args.flag_tx_queue_size, pending_set: match self.args.flag_relay_set.as_str() { "cheap" => PendingSet::AlwaysQueue, diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index e3aed553f..88a12a74f 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -55,7 +55,7 @@ fn miner_service(spec: Spec, accounts: Arc) -> Arc { reseal_on_external_tx: true, reseal_on_own_tx: true, tx_queue_size: 1024, - max_tx_gas: !U256::zero(), + tx_gas_limit: !U256::zero(), pending_set: PendingSet::SealingOrElseQueue, }, spec, From 6895a560999e967928d56b72abd3543f3a74bcc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 28 Jun 2016 11:10:39 +0200 Subject: [PATCH 228/239] Adding default for value (#1465) --- Cargo.lock | 2 +- rpc/src/v1/impls/eth_signing.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 5e2bc6e13..0a2e21df2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1446,7 +1446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ws" version = "0.5.0" -source = "git+https://github.com/ethcore/ws-rs.git?branch=stable#e2452450c830618aed30db02e63f3a68710cc40e" +source = "git+https://github.com/ethcore/ws-rs.git?branch=stable#a876fc115c3ef50a17c8822c9bd2f6e94473e005" dependencies = [ "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/eth_signing.rs index 700c679d6..fa4330f46 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/eth_signing.rs @@ -29,6 +29,9 @@ use v1::impls::{default_gas_price, sign_and_dispatch}; fn fill_optional_fields(request: &mut TransactionRequest, client: &C, miner: &M) where C: MiningBlockChainClient, M: MinerService { + if request.value.is_none() { + request.value = Some(U256::zero()); + } if request.gas.is_none() { request.gas = Some(miner.sensible_gas_limit()); } From 4f56f8b27c5e2cd0d0b1a2b2245e1454621c18a4 Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 28 Jun 2016 11:52:59 +0200 Subject: [PATCH 229/239] removed unsafe code (#1466) --- util/bigint/src/uint.rs | 10 +--------- util/src/hash.rs | 11 +++-------- util/src/rlp/bytes.rs | 9 +-------- 3 files changed, 5 insertions(+), 25 deletions(-) diff --git a/util/bigint/src/uint.rs b/util/bigint/src/uint.rs index 3e629032e..2b9863135 100644 --- a/util/bigint/src/uint.rs +++ b/util/bigint/src/uint.rs @@ -557,7 +557,7 @@ macro_rules! construct_uint { ($name:ident, $n_words:expr) => ( /// Little-endian large integer type #[repr(C)] - #[derive(Copy, Clone, Eq, PartialEq)] + #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct $name(pub [u64; $n_words]); impl Uint for $name { @@ -1126,14 +1126,6 @@ macro_rules! construct_uint { Ok(()) } } - - #[cfg_attr(feature="dev", allow(derive_hash_xor_eq))] // We are pretty sure it's ok. - impl Hash for $name { - fn hash(&self, state: &mut H) where H: Hasher { - unsafe { state.write(::std::slice::from_raw_parts(self.0.as_ptr() as *mut u8, self.0.len() * 8)); } - state.finish(); - } - } ); } diff --git a/util/src/hash.rs b/util/src/hash.rs index 6c1f8b2a4..16f0bde9e 100644 --- a/util/src/hash.rs +++ b/util/src/hash.rs @@ -132,15 +132,10 @@ macro_rules! impl_hash { $size } - // TODO: remove once slice::clone_from_slice is stable #[inline] fn clone_from_slice(&mut self, src: &[u8]) -> usize { - let min = ::std::cmp::min($size, src.len()); - let dst = &mut self.deref_mut()[.. min]; - let src = &src[.. min]; - for i in 0..min { - dst[i] = src[i]; - } + let min = cmp::min($size, src.len()); + self.0[..min].copy_from_slice(&src[..min]); min } @@ -151,7 +146,7 @@ macro_rules! impl_hash { } fn copy_to(&self, dest: &mut[u8]) { - let min = ::std::cmp::min($size, dest.len()); + let min = cmp::min($size, dest.len()); dest[..min].copy_from_slice(&self.0[..min]); } diff --git a/util/src/rlp/bytes.rs b/util/src/rlp/bytes.rs index 1145ba27e..d252af828 100644 --- a/util/src/rlp/bytes.rs +++ b/util/src/rlp/bytes.rs @@ -258,14 +258,7 @@ impl FromBytes for T where T: FixedHash { Ordering::Equal => () }; - unsafe { - use std::{mem, ptr}; - - let mut res: T = mem::uninitialized(); - ptr::copy(bytes.as_ptr(), res.as_slice_mut().as_mut_ptr(), T::len()); - - Ok(res) - } + Ok(T::from_slice(bytes)) } } From 4ecf23df9a80c866f1892bac0370025ce76aff61 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 28 Jun 2016 12:08:30 +0200 Subject: [PATCH 230/239] tests for TransactionView --- ethcore/src/views/mod.rs | 5 ++ ethcore/src/views/transaction.rs | 97 ++++++++++++++++++++++++++++++++ ethcore/src/{ => views}/views.rs | 59 +------------------ 3 files changed, 103 insertions(+), 58 deletions(-) create mode 100644 ethcore/src/views/mod.rs create mode 100644 ethcore/src/views/transaction.rs rename ethcore/src/{ => views}/views.rs (85%) diff --git a/ethcore/src/views/mod.rs b/ethcore/src/views/mod.rs new file mode 100644 index 000000000..cb7d82752 --- /dev/null +++ b/ethcore/src/views/mod.rs @@ -0,0 +1,5 @@ +mod transaction; +mod views; + +pub use self::transaction::TransactionView; +pub use self::views::*; diff --git a/ethcore/src/views/transaction.rs b/ethcore/src/views/transaction.rs new file mode 100644 index 000000000..d83290909 --- /dev/null +++ b/ethcore/src/views/transaction.rs @@ -0,0 +1,97 @@ +// Copyright 2015, 2016 Ethcore (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 . + +//! View onto transaction rlp +use util::{Rlp, U256, Bytes, Hashable, H256, View}; + +/// View onto transaction rlp. +pub struct TransactionView<'a> { + rlp: Rlp<'a> +} + +impl<'a> TransactionView<'a> { + /// Creates new view onto block from raw bytes. + pub fn new(bytes: &'a [u8]) -> TransactionView<'a> { + TransactionView { + rlp: Rlp::new(bytes) + } + } + + /// Creates new view onto block from rlp. + pub fn new_from_rlp(rlp: Rlp<'a>) -> TransactionView<'a> { + TransactionView { + rlp: rlp + } + } + + /// Return reference to underlaying rlp. + pub fn rlp(&self) -> &Rlp<'a> { + &self.rlp + } + + /// Get the nonce field of the transaction. + pub fn nonce(&self) -> U256 { self.rlp.val_at(0) } + + /// Get the gas_price field of the transaction. + pub fn gas_price(&self) -> U256 { self.rlp.val_at(1) } + + /// Get the gas field of the transaction. + pub fn gas(&self) -> U256 { self.rlp.val_at(2) } + + /// Get the value field of the transaction. + pub fn value(&self) -> U256 { self.rlp.val_at(4) } + + /// Get the data field of the transaction. + pub fn data(&self) -> Bytes { self.rlp.val_at(5) } + + /// Get the v field of the transaction. + pub fn v(&self) -> u8 { let r: u16 = self.rlp.val_at(6); r as u8 } + + /// Get the r field of the transaction. + pub fn r(&self) -> U256 { self.rlp.val_at(7) } + + /// Get the s field of the transaction. + pub fn s(&self) -> U256 { self.rlp.val_at(8) } +} + +impl<'a> Hashable for TransactionView<'a> { + fn sha3(&self) -> H256 { + self.rlp.as_raw().sha3() + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use rustc_serialize::hex::FromHex; + use util::U256; + use super::TransactionView; + + #[test] + fn test_transaction_view() { + let rlp = "f87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804".from_hex().unwrap(); + + let view = TransactionView::new(&rlp); + assert_eq!(view.nonce(), U256::from(0)); + assert_eq!(view.gas_price(), U256::from(1)); + assert_eq!(view.gas(), U256::from(0x61a8)); + assert_eq!(view.value(), U256::from(0xa)); + assert_eq!(view.data(), "0000000000000000000000000000000000000000000000000000000000".from_hex().unwrap()); + assert_eq!(view.r(), U256::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353").unwrap()); + assert_eq!(view.s(), U256::from_str("efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); + assert_eq!(view.v(), 0x1b); + } +} diff --git a/ethcore/src/views.rs b/ethcore/src/views/views.rs similarity index 85% rename from ethcore/src/views.rs rename to ethcore/src/views/views.rs index 0802e11bf..419c70c47 100644 --- a/ethcore/src/views.rs +++ b/ethcore/src/views/views.rs @@ -18,64 +18,7 @@ use util::*; use header::*; use transaction::*; - -/// View onto transaction rlp. -pub struct TransactionView<'a> { - rlp: Rlp<'a> -} - -impl<'a> TransactionView<'a> { - /// Creates new view onto block from raw bytes. - pub fn new(bytes: &'a [u8]) -> TransactionView<'a> { - TransactionView { - rlp: Rlp::new(bytes) - } - } - - /// Creates new view onto block from rlp. - pub fn new_from_rlp(rlp: Rlp<'a>) -> TransactionView<'a> { - TransactionView { - rlp: rlp - } - } - - /// Return reference to underlaying rlp. - pub fn rlp(&self) -> &Rlp<'a> { - &self.rlp - } - - /// Get the nonce field of the transaction. - pub fn nonce(&self) -> U256 { self.rlp.val_at(0) } - - /// Get the gas_price field of the transaction. - pub fn gas_price(&self) -> U256 { self.rlp.val_at(1) } - - /// Get the gas field of the transaction. - pub fn gas(&self) -> U256 { self.rlp.val_at(2) } - - /// Get the value field of the transaction. - pub fn value(&self) -> U256 { self.rlp.val_at(4) } - - /// Get the data field of the transaction. - pub fn data(&self) -> Bytes { self.rlp.val_at(5) } - - /// Get the v field of the transaction. - pub fn v(&self) -> u8 { let r: u16 = self.rlp.val_at(6); r as u8 } - - /// Get the r field of the transaction. - pub fn r(&self) -> U256 { self.rlp.val_at(7) } - - /// Get the s field of the transaction. - pub fn s(&self) -> U256 { self.rlp.val_at(8) } - - // TODO: something like pub fn action(&self) -> Action { self.rlp.val_at(3) } -} - -impl<'a> Hashable for TransactionView<'a> { - fn sha3(&self) -> H256 { - self.rlp.as_raw().sha3() - } -} +use super::TransactionView; /// View onto transaction rlp. pub struct AccountView<'a> { From af891f65a77971e00eab3071a1613899cde430ab Mon Sep 17 00:00:00 2001 From: Marek Kotewicz Date: Tue, 28 Jun 2016 13:23:15 +0200 Subject: [PATCH 231/239] verifier is no longer a template type of client (#1467) * verifier is no longer a template type of client * added missing , --- ethcore/src/client/client.rs | 31 +++++++++------------- ethcore/src/client/config.rs | 3 +++ ethcore/src/verification/canon_verifier.rs | 4 +-- ethcore/src/verification/mod.rs | 25 +++++++++++++++-- ethcore/src/verification/noop_verifier.rs | 4 +-- ethcore/src/verification/verifier.rs | 4 +-- 6 files changed, 44 insertions(+), 27 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index b65bdfd4d..1a437bfac 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -16,7 +16,6 @@ //! Blockchain database client. -use std::marker::PhantomData; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use util::*; @@ -30,7 +29,8 @@ use engine::Engine; use views::HeaderView; use service::{NetSyncMessage, SyncMessage}; use env_info::LastHashes; -use verification::*; +use verification; +use verification::{PreverifiedBlock, Verifier}; use block::*; use transaction::{LocalizedTransaction, SignedTransaction, Action}; use blockchain::extras::TransactionAddress; @@ -83,7 +83,7 @@ impl ClientReport { /// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue. /// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue. -pub struct Client where V: Verifier { +pub struct Client { chain: Arc, tracedb: Arc>, engine: Arc>, @@ -92,7 +92,7 @@ pub struct Client where V: Verifier { report: RwLock, import_lock: Mutex<()>, panic_handler: Arc, - verifier: PhantomData, + verifier: Box, vm_factory: Arc, miner: Arc, io_channel: IoChannel, @@ -107,13 +107,6 @@ const HISTORY: u64 = 1200; // of which you actually want force an upgrade. const CLIENT_DB_VER_STR: &'static str = "5.3"; -impl Client { - /// Create a new client with given spec and DB path. - pub fn new(config: ClientConfig, spec: Spec, path: &Path, miner: Arc, message_channel: IoChannel ) -> Result, ClientError> { - Client::::new_with_verifier(config, spec, path, miner, message_channel) - } -} - /// Get the path for the databases given the root path and information on the databases. pub fn get_db_path(path: &Path, pruning: journaldb::Algorithm, genesis_hash: H256) -> PathBuf { let mut dir = path.to_path_buf(); @@ -131,15 +124,15 @@ pub fn append_path(path: &Path, item: &str) -> String { p.to_str().unwrap().to_owned() } -impl Client where V: Verifier { +impl Client { /// Create a new client with given spec and DB path and custom verifier. - pub fn new_with_verifier( + pub fn new( config: ClientConfig, spec: Spec, path: &Path, miner: Arc, message_channel: IoChannel) - -> Result>, ClientError> + -> Result, ClientError> { let path = get_db_path(path, config.pruning, spec.genesis_header().hash()); let gb = spec.genesis_block(); @@ -180,7 +173,7 @@ impl Client where V: Verifier { report: RwLock::new(Default::default()), import_lock: Mutex::new(()), panic_handler: panic_handler, - verifier: PhantomData, + verifier: verification::new(config.verifier_type), vm_factory: Arc::new(EvmFactory::new(config.vm_type)), miner: miner, io_channel: message_channel, @@ -222,7 +215,7 @@ impl Client where V: Verifier { } // Verify Block Family - let verify_family_result = V::verify_block_family(&header, &block.bytes, engine, self.chain.deref()); + let verify_family_result = self.verifier.verify_block_family(&header, &block.bytes, engine, self.chain.deref()); if let Err(e) = verify_family_result { warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); @@ -248,7 +241,7 @@ impl Client where V: Verifier { // Final Verification let locked_block = enact_result.unwrap(); - if let Err(e) = V::verify_block_final(&header, locked_block.block().header()) { + if let Err(e) = self.verifier.verify_block_final(&header, locked_block.block().header()) { warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); return Err(()); } @@ -483,7 +476,7 @@ impl Client where V: Verifier { } } -impl BlockChainClient for Client where V: Verifier { +impl BlockChainClient for Client { fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result { let header = self.block_header(BlockID::Latest).unwrap(); let view = HeaderView::new(&header); @@ -806,7 +799,7 @@ impl BlockChainClient for Client where V: Verifier { } } -impl MiningBlockChainClient for Client where V: Verifier { +impl MiningBlockChainClient for Client { fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock { let engine = self.engine.deref().deref(); let h = self.chain.best_block_hash(); diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index 7d7f8e524..52a875a2f 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -18,6 +18,7 @@ pub use block_queue::BlockQueueConfig; pub use blockchain::Config as BlockChainConfig; pub use trace::{Config as TraceConfig, Switch}; pub use evm::VMType; +pub use verification::VerifierType; use util::journaldb; /// Client state db compaction profile @@ -52,4 +53,6 @@ pub struct ClientConfig { pub db_cache_size: Option, /// State db compaction profile pub db_compaction: DatabaseCompactionProfile, + /// Type of block verifier used by client. + pub verifier_type: VerifierType, } diff --git a/ethcore/src/verification/canon_verifier.rs b/ethcore/src/verification/canon_verifier.rs index 30e368f1b..e0ebf1b7c 100644 --- a/ethcore/src/verification/canon_verifier.rs +++ b/ethcore/src/verification/canon_verifier.rs @@ -24,11 +24,11 @@ use super::verification; pub struct CanonVerifier; impl Verifier for CanonVerifier { - fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> { + fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> { verification::verify_block_family(header, bytes, engine, bc) } - fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> { + fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error> { verification::verify_block_final(expected, got) } } diff --git a/ethcore/src/verification/mod.rs b/ethcore/src/verification/mod.rs index fe1f406cc..10aee21f4 100644 --- a/ethcore/src/verification/mod.rs +++ b/ethcore/src/verification/mod.rs @@ -17,11 +17,32 @@ pub mod verification; pub mod verifier; mod canon_verifier; -#[cfg(test)] mod noop_verifier; pub use self::verification::*; pub use self::verifier::Verifier; pub use self::canon_verifier::CanonVerifier; -#[cfg(test)] pub use self::noop_verifier::NoopVerifier; + +/// Verifier type. +#[derive(Debug)] +pub enum VerifierType { + /// Verifies block normally. + Canon, + /// Does not verify block at all. + /// Used in tests. + Noop, +} + +impl Default for VerifierType { + fn default() -> Self { + VerifierType::Canon + } +} + +pub fn new(v: VerifierType) -> Box { + match v { + VerifierType::Canon => Box::new(CanonVerifier), + VerifierType::Noop => Box::new(NoopVerifier), + } +} diff --git a/ethcore/src/verification/noop_verifier.rs b/ethcore/src/verification/noop_verifier.rs index 20c15c3f1..99d1d594c 100644 --- a/ethcore/src/verification/noop_verifier.rs +++ b/ethcore/src/verification/noop_verifier.rs @@ -24,11 +24,11 @@ use super::Verifier; pub struct NoopVerifier; impl Verifier for NoopVerifier { - fn verify_block_family(_header: &Header, _bytes: &[u8], _engine: &Engine, _bc: &BlockProvider) -> Result<(), Error> { + fn verify_block_family(&self, _header: &Header, _bytes: &[u8], _engine: &Engine, _bc: &BlockProvider) -> Result<(), Error> { Ok(()) } - fn verify_block_final(_expected: &Header, _got: &Header) -> Result<(), Error> { + fn verify_block_final(&self, _expected: &Header, _got: &Header) -> Result<(), Error> { Ok(()) } } diff --git a/ethcore/src/verification/verifier.rs b/ethcore/src/verification/verifier.rs index cc5edce29..5db81a4eb 100644 --- a/ethcore/src/verification/verifier.rs +++ b/ethcore/src/verification/verifier.rs @@ -21,6 +21,6 @@ use header::Header; /// Should be used to verify blocks. pub trait Verifier: Send + Sync { - fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>; - fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error>; + fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>; + fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>; } From 0b86723e6847d3c96638461e70567555980df04a Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 28 Jun 2016 14:28:42 +0200 Subject: [PATCH 232/239] tests for HeaderView and BlockView, fixed #144 --- ethcore/src/views/{views.rs => block.rs} | 147 +++-------------------- ethcore/src/views/header.rs | 134 +++++++++++++++++++++ ethcore/src/views/mod.rs | 26 +++- 3 files changed, 173 insertions(+), 134 deletions(-) rename ethcore/src/views/{views.rs => block.rs} (52%) create mode 100644 ethcore/src/views/header.rs diff --git a/ethcore/src/views/views.rs b/ethcore/src/views/block.rs similarity index 52% rename from ethcore/src/views/views.rs rename to ethcore/src/views/block.rs index 419c70c47..82b8fb805 100644 --- a/ethcore/src/views/views.rs +++ b/ethcore/src/views/block.rs @@ -14,49 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Block oriented views onto rlp. +//! View onto block rlp. + use util::*; use header::*; use transaction::*; -use super::TransactionView; - -/// View onto transaction rlp. -pub struct AccountView<'a> { - rlp: Rlp<'a> -} - -impl<'a> AccountView<'a> { - /// Creates new view onto block from raw bytes. - pub fn new(bytes: &'a [u8]) -> AccountView<'a> { - AccountView { - rlp: Rlp::new(bytes) - } - } - - /// Creates new view onto block from rlp. - pub fn new_from_rlp(rlp: Rlp<'a>) -> AccountView<'a> { - AccountView { - rlp: rlp - } - } - - /// Return reference to underlaying rlp. - pub fn rlp(&self) -> &Rlp<'a> { - &self.rlp - } - - /// Get the nonce field of the transaction. - pub fn nonce(&self) -> U256 { self.rlp.val_at(0) } - - /// Get the gas_price field of the transaction. - pub fn balance(&self) -> U256 { self.rlp.val_at(1) } - - /// Get the gas field of the transaction. - pub fn storage_root(&self) -> H256 { self.rlp.val_at(2) } - - /// Get the value field of the transaction. - pub fn code_hash(&self) -> H256 { self.rlp.val_at(3) } -} +use super::{TransactionView, HeaderView}; /// View onto block rlp. pub struct BlockView<'a> { @@ -78,6 +41,11 @@ impl<'a> BlockView<'a> { } } + /// Block header hash. + pub fn hash(&self) -> H256 { + self.sha3() + } + /// Return reference to underlaying rlp. pub fn rlp(&self) -> &Rlp<'a> { &self.rlp @@ -179,104 +147,21 @@ impl<'a> Hashable for BlockView<'a> { } } -/// View onto block header rlp. -pub struct HeaderView<'a> { - rlp: Rlp<'a> -} - -impl<'a> HeaderView<'a> { - /// Creates new view onto header from raw bytes. - pub fn new(bytes: &'a [u8]) -> HeaderView<'a> { - HeaderView { - rlp: Rlp::new(bytes) - } - } - - /// Creates new view onto header from rlp. - pub fn new_from_rlp(rlp: Rlp<'a>) -> HeaderView<'a> { - HeaderView { - rlp: rlp - } - } - - /// Returns header hash. - pub fn hash(&self) -> H256 { self.sha3() } - - /// Returns raw rlp. - pub fn rlp(&self) -> &Rlp<'a> { &self.rlp } - - /// Returns parent hash. - pub fn parent_hash(&self) -> H256 { self.rlp.val_at(0) } - - /// Returns uncles hash. - pub fn uncles_hash(&self) -> H256 { self.rlp.val_at(1) } - - /// Returns author. - pub fn author(&self) -> Address { self.rlp.val_at(2) } - - /// Returns state root. - pub fn state_root(&self) -> H256 { self.rlp.val_at(3) } - - /// Returns transactions root. - pub fn transactions_root(&self) -> H256 { self.rlp.val_at(4) } - - /// Returns block receipts root. - pub fn receipts_root(&self) -> H256 { self.rlp.val_at(5) } - - /// Returns block log bloom. - pub fn log_bloom(&self) -> H2048 { self.rlp.val_at(6) } - - /// Returns block difficulty. - pub fn difficulty(&self) -> U256 { self.rlp.val_at(7) } - - /// Returns block number. - pub fn number(&self) -> BlockNumber { self.rlp.val_at(8) } - - /// Returns block gas limit. - pub fn gas_limit(&self) -> U256 { self.rlp.val_at(9) } - - /// Returns block gas used. - pub fn gas_used(&self) -> U256 { self.rlp.val_at(10) } - - /// Returns timestamp. - pub fn timestamp(&self) -> u64 { self.rlp.val_at(11) } - - /// Returns block extra data. - pub fn extra_data(&self) -> Bytes { self.rlp.val_at(12) } - - /// Returns a vector of post-RLP-encoded seal fields. - pub fn seal(&self) -> Vec { - let mut seal = vec![]; - for i in 13..self.rlp.item_count() { - seal.push(self.rlp.at(i).as_raw().to_vec()); - } - seal - } -} - -impl<'a> Hashable for HeaderView<'a> { - fn sha3(&self) -> H256 { - self.rlp.as_raw().sha3() - } -} - #[cfg(test)] mod tests { + use std::str::FromStr; use rustc_serialize::hex::FromHex; + use util::H256; use super::BlockView; #[test] - fn test_header_view_seal_fields() { + fn test_block_view() { // that's rlp of block created with ethash engine. - let block_rlp = "f90261f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23f862f86002018304cb2f94ec0e71ad0a90ffe1909d27dac207f7680abba42d01801ba03a347e72953c860f32b1eb2c78a680d8734b2ea08085d949d729479796f218d5a047ea6239d9e31ccac8af3366f5ca37184d26e7646e3191a3aeb81c4cf74de500c0".from_hex().unwrap(); - let mix_hash = "a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd".from_hex().unwrap(); - let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap(); + let rlp = "f90261f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23f862f86002018304cb2f94ec0e71ad0a90ffe1909d27dac207f7680abba42d01801ba03a347e72953c860f32b1eb2c78a680d8734b2ea08085d949d729479796f218d5a047ea6239d9e31ccac8af3366f5ca37184d26e7646e3191a3aeb81c4cf74de500c0".from_hex().unwrap(); - let block_view = BlockView::new(&block_rlp); - let header_view = block_view.header_view(); - let seal_fields = header_view.seal(); - assert_eq!(seal_fields.len(), 2); - assert_eq!(seal_fields[0], mix_hash); - assert_eq!(seal_fields[1], nonce); + let view = BlockView::new(&rlp); + assert_eq!(view.hash(), H256::from_str("2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259").unwrap()); + assert_eq!(view.transactions_count(), 1); + assert_eq!(view.uncles_count(), 0); } } diff --git a/ethcore/src/views/header.rs b/ethcore/src/views/header.rs new file mode 100644 index 000000000..70b59fbfa --- /dev/null +++ b/ethcore/src/views/header.rs @@ -0,0 +1,134 @@ +// Copyright 2015, 2016 Ethcore (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 . + +//! View onto block header rlp + +use util::{Rlp, U256, Bytes, Hashable, H256, Address, H2048, View}; +use header::BlockNumber; + +/// View onto block header rlp. +pub struct HeaderView<'a> { + rlp: Rlp<'a> +} + +impl<'a> HeaderView<'a> { + /// Creates new view onto header from raw bytes. + pub fn new(bytes: &'a [u8]) -> HeaderView<'a> { + HeaderView { + rlp: Rlp::new(bytes) + } + } + + /// Creates new view onto header from rlp. + pub fn new_from_rlp(rlp: Rlp<'a>) -> HeaderView<'a> { + HeaderView { + rlp: rlp + } + } + + /// Returns header hash. + pub fn hash(&self) -> H256 { self.sha3() } + + /// Returns raw rlp. + pub fn rlp(&self) -> &Rlp<'a> { &self.rlp } + + /// Returns parent hash. + pub fn parent_hash(&self) -> H256 { self.rlp.val_at(0) } + + /// Returns uncles hash. + pub fn uncles_hash(&self) -> H256 { self.rlp.val_at(1) } + + /// Returns author. + pub fn author(&self) -> Address { self.rlp.val_at(2) } + + /// Returns state root. + pub fn state_root(&self) -> H256 { self.rlp.val_at(3) } + + /// Returns transactions root. + pub fn transactions_root(&self) -> H256 { self.rlp.val_at(4) } + + /// Returns block receipts root. + pub fn receipts_root(&self) -> H256 { self.rlp.val_at(5) } + + /// Returns block log bloom. + pub fn log_bloom(&self) -> H2048 { self.rlp.val_at(6) } + + /// Returns block difficulty. + pub fn difficulty(&self) -> U256 { self.rlp.val_at(7) } + + /// Returns block number. + pub fn number(&self) -> BlockNumber { self.rlp.val_at(8) } + + /// Returns block gas limit. + pub fn gas_limit(&self) -> U256 { self.rlp.val_at(9) } + + /// Returns block gas used. + pub fn gas_used(&self) -> U256 { self.rlp.val_at(10) } + + /// Returns timestamp. + pub fn timestamp(&self) -> u64 { self.rlp.val_at(11) } + + /// Returns block extra data. + pub fn extra_data(&self) -> Bytes { self.rlp.val_at(12) } + + /// Returns a vector of post-RLP-encoded seal fields. + pub fn seal(&self) -> Vec { + let mut seal = vec![]; + for i in 13..self.rlp.item_count() { + seal.push(self.rlp.at(i).as_raw().to_vec()); + } + seal + } +} + +impl<'a> Hashable for HeaderView<'a> { + fn sha3(&self) -> H256 { + self.rlp.as_raw().sha3() + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + use rustc_serialize::hex::FromHex; + use util::{H256, Address, H2048, U256}; + use super::HeaderView; + + #[test] + fn test_header_view() { + // that's rlp of block header created with ethash engine. + let rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap(); + let mix_hash = "a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd".from_hex().unwrap(); + let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap(); + + let view = HeaderView::new(&rlp); + assert_eq!(view.hash(), H256::from_str("2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259").unwrap()); + assert_eq!(view.parent_hash(), H256::from_str("d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7").unwrap()); + assert_eq!(view.uncles_hash(), H256::from_str("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").unwrap()); + assert_eq!(view.author(), Address::from_str("8888f1f195afa192cfee860698584c030f4c9db1").unwrap()); + assert_eq!(view.state_root(), H256::from_str("5fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25").unwrap()); + assert_eq!(view.transactions_root(), H256::from_str("88d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158").unwrap()); + assert_eq!(view.receipts_root(), H256::from_str("07c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1").unwrap()); + assert_eq!(view.log_bloom(), H2048::default()); + assert_eq!(view.difficulty(), U256::from(0x02_00_80)); + assert_eq!(view.number(), 3); + assert_eq!(view.gas_limit(), U256::from(0x2f_ef_ba)); + assert_eq!(view.gas_used(), U256::from(0x52_4d)); + assert_eq!(view.timestamp(), 0x56_8e_93_2a); + assert_eq!(view.extra_data(), vec![] as Vec); + assert_eq!(view.seal(), vec![mix_hash, nonce]); + } +} diff --git a/ethcore/src/views/mod.rs b/ethcore/src/views/mod.rs index cb7d82752..c0102be3d 100644 --- a/ethcore/src/views/mod.rs +++ b/ethcore/src/views/mod.rs @@ -1,5 +1,25 @@ -mod transaction; -mod views; +// Copyright 2015, 2016 Ethcore (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 . + +//! Block oriented views onto rlp. + +mod block; +mod header; +mod transaction; + +pub use self::block::BlockView; +pub use self::header::HeaderView; pub use self::transaction::TransactionView; -pub use self::views::*; From 8dbf1826187998568536c147fda7c974be3ec2ad Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 28 Jun 2016 16:10:21 +0200 Subject: [PATCH 233/239] give appveyor some breath --- appveyor.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index b980aba42..556c9dc30 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,6 +1,15 @@ environment: matrix: - TARGET: x86_64-pc-windows-msvc + +branches: + only: + - master + - /^beta-.*$/ + - /^stable-.*$/ + - /^beta$/ + - /^stable$/ + install: - git submodule update --init --recursive - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.9.0-x86_64-pc-windows-msvc.exe" From 477fdefb551eb6790cb2e2fa8302795b3d6138e9 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 28 Jun 2016 18:22:05 +0400 Subject: [PATCH 234/239] json ipc version bump (#1470) * bump version once * version bump 2 --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a2e21df2..8448b0a97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,7 +20,7 @@ dependencies = [ "ethsync 1.3.0", "fdlimit 0.1.0", "hyper 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "json-ipc-server 0.2.3 (git+https://github.com/ethcore/json-ipc-server.git)", + "json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -344,7 +344,7 @@ dependencies = [ "ethcore-util 1.3.0", "ethjson 0.1.0", "ethsync 1.3.0", - "json-ipc-server 0.2.3 (git+https://github.com/ethcore/json-ipc-server.git)", + "json-ipc-server 0.2.4 (git+https://github.com/ethcore/json-ipc-server.git)", "jsonrpc-core 2.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-http-server 5.1.0 (git+https://github.com/ethcore/jsonrpc-http-server.git)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -594,8 +594,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "json-ipc-server" -version = "0.2.3" -source = "git+https://github.com/ethcore/json-ipc-server.git#bfe16b66b2e9412d153b1ea53bc078d74037da7f" +version = "0.2.4" +source = "git+https://github.com/ethcore/json-ipc-server.git#902b031b8f50a59ecb4f389cbec1d264a98556bc" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", From 3ae8ccf8c6eb6d7727dc39b2be616e93b967fba8 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 28 Jun 2016 18:13:21 +0300 Subject: [PATCH 235/239] signing installer --- appveyor.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b980aba42..05111c821 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,13 +1,19 @@ environment: matrix: - TARGET: x86_64-pc-windows-msvc + cert: + secure: ESPpYVVAMG1fbJx6kq4ct/g9SQTXac4Hs6xXr6Oh4Zrk2dwYglNjxmzErdPnvu7gs/gekzrJ6KEQHYRc+5+4dKg6rRADQ681NLVx9vOggBs= + certpass: + secure: 0BgXJqxq9Ei34/hZ7121FQ== + keyfile: C:\users\appveyor\Certificates.p12 + install: - git submodule update --init --recursive - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.9.0-x86_64-pc-windows-msvc.exe" - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/SimpleFC.dll" -FileName nsis\SimpleFC.dll - ps: Start-FileDownload "https://github.com/ethcore/win-build/raw/master/vc_redist.x64.exe" -FileName nsis\vc_redist.x64.exe - rust-1.9.0-x86_64-pc-windows-msvc.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust" - - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin;C:\Program Files (x86)\NSIS + - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin;C:\Program Files (x86)\NSIS;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin - rustc -V - cargo -V @@ -19,6 +25,8 @@ test_script: after_test: - cargo build --verbose --release - makensis.exe nsis\installer.nsi + - ps: if($env:cert) { Start-FileDownload $env:cert -FileName $env:keyfile } + - ps: if($env:cert) { signtool /f $env:keyfile /p $env:certpass nsis\installer.exe } artifacts: - path: nsis\installer.exe From a3758161ac8eb3fb3886f17c8af686a51ca87555 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 28 Jun 2016 18:46:09 +0200 Subject: [PATCH 236/239] Ensure we always get the latest work when mining on submitted. (#1469) * Ensure we always get the latest work when mining on submitted. * Build fix. * Smaller timeslices for the wait. --- rpc/src/v1/impls/eth.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 9b1f06416..05dc89564 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -18,6 +18,8 @@ extern crate ethash; +use std::thread; +use std::time::{Instant, Duration}; use std::sync::{Arc, Weak, Mutex}; use std::ops::Deref; use ethsync::{SyncProvider, SyncState}; @@ -479,6 +481,12 @@ impl Eth for EthClient where trace!(target: "miner", "Syncing. Cannot give any work."); return Err(no_work_err()); } + + // Otherwise spin until our submitted block has been included. + let timeout = Instant::now() + Duration::from_millis(1000); + while Instant::now() < timeout && client.queue_info().total_queue_size() > 0 { + thread::sleep(Duration::from_millis(1)); + } } let miner = take_weak!(self.miner); From ebcbb19aefe600b8e431748d0efa233949d2f611 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Tue, 28 Jun 2016 21:02:15 +0300 Subject: [PATCH 237/239] sign command --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 05111c821..3811bcd96 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -26,7 +26,7 @@ after_test: - cargo build --verbose --release - makensis.exe nsis\installer.nsi - ps: if($env:cert) { Start-FileDownload $env:cert -FileName $env:keyfile } - - ps: if($env:cert) { signtool /f $env:keyfile /p $env:certpass nsis\installer.exe } + - ps: if($env:cert) { signtool sign /f $env:keyfile /p $env:certpass nsis\installer.exe } artifacts: - path: nsis\installer.exe From 72771bd8337ddd936db9ae36bbf3af29a4f607c8 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Wed, 29 Jun 2016 01:58:15 +0300 Subject: [PATCH 238/239] signing executable also --- appveyor.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 3811bcd96..64f5dc132 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,8 +24,9 @@ test_script: after_test: - cargo build --verbose --release - - makensis.exe nsis\installer.nsi - ps: if($env:cert) { Start-FileDownload $env:cert -FileName $env:keyfile } + - ps: if($env:cert) { signtool sign /f $env:keyfile /p $env:certpass target\release\parity.exe } + - makensis.exe nsis\installer.nsi - ps: if($env:cert) { signtool sign /f $env:keyfile /p $env:certpass nsis\installer.exe } artifacts: From e3214c63c6a47e47c8920aeeb892b5998d2c6d41 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 29 Jun 2016 09:28:56 +0200 Subject: [PATCH 239/239] Rearrange fork CLI options. (#1476) * Rearrange fork CLI options. * Fixed compilation --- parity/cli.rs | 21 +++++++++------------ parity/configuration.rs | 26 +++++++++++++++++++++----- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/parity/cli.rs b/parity/cli.rs index 3ee6f31c8..27578df73 100644 --- a/parity/cli.rs +++ b/parity/cli.rs @@ -42,14 +42,12 @@ Protocol Options: --keys-path PATH Specify the path for JSON key files to be found [default: $HOME/.parity/keys]. --identity NAME Specify your node's name. - -DAO-Rescue Soft-fork Options: - --help-rescue-dao Does nothing - on by default. - --dont-help-rescue-dao Votes against the DAO-rescue soft-fork, but supports - it if it is triggered anyway. - Equivalent to --gas-floor-target=3141592. - --dogmatic Ignores all DAO-rescue soft-fork behaviour. Even if - it means losing mining rewards. + --fork POLICY Specifies the client's fork policy. POLICY must be + one of: + dogmatic - sticks rigidly to the standard chain. + dao-soft - votes for the DAO-rescue soft-fork. + normal - goes with whatever fork is decided but + votes for none. [default: normal]. Account Options: --unlock ACCOUNTS Unlock ACCOUNTS for the duration of the execution. @@ -157,9 +155,9 @@ Sealing/Mining Options: web service in turn and fallback on the last known good value [default: auto]. --gas-floor-target GAS Amount of gas per block to target when sealing a new - block [default: 3141592]. + block [default: 4700000]. --gas-cap GAS A cap on how large we will raise the gas limit per - block due to transaction volume [default: 3141592]. + block due to transaction volume [default: 6283184]. --extra-data STRING Specify a custom extra-data for authored blocks, no more than 32 characters. --tx-queue-size LIMIT Maximum amount of transactions in the queue (waiting @@ -262,8 +260,7 @@ pub struct Args { pub flag_chain: String, pub flag_db_path: String, pub flag_identity: String, - pub flag_dont_help_rescue_dao: bool, - pub flag_dogmatic: bool, + pub flag_fork: String, pub flag_unlock: Option, pub flag_password: Vec, pub flag_cache: Option, diff --git a/parity/configuration.rs b/parity/configuration.rs index 4bd0cd493..121d40e6e 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -45,6 +45,13 @@ pub struct Directories { pub signer: String, } +#[derive(Eq, PartialEq, Debug)] +pub enum Policy { + DaoSoft, + Normal, + Dogmatic, +} + impl Configuration { pub fn parse() -> Self { Configuration { @@ -107,9 +114,18 @@ impl Configuration { })) } + pub fn policy(&self) -> Policy { + match self.args.flag_fork.as_str() { + "dao-soft" => Policy::DaoSoft, + "normal" => Policy::Normal, + "dogmatic" => Policy::Dogmatic, + x => die!("{}: Invalid value given for --policy option. Use --help for more info.", x) + } + } + pub fn gas_floor_target(&self) -> U256 { - if self.args.flag_dont_help_rescue_dao || self.args.flag_dogmatic { - 4_700_000.into() + if self.policy() == Policy::DaoSoft { + 3_141_592.into() } else { let d = &self.args.flag_gas_floor_target; U256::from_dec_str(d).unwrap_or_else(|_| { @@ -119,8 +135,8 @@ impl Configuration { } pub fn gas_ceil_target(&self) -> U256 { - if self.args.flag_dont_help_rescue_dao || self.args.flag_dogmatic { - 10_000_000.into() + if self.policy() == Policy::DaoSoft { + 3_141_592.into() } else { let d = &self.args.flag_gas_cap; U256::from_dec_str(d).unwrap_or_else(|_| { @@ -172,7 +188,7 @@ impl Configuration { pub fn spec(&self) -> Spec { match self.chain().as_str() { - "frontier" | "homestead" | "mainnet" => ethereum::new_frontier(!self.args.flag_dogmatic), + "frontier" | "homestead" | "mainnet" => ethereum::new_frontier(self.policy() != Policy::Dogmatic), "morden" | "testnet" => ethereum::new_morden(), "olympic" => ethereum::new_olympic(), f => Spec::load(contents(f).unwrap_or_else(|_| {