From 343b29866c4cc592afa9038995217b6ba99e70fa Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 25 May 2018 10:16:08 +0800 Subject: [PATCH 01/29] new blooms database --- Cargo.lock | 12 + Cargo.toml | 1 + ethcore/Cargo.toml | 3 +- ethcore/light/src/client/service.rs | 7 +- ethcore/service/src/service.rs | 13 +- ethcore/src/blockchain/blockchain.rs | 227 ++++++-------- ethcore/src/blockchain/cache.rs | 4 +- ethcore/src/blockchain/extras.rs | 28 -- ethcore/src/blockchain/mod.rs | 2 +- ethcore/src/blockchain/update.rs | 5 +- ethcore/src/blooms/bloom_group.rs | 8 - ethcore/src/client/client.rs | 36 +-- ethcore/src/lib.rs | 3 +- ethcore/src/snapshot/consensus/authority.rs | 6 +- ethcore/src/snapshot/consensus/mod.rs | 4 +- ethcore/src/snapshot/consensus/work.rs | 6 +- ethcore/src/snapshot/service.rs | 17 +- ethcore/src/snapshot/tests/helpers.rs | 6 +- .../src/snapshot/tests/proof_of_authority.rs | 9 +- ethcore/src/snapshot/tests/proof_of_work.rs | 9 +- ethcore/src/snapshot/tests/service.rs | 9 +- ethcore/src/test_helpers.rs | 43 ++- ethcore/src/test_helpers_internal.rs | 35 ++- ethcore/src/tests/client.rs | 46 +-- ethcore/src/tests/trace.rs | 10 +- ethcore/src/tx_filter.rs | 6 +- parity/db/rocksdb/mod.rs | 68 +++-- parity/lib.rs | 1 + parity/run.rs | 2 +- util/blooms-db/Cargo.toml | 12 + util/blooms-db/benches/blooms.rs | 30 ++ util/blooms-db/src/db.rs | 279 ++++++++++++++++++ util/blooms-db/src/file.rs | 134 +++++++++ util/blooms-db/src/lib.rs | 20 ++ util/blooms-db/src/meta.rs | 41 +++ util/blooms-db/src/pending.rs | 158 ++++++++++ 36 files changed, 997 insertions(+), 303 deletions(-) create mode 100644 util/blooms-db/Cargo.toml create mode 100644 util/blooms-db/benches/blooms.rs create mode 100644 util/blooms-db/src/db.rs create mode 100644 util/blooms-db/src/file.rs create mode 100644 util/blooms-db/src/lib.rs create mode 100644 util/blooms-db/src/meta.rs create mode 100644 util/blooms-db/src/pending.rs diff --git a/Cargo.lock b/Cargo.lock index e4c80310c1c..80dd7d83b35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,6 +159,16 @@ dependencies = [ "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "blooms-db" +version = "0.1.0" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bn" version = "0.4.4" @@ -513,6 +523,7 @@ version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "bloomchain 0.2.0", + "blooms-db 0.1.0", "bn 0.4.4 (git+https://github.com/paritytech/bn)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", @@ -1959,6 +1970,7 @@ version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "blooms-db 0.1.0", "clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)", "daemonize 0.2.3 (git+https://github.com/paritytech/daemonize)", diff --git a/Cargo.toml b/Cargo.toml index de1a78bf4fa..1166fd33c54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ license = "GPL-3.0" authors = ["Parity Technologies "] [dependencies] +blooms-db = { path = "util/blooms-db" } log = "0.3" env_logger = "0.4" rustc-hex = "1.0" diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 71c84a293f9..88e8ff85049 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -9,6 +9,7 @@ authors = ["Parity Technologies "] [dependencies] ansi_term = "0.10" bloomchain = { path = "../util/bloomchain" } +blooms-db = { path = "../util/blooms-db" } bn = { git = "https://github.com/paritytech/bn", default-features = false } byteorder = "1.0" common-types = { path = "types" } @@ -67,8 +68,6 @@ keccak-hash = { path = "../util/hash" } triehash = { path = "../util/triehash" } unexpected = { path = "../util/unexpected" } journaldb = { path = "../util/journaldb" } - -[dev-dependencies] tempdir = "0.3" trie-standardmap = { path = "../util/trie-standardmap" } kvdb-rocksdb = { path = "../util/kvdb-rocksdb" } diff --git a/ethcore/light/src/client/service.rs b/ethcore/light/src/client/service.rs index a3ec8a36866..8394314d385 100644 --- a/ethcore/light/src/client/service.rs +++ b/ethcore/light/src/client/service.rs @@ -21,7 +21,7 @@ use std::fmt; use std::sync::Arc; use ethcore::client::ClientIoMessage; -use ethcore::db; +use ethcore::{db, BlockChainDB}; use ethcore::error::Error as CoreError; use ethcore::spec::Spec; use io::{IoContext, IoError, IoHandler, IoService}; @@ -65,11 +65,10 @@ pub struct Service { impl Service { /// Start the service: initialize I/O workers and client itself. - pub fn start(config: ClientConfig, spec: &Spec, fetcher: T, db: Arc, cache: Arc>) -> Result { - + pub fn start(config: ClientConfig, spec: &Spec, fetcher: T, db: Arc, cache: Arc>) -> Result { let io_service = IoService::::start().map_err(Error::Io)?; let client = Arc::new(Client::new(config, - db, + db.key_value().clone(), db::COL_LIGHT_CHAIN, spec, fetcher, diff --git a/ethcore/service/src/service.rs b/ethcore/service/src/service.rs index 5f46799796a..97ef81caa2c 100644 --- a/ethcore/service/src/service.rs +++ b/ethcore/service/src/service.rs @@ -26,6 +26,7 @@ use kvdb::{KeyValueDB, KeyValueDBHandler}; use stop_guard::StopGuard; use sync::PrivateTxHandler; +use ethcore::{BlockChainDB, BlockChainDBHandler}; use ethcore::client::{Client, ClientConfig, ChainNotify, ClientIoMessage}; use ethcore::miner::Miner; use ethcore::snapshot::service::{Service as SnapshotService, ServiceParams as SnapServiceParams}; @@ -69,7 +70,7 @@ pub struct ClientService { client: Arc, snapshot: Arc, private_tx: Arc, - database: Arc, + database: Arc, _stop_guard: StopGuard, } @@ -78,9 +79,9 @@ impl ClientService { pub fn start( config: ClientConfig, spec: &Spec, - client_db: Arc, + blockchain_db: Arc, snapshot_path: &Path, - restoration_db_handler: Box, + restoration_db_handler: Box, _ipc_path: &Path, miner: Arc, account_provider: Arc, @@ -93,7 +94,7 @@ impl ClientService { info!("Configured for {} using {} engine", Colour::White.bold().paint(spec.name.clone()), Colour::Yellow.bold().paint(spec.engine.name())); let pruning = config.pruning; - let client = Client::new(config, &spec, client_db.clone(), miner.clone(), io_service.channel())?; + let client = Client::new(config, &spec, blockchain_db.clone(), miner.clone(), io_service.channel())?; let snapshot_params = SnapServiceParams { engine: spec.engine.clone(), @@ -131,7 +132,7 @@ impl ClientService { client: client, snapshot: snapshot, private_tx, - database: client_db, + database: blockchain_db, _stop_guard: stop_guard, }) } @@ -167,7 +168,7 @@ impl ClientService { } /// Get a handle to the database. - pub fn db(&self) -> Arc { self.database.clone() } + pub fn db(&self) -> Arc { self.database.clone() } } /// IO interface for the Client handler diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index f2621d00e1b..43b35f9f0ac 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -16,11 +16,11 @@ //! Blockchain database. -use std::collections::{HashMap, HashSet, hash_map}; +use std::collections::{HashMap, HashSet}; use std::sync::Arc; use std::mem; use itertools::Itertools; -use bloomchain as bc; +use blooms_db; use heapsize::HeapSizeOf; use ethereum_types::{H256, Bloom, U256}; use parking_lot::{Mutex, RwLock}; @@ -32,7 +32,6 @@ use transaction::*; use views::{BlockView, HeaderView}; use log_entry::{LogEntry, LocalizedLogEntry}; use receipt::Receipt; -use blooms::{BloomGroup, GroupPosition}; use blockchain::best_block::{BestBlock, BestAncientBlock}; use blockchain::block_info::{BlockInfo, BlockLocation, BranchBecomingCanonChainData}; use blockchain::extras::{BlockReceipts, BlockDetails, TransactionAddress, EPOCH_KEY_PREFIX, EpochTransitions}; @@ -48,9 +47,20 @@ use engines::epoch::{Transition as EpochTransition, PendingTransition as Pending use rayon::prelude::*; use ansi_term::Colour; use kvdb::{DBTransaction, KeyValueDB}; +use error::Error; +use std::path::Path; -const LOG_BLOOMS_LEVELS: usize = 3; -const LOG_BLOOMS_ELEMENTS_PER_INDEX: usize = 16; +/// Database backing `BlockChain`. +pub trait BlockChainDB: Send + Sync { + fn key_value(&self) -> &Arc; + + fn blooms(&self) -> &RwLock; +} + +pub trait BlockChainDBHandler: Send + Sync { + /// Open the predefined key-value database. + fn open(&self, path: &Path) -> Result, Error>; +} /// Interface for querying blocks by hash and by number. pub trait BlockProvider { @@ -166,26 +176,14 @@ enum CacheId { BlockDetails(H256), BlockHashes(BlockNumber), TransactionAddresses(H256), - BlocksBlooms(GroupPosition), BlockReceipts(H256), } -impl bc::group::BloomGroupDatabase for BlockChain { - fn blooms_at(&self, position: &bc::group::GroupPosition) -> Option { - let position = GroupPosition::from(position.clone()); - let result = self.db.read_with_cache(db::COL_EXTRA, &self.blocks_blooms, &position).map(Into::into); - self.cache_man.lock().note_used(CacheId::BlocksBlooms(position)); - result - } -} - /// Structure providing fast access to blockchain data. /// /// **Does not do input data verification.** pub struct BlockChain { // All locks must be captured in the order declared here. - blooms_config: bc::Config, - best_block: RwLock, // Stores best block of the first uninterrupted sequence of blocks. `None` if there are no gaps. // Only updated with `insert_unordered_block`. @@ -202,10 +200,9 @@ pub struct BlockChain { block_details: RwLock>, block_hashes: RwLock>, transaction_addresses: RwLock>, - blocks_blooms: RwLock>, block_receipts: RwLock>, - db: Arc, + db: Arc, cache_man: Mutex>, @@ -219,7 +216,7 @@ impl BlockProvider for BlockChain { /// Returns true if the given block is known /// (though not necessarily a part of the canon chain). fn is_known(&self, hash: &H256) -> bool { - self.db.exists_with_cache(db::COL_EXTRA, &self.block_details, hash) + self.db.key_value().exists_with_cache(db::COL_EXTRA, &self.block_details, hash) } fn first_block(&self) -> Option { @@ -260,7 +257,7 @@ impl BlockProvider for BlockChain { } // Read from DB and populate cache - let b = self.db.get(db::COL_HEADERS, hash) + let b = self.db.key_value().get(db::COL_HEADERS, hash) .expect("Low level database error. Some issue with disk?")?; let header = encoded::Header::new(decompress(&b, blocks_swapper()).into_vec()); @@ -290,7 +287,7 @@ impl BlockProvider for BlockChain { } // Read from DB and populate cache - let b = self.db.get(db::COL_BODIES, hash) + let b = self.db.key_value().get(db::COL_BODIES, hash) .expect("Low level database error. Some issue with disk?")?; let body = encoded::Body::new(decompress(&b, blocks_swapper()).into_vec()); @@ -303,40 +300,39 @@ impl BlockProvider for BlockChain { /// Get the familial details concerning a block. fn block_details(&self, hash: &H256) -> Option { - let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_details, hash)?; + let result = self.db.key_value().read_with_cache(db::COL_EXTRA, &self.block_details, hash)?; self.cache_man.lock().note_used(CacheId::BlockDetails(*hash)); Some(result) } /// Get the hash of given block's number. fn block_hash(&self, index: BlockNumber) -> Option { - let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_hashes, &index)?; + let result = self.db.key_value().read_with_cache(db::COL_EXTRA, &self.block_hashes, &index)?; self.cache_man.lock().note_used(CacheId::BlockHashes(index)); Some(result) } /// Get the address of transaction with given hash. fn transaction_address(&self, hash: &H256) -> Option { - let result = self.db.read_with_cache(db::COL_EXTRA, &self.transaction_addresses, hash)?; + let result = self.db.key_value().read_with_cache(db::COL_EXTRA, &self.transaction_addresses, hash)?; self.cache_man.lock().note_used(CacheId::TransactionAddresses(*hash)); Some(result) } /// Get receipts of block with given hash. fn block_receipts(&self, hash: &H256) -> Option { - let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_receipts, hash)?; + let result = self.db.key_value().read_with_cache(db::COL_EXTRA, &self.block_receipts, hash)?; self.cache_man.lock().note_used(CacheId::BlockReceipts(*hash)); Some(result) } /// Returns numbers of blocks containing given bloom. fn blocks_with_bloom(&self, bloom: &Bloom, from_block: BlockNumber, to_block: BlockNumber) -> Vec { - let range = from_block as bc::Number..to_block as bc::Number; - let chain = bc::group::BloomGroupChain::new(self.blooms_config, self); - chain.with_bloom(&range, bloom) - .into_iter() - .map(|b| b as BlockNumber) - .collect() + self.db.blooms().read() + .iterate_matching(from_block, to_block, bloom) + .expect("TODO: blooms pr") + .collect::, _>>() + .expect("TODO: blooms pr") } /// Returns logs matching given filter. The order of logs returned will be the same as the order of the blocks @@ -498,15 +494,11 @@ impl<'a> Iterator for EpochTransitionIter<'a> { impl BlockChain { /// Create new instance of blockchain from given Genesis. - pub fn new(config: Config, genesis: &[u8], db: Arc) -> BlockChain { + pub fn new(config: Config, genesis: &[u8], db: Arc) -> BlockChain { // 400 is the average size of the key let cache_man = CacheManager::new(config.pref_cache_size, config.max_cache_size, 400); let mut bc = BlockChain { - blooms_config: bc::Config { - levels: LOG_BLOOMS_LEVELS, - elements_per_index: LOG_BLOOMS_ELEMENTS_PER_INDEX, - }, first_block: None, best_block: RwLock::new(BestBlock { // BestBlock will be overwritten anyway. @@ -520,7 +512,6 @@ impl BlockChain { block_details: RwLock::new(HashMap::new()), block_hashes: RwLock::new(HashMap::new()), transaction_addresses: RwLock::new(HashMap::new()), - blocks_blooms: RwLock::new(HashMap::new()), block_receipts: RwLock::new(HashMap::new()), db: db.clone(), cache_man: Mutex::new(cache_man), @@ -531,7 +522,7 @@ impl BlockChain { }; // load best block - let best_block_hash = match bc.db.get(db::COL_EXTRA, b"best").unwrap() { + let best_block_hash = match bc.db.key_value().get(db::COL_EXTRA, b"best").unwrap() { Some(best) => { H256::from_slice(&best) } @@ -559,7 +550,7 @@ impl BlockChain { batch.write(db::COL_EXTRA, &header.number(), &hash); batch.put(db::COL_EXTRA, b"best", &hash); - bc.db.write(batch).expect("Low level database error. Some issue with disk?"); + bc.db.key_value().write(batch).expect("Low level database error. Some issue with disk?"); hash } }; @@ -581,8 +572,8 @@ impl BlockChain { { let best_block_number = bc.best_block.read().header.number(); // Fetch first and best ancient block details - let raw_first = bc.db.get(db::COL_EXTRA, b"first").unwrap().map(|v| v.into_vec()); - let mut best_ancient = bc.db.get(db::COL_EXTRA, b"ancient").unwrap().map(|h| H256::from_slice(&h)); + let raw_first = bc.db.key_value().get(db::COL_EXTRA, b"first").unwrap().map(|v| v.into_vec()); + let mut best_ancient = bc.db.key_value().get(db::COL_EXTRA, b"ancient").unwrap().map(|h| H256::from_slice(&h)); let best_ancient_number; if best_ancient.is_none() && best_block_number > 1 && bc.block_hash(1).is_none() { best_ancient = Some(bc.genesis_hash()); @@ -611,9 +602,9 @@ impl BlockChain { if hash != bc.genesis_hash() { trace!("First block calculated: {:?}", hash); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); batch.put(db::COL_EXTRA, b"first", &hash); - db.write(batch).expect("Low level database error."); + db.key_value().write(batch).expect("Low level database error."); bc.first_block = Some(hash); } }, @@ -638,7 +629,7 @@ impl BlockChain { /// Returns true if the given parent block has given child /// (though not necessarily a part of the canon chain). fn is_known_child(&self, parent: &H256, hash: &H256) -> bool { - self.db.read_with_cache(db::COL_EXTRA, &self.block_details, parent).map_or(false, |d| d.children.contains(hash)) + self.db.key_value().read_with_cache(db::COL_EXTRA, &self.block_details, parent).map_or(false, |d| d.children.contains(hash)) } /// Returns a tree route between `from` and `to`, which is a tuple of: @@ -843,7 +834,7 @@ impl BlockChain { /// /// The block the transition occurred at should have already been inserted into the chain. pub fn insert_epoch_transition(&self, batch: &mut DBTransaction, epoch_num: u64, transition: EpochTransition) { - let mut transitions = match self.db.read(db::COL_EXTRA, &epoch_num) { + let mut transitions = match self.db.key_value().read(db::COL_EXTRA, &epoch_num) { Some(existing) => existing, None => EpochTransitions { number: epoch_num, @@ -861,7 +852,7 @@ impl BlockChain { /// Iterate over all epoch transitions. /// This will only return transitions within the canonical chain. pub fn epoch_transitions(&self) -> EpochTransitionIter { - let iter = self.db.iter_from_prefix(db::COL_EXTRA, &EPOCH_KEY_PREFIX[..]); + let iter = self.db.key_value().iter_from_prefix(db::COL_EXTRA, &EPOCH_KEY_PREFIX[..]); EpochTransitionIter { chain: self, prefix_iter: iter, @@ -873,7 +864,7 @@ impl BlockChain { trace!(target: "blockchain", "Loading epoch transition at block {}, {}", block_num, block_hash); - self.db.read(db::COL_EXTRA, &block_num).and_then(|transitions: EpochTransitions| { + self.db.key_value().read(db::COL_EXTRA, &block_num).and_then(|transitions: EpochTransitions| { transitions.candidates.into_iter().find(|c| c.block_hash == block_hash) }) } @@ -919,7 +910,7 @@ impl BlockChain { // TODO: implement removal safely: this can only be done upon finality of a block // that _uses_ the pending transition. pub fn get_pending_transition(&self, hash: H256) -> Option { - self.db.read(db::COL_EXTRA, &hash) + self.db.key_value().read(db::COL_EXTRA, &hash) } /// Add a child to a given block. Assumes that the block hash is in @@ -1064,35 +1055,8 @@ impl BlockChain { batch.extend_with_cache(db::COL_EXTRA, &mut *write_receipts, update.block_receipts, CacheUpdatePolicy::Remove); } - { - let mut write_blocks_blooms = self.blocks_blooms.write(); - // update best block - match update.info.location { - BlockLocation::Branch => (), - BlockLocation::BranchBecomingCanonChain(_) => { - // clear all existing blooms, cause they may be created for block - // number higher than current best block - *write_blocks_blooms = update.blocks_blooms; - for (key, value) in write_blocks_blooms.iter() { - batch.write(db::COL_EXTRA, key, value); - } - }, - BlockLocation::CanonChain => { - // update all existing blooms groups - for (key, value) in update.blocks_blooms { - match write_blocks_blooms.entry(key) { - hash_map::Entry::Occupied(mut entry) => { - entry.get_mut().accrue_bloom_group(&value); - batch.write(db::COL_EXTRA, entry.key(), entry.get()); - }, - hash_map::Entry::Vacant(entry) => { - batch.write(db::COL_EXTRA, entry.key(), &value); - entry.insert(value); - }, - } - } - }, - } + if let Some((block, blooms)) = update.blocks_blooms { + self.db.blooms().write().insert_blooms(block, blooms.iter()).expect("TODO: blooms pr"); } // These cached values must be updated last with all four locks taken to avoid @@ -1121,6 +1085,7 @@ impl BlockChain { /// Apply pending insertion updates pub fn commit(&self) { + self.db.blooms().write().flush().expect("TODO: blooms pr"); let mut pending_best_block = self.pending_best_block.write(); let mut pending_write_hashes = self.pending_block_hashes.write(); let mut pending_block_details = self.pending_block_details.write(); @@ -1355,25 +1320,23 @@ impl BlockChain { /// Later, BloomIndexer is used to map bloom location on filter layer (BloomIndex) /// to bloom location in database (BlocksBloomLocation). /// - fn prepare_block_blooms_update(&self, block_bytes: &[u8], info: &BlockInfo) -> HashMap { + fn prepare_block_blooms_update(&self, block_bytes: &[u8], info: &BlockInfo) -> Option<(u64, Vec)> { let block = view!(BlockView, block_bytes); let header = block.header_view(); - let log_blooms = match info.location { - BlockLocation::Branch => HashMap::new(), + match info.location { + BlockLocation::Branch => None, BlockLocation::CanonChain => { let log_bloom = header.log_bloom(); if log_bloom.is_zero() { - HashMap::new() + None } else { - let chain = bc::group::BloomGroupChain::new(self.blooms_config, self); - chain.insert(info.number as bc::Number, log_bloom) + Some((info.number, vec![log_bloom])) } }, BlockLocation::BranchBecomingCanonChain(ref data) => { let ancestor_number = self.block_number(&data.ancestor).unwrap(); let start_number = ancestor_number + 1; - let range = start_number as bc::Number..self.best_block_number() as bc::Number; let mut blooms: Vec = data.enacted.iter() .map(|hash| self.block_header_data(hash).unwrap()) @@ -1381,15 +1344,9 @@ impl BlockChain { .collect(); blooms.push(header.log_bloom()); - - let chain = bc::group::BloomGroupChain::new(self.blooms_config, self); - chain.replace(&range, blooms) + Some((start_number, blooms)) } - }; - - log_blooms.into_iter() - .map(|p| (From::from(p.0), From::from(p.1))) - .collect() + } } /// Get best block hash. @@ -1423,7 +1380,6 @@ impl BlockChain { blocks: self.block_headers.read().heap_size_of_children() + self.block_bodies.read().heap_size_of_children(), block_details: self.block_details.read().heap_size_of_children(), transaction_addresses: self.transaction_addresses.read().heap_size_of_children(), - blocks_blooms: self.blocks_blooms.read().heap_size_of_children(), block_receipts: self.block_receipts.read().heap_size_of_children(), } } @@ -1437,7 +1393,6 @@ impl BlockChain { let mut block_details = self.block_details.write(); let mut block_hashes = self.block_hashes.write(); let mut transaction_addresses = self.transaction_addresses.write(); - let mut blocks_blooms = self.blocks_blooms.write(); let mut block_receipts = self.block_receipts.write(); let mut cache_man = self.cache_man.lock(); @@ -1449,7 +1404,6 @@ impl BlockChain { CacheId::BlockDetails(ref h) => { block_details.remove(h); } CacheId::BlockHashes(ref h) => { block_hashes.remove(h); } CacheId::TransactionAddresses(ref h) => { transaction_addresses.remove(h); } - CacheId::BlocksBlooms(ref h) => { blocks_blooms.remove(h); } CacheId::BlockReceipts(ref h) => { block_receipts.remove(h); } } } @@ -1459,7 +1413,6 @@ impl BlockChain { block_details.shrink_to_fit(); block_hashes.shrink_to_fit(); transaction_addresses.shrink_to_fit(); - blocks_blooms.shrink_to_fit(); block_receipts.shrink_to_fit(); block_headers.heap_size_of_children() + @@ -1467,7 +1420,6 @@ impl BlockChain { block_details.heap_size_of_children() + block_hashes.heap_size_of_children() + transaction_addresses.heap_size_of_children() + - blocks_blooms.heap_size_of_children() + block_receipts.heap_size_of_children() }); } @@ -1511,7 +1463,7 @@ mod tests { use kvdb_memorydb; use ethereum_types::*; use receipt::{Receipt, TransactionOutcome}; - use blockchain::{BlockProvider, BlockChain, Config, ImportRoute}; + use blockchain::{BlockProvider, BlockChain, BlockChainDB, Config, ImportRoute}; use test_helpers::{ generate_dummy_blockchain, generate_dummy_blockchain_with_extra, generate_dummy_empty_blockchain @@ -1521,23 +1473,24 @@ mod tests { use transaction::{Transaction, Action}; use log_entry::{LogEntry, LocalizedLogEntry}; use ethkey::Secret; + use test_helpers::new_db; - fn new_db() -> Arc { - Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))) - } + //fn new_db() -> Arc + //Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))) + //} - fn new_chain(genesis: &[u8], db: Arc) -> BlockChain { + fn new_chain(genesis: &[u8], db: Arc) -> BlockChain { BlockChain::new(Config::default(), genesis, db) } - fn insert_block(db: &Arc, bc: &BlockChain, bytes: &[u8], receipts: Vec) -> ImportRoute { + fn insert_block(db: &Arc, bc: &BlockChain, bytes: &[u8], receipts: Vec) -> ImportRoute { insert_block_commit(db, bc, bytes, receipts, true) } - fn insert_block_commit(db: &Arc, bc: &BlockChain, bytes: &[u8], receipts: Vec, commit: bool) -> ImportRoute { - let mut batch = db.transaction(); + fn insert_block_commit(db: &Arc, bc: &BlockChain, bytes: &[u8], receipts: Vec, commit: bool) -> ImportRoute { + let mut batch = db.key_value().transaction(); let res = insert_block_batch(&mut batch, bc, bytes, receipts); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); if commit { bc.commit(); } @@ -1606,9 +1559,9 @@ mod tests { assert_eq!(bc.block_hash(1), None); assert_eq!(bc.block_details(&genesis_hash).unwrap().children, vec![]); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); insert_block_batch(&mut batch, &bc, &first.encoded(), vec![]); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); bc.commit(); assert_eq!(bc.block_hash(0), Some(genesis_hash)); @@ -1630,13 +1583,13 @@ mod tests { let bc = new_chain(&genesis.last().encoded(), db.clone()); let mut block_hashes = vec![genesis.last().hash()]; - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); for block in generator { block_hashes.push(block.hash()); insert_block_batch(&mut batch, &bc, &block.encoded(), vec![]); bc.commit(); } - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); block_hashes.reverse(); @@ -1709,12 +1662,12 @@ mod tests { let db = new_db(); let bc = new_chain(&genesis.last().encoded(), db.clone()); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); let _ = insert_block_batch(&mut batch, &bc, &b1a.last().encoded(), vec![]); bc.commit(); let _ = insert_block_batch(&mut batch, &bc, &b1b.last().encoded(), vec![]); bc.commit(); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); assert_eq!(bc.best_block_hash(), b1a_hash); assert_eq!(bc.transaction_address(&t1_hash), Some(TransactionAddress { @@ -1723,10 +1676,10 @@ mod tests { })); // now let's make forked chain the canon chain - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); let _ = insert_block_batch(&mut batch, &bc, &b2.last().encoded(), vec![]); bc.commit(); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); // Transaction should be retracted assert_eq!(bc.best_block_hash(), b2_hash); @@ -1784,12 +1737,12 @@ mod tests { let db = new_db(); let bc = new_chain(&genesis.last().encoded(), db.clone()); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); let _ = insert_block_batch(&mut batch, &bc, &b1a.last().encoded(), vec![]); bc.commit(); let _ = insert_block_batch(&mut batch, &bc, &b1b.last().encoded(), vec![]); bc.commit(); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); assert_eq!(bc.best_block_hash(), b1a_hash); assert_eq!(bc.transaction_address(&t1_hash), Some(TransactionAddress { @@ -1802,10 +1755,10 @@ mod tests { })); // now let's make forked chain the canon chain - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); let _ = insert_block_batch(&mut batch, &bc, &b2.last().encoded(), vec![]); bc.commit(); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); assert_eq!(bc.best_block_hash(), b2_hash); assert_eq!(bc.transaction_address(&t1_hash), Some(TransactionAddress { @@ -1842,19 +1795,19 @@ mod tests { let db = new_db(); let bc = new_chain(&genesis.last().encoded(), db.clone()); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); let ir1 = insert_block_batch(&mut batch, &bc, &b1.last().encoded(), vec![]); bc.commit(); let ir2 = insert_block_batch(&mut batch, &bc, &b2.last().encoded(), vec![]); bc.commit(); let ir3b = insert_block_batch(&mut batch, &bc, &b3b.last().encoded(), vec![]); bc.commit(); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); assert_eq!(bc.block_hash(3).unwrap(), b3b_hash); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); let ir3a = insert_block_batch(&mut batch, &bc, &b3a.last().encoded(), vec![]); bc.commit(); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); assert_eq!(ir1, ImportRoute { enacted: vec![b1_hash], @@ -1956,9 +1909,9 @@ mod tests { { let bc = new_chain(&genesis.last().encoded(), db.clone()); assert_eq!(bc.best_block_hash(), genesis_hash); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); insert_block_batch(&mut batch, &bc, &first.last().encoded(), vec![]); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); bc.commit(); assert_eq!(bc.best_block_hash(), first_hash); } @@ -2015,9 +1968,9 @@ mod tests { let db = new_db(); let bc = new_chain(&genesis, db.clone()); - let mut batch =db.transaction(); + let mut batch = db.key_value().transaction(); insert_block_batch(&mut batch, &bc, &b1, vec![]); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); bc.commit(); let transactions = bc.transactions(&b1_hash).unwrap(); @@ -2273,14 +2226,14 @@ mod tests { let db = new_db(); let bc = new_chain(&genesis.last().encoded(), db.clone()); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); bc.insert_unordered_block(&mut batch, &b2.last().encoded(), vec![], Some(b1_total_difficulty), false, false); bc.commit(); bc.insert_unordered_block(&mut batch, &b3.last().encoded(), vec![], None, true, false); bc.commit(); bc.insert_unordered_block(&mut batch, &b1.last().encoded(), vec![], None, false, false); bc.commit(); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); assert_eq!(bc.best_block_hash(), b3.last().hash()); assert_eq!(bc.block_hash(1).unwrap(), b1.last().hash()); @@ -2307,7 +2260,7 @@ mod tests { { let bc = new_chain(&genesis.last().encoded(), db.clone()); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); // create a longer fork for block in generator { insert_block_batch(&mut batch, &bc, &block.encoded(), vec![]); @@ -2316,7 +2269,7 @@ mod tests { assert_eq!(bc.best_block_number(), 5); insert_block_batch(&mut batch, &bc, &uncle.last().encoded(), vec![]); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); bc.commit(); } @@ -2338,7 +2291,7 @@ mod tests { { let bc = new_chain(&genesis.last().encoded(), db.clone()); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); // create a longer fork for (i, block) in generator.into_iter().enumerate() { @@ -2360,7 +2313,7 @@ mod tests { proof: vec![], }); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); bc.commit(); // epoch 999 not in canonical chain. @@ -2391,13 +2344,13 @@ mod tests { let bc = new_chain(&genesis.last().encoded(), db.clone()); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); bc.insert_epoch_transition(&mut batch, 0, EpochTransition { block_hash: bc.genesis_hash(), block_number: 0, proof: vec![], }); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); // set up a chain where we have a canonical chain of 10 blocks // and a non-canonical fork of 8 from genesis. @@ -2416,13 +2369,13 @@ mod tests { assert_eq!(bc.best_block_number(), 10); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); bc.insert_epoch_transition(&mut batch, 4, EpochTransition { block_hash: bc.block_hash(4).unwrap(), block_number: 4, proof: vec![], }); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); // blocks where the parent is one of the first 4 will be part of genesis epoch. for i in 0..4 { diff --git a/ethcore/src/blockchain/cache.rs b/ethcore/src/blockchain/cache.rs index 999be423df7..5a609f9d728 100644 --- a/ethcore/src/blockchain/cache.rs +++ b/ethcore/src/blockchain/cache.rs @@ -23,8 +23,6 @@ pub struct CacheSize { pub block_details: usize, /// Transaction addresses cache size. pub transaction_addresses: usize, - /// Blooms cache size. - pub blocks_blooms: usize, /// Block receipts size. pub block_receipts: usize, } @@ -32,6 +30,6 @@ pub struct CacheSize { impl CacheSize { /// Total amount used by the cache. pub fn total(&self) -> usize { - self.blocks + self.block_details + self.transaction_addresses + self.blocks_blooms + self.block_receipts + self.blocks + self.block_details + self.transaction_addresses + self.block_receipts } } diff --git a/ethcore/src/blockchain/extras.rs b/ethcore/src/blockchain/extras.rs index 3fb25e7b1b1..edc0e1a5f73 100644 --- a/ethcore/src/blockchain/extras.rs +++ b/ethcore/src/blockchain/extras.rs @@ -18,7 +18,6 @@ use std::ops; use std::io::Write; -use blooms::{GroupPosition, BloomGroup}; use db::Key; use engines::epoch::{Transition as EpochTransition}; use header::BlockNumber; @@ -38,8 +37,6 @@ pub enum ExtrasIndex { BlockHash = 1, /// Transaction address index TransactionAddress = 2, - /// Block blooms index - BlocksBlooms = 3, /// Block receipts index BlockReceipts = 4, /// Epoch transition data index. @@ -87,31 +84,6 @@ impl Key for H256 { } } -pub struct LogGroupKey([u8; 6]); - -impl ops::Deref for LogGroupKey { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Key for GroupPosition { - type Target = LogGroupKey; - - fn key(&self) -> Self::Target { - let mut result = [0u8; 6]; - result[0] = ExtrasIndex::BlocksBlooms as u8; - result[1] = self.level; - result[2] = (self.index >> 24) as u8; - result[3] = (self.index >> 16) as u8; - result[4] = (self.index >> 8) as u8; - result[5] = self.index as u8; - LogGroupKey(result) - } -} - impl Key for H256 { type Target = H264; diff --git a/ethcore/src/blockchain/mod.rs b/ethcore/src/blockchain/mod.rs index f991692dedf..e9a19178f1d 100644 --- a/ethcore/src/blockchain/mod.rs +++ b/ethcore/src/blockchain/mod.rs @@ -28,7 +28,7 @@ mod update; #[cfg(test)] pub mod generator; -pub use self::blockchain::{BlockProvider, BlockChain}; +pub use self::blockchain::{BlockProvider, BlockChain, BlockChainDB, BlockChainDBHandler}; pub use self::cache::CacheSize; pub use self::config::Config; pub use self::extras::{BlockReceipts, BlockDetails, TransactionAddress}; diff --git a/ethcore/src/blockchain/update.rs b/ethcore/src/blockchain/update.rs index b695b9236b0..710e549fc2d 100644 --- a/ethcore/src/blockchain/update.rs +++ b/ethcore/src/blockchain/update.rs @@ -1,9 +1,8 @@ use std::collections::HashMap; -use ethereum_types::H256; +use ethereum_types::{H256, Bloom}; use header::BlockNumber; use blockchain::block_info::BlockInfo; use blockchain::extras::{BlockDetails, BlockReceipts, TransactionAddress}; -use blooms::{BloomGroup, GroupPosition}; /// Block extras update info. pub struct ExtrasUpdate<'a> { @@ -18,7 +17,7 @@ pub struct ExtrasUpdate<'a> { /// Modified block receipts. pub block_receipts: HashMap, /// Modified blocks blooms. - pub blocks_blooms: HashMap, + pub blocks_blooms: Option<(u64, Vec)>, /// Modified transaction addresses (None signifies removed transactions). pub transactions_addresses: HashMap>, } diff --git a/ethcore/src/blooms/bloom_group.rs b/ethcore/src/blooms/bloom_group.rs index 4b47b1ad947..bb4a160b8a0 100644 --- a/ethcore/src/blooms/bloom_group.rs +++ b/ethcore/src/blooms/bloom_group.rs @@ -24,14 +24,6 @@ pub struct BloomGroup { blooms: Vec, } -impl BloomGroup { - pub fn accrue_bloom_group(&mut self, group: &BloomGroup) { - for (bloom, other) in self.blooms.iter_mut().zip(group.blooms.iter()) { - bloom.accrue_bloom(other); - } - } -} - impl From for BloomGroup { fn from(group: bc::BloomGroup) -> Self { BloomGroup { diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 5cfe8fce82c..e2a3833c6df 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -33,7 +33,7 @@ use util_error::UtilError; // other use ethereum_types::{H256, Address, U256}; use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock}; -use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert}; +use blockchain::{BlockChain, BlockChainDB, BlockProvider, TreeRoute, ImportRoute, TransactionAddress, ExtrasInsert}; use client::ancient_import::AncientVerifier; use client::Error as ClientError; use client::{ @@ -190,7 +190,7 @@ pub struct Client { pruning: journaldb::Algorithm, /// Client uses this to store blocks, traces, etc. - db: RwLock>, + db: RwLock>, state_db: RwLock, @@ -337,7 +337,7 @@ impl Importer { } } - client.db.read().flush().expect("DB flush failed."); + client.db.read().key_value().flush().expect("DB flush failed."); imported } @@ -552,7 +552,7 @@ impl Importer { let is_canon = route.enacted.last().map_or(false, |h| h == hash); state.sync_cache(&route.enacted, &route.retracted, is_canon); // Final commit to the DB - client.db.read().write_buffered(batch); + client.db.read().key_value().write_buffered(batch); chain.commit(); self.check_epoch_end(&header, &chain, client); @@ -680,7 +680,7 @@ impl Importer { // always write the batch directly since epoch transition proofs are // fetched from a DB iterator and DB iterators are only available on // flushed data. - client.db.read().write(batch).expect("DB flush failed"); + client.db.read().key_value().write(batch).expect("DB flush failed"); } } } @@ -691,7 +691,7 @@ impl Client { pub fn new( config: ClientConfig, spec: &Spec, - db: Arc, + db: Arc, miner: Arc, message_channel: IoChannel, ) -> Result, ::error::Error> { @@ -707,19 +707,19 @@ impl Client { accountdb: Default::default(), }; - let journal_db = journaldb::new(db.clone(), config.pruning, ::db::COL_STATE); + let journal_db = journaldb::new(db.key_value().clone(), config.pruning, ::db::COL_STATE); let mut state_db = StateDB::new(journal_db, config.state_cache_size); if state_db.journal_db().is_empty() { // Sets the correct state root. state_db = spec.ensure_db_good(state_db, &factories)?; let mut batch = DBTransaction::new(); state_db.journal_under(&mut batch, 0, &spec.genesis_header().hash())?; - db.write(batch).map_err(ClientError::Database)?; + db.key_value().write(batch).map_err(ClientError::Database)?; } let gb = spec.genesis_block(); let chain = Arc::new(BlockChain::new(config.blockchain.clone(), &gb, db.clone())); - let tracedb = RwLock::new(TraceDB::new(config.tracing.clone(), db.clone(), chain.clone())); + let tracedb = RwLock::new(TraceDB::new(config.tracing.clone(), db.key_value().clone(), chain.clone())); trace!("Cleanup journal: DB Earliest = {:?}, Latest = {:?}", state_db.journal_db().earliest_era(), state_db.journal_db().latest_era()); @@ -757,7 +757,7 @@ impl Client { engine: engine, pruning: config.pruning.clone(), config: config, - db: RwLock::new(db), + db: RwLock::new(db.clone()), state_db: RwLock::new(state_db), report: RwLock::new(Default::default()), io_channel: Mutex::new(message_channel), @@ -811,12 +811,12 @@ impl Client { proof: proof, }); - client.db.read().write_buffered(batch); + client.db.read().key_value().write_buffered(batch); } } // ensure buffered changes are flushed. - client.db.read().flush().map_err(ClientError::Database)?; + client.db.read().key_value().flush().map_err(ClientError::Database)?; Ok(client) } @@ -961,7 +961,7 @@ impl Client { Some(ancient_hash) => { let mut batch = DBTransaction::new(); state_db.mark_canonical(&mut batch, era, &ancient_hash)?; - self.db.read().write_buffered(batch); + self.db.read().key_value().write_buffered(batch); state_db.journal_db().flush(); } None => @@ -1290,12 +1290,12 @@ impl snapshot::DatabaseRestore for Client { let mut tracedb = self.tracedb.write(); self.importer.miner.clear(); let db = self.db.write(); - db.restore(new_db)?; + db.key_value().restore(new_db)?; let cache_size = state_db.cache_size(); - *state_db = StateDB::new(journaldb::new(db.clone(), self.pruning, ::db::COL_STATE), cache_size); + *state_db = StateDB::new(journaldb::new(db.key_value().clone(), self.pruning, ::db::COL_STATE), cache_size); *chain = Arc::new(BlockChain::new(self.config.blockchain.clone(), &[], db.clone())); - *tracedb = TraceDB::new(self.config.tracing.clone(), db.clone(), chain.clone()); + *tracedb = TraceDB::new(self.config.tracing.clone(), db.key_value().clone(), chain.clone()); Ok(()) } } @@ -2056,7 +2056,7 @@ impl IoClient for Client { &header, &block_bytes, &receipts_bytes, - &**client.db.read(), + &**client.db.read().key_value(), &*client.chain.read() ); @@ -2192,7 +2192,7 @@ impl ImportSealedBlock for Client { start.elapsed(), ); }); - self.db.read().flush().expect("DB flush failed."); + self.db.read().key_value().flush().expect("DB flush failed."); Ok(h) } } diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index b1782cb1d6c..32bce8cc69c 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -59,6 +59,7 @@ #![recursion_limit="128"] extern crate bloomchain; +extern crate blooms_db; extern crate bn; extern crate byteorder; extern crate crossbeam; @@ -108,7 +109,6 @@ extern crate vm; extern crate wasm; extern crate memory_cache; extern crate journaldb; -#[cfg(test)] extern crate tempdir; #[macro_use] @@ -183,3 +183,4 @@ mod test_helpers_internal; pub use types::*; pub use executive::contract_address; pub use evm::CreateContractAddress; +pub use blockchain::{BlockChainDB, BlockChainDBHandler}; diff --git a/ethcore/src/snapshot/consensus/authority.rs b/ethcore/src/snapshot/consensus/authority.rs index 38d2c184ca1..4a85d9846a6 100644 --- a/ethcore/src/snapshot/consensus/authority.rs +++ b/ethcore/src/snapshot/consensus/authority.rs @@ -24,7 +24,7 @@ use super::{SnapshotComponents, Rebuilder, ChunkSink}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use blockchain::{BlockChain, BlockProvider}; +use blockchain::{BlockChain, BlockChainDB, BlockProvider}; use engines::{EthEngine, EpochVerifier, EpochTransition}; use machine::EthereumMachine; use ids::BlockId; @@ -125,14 +125,14 @@ impl SnapshotComponents for PoaSnapshot { fn rebuilder( &self, chain: BlockChain, - db: Arc, + db: Arc, manifest: &ManifestData, ) -> Result, ::error::Error> { Ok(Box::new(ChunkRebuilder { manifest: manifest.clone(), warp_target: None, chain: chain, - db: db, + db: db.key_value().clone(), had_genesis: false, unverified_firsts: Vec::new(), last_epochs: Vec::new(), diff --git a/ethcore/src/snapshot/consensus/mod.rs b/ethcore/src/snapshot/consensus/mod.rs index 712c245ff37..e1ee2cec925 100644 --- a/ethcore/src/snapshot/consensus/mod.rs +++ b/ethcore/src/snapshot/consensus/mod.rs @@ -20,7 +20,7 @@ use std::sync::atomic::AtomicBool; use std::sync::Arc; -use blockchain::BlockChain; +use blockchain::{BlockChain, BlockChainDB}; use engines::EthEngine; use snapshot::{Error, ManifestData}; @@ -63,7 +63,7 @@ pub trait SnapshotComponents: Send { fn rebuilder( &self, chain: BlockChain, - db: Arc, + db: Arc, manifest: &ManifestData, ) -> Result, ::error::Error>; diff --git a/ethcore/src/snapshot/consensus/work.rs b/ethcore/src/snapshot/consensus/work.rs index b71f7b9d1da..f1000b0c684 100644 --- a/ethcore/src/snapshot/consensus/work.rs +++ b/ethcore/src/snapshot/consensus/work.rs @@ -26,7 +26,7 @@ use std::collections::VecDeque; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use blockchain::{BlockChain, BlockProvider}; +use blockchain::{BlockChain, BlockChainDB, BlockProvider}; use engines::EthEngine; use snapshot::{Error, ManifestData}; use snapshot::block::AbridgedBlock; @@ -78,10 +78,10 @@ impl SnapshotComponents for PowSnapshot { fn rebuilder( &self, chain: BlockChain, - db: Arc, + db: Arc, manifest: &ManifestData, ) -> Result, ::error::Error> { - PowRebuilder::new(chain, db, manifest, self.max_restore_blocks).map(|r| Box::new(r) as Box<_>) + PowRebuilder::new(chain, db.key_value().clone(), manifest, self.max_restore_blocks).map(|r| Box::new(r) as Box<_>) } fn min_supported_version(&self) -> u64 { ::snapshot::MIN_SUPPORTED_STATE_CHUNK_VERSION } diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index 17c362e0440..4a2b8013fc2 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -26,7 +26,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use super::{ManifestData, StateRebuilder, Rebuilder, RestorationStatus, SnapshotService, MAX_CHUNK_SIZE}; use super::io::{SnapshotReader, LooseReader, SnapshotWriter, LooseWriter}; -use blockchain::BlockChain; +use blockchain::{BlockChain, BlockChainDB, BlockChainDBHandler}; use client::{Client, ChainInfo, ClientIoMessage}; use engines::EthEngine; use error::Error; @@ -80,13 +80,13 @@ struct Restoration { snappy_buffer: Bytes, final_state_root: H256, guard: Guard, - db: Arc, + db: Arc, } struct RestorationParams<'a> { manifest: ManifestData, // manifest to base restoration on. pruning: Algorithm, // pruning algorithm for the database. - db: Arc, // database + db: Arc, // database writer: Option, // writer for recovered snapshot. genesis: &'a [u8], // genesis block of the chain. guard: Guard, // guard for the restoration directory. @@ -115,7 +115,7 @@ impl Restoration { manifest: manifest, state_chunks_left: state_chunks, block_chunks_left: block_chunks, - state: StateRebuilder::new(raw_db.clone(), params.pruning), + state: StateRebuilder::new(raw_db.key_value().clone(), params.pruning), secondary: secondary, writer: params.writer, snappy_buffer: Vec::new(), @@ -213,7 +213,7 @@ pub struct ServiceParams { /// State pruning algorithm. pub pruning: Algorithm, /// Handler for opening a restoration DB. - pub restoration_db_handler: Box, + pub restoration_db_handler: Box, /// Async IO channel for sending messages. pub channel: Channel, /// The directory to put snapshots in. @@ -227,7 +227,7 @@ pub struct ServiceParams { /// This controls taking snapshots and restoring from them. pub struct Service { restoration: Mutex>, - restoration_db_handler: Box, + restoration_db_handler: Box, snapshot_root: PathBuf, io_channel: Mutex, pruning: Algorithm, @@ -622,7 +622,8 @@ impl Service { match is_done { true => { - db.flush().map_err(UtilError::from)?; + // TODO: flush also blooms? + db.key_value().flush().map_err(UtilError::from)?; drop(db); return self.finalize_restoration(&mut *restoration); }, @@ -635,7 +636,7 @@ impl Service { } } }; - result.and_then(|_| db.flush().map_err(|e| UtilError::from(e).into())) + result.and_then(|_| db.key_value().flush().map_err(|e| UtilError::from(e).into())) } /// Feed a state chunk to be processed synchronously. diff --git a/ethcore/src/snapshot/tests/helpers.rs b/ethcore/src/snapshot/tests/helpers.rs index 067a3abab07..369fe826ccb 100644 --- a/ethcore/src/snapshot/tests/helpers.rs +++ b/ethcore/src/snapshot/tests/helpers.rs @@ -24,7 +24,7 @@ use hash::{KECCAK_NULL_RLP}; use account_db::AccountDBMut; use basic_account::BasicAccount; -use blockchain::BlockChain; +use blockchain::{BlockChain, BlockChainDB}; use client::{Client, ChainInfo}; use engines::EthEngine; use snapshot::{StateRebuilder}; @@ -158,7 +158,7 @@ pub fn snap(client: &Client) -> (Box, TempDir) { /// Restore a snapshot into a given database. This will read chunks from the given reader /// write into the given database. pub fn restore( - db: Arc, + db: Arc, engine: &EthEngine, reader: &SnapshotReader, genesis: &[u8], @@ -170,7 +170,7 @@ pub fn restore( let components = engine.snapshot_components().unwrap(); let manifest = reader.manifest(); - let mut state = StateRebuilder::new(db.clone(), journaldb::Algorithm::Archive); + let mut state = StateRebuilder::new(db.key_value().clone(), journaldb::Algorithm::Archive); let mut secondary = { let chain = BlockChain::new(Default::default(), genesis, db.clone()); components.rebuilder(chain, db, manifest).unwrap() diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/ethcore/src/snapshot/tests/proof_of_authority.rs index 4b1b3d6ad0e..28dc1045b27 100644 --- a/ethcore/src/snapshot/tests/proof_of_authority.rs +++ b/ethcore/src/snapshot/tests/proof_of_authority.rs @@ -31,6 +31,7 @@ use tempdir::TempDir; use ethereum_types::Address; use kvdb_memorydb; +use test_helpers; use_contract!(test_validator_set, "ValidatorSet", "res/contracts/test_validator_set.json"); @@ -227,12 +228,12 @@ fn fixed_to_contract_only() { assert_eq!(client.chain_info().best_block_number, 11); let (reader, _tempdir) = snapshot_helpers::snap(&*client); - let new_db = kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0)); + let new_db = test_helpers::new_db(); let spec = spec_fixed_to_contract(); // ensure fresh engine's step matches. for _ in 0..11 { spec.engine.step() } - snapshot_helpers::restore(Arc::new(new_db), &*spec.engine, &*reader, &spec.genesis_block()).unwrap(); + snapshot_helpers::restore(new_db, &*spec.engine, &*reader, &spec.genesis_block()).unwrap(); } #[test] @@ -259,9 +260,9 @@ fn fixed_to_contract_to_contract() { assert_eq!(client.chain_info().best_block_number, 16); let (reader, _tempdir) = snapshot_helpers::snap(&*client); - let new_db = kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0)); + let new_db = test_helpers::new_db(); let spec = spec_fixed_to_contract(); for _ in 0..16 { spec.engine.step() } - snapshot_helpers::restore(Arc::new(new_db), &*spec.engine, &*reader, &spec.genesis_block()).unwrap(); + snapshot_helpers::restore(new_db, &*spec.engine, &*reader, &spec.genesis_block()).unwrap(); } diff --git a/ethcore/src/snapshot/tests/proof_of_work.rs b/ethcore/src/snapshot/tests/proof_of_work.rs index 3c3b47ce9c5..3fb764dfe19 100644 --- a/ethcore/src/snapshot/tests/proof_of_work.rs +++ b/ethcore/src/snapshot/tests/proof_of_work.rs @@ -30,6 +30,7 @@ use parking_lot::Mutex; use snappy; use kvdb::{KeyValueDB, DBTransaction}; use kvdb_memorydb; +use test_helpers; const SNAPSHOT_MODE: ::snapshot::PowSnapshot = ::snapshot::PowSnapshot { blocks: 30000, max_restore_blocks: 30000 }; @@ -43,7 +44,7 @@ fn chunk_and_restore(amount: u64) { let tempdir = TempDir::new("").unwrap(); let snapshot_path = tempdir.path().join("SNAP"); - let old_db = Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); + let old_db = test_helpers::new_db(); let bc = BlockChain::new(Default::default(), &genesis.encoded(), old_db.clone()); // build the blockchain. @@ -57,7 +58,7 @@ fn chunk_and_restore(amount: u64) { bc.commit(); } - old_db.write(batch).unwrap(); + old_db.key_value().write(batch).unwrap(); let best_hash = bc.best_block_hash(); @@ -83,7 +84,7 @@ fn chunk_and_restore(amount: u64) { writer.into_inner().finish(manifest.clone()).unwrap(); // restore it. - let new_db = Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); + let new_db = test_helpers::new_db(); let new_chain = BlockChain::new(Default::default(), &genesis.encoded(), new_db.clone()); let mut rebuilder = SNAPSHOT_MODE.rebuilder(new_chain, new_db.clone(), &manifest).unwrap(); @@ -129,7 +130,7 @@ fn checks_flag() { let genesis = BlockBuilder::genesis(); let chunk = stream.out(); - let db = Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); + let db = test_helpers::new_db(); let engine = ::spec::Spec::new_test().engine; let chain = BlockChain::new(Default::default(), &genesis.last().encoded(), db.clone()); diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 3fcb0addfab..43367e0961d 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -24,7 +24,7 @@ use ids::BlockId; use snapshot::service::{Service, ServiceParams}; use snapshot::{self, ManifestData, SnapshotService}; use spec::Spec; -use test_helpers::generate_dummy_client_with_spec_and_data; +use test_helpers::{self, generate_dummy_client_with_spec_and_data}; use test_helpers_internal::restoration_db_handler; use io::IoChannel; @@ -52,13 +52,14 @@ fn restored_is_equivalent() { let path = tempdir.path().join("snapshot"); let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Database::open(&db_config, client_db.to_str().unwrap()).unwrap(); + let restoration = restoration_db_handler(db_config); + let blockchain_db = restoration.open(&client_db).unwrap(); let spec = Spec::new_null(); let client2 = Client::new( Default::default(), &spec, - Arc::new(client_db), + blockchain_db, Arc::new(::miner::Miner::new_for_tests(&spec, None)), IoChannel::disconnected(), ).unwrap(); @@ -66,7 +67,7 @@ fn restored_is_equivalent() { let service_params = ServiceParams { engine: spec.engine.clone(), genesis_block: spec.genesis_block(), - restoration_db_handler: restoration_db_handler(db_config), + restoration_db_handler: restoration, pruning: ::journaldb::Algorithm::Archive, channel: IoChannel::disconnected(), snapshot_root: path, diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index e57d16a6549..32b7f9100cb 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -19,7 +19,7 @@ use account_provider::AccountProvider; use ethereum_types::{H256, U256, Address}; use block::{OpenBlock, Drain}; -use blockchain::{BlockChain, Config as BlockChainConfig, ExtrasInsert}; +use blockchain::{BlockChain, BlockChainDB, Config as BlockChainConfig, ExtrasInsert}; use bytes::Bytes; use client::{Client, ClientConfig, ChainInfo, ImportBlock, ChainNotify, ChainMessageType, PrepareOpenBlock}; use ethkey::KeyPair; @@ -37,6 +37,9 @@ use state::*; use std::sync::Arc; use transaction::{Action, Transaction, SignedTransaction}; use views::BlockView; +use blooms_db; +use kvdb::KeyValueDB; +use tempdir::TempDir; /// Creates test block with corresponding header pub fn create_test_block(header: &Header) -> Bytes { @@ -255,8 +258,32 @@ pub fn get_test_client_with_blocks(blocks: Vec) -> Arc { client } -fn new_db() -> Arc<::kvdb::KeyValueDB> { - Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))) +pub fn new_db() -> Arc { + struct TestBlockChainDB { + blooms_dir: TempDir, + blooms: RwLock, + key_value: Arc, + } + + impl BlockChainDB for TestBlockChainDB { + fn key_value(&self) -> &Arc { + &self.key_value + } + + fn blooms(&self) -> &RwLock { + &self.blooms + } + } + + let tempdir = TempDir::new("").unwrap(); + + let db = TestBlockChainDB { + blooms: RwLock::new(blooms_db::Database::open(tempdir.path()).unwrap()), + blooms_dir: tempdir, + key_value: Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap())) + }; + + Arc::new(db) } /// Generates dummy blockchain with corresponding amount of blocks @@ -264,7 +291,7 @@ pub fn generate_dummy_blockchain(block_number: u32) -> BlockChain { let db = new_db(); let bc = BlockChain::new(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone()); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); for block_order in 1..block_number { // Total difficulty is always 0 here. bc.insert_block(&mut batch, &create_unverifiable_block(block_order, bc.best_block_hash()), vec![], ExtrasInsert { @@ -274,7 +301,7 @@ pub fn generate_dummy_blockchain(block_number: u32) -> BlockChain { }); bc.commit(); } - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); bc } @@ -284,7 +311,7 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> BlockChain { let bc = BlockChain::new(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone()); - let mut batch = db.transaction(); + let mut batch = db.key_value().transaction(); for block_order in 1..block_number { // Total difficulty is always 0 here. bc.insert_block(&mut batch, &create_unverifiable_block_with_extra(block_order, bc.best_block_hash(), None), vec![], ExtrasInsert { @@ -294,7 +321,7 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> BlockChain { }); bc.commit(); } - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); bc } @@ -322,7 +349,7 @@ pub fn get_temp_state_with_factory(factory: EvmFactory) -> State<::state_db::Sta /// Returns temp state db pub fn get_temp_state_db() -> StateDB { let db = new_db(); - let journal_db = ::journaldb::new(db, ::journaldb::Algorithm::EarlyMerge, ::db::COL_STATE); + let journal_db = ::journaldb::new(db.key_value().clone(), ::journaldb::Algorithm::EarlyMerge, ::db::COL_STATE); StateDB::new(journal_db, 5 * 1024 * 1024) } diff --git a/ethcore/src/test_helpers_internal.rs b/ethcore/src/test_helpers_internal.rs index ef98c7c85b5..54cb5509ada 100644 --- a/ethcore/src/test_helpers_internal.rs +++ b/ethcore/src/test_helpers_internal.rs @@ -18,20 +18,43 @@ use std::path::Path; use std::sync::Arc; +use parking_lot::RwLock; use kvdb::{KeyValueDB, KeyValueDBHandler}; use kvdb_rocksdb::{Database, DatabaseConfig}; +use blockchain::{BlockChainDBHandler, BlockChainDB}; +use blooms_db; +use error::Error; /// Creates new instance of KeyValueDBHandler -pub fn restoration_db_handler(config: DatabaseConfig) -> Box { - use kvdb::Error; - +pub fn restoration_db_handler(config: DatabaseConfig) -> Box { struct RestorationDBHandler { config: DatabaseConfig, } - impl KeyValueDBHandler for RestorationDBHandler { - fn open(&self, db_path: &Path) -> Result, Error> { - Ok(Arc::new(Database::open(&self.config, &db_path.to_string_lossy())?)) + struct RestorationDB { + blooms: RwLock, + key_value: Arc, + } + + impl BlockChainDB for RestorationDB { + fn key_value(&self) -> &Arc { + &self.key_value + } + + fn blooms(&self) -> &RwLock { + &self.blooms + } + } + + impl BlockChainDBHandler for RestorationDBHandler { + fn open(&self, db_path: &Path) -> Result, Error> { + let key_value = Arc::new(Database::open(&self.config, &db_path.to_string_lossy())?); + let blooms = RwLock::new(blooms_db::Database::open(db_path).unwrap()); + let db = RestorationDB { + blooms, + key_value, + }; + Ok(Arc::new(db)) } } diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 6dcad9ba62f..184000f5687 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -38,18 +38,20 @@ use transaction::{PendingTransaction, Transaction, Action, Condition}; use miner::MinerService; use rlp::{RlpStream, EMPTY_LIST_RLP}; use tempdir::TempDir; +use test_helpers; #[test] fn imports_from_empty() { - let tempdir = TempDir::new("").unwrap(); + let db = test_helpers::new_db(); + //let tempdir = TempDir::new("").unwrap(); let spec = Spec::new_test(); - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); + //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), &spec, - client_db, + db, Arc::new(Miner::new_for_tests(&spec, None)), IoChannel::disconnected(), ).unwrap(); @@ -59,15 +61,16 @@ fn imports_from_empty() { #[test] fn should_return_registrar() { + let db = test_helpers::new_db(); let tempdir = TempDir::new("").unwrap(); let spec = ethereum::new_morden(&tempdir.path().to_owned()); - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); + //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), &spec, - client_db, + db, Arc::new(Miner::new_for_tests(&spec, None)), IoChannel::disconnected(), ).unwrap(); @@ -89,15 +92,16 @@ fn returns_state_root_basic() { #[test] fn imports_good_block() { - let tempdir = TempDir::new("").unwrap(); + let db = test_helpers::new_db(); + //let tempdir = TempDir::new("").unwrap(); let spec = Spec::new_test(); - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); + //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), &spec, - client_db, + db, Arc::new(Miner::new_for_tests(&spec, None)), IoChannel::disconnected(), ).unwrap(); @@ -133,15 +137,16 @@ fn fails_to_import_block_with_invalid_rlp() { #[test] fn query_none_block() { - let tempdir = TempDir::new("").unwrap(); + let db = test_helpers::new_db(); + //let tempdir = TempDir::new("").unwrap(); let spec = Spec::new_test(); - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); + //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), &spec, - client_db, + db, Arc::new(Miner::new_for_tests(&spec, None)), IoChannel::disconnected(), ).unwrap(); @@ -284,11 +289,12 @@ fn can_mine() { #[test] fn change_history_size() { - let tempdir = TempDir::new("").unwrap(); + let db = test_helpers::new_db(); + //let tempdir = TempDir::new("").unwrap(); let test_spec = Spec::new_null(); let mut config = ClientConfig::default(); - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); + //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); config.history = 2; let address = Address::random(); @@ -296,7 +302,7 @@ fn change_history_size() { let client = Client::new( ClientConfig::default(), &test_spec, - client_db.clone(), + db.clone(), Arc::new(Miner::new_for_tests(&test_spec, None)), IoChannel::disconnected() ).unwrap(); @@ -314,7 +320,7 @@ fn change_history_size() { let client = Client::new( config, &test_spec, - client_db, + db, Arc::new(Miner::new_for_tests(&test_spec, None)), IoChannel::disconnected(), ).unwrap(); diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index a98667b1423..cb2a9a6606a 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -34,22 +34,24 @@ use transaction::{Action, Transaction}; use views::BlockView; use trace::{RewardType, LocalizedTrace}; use trace::trace::Action::Reward; +use test_helpers; #[test] fn can_trace_block_and_uncle_reward() { - let tempdir = TempDir::new("").unwrap(); + let db = test_helpers::new_db(); + //let tempdir = TempDir::new("").unwrap(); let spec = Spec::new_test_with_reward(); let engine = &*spec.engine; // Create client - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let mut client_config = ClientConfig::default(); client_config.tracing.enabled = true; - let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); + //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( client_config, &spec, - client_db, + db, Arc::new(Miner::new_for_tests(&spec, None)), IoChannel::disconnected(), ).unwrap(); diff --git a/ethcore/src/tx_filter.rs b/ethcore/src/tx_filter.rs index 8bbb499052b..d2abf97ab34 100644 --- a/ethcore/src/tx_filter.rs +++ b/ethcore/src/tx_filter.rs @@ -106,6 +106,7 @@ mod test { use super::TransactionFilter; use transaction::{Transaction, Action}; use tempdir::TempDir; + use test_helpers; /// Contract code: https://gist.github.com/arkpar/38a87cb50165b7e683585eec71acb05a #[test] @@ -156,14 +157,15 @@ mod test { } "#; + let db = test_helpers::new_db(); let tempdir = TempDir::new("").unwrap(); let spec = Spec::load(&tempdir.path(), spec_data.as_bytes()).unwrap(); - let client_db = Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); + //let client_db = Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); let client = Client::new( ClientConfig::default(), &spec, - client_db, + db, Arc::new(Miner::new_for_tests(&spec, None)), IoChannel::disconnected(), ).unwrap(); diff --git a/parity/db/rocksdb/mod.rs b/parity/db/rocksdb/mod.rs index 7bfd28f6502..44bafee437d 100644 --- a/parity/db/rocksdb/mod.rs +++ b/parity/db/rocksdb/mod.rs @@ -19,6 +19,10 @@ extern crate migration_rocksdb; use std::sync::Arc; use std::path::Path; +use parking_lot::RwLock; +use blooms_db; +use ethcore::{BlockChainDBHandler, BlockChainDB}; +use ethcore::error::Error; use ethcore::db::NUM_COLUMNS; use ethcore::client::{ClientConfig, DatabaseCompactionProfile}; use kvdb::{KeyValueDB, KeyValueDBHandler}; @@ -31,6 +35,21 @@ mod helpers; pub use self::migration::migrate; +struct AppDB { + key_value: Arc, + blooms: RwLock, +} + +impl BlockChainDB for AppDB { + fn key_value(&self) -> &Arc { + &self.key_value + } + + fn blooms(&self) -> &RwLock { + &self.blooms + } +} + /// Open a secret store DB using the given secret store data path. The DB path is one level beneath the data path. #[cfg(feature = "secretstore")] pub fn open_secretstore_db(data_path: &str) -> Result, String> { @@ -43,7 +62,7 @@ pub fn open_secretstore_db(data_path: &str) -> Result, String> { } /// Open a new client DB. -pub fn open_client_db(client_path: &Path, client_config: &ClientConfig) -> Result, String> { +pub fn open_client_db(client_path: &Path, client_config: &ClientConfig) -> Result, String> { let client_db_config = helpers::client_db_config(client_path, client_config); let client_db = Arc::new(Database::open( @@ -51,22 +70,30 @@ pub fn open_client_db(client_path: &Path, client_config: &ClientConfig) -> Resul &client_path.to_str().expect("DB path could not be converted to string.") ).map_err(|e| format!("Client service database error: {:?}", e))?); - Ok(client_db) + let db = AppDB { + key_value: client_db, + blooms: RwLock::new(blooms_db::Database::open(client_path).map_err(|e| e.to_string())?), + }; + + Ok(Arc::new(db)) } /// Create a restoration db handler using the config generated by `client_path` and `client_config`. -pub fn restoration_db_handler(client_path: &Path, client_config: &ClientConfig) -> Box { - use kvdb::Error; - +pub fn restoration_db_handler(client_path: &Path, client_config: &ClientConfig) -> Box { let client_db_config = helpers::client_db_config(client_path, client_config); struct RestorationDBHandler { config: DatabaseConfig, } - impl KeyValueDBHandler for RestorationDBHandler { - fn open(&self, db_path: &Path) -> Result, Error> { - Ok(Arc::new(Database::open(&self.config, &db_path.to_string_lossy())?)) + impl BlockChainDBHandler for RestorationDBHandler { + fn open(&self, db_path: &Path) -> Result, Error> { + let db = AppDB { + key_value: Arc::new(Database::open(&self.config, &db_path.to_string_lossy())?), + blooms: RwLock::new(blooms_db::Database::open(db_path)?), + }; + + Ok(Arc::new(db)) } } @@ -76,16 +103,17 @@ pub fn restoration_db_handler(client_path: &Path, client_config: &ClientConfig) } /// Open a new main DB. -pub fn open_db(client_path: &str, cache_config: &CacheConfig, compaction: &DatabaseCompactionProfile, wal: bool) -> Result, String> { - let db_config = DatabaseConfig { - memory_budget: Some(cache_config.blockchain() as usize * 1024 * 1024), - compaction: helpers::compaction_profile(&compaction, &Path::new(client_path)), - wal: wal, - .. DatabaseConfig::with_columns(NUM_COLUMNS) - }; - - Ok(Arc::new(Database::open( - &db_config, - client_path - ).map_err(|e| format!("Failed to open database: {}", e))?)) +pub fn open_db(client_path: &str, cache_config: &CacheConfig, compaction: &DatabaseCompactionProfile, wal: bool) -> Result, String> { + //let db_config = DatabaseConfig { + //memory_budget: Some(cache_config.blockchain() as usize * 1024 * 1024), + //compaction: helpers::compaction_profile(&compaction, &Path::new(client_path)), + //wal: wal, + //.. DatabaseConfig::with_columns(NUM_COLUMNS) + //}; + + //Ok(Arc::new(Database::open( + //&db_config, + //client_path + //).map_err(|e| format!("Failed to open database: {}", e))?)) + unimplemented!(); } diff --git a/parity/lib.rs b/parity/lib.rs index 4d9d1a2c95f..63535ddfecf 100644 --- a/parity/lib.rs +++ b/parity/lib.rs @@ -42,6 +42,7 @@ extern crate serde_json; extern crate serde_derive; extern crate toml; +extern crate blooms_db; extern crate ethcore; extern crate ethcore_bytes as bytes; extern crate ethcore_io as io; diff --git a/parity/run.rs b/parity/run.rs index 73113055bbf..5f3f4c85d28 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -627,7 +627,7 @@ fn execute_impl(cmd: RunCmd, logger: Arc, on_client_rq: } }; - let store = ::local_store::create(db, ::ethcore::db::COL_NODE_INFO, node_info); + let store = ::local_store::create(db.key_value().clone(), ::ethcore::db::COL_NODE_INFO, node_info); if cmd.no_persistent_txqueue { info!("Running without a persistent transaction queue."); diff --git a/util/blooms-db/Cargo.toml b/util/blooms-db/Cargo.toml new file mode 100644 index 00000000000..aba7ebc36ce --- /dev/null +++ b/util/blooms-db/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "blooms-db" +version = "0.1.0" +authors = ["debris "] + +[dependencies] +byteorder = "1.2" +ethbloom = "0.5" +tiny-keccak = "1.4" + +[dev-dependencies] +tempdir = "0.3" diff --git a/util/blooms-db/benches/blooms.rs b/util/blooms-db/benches/blooms.rs new file mode 100644 index 00000000000..516175c5bd7 --- /dev/null +++ b/util/blooms-db/benches/blooms.rs @@ -0,0 +1,30 @@ +#![feature(test)] + +extern crate test; +extern crate tempdir; +extern crate blooms_db; +extern crate ethbloom; + +use std::iter; +use test::Bencher; +use tempdir::TempDir; +use blooms_db::Database; +use ethbloom::Bloom; + +#[bench] +fn blooms_filter_1_million(b: &mut Bencher) { + let tempdir = TempDir::new("").unwrap(); + let mut database = Database::open(tempdir.path()).unwrap(); + database.insert_blooms(999_999, iter::once(&Bloom::from(0))).unwrap(); + let bloom = Bloom::from(0x001); + database.insert_blooms(200_000, iter::once(&bloom)).unwrap(); + database.insert_blooms(400_000, iter::once(&bloom)).unwrap(); + database.insert_blooms(600_000, iter::once(&bloom)).unwrap(); + database.insert_blooms(800_000, iter::once(&bloom)).unwrap(); + database.flush().unwrap(); + + b.iter(|| { + let matches = database.iterate_matching(0, 999_999, &bloom).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![200_000, 400_000, 600_000, 800_000]); + }); +} diff --git a/util/blooms-db/src/db.rs b/util/blooms-db/src/db.rs new file mode 100644 index 00000000000..59df4412e78 --- /dev/null +++ b/util/blooms-db/src/db.rs @@ -0,0 +1,279 @@ +use std::io; +use std::path::{Path, PathBuf}; + +use ethbloom; + +use VERSION; +use file::{File, FileIterator}; +use meta::{Meta, read_meta, save_meta}; +use pending::Pending; + +/// Bloom positions in database files. +#[derive(Debug)] +struct Positions { + top: u64, + mid: u64, + bot: u64 +} + +impl Positions { + fn from_index(index: u64) -> Self { + Positions { + top: index >> 8, + mid: index >> 4, + bot: index, + } + } +} + +/// Blooms database. +pub struct Database { + /// Top level bloom file + /// + /// Every bloom represents 16 blooms on mid level + top: File, + /// Mid level bloom file + /// + /// Every bloom represents 16 blooms on bot level + mid: File, + /// Bot level bloom file + /// + /// Every bloom is an ethereum header bloom + bot: File, + /// Pending changes + /// + /// Inserted blooms are always appended to this file + pending: Pending, + /// Datbase directory + path: PathBuf, +} + +impl Database { + /// Opens blooms database. + pub fn open

(path: P) -> io::Result where P: AsRef { + let path = path.as_ref(); + let database = Database { + top: File::open(path.join("top.bdb"))?, + mid: File::open(path.join("mid.bdb"))?, + bot: File::open(path.join("bot.bdb"))?, + pending: Pending::open(path.join("pending.bdb"))?, + path: path.to_path_buf(), + }; + + match read_meta(path.join("meta.bdb")) { + Ok(meta) => { + let pending_hash = database.pending.hash()?; + if pending_hash != meta.pending_hash { + return Err(io::Error::new(io::ErrorKind::InvalidData, "Malformed pending file")); + } + }, + Err(ref err) if err.kind() == io::ErrorKind::NotFound => {}, + Err(err) => return Err(err), + } + + Ok(database) + } + + /// Insert consecutive blooms into database starting with positon from. + pub fn insert_blooms<'a, B>(&'a mut self, from: u64, blooms: impl Iterator) -> io::Result<()> + where ethbloom::BloomRef<'a>: From { + for (index, bloom) in (from..).into_iter().zip(blooms) { + self.pending.append(index, bloom)?; + } + self.pending.flush()?; + self.flush_meta() + } + + /// Flush pending blooms. + pub fn flush(&mut self) -> io::Result<()> { + for tuple in self.pending.iterator()? { + let (index, bloom) = tuple?; + let pos = Positions::from_index(index); + + // constant forks make lead to increased ration of false positives in bloom filters + // since we do not rebuild top or mid level, but we should not be worried about that + // most of the time events at block n(a) occur also on block n(b) or n+1(b) + self.top.accrue_bloom(pos.top, &bloom)?; + self.mid.accrue_bloom(pos.mid, &bloom)?; + self.bot.replace_bloom(pos.bot, &bloom)?; + } + self.top.flush()?; + self.mid.flush()?; + self.bot.flush()?; + self.pending.clear()?; + self.flush_meta() + } + + /// Returns an iterator yielding all indexes containing given bloom. + pub fn iterate_matching<'a, B>(&'a self, from: u64, to: u64, bloom: B) -> io::Result> + where ethbloom::BloomRef<'a>: From { + let index = from / 256 * 256; + let pos = Positions::from_index(index); + + let iter = DatabaseIterator { + top: self.top.iterator_from(pos.top)?, + mid: self.mid.iterator_from(pos.mid)?, + bot: self.bot.iterator_from(pos.bot)?, + state: IteratorState::Top, + from, + to, + index, + bloom: bloom.into(), + }; + + Ok(iter) + } + + fn flush_meta(&self) -> io::Result<()> { + let meta = Meta { + version: VERSION, + pending_hash: self.pending.hash()? + }; + + save_meta(self.path.join("meta.bdb"), &meta) + } +} + +/// Blooms database iterator +pub struct DatabaseIterator<'a> { + top: FileIterator<'a>, + mid: FileIterator<'a>, + bot: FileIterator<'a>, + state: IteratorState, + from: u64, + to: u64, + index: u64, + bloom: ethbloom::BloomRef<'a>, +} + +/// Database iterator state. +#[derive(Debug)] +enum IteratorState { + /// Iterator should read top level bloom + Top, + /// Iterator should read mid level bloom `x` more times + Mid(usize), + /// Iterator should read mid level bloom `mid` more times + /// and bot level `mix * 16 + bot` times + Bot { mid: usize, bot: usize }, +} + +impl<'a> Iterator for DatabaseIterator<'a> { + type Item = io::Result; + + fn next(&mut self) -> Option { + macro_rules! try_o { + ($expr: expr) => { + match $expr { + Err(err) => return Some(Err(err)), + Ok(ok) => ok, + } + } + } + + loop { + if self.index > self.to { + return None; + } + + self.state = match self.state { + IteratorState::Top => { + if try_o!(self.top.next()?).contains_bloom(self.bloom) { + IteratorState::Mid(16) + } else { + self.index += 256; + try_o!(self.mid.advance(16)); + try_o!(self.bot.advance(256)); + IteratorState::Top + } + }, + IteratorState::Mid(left) => { + if left == 0 { + IteratorState::Top + } else if try_o!(self.mid.next()?).contains_bloom(self.bloom) && self.index + 16 >= self.from { + IteratorState::Bot { mid: left - 1, bot: 16 } + } else { + self.index += 16; + try_o!(self.bot.advance(16)); + IteratorState::Mid(left - 1) + } + }, + IteratorState::Bot { mid, bot } => { + if bot == 0 { + IteratorState::Mid(mid) + } else if try_o!(self.bot.next()?).contains_bloom(self.bloom) && self.index >= self.from { + let result = self.index; + self.index += 1; + self.state = IteratorState::Bot { mid, bot: bot - 1 }; + return Some(Ok(result)); + } else { + self.index += 1; + IteratorState::Bot { mid, bot: bot - 1 } + } + } + } + } + } +} + +#[cfg(test)] +mod tests { + use ethbloom::Bloom; + use tempdir::TempDir; + use super::Database; + + #[test] + fn test_database() { + let tempdir = TempDir::new("").unwrap(); + let mut database = Database::open(tempdir.path()).unwrap(); + database.insert_blooms(0, vec![Bloom::from(0), Bloom::from(0x01), Bloom::from(0x10), Bloom::from(0x11)].iter()).unwrap(); + database.flush().unwrap(); + + let matches = database.iterate_matching(0, 3, &Bloom::from(0)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![0, 1, 2, 3]); + + let matches = database.iterate_matching(0, 4, &Bloom::from(0)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![0, 1, 2, 3]); + + let matches = database.iterate_matching(1, 3, &Bloom::from(0)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![1, 2, 3]); + + let matches = database.iterate_matching(1, 2, &Bloom::from(0)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![1, 2]); + + let matches = database.iterate_matching(0, 3, &Bloom::from(0x01)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![1, 3]); + + let matches = database.iterate_matching(0, 3, &Bloom::from(0x10)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![2, 3]); + + let matches = database.iterate_matching(2, 2, &Bloom::from(0x10)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![2]); + } + + #[test] + fn test_database2() { + let tempdir = TempDir::new("").unwrap(); + let mut database = Database::open(tempdir.path()).unwrap(); + database.insert_blooms(254, vec![Bloom::from(0x100), Bloom::from(0x01), Bloom::from(0x10), Bloom::from(0x11)].iter()).unwrap(); + database.flush().unwrap(); + + let matches = database.iterate_matching(0, 257, &Bloom::from(0x01)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![255, 257]); + + let matches = database.iterate_matching(0, 258, &Bloom::from(0x100)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![254]); + + let matches = database.iterate_matching(0, 256, &Bloom::from(0x01)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![255]); + + let matches = database.iterate_matching(255, 255, &Bloom::from(0x01)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![255]); + + let matches = database.iterate_matching(256, 256, &Bloom::from(0x10)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![256]); + + let matches = database.iterate_matching(256, 257, &Bloom::from(0x10)).unwrap().collect::, _>>().unwrap(); + assert_eq!(matches, vec![256, 257]); + } +} diff --git a/util/blooms-db/src/file.rs b/util/blooms-db/src/file.rs new file mode 100644 index 00000000000..1e2cccbf783 --- /dev/null +++ b/util/blooms-db/src/file.rs @@ -0,0 +1,134 @@ +use std::io::{Seek, SeekFrom, Write, Read}; +use std::path::Path; +use std::{io, fs}; + +use ethbloom; + +/// Autoresizable file containing blooms. +pub struct File { + /// Backing file. + file: fs::File, + /// Current file len. + len: u64, +} + +impl File { + /// Opens database file. Creates new file if database file does not exist. + pub fn open

(path: P) -> io::Result where P: AsRef { + let file = fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + // appending is done manually by calling `ensure_space_for_write` + .append(false) + .open(path)?; + let len = file.metadata()?.len(); + + let file = File { + file, + len, + }; + + Ok(file) + + } + + /// Resizes the file if there is not enough space to write bloom at given position. + fn ensure_space_for_write(&mut self, pos: u64) -> io::Result<()> { + // position to write + 256 bytes + let required_space = (pos + 1) * 256; + if required_space > self.len { + self.file.set_len(required_space)?; + self.len = required_space; + } + Ok(()) + } + + /// Read bloom at given position. + pub fn read_bloom(&self, pos: u64) -> io::Result { + let mut file_ref = &self.file; + file_ref.seek(SeekFrom::Start(pos * 256))?; + let mut bloom = ethbloom::Bloom::default(); + file_ref.read_exact(&mut bloom)?; + Ok(bloom) + } + + /// Accrue bloom into bloom at given position. + pub fn accrue_bloom<'a, B>(&mut self, pos: u64, bloom: B) -> io::Result<()> where ethbloom::BloomRef<'a>: From { + self.ensure_space_for_write(pos)?; + let mut old_bloom: ethbloom::Bloom = self.read_bloom(pos)?; + old_bloom.accrue_bloom(bloom); + let mut file_ref = &self.file; + file_ref.seek(SeekFrom::Start(pos * 256))?; + file_ref.write_all(&old_bloom) + } + + /// Replace bloom at given position with a new one. + pub fn replace_bloom<'a, B>(&mut self, pos: u64, bloom: B) -> io::Result<()> where ethbloom::BloomRef<'a>: From { + self.ensure_space_for_write(pos)?; + let mut file_ref = &self.file; + file_ref.seek(SeekFrom::Start(pos * 256))?; + file_ref.write_all(ethbloom::BloomRef::from(bloom).data()) + } + + /// Returns an iterator over file. + pub fn iterator_from(&self, pos: u64) -> io::Result { + let mut file_ref = &self.file; + file_ref.seek(SeekFrom::Start(pos * 256))?; + + let iter = FileIterator { + file: file_ref, + }; + + Ok(iter) + } + + /// Flush outstanding modifications to the disk + pub fn flush(&mut self) -> io::Result<()> { + self.file.flush() + } +} + +/// Iterator over blooms of a single file. +pub struct FileIterator<'a> { + /// Backing file. + file: &'a fs::File, +} + +impl<'a> FileIterator<'a> { + /// Advance file by n blooms + pub fn advance(&mut self, n: u64) -> io::Result<()> { + self.file.seek(SeekFrom::Current(n as i64 * 256))?; + Ok(()) + } +} + +impl<'a> Iterator for FileIterator<'a> { + type Item = io::Result; + + fn next(&mut self) -> Option { + let mut bloom = ethbloom::Bloom::default(); + match self.file.read_exact(&mut bloom) { + Ok(_) => Some(Ok(bloom)), + Err(ref err) if err.kind() == io::ErrorKind::UnexpectedEof => None, + Err(err) => Some(Err(err)), + } + } +} + +#[cfg(test)] +mod tests { + use ethbloom::Bloom; + use tempdir::TempDir; + use super::File; + + #[test] + fn test_file() { + let tempdir = TempDir::new("").unwrap(); + let mut file = File::open(tempdir.path().join("file")).unwrap(); + file.accrue_bloom(0, &Bloom::from(1)).unwrap(); + file.flush().unwrap(); + assert_eq!(file.read_bloom(0).unwrap(), Bloom::from(1)); + + } +} diff --git a/util/blooms-db/src/lib.rs b/util/blooms-db/src/lib.rs new file mode 100644 index 00000000000..5fdb6ee6863 --- /dev/null +++ b/util/blooms-db/src/lib.rs @@ -0,0 +1,20 @@ +//! Ethereum blooms database +//! +//! zero allocation +//! zero copying + +extern crate byteorder; +extern crate ethbloom; +extern crate tiny_keccak; + +#[cfg(test)] +extern crate tempdir; + +mod db; +mod file; +mod meta; +mod pending; + +pub const VERSION: u64 = 1; + +pub use db::{Database, DatabaseIterator}; diff --git a/util/blooms-db/src/meta.rs b/util/blooms-db/src/meta.rs new file mode 100644 index 00000000000..e24600f8066 --- /dev/null +++ b/util/blooms-db/src/meta.rs @@ -0,0 +1,41 @@ +use std::io::{Write, Read}; +use std::path::Path; +use std::{fs, io}; + +use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian}; + +#[derive(Debug)] +pub struct Meta { + /// Database version. + pub version: u64, + /// Pending file hash. + pub pending_hash: [u8; 32], +} + +pub fn read_meta

(path: P) -> io::Result where P: AsRef { + let mut file = fs::OpenOptions::new() + .read(true) + .open(path)?; + + let version = file.read_u64::()?; + let mut pending_hash = [0u8; 32]; + file.read_exact(&mut pending_hash)?; + + let meta = Meta { + version, + pending_hash, + }; + + Ok(meta) +} + +pub fn save_meta

(path: P, meta: &Meta) -> io::Result<()> where P: AsRef { + let mut file = fs::OpenOptions::new() + .write(true) + .create(true) + .open(path)?; + + file.write_u64::(meta.version)?; + file.write_all(&meta.pending_hash)?; + file.flush() +} diff --git a/util/blooms-db/src/pending.rs b/util/blooms-db/src/pending.rs new file mode 100644 index 00000000000..acca3667e4d --- /dev/null +++ b/util/blooms-db/src/pending.rs @@ -0,0 +1,158 @@ +use std::io::{Seek, SeekFrom, Write, Read}; +use std::path::Path; +use std::{fs, io}; + +use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian}; +use ethbloom; +use tiny_keccak::Keccak; + +/// File with blooms which are not flushed to the database yet. +pub struct Pending { + file: fs::File, +} + +impl Pending { + /// Opens pending changes file. Creates new file if pending changes do not exist. + pub fn open

(path: P) -> io::Result where P: AsRef { + let file = fs::OpenOptions::new() + .read(true) + .write(true) + .create(true) + .append(true) + .open(path)?; + + let pending = Pending { + file, + }; + + Ok(pending) + } + + /// Pushes pending changes to a file. + pub fn append<'a, B>(&mut self, index: u64, bloom: B) -> io::Result<()> where ethbloom::BloomRef<'a>: From { + self.file.write_u64::(index)?; + self.file.write_all(ethbloom::BloomRef::from(bloom).data()) + } + + /// Flushes changes to underlying file. + pub fn flush(&mut self) -> io::Result<()> { + self.file.sync_all() + } + + /// Clears underlying file. + pub fn clear(&mut self) -> io::Result<()> { + self.file.seek(SeekFrom::Start(0))?; + self.file.set_len(0)?; + self.file.sync_all() + } + + /// Returns an iterator over blooms in the file. + pub fn iterator(&self) -> io::Result { + let mut file_ref = &self.file; + file_ref.seek(SeekFrom::Start(0))?; + + let iter = PendingIterator { + file: file_ref, + }; + + Ok(iter) + } + + /// Returns file hash. + pub fn hash(&self) -> io::Result<[u8; 32]> { + let mut file_ref = &self.file; + file_ref.seek(SeekFrom::Start(0))?; + let mut keccak = Keccak::new_keccak256(); + let mut buffer = [0u8; 256 + 8]; + loop { + match file_ref.read_exact(&mut buffer) { + Ok(_) => { + keccak.update(&mut buffer); + }, + Err(ref err) if err.kind() == io::ErrorKind::UnexpectedEof => { + let mut result = [0u8; 32]; + keccak.finalize(&mut result); + return Ok(result); + }, + Err(err) => return Err(err), + } + } + } +} + +/// Iterator over blooms in the file. +pub struct PendingIterator<'a> { + file: &'a fs::File, +} + +impl<'a> Iterator for PendingIterator<'a> { + type Item = io::Result<(u64, ethbloom::Bloom)>; + + fn next(&mut self) -> Option { + let index = match self.file.read_u64::() { + Ok(index) => index, + Err(ref err) if err.kind() == io::ErrorKind::UnexpectedEof => return None, + Err(err) => return Some(Err(err)), + }; + + let mut bloom = ethbloom::Bloom::default(); + match self.file.read_exact(&mut bloom) { + Ok(_) => Some(Ok((index, bloom))), + Err(err) => Some(Err(err)), + } + } +} + +#[cfg(test)] +mod tests { + use ethbloom::Bloom; + use tempdir::TempDir; + use super::Pending; + + #[test] + fn test_pending() { + let tempdir = TempDir::new("").unwrap(); + let mut pending = Pending::open(tempdir.path().join("pending")).unwrap(); + + // append elements + pending.append(0, &Bloom::from(0)).unwrap(); + pending.append(1, &Bloom::from(1)).unwrap(); + pending.append(2, &Bloom::from(2)).unwrap(); + pending.append(3, &Bloom::from(3)).unwrap(); + pending.append(2, &Bloom::from(4)).unwrap(); + + // flush + pending.flush().unwrap(); + + // validate all elements + let elements = pending.iterator().unwrap().collect::, _>>().unwrap(); + assert_eq!(elements, vec![ + (0, 0.into()), + (1, 1.into()), + (2, 2.into()), + (3, 3.into()), + (2, 4.into()) + ]); + + // move iterator + let first = pending.iterator().unwrap().next().unwrap().unwrap(); + assert_eq!(first, (0, 0.into())); + + // validate that after moving an iterator the element is still appended to the of the file + pending.append(4, &Bloom::from(5)).unwrap(); + pending.flush().unwrap(); + let elements2 = pending.iterator().unwrap().collect::, _>>().unwrap(); + assert_eq!(elements2, vec![ + (0, 0.into()), + (1, 1.into()), + (2, 2.into()), + (3, 3.into()), + (2, 4.into()), + (4, 5.into()) + ]); + + pending.clear().unwrap(); + let elements3 = pending.iterator().unwrap().collect::, _>>().unwrap(); + assert!(elements3.is_empty()); + } +} From 2eb233b36d792cda6d251f4cbc15d5f5a3fdddc7 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 25 May 2018 12:19:01 +0800 Subject: [PATCH 02/29] fixed conflict in Cargo.lock --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index e8495ee40b5..0f7a9299db5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,7 +166,7 @@ dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] From f55ee49060b14cf8be852be137c8fe786d0d0ea5 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 25 May 2018 17:34:11 +0800 Subject: [PATCH 03/29] removed bloomchain --- Cargo.lock | 10 - ethcore/Cargo.toml | 1 - ethcore/src/blooms/bloom_group.rs | 47 -- ethcore/src/blooms/group_position.rs | 42 - ethcore/src/blooms/mod.rs | 23 - ethcore/src/client/client.rs | 5 +- ethcore/src/lib.rs | 2 - ethcore/src/trace/config.rs | 7 - ethcore/src/trace/db.rs | 148 +--- ethcore/src/trace/types/filter.rs | 11 - util/bloomchain/.gitignore | 3 - util/bloomchain/Cargo.toml | 15 - util/bloomchain/README.md | 9 - util/bloomchain/src/chain.rs | 158 ---- util/bloomchain/src/config.rs | 17 - util/bloomchain/src/database.rs | 7 - util/bloomchain/src/filter.rs | 11 - util/bloomchain/src/group/bridge.rs | 31 - util/bloomchain/src/group/chain.rs | 70 -- util/bloomchain/src/group/database.rs | 6 - util/bloomchain/src/group/group.rs | 17 - util/bloomchain/src/group/mod.rs | 16 - util/bloomchain/src/group/position/manager.rs | 28 - util/bloomchain/src/group/position/mod.rs | 5 - .../bloomchain/src/group/position/position.rs | 17 - util/bloomchain/src/lib.rs | 17 - util/bloomchain/src/number.rs | 2 - util/bloomchain/src/position/manager.rs | 142 ---- util/bloomchain/src/position/mod.rs | 5 - util/bloomchain/src/position/position.rs | 8 - util/bloomchain/tests/bloomchain.rs | 170 ---- util/bloomchain/tests/data/blooms.txt | 739 ------------------ util/bloomchain/tests/groupchain.rs | 172 ---- util/bloomchain/tests/util/db.rs | 39 - util/bloomchain/tests/util/each.rs | 24 - util/bloomchain/tests/util/from_hex.rs | 16 - util/bloomchain/tests/util/mod.rs | 9 - util/bloomchain/tests/util/random.rs | 24 - 38 files changed, 40 insertions(+), 2033 deletions(-) delete mode 100644 ethcore/src/blooms/bloom_group.rs delete mode 100644 ethcore/src/blooms/group_position.rs delete mode 100644 ethcore/src/blooms/mod.rs delete mode 100644 util/bloomchain/.gitignore delete mode 100644 util/bloomchain/Cargo.toml delete mode 100644 util/bloomchain/README.md delete mode 100644 util/bloomchain/src/chain.rs delete mode 100644 util/bloomchain/src/config.rs delete mode 100644 util/bloomchain/src/database.rs delete mode 100644 util/bloomchain/src/filter.rs delete mode 100644 util/bloomchain/src/group/bridge.rs delete mode 100644 util/bloomchain/src/group/chain.rs delete mode 100644 util/bloomchain/src/group/database.rs delete mode 100644 util/bloomchain/src/group/group.rs delete mode 100644 util/bloomchain/src/group/mod.rs delete mode 100644 util/bloomchain/src/group/position/manager.rs delete mode 100644 util/bloomchain/src/group/position/mod.rs delete mode 100644 util/bloomchain/src/group/position/position.rs delete mode 100644 util/bloomchain/src/lib.rs delete mode 100644 util/bloomchain/src/number.rs delete mode 100644 util/bloomchain/src/position/manager.rs delete mode 100644 util/bloomchain/src/position/mod.rs delete mode 100644 util/bloomchain/src/position/position.rs delete mode 100644 util/bloomchain/tests/bloomchain.rs delete mode 100644 util/bloomchain/tests/data/blooms.txt delete mode 100644 util/bloomchain/tests/groupchain.rs delete mode 100644 util/bloomchain/tests/util/db.rs delete mode 100644 util/bloomchain/tests/util/each.rs delete mode 100644 util/bloomchain/tests/util/from_hex.rs delete mode 100644 util/bloomchain/tests/util/mod.rs delete mode 100644 util/bloomchain/tests/util/random.rs diff --git a/Cargo.lock b/Cargo.lock index 0f7a9299db5..b25b51517c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,15 +150,6 @@ name = "bitflags" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "bloomchain" -version = "0.2.0" -dependencies = [ - "ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "blooms-db" version = "0.1.0" @@ -522,7 +513,6 @@ name = "ethcore" version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bloomchain 0.2.0", "blooms-db 0.1.0", "bn 0.4.4 (git+https://github.com/paritytech/bn)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 88e8ff85049..36068aa513e 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -8,7 +8,6 @@ authors = ["Parity Technologies "] [dependencies] ansi_term = "0.10" -bloomchain = { path = "../util/bloomchain" } blooms-db = { path = "../util/blooms-db" } bn = { git = "https://github.com/paritytech/bn", default-features = false } byteorder = "1.0" diff --git a/ethcore/src/blooms/bloom_group.rs b/ethcore/src/blooms/bloom_group.rs deleted file mode 100644 index bb4a160b8a0..00000000000 --- a/ethcore/src/blooms/bloom_group.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -use bloomchain::group as bc; -use heapsize::HeapSizeOf; -use ethereum_types::Bloom; - -/// Represents group of X consecutive blooms. -#[derive(Debug, Clone, RlpEncodableWrapper, RlpDecodableWrapper)] -pub struct BloomGroup { - blooms: Vec, -} - -impl From for BloomGroup { - fn from(group: bc::BloomGroup) -> Self { - BloomGroup { - blooms: group.blooms - } - } -} - -impl Into for BloomGroup { - fn into(self) -> bc::BloomGroup { - bc::BloomGroup { - blooms: self.blooms - } - } -} - -impl HeapSizeOf for BloomGroup { - fn heap_size_of_children(&self) -> usize { - self.blooms.heap_size_of_children() - } -} diff --git a/ethcore/src/blooms/group_position.rs b/ethcore/src/blooms/group_position.rs deleted file mode 100644 index b1ea8279261..00000000000 --- a/ethcore/src/blooms/group_position.rs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -use bloomchain::group as bc; -use heapsize::HeapSizeOf; - -/// Represents `BloomGroup` position in database. -#[derive(PartialEq, Eq, Hash, Clone, Debug)] -pub struct GroupPosition { - /// Bloom level. - pub level: u8, - /// Group index. - pub index: u32, -} - -impl From for GroupPosition { - fn from(p: bc::GroupPosition) -> Self { - GroupPosition { - level: p.level as u8, - index: p.index as u32, - } - } -} - -impl HeapSizeOf for GroupPosition { - fn heap_size_of_children(&self) -> usize { - 0 - } -} diff --git a/ethcore/src/blooms/mod.rs b/ethcore/src/blooms/mod.rs deleted file mode 100644 index a66485782b3..00000000000 --- a/ethcore/src/blooms/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -//! Bridge between bloomchain crate types and ethcore. - -mod bloom_group; -mod group_position; - -pub use self::bloom_group::BloomGroup; -pub use self::group_position::GroupPosition; diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index e2a3833c6df..8631345351f 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -719,7 +719,7 @@ impl Client { let gb = spec.genesis_block(); let chain = Arc::new(BlockChain::new(config.blockchain.clone(), &gb, db.clone())); - let tracedb = RwLock::new(TraceDB::new(config.tracing.clone(), db.key_value().clone(), chain.clone())); + let tracedb = RwLock::new(TraceDB::new(config.tracing.clone(), db.clone(), chain.clone())); trace!("Cleanup journal: DB Earliest = {:?}, Latest = {:?}", state_db.journal_db().earliest_era(), state_db.journal_db().latest_era()); @@ -1292,10 +1292,11 @@ impl snapshot::DatabaseRestore for Client { let db = self.db.write(); db.key_value().restore(new_db)?; + // TODO: restore blooms properly let cache_size = state_db.cache_size(); *state_db = StateDB::new(journaldb::new(db.key_value().clone(), self.pruning, ::db::COL_STATE), cache_size); *chain = Arc::new(BlockChain::new(self.config.blockchain.clone(), &[], db.clone())); - *tracedb = TraceDB::new(self.config.tracing.clone(), db.key_value().clone(), chain.clone()); + *tracedb = TraceDB::new(self.config.tracing.clone(), db.clone(), chain.clone()); Ok(()) } } diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 32bce8cc69c..31b7a939736 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -58,7 +58,6 @@ // error_chain foreign_links. #![recursion_limit="128"] -extern crate bloomchain; extern crate blooms_db; extern crate bn; extern crate byteorder; @@ -163,7 +162,6 @@ pub mod trace; pub mod verification; mod cache_manager; -mod blooms; mod pod_account; mod account_db; mod builtin; diff --git a/ethcore/src/trace/config.rs b/ethcore/src/trace/config.rs index dbd8a97affe..59ce099de0b 100644 --- a/ethcore/src/trace/config.rs +++ b/ethcore/src/trace/config.rs @@ -15,7 +15,6 @@ // along with Parity. If not, see . //! Traces config. -use bloomchain::Config as BloomConfig; /// Traces config. #[derive(Debug, PartialEq, Clone)] @@ -23,8 +22,6 @@ pub struct Config { /// Indicates if tracing should be enabled or not. /// If it's None, it will be automatically configured. pub enabled: bool, - /// Traces blooms configuration. - pub blooms: BloomConfig, /// Preferef cache-size. pub pref_cache_size: usize, /// Max cache-size. @@ -35,10 +32,6 @@ impl Default for Config { fn default() -> Self { Config { enabled: false, - blooms: BloomConfig { - levels: 3, - elements_per_index: 16, - }, pref_cache_size: 15 * 1024 * 1024, max_cache_size: 20 * 1024 * 1024, } diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 45b9ebc150a..ab97bc532e9 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -18,8 +18,7 @@ use std::ops::Deref; use std::collections::{HashMap, VecDeque}; use std::sync::Arc; -use bloomchain::{Number, Config as BloomConfig}; -use bloomchain::group::{BloomGroupDatabase, BloomGroupChain, GroupPosition, BloomGroup}; +use blockchain::{BlockChainDB}; use heapsize::HeapSizeOf; use ethereum_types::{H256, H264}; use kvdb::{KeyValueDB, DBTransaction}; @@ -27,7 +26,6 @@ use parking_lot::RwLock; use header::BlockNumber; use trace::{LocalizedTrace, Config, Filter, Database as TraceDatabase, ImportRequest, DatabaseExtras}; use db::{self, Key, Writable, Readable, CacheUpdatePolicy}; -use blooms; use super::flat::{FlatTrace, FlatBlockTraces, FlatTransactionTraces}; use cache_manager::CacheManager; @@ -37,8 +35,6 @@ const TRACE_DB_VER: &'static [u8] = b"1.0"; enum TraceDBIndex { /// Block traces index. BlockTraces = 0, - /// Trace bloom group index. - BloomGroups = 1, } impl Key for H256 { @@ -52,53 +48,9 @@ impl Key for H256 { } } -/// Wrapper around `blooms::GroupPosition` so it could be -/// uniquely identified in the database. -#[derive(Debug, PartialEq, Eq, Hash, Clone)] -struct TraceGroupPosition(blooms::GroupPosition); - -impl From for TraceGroupPosition { - fn from(position: GroupPosition) -> Self { - TraceGroupPosition(From::from(position)) - } -} - -impl HeapSizeOf for TraceGroupPosition { - fn heap_size_of_children(&self) -> usize { - 0 - } -} - -/// Helper data structure created cause [u8; 6] does not implement Deref to &[u8]. -pub struct TraceGroupKey([u8; 6]); - -impl Deref for TraceGroupKey { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Key for TraceGroupPosition { - type Target = TraceGroupKey; - - fn key(&self) -> Self::Target { - let mut result = [0u8; 6]; - result[0] = TraceDBIndex::BloomGroups as u8; - result[1] = self.0.level; - result[2] = self.0.index as u8; - result[3] = (self.0.index >> 8) as u8; - result[4] = (self.0.index >> 16) as u8; - result[5] = (self.0.index >> 24) as u8; - TraceGroupKey(result) - } -} - #[derive(Debug, Hash, Eq, PartialEq)] enum CacheId { Trace(H256), - Bloom(TraceGroupPosition), } /// Database to store transaction execution trace. @@ -110,52 +62,39 @@ enum CacheId { pub struct TraceDB where T: DatabaseExtras { // cache traces: RwLock>, - blooms: RwLock>, cache_manager: RwLock>, // db - tracesdb: Arc, - // config, - bloom_config: BloomConfig, + tracesdb: Arc, // tracing enabled enabled: bool, // extras extras: Arc, } -impl BloomGroupDatabase for TraceDB where T: DatabaseExtras { - fn blooms_at(&self, position: &GroupPosition) -> Option { - let position = TraceGroupPosition::from(position.clone()); - let result = self.tracesdb.read_with_cache(db::COL_TRACE, &self.blooms, &position).map(Into::into); - self.note_used(CacheId::Bloom(position)); - result - } -} - impl TraceDB where T: DatabaseExtras { /// Creates new instance of `TraceDB`. - pub fn new(config: Config, tracesdb: Arc, extras: Arc) -> Self { + pub fn new(config: Config, tracesdb: Arc, extras: Arc) -> Self { let mut batch = DBTransaction::new(); let genesis = extras.block_hash(0) .expect("Genesis block is always inserted upon extras db creation qed"); batch.write(db::COL_TRACE, &genesis, &FlatBlockTraces::default()); batch.put(db::COL_TRACE, b"version", TRACE_DB_VER); - tracesdb.write(batch).expect("failed to update version"); + tracesdb.key_value().write(batch).expect("failed to update version"); TraceDB { traces: RwLock::new(HashMap::new()), - blooms: RwLock::new(HashMap::new()), + //blooms: RwLock::new(HashMap::new()), cache_manager: RwLock::new(CacheManager::new(config.pref_cache_size, config.max_cache_size, 10 * 1024)), tracesdb: tracesdb, - bloom_config: config.blooms, enabled: config.enabled, extras: extras, } } fn cache_size(&self) -> usize { - let traces = self.traces.read().heap_size_of_children(); - let blooms = self.blooms.read().heap_size_of_children(); - traces + blooms + self.traces.read().heap_size_of_children() + //let blooms = self.blooms.read().heap_size_of_children(); + //traces + blooms } /// Let the cache system know that a cacheable item has been used. @@ -169,26 +108,26 @@ impl TraceDB where T: DatabaseExtras { let current_size = self.cache_size(); let mut traces = self.traces.write(); - let mut blooms = self.blooms.write(); + //let mut blooms = self.blooms.write(); let mut cache_manager = self.cache_manager.write(); cache_manager.collect_garbage(current_size, | ids | { for id in &ids { match *id { CacheId::Trace(ref h) => { traces.remove(h); }, - CacheId::Bloom(ref h) => { blooms.remove(h); }, + //CacheId::Bloom(ref h) => { blooms.remove(h); }, } } traces.shrink_to_fit(); - blooms.shrink_to_fit(); + //blooms.shrink_to_fit(); - traces.heap_size_of_children() + blooms.heap_size_of_children() + traces.heap_size_of_children() }); } /// Returns traces for block with hash. fn traces(&self, block_hash: &H256) -> Option { - let result = self.tracesdb.read_with_cache(db::COL_TRACE, &self.traces, block_hash); + let result = self.tracesdb.key_value().read_with_cache(db::COL_TRACE, &self.traces, block_hash); self.note_used(CacheId::Trace(block_hash.clone())); result } @@ -271,10 +210,10 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { // now let's rebuild the blooms if !request.enacted.is_empty() { - let range_start = request.block_number as Number + 1 - request.enacted.len(); - let range_end = range_start + request.retracted; - let replaced_range = range_start..range_end; - let enacted_blooms = request.enacted + let range_start = request.block_number + 1 - request.enacted.len() as u64; + //let range_end = range_start + request.retracted; + //let replaced_range = range_start..range_end; + let enacted_blooms: Vec<_> = request.enacted .iter() // all traces are expected to be found here. That's why `expect` has been used // instead of `filter_map`. If some traces haven't been found, it meens that @@ -286,19 +225,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { }) .collect(); - let chain = BloomGroupChain::new(self.bloom_config, self); - let trace_blooms = chain.replace(&replaced_range, enacted_blooms); - let blooms_to_insert = trace_blooms.into_iter() - .map(|p| (From::from(p.0), From::from(p.1))) - .collect::>(); - - let blooms_keys: Vec<_> = blooms_to_insert.keys().cloned().collect(); - let mut blooms = self.blooms.write(); - batch.extend_with_cache(db::COL_TRACE, &mut *blooms, blooms_to_insert, CacheUpdatePolicy::Remove); - // note_used must be called after locking blooms to avoid cache/traces deadlock on garbage collection - for key in blooms_keys { - self.note_used(CacheId::Bloom(key)); - } + // TODO: replace it with database for trace blooms + self.tracesdb.blooms().write().insert_blooms(range_start, enacted_blooms.iter()).expect("TODO: blooms pr"); } // insert new block traces into the cache and the database @@ -396,18 +324,19 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { } fn filter(&self, filter: &Filter) -> Vec { - let chain = BloomGroupChain::new(self.bloom_config, self); - let numbers = chain.filter(filter); - numbers.into_iter() - .flat_map(|n| { - let number = n as BlockNumber; - let hash = self.extras.block_hash(number) - .expect("Expected to find block hash. Extras db is probably corrupted"); - let traces = self.traces(&hash) - .expect("Expected to find a trace. Db is probably corrupted."); - self.matching_block_traces(filter, traces, hash, number) - }) - .collect() + unimplemented!(); + //let chain = BloomGroupChain::new(self.bloom_config, self); + //let numbers = chain.filter(filter); + //numbers.into_iter() + //.flat_map(|n| { + //let number = n as BlockNumber; + //let hash = self.extras.block_hash(number) + //.expect("Expected to find block hash. Extras db is probably corrupted"); + //let traces = self.traces(&hash) + //.expect("Expected to find a trace. Db is probably corrupted."); + //self.matching_block_traces(filter, traces, hash, number) + //}) + //.collect() } } @@ -424,6 +353,7 @@ mod tests { use trace::trace::{Call, Action, Res}; use trace::flat::{FlatTrace, FlatBlockTraces, FlatTransactionTraces}; use evm::CallType; + use test_helpers::new_db; struct NoopExtras; @@ -467,10 +397,6 @@ mod tests { } } - fn new_db() -> Arc { - Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))) - } - #[test] fn test_reopening_db_with_tracing_off() { let db = new_db(); @@ -585,7 +511,7 @@ mod tests { let request = create_noncanon_import_request(0, block_0.clone()); let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); assert!(tracedb.traces(&block_0).is_some(), "Traces should be available even if block is non-canon."); } @@ -615,7 +541,7 @@ mod tests { let request = create_simple_import_request(1, block_1.clone()); let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); let filter = Filter { range: (1..1), @@ -631,7 +557,7 @@ mod tests { let request = create_simple_import_request(2, block_2.clone()); let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); let filter = Filter { range: (1..2), @@ -693,7 +619,7 @@ mod tests { let request = create_simple_import_request(1, block_0.clone()); let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); - db.write(batch).unwrap(); + db.key_value().write(batch).unwrap(); } { diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 308eb72da7b..f1b26e2a683 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -17,7 +17,6 @@ //! Trace filters type definitions use std::ops::Range; -use bloomchain::{Filter as BloomFilter, Number}; use ethereum_types::{Address, Bloom, BloomInput}; use trace::flat::FlatTrace; use super::trace::{Action, Res}; @@ -88,16 +87,6 @@ pub struct Filter { pub to_address: AddressesFilter, } -impl BloomFilter for Filter { - fn bloom_possibilities(&self) -> Vec { - self.bloom_possibilities() - } - - fn range(&self) -> Range { - self.range.clone() - } -} - impl Filter { /// Returns combinations of each address. fn bloom_possibilities(&self) -> Vec { diff --git a/util/bloomchain/.gitignore b/util/bloomchain/.gitignore deleted file mode 100644 index d4f917d3d50..00000000000 --- a/util/bloomchain/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -target -Cargo.lock -*.swp diff --git a/util/bloomchain/Cargo.toml b/util/bloomchain/Cargo.toml deleted file mode 100644 index 6bcf6a9b146..00000000000 --- a/util/bloomchain/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -description = "Standalone blockchain bloom filter" -homepage = "https://github.com/debris/bloomchain" -name = "bloomchain" -version = "0.2.0" -authors = ["debris "] -license = "MIT" -keywords = ["ethereum", "ethcore", "bloom", "chain", "filter"] - -[dependencies] -ethbloom = "0.5" - -[dev-dependencies] -rustc-hex = "1.0" -rand = "0.4" diff --git a/util/bloomchain/README.md b/util/bloomchain/README.md deleted file mode 100644 index f5a1fafc8c1..00000000000 --- a/util/bloomchain/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# bloomchain -Standalone blockchain bloom filter. - -[![Build Status][travis-image]][travis-url] - -[travis-image]: https://travis-ci.org/paritytech/bloomchain.svg?branch=master -[travis-url]: https://travis-ci.org/paritytech/bloomchain - -[Documentation](http://paritytech.github.io/bloomchain/bloomchain/index.html) diff --git a/util/bloomchain/src/chain.rs b/util/bloomchain/src/chain.rs deleted file mode 100644 index ba7bc21b356..00000000000 --- a/util/bloomchain/src/chain.rs +++ /dev/null @@ -1,158 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::ops::Range; -use number::Number; -use position::{Position, Manager as PositionManager}; -use bloom::Bloom; -use filter::Filter; -use config::Config; -use database::BloomDatabase; - -/// Prepares all bloom database operations. -pub struct BloomChain<'a> { - positioner: PositionManager, - db: &'a BloomDatabase, -} - -impl<'a> BloomChain<'a> { - /// Creates new bloom chain. - pub fn new(config: Config, db: &'a BloomDatabase) -> Self { - let positioner = PositionManager::new(config.elements_per_index, config.levels); - - BloomChain { - positioner: positioner, - db: db, - } - } - - /// Internal function which does bloom search recursively. - fn blocks(&self, range: &Range, bloom: &Bloom, level: usize, offset: usize) -> Option> { - let index = self.positioner.position(offset, level); - - match self.db.bloom_at(&index) { - None => return None, - Some(level_bloom) => match level { - // if we are on the lowest level - 0 if level_bloom.contains_bloom(bloom) => return Some(vec![offset]), - // return None if current level doesnt contain given bloom - _ if !level_bloom.contains_bloom(bloom) => return None, - // continue processing && go down - _ => () - } - }; - - let level_size = self.positioner.level_size(level - 1); - let from_position = self.positioner.position(range.start, level - 1); - let to_position = self.positioner.position(range.end, level - 1); - let res: Vec = self.positioner.lower_level_positions(&index).into_iter() - // chose only blooms in range - .filter(|li| li.index >= from_position.index && li.index <= to_position.index) - // map them to offsets - .map(|li| li.index * level_size) - // get all blocks that may contain our bloom - // filter existing ones - .filter_map(|off| self.blocks(range, bloom, level - 1, off)) - // flatten nested structures - .flat_map(|v| v) - .collect(); - Some(res) - } - - /// Inserts the bloom at all filter levels. - pub fn insert(&self, number: Number, bloom: Bloom) -> HashMap { - let mut result: HashMap = HashMap::new(); - - for level in 0..self.positioner.levels() { - let position = self.positioner.position(number, level); - let new_bloom = match self.db.bloom_at(&position) { - Some(mut old_bloom) => { - old_bloom.accrue_bloom(&bloom); - old_bloom - }, - None => bloom.clone(), - }; - - result.insert(position, new_bloom); - } - - result - } - - /// Resets data in range. - /// Inserts new data. - /// Inserted data may exceed reseted range. - pub fn replace(&self, range: &Range, blooms: Vec) -> HashMap { - let mut result: HashMap = HashMap::new(); - - // insert all new blooms at level 0 - for (i, bloom) in blooms.iter().enumerate() { - result.insert(self.positioner.position(range.start + i, 0), bloom.clone()); - } - - // reset the rest of blooms - for reset_number in range.start + blooms.len()..(range.end + 1) { - result.insert(self.positioner.position(reset_number, 0), Bloom::default()); - } - - for level in 1..self.positioner.levels() { - for i in 0..blooms.len() { - - let index = self.positioner.position(range.start + i, level); - let new_bloom = { - // use new blooms before db blooms where necessary - let bloom_at = | index | { result.get(&index).cloned().or_else(|| self.db.bloom_at(&index)) }; - - self.positioner.lower_level_positions(&index) - .into_iter() - // get blooms - // filter existing ones - .filter_map(bloom_at) - // BitOr all of them - .fold(Bloom::default(), |mut acc, bloom| { - acc.accrue_bloom(&bloom); - acc - }) - }; - - result.insert(index, new_bloom); - } - } - - result - } - - /// Returns all numbers with given bloom. - pub fn with_bloom(&self, range: &Range, bloom: &Bloom) -> Vec { - let mut result = vec![]; - // lets start from highest level - let max_level = self.positioner.max_level(); - let level_size = self.positioner.level_size(max_level); - let from_position = self.positioner.position(range.start, max_level); - let to_position = self.positioner.position(range.end, max_level); - - for index in from_position.index..to_position.index + 1 { - // offset will be used to calculate where we are right now - let offset = level_size * index; - - // go doooown! - if let Some(blocks) = self.blocks(range, bloom, max_level, offset) { - result.extend(blocks); - } - } - - result - } - - /// Filter the chain returing all numbers matching the filter. - pub fn filter(&self, filter: &Filter) -> Vec { - let range = filter.range(); - let mut blocks = filter.bloom_possibilities() - .into_iter() - .flat_map(|ref bloom| self.with_bloom(&range, bloom)) - .collect::>() - .into_iter() - .collect::>(); - - blocks.sort(); - blocks - } -} diff --git a/util/bloomchain/src/config.rs b/util/bloomchain/src/config.rs deleted file mode 100644 index 3e729922a17..00000000000 --- a/util/bloomchain/src/config.rs +++ /dev/null @@ -1,17 +0,0 @@ -/// `BloomChain` configuration. -#[derive(Debug, PartialEq, Clone, Copy)] -pub struct Config { - /// Number of levels. - pub levels: usize, - /// Number of elements in a single index. - pub elements_per_index: usize, -} - -impl Default for Config { - fn default() -> Self { - Config { - levels: 3, - elements_per_index: 16, - } - } -} diff --git a/util/bloomchain/src/database.rs b/util/bloomchain/src/database.rs deleted file mode 100644 index 9aba41e7c64..00000000000 --- a/util/bloomchain/src/database.rs +++ /dev/null @@ -1,7 +0,0 @@ -use position::Position; -use bloom::Bloom; - -/// Readonly `Bloom` database. -pub trait BloomDatabase { - fn bloom_at(&self, position: &Position) -> Option; -} diff --git a/util/bloomchain/src/filter.rs b/util/bloomchain/src/filter.rs deleted file mode 100644 index 06d657ba442..00000000000 --- a/util/bloomchain/src/filter.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::ops::Range; -use bloom::Bloom; -use number::Number; - -/// Should be used to filter blocks from `BloomChain`. -pub trait Filter { - /// All bloom possibilities that we are searching for. - fn bloom_possibilities(&self) -> Vec; - /// Range of search. - fn range(&self) -> Range; -} diff --git a/util/bloomchain/src/group/bridge.rs b/util/bloomchain/src/group/bridge.rs deleted file mode 100644 index b01650157c6..00000000000 --- a/util/bloomchain/src/group/bridge.rs +++ /dev/null @@ -1,31 +0,0 @@ -use bloom::Bloom; -use config::Config; -use database::BloomDatabase; -use position::Position; -use group::position::Manager as PositionManager; -use super::BloomGroupDatabase; - -/// Bridge between `BloomDatabase` and `BloomGroupDatabase`. -pub struct GroupDatabaseBridge<'a> { - positioner: PositionManager, - db: &'a BloomGroupDatabase, -} - -impl<'a> GroupDatabaseBridge<'a> { - pub fn new(config: Config, db: &'a BloomGroupDatabase) -> Self { - let positioner = PositionManager::new(config.elements_per_index); - - GroupDatabaseBridge { - positioner: positioner, - db: db, - } - } -} - -impl<'a> BloomDatabase for GroupDatabaseBridge<'a> { - fn bloom_at(&self, position: &Position) -> Option { - let position = self.positioner.position(position); - self.db.blooms_at(&position.group) - .and_then(|group| group.blooms.into_iter().nth(position.number)) - } -} diff --git a/util/bloomchain/src/group/chain.rs b/util/bloomchain/src/group/chain.rs deleted file mode 100644 index cfd7796f4d0..00000000000 --- a/util/bloomchain/src/group/chain.rs +++ /dev/null @@ -1,70 +0,0 @@ -use std::collections::HashMap; -use std::ops::Range; -use bloom::Bloom; -use chain::BloomChain; -use config::Config; -use number::Number; -use filter::Filter; -use position::Position as BloomPosition; -use super::{GroupDatabaseBridge, BloomGroupDatabase, BloomGroup, GroupPosition}; -use super::position::Manager as PositionManager; - -/// Performs all bloom database operations using `BloomGroup`s. -pub struct BloomGroupChain<'a> { - config: Config, - db: &'a BloomGroupDatabase, - bridge: GroupDatabaseBridge<'a>, -} - -impl<'a> BloomGroupChain<'a> { - pub fn new(config: Config, db: &'a BloomGroupDatabase) -> Self { - let bridge = GroupDatabaseBridge::new(config, db); - - BloomGroupChain { - config: config, - db: db, - bridge: bridge, - } - } - - fn group_blooms(&self, blooms: HashMap) -> HashMap { - let positioner = PositionManager::new(self.config.elements_per_index); - blooms.into_iter() - .fold(HashMap::new(), | mut acc, (position, bloom) | { - { - let position = positioner.position(&position); - let group = acc - .entry(position.group.clone()) - .or_insert_with(|| self.db - .blooms_at(&position.group) - .unwrap_or_else(|| BloomGroup::new(self.config.elements_per_index)) - ); - assert_eq!(self.config.elements_per_index, group.blooms.len()); - group.blooms[position.number] = bloom; - } - acc - }) - } - - pub fn insert(&self, number: Number, bloom: Bloom) -> HashMap { - let bloom_chain = BloomChain::new(self.config, &self.bridge); - let modified_blooms = bloom_chain.insert(number, bloom); - self.group_blooms(modified_blooms) - } - - pub fn replace(&self, range: &Range, blooms: Vec) -> HashMap { - let bloom_chain = BloomChain::new(self.config, &self.bridge); - let modified_blooms = bloom_chain.replace(range, blooms); - self.group_blooms(modified_blooms) - } - - pub fn with_bloom(&self, range: &Range, bloom: &Bloom) -> Vec { - let bloom_chain = BloomChain::new(self.config, &self.bridge); - bloom_chain.with_bloom(range, bloom) - } - - pub fn filter(&self, filter: &Filter) -> Vec { - let bloom_chain = BloomChain::new(self.config, &self.bridge); - bloom_chain.filter(filter) - } -} diff --git a/util/bloomchain/src/group/database.rs b/util/bloomchain/src/group/database.rs deleted file mode 100644 index 494184f3ebc..00000000000 --- a/util/bloomchain/src/group/database.rs +++ /dev/null @@ -1,6 +0,0 @@ -use group::{GroupPosition, BloomGroup}; - -/// Readonly `BloomGroup` database. -pub trait BloomGroupDatabase { - fn blooms_at(&self, position: &GroupPosition) -> Option; -} diff --git a/util/bloomchain/src/group/group.rs b/util/bloomchain/src/group/group.rs deleted file mode 100644 index 084c8f8e48e..00000000000 --- a/util/bloomchain/src/group/group.rs +++ /dev/null @@ -1,17 +0,0 @@ -use bloom::Bloom; - -/// Group of blooms that are in the same index. -#[derive(Debug, Clone)] -pub struct BloomGroup { - pub blooms: Vec, -} - -impl BloomGroup { - pub fn new(size: usize) -> Self { - let blooms = (0..size).into_iter().map(|_| Bloom::default()).collect(); - - BloomGroup { - blooms: blooms - } - } -} diff --git a/util/bloomchain/src/group/mod.rs b/util/bloomchain/src/group/mod.rs deleted file mode 100644 index b6cabf628fc..00000000000 --- a/util/bloomchain/src/group/mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Bloom grouping. -//! -//! Optimization gathering together blooms that are in the same index and are likely to be retrived together. - -mod bridge; -mod chain; -mod database; -mod group; -mod position; - -pub use self::bridge::GroupDatabaseBridge; -pub use self::chain::BloomGroupChain; - -pub use self::database::BloomGroupDatabase; -pub use self::group::BloomGroup; -pub use self::position::GroupPosition; diff --git a/util/bloomchain/src/group/position/manager.rs b/util/bloomchain/src/group/position/manager.rs deleted file mode 100644 index 611a5bb784c..00000000000 --- a/util/bloomchain/src/group/position/manager.rs +++ /dev/null @@ -1,28 +0,0 @@ -use super::{Position, GroupPosition}; -use position::Position as BloomPosition; - -pub struct Manager { - index_size: usize -} - -impl Manager { - pub fn new(index_size: usize) -> Self { - Manager { - index_size: index_size - } - } - - pub fn group_position(&self, pos: &BloomPosition) -> GroupPosition { - GroupPosition { - level: pos.level, - index: pos.index / self.index_size, - } - } - - pub fn position(&self, pos: &BloomPosition) -> Position { - Position { - group: self.group_position(pos), - number: pos.index % self.index_size, - } - } -} diff --git a/util/bloomchain/src/group/position/mod.rs b/util/bloomchain/src/group/position/mod.rs deleted file mode 100644 index fc95de4dd05..00000000000 --- a/util/bloomchain/src/group/position/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod position; -mod manager; - -pub use self::position::{Position, GroupPosition}; -pub use self::manager::Manager; diff --git a/util/bloomchain/src/group/position/position.rs b/util/bloomchain/src/group/position/position.rs deleted file mode 100644 index 88f26d69aba..00000000000 --- a/util/bloomchain/src/group/position/position.rs +++ /dev/null @@ -1,17 +0,0 @@ -/// Uniquely identifies bloom group position. -#[derive(Debug, PartialEq, Eq, Hash, Clone)] -pub struct GroupPosition { - /// Bloom level. - pub level: usize, - /// Index of the group. - pub index: usize, -} - -/// Uniquely identifies bloom position including the position in the group. -#[derive(Debug, PartialEq, Eq, Hash, Clone)] -pub struct Position { - /// Group position. - pub group: GroupPosition, - /// Number in group. - pub number: usize, -} diff --git a/util/bloomchain/src/lib.rs b/util/bloomchain/src/lib.rs deleted file mode 100644 index 997ae083912..00000000000 --- a/util/bloomchain/src/lib.rs +++ /dev/null @@ -1,17 +0,0 @@ -extern crate ethbloom as bloom; - -mod chain; -mod config; -mod database; -pub mod group; -mod number; -mod position; -mod filter; - -pub use bloom::{Bloom, BloomRef, Input}; -pub use chain::BloomChain; -pub use config::Config; -pub use database::BloomDatabase; -pub use number::Number; -pub use position::Position; -pub use filter::Filter; diff --git a/util/bloomchain/src/number.rs b/util/bloomchain/src/number.rs deleted file mode 100644 index 3ff82f19573..00000000000 --- a/util/bloomchain/src/number.rs +++ /dev/null @@ -1,2 +0,0 @@ -/// Represents block number. -pub type Number = usize; diff --git a/util/bloomchain/src/position/manager.rs b/util/bloomchain/src/position/manager.rs deleted file mode 100644 index a405878ab52..00000000000 --- a/util/bloomchain/src/position/manager.rs +++ /dev/null @@ -1,142 +0,0 @@ -//! Simplifies working with bloom indexes. - -use super::Position; - -/// Simplifies working with bloom indexes. -pub struct Manager { - index_size: usize, - level_sizes: Vec, -} - -impl Manager { - /// Creates new indexer. - pub fn new(index_size: usize, levels: usize) -> Self { - if levels == 0 { - panic!("Manager requires at least 1 level."); - } - - let mut level_sizes = vec![1]; - level_sizes.extend_from_slice(&(1..).into_iter() - .scan(1, |acc, _| { - *acc = *acc * index_size; - Some(*acc) - }) - .take(levels - 1) - .collect::>()); - - Manager { - index_size: index_size, - level_sizes: level_sizes, - } - } - - /// Unsafely get level size. - pub fn level_size(&self, level: usize) -> usize { - self.level_sizes[level as usize] - } - - /// Converts block number and level to `Position`. - pub fn position(&self, block_number: usize, level: usize) -> Position { - Position { - level: level, - index: block_number / self.level_size(level), - } - } - - /// Return bloom which are dependencies for given index. - /// - /// Bloom indexes are ordered from lowest to highest. - pub fn lower_level_positions(&self, index: &Position) -> Vec { - // this is the lowest level - if index.level == 0 { - return vec![]; - } - - let new_level = index.level - 1; - let offset = self.index_size * index.index; - - (0..self.index_size) - .map(|i| Position { - level: new_level, - index: offset + i - }) - .collect() - } - - /// Return number of levels. - pub fn levels(&self) -> usize { - self.level_sizes.len() - } - - /// Returns max indexer level. - pub fn max_level(&self) -> usize { - self.level_sizes.len() - 1 - } -} - -#[cfg(test)] -mod tests { - use position::Position; - use super::*; - #[test] - fn test_level_size() { - let indexer = Manager::new(16, 3); - assert_eq!(indexer.level_size(0), 1); - assert_eq!(indexer.level_size(1), 16); - assert_eq!(indexer.level_size(2), 256); - } - - #[test] - fn test_position() { - let indexer = Manager::new(16, 3); - - let bi0 = indexer.position(0, 0); - assert_eq!(bi0.level, 0); - assert_eq!(bi0.index, 0); - - let bi1 = indexer.position(1, 0); - assert_eq!(bi1.level, 0); - assert_eq!(bi1.index, 1); - - let bi2 = indexer.position(2, 0); - assert_eq!(bi2.level, 0); - assert_eq!(bi2.index, 2); - - let bi3 = indexer.position(3, 1); - assert_eq!(bi3.level, 1); - assert_eq!(bi3.index, 0); - - let bi4 = indexer.position(15, 1); - assert_eq!(bi4.level, 1); - assert_eq!(bi4.index, 0); - - let bi5 = indexer.position(16, 1); - assert_eq!(bi5.level, 1); - assert_eq!(bi5.index, 1); - - let bi6 = indexer.position(255, 2); - assert_eq!(bi6.level, 2); - assert_eq!(bi6.index, 0); - - let bi7 = indexer.position(256, 2); - assert_eq!(bi7.level, 2); - assert_eq!(bi7.index, 1); - } - - #[test] - fn test_lower_level_positions() { - let indexer = Manager::new(16, 3); - - let bi = indexer.position(256, 2); - assert_eq!(bi.level, 2); - assert_eq!(bi.index, 1); - - let mut ebis = vec![]; - for i in 16..32 { - ebis.push(Position { level: 1, index: i}); - } - - let bis = indexer.lower_level_positions(&bi); - assert_eq!(ebis, bis); - } -} diff --git a/util/bloomchain/src/position/mod.rs b/util/bloomchain/src/position/mod.rs deleted file mode 100644 index 4fa736a1636..00000000000 --- a/util/bloomchain/src/position/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod position; -pub mod manager; - -pub use self::position::Position; -pub use self::manager::Manager; diff --git a/util/bloomchain/src/position/position.rs b/util/bloomchain/src/position/position.rs deleted file mode 100644 index 32845cbcc5d..00000000000 --- a/util/bloomchain/src/position/position.rs +++ /dev/null @@ -1,8 +0,0 @@ -/// Uniquely identifies bloom position. -#[derive(Debug, PartialEq, Eq, Hash)] -pub struct Position { - /// Bloom level. - pub level: usize, - /// Index of the bloom. - pub index: usize, -} diff --git a/util/bloomchain/tests/bloomchain.rs b/util/bloomchain/tests/bloomchain.rs deleted file mode 100644 index 4a77407a7a2..00000000000 --- a/util/bloomchain/tests/bloomchain.rs +++ /dev/null @@ -1,170 +0,0 @@ -extern crate bloomchain; -extern crate rustc_hex; - -mod util; - -use bloomchain::{Bloom, BloomChain, Config}; -use util::{BloomMemoryDatabase, FromHex, for_each_bloom, generate_n_random_blooms}; - -#[test] -fn simple_bloom_search() { - let config = Config::default(); - let mut db = BloomMemoryDatabase::default(); - let bloom = Bloom::from_hex("00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - - let modified_blooms = { - let chain = BloomChain::new(config, &db); - let block_number = 23; - chain.insert(block_number, bloom.clone()) - }; - - // number of modified blooms should always be equal number of levels - assert_eq!(modified_blooms.len(), config.levels); - db.insert_blooms(modified_blooms); - - let chain = BloomChain::new(config, &db); - assert_eq!(chain.with_bloom(&(0..100), &bloom), vec![23]); - assert_eq!(chain.with_bloom(&(0..22), &bloom), vec![]); - assert_eq!(chain.with_bloom(&(23..23), &bloom), vec![23]); - assert_eq!(chain.with_bloom(&(24..100), &bloom), vec![]); -} - -#[test] -fn partly_matching_bloom_searach() { - let config = Config::default(); - let mut db = BloomMemoryDatabase::default(); - let bloom0 = Bloom::from_hex("10100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom1 = Bloom::from_hex("11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom2 = Bloom::from_hex("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - - let modified_blooms_0 = { - let chain = BloomChain::new(config, &db); - let block_number = 14; - chain.insert(block_number, bloom0) - }; - - db.insert_blooms(modified_blooms_0); - - let modified_blooms_1 = { - let chain = BloomChain::new(config, &db); - let block_number = 15; - chain.insert(block_number, bloom1) - }; - - db.insert_blooms(modified_blooms_1); - - - let chain = BloomChain::new(config, &db); - assert_eq!(chain.with_bloom(&(0..100), &bloom2), vec![14, 15]); -} - -#[test] -fn bloom_replace() { - let config = Config::default(); - let mut db = BloomMemoryDatabase::default(); - let bloom0 = Bloom::from_hex("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom1 = Bloom::from_hex("01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom2 = Bloom::from_hex("00100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom3 = Bloom::from_hex("00010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom4 = Bloom::from_hex("00001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom5 = Bloom::from_hex("00000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - - let modified_blooms_0 = { - let chain = BloomChain::new(config, &db); - let block_number = 14; - chain.insert(block_number, bloom0.clone()) - }; - - db.insert_blooms(modified_blooms_0); - - let modified_blooms_1 = { - let chain = BloomChain::new(config, &db); - let block_number = 15; - chain.insert(block_number, bloom1.clone()) - }; - - db.insert_blooms(modified_blooms_1); - - let modified_blooms_2 = { - let chain = BloomChain::new(config, &db); - let block_number = 16; - chain.insert(block_number, bloom2.clone()) - }; - - db.insert_blooms(modified_blooms_2); - - let modified_blooms_3 = { - let chain = BloomChain::new(config, &db); - let block_number = 17; - chain.insert(block_number, bloom3.clone()) - }; - - db.insert_blooms(modified_blooms_3); - - - let reset_modified_blooms = { - let chain = BloomChain::new(config, &db); - chain.replace(&(15..17), vec![bloom4.clone(), bloom5.clone()]) - }; - - db.insert_blooms(reset_modified_blooms); - - let chain = BloomChain::new(config, &db); - assert_eq!(chain.with_bloom(&(0..100), &bloom0), vec![14]); - assert_eq!(chain.with_bloom(&(0..100), &bloom1), vec![]); - assert_eq!(chain.with_bloom(&(0..100), &bloom2), vec![]); - assert_eq!(chain.with_bloom(&(0..100), &bloom3), vec![]); - assert_eq!(chain.with_bloom(&(0..100), &bloom4), vec![15]); - assert_eq!(chain.with_bloom(&(0..100), &bloom5), vec![16]); -} - -#[test] -fn file_test_bloom_search() { - let config = Config::default(); - let mut db = BloomMemoryDatabase::default(); - let blooms_file = include_bytes!("data/blooms.txt"); - - for_each_bloom(blooms_file, | block_number, bloom | { - let modified_blooms = { - let chain = BloomChain::new(config, &db); - chain.insert(block_number, bloom) - }; - - // number of modified blooms should always be equal number of levels - assert_eq!(modified_blooms.len(), config.levels); - db.insert_blooms(modified_blooms); - }); - - for_each_bloom(blooms_file, | block_number, bloom | { - let chain = BloomChain::new(config, &db); - let blocks = chain.with_bloom(&(block_number..block_number), &bloom); - assert_eq!(blocks.len(), 1); - assert_eq!(blocks[0], block_number); - }); -} - -#[test] -fn random_bloom_replacement() { - let insertions = 10_000; - - let config = Config::default(); - let mut db = BloomMemoryDatabase::default(); - let blooms = generate_n_random_blooms(insertions); - - for (i, bloom) in blooms.iter().enumerate() { - - let modified_blooms = { - let chain = BloomChain::new(config, &db); - chain.replace(&(i..i), vec![bloom.clone()]) - }; - - db.insert_blooms(modified_blooms); - } - - for (i, bloom) in blooms.iter().enumerate() { - let chain = BloomChain::new(config, &db); - let blocks = chain.with_bloom(&(i..i), bloom); - assert_eq!(blocks.len(), 1); - assert_eq!(blocks[0], i); - } -} diff --git a/util/bloomchain/tests/data/blooms.txt b/util/bloomchain/tests/data/blooms.txt deleted file mode 100644 index 204186ec349..00000000000 --- a/util/bloomchain/tests/data/blooms.txt +++ /dev/null @@ -1,739 +0,0 @@ -300054 0x00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -300059 0x00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000 -300221 0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -301826 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -303166 0x00000000000000000000000000000000000000001000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000808000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000020000000001000000000000000000000000000000000000000000000000000000000000000000 -303345 0x00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -303379 0x00000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000800000000000000001000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000080000000006000008000000000000000000080000000000000000000000000000000000000000001000000000000000000000008000000000400000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000800000000000000000000000000000000000002004000000000000 -303388 0x00000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000800000040000000001000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000080000000006001008000000000000008000080000000000000000000000000000000000000000001000000000000000000000008000000000400000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000800000000000000040000000000000000000002004000000000000 -303621 0x00000000000000000000008000000000200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000080000000000000000000000080000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000 -303670 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000400200000000000000 -303674 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000040000000000000000000000000000000000000000000000000000000000000000000000001000000000000200000000000000 -303683 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000400200000000000000 -303689 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000000400000000000000000000000000000000000000000000000000000000001000000000040200000000000000 -303692 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000400000000000000000000000000000000000000000000000000000000001000000000040200000000000000 -303716 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000040000000000000000000000000000000000000000000000000000000000000000000000001000000000000200000000000000 -303717 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000040000000000000000000000000000000000000000000000000000000000000000000000001000000000000200000000000000 -303748 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000400200000000000000 -303756 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000000400000000000000000000000000000000000000000000000000000000001000000000040200000000000000 -303758 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000400000000000000000000000000000000000000000000000000000000001000000000040200000000000000 -304090 0x00000000000000000000000000000000100000000000000000000000000000000000000000000000000200000000000000800000000000000000000000040000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000003000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000 -304095 0x04000000000000000000000000000000100000000000000000000000000000000000000000000000000200000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000 -304107 0x00000000000000000000000000000000100000000000000000000000000000000000000000000000000200000000000000800000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000400000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304113 0x00000000000000000000000000000000100000000000000000000000000000000000000000000000000200000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000002000000000000000000000000000000000000000000000000003008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304222 0x00000000000000000000000000000000100000000000000000000000000000000000000000000000000200000000000000800000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000800000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304245 0x00000000000000000000000000000000100000000000000000000000000000000000000000000000000200000000000000800000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000080000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304247 0x000000080000000000000000000000800000020000000000000000000000000000000000000000000202000000000000008000004004000000000000000000000000000000000000000000000200000000200000000080000000000000000000000004000000000000000000000000000000001040000000000000000000000000000004000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000c0002000000000000000000000000000000001000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304312 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000040000000000000200000000000000000000000000000000000000000000000000000000000000000000000000 -304319 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000100000000000020000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000080000000000000000000000000008000000000000000000000000000000000008000000000000000000000000000000000000020000000000002000000000000000000040000000000000200000000000000000000000000000000000000000000000000000000000000000000000000 -304367 0x00000000000000000000001000000000000000000400020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000100000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304375 0x00000000004000000000001000000000000000000400020000000800000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000020000000000000000000000000000000000000000000000000008000000000000010000000008000000000000000000000000000000000008000800000000000000000000000100000000000000000000000000000000000000000100000000000000002000000000002000000040010010000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304407 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304431 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -304433 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -304608 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000400000000000000000000040000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 -304609 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000400000000000000000000040000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 -304788 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -304794 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -304819 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -304835 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304849 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -304856 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304862 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -304872 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -304881 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -304902 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -304996 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -304999 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305006 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -305010 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305425 0x00000000004000000000000000000001000000000000020000000000000000000000000000000000000000000000000000000000008000000080000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010400000048000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000400000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305445 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000080000100000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305448 0x00000000004000000000000000000000000000000000020000000000000000000004000008000000000000000000000000000000000000000000000000000800000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000080000100000000002000000000000000000040000000000000000000000100000000000000000000000000000000000000000000000000000000000000000 -305450 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000080000000000000000000000000000020000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000004000000000000000000000000000 -305452 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000002000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000080000000000000000000000000000020000000000000000000000000000000000000000000008002000000000000000000040000000000000000000000000400000000000000000000000000000000004000000000000000000000000000 -305454 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000001000000040000000000000000000000000000000000000000000000000000000000000000000000000840000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305457 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305463 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000200080000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305464 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000008000000000000000000000000000000000240000000200480000000000000000000000000000000000000000000000000000002000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305468 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008080000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305488 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000002000000000000008000000000000010000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305492 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000008000000000000000000000000000000008040000000000000000000000000000002000000000001000000000000000000000000000400000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000200000000000000000000000000000000000000000000 -305501 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000008000000000000000000040000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000080000000000000 -305502 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000008000000000000008000000000000000000040000000001000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000080000000000000000000000000000000000010000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000080000000000000 -305510 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000044000004000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305616 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305620 0x0000000000400000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000040000000000000080000000000000000000000000000800000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000040000000001000000000a000000000000000010000000000000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305622 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000080000000000000000000000000200000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000080000000000000 -305624 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000001000000000000000080000000000000000000000000200000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000004000000000000000000000000004000000000000000000000000000000000000080000000000000 -305626 0x00000000004000000000100000000000000000000000020000000000000000000000000002000000000000000000000000000000200000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000004000000000002000000000000002000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305627 0x00000001000000000000000000000200000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000040000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305629 0x00000001004000000000000000000200000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000040000000002000000000000000000040000000000000000001040000000000000000000000000000000000000000000000000000000000000000000 -305634 0x00000000005080000000000000000000000000000000020000400000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008020000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000400000000000000000000000 -305826 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000400000000000000002000000000000000000840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305827 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000100000000000000000000000000040000000000000000000000000000000000000000000000000000000000000040000000000000000000000010000000008000000000000000000000000000000100008000000000000000000000000000000000000000000000000000000000000000000000400000000000000002004000000000000000840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305829 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000008000000000080000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000080000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305834 0x00000000004002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000008000000000080000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000020000000000000000000000000000008000000000000000000000000000000000000000000000080000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -305839 0x00000000000000000000000000000000000010000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000080000000000000000000000000000000000000000000000000000000000000 -305841 0x40000000004000000000000000000000000010000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000008000000008000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000080000000000000000000000000000000000000000000008000000000000000 -306889 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -307290 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -307508 0x00000000000000000000000000000000000000000000020000000000000000000000200000000000400000000000000000000000000000000000000000000000002000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -307509 0x00000000004000000000000000000000000000000000020000000000000000000000200000000000400000000000000000000000000000000000000000000000002000000000000000008000000000000000000000000000000000040000000000040000000000000000000000000000000000000000000000000000000000000000000000000010000000008000010000004000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -307513 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000004000000000000000000000000010000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000200000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -307519 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000001000000000000002000000000000000000040000000000000000000000000000000000000000000080000000000000000000000000000000000000000000 -307528 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000020000000000000000000000000000000000000000000000000000000000000000100000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -308010 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000080000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000 -308115 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000040000000000000000000000000000000000000000000000000000000000000000000000001000000000000200000000000000 -308124 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000400200000000000000 -308127 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000040000000000000000000000000000000000000000000000000000000000000000000000001000000000000200000000000000 -308157 0x00000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000020000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000 -308183 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000002020000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -308190 0x00000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000020000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000 -308216 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000002020000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000 -308224 0x00000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000020000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000 -308257 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -308265 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -308267 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -308268 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -308285 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -308599 0x00000000000000000000000000000000000000000000080000000000000800000000000000000010000000000000000000200002000000000000000000000000000000000000000000020000001000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004010010000002000000000000000400000000000000000000000000000000000000000000040000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -309175 0x00000000002000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -309177 0x00000000002000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -309184 0x00000000002000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -309186 0x00000000002000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -309190 0x00000000002000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -309194 0x00000000002000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -309198 0x00000000002000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -309417 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -309881 0x00400000000000000000000000000000000000000000004000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000 -309883 0x00400000000000000000000000000000000000000000004000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000 -309892 0x00400000000000000000000000000000000000000000004000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000 -310069 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -310114 0x00400000000000000000000000000000000000000000004000000000000000000000000000100000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -310116 0x00400000000000000000000000000000000000000000004000000000000000000000000000100000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -310177 0x00400000000000000000000000000000000000000000004000000000000000000000000000100000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -310533 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -310589 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -310592 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -310599 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -310601 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -310604 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -311317 0x00000000002000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -311758 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -311858 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -311859 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -311865 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -311888 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -312096 0x00400000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000200000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -312124 0x00400000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000200000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -312367 0x00400000000000000000000000000000000400000000004000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -312371 0x00400000000000000000000000000000000400000000004000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -312383 0x00400000000000000000000000000000000400000000004000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -313355 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -313368 0x00000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -313507 0x00000000000000000000000000000000000000000200000000000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -313526 0x00000000000000000000000000000000000000000200000000000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -313724 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -313789 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -314190 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -314375 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000008000000000000000008000400000000000000000000000000 -315698 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -315705 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -315780 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -316726 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000400000000000000000000000020000000000000000000000000000000000000000000040000000000000000 -316747 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -317179 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000040000000000000000000000000000000000000000000000000000000000000000000000001000000000000200000000000000 -317522 0x04000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000800000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000006001008000000000000008000080000000000000000000000000000000000000000001000000000100000000000008000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000040000000000000008000002004000000000000 -317526 0x00000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -317536 0x00000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000020000000000800000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000006000008000000000000000000080000000000000000000000000000000000000000001000000000000000000000008000000800400000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000002004000000000000 -317567 0x00000000000000200000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000001004000000000000000004000000020000000000000000000000000000000000000000000000000000000000000000000000000000000001000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -317588 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -317597 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000400000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -317606 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -317610 0x00000000000000200000000000000000000000000000000000020000000000000000000000000000000000400000000000000000000800000080000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000001044000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000400000000000000000000000000000000000000000000000000000000000000000000440000000000000000 -317643 0x00000000000000200000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000010000000000000000000000000000004000000000020000000000000000000000000000000000000000000001004000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -317646 0x00000000000000000000000000000000000000000000000000004000000000000000000000000000000000400000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000010000000000000000000000000000004000000000020000000000000000000000000000000000000000000001000000000000000000004000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -317660 0x00000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000800000000000000001000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000080000000006000008000000000000000000080000000000000000000000000000000000000000001000000000000000000000008000000000400002000000000000000000000000000000000000000000000000000008000000000000000000000000000000000800000000000000000000000000000000000002004000000000000 -317957 0x00000000000000000000000000000000000000000200000000000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -318030 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -318032 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -318033 0x00000000001000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000000000800000000000000001000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000004000000000000000080000000006000000000000000000000000080000000000000000000000000000000000000000005000000000000000000000000000000008400000000000000000000000000000000000000000000000000008000000000000000000000000020000000000000800000000000000000000000000000000000002004000000000000 -318034 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -318036 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -318063 0x00000000001000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000000000800000040000000001000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000080000000006000000000000000000000000080000000000000000000000000000000000000000005000000000000000000000000000000008400000000000000000000000000000000000000000000000000008000000000000000000000000040000000000000800000000000000000000000000000000000002004000000000000 -318074 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000010020000000000000000000200000000000000000080000000020000000000000000000800000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000008000000000000000000000000000000000000000000000000000008000000000000000000000000020000000000000000000000000000000000000000000000000102000000000000000 -318096 0x04000000001000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000000000800000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000080000000006000000000000000000000000080000000000000000000000000000000000000000005000000000100000000000000000000008400000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000800000000000000000000000000000008000002004000000000000 -318137 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -318528 0x00000000001000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000020000000000800000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000080000000006000000000000000000000000080000000000000000000000000000000000000000005000000000000000000000000000000808400000000000000400000000000000000000000000000000000008000000000000000000000000000000000000000800000000000000000000000000000000000002004000000000000 -318627 0x00000000001000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000000000800000000000000001000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000004000000000000000080000000006000000000000000000000000080000000000000000000000000000000000000000005000000000000000000000000000000008400002000000000000000000000000000000000000000000000008000008000000000000000000000000000000000800000000000000000000000000000000000002004000000000000 -318639 0x00000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000800000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000002000000000000000000000010000000000000004800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000080000000000000000000000000 -318650 0x00000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000800000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000010000000000000004000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000 -318653 0x00000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000004000000000000000000000000080000000000000000000000000000000000000000000000000000000200000000000000000000000000800000000000000000000000000000000000000000000000000000000000010000000000000000000000000800000000000000000000000000000000000000000000000000000 -318904 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -319523 0x00000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000400000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -321346 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -321884 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -321900 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000400000000000000000000000020000000000000000000000000000000000000000000040000000000000000 -322038 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -322041 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -322043 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -322047 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -322048 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -322056 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -322059 0x00000000001000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000000000000800000000000000011000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000080000000006000000000000000000000001080000800000000000000000000000000000000000005000000000000000000000000000000008400000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000800000000000000000000000000000000000002004000000000000 -322083 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -322090 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -322108 0x04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000010020000000000000000000200000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080000000000000000000000000000000000000000004000000000100000000000000000000008000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000800000000000000000000000000000008000100000000000000000 -322121 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000010000000000100000010020000000000000000000200000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000001080000800000000000000000000000000000000000004000000000000000000000000000000808000000000000000400000000000000000000000000000000000008000000000000000000000000000000000000000800000000000000000000000000000000000100000000000000000 -322122 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000100000010020000000000000000040200000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080000000000000000000000000000000000000000004000000000000000000000000000000008000000000000000000000000000000000000000000000000000008000000000000000000000000040000000000000800000000000000000000000000000000000100000000000000000 -322128 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000010020000000000000000000200000000000000000088000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080000000000000000000000000000000000000000004000000000000000000000000000000008000002000000000000000000000000000000000000000000000008000008000000000000000000000000000000000800000000000000000000000000000000000100000000000000000 -322454 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008010000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000010000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000080000000000000000000000000000000000000000000000000000000000000000000000000 -322509 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008010000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000080000000000000000000000000000008000000000200000000000000000010000000000000000000000000000000000000000000000000000000002000000000200000000040000000000000080000000000000000000000000000000000000000000000000000000000000000000000000 -322550 0x00000000000000000000000000000000000000000200000000000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -322749 0x00000000001000000000000000000000000000000000000000000000000000000000000800000008000000000000000000000000000400000000800000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000080000000006400000000000000000000000080000000000000000000000000000000000000000005000000000000000000000000000000008400000000080000000000000000000000000000000000000000008000000000000000000000000000000000000000800000000000000000000000000000000000002004000000000000 -322750 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000080000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000020000000000000040000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -322752 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000008000000000000000000080000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000080000020000000000000040000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000080000000000000000000000 -322758 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -322760 0x00000004004000000000000000000000000000000000020000000000000000000000100000000000000000000000000000000000000000000000000000000000010000000000000000008000000000000000000000000000000000040000000000002000000000000000000000000000000000000000000004000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -322764 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000001000000000000000000000000000000000000000000000000000000000000001000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000020000000000000000000000000000000 -322765 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000001000000000000000000000000000000000000000000000000000000000000001000000000000000002000000000200000000040000000000000000000000000000000000000000000000000000000020000000000000000000000000000000 -322767 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080000000000000000040000000000000000000000000000000000000000000002000000000000000000000000000000000000000000 -322768 0x00000000004000000000000000000000000000000000120000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000400000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002080004000000000000040000000000000000000000000000000000000000000002000000000000000000000000000000000000000000 -322774 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000000000000000008000000000000000000000000000000000000000000000000000000000000000000002001000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -322776 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000010000000000000000000000000040000000000000000000000000000000010000000008000000000000000000000000000000000009000000000000000008000000000000000000000000000000000000000000000000000000000000000000002001000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -322777 0x00000000004000000000008000100000000000000000020000000000000002000000000000000000000000000000000000000004000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000020000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000001000000000000000000000000000000000000000000000000 -324029 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -324316 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000004000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -324318 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000 -324322 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000400000000000000000000000000000000000000000000000000000008000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -325807 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -326760 0x00000000000000000000000000000000000000000000000000000040000000000000001000000000000000000000000000008000000000000000000000000000000000008000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000002000000000000008000000000000000 -327103 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -327105 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -327227 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000400000000000000000000000020000000000000000000000000000000000000000000040000000000000000 -327399 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -327544 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -327690 0x00000000000000000000000000000100000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -328002 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000200000000000 -328269 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -328529 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -328585 0x20000000000000000000100000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -328870 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -329480 0x00000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000200000000000000000000000020000000000000000000000000000000000000000000 -329484 0x00000000004000000000000008000000000000000000020000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000040000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000200000000000000000000000020000000000000000000000000000000000000000000 -329485 0x00000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -329491 0x00000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -329513 0x00000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -329519 0x00000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -329659 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000020000000000000000000000000000000000000000000000000000000000020000000010000000008000000000000000000000000000000000008000000400000000000000000000000000000000000000000000000000000000000000000000000000000002000000080000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000020000000 -329667 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000100000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000002000000000000000000000000000000000000000000 -329668 0x0000000000400000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000004000000000000010000000000000000000000000000000000000000000000000001000000000000000000001000000000c000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000002000000000000000000800000000000000000000000 -329673 0x00000000004000001000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000004000000000000000000000000000000000000000000000000004000000000000000000010000000008000000000000000000000000000002000008000000000000000000000000000000000000000000000000000000000000000000000400400000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -329740 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000010000000000000 -329749 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000008000000000000000000000000000000000000000002000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -329750 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000008000000000000000000000000000000000040000000040000000000000000000000010000000000000000000000000000000000000000000000000000010000000008000000000000000000000080000000000008000000000000000000000000000000000000000002000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000400000000000000000000000000000000000000000000 -329824 0x00000000000000000000000000000000000000000000200000000000000000000000001000000000000000000000000000008000000008000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -329964 0x00000000000000000000000000000000000000000000000000000000100000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -330023 0x00000000000000000000000000000000000000000000000000000000100000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -330207 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000004000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000200000000000000000000000008000000000000000 -330473 0x00000000000400000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000001000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -330511 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000002000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000400000000000000000000000020000000000000000000000000000000000000000000040000000000000000 -330579 0x00000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -330683 0x00000000000000000000000000000000000000000000080000000000004000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -330919 0x00020000000000000000000000000000000000000000000000000000000000000008001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -331009 0x00000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -331542 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000100000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000004000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -332007 0x00000000000000000000000000000000000000000000000000000200000080000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008200000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -333256 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000400000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000010000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -333294 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -333583 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000200000000000000000000000000000000000000000000000000010008000000000000000 -333640 0x80000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000004000000008000000000000000000000000000000000000010000000000000000000000000000000000008000000000000000 -334263 0x00000000000000080000000000000000000000000000000000000000000000000100001000000000000010000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -334279 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000040000020000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000 -334883 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -334915 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000004000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -334919 0x00000020000000000000000000000000000000000000000000000000000000000000001000000000000020000000000000008000000000000000000000000000000000000020000000000000020000812000002000000000000000000000000001000000000000000000000000000000400000000000000000000000000000000000000000000000040000800000000010000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000008000400000000008000000000000000 -335076 0x00000000000000001000000000000000000000000000000000000000000000000000001000000000000000000100000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -335348 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000080000000008000000000000000000000040000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000008000000000 -335643 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -335649 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -335652 0x00000000000008000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -335684 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000002000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000004000000000000000000000000000000000000000000000000000000000000008000000000000000 -336089 0x0000000000000000000000000000000000000000000000000000000000020000000000100000000000000000000000000000800000000000000000000000000000000000000000000000000000000080200000a000000000000000000000000001000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -336231 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336234 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336242 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336243 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336244 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336245 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336247 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336248 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336255 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336260 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336263 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336264 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336266 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336334 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336336 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336337 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336338 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336439 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336451 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336452 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336453 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336461 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336495 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336497 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336507 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336508 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336509 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336510 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336518 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336520 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336521 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336522 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336526 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336527 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336528 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -336543 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000080000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000040000000000000000000200000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000 -337012 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000001000000000000000000000000400000000000000802000002000000200000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -337642 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000408000000000000000000000000000000000040000080000000000000000080000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000020000000000000000002000000000000000000040000000000000001000000000000000000000000000000000000000000000000000000000000000000000000 -337647 0x00000000000000000000000000000000000000000000020000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000800000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -337649 0x00000000004000000000000000000000000000000000020000000000000080000000100000000000000000000000000000000000000000000000000000000000000000000000000000008002000000000000000000000000000000040000000000000000000000000000000800000000000000000000000000000000000000000000000002000010000000008000000000000000000000000000000000008000000000000000000000000000000000200000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -337653 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000040000000000000000000040000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -337654 0x00000000004000000000008000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000020000040000000000000000000040000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -337655 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000040000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000400000000040000000000000000000000000000000000000000000000000000000000000000000000 -337656 0x00000000004000000000000000000000000400000000020000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000008000040000000000000000000000000000040000000000000000000000000000000000000000000000000000004000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000400000000040000000000000000000000000000000000000000000000000000000000000000000000 -337663 0x00000000004000000000000000000000080000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000001000000000000000000000000000050000000000000000000000000040000000000000000000000000000000000000000004000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000080000000000000000000000000000000000000 -337664 0x00000000000000000000000000000000000000000000020000000010000000000000000000000000001000000000000000000000000000000000000000000000000200000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -337669 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000020000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000008000000000 -337672 0x40000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000020000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000020000000000000010000000008000000000000000000000000008000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000008000008000000000 -337731 0x00000000000000000000000020000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000800000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -338275 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010004000200000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -338281 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010004000200000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -338336 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -338424 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008004000000000000000000000000000000000000100000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -338435 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000008000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000004000000000000000000000000010000000000000000000000000000000000000 -338439 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000010802000002000000000000000000000000001000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000040000000000000000000000000000000000000000000000008000000000000000 -338661 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -338991 0x00000000000000000000000000200000000000000008000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000400800000000000000000000000000000010000000000000000000000000000000000000000000000000 -339173 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002400000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000088000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -339369 0x00000020000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -339427 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000020000000000000000000001000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -340633 0x00000000000000000000000000000000000000000000020000000004000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000008000000000000001000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -340635 0x00000000004000000000000000000000000000000000020000000004000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000008000000000000001000000000000200000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000001000000000200000000000000000000000000000000000000000000000000000000000000000000 -340653 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000001000000002000000000000000000040000000000000000000000000000000000000000000000000000000010000000000000000000000000000000 -340658 0x0000000000400000000000000000000400000000000002000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000001000000000800000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000100000000a000000000000000000040000000000000000000000000000000000000000000000000000000010000000000000000000000000000000 -340674 0x00000000000800000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000100000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040080000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -340675 0x00000000004800000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000100000000000000000000000000000000000000000000000000000000000000000000000000000002000010000000000000040080000000000000000000000000000000000002000000000000000000080000000000000000000000000000 -340685 0x00000000000000000000000000000000000000000000020010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000008000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -340686 0x00004000004000000000000000000000000000000000820010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000008000000000000040000000000000000000000000000000000000000000000000002000000000000000000000000000000000000 -340700 0x00000000004000000000000000000000000000000000020001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000080000000000000000000000000000000000008000000000000000000000000000000000000000000002004200000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000001000 -340708 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000008000000000000000000000000000040000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000080000000000000000000000000000000000000 -340710 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000008000000000000000000000000000040000000000000100000000000000000800000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000400000000000000000000000000000000000000000000000000002000002000000000000040000000000000000000000000000000000000000000000000080000000000000000000000000000000000000 -340712 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000008000000000200000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -340713 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000080840000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000028000000100000000000000000000000000008000000000200000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000001000000000000000000000 -340718 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000100000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000002000000000000 -340719 0x00000000004000000000000000000000000000000000020000000040000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000008000000000000080000002000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000100000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000002000000000000 -340727 0x00000000004000000000040000002000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000200000000000080000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000002000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000001000000000000000000000000000000 -340728 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000002000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000100000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -340835 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -340988 0x00000000000000000010000000000000000000000010000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000010000000000008000000000000000 -341695 0x00000000000000000000000010000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000001000000000000000000000000000000000000000000000000000000000008000000000000000 -341985 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000100000000000004000000000000001000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -341997 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104000000000004000000000000001000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -342001 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000100000000000004000000000000001000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -342004 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000100000000000004000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -342007 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000004000000000000001000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -342008 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000004000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -342026 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000002000000004000000000000000000000000000000000000000000000000000000001000000000000000000004000000020000080000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -342027 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -342033 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -342035 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -342036 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -342041 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 -342047 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000100000000000000000000000000000000002000000104000000000044100000000000001000002000000000000000000000001000000000000000000004000000000000080000000000000000000000000000000000000002000000000000000000000000020000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -342053 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -342080 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000400000002000000000000000000000000000000000000000000040000000000000000000001040000000000000000000000000000000080000000010000000000000000000000000000000000000000000000000000000020000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000440000000000000000 -342101 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 -342107 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -342111 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -342115 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 -342118 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000400000002000000004000000000000000000000000000000000000000000000000000000001000000000000000000004000000000000080000000010000000000000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -342125 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -342140 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000008000000000000000000080000000000000000800000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 -342141 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -342145 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000400000002000000000000000000000000000000000000000000040000000000000000000001040000000000000000000000000000000080000000010000000000000000000000000000000000000000000000000000000020000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000440000000000000000 -342162 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -342173 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -342188 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -342272 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000400000000000000000 -342386 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000008000000000000000000000000000000000000000000000000000004000000000000000000000000000008000000000000000000000000001000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000010000000004000000000000000000000000010000000000000000000400000000000000000 -342399 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000 -342466 0x00000000000000000000000000000000000000000000000000002000000000000000001000000000080000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -342601 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -342616 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000008000000000000000000080000000000000000800000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 -342618 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000008000000000000000000080000000000000000800000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 -342924 0x00000000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -342964 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -343006 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000080000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000 -343021 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000004000000000000000000000000000000000000000000000000080000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000 -343059 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000008000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -343079 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000200000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -343083 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000040000000000000802000002000000000000000000000000001000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -343133 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -343162 0x00000020000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000100000000000000000000000000008000400000000000000000000000000 -343185 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000008000400000000000000000000000000 -343339 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000080000000000000000802000002000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -343946 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -343966 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -343971 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -344121 0x00000000000000000000000000000000000000000000000000000040000000000000001000000000000000000000000000008000000000000000000000000000000000008000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000002000000000000008000000000000000 -344164 0x00000000000000000000000000000000000000000000000000000040000000000000001000000000000000000000000000008000000000000000000000000000000000008000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000002000000000000008000000000000000 -344839 0x00000000000000000000000000000000000000000000000000000000000000000200001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000008000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -345506 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -346112 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -346392 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -346395 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -346398 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -346425 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -346448 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -346451 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -346454 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -346464 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -346466 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -347014 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000400000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -347301 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000200000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000002000000000000000000000000000000000000000000000000000000000000000008000000000000000 -347333 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000200000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000002000000000000000000000000000000000000000000000000000000000000000008000000000000000 -347613 0x00000000000000000000000000000000000000000800000000000000000000000000000000000000000001000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010004000000002000000000000000000000000000000000000000000000000000000001000000040000000000000000000000800000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001000000000000000000000 -347700 0x00000000000000000000000000000000000000000000000000000000002000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400010000000000000 -347705 0x00000000000000000000000000000000000000000000000000000000002000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400010000000000000 -347711 0x00000000000000000000000000000000000000004000000000020000002000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040010000000000000 -347853 0x00000000000000000000000000000000000000000000000000000000002000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000 -347953 0x00000000000000000000000000000000000000000000000000000000002000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000080000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000 -347958 0x00000000000000000000000000000000000000004000000000020000002000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040010000000000000 -347960 0x00000000000000000000000000000000000000000000000000020000002000000001000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040010000000000000 -348019 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -348244 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000004000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -348443 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000400000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -348675 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000080000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000400100000000000000000000000000000000000000000000000008000000000000000 -348743 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -348936 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000100000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000002000000000000000000000000000000000000000008000000000000000 -350544 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -351473 0x00000000000000000000000000000000000000000000000000000000002000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000 -353157 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -353181 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000004000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000400000000000000000 -353196 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000004000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000080000000000000000000000000000000000000040000000000000000 -353273 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000080000000000000000800000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000 -353276 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000080000000000000000000000000000000000000040000000000000000 -353359 0x00000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000200000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000100000040 -353360 0x00000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000040 -353361 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008002400000000000000000000000000 -353367 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000080000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000008000000000000000 -353370 0x02000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -353438 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000080000000000000000000000000000000000000000000000000002000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000040 -353443 0x0000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000a000400000000000000000000000000 -353447 0x00000028000000000000000000000080000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -353479 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000002000001000000000000000000000000100000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -354071 0x02000000000000000000000000000000000000000000020000000000000000000000000040000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000020000000000000000000000200000000000000020000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000 -354151 0x00000000000000000000000000000000000000000000002000000000000000000000400000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004040000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000080000000400000000000000000000000000000000000000000000000000000000000000000000000000000 -354162 0x00000000000000000000000000004000000000000000000000000000000000000000410000000000200000000000000002000000000002000000000040000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000 -354233 0x00000000000000000000000000000000000000000000000000000000000000000000400040000004000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024040000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000400000000000000000000000040000000000000000000000000000000000100000000000000000 -354585 0x00000000000000000000000000000000000000000000000000100000000000000000400000000000200000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000 -354866 0x00000000000000000000000000000000000000000000000000001000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000001 -356461 0x00000000000000000000000000200000000000000000000000000000010000000000000000000000000000000000000000202000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -356488 0x00000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000200000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000020000000000000080000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000 -356513 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000100001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000080000000000000a00000000000000000000000 -356526 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -356535 0x00000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000 -356543 0x00000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000800080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000 -357195 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -357579 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -357588 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -357590 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000200000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -357592 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -357600 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -357622 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -357630 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -358290 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000400000002000000004000000000000000000000000000000000000000000000000000000001000000000000000000004000000000000080000000010000000000000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -358426 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 -358556 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -358811 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000400000000000000000000000000000000002000000000008000000000000000 -359114 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -359375 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000100000000000000000 -359378 0x00000020000000000010000000000000000004000000000000000200400000000000000000000000000000000002000000000000000000020000000000000000000000000000000000000000000000010000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000040000000000040010000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000400000000000 -359538 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -361585 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -361588 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -361732 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000842000002000000000000000000000000001000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000080000000000000000000000000000000000000000000000000000008000000000000000 -361757 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -361775 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000008000000000000000000080000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -362002 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000010000000000000000000000000802000002000000000000000000000400001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -365791 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000040 -365793 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000010000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000400010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -369141 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000200000000000000000000000000000000000000000000000000000000000000000008000000000010000 -369239 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -369249 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -369253 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -369259 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -369261 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -369263 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -369274 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -369426 0x00000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000200000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000100000040 -369428 0x20000020000000000000000000800000000004000000000000000200400000000000000040000000000000000000000000000000000000020000000000000000000000000000000000000000000000010000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000040000000000000010000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000008000400800000000000000000000000 -369431 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000400000000000100000000000040 -369538 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000040 -369540 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000008000400000000000000000000000000 -370399 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000001000000000000802000002000000000000000000000000001000000100000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -370517 0x00000000000000000000000000000080200000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000080004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -370545 0x00000000000000000000000000000080200000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000080004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371190 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371280 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371286 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371288 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371299 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371307 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371327 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371329 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371352 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371360 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371362 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371369 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371378 0x00000000000000000000000000000080200000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000080004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371450 0x00000000000000000000000000000080200000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000080004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371489 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371509 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371532 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371658 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371660 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371876 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371904 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371906 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371912 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371914 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371918 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371931 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371933 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371938 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -371940 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -371973 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -372006 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -372014 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -372847 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -374209 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -374225 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -374365 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000010000000000000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -374388 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020001000000000000000000000200000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -375079 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -375093 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -375401 0x00000000000000000000000000000000000400000400000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -375440 0x00000000000000000000000000000000000400000400000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -375447 0x00000000000000000000000000000000000400000400000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -376493 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -376573 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -376588 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -376644 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -376650 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -376668 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -376906 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -377026 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -377139 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000001000000000000080000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000080000000000000000000000000000000000000040000000000000000 -377506 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -377523 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -377525 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -377581 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000040 -377586 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000040000000000000000000000100000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -377608 0x00000000000000000000000000000000000000000200000000000000000000000000800000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -377627 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000004000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000080000000000000000000000000000000000000040000000000000000 -377629 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000004000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000080000000000000000000000000000000000000040000000000000000 -377703 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000001000000000000080000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000080000000000000000000000000000000000000040000000000000000 -377730 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -377746 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000004000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000400000000000000000 -377877 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000400000002000000004000000000000000000000000000000000000000000000000000000001000000000000000000004000000000000080000000010000000000000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -377894 0x00000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -377905 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000400000002000000004000000000000000000000000000000000000000000000000000000001000000000000000000004000000000000080000000010000000000000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -377917 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -377922 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000040000000000000000 -377925 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -378345 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -378347 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -379027 0x00000020000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -379032 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -379039 0x08000020000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -379158 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000400000000000000000002000040000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -379161 0x00000400004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000040000000000000000000000000000000000000000000010000000008000000000000000000000000000000020008000000000000000000000000000000000000000000000000000000000000000000400000000000000000002000040000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -379163 0x00000000000000000000000000000000000000000000020000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000008000010000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000080000000000000000000000000000000000000000 -379164 0x00000000004000000000000000000000000000100000020000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000008000010000000000000000000000000000040000000000001000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000100000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000080000000000000000000000000000000000000000 -379167 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000004 -379170 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -379171 0x00000000004000000000000000800000000000000000020000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000008000000000000000000000000000002000140000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000200000000000000000000004 -379172 0x00000000000000000010000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000200000000000000000000000000000000000000000000000000000000000000000000000 -379176 0x00000000004000000010000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000100000000000000000000000000000000000000000200000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000040000000000000000000000000000000002000000000000000000040000000000000000200000000000000000000000000000000000001000000000000000000000000000000000 -379180 0x00000000000080000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000800000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -379182 0x00000000004080000000000002000000000000000800020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000800000000000000000000050000000008000000000000000000000000800000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -379210 0x00000000000000040000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000004000000000000000000000400000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -379212 0x00000000004000040000000000000000000000000000020000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000200000000000008000000000000000000000000000000000000000004000000000000000000000400000000000000000000002000000000000000000040002000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -379214 0x00000001000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -379216 0x00000001004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000008000000000000008000000000000000000000000000000000040000000000000000000000000000000000020000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000020002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -379217 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000800000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000020000000000000000000000000000000000000000000000000000000000000000 -379219 0x00000000004000000000000000000000000000000000020000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000008000000000000000000000000010000000000000000010000000008800000000000000000000000000000000008000020000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000020000000000000000000000000000000000000000000000000000000000000000 -379220 0x00000000000000000000000000200000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000100000000000100002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -379224 0x00000000004000000000000000200000000000000000020000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000008000000000000000040000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000008000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000100000000000100002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000400000000000000 -379235 0x00000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000080000000000000000000000000000000000000000800000000000000000000000000000 -379237 0x00000000004000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000100000000008000000000000000000000000000000000000010000000008008000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000080000000000000040000000000000000080000000000000000000000000000000000000000800000000000000000000000000000 -381271 0x00000000000000000000000000000080000080004000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000000004000000000000000000000000002000000000000000000400000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -381276 0x00000000000000000000000000000080000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -381689 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -382200 0x00000020000000000000000008000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -382217 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000400000010000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -382644 0x00000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000200000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000002000000000000000000000000000000000000000000000000000000000000000008000000000000000 -383284 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -383337 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -383354 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -383361 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -383427 0x00000000000000000000000000000000000004000800000000000000000000000000000000000000000001000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000800000001000000000008000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000040000000000000000000 -383466 0x00000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -383469 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000001000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -383515 0x00000000000000000000000000000000000004000800000000000000000000000000000000000000000001000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000800000001000000000008000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000040000000000000000000 -383519 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000800000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000002000000000000000000000000000 -383630 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000400000000000000000 -383760 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000010000000000000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -383802 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000080000000000400000000000000000 -383815 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000000001000000000000000000004000000000000000000000010000000000000000000000040000000000000000000000000000000020000000100000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -383844 0x00000000000000000000000000000000100000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -383852 0x00000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000002000000000000000000000000000400000000000000004000000000000000080000000000000000000000000000000000000001000000000000000000004000000000000000000000010000000000000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -383859 0x00000000000000000000000000000000000000804000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000002000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -383864 0x00000000000000000000000000000000000000800000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000080000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -383968 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000001000000000000080000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000080000000000000000000000000000000000000040000000000000000 -383973 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 -384127 0x00000000000000000000000000000000000004000800000000000000000000000000000000000000000001000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000800000001000000000008000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000040000000000000000000 -384138 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -384149 0x00000000000000000000000000000000100000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -384173 0x00000000000000000000000000000000100000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000400000000000000000000080000000000000000000000000000000000008000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000001000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000800000000000000000000000000000400000000000000000 -384301 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000040000000000000000000000000000000000000000400000000000000000 -384422 0x00000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000400000000000000000 -384506 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -384511 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000400000000000000000 -384546 0x00000000000000000000000000000000000004000800000000000000000000000000000000000000000001000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000800000001000000000008000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000040000000000000000000 -384771 0x00001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000800000 -384825 0x00001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000 -384861 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -384917 0x00000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000400000000000000000 -384923 0x00002000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000001000000 -384965 0x00000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -385067 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000008000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000400000000000000000 -385073 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000008000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000400000000000000000 -385356 0x00002000000000000000000000000000000000010000000000000000000000000000000400000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000004000000000000000000000000000000004000000000000000000000000000000000000000000000000000000001000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000001000000 -386571 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -386620 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000 -386736 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000040000000000000000000000000000010000000020000000000000000000000000000000000000000000000000000000000000000010 -386786 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000280000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000040000000000000000000000000000010000000040000000000000000000000000000000000000000000000000000000000000000010 -386795 0x04000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000040000000000000000000000000000000000040000000000000000000000000000010000000000000000000000000000000000000000000000000000008000000000000000000010 -386804 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000040000000000400000000000000000000000040000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000010 -386812 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000040000000000000000008000000000010000000000000000000000000000000000000000000000000000000000000000000000000010 -386818 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000800000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000040000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000010 -386899 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000080000000000000000000000000000040000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000010 -386939 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000002000000000000000000000000000000000000000200000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000010000000020000000000000000000000000000000000000000000000000000000000000000000 -386945 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000020000000000000000000800000000000000000000000000000000000000000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000 -386975 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000100000000000000000020000000000000000000000000000000000000000000000000000000000000000000 -387011 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000010000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000 -387014 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000001000000000000000000000040000000000000000000000000000000000000000000000040000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000 -387016 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000400000000800000000 -387032 0x04000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000 -387044 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000020000000000000000000000000000000000000000000080000000000000000000000 -387045 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000400000000800000000 -387206 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -387225 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -387241 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -387276 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000008000000000000000004000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000021000000000000000000004000000000000000000000400000000000000000000000000000000080000000000000000000000000000000000000040000000000001000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -387284 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000040000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -387365 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000 -387615 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000800008000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -387627 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000800000000000000000400000000000000000 -387641 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800008000000000000000000000001000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -387648 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000800008000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -387654 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800008000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -387658 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000800008000000000000000000000001000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -387683 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000800008000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -387688 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000800008000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -387690 0x00000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000800008000000000000000000000001000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -387761 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000 -388108 0x00000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -388111 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000800000000 -388150 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000800000000 -388246 0x00000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000001000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000 -388285 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -388296 0x00000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000001000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000 -388516 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -388860 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000020000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000 -388893 0x00000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000008000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000008000000000000000020000000000000000000010000000000001000000000000000000000000000000000000000000000000000000000000000400000000000000000 -388894 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000020000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000 -388907 0x00000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000104000000000004000000000000001000000000000000000000000000001000000000000000000004080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000004000000000000000400000000000000000 -388909 0x00000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000400000000000000000 -388912 0x00000000000000000000000000000000000000004000000000020000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000004000000000000000040000000000000000 -388918 0x00000000000000000000000000000000000000000000000000020000002000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000040000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000004000000000000000040000000000000000 -388923 0x00000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000008000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000001000000000000000000000080000000000000000000000000000000000000000000000000000000000008000000000000000020000000000000000000000000000000001000000000000000000000000000000000000000000000004000000000000000400000000000000000 -388940 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000020000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000 -388971 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000004000000000000000000000000000000000000000800000000000000000000000000000000000 -388990 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000 -389012 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000 -389158 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000 -389206 0x00000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000400000000000000000 -389238 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -389277 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000100000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000400000000000000000 -389292 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000800000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -389301 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000020000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -389309 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000020000000000000000000000000000000000000000000000000000000008000000000000000000080000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -389324 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000008000000000000000000000000004000000000000000000000000004000000000000000000000000000000000000000000000000000000001000000000000800000024000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000 -389328 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -389343 0x00000000000000000000000000000000000000004000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000020000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000040000000000000000 -390001 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000001000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -390004 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000200000000000000000000000000000000000000020000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -390024 0x00000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -390042 0x00000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -390236 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -390306 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000001000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -390867 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -391685 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000800000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000002000000000000000000000000000 -391690 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000800000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000002000000000000000000000000000 -391691 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000800000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000002000000000000000000000000000 -391697 0x00000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000040000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000 -391713 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000 -391849 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000100000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000400000000000000000 -392002 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000 -392097 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000020000000000000000000000000000000000000000000000000000000008000000000000000000080000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -392104 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000010000000000000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -392110 0x00000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000 -392294 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000004000000000000000000000000000000000000000000000000000000000 -392697 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000010000000000000000000000000000400000000000000000 -392960 0x00000000000000200000400000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -392970 0x00000000000000200000400000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -392990 0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -393302 0x00000010000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000400000000000000000 -393370 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -393752 0x00000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000 -394354 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000800000024000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -394389 0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -394390 0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -394391 0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -394393 0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -394394 0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -394395 0x00000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000002000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000002000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -394426 0x00000000000000200000400000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000200000000000000000000000000000000000000000000000000000000000000000000000008000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -394800 0x00000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000100000010000000000000000000000000000000000000000000000000000000000020000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000000000 -395595 0x00000000000000000000000000000000000000000000000000000000000100000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000800000000000000000000000000000000000000000000000000000000000000000008000000000000000 -395969 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -396348 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000010000000000000000000000000000400000000000000000 -397108 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000 -397588 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000 -397591 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000 -398412 0x00000000000000000000000000000000000000000000000000000000001000000000001000000000000000000000000000008000000000000000000000000000000000000000000000000000000000802000002000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000008000000000000000000000000000000000000000000000000080000000000000000000800008000000000000000 -398456 0x00000020000000080000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000 -398477 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -398679 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040100000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -398968 0x00000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020200000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000 -398972 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000400000000000000000 -399058 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000200000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000 -399804 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000010000000000000000000000000000400000000000000000 -399849 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/util/bloomchain/tests/groupchain.rs b/util/bloomchain/tests/groupchain.rs deleted file mode 100644 index ec396346ac3..00000000000 --- a/util/bloomchain/tests/groupchain.rs +++ /dev/null @@ -1,172 +0,0 @@ -extern crate bloomchain; -extern crate rustc_hex; - -mod util; - -use bloomchain::{Bloom, Config}; -use bloomchain::group::BloomGroupChain; -use util::{BloomGroupMemoryDatabase, FromHex, for_each_bloom, generate_n_random_blooms}; - -#[test] -fn simple_bloom_group_search() { - let config = Config::default(); - let mut db = BloomGroupMemoryDatabase::default(); - let bloom = Bloom::from_hex("00000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000008000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - - let modified_blooms = { - let chain = BloomGroupChain::new(config, &db); - let block_number = 23; - chain.insert(block_number, bloom.clone()) - }; - - // number of modified blooms should always be equal number of levels - assert_eq!(modified_blooms.len(), config.levels); - db.insert_blooms(modified_blooms); - - - let chain = BloomGroupChain::new(config, &db); - assert_eq!(chain.with_bloom(&(0..100), &bloom), vec![23]); - assert_eq!(chain.with_bloom(&(0..22), &bloom), vec![]); - assert_eq!(chain.with_bloom(&(23..23), &bloom), vec![23]); - assert_eq!(chain.with_bloom(&(24..100), &bloom), vec![]); -} - -#[test] -fn partly_matching_bloom_group_searach() { - let config = Config::default(); - let mut db = BloomGroupMemoryDatabase::default(); - let bloom0 = Bloom::from_hex("10100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom1 = Bloom::from_hex("11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom2 = Bloom::from_hex("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - - let modified_blooms_0 = { - let chain = BloomGroupChain::new(config, &db); - let block_number = 14; - chain.insert(block_number, bloom0) - }; - - db.insert_blooms(modified_blooms_0); - - let modified_blooms_1 = { - let chain = BloomGroupChain::new(config, &db); - let block_number = 15; - chain.insert(block_number, bloom1) - }; - - db.insert_blooms(modified_blooms_1); - - - let chain = BloomGroupChain::new(config, &db); - assert_eq!(chain.with_bloom(&(0..100), &bloom2), vec![14, 15]); -} - -#[test] -fn bloom_group_replace() { - let config = Config::default(); - let mut db = BloomGroupMemoryDatabase::default(); - let bloom0 = Bloom::from_hex("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom1 = Bloom::from_hex("01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom2 = Bloom::from_hex("00100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom3 = Bloom::from_hex("00010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom4 = Bloom::from_hex("00001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - let bloom5 = Bloom::from_hex("00000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - - let modified_blooms_0 = { - let chain = BloomGroupChain::new(config, &db); - let block_number = 14; - chain.insert(block_number, bloom0.clone()) - }; - - db.insert_blooms(modified_blooms_0); - - let modified_blooms_1 = { - let chain = BloomGroupChain::new(config, &db); - let block_number = 15; - chain.insert(block_number, bloom1.clone()) - }; - - db.insert_blooms(modified_blooms_1); - - let modified_blooms_2 = { - let chain = BloomGroupChain::new(config, &db); - let block_number = 16; - chain.insert(block_number, bloom2.clone()) - }; - - db.insert_blooms(modified_blooms_2); - - let modified_blooms_3 = { - let chain = BloomGroupChain::new(config, &db); - let block_number = 17; - chain.insert(block_number, bloom3.clone()) - }; - - db.insert_blooms(modified_blooms_3); - - - let reset_modified_blooms = { - let chain = BloomGroupChain::new(config, &db); - chain.replace(&(15..17), vec![bloom4.clone(), bloom5.clone()]) - }; - - db.insert_blooms(reset_modified_blooms); - - let chain = BloomGroupChain::new(config, &db); - assert_eq!(chain.with_bloom(&(0..100), &bloom0), vec![14]); - assert_eq!(chain.with_bloom(&(0..100), &bloom1), vec![]); - assert_eq!(chain.with_bloom(&(0..100), &bloom2), vec![]); - assert_eq!(chain.with_bloom(&(0..100), &bloom3), vec![]); - assert_eq!(chain.with_bloom(&(0..100), &bloom4), vec![15]); - assert_eq!(chain.with_bloom(&(0..100), &bloom5), vec![16]); -} - -#[test] -fn file_test_bloom_group_search() { - let config = Config::default(); - let mut db = BloomGroupMemoryDatabase::default(); - let blooms_file = include_bytes!("data/blooms.txt"); - - for_each_bloom(blooms_file, | block_number, bloom | { - let modified_blooms = { - let chain = BloomGroupChain::new(config, &db); - chain.insert(block_number, bloom) - }; - - // number of modified blooms should always be equal number of levels - assert_eq!(modified_blooms.len(), config.levels); - db.insert_blooms(modified_blooms); - }); - - for_each_bloom(blooms_file, | block_number, bloom | { - let chain = BloomGroupChain::new(config, &db); - let blocks = chain.with_bloom(&(block_number..block_number), &bloom); - assert_eq!(blocks.len(), 1); - assert_eq!(blocks[0], block_number); - }); -} - -#[test] -fn random_bloom_group_replacement() { - let insertions = 10_000; - - let config = Config::default(); - let mut db = BloomGroupMemoryDatabase::default(); - let blooms = generate_n_random_blooms(insertions); - - for (i, bloom) in blooms.iter().enumerate() { - - let modified_blooms = { - let chain = BloomGroupChain::new(config, &db); - chain.replace(&(i..i), vec![bloom.clone()]) - }; - - db.insert_blooms(modified_blooms); - } - - for (i, bloom) in blooms.iter().enumerate() { - let chain = BloomGroupChain::new(config, &db); - let blocks = chain.with_bloom(&(i..i), bloom); - assert_eq!(blocks.len(), 1); - assert_eq!(blocks[0], i); - } -} diff --git a/util/bloomchain/tests/util/db.rs b/util/bloomchain/tests/util/db.rs deleted file mode 100644 index 8101b37848d..00000000000 --- a/util/bloomchain/tests/util/db.rs +++ /dev/null @@ -1,39 +0,0 @@ -use std::collections::HashMap; -use bloomchain::{Position, Bloom, BloomDatabase}; -use bloomchain::group::{GroupPosition, BloomGroup, BloomGroupDatabase}; - -#[derive(Default)] -pub struct BloomMemoryDatabase { - mem: HashMap, -} - -impl BloomMemoryDatabase { - #[allow(dead_code)] - pub fn insert_blooms(&mut self, blooms: HashMap) { - self.mem.extend(blooms); - } -} - -impl BloomDatabase for BloomMemoryDatabase { - fn bloom_at(&self, position: &Position) -> Option { - self.mem.get(position).cloned() - } -} - -#[derive(Default)] -pub struct BloomGroupMemoryDatabase { - mem: HashMap, -} - -impl BloomGroupMemoryDatabase { - #[allow(dead_code)] - pub fn insert_blooms(&mut self, groups: HashMap) { - self.mem.extend(groups); - } -} - -impl BloomGroupDatabase for BloomGroupMemoryDatabase { - fn blooms_at(&self, position: &GroupPosition) -> Option { - self.mem.get(position).cloned() - } -} diff --git a/util/bloomchain/tests/util/each.rs b/util/bloomchain/tests/util/each.rs deleted file mode 100644 index 19ca1b67cf5..00000000000 --- a/util/bloomchain/tests/util/each.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::io::{BufReader, Read, BufRead}; -use bloomchain::Bloom; -use super::FromHex; - -pub fn for_each_bloom(bytes: &[u8], mut f: F) where F: FnMut(usize, Bloom) { - let mut reader = BufReader::new(bytes); - let mut line = String::new(); - while reader.read_line(&mut line).unwrap() > 0 { - { - let mut number_bytes = vec![]; - let mut bloom_bytes = [0; 512]; - - let mut line_reader = BufReader::new(line.as_ref() as &[u8]); - line_reader.read_until(b' ', &mut number_bytes).unwrap(); - line_reader.consume(2); - line_reader.read_exact(&mut bloom_bytes).unwrap(); - - let number = String::from_utf8(number_bytes).map(|s| s[..s.len() -1].to_owned()).unwrap().parse::().unwrap(); - let bloom = Bloom::from_hex(&String::from_utf8(bloom_bytes.to_vec()).unwrap()); - f(number, bloom); - } - line.clear(); - } -} diff --git a/util/bloomchain/tests/util/from_hex.rs b/util/bloomchain/tests/util/from_hex.rs deleted file mode 100644 index 9152d304fdf..00000000000 --- a/util/bloomchain/tests/util/from_hex.rs +++ /dev/null @@ -1,16 +0,0 @@ -use rustc_hex::FromHex as RustcFromHex; -use bloomchain::Bloom; - -pub trait FromHex { - fn from_hex(s: &str) -> Self where Self: Sized; -} - -impl FromHex for Bloom { - fn from_hex(s: &str) -> Self { - let mut res = [0u8; 256]; - let v = s.from_hex().unwrap(); - assert_eq!(res.len(), v.len()); - res.copy_from_slice(&v); - From::from(res) - } -} diff --git a/util/bloomchain/tests/util/mod.rs b/util/bloomchain/tests/util/mod.rs deleted file mode 100644 index 2a1e55af9a0..00000000000 --- a/util/bloomchain/tests/util/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod db; -mod each; -mod from_hex; -mod random; - -pub use self::db::{BloomMemoryDatabase, BloomGroupMemoryDatabase}; -pub use self::each::for_each_bloom; -pub use self::from_hex::FromHex; -pub use self::random::{generate_random_bloom, generate_n_random_blooms}; diff --git a/util/bloomchain/tests/util/random.rs b/util/bloomchain/tests/util/random.rs deleted file mode 100644 index 3d50b5ac10a..00000000000 --- a/util/bloomchain/tests/util/random.rs +++ /dev/null @@ -1,24 +0,0 @@ -extern crate rand; - -use self::rand::random; -use bloomchain::Bloom; - -pub fn generate_random_bloom() -> Bloom { - let mut res = [0u8; 256]; - let p0 = random::(); - let b0 = random::() % 8; - let p1 = random::(); - let b1 = random::() % 8; - let p2 = random::(); - let b2 = random::() % 8; - - res[p0 as usize] |= 1 << b0; - res[p1 as usize] |= 1 << b1; - res[p2 as usize] |= 1 << b2; - - From::from(res) -} - -pub fn generate_n_random_blooms(n: usize) -> Vec { - (0..n).map(|_| generate_random_bloom()).collect() -} From 94dfcd476e1bced69df1c53d5d20ed80aaaa1c31 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 25 May 2018 19:19:22 +0800 Subject: [PATCH 04/29] cleanup in progress --- ethcore/src/blockchain/blockchain.rs | 1 - ethcore/src/snapshot/consensus/mod.rs | 1 - ethcore/src/snapshot/service.rs | 1 - ethcore/src/snapshot/tests/proof_of_authority.rs | 1 - ethcore/src/snapshot/tests/proof_of_work.rs | 2 -- ethcore/src/snapshot/tests/service.rs | 4 ++-- ethcore/src/test_helpers.rs | 4 ++-- ethcore/src/tests/client.rs | 6 ------ ethcore/src/tests/trace.rs | 2 -- ethcore/src/trace/db.rs | 12 +----------- 10 files changed, 5 insertions(+), 29 deletions(-) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 43b35f9f0ac..a50b5e5c046 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -1460,7 +1460,6 @@ mod tests { use rustc_hex::FromHex; use hash::keccak; use kvdb::{KeyValueDB, DBTransaction}; - use kvdb_memorydb; use ethereum_types::*; use receipt::{Receipt, TransactionOutcome}; use blockchain::{BlockProvider, BlockChain, BlockChainDB, Config, ImportRoute}; diff --git a/ethcore/src/snapshot/consensus/mod.rs b/ethcore/src/snapshot/consensus/mod.rs index e1ee2cec925..488f070fb2c 100644 --- a/ethcore/src/snapshot/consensus/mod.rs +++ b/ethcore/src/snapshot/consensus/mod.rs @@ -25,7 +25,6 @@ use engines::EthEngine; use snapshot::{Error, ManifestData}; use ethereum_types::H256; -use kvdb::KeyValueDB; mod authority; mod work; diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index 4a2b8013fc2..69680c5f96e 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -40,7 +40,6 @@ use parking_lot::{Mutex, RwLock, RwLockReadGuard}; use util_error::UtilError; use bytes::Bytes; use journaldb::Algorithm; -use kvdb::{KeyValueDB, KeyValueDBHandler}; use snappy; /// Helper for removing directories in case of error. diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/ethcore/src/snapshot/tests/proof_of_authority.rs index 28dc1045b27..bc0e9a23873 100644 --- a/ethcore/src/snapshot/tests/proof_of_authority.rs +++ b/ethcore/src/snapshot/tests/proof_of_authority.rs @@ -30,7 +30,6 @@ use transaction::{Transaction, Action, SignedTransaction}; use tempdir::TempDir; use ethereum_types::Address; -use kvdb_memorydb; use test_helpers; use_contract!(test_validator_set, "ValidatorSet", "res/contracts/test_validator_set.json"); diff --git a/ethcore/src/snapshot/tests/proof_of_work.rs b/ethcore/src/snapshot/tests/proof_of_work.rs index 3fb764dfe19..9deb2182707 100644 --- a/ethcore/src/snapshot/tests/proof_of_work.rs +++ b/ethcore/src/snapshot/tests/proof_of_work.rs @@ -16,7 +16,6 @@ //! PoW block chunker and rebuilder tests. -use std::sync::Arc; use std::sync::atomic::AtomicBool; use tempdir::TempDir; use error::{Error, ErrorKind}; @@ -29,7 +28,6 @@ use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter}; use parking_lot::Mutex; use snappy; use kvdb::{KeyValueDB, DBTransaction}; -use kvdb_memorydb; use test_helpers; const SNAPSHOT_MODE: ::snapshot::PowSnapshot = ::snapshot::PowSnapshot { blocks: 30000, max_restore_blocks: 30000 }; diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 43367e0961d..75572c3fabe 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -24,11 +24,11 @@ use ids::BlockId; use snapshot::service::{Service, ServiceParams}; use snapshot::{self, ManifestData, SnapshotService}; use spec::Spec; -use test_helpers::{self, generate_dummy_client_with_spec_and_data}; +use test_helpers::{generate_dummy_client_with_spec_and_data}; use test_helpers_internal::restoration_db_handler; use io::IoChannel; -use kvdb_rocksdb::{Database, DatabaseConfig}; +use kvdb_rocksdb::{DatabaseConfig}; struct NoopDBRestore; diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index 32b7f9100cb..163ba34fe47 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -260,7 +260,7 @@ pub fn get_test_client_with_blocks(blocks: Vec) -> Arc { pub fn new_db() -> Arc { struct TestBlockChainDB { - blooms_dir: TempDir, + _blooms_dir: TempDir, blooms: RwLock, key_value: Arc, } @@ -279,7 +279,7 @@ pub fn new_db() -> Arc { let db = TestBlockChainDB { blooms: RwLock::new(blooms_db::Database::open(tempdir.path()).unwrap()), - blooms_dir: tempdir, + _blooms_dir: tempdir, key_value: Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap())) }; diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 184000f5687..b6b91ee7d32 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -29,7 +29,6 @@ use test_helpers::{ }; use types::filter::Filter; use ethereum_types::{U256, Address}; -use kvdb_rocksdb::{Database, DatabaseConfig}; use miner::Miner; use spec::Spec; use views::BlockView; @@ -43,10 +42,7 @@ use test_helpers; #[test] fn imports_from_empty() { let db = test_helpers::new_db(); - //let tempdir = TempDir::new("").unwrap(); let spec = Spec::new_test(); - //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), @@ -64,8 +60,6 @@ fn should_return_registrar() { let db = test_helpers::new_db(); let tempdir = TempDir::new("").unwrap(); let spec = ethereum::new_morden(&tempdir.path().to_owned()); - //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index cb2a9a6606a..c8abb3ccb65 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -16,7 +16,6 @@ //! Client tests of tracing -use tempdir::TempDir; use ethkey::KeyPair; use hash::keccak; use block::*; @@ -26,7 +25,6 @@ use spec::*; use client::*; use test_helpers::get_temp_state_db; use client::{BlockChainClient, Client, ClientConfig}; -use kvdb_rocksdb::{Database, DatabaseConfig}; use std::sync::Arc; use header::Header; use miner::Miner; diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index ab97bc532e9..5d67728c473 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -15,13 +15,12 @@ // along with Parity. If not, see . //! Trace database. -use std::ops::Deref; use std::collections::{HashMap, VecDeque}; use std::sync::Arc; use blockchain::{BlockChainDB}; use heapsize::HeapSizeOf; use ethereum_types::{H256, H264}; -use kvdb::{KeyValueDB, DBTransaction}; +use kvdb::{DBTransaction}; use parking_lot::RwLock; use header::BlockNumber; use trace::{LocalizedTrace, Config, Filter, Database as TraceDatabase, ImportRequest, DatabaseExtras}; @@ -83,7 +82,6 @@ impl TraceDB where T: DatabaseExtras { TraceDB { traces: RwLock::new(HashMap::new()), - //blooms: RwLock::new(HashMap::new()), cache_manager: RwLock::new(CacheManager::new(config.pref_cache_size, config.max_cache_size, 10 * 1024)), tracesdb: tracesdb, enabled: config.enabled, @@ -93,8 +91,6 @@ impl TraceDB where T: DatabaseExtras { fn cache_size(&self) -> usize { self.traces.read().heap_size_of_children() - //let blooms = self.blooms.read().heap_size_of_children(); - //traces + blooms } /// Let the cache system know that a cacheable item has been used. @@ -108,18 +104,15 @@ impl TraceDB where T: DatabaseExtras { let current_size = self.cache_size(); let mut traces = self.traces.write(); - //let mut blooms = self.blooms.write(); let mut cache_manager = self.cache_manager.write(); cache_manager.collect_garbage(current_size, | ids | { for id in &ids { match *id { CacheId::Trace(ref h) => { traces.remove(h); }, - //CacheId::Bloom(ref h) => { blooms.remove(h); }, } } traces.shrink_to_fit(); - //blooms.shrink_to_fit(); traces.heap_size_of_children() }); @@ -211,8 +204,6 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { // now let's rebuild the blooms if !request.enacted.is_empty() { let range_start = request.block_number + 1 - request.enacted.len() as u64; - //let range_end = range_start + request.retracted; - //let replaced_range = range_start..range_end; let enacted_blooms: Vec<_> = request.enacted .iter() // all traces are expected to be found here. That's why `expect` has been used @@ -346,7 +337,6 @@ mod tests { use std::sync::Arc; use ethereum_types::{H256, U256, Address}; use kvdb::{DBTransaction, KeyValueDB}; - use kvdb_memorydb; use header::BlockNumber; use trace::{Config, TraceDB, Database as TraceDatabase, DatabaseExtras, ImportRequest}; use trace::{Filter, LocalizedTrace, AddressesFilter, TraceError}; From 0da3c9bcafb215b548b5efb056a95342b1017e5e Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 26 May 2018 11:01:07 +0800 Subject: [PATCH 05/29] all tests passing in trace db with new blooms-db --- ethcore/src/blockchain/blockchain.rs | 2 +- ethcore/src/snapshot/tests/helpers.rs | 2 +- ethcore/src/snapshot/tests/proof_of_work.rs | 2 +- ethcore/src/test_helpers_internal.rs | 2 +- ethcore/src/trace/db.rs | 38 +++++++++++++-------- ethcore/src/trace/types/filter.rs | 2 +- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index a50b5e5c046..787bf3c1afb 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -1459,7 +1459,7 @@ mod tests { use std::sync::Arc; use rustc_hex::FromHex; use hash::keccak; - use kvdb::{KeyValueDB, DBTransaction}; + use kvdb::{DBTransaction}; use ethereum_types::*; use receipt::{Receipt, TransactionOutcome}; use blockchain::{BlockProvider, BlockChain, BlockChainDB, Config, ImportRoute}; diff --git a/ethcore/src/snapshot/tests/helpers.rs b/ethcore/src/snapshot/tests/helpers.rs index 369fe826ccb..d0370bcb6b9 100644 --- a/ethcore/src/snapshot/tests/helpers.rs +++ b/ethcore/src/snapshot/tests/helpers.rs @@ -33,7 +33,7 @@ use snapshot::io::{SnapshotReader, PackedWriter, PackedReader}; use tempdir::TempDir; use rand::Rng; -use kvdb::{KeyValueDB, DBValue}; +use kvdb::{DBValue}; use ethereum_types::H256; use hashdb::HashDB; use journaldb; diff --git a/ethcore/src/snapshot/tests/proof_of_work.rs b/ethcore/src/snapshot/tests/proof_of_work.rs index 9deb2182707..769f7060969 100644 --- a/ethcore/src/snapshot/tests/proof_of_work.rs +++ b/ethcore/src/snapshot/tests/proof_of_work.rs @@ -27,7 +27,7 @@ use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter}; use parking_lot::Mutex; use snappy; -use kvdb::{KeyValueDB, DBTransaction}; +use kvdb::{DBTransaction}; use test_helpers; const SNAPSHOT_MODE: ::snapshot::PowSnapshot = ::snapshot::PowSnapshot { blocks: 30000, max_restore_blocks: 30000 }; diff --git a/ethcore/src/test_helpers_internal.rs b/ethcore/src/test_helpers_internal.rs index 54cb5509ada..5ee6c83ae5a 100644 --- a/ethcore/src/test_helpers_internal.rs +++ b/ethcore/src/test_helpers_internal.rs @@ -19,7 +19,7 @@ use std::path::Path; use std::sync::Arc; use parking_lot::RwLock; -use kvdb::{KeyValueDB, KeyValueDBHandler}; +use kvdb::{KeyValueDB}; use kvdb_rocksdb::{Database, DatabaseConfig}; use blockchain::{BlockChainDBHandler, BlockChainDB}; use blooms_db; diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 5d67728c473..9bb0b06d717 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . //! Trace database. -use std::collections::{HashMap, VecDeque}; +use std::collections::{HashMap, BTreeSet, VecDeque}; use std::sync::Arc; use blockchain::{BlockChainDB}; use heapsize::HeapSizeOf; @@ -315,19 +315,25 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { } fn filter(&self, filter: &Filter) -> Vec { - unimplemented!(); - //let chain = BloomGroupChain::new(self.bloom_config, self); - //let numbers = chain.filter(filter); - //numbers.into_iter() - //.flat_map(|n| { - //let number = n as BlockNumber; - //let hash = self.extras.block_hash(number) - //.expect("Expected to find block hash. Extras db is probably corrupted"); - //let traces = self.traces(&hash) - //.expect("Expected to find a trace. Db is probably corrupted."); - //self.matching_block_traces(filter, traces, hash, number) - //}) - //.collect() + let possibilities = filter.bloom_possibilities(); + let blooms_db = self.tracesdb.blooms().read(); + let numbers = possibilities.iter() + .map(|bloom| blooms_db.iterate_matching(filter.range.start as u64, filter.range.end as u64, bloom)?.collect::, _>>()) + .collect::, _>>().expect("TODO: blooms pr") + .into_iter() + .flat_map(|n| n) + .collect::>(); + + numbers.into_iter() + .flat_map(|n| { + let number = n as BlockNumber; + let hash = self.extras.block_hash(number) + .expect("Expected to find block hash. Extras db is probably corrupted"); + let traces = self.traces(&hash) + .expect("Expected to find a trace. Db is probably corrupted."); + self.matching_block_traces(filter, traces, hash, number) + }) + .collect() } } @@ -336,7 +342,7 @@ mod tests { use std::collections::HashMap; use std::sync::Arc; use ethereum_types::{H256, U256, Address}; - use kvdb::{DBTransaction, KeyValueDB}; + use kvdb::{DBTransaction}; use header::BlockNumber; use trace::{Config, TraceDB, Database as TraceDatabase, DatabaseExtras, ImportRequest}; use trace::{Filter, LocalizedTrace, AddressesFilter, TraceError}; @@ -532,6 +538,7 @@ mod tests { let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); db.key_value().write(batch).unwrap(); + db.blooms().write().flush().unwrap(); let filter = Filter { range: (1..1), @@ -548,6 +555,7 @@ mod tests { let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); db.key_value().write(batch).unwrap(); + db.blooms().write().flush().unwrap(); let filter = Filter { range: (1..2), diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index f1b26e2a683..57d0da5cf05 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -89,7 +89,7 @@ pub struct Filter { impl Filter { /// Returns combinations of each address. - fn bloom_possibilities(&self) -> Vec { + pub fn bloom_possibilities(&self) -> Vec { self.to_address.with_blooms(self.from_address.blooms()) } From 0fb7b9514a48d80ce1ed77ae0c5d244ba6cad0ab Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 26 May 2018 11:38:00 +0800 Subject: [PATCH 06/29] added trace_blooms to BlockChainDB interface, fixed db flushing --- ethcore/src/blockchain/blockchain.rs | 7 +++++++ ethcore/src/client/client.rs | 5 ++++- ethcore/src/test_helpers.rs | 15 ++++++++++++--- ethcore/src/test_helpers_internal.rs | 14 +++++++++++++- ethcore/src/trace/db.rs | 26 +++++++++++++------------- 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 787bf3c1afb..0cfcb74b17e 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -52,11 +52,18 @@ use std::path::Path; /// Database backing `BlockChain`. pub trait BlockChainDB: Send + Sync { + /// Generic key value store. fn key_value(&self) -> &Arc; + /// Header blooms database. fn blooms(&self) -> &RwLock; + + /// Trace blooms database. + fn trace_blooms(&self) -> &RwLock; } +/// Generic database handler. This trait contains one function `open`. When called, it opens database with a +/// predefined config. pub trait BlockChainDBHandler: Send + Sync { /// Open the predefined key-value database. fn open(&self, path: &Path) -> Result, Error>; diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 8631345351f..417c6d9e9d8 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -337,7 +337,10 @@ impl Importer { } } - client.db.read().key_value().flush().expect("DB flush failed."); + let db = client.db.read(); + db.key_value().flush().expect("DB flush failed."); + db.blooms().write().flush().expect("DB flush failed."); + db.trace_blooms().write().flush().expect("DB flush failed."); imported } diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index 163ba34fe47..2429e5da082 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -261,7 +261,9 @@ pub fn get_test_client_with_blocks(blocks: Vec) -> Arc { pub fn new_db() -> Arc { struct TestBlockChainDB { _blooms_dir: TempDir, + _trace_blooms_dir: TempDir, blooms: RwLock, + trace_blooms: RwLock, key_value: Arc, } @@ -273,13 +275,20 @@ pub fn new_db() -> Arc { fn blooms(&self) -> &RwLock { &self.blooms } + + fn trace_blooms(&self) -> &RwLock { + &self.trace_blooms + } } - let tempdir = TempDir::new("").unwrap(); + let blooms_dir = TempDir::new("").unwrap(); + let trace_blooms_dir = TempDir::new("").unwrap(); let db = TestBlockChainDB { - blooms: RwLock::new(blooms_db::Database::open(tempdir.path()).unwrap()), - _blooms_dir: tempdir, + blooms: RwLock::new(blooms_db::Database::open(blooms_dir.path()).unwrap()), + trace_blooms: RwLock::new(blooms_db::Database::open(trace_blooms_dir.path()).unwrap()), + _blooms_dir: blooms_dir, + _trace_blooms_dir: trace_blooms_dir, key_value: Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap())) }; diff --git a/ethcore/src/test_helpers_internal.rs b/ethcore/src/test_helpers_internal.rs index 5ee6c83ae5a..e1ea85e4371 100644 --- a/ethcore/src/test_helpers_internal.rs +++ b/ethcore/src/test_helpers_internal.rs @@ -16,6 +16,7 @@ //! Internal helpers for client tests +use std::fs; use std::path::Path; use std::sync::Arc; use parking_lot::RwLock; @@ -33,6 +34,7 @@ pub fn restoration_db_handler(config: DatabaseConfig) -> Box, + trace_blooms: RwLock, key_value: Arc, } @@ -44,14 +46,24 @@ pub fn restoration_db_handler(config: DatabaseConfig) -> Box &RwLock { &self.blooms } + + fn trace_blooms(&self) -> &RwLock { + &self.trace_blooms + } } impl BlockChainDBHandler for RestorationDBHandler { fn open(&self, db_path: &Path) -> Result, Error> { let key_value = Arc::new(Database::open(&self.config, &db_path.to_string_lossy())?); - let blooms = RwLock::new(blooms_db::Database::open(db_path).unwrap()); + let blooms_path = db_path.join("blooms"); + let trace_blooms_path = db_path.join("trace_blooms"); + fs::create_dir(&blooms_path)?; + fs::create_dir(&trace_blooms_path)?; + let blooms = RwLock::new(blooms_db::Database::open(blooms_path).unwrap()); + let trace_blooms = RwLock::new(blooms_db::Database::open(trace_blooms_path).unwrap()); let db = RestorationDB { blooms, + trace_blooms, key_value, }; Ok(Arc::new(db)) diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 9bb0b06d717..9867572d591 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -59,31 +59,31 @@ enum CacheId { /// touched, which have been created during the execution of transaction, and /// which calls failed. pub struct TraceDB where T: DatabaseExtras { - // cache + /// cache traces: RwLock>, cache_manager: RwLock>, - // db - tracesdb: Arc, - // tracing enabled + /// db + db: Arc, + /// tracing enabled enabled: bool, - // extras + /// extras extras: Arc, } impl TraceDB where T: DatabaseExtras { /// Creates new instance of `TraceDB`. - pub fn new(config: Config, tracesdb: Arc, extras: Arc) -> Self { + pub fn new(config: Config, db: Arc, extras: Arc) -> Self { let mut batch = DBTransaction::new(); let genesis = extras.block_hash(0) .expect("Genesis block is always inserted upon extras db creation qed"); batch.write(db::COL_TRACE, &genesis, &FlatBlockTraces::default()); batch.put(db::COL_TRACE, b"version", TRACE_DB_VER); - tracesdb.key_value().write(batch).expect("failed to update version"); + db.key_value().write(batch).expect("failed to update version"); TraceDB { traces: RwLock::new(HashMap::new()), cache_manager: RwLock::new(CacheManager::new(config.pref_cache_size, config.max_cache_size, 10 * 1024)), - tracesdb: tracesdb, + db, enabled: config.enabled, extras: extras, } @@ -120,7 +120,7 @@ impl TraceDB where T: DatabaseExtras { /// Returns traces for block with hash. fn traces(&self, block_hash: &H256) -> Option { - let result = self.tracesdb.key_value().read_with_cache(db::COL_TRACE, &self.traces, block_hash); + let result = self.db.key_value().read_with_cache(db::COL_TRACE, &self.traces, block_hash); self.note_used(CacheId::Trace(block_hash.clone())); result } @@ -217,7 +217,7 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { .collect(); // TODO: replace it with database for trace blooms - self.tracesdb.blooms().write().insert_blooms(range_start, enacted_blooms.iter()).expect("TODO: blooms pr"); + self.db.trace_blooms().write().insert_blooms(range_start, enacted_blooms.iter()).expect("TODO: blooms pr"); } // insert new block traces into the cache and the database @@ -316,7 +316,7 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { fn filter(&self, filter: &Filter) -> Vec { let possibilities = filter.bloom_possibilities(); - let blooms_db = self.tracesdb.blooms().read(); + let blooms_db = self.db.trace_blooms().read(); let numbers = possibilities.iter() .map(|bloom| blooms_db.iterate_matching(filter.range.start as u64, filter.range.end as u64, bloom)?.collect::, _>>()) .collect::, _>>().expect("TODO: blooms pr") @@ -538,7 +538,7 @@ mod tests { let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); db.key_value().write(batch).unwrap(); - db.blooms().write().flush().unwrap(); + db.trace_blooms().write().flush().unwrap(); let filter = Filter { range: (1..1), @@ -555,7 +555,7 @@ mod tests { let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); db.key_value().write(batch).unwrap(); - db.blooms().write().flush().unwrap(); + db.trace_blooms().write().flush().unwrap(); let filter = Filter { range: (1..2), From 24a6ba2f5847fb848e4209d0122de3319d45200d Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 31 May 2018 14:08:06 +0200 Subject: [PATCH 07/29] BlockChainDB no longer exposes RwLock in the interface --- Cargo.lock | 1 + ethcore/light/src/client/service.rs | 1 - ethcore/service/src/service.rs | 1 - ethcore/src/blockchain/blockchain.rs | 14 +++++------ ethcore/src/client/client.rs | 4 ++-- ethcore/src/test_helpers.rs | 12 +++++----- ethcore/src/test_helpers_internal.rs | 13 +++++----- ethcore/src/trace/db.rs | 11 ++++----- parity/db/rocksdb/mod.rs | 21 ++++++++-------- util/blooms-db/Cargo.toml | 1 + util/blooms-db/benches/blooms.rs | 4 ++-- util/blooms-db/src/db.rs | 23 ++++++++++++++---- util/blooms-db/src/lib.rs | 36 +++++++++++++++++++++++++++- 13 files changed, 93 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4276d0347fd..cedadf8ce13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,6 +156,7 @@ version = "0.1.0" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ethcore/light/src/client/service.rs b/ethcore/light/src/client/service.rs index 8394314d385..fb1cc36cf84 100644 --- a/ethcore/light/src/client/service.rs +++ b/ethcore/light/src/client/service.rs @@ -25,7 +25,6 @@ use ethcore::{db, BlockChainDB}; use ethcore::error::Error as CoreError; use ethcore::spec::Spec; use io::{IoContext, IoError, IoHandler, IoService}; -use kvdb::KeyValueDB; use cache::Cache; use parking_lot::Mutex; diff --git a/ethcore/service/src/service.rs b/ethcore/service/src/service.rs index 5ff2ff2f393..571e8ff3bd8 100644 --- a/ethcore/service/src/service.rs +++ b/ethcore/service/src/service.rs @@ -22,7 +22,6 @@ use std::time::Duration; use ansi_term::Colour; use io::{IoContext, TimerToken, IoHandler, IoService, IoError}; -use kvdb::{KeyValueDB, KeyValueDBHandler}; use stop_guard::StopGuard; use sync::PrivateTxHandler; diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 0cfcb74b17e..b970a9dca41 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -56,10 +56,10 @@ pub trait BlockChainDB: Send + Sync { fn key_value(&self) -> &Arc; /// Header blooms database. - fn blooms(&self) -> &RwLock; + fn blooms(&self) -> &blooms_db::Database; /// Trace blooms database. - fn trace_blooms(&self) -> &RwLock; + fn trace_blooms(&self) -> &blooms_db::Database; } /// Generic database handler. This trait contains one function `open`. When called, it opens database with a @@ -335,10 +335,8 @@ impl BlockProvider for BlockChain { /// Returns numbers of blocks containing given bloom. fn blocks_with_bloom(&self, bloom: &Bloom, from_block: BlockNumber, to_block: BlockNumber) -> Vec { - self.db.blooms().read() - .iterate_matching(from_block, to_block, bloom) - .expect("TODO: blooms pr") - .collect::, _>>() + self.db.blooms() + .filter(from_block, to_block, bloom) .expect("TODO: blooms pr") } @@ -1063,7 +1061,7 @@ impl BlockChain { } if let Some((block, blooms)) = update.blocks_blooms { - self.db.blooms().write().insert_blooms(block, blooms.iter()).expect("TODO: blooms pr"); + self.db.blooms().insert_blooms(block, blooms.iter()).expect("TODO: blooms pr"); } // These cached values must be updated last with all four locks taken to avoid @@ -1092,7 +1090,7 @@ impl BlockChain { /// Apply pending insertion updates pub fn commit(&self) { - self.db.blooms().write().flush().expect("TODO: blooms pr"); + self.db.blooms().flush().expect("TODO: blooms pr"); let mut pending_best_block = self.pending_best_block.write(); let mut pending_write_hashes = self.pending_block_hashes.write(); let mut pending_block_details = self.pending_block_details.write(); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 417c6d9e9d8..5fc29d8a322 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -339,8 +339,8 @@ impl Importer { let db = client.db.read(); db.key_value().flush().expect("DB flush failed."); - db.blooms().write().flush().expect("DB flush failed."); - db.trace_blooms().write().flush().expect("DB flush failed."); + db.blooms().flush().expect("DB flush failed."); + db.trace_blooms().flush().expect("DB flush failed."); imported } diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index 2429e5da082..e4777c61c0c 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -262,8 +262,8 @@ pub fn new_db() -> Arc { struct TestBlockChainDB { _blooms_dir: TempDir, _trace_blooms_dir: TempDir, - blooms: RwLock, - trace_blooms: RwLock, + blooms: blooms_db::Database, + trace_blooms: blooms_db::Database, key_value: Arc, } @@ -272,11 +272,11 @@ pub fn new_db() -> Arc { &self.key_value } - fn blooms(&self) -> &RwLock { + fn blooms(&self) -> &blooms_db::Database { &self.blooms } - fn trace_blooms(&self) -> &RwLock { + fn trace_blooms(&self) -> &blooms_db::Database { &self.trace_blooms } } @@ -285,8 +285,8 @@ pub fn new_db() -> Arc { let trace_blooms_dir = TempDir::new("").unwrap(); let db = TestBlockChainDB { - blooms: RwLock::new(blooms_db::Database::open(blooms_dir.path()).unwrap()), - trace_blooms: RwLock::new(blooms_db::Database::open(trace_blooms_dir.path()).unwrap()), + blooms: blooms_db::Database::open(blooms_dir.path()).unwrap(), + trace_blooms: blooms_db::Database::open(trace_blooms_dir.path()).unwrap(), _blooms_dir: blooms_dir, _trace_blooms_dir: trace_blooms_dir, key_value: Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap())) diff --git a/ethcore/src/test_helpers_internal.rs b/ethcore/src/test_helpers_internal.rs index e1ea85e4371..d8fd93d97e4 100644 --- a/ethcore/src/test_helpers_internal.rs +++ b/ethcore/src/test_helpers_internal.rs @@ -19,7 +19,6 @@ use std::fs; use std::path::Path; use std::sync::Arc; -use parking_lot::RwLock; use kvdb::{KeyValueDB}; use kvdb_rocksdb::{Database, DatabaseConfig}; use blockchain::{BlockChainDBHandler, BlockChainDB}; @@ -33,8 +32,8 @@ pub fn restoration_db_handler(config: DatabaseConfig) -> Box, - trace_blooms: RwLock, + blooms: blooms_db::Database, + trace_blooms: blooms_db::Database, key_value: Arc, } @@ -43,11 +42,11 @@ pub fn restoration_db_handler(config: DatabaseConfig) -> Box &RwLock { + fn blooms(&self) -> &blooms_db::Database { &self.blooms } - fn trace_blooms(&self) -> &RwLock { + fn trace_blooms(&self) -> &blooms_db::Database { &self.trace_blooms } } @@ -59,8 +58,8 @@ pub fn restoration_db_handler(config: DatabaseConfig) -> Box TraceDatabase for TraceDB where T: DatabaseExtras { .collect(); // TODO: replace it with database for trace blooms - self.db.trace_blooms().write().insert_blooms(range_start, enacted_blooms.iter()).expect("TODO: blooms pr"); + self.db.trace_blooms().insert_blooms(range_start, enacted_blooms.iter()).expect("TODO: blooms pr"); } // insert new block traces into the cache and the database @@ -316,10 +316,9 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { fn filter(&self, filter: &Filter) -> Vec { let possibilities = filter.bloom_possibilities(); - let blooms_db = self.db.trace_blooms().read(); + let blooms_db = self.db.trace_blooms(); let numbers = possibilities.iter() - .map(|bloom| blooms_db.iterate_matching(filter.range.start as u64, filter.range.end as u64, bloom)?.collect::, _>>()) - .collect::, _>>().expect("TODO: blooms pr") + .map(|bloom| blooms_db.filter(filter.range.start as u64, filter.range.end as u64, bloom).expect("TODO: blooms pr")) .into_iter() .flat_map(|n| n) .collect::>(); @@ -538,7 +537,7 @@ mod tests { let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); db.key_value().write(batch).unwrap(); - db.trace_blooms().write().flush().unwrap(); + db.trace_blooms().flush().unwrap(); let filter = Filter { range: (1..1), @@ -555,7 +554,7 @@ mod tests { let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); db.key_value().write(batch).unwrap(); - db.trace_blooms().write().flush().unwrap(); + db.trace_blooms().flush().unwrap(); let filter = Filter { range: (1..2), diff --git a/parity/db/rocksdb/mod.rs b/parity/db/rocksdb/mod.rs index 414b0a13957..7dafdaeb051 100644 --- a/parity/db/rocksdb/mod.rs +++ b/parity/db/rocksdb/mod.rs @@ -20,7 +20,6 @@ extern crate migration_rocksdb; use std::fs; use std::sync::Arc; use std::path::Path; -use parking_lot::RwLock; use blooms_db; use ethcore::{BlockChainDBHandler, BlockChainDB}; use ethcore::error::Error; @@ -38,8 +37,8 @@ pub use self::migration::migrate; struct AppDB { key_value: Arc, - blooms: RwLock, - trace_blooms: RwLock, + blooms: blooms_db::Database, + trace_blooms: blooms_db::Database, } impl BlockChainDB for AppDB { @@ -47,11 +46,11 @@ impl BlockChainDB for AppDB { &self.key_value } - fn blooms(&self) -> &RwLock { + fn blooms(&self) -> &blooms_db::Database { &self.blooms } - fn trace_blooms(&self) -> &RwLock { + fn trace_blooms(&self) -> &blooms_db::Database { &self.trace_blooms } } @@ -82,8 +81,8 @@ pub fn open_client_db(client_path: &Path, client_config: &ClientConfig) -> Resul let db = AppDB { key_value: client_db, - blooms: RwLock::new(blooms_db::Database::open(blooms_path).map_err(|e| e.to_string())?), - trace_blooms: RwLock::new(blooms_db::Database::open(trace_blooms_path).map_err(|e| e.to_string())?), + blooms: blooms_db::Database::open(blooms_path).map_err(|e| e.to_string())?, + trace_blooms: blooms_db::Database::open(trace_blooms_path).map_err(|e| e.to_string())?, }; Ok(Arc::new(db)) @@ -106,8 +105,8 @@ pub fn restoration_db_handler(client_path: &Path, client_config: &ClientConfig) let db = AppDB { key_value: Arc::new(Database::open(&self.config, &db_path.to_string_lossy())?), - blooms: RwLock::new(blooms_db::Database::open(blooms_path)?), - trace_blooms: RwLock::new(blooms_db::Database::open(trace_blooms_path)?), + blooms: blooms_db::Database::open(blooms_path)?, + trace_blooms: blooms_db::Database::open(trace_blooms_path)?, }; Ok(Arc::new(db)) @@ -142,8 +141,8 @@ pub fn open_db(client_path: &str, cache_config: &CacheConfig, compaction: &Datab let db = AppDB { key_value, - blooms: RwLock::new(blooms_db::Database::open(blooms_path).map_err(|e| e.to_string())?), - trace_blooms: RwLock::new(blooms_db::Database::open(trace_blooms_path).map_err(|e| e.to_string())?), + blooms: blooms_db::Database::open(blooms_path).map_err(|e| e.to_string())?, + trace_blooms: blooms_db::Database::open(trace_blooms_path).map_err(|e| e.to_string())?, }; Ok(Arc::new(db)) diff --git a/util/blooms-db/Cargo.toml b/util/blooms-db/Cargo.toml index aba7ebc36ce..2abf03cba0e 100644 --- a/util/blooms-db/Cargo.toml +++ b/util/blooms-db/Cargo.toml @@ -6,6 +6,7 @@ authors = ["debris "] [dependencies] byteorder = "1.2" ethbloom = "0.5" +parking_lot = "0.5.4" tiny-keccak = "1.4" [dev-dependencies] diff --git a/util/blooms-db/benches/blooms.rs b/util/blooms-db/benches/blooms.rs index 516175c5bd7..c1070533999 100644 --- a/util/blooms-db/benches/blooms.rs +++ b/util/blooms-db/benches/blooms.rs @@ -14,7 +14,7 @@ use ethbloom::Bloom; #[bench] fn blooms_filter_1_million(b: &mut Bencher) { let tempdir = TempDir::new("").unwrap(); - let mut database = Database::open(tempdir.path()).unwrap(); + let database = Database::open(tempdir.path()).unwrap(); database.insert_blooms(999_999, iter::once(&Bloom::from(0))).unwrap(); let bloom = Bloom::from(0x001); database.insert_blooms(200_000, iter::once(&bloom)).unwrap(); @@ -24,7 +24,7 @@ fn blooms_filter_1_million(b: &mut Bencher) { database.flush().unwrap(); b.iter(|| { - let matches = database.iterate_matching(0, 999_999, &bloom).unwrap().collect::, _>>().unwrap(); + let matches = database.filter(0, 999_999, &bloom).unwrap(); assert_eq!(matches, vec![200_000, 400_000, 600_000, 800_000]); }); } diff --git a/util/blooms-db/src/db.rs b/util/blooms-db/src/db.rs index 59df4412e78..6e3216b35c5 100644 --- a/util/blooms-db/src/db.rs +++ b/util/blooms-db/src/db.rs @@ -1,4 +1,4 @@ -use std::io; +use std::{io, fmt}; use std::path::{Path, PathBuf}; use ethbloom; @@ -75,7 +75,7 @@ impl Database { } /// Insert consecutive blooms into database starting with positon from. - pub fn insert_blooms<'a, B>(&'a mut self, from: u64, blooms: impl Iterator) -> io::Result<()> + pub fn insert_blooms<'a, B>(&mut self, from: u64, blooms: impl Iterator) -> io::Result<()> where ethbloom::BloomRef<'a>: From { for (index, bloom) in (from..).into_iter().zip(blooms) { self.pending.append(index, bloom)?; @@ -105,8 +105,8 @@ impl Database { } /// Returns an iterator yielding all indexes containing given bloom. - pub fn iterate_matching<'a, B>(&'a self, from: u64, to: u64, bloom: B) -> io::Result> - where ethbloom::BloomRef<'a>: From { + pub fn iterate_matching<'a, 'b, B>(&'a self, from: u64, to: u64, bloom: B) -> io::Result> + where ethbloom::BloomRef<'b>: From, 'b: 'a { let index = from / 256 * 256; let pos = Positions::from_index(index); @@ -146,6 +146,21 @@ pub struct DatabaseIterator<'a> { bloom: ethbloom::BloomRef<'a>, } +impl<'a> fmt::Debug for DatabaseIterator<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("DatabaseIterator") + .field("state", &self.state) + .field("from", &self.from) + .field("to", &self.to) + .field("index", &self.index) + .field("bloom", &"...") + .field("top", &"...") + .field("mid", &"...") + .field("bot", &"...") + .finish() + } +} + /// Database iterator state. #[derive(Debug)] enum IteratorState { diff --git a/util/blooms-db/src/lib.rs b/util/blooms-db/src/lib.rs index 5fdb6ee6863..1167239f31e 100644 --- a/util/blooms-db/src/lib.rs +++ b/util/blooms-db/src/lib.rs @@ -5,6 +5,7 @@ extern crate byteorder; extern crate ethbloom; +extern crate parking_lot; extern crate tiny_keccak; #[cfg(test)] @@ -17,4 +18,37 @@ mod pending; pub const VERSION: u64 = 1; -pub use db::{Database, DatabaseIterator}; +use std::io; +use std::path::Path; +use parking_lot::RwLock; + +pub struct Database { + database: RwLock, +} + +impl Database { + pub fn open

(path: P) -> io::Result where P: AsRef { + let result = Database { + database: RwLock::new(db::Database::open(path)?), + }; + + Ok(result) + } + + pub fn insert_blooms<'a, B>(&self, from: u64, blooms: impl Iterator) -> io::Result<()> + where ethbloom::BloomRef<'a>: From { + self.database.write().insert_blooms(from, blooms) + } + + pub fn flush(&self) -> io::Result<()> { + self.database.write().flush() + } + + pub fn filter<'a, B>(&'a self, from: u64, to: u64, bloom: B) -> io::Result> + where ethbloom::BloomRef<'a>: From { + let database = self.database.read(); + database + .iterate_matching(from, to, bloom)? + .collect::, _>>() + } +} From 7fa05cd3f1b0ac0991dd5a4786ade0072473f557 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 1 Jun 2018 11:23:06 +0200 Subject: [PATCH 08/29] automatically flush blooms-db after every insert --- ethcore/src/blockchain/blockchain.rs | 1 - ethcore/src/client/client.rs | 2 - ethcore/src/trace/db.rs | 2 - util/blooms-db/benches/blooms.rs | 1 - util/blooms-db/src/db.rs | 61 ++--------- util/blooms-db/src/lib.rs | 12 +- util/blooms-db/src/meta.rs | 41 ------- util/blooms-db/src/pending.rs | 158 --------------------------- 8 files changed, 10 insertions(+), 268 deletions(-) delete mode 100644 util/blooms-db/src/meta.rs delete mode 100644 util/blooms-db/src/pending.rs diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index b970a9dca41..e23493bfd82 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -1090,7 +1090,6 @@ impl BlockChain { /// Apply pending insertion updates pub fn commit(&self) { - self.db.blooms().flush().expect("TODO: blooms pr"); let mut pending_best_block = self.pending_best_block.write(); let mut pending_write_hashes = self.pending_block_hashes.write(); let mut pending_block_details = self.pending_block_details.write(); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index a022518ba4c..3492796f6c3 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -339,8 +339,6 @@ impl Importer { let db = client.db.read(); db.key_value().flush().expect("DB flush failed."); - db.blooms().flush().expect("DB flush failed."); - db.trace_blooms().flush().expect("DB flush failed."); imported } diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 39190f014ca..7e89db90b02 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -537,7 +537,6 @@ mod tests { let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); db.key_value().write(batch).unwrap(); - db.trace_blooms().flush().unwrap(); let filter = Filter { range: (1..1), @@ -554,7 +553,6 @@ mod tests { let mut batch = DBTransaction::new(); tracedb.import(&mut batch, request); db.key_value().write(batch).unwrap(); - db.trace_blooms().flush().unwrap(); let filter = Filter { range: (1..2), diff --git a/util/blooms-db/benches/blooms.rs b/util/blooms-db/benches/blooms.rs index c1070533999..8e92c4c3850 100644 --- a/util/blooms-db/benches/blooms.rs +++ b/util/blooms-db/benches/blooms.rs @@ -21,7 +21,6 @@ fn blooms_filter_1_million(b: &mut Bencher) { database.insert_blooms(400_000, iter::once(&bloom)).unwrap(); database.insert_blooms(600_000, iter::once(&bloom)).unwrap(); database.insert_blooms(800_000, iter::once(&bloom)).unwrap(); - database.flush().unwrap(); b.iter(|| { let matches = database.filter(0, 999_999, &bloom).unwrap(); diff --git a/util/blooms-db/src/db.rs b/util/blooms-db/src/db.rs index 6e3216b35c5..3311ec97fbe 100644 --- a/util/blooms-db/src/db.rs +++ b/util/blooms-db/src/db.rs @@ -1,12 +1,9 @@ use std::{io, fmt}; -use std::path::{Path, PathBuf}; +use std::path::Path; use ethbloom; -use VERSION; use file::{File, FileIterator}; -use meta::{Meta, read_meta, save_meta}; -use pending::Pending; /// Bloom positions in database files. #[derive(Debug)] @@ -40,12 +37,6 @@ pub struct Database { /// /// Every bloom is an ethereum header bloom bot: File, - /// Pending changes - /// - /// Inserted blooms are always appended to this file - pending: Pending, - /// Datbase directory - path: PathBuf, } impl Database { @@ -56,52 +47,27 @@ impl Database { top: File::open(path.join("top.bdb"))?, mid: File::open(path.join("mid.bdb"))?, bot: File::open(path.join("bot.bdb"))?, - pending: Pending::open(path.join("pending.bdb"))?, - path: path.to_path_buf(), }; - match read_meta(path.join("meta.bdb")) { - Ok(meta) => { - let pending_hash = database.pending.hash()?; - if pending_hash != meta.pending_hash { - return Err(io::Error::new(io::ErrorKind::InvalidData, "Malformed pending file")); - } - }, - Err(ref err) if err.kind() == io::ErrorKind::NotFound => {}, - Err(err) => return Err(err), - } - Ok(database) } /// Insert consecutive blooms into database starting with positon from. - pub fn insert_blooms<'a, B>(&mut self, from: u64, blooms: impl Iterator) -> io::Result<()> - where ethbloom::BloomRef<'a>: From { - for (index, bloom) in (from..).into_iter().zip(blooms) { - self.pending.append(index, bloom)?; - } - self.pending.flush()?; - self.flush_meta() - } - - /// Flush pending blooms. - pub fn flush(&mut self) -> io::Result<()> { - for tuple in self.pending.iterator()? { - let (index, bloom) = tuple?; + pub fn insert_blooms<'a, I, B>(&mut self, from: u64, blooms: I) -> io::Result<()> + where ethbloom::BloomRef<'a>: From, I: Iterator { + for (index, bloom) in (from..).into_iter().zip(blooms.map(Into::into)) { let pos = Positions::from_index(index); // constant forks make lead to increased ration of false positives in bloom filters // since we do not rebuild top or mid level, but we should not be worried about that // most of the time events at block n(a) occur also on block n(b) or n+1(b) - self.top.accrue_bloom(pos.top, &bloom)?; - self.mid.accrue_bloom(pos.mid, &bloom)?; - self.bot.replace_bloom(pos.bot, &bloom)?; + self.top.accrue_bloom::(pos.top, bloom)?; + self.mid.accrue_bloom::(pos.mid, bloom)?; + self.bot.replace_bloom::(pos.bot, bloom)?; } self.top.flush()?; self.mid.flush()?; - self.bot.flush()?; - self.pending.clear()?; - self.flush_meta() + self.bot.flush() } /// Returns an iterator yielding all indexes containing given bloom. @@ -123,15 +89,6 @@ impl Database { Ok(iter) } - - fn flush_meta(&self) -> io::Result<()> { - let meta = Meta { - version: VERSION, - pending_hash: self.pending.hash()? - }; - - save_meta(self.path.join("meta.bdb"), &meta) - } } /// Blooms database iterator @@ -242,7 +199,6 @@ mod tests { let tempdir = TempDir::new("").unwrap(); let mut database = Database::open(tempdir.path()).unwrap(); database.insert_blooms(0, vec![Bloom::from(0), Bloom::from(0x01), Bloom::from(0x10), Bloom::from(0x11)].iter()).unwrap(); - database.flush().unwrap(); let matches = database.iterate_matching(0, 3, &Bloom::from(0)).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![0, 1, 2, 3]); @@ -271,7 +227,6 @@ mod tests { let tempdir = TempDir::new("").unwrap(); let mut database = Database::open(tempdir.path()).unwrap(); database.insert_blooms(254, vec![Bloom::from(0x100), Bloom::from(0x01), Bloom::from(0x10), Bloom::from(0x11)].iter()).unwrap(); - database.flush().unwrap(); let matches = database.iterate_matching(0, 257, &Bloom::from(0x01)).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![255, 257]); diff --git a/util/blooms-db/src/lib.rs b/util/blooms-db/src/lib.rs index 1167239f31e..ad139125615 100644 --- a/util/blooms-db/src/lib.rs +++ b/util/blooms-db/src/lib.rs @@ -13,10 +13,6 @@ extern crate tempdir; mod db; mod file; -mod meta; -mod pending; - -pub const VERSION: u64 = 1; use std::io; use std::path::Path; @@ -35,15 +31,11 @@ impl Database { Ok(result) } - pub fn insert_blooms<'a, B>(&self, from: u64, blooms: impl Iterator) -> io::Result<()> - where ethbloom::BloomRef<'a>: From { + pub fn insert_blooms<'a, I, B>(&self, from: u64, blooms: I) -> io::Result<()> + where ethbloom::BloomRef<'a>: From, I: Iterator { self.database.write().insert_blooms(from, blooms) } - pub fn flush(&self) -> io::Result<()> { - self.database.write().flush() - } - pub fn filter<'a, B>(&'a self, from: u64, to: u64, bloom: B) -> io::Result> where ethbloom::BloomRef<'a>: From { let database = self.database.read(); diff --git a/util/blooms-db/src/meta.rs b/util/blooms-db/src/meta.rs deleted file mode 100644 index e24600f8066..00000000000 --- a/util/blooms-db/src/meta.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::io::{Write, Read}; -use std::path::Path; -use std::{fs, io}; - -use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian}; - -#[derive(Debug)] -pub struct Meta { - /// Database version. - pub version: u64, - /// Pending file hash. - pub pending_hash: [u8; 32], -} - -pub fn read_meta

(path: P) -> io::Result where P: AsRef { - let mut file = fs::OpenOptions::new() - .read(true) - .open(path)?; - - let version = file.read_u64::()?; - let mut pending_hash = [0u8; 32]; - file.read_exact(&mut pending_hash)?; - - let meta = Meta { - version, - pending_hash, - }; - - Ok(meta) -} - -pub fn save_meta

(path: P, meta: &Meta) -> io::Result<()> where P: AsRef { - let mut file = fs::OpenOptions::new() - .write(true) - .create(true) - .open(path)?; - - file.write_u64::(meta.version)?; - file.write_all(&meta.pending_hash)?; - file.flush() -} diff --git a/util/blooms-db/src/pending.rs b/util/blooms-db/src/pending.rs deleted file mode 100644 index acca3667e4d..00000000000 --- a/util/blooms-db/src/pending.rs +++ /dev/null @@ -1,158 +0,0 @@ -use std::io::{Seek, SeekFrom, Write, Read}; -use std::path::Path; -use std::{fs, io}; - -use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian}; -use ethbloom; -use tiny_keccak::Keccak; - -/// File with blooms which are not flushed to the database yet. -pub struct Pending { - file: fs::File, -} - -impl Pending { - /// Opens pending changes file. Creates new file if pending changes do not exist. - pub fn open

(path: P) -> io::Result where P: AsRef { - let file = fs::OpenOptions::new() - .read(true) - .write(true) - .create(true) - .append(true) - .open(path)?; - - let pending = Pending { - file, - }; - - Ok(pending) - } - - /// Pushes pending changes to a file. - pub fn append<'a, B>(&mut self, index: u64, bloom: B) -> io::Result<()> where ethbloom::BloomRef<'a>: From { - self.file.write_u64::(index)?; - self.file.write_all(ethbloom::BloomRef::from(bloom).data()) - } - - /// Flushes changes to underlying file. - pub fn flush(&mut self) -> io::Result<()> { - self.file.sync_all() - } - - /// Clears underlying file. - pub fn clear(&mut self) -> io::Result<()> { - self.file.seek(SeekFrom::Start(0))?; - self.file.set_len(0)?; - self.file.sync_all() - } - - /// Returns an iterator over blooms in the file. - pub fn iterator(&self) -> io::Result { - let mut file_ref = &self.file; - file_ref.seek(SeekFrom::Start(0))?; - - let iter = PendingIterator { - file: file_ref, - }; - - Ok(iter) - } - - /// Returns file hash. - pub fn hash(&self) -> io::Result<[u8; 32]> { - let mut file_ref = &self.file; - file_ref.seek(SeekFrom::Start(0))?; - let mut keccak = Keccak::new_keccak256(); - let mut buffer = [0u8; 256 + 8]; - loop { - match file_ref.read_exact(&mut buffer) { - Ok(_) => { - keccak.update(&mut buffer); - }, - Err(ref err) if err.kind() == io::ErrorKind::UnexpectedEof => { - let mut result = [0u8; 32]; - keccak.finalize(&mut result); - return Ok(result); - }, - Err(err) => return Err(err), - } - } - } -} - -/// Iterator over blooms in the file. -pub struct PendingIterator<'a> { - file: &'a fs::File, -} - -impl<'a> Iterator for PendingIterator<'a> { - type Item = io::Result<(u64, ethbloom::Bloom)>; - - fn next(&mut self) -> Option { - let index = match self.file.read_u64::() { - Ok(index) => index, - Err(ref err) if err.kind() == io::ErrorKind::UnexpectedEof => return None, - Err(err) => return Some(Err(err)), - }; - - let mut bloom = ethbloom::Bloom::default(); - match self.file.read_exact(&mut bloom) { - Ok(_) => Some(Ok((index, bloom))), - Err(err) => Some(Err(err)), - } - } -} - -#[cfg(test)] -mod tests { - use ethbloom::Bloom; - use tempdir::TempDir; - use super::Pending; - - #[test] - fn test_pending() { - let tempdir = TempDir::new("").unwrap(); - let mut pending = Pending::open(tempdir.path().join("pending")).unwrap(); - - // append elements - pending.append(0, &Bloom::from(0)).unwrap(); - pending.append(1, &Bloom::from(1)).unwrap(); - pending.append(2, &Bloom::from(2)).unwrap(); - pending.append(3, &Bloom::from(3)).unwrap(); - pending.append(2, &Bloom::from(4)).unwrap(); - - // flush - pending.flush().unwrap(); - - // validate all elements - let elements = pending.iterator().unwrap().collect::, _>>().unwrap(); - assert_eq!(elements, vec![ - (0, 0.into()), - (1, 1.into()), - (2, 2.into()), - (3, 3.into()), - (2, 4.into()) - ]); - - // move iterator - let first = pending.iterator().unwrap().next().unwrap().unwrap(); - assert_eq!(first, (0, 0.into())); - - // validate that after moving an iterator the element is still appended to the of the file - pending.append(4, &Bloom::from(5)).unwrap(); - pending.flush().unwrap(); - let elements2 = pending.iterator().unwrap().collect::, _>>().unwrap(); - assert_eq!(elements2, vec![ - (0, 0.into()), - (1, 1.into()), - (2, 2.into()), - (3, 3.into()), - (2, 4.into()), - (4, 5.into()) - ]); - - pending.clear().unwrap(); - let elements3 = pending.iterator().unwrap().collect::, _>>().unwrap(); - assert!(elements3.is_empty()); - } -} From 979ed3328b3b4e8846ccfa70b8a11c2bbacaeb5f Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 1 Jun 2018 14:23:06 +0200 Subject: [PATCH 09/29] blooms-db uses io::BufReader to read files, wrap blooms-db into Mutex, cause fs::File is just a shared file handle --- util/blooms-db/src/db.rs | 2 +- util/blooms-db/src/file.rs | 13 ++++++++----- util/blooms-db/src/lib.rs | 15 +++++++-------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/util/blooms-db/src/db.rs b/util/blooms-db/src/db.rs index 3311ec97fbe..fc074875cff 100644 --- a/util/blooms-db/src/db.rs +++ b/util/blooms-db/src/db.rs @@ -71,7 +71,7 @@ impl Database { } /// Returns an iterator yielding all indexes containing given bloom. - pub fn iterate_matching<'a, 'b, B>(&'a self, from: u64, to: u64, bloom: B) -> io::Result> + pub fn iterate_matching<'a, 'b, B>(&'a mut self, from: u64, to: u64, bloom: B) -> io::Result> where ethbloom::BloomRef<'b>: From, 'b: 'a { let index = from / 256 * 256; let pos = Positions::from_index(index); diff --git a/util/blooms-db/src/file.rs b/util/blooms-db/src/file.rs index 1e2cccbf783..6fd371e5e0d 100644 --- a/util/blooms-db/src/file.rs +++ b/util/blooms-db/src/file.rs @@ -72,12 +72,15 @@ impl File { } /// Returns an iterator over file. - pub fn iterator_from(&self, pos: u64) -> io::Result { - let mut file_ref = &self.file; - file_ref.seek(SeekFrom::Start(pos * 256))?; + /// + /// This function needs to be mutable `fs::File` is just a shared reference a system file handle. + /// https://users.rust-lang.org/t/how-to-handle-match-with-irrelevant-ok--/6291/15 + pub fn iterator_from(&mut self, pos: u64) -> io::Result { + let mut buf_reader = io::BufReader::new(&self.file); + buf_reader.seek(SeekFrom::Start(pos * 256))?; let iter = FileIterator { - file: file_ref, + file: buf_reader, }; Ok(iter) @@ -92,7 +95,7 @@ impl File { /// Iterator over blooms of a single file. pub struct FileIterator<'a> { /// Backing file. - file: &'a fs::File, + file: io::BufReader<&'a fs::File>, } impl<'a> FileIterator<'a> { diff --git a/util/blooms-db/src/lib.rs b/util/blooms-db/src/lib.rs index ad139125615..964cb266efc 100644 --- a/util/blooms-db/src/lib.rs +++ b/util/blooms-db/src/lib.rs @@ -16,16 +16,16 @@ mod file; use std::io; use std::path::Path; -use parking_lot::RwLock; +use parking_lot::Mutex; pub struct Database { - database: RwLock, + database: Mutex, } impl Database { pub fn open

(path: P) -> io::Result where P: AsRef { let result = Database { - database: RwLock::new(db::Database::open(path)?), + database: Mutex::new(db::Database::open(path)?), }; Ok(result) @@ -33,14 +33,13 @@ impl Database { pub fn insert_blooms<'a, I, B>(&self, from: u64, blooms: I) -> io::Result<()> where ethbloom::BloomRef<'a>: From, I: Iterator { - self.database.write().insert_blooms(from, blooms) + self.database.lock().insert_blooms(from, blooms) } pub fn filter<'a, B>(&'a self, from: u64, to: u64, bloom: B) -> io::Result> where ethbloom::BloomRef<'a>: From { - let database = self.database.read(); - database - .iterate_matching(from, to, bloom)? - .collect::, _>>() + self.database.lock() + .iterate_matching(from, to, bloom)? + .collect::, _>>() } } From 77f0af8434648d92743c978b2f3de04b7366577f Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 1 Jun 2018 14:45:08 +0200 Subject: [PATCH 10/29] fix json_tests --- ethcore/src/json_tests/chain.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 89b8df4a261..e5dae281604 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -21,6 +21,7 @@ use spec::Genesis; use ethjson; use miner::Miner; use io::IoChannel; +use test_helpers; pub fn json_chain_test(json_data: &[u8]) -> Vec { ::ethcore_logger::init_log(); @@ -57,7 +58,7 @@ pub fn json_chain_test(json_data: &[u8]) -> Vec { }; { - let db = Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); + let db = test_helpers::new_db(); let mut config = ClientConfig::default(); config.history = 8; let client = Client::new( From 6367ceaab50189d4abae9c34f7c2c94f9c279ce6 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 1 Jun 2018 16:17:05 +0200 Subject: [PATCH 11/29] blooms-db can filter multiple possibilities at the same time --- ethcore/Cargo.toml | 2 + ethcore/src/blockchain/blockchain.rs | 46 +++++++------- ethcore/src/client/client.rs | 11 +--- ethcore/src/trace/db.rs | 10 +--- ethcore/src/verification/verification.rs | 5 +- util/blooms-db/benches/blooms.rs | 56 ++++++++++++++++- util/blooms-db/src/db.rs | 76 ++++++++++++++++-------- util/blooms-db/src/file.rs | 16 +++++ util/blooms-db/src/lib.rs | 48 +++++++++++++-- 9 files changed, 198 insertions(+), 72 deletions(-) diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 36068aa513e..649b6102201 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -68,6 +68,8 @@ triehash = { path = "../util/triehash" } unexpected = { path = "../util/unexpected" } journaldb = { path = "../util/journaldb" } tempdir = "0.3" + +[dev-dependencies] trie-standardmap = { path = "../util/trie-standardmap" } kvdb-rocksdb = { path = "../util/kvdb-rocksdb" } diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index e23493bfd82..bdf00fef896 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -22,7 +22,7 @@ use std::mem; use itertools::Itertools; use blooms_db; use heapsize::HeapSizeOf; -use ethereum_types::{H256, Bloom, U256}; +use ethereum_types::{H256, Bloom, BloomRef, U256}; use parking_lot::{Mutex, RwLock}; use bytes::Bytes; use rlp::RlpStream; @@ -169,7 +169,8 @@ pub trait BlockProvider { } /// Returns numbers of blocks containing given bloom. - fn blocks_with_bloom(&self, bloom: &Bloom, from_block: BlockNumber, to_block: BlockNumber) -> Vec; + fn blocks_with_bloom<'a, B, I, II>(&self, blooms: II, from_block: BlockNumber, to_block: BlockNumber) -> Vec + where BloomRef<'a>: From, II: IntoIterator + Copy, I: Iterator, Self: Sized; /// Returns logs matching given filter. fn logs(&self, blocks: Vec, matches: F, limit: Option) -> Vec @@ -334,9 +335,10 @@ impl BlockProvider for BlockChain { } /// Returns numbers of blocks containing given bloom. - fn blocks_with_bloom(&self, bloom: &Bloom, from_block: BlockNumber, to_block: BlockNumber) -> Vec { + fn blocks_with_bloom<'a, B, I, II>(&self, blooms: II, from_block: BlockNumber, to_block: BlockNumber) -> Vec + where BloomRef<'a>: From, II: IntoIterator + Copy, I: Iterator { self.db.blooms() - .filter(from_block, to_block, bloom) + .filter(from_block, to_block, blooms) .expect("TODO: blooms pr") } @@ -2168,46 +2170,46 @@ mod tests { let db = new_db(); let bc = new_chain(&genesis.last().encoded(), db.clone()); - let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); - let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); + let blocks_b1 = bc.blocks_with_bloom(Some(&bloom_b1), 0, 5); + let blocks_b2 = bc.blocks_with_bloom(Some(&bloom_b2), 0, 5); assert!(blocks_b1.is_empty()); assert!(blocks_b2.is_empty()); insert_block(&db, &bc, &b1.last().encoded(), vec![]); - let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); - let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); + let blocks_b1 = bc.blocks_with_bloom(Some(&bloom_b1), 0, 5); + let blocks_b2 = bc.blocks_with_bloom(Some(&bloom_b2), 0, 5); assert_eq!(blocks_b1, vec![1]); assert!(blocks_b2.is_empty()); insert_block(&db, &bc, &b2.last().encoded(), vec![]); - let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); - let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); + let blocks_b1 = bc.blocks_with_bloom(Some(&bloom_b1), 0, 5); + let blocks_b2 = bc.blocks_with_bloom(Some(&bloom_b2), 0, 5); assert_eq!(blocks_b1, vec![1]); assert_eq!(blocks_b2, vec![2]); // hasn't been forked yet insert_block(&db, &bc, &b1a.last().encoded(), vec![]); - let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); - let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); - let blocks_ba = bc.blocks_with_bloom(&bloom_ba, 0, 5); + let blocks_b1 = bc.blocks_with_bloom(Some(&bloom_b1), 0, 5); + let blocks_b2 = bc.blocks_with_bloom(Some(&bloom_b2), 0, 5); + let blocks_ba = bc.blocks_with_bloom(Some(&bloom_ba), 0, 5); assert_eq!(blocks_b1, vec![1]); assert_eq!(blocks_b2, vec![2]); assert!(blocks_ba.is_empty()); // fork has happend insert_block(&db, &bc, &b2a.last().encoded(), vec![]); - let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); - let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); - let blocks_ba = bc.blocks_with_bloom(&bloom_ba, 0, 5); + let blocks_b1 = bc.blocks_with_bloom(Some(&bloom_b1), 0, 5); + let blocks_b2 = bc.blocks_with_bloom(Some(&bloom_b2), 0, 5); + let blocks_ba = bc.blocks_with_bloom(Some(&bloom_ba), 0, 5); assert!(blocks_b1.is_empty()); assert!(blocks_b2.is_empty()); assert_eq!(blocks_ba, vec![1, 2]); // fork back insert_block(&db, &bc, &b3.last().encoded(), vec![]); - let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); - let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); - let blocks_ba = bc.blocks_with_bloom(&bloom_ba, 0, 5); + let blocks_b1 = bc.blocks_with_bloom(Some(&bloom_b1), 0, 5); + let blocks_b2 = bc.blocks_with_bloom(Some(&bloom_b2), 0, 5); + let blocks_ba = bc.blocks_with_bloom(Some(&bloom_ba), 0, 5); assert_eq!(blocks_b1, vec![1]); assert_eq!(blocks_b2, vec![2]); assert_eq!(blocks_ba, vec![3]); @@ -2243,9 +2245,9 @@ mod tests { assert_eq!(bc.block_hash(2).unwrap(), b2.last().hash()); assert_eq!(bc.block_hash(3).unwrap(), b3.last().hash()); - let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 3); - let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 3); - let blocks_b3 = bc.blocks_with_bloom(&bloom_b3, 0, 3); + let blocks_b1 = bc.blocks_with_bloom(Some(&bloom_b1), 0, 3); + let blocks_b2 = bc.blocks_with_bloom(Some(&bloom_b2), 0, 3); + let blocks_b3 = bc.blocks_with_bloom(Some(&bloom_b3), 0, 3); assert_eq!(blocks_b1, vec![1]); assert_eq!(blocks_b2, vec![2]); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 3492796f6c3..4f015e156f5 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::collections::{HashSet, BTreeMap, BTreeSet, VecDeque}; +use std::collections::{HashSet, BTreeMap, VecDeque}; use std::fmt; use std::str::FromStr; use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; @@ -1838,17 +1838,10 @@ impl BlockChainClient for Client { let from = self.block_number_ref(&filter.from_block)?; let to = self.block_number_ref(&filter.to_block)?; - filter.bloom_possibilities().iter() - .map(|bloom| { - chain.blocks_with_bloom(bloom, from, to) - }) - .flat_map(|m| m) - // remove duplicate elements - .collect::>() + chain.blocks_with_bloom(&filter.bloom_possibilities(), from, to) .into_iter() .filter_map(|n| chain.block_hash(n)) .collect::>() - } else { // Otherwise, we use a slower version that finds a link between from_block and to_block. let from_hash = Self::block_hash(&chain, filter.from_block)?; diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 7e89db90b02..18507eeec27 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . //! Trace database. -use std::collections::{HashMap, BTreeSet, VecDeque}; +use std::collections::{HashMap, VecDeque}; use std::sync::Arc; use blockchain::{BlockChainDB}; use heapsize::HeapSizeOf; @@ -316,12 +316,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { fn filter(&self, filter: &Filter) -> Vec { let possibilities = filter.bloom_possibilities(); - let blooms_db = self.db.trace_blooms(); - let numbers = possibilities.iter() - .map(|bloom| blooms_db.filter(filter.range.start as u64, filter.range.end as u64, bloom).expect("TODO: blooms pr")) - .into_iter() - .flat_map(|n| n) - .collect::>(); + let numbers = self.db.trace_blooms() + .filter(filter.range.start as u64, filter.range.end as u64, &possibilities).expect("TODO: blooms pr"); numbers.into_iter() .flat_map(|n| { diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index de2f6c7195d..7e0a8a0fe8c 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -352,7 +352,7 @@ mod tests { use std::collections::{BTreeMap, HashMap}; use std::time::{SystemTime, UNIX_EPOCH}; - use ethereum_types::{H256, Bloom, U256}; + use ethereum_types::{H256, BloomRef, U256}; use blockchain::{BlockDetails, TransactionAddress, BlockReceipts}; use encoded; use hash::keccak; @@ -474,7 +474,8 @@ mod tests { unimplemented!() } - fn blocks_with_bloom(&self, _bloom: &Bloom, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec { + fn blocks_with_bloom<'a, B, I, II>(&self, _blooms: II, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec + where BloomRef<'a>: From, II: IntoIterator + Copy, I: Iterator, Self: Sized { unimplemented!() } diff --git a/util/blooms-db/benches/blooms.rs b/util/blooms-db/benches/blooms.rs index 8e92c4c3850..7a27260b35a 100644 --- a/util/blooms-db/benches/blooms.rs +++ b/util/blooms-db/benches/blooms.rs @@ -1,3 +1,19 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + #![feature(test)] extern crate test; @@ -12,18 +28,54 @@ use blooms_db::Database; use ethbloom::Bloom; #[bench] -fn blooms_filter_1_million(b: &mut Bencher) { +fn blooms_filter_1_million_ok(b: &mut Bencher) { + let tempdir = TempDir::new("").unwrap(); + let database = Database::open(tempdir.path()).unwrap(); + database.insert_blooms(999_999, iter::once(&Bloom::from(0))).unwrap(); + let bloom = Bloom::from(0x001); + database.insert_blooms(200_000, iter::once(&bloom)).unwrap(); + database.insert_blooms(400_000, iter::once(&bloom)).unwrap(); + database.insert_blooms(600_000, iter::once(&bloom)).unwrap(); + database.insert_blooms(800_000, iter::once(&bloom)).unwrap(); + + b.iter(|| { + let matches = database.filter(0, 999_999, Some(&bloom)).unwrap(); + assert_eq!(matches, vec![200_000, 400_000, 600_000, 800_000]); + }); +} + +#[bench] +fn blooms_filter_1_million_miss(b: &mut Bencher) { + let tempdir = TempDir::new("").unwrap(); + let database = Database::open(tempdir.path()).unwrap(); + database.insert_blooms(999_999, iter::once(&Bloom::from(0))).unwrap(); + let bloom = Bloom::from(0x001); + let bad_bloom = Bloom::from(0x0001); + database.insert_blooms(200_000, iter::once(&bloom)).unwrap(); + database.insert_blooms(400_000, iter::once(&bloom)).unwrap(); + database.insert_blooms(600_000, iter::once(&bloom)).unwrap(); + database.insert_blooms(800_000, iter::once(&bloom)).unwrap(); + + b.iter(|| { + let matches = database.filter(0, 999_999, Some(&bad_bloom)).unwrap(); + assert_eq!(matches, vec![200_000, 400_000, 600_000, 800_000]); + }); +} + +#[bench] +fn blooms_filter_1_million_miss_and_ok(b: &mut Bencher) { let tempdir = TempDir::new("").unwrap(); let database = Database::open(tempdir.path()).unwrap(); database.insert_blooms(999_999, iter::once(&Bloom::from(0))).unwrap(); let bloom = Bloom::from(0x001); + let bad_bloom = Bloom::from(0x0001); database.insert_blooms(200_000, iter::once(&bloom)).unwrap(); database.insert_blooms(400_000, iter::once(&bloom)).unwrap(); database.insert_blooms(600_000, iter::once(&bloom)).unwrap(); database.insert_blooms(800_000, iter::once(&bloom)).unwrap(); b.iter(|| { - let matches = database.filter(0, 999_999, &bloom).unwrap(); + let matches = database.filter(0, 999_999, &vec![bad_bloom, bloom]).unwrap(); assert_eq!(matches, vec![200_000, 400_000, 600_000, 800_000]); }); } diff --git a/util/blooms-db/src/db.rs b/util/blooms-db/src/db.rs index fc074875cff..cb88927c7d0 100644 --- a/util/blooms-db/src/db.rs +++ b/util/blooms-db/src/db.rs @@ -1,3 +1,19 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + use std::{io, fmt}; use std::path::Path; @@ -71,8 +87,8 @@ impl Database { } /// Returns an iterator yielding all indexes containing given bloom. - pub fn iterate_matching<'a, 'b, B>(&'a mut self, from: u64, to: u64, bloom: B) -> io::Result> - where ethbloom::BloomRef<'b>: From, 'b: 'a { + pub fn iterate_matching<'a, 'b, B, I, II>(&'a mut self, from: u64, to: u64, blooms: II) -> io::Result> + where ethbloom::BloomRef<'b>: From, 'b: 'a, II: IntoIterator + Copy, I: Iterator { let index = from / 256 * 256; let pos = Positions::from_index(index); @@ -84,15 +100,20 @@ impl Database { from, to, index, - bloom: bloom.into(), + blooms, }; Ok(iter) } } +fn contains_any<'a, I, B>(bloom: ethbloom::Bloom, mut iterator: I) -> bool +where ethbloom::BloomRef<'a>: From, I: Iterator { + iterator.any(|item| bloom.contains_bloom(item)) +} + /// Blooms database iterator -pub struct DatabaseIterator<'a> { +pub struct DatabaseIterator<'a, I> { top: FileIterator<'a>, mid: FileIterator<'a>, bot: FileIterator<'a>, @@ -100,17 +121,17 @@ pub struct DatabaseIterator<'a> { from: u64, to: u64, index: u64, - bloom: ethbloom::BloomRef<'a>, + blooms: I, } -impl<'a> fmt::Debug for DatabaseIterator<'a> { +impl<'a, I> fmt::Debug for DatabaseIterator<'a, I> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("DatabaseIterator") .field("state", &self.state) .field("from", &self.from) .field("to", &self.to) .field("index", &self.index) - .field("bloom", &"...") + .field("blooms", &"...") .field("top", &"...") .field("mid", &"...") .field("bot", &"...") @@ -130,7 +151,8 @@ enum IteratorState { Bot { mid: usize, bot: usize }, } -impl<'a> Iterator for DatabaseIterator<'a> { +impl<'a, 'b, B, I, II> Iterator for DatabaseIterator<'a, II> +where ethbloom::BloomRef<'b>: From, 'b: 'a, II: IntoIterator + Copy, I: Iterator { type Item = io::Result; fn next(&mut self) -> Option { @@ -143,6 +165,12 @@ impl<'a> Iterator for DatabaseIterator<'a> { } } + macro_rules! next_bloom { + ($iter: expr) => { + try_o!($iter.next()?) + } + } + loop { if self.index > self.to { return None; @@ -150,7 +178,7 @@ impl<'a> Iterator for DatabaseIterator<'a> { self.state = match self.state { IteratorState::Top => { - if try_o!(self.top.next()?).contains_bloom(self.bloom) { + if contains_any(next_bloom!(self.top), self.blooms.into_iter()) { IteratorState::Mid(16) } else { self.index += 256; @@ -162,7 +190,7 @@ impl<'a> Iterator for DatabaseIterator<'a> { IteratorState::Mid(left) => { if left == 0 { IteratorState::Top - } else if try_o!(self.mid.next()?).contains_bloom(self.bloom) && self.index + 16 >= self.from { + } else if contains_any(next_bloom!(self.mid), self.blooms.into_iter()) && self.index + 16 >= self.from { IteratorState::Bot { mid: left - 1, bot: 16 } } else { self.index += 16; @@ -173,7 +201,7 @@ impl<'a> Iterator for DatabaseIterator<'a> { IteratorState::Bot { mid, bot } => { if bot == 0 { IteratorState::Mid(mid) - } else if try_o!(self.bot.next()?).contains_bloom(self.bloom) && self.index >= self.from { + } else if contains_any(next_bloom!(self.bot), self.blooms.into_iter()) && self.index >= self.from { let result = self.index; self.index += 1; self.state = IteratorState::Bot { mid, bot: bot - 1 }; @@ -200,25 +228,25 @@ mod tests { let mut database = Database::open(tempdir.path()).unwrap(); database.insert_blooms(0, vec![Bloom::from(0), Bloom::from(0x01), Bloom::from(0x10), Bloom::from(0x11)].iter()).unwrap(); - let matches = database.iterate_matching(0, 3, &Bloom::from(0)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(0, 3, Some(&Bloom::from(0))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![0, 1, 2, 3]); - let matches = database.iterate_matching(0, 4, &Bloom::from(0)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(0, 4, Some(&Bloom::from(0))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![0, 1, 2, 3]); - let matches = database.iterate_matching(1, 3, &Bloom::from(0)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(1, 3, Some(&Bloom::from(0))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![1, 2, 3]); - let matches = database.iterate_matching(1, 2, &Bloom::from(0)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(1, 2, Some(&Bloom::from(0))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![1, 2]); - let matches = database.iterate_matching(0, 3, &Bloom::from(0x01)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(0, 3, Some(&Bloom::from(0x01))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![1, 3]); - let matches = database.iterate_matching(0, 3, &Bloom::from(0x10)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(0, 3, Some(&Bloom::from(0x10))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![2, 3]); - let matches = database.iterate_matching(2, 2, &Bloom::from(0x10)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(2, 2, Some(&Bloom::from(0x10))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![2]); } @@ -228,22 +256,22 @@ mod tests { let mut database = Database::open(tempdir.path()).unwrap(); database.insert_blooms(254, vec![Bloom::from(0x100), Bloom::from(0x01), Bloom::from(0x10), Bloom::from(0x11)].iter()).unwrap(); - let matches = database.iterate_matching(0, 257, &Bloom::from(0x01)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(0, 257, Some(&Bloom::from(0x01))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![255, 257]); - let matches = database.iterate_matching(0, 258, &Bloom::from(0x100)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(0, 258, Some(&Bloom::from(0x100))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![254]); - let matches = database.iterate_matching(0, 256, &Bloom::from(0x01)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(0, 256, Some(&Bloom::from(0x01))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![255]); - let matches = database.iterate_matching(255, 255, &Bloom::from(0x01)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(255, 255, Some(&Bloom::from(0x01))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![255]); - let matches = database.iterate_matching(256, 256, &Bloom::from(0x10)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(256, 256, Some(&Bloom::from(0x10))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![256]); - let matches = database.iterate_matching(256, 257, &Bloom::from(0x10)).unwrap().collect::, _>>().unwrap(); + let matches = database.iterate_matching(256, 257, Some(&Bloom::from(0x10))).unwrap().collect::, _>>().unwrap(); assert_eq!(matches, vec![256, 257]); } } diff --git a/util/blooms-db/src/file.rs b/util/blooms-db/src/file.rs index 6fd371e5e0d..64766c5cde7 100644 --- a/util/blooms-db/src/file.rs +++ b/util/blooms-db/src/file.rs @@ -1,3 +1,19 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + use std::io::{Seek, SeekFrom, Write, Read}; use std::path::Path; use std::{io, fs}; diff --git a/util/blooms-db/src/lib.rs b/util/blooms-db/src/lib.rs index 964cb266efc..597012e064a 100644 --- a/util/blooms-db/src/lib.rs +++ b/util/blooms-db/src/lib.rs @@ -1,7 +1,20 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + //! Ethereum blooms database -//! -//! zero allocation -//! zero copying extern crate byteorder; extern crate ethbloom; @@ -18,11 +31,21 @@ use std::io; use std::path::Path; use parking_lot::Mutex; +/// Threadsafe API for blooms database. +/// +/// # Warning +/// +/// This database does not guarantee atomic writes. pub struct Database { database: Mutex, } impl Database { + /// Creates new database handle. + /// + /// # Arguments + /// + /// * `path` - database directory pub fn open

(path: P) -> io::Result where P: AsRef { let result = Database { database: Mutex::new(db::Database::open(path)?), @@ -31,15 +54,28 @@ impl Database { Ok(result) } + /// Inserts one or more blooms into database. + /// + /// # Arguments + /// + /// * `from` - index of the first bloom that needs to be inserted + /// * `blooms` - iterator over blooms pub fn insert_blooms<'a, I, B>(&self, from: u64, blooms: I) -> io::Result<()> where ethbloom::BloomRef<'a>: From, I: Iterator { self.database.lock().insert_blooms(from, blooms) } - pub fn filter<'a, B>(&'a self, from: u64, to: u64, bloom: B) -> io::Result> - where ethbloom::BloomRef<'a>: From { + /// Returns indexes of all headers matching given bloom in a specified range. + /// + /// # Arguments + /// + /// * `from` - index of the first bloom that needs to be checked + /// * `to` - index of the last bloom that needs to be checked (inclusive range) + /// * `blooms` - searched pattern + pub fn filter<'a, B, I, II>(&self, from: u64, to: u64, blooms: II) -> io::Result> + where ethbloom::BloomRef<'a>: From, II: IntoIterator + Copy, I: Iterator { self.database.lock() - .iterate_matching(from, to, bloom)? + .iterate_matching(from, to, blooms)? .collect::, _>>() } } From 6a806a1cbbac2371ac2e24b3b8fdac04e3a98dfb Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 1 Jun 2018 16:41:03 +0200 Subject: [PATCH 12/29] removed enum trace/db.rs CacheId --- ethcore/src/trace/db.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 18507eeec27..05b357ec778 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -47,11 +47,6 @@ impl Key for H256 { } } -#[derive(Debug, Hash, Eq, PartialEq)] -enum CacheId { - Trace(H256), -} - /// Database to store transaction execution trace. /// /// Whenever a transaction is executed by EVM it's execution trace is stored @@ -61,7 +56,7 @@ enum CacheId { pub struct TraceDB where T: DatabaseExtras { /// cache traces: RwLock>, - cache_manager: RwLock>, + cache_manager: RwLock>, /// db db: Arc, /// tracing enabled @@ -94,9 +89,9 @@ impl TraceDB where T: DatabaseExtras { } /// Let the cache system know that a cacheable item has been used. - fn note_used(&self, id: CacheId) { + fn note_trace_used(&self, trace_id: H256) { let mut cache_manager = self.cache_manager.write(); - cache_manager.note_used(id); + cache_manager.note_used(trace_id); } /// Ticks our cache system and throws out any old data. @@ -108,9 +103,7 @@ impl TraceDB where T: DatabaseExtras { cache_manager.collect_garbage(current_size, | ids | { for id in &ids { - match *id { - CacheId::Trace(ref h) => { traces.remove(h); }, - } + traces.remove(id); } traces.shrink_to_fit(); @@ -121,7 +114,7 @@ impl TraceDB where T: DatabaseExtras { /// Returns traces for block with hash. fn traces(&self, block_hash: &H256) -> Option { let result = self.db.key_value().read_with_cache(db::COL_TRACE, &self.traces, block_hash); - self.note_used(CacheId::Trace(block_hash.clone())); + self.note_trace_used(*block_hash); result } @@ -227,7 +220,7 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { // cause this value might be queried by hash later batch.write_with_cache(db::COL_TRACE, &mut *traces, request.block_hash, request.traces, CacheUpdatePolicy::Overwrite); // note_used must be called after locking traces to avoid cache/traces deadlock on garbage collection - self.note_used(CacheId::Trace(request.block_hash.clone())); + self.note_trace_used(request.block_hash); } } From 65f9f9190eaf668fcc0a7c64b0bbb6fd9305fd88 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 1 Jun 2018 16:50:29 +0200 Subject: [PATCH 13/29] lint fixes --- ethcore/src/blockchain/blockchain.rs | 6 +----- ethcore/src/snapshot/tests/helpers.rs | 2 +- ethcore/src/snapshot/tests/service.rs | 2 +- ethcore/src/test_helpers.rs | 1 + ethcore/src/tests/client.rs | 9 --------- ethcore/src/tests/trace.rs | 3 --- 6 files changed, 4 insertions(+), 19 deletions(-) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index bdf00fef896..587742ecd82 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -1465,7 +1465,7 @@ mod tests { use std::sync::Arc; use rustc_hex::FromHex; use hash::keccak; - use kvdb::{DBTransaction}; + use kvdb::DBTransaction; use ethereum_types::*; use receipt::{Receipt, TransactionOutcome}; use blockchain::{BlockProvider, BlockChain, BlockChainDB, Config, ImportRoute}; @@ -1480,10 +1480,6 @@ mod tests { use ethkey::Secret; use test_helpers::new_db; - //fn new_db() -> Arc - //Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))) - //} - fn new_chain(genesis: &[u8], db: Arc) -> BlockChain { BlockChain::new(Config::default(), genesis, db) } diff --git a/ethcore/src/snapshot/tests/helpers.rs b/ethcore/src/snapshot/tests/helpers.rs index d0370bcb6b9..ee5fe8d104c 100644 --- a/ethcore/src/snapshot/tests/helpers.rs +++ b/ethcore/src/snapshot/tests/helpers.rs @@ -33,7 +33,7 @@ use snapshot::io::{SnapshotReader, PackedWriter, PackedReader}; use tempdir::TempDir; use rand::Rng; -use kvdb::{DBValue}; +use kvdb::DBValue; use ethereum_types::H256; use hashdb::HashDB; use journaldb; diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 75572c3fabe..6207781f7f0 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -28,7 +28,7 @@ use test_helpers::{generate_dummy_client_with_spec_and_data}; use test_helpers_internal::restoration_db_handler; use io::IoChannel; -use kvdb_rocksdb::{DatabaseConfig}; +use kvdb_rocksdb::DatabaseConfig; struct NoopDBRestore; diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index e4777c61c0c..8f825416f87 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -258,6 +258,7 @@ pub fn get_test_client_with_blocks(blocks: Vec) -> Arc { client } +/// Creates new test instance of `BlockChainDB` pub fn new_db() -> Arc { struct TestBlockChainDB { _blooms_dir: TempDir, diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index b6b91ee7d32..e1f457369fd 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -87,10 +87,7 @@ fn returns_state_root_basic() { #[test] fn imports_good_block() { let db = test_helpers::new_db(); - //let tempdir = TempDir::new("").unwrap(); let spec = Spec::new_test(); - //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), @@ -132,10 +129,7 @@ fn fails_to_import_block_with_invalid_rlp() { #[test] fn query_none_block() { let db = test_helpers::new_db(); - //let tempdir = TempDir::new("").unwrap(); let spec = Spec::new_test(); - //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), @@ -284,11 +278,8 @@ fn can_mine() { #[test] fn change_history_size() { let db = test_helpers::new_db(); - //let tempdir = TempDir::new("").unwrap(); let test_spec = Spec::new_null(); let mut config = ClientConfig::default(); - //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); config.history = 2; let address = Address::random(); diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs index c8abb3ccb65..3008b935984 100644 --- a/ethcore/src/tests/trace.rs +++ b/ethcore/src/tests/trace.rs @@ -37,15 +37,12 @@ use test_helpers; #[test] fn can_trace_block_and_uncle_reward() { let db = test_helpers::new_db(); - //let tempdir = TempDir::new("").unwrap(); let spec = Spec::new_test_with_reward(); let engine = &*spec.engine; // Create client - //let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let mut client_config = ClientConfig::default(); client_config.tracing.enabled = true; - //let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( client_config, &spec, From ffd5a2a51157d52482b425c189c94295693efd1e Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 1 Jun 2018 18:19:30 +0200 Subject: [PATCH 14/29] fixed tests --- ethcore/Cargo.toml | 2 +- ethcore/light/src/client/service.rs | 5 +- ethcore/node_filter/src/lib.rs | 3 +- ethcore/service/src/service.rs | 25 ++----- ethcore/src/blockchain/blockchain.rs | 6 +- ethcore/src/client/config.rs | 2 +- ethcore/src/lib.rs | 10 +-- ethcore/src/snapshot/service.rs | 2 +- ethcore/src/snapshot/tests/proof_of_work.rs | 2 +- ethcore/src/snapshot/tests/service.rs | 3 +- ethcore/src/test_helpers.rs | 53 ++++++++++++++- ethcore/src/test_helpers_internal.rs | 73 --------------------- ethcore/sync/src/tests/helpers.rs | 3 +- rpc/src/v1/tests/eth.rs | 4 +- 14 files changed, 77 insertions(+), 116 deletions(-) delete mode 100644 ethcore/src/test_helpers_internal.rs diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 649b6102201..25a16296bbb 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -68,10 +68,10 @@ triehash = { path = "../util/triehash" } unexpected = { path = "../util/unexpected" } journaldb = { path = "../util/journaldb" } tempdir = "0.3" +kvdb-rocksdb = { path = "../util/kvdb-rocksdb" } [dev-dependencies] trie-standardmap = { path = "../util/trie-standardmap" } -kvdb-rocksdb = { path = "../util/kvdb-rocksdb" } [features] # Display EVM debug traces. diff --git a/ethcore/light/src/client/service.rs b/ethcore/light/src/client/service.rs index fb1cc36cf84..288606b7efc 100644 --- a/ethcore/light/src/client/service.rs +++ b/ethcore/light/src/client/service.rs @@ -120,12 +120,11 @@ mod tests { use client::fetch; use std::time::Duration; use parking_lot::Mutex; - use kvdb_memorydb; - use ethcore::db::NUM_COLUMNS; + use ethcore::test_helpers; #[test] fn it_works() { - let db = Arc::new(kvdb_memorydb::create(NUM_COLUMNS.unwrap_or(0))); + let db = test_helpers::new_db(); let spec = Spec::new_test(); let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); diff --git a/ethcore/node_filter/src/lib.rs b/ethcore/node_filter/src/lib.rs index c731ad356ad..ccddca32245 100644 --- a/ethcore/node_filter/src/lib.rs +++ b/ethcore/node_filter/src/lib.rs @@ -116,6 +116,7 @@ mod test { use ethcore::spec::Spec; use ethcore::client::{BlockChainClient, Client, ClientConfig}; use ethcore::miner::Miner; + use ethcore::test_helpers; use network::{ConnectionDirection, ConnectionFilter, NodeId}; use io::IoChannel; use super::NodeFilter; @@ -128,7 +129,7 @@ mod test { let data = include_bytes!("../res/node_filter.json"); let tempdir = TempDir::new("").unwrap(); let spec = Spec::load(&tempdir.path(), &data[..]).unwrap(); - let client_db = Arc::new(::kvdb_memorydb::create(::ethcore::db::NUM_COLUMNS.unwrap_or(0))); + let client_db = test_helpers::new_db(); let client = Client::new( ClientConfig::default(), diff --git a/ethcore/service/src/service.rs b/ethcore/service/src/service.rs index 571e8ff3bd8..570f44002ec 100644 --- a/ethcore/service/src/service.rs +++ b/ethcore/service/src/service.rs @@ -259,8 +259,8 @@ mod tests { use ethcore::miner::Miner; use ethcore::spec::Spec; use ethcore::db::NUM_COLUMNS; - use kvdb::Error; - use kvdb_rocksdb::{Database, DatabaseConfig, CompactionProfile}; + use ethcore::test_helpers; + use kvdb_rocksdb::{DatabaseConfig, CompactionProfile}; use super::*; use ethcore_private_tx; @@ -278,24 +278,9 @@ mod tests { client_db_config.compaction = CompactionProfile::auto(&client_path); client_db_config.wal = client_config.db_wal; - let client_db = Arc::new(Database::open( - &client_db_config, - &client_path.to_str().expect("DB path could not be converted to string.") - ).unwrap()); - - struct RestorationDBHandler { - config: DatabaseConfig, - } - - impl KeyValueDBHandler for RestorationDBHandler { - fn open(&self, db_path: &Path) -> Result, Error> { - Ok(Arc::new(Database::open(&self.config, &db_path.to_string_lossy())?)) - } - } - - let restoration_db_handler = Box::new(RestorationDBHandler { - config: client_db_config, - }); + let client_db_handler = test_helpers::restoration_db_handler(client_db_config.clone()); + let client_db = client_db_handler.open(&client_path).unwrap(); + let restoration_db_handler = test_helpers::restoration_db_handler(client_db_config); let spec = Spec::new_test(); let service = ClientService::start( diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 587742ecd82..8b12d131d17 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -339,7 +339,7 @@ impl BlockProvider for BlockChain { where BloomRef<'a>: From, II: IntoIterator + Copy, I: Iterator { self.db.blooms() .filter(from_block, to_block, blooms) - .expect("TODO: blooms pr") + .expect("Low level database error. Some issue with disk?") } /// Returns logs matching given filter. The order of logs returned will be the same as the order of the blocks @@ -1063,7 +1063,9 @@ impl BlockChain { } if let Some((block, blooms)) = update.blocks_blooms { - self.db.blooms().insert_blooms(block, blooms.iter()).expect("TODO: blooms pr"); + self.db.blooms() + .insert_blooms(block, blooms.iter()) + .expect("Low level database error. Some issue with disk?"); } // These cached values must be updated last with all four locks taken to avoid diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index 9787f822a4d..eb035f481a7 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -112,7 +112,7 @@ impl From for Mode { /// Client configuration. Includes configs for all sub-systems. -#[derive(Debug, PartialEq, Default)] +#[derive(Debug, PartialEq, Default, Clone)] pub struct ClientConfig { /// Block queue configuration. pub queue: QueueConfig, diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 31b7a939736..ebb1344a904 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -78,6 +78,9 @@ extern crate ethkey; extern crate hardware_wallet; extern crate hashdb; extern crate itertools; +extern crate kvdb; +extern crate kvdb_memorydb; +extern crate kvdb_rocksdb; extern crate lru_cache; extern crate num_cpus; extern crate num; @@ -94,8 +97,6 @@ extern crate patricia_trie as trie; extern crate triehash; extern crate ansi_term; extern crate unexpected; -extern crate kvdb; -extern crate kvdb_memorydb; extern crate util_error; extern crate snappy; @@ -135,9 +136,6 @@ pub extern crate ethstore; #[macro_use] pub mod views; -#[cfg(test)] -extern crate kvdb_rocksdb; - pub mod account_provider; pub mod block; pub mod client; @@ -175,8 +173,6 @@ mod tests; #[cfg(test)] #[cfg(feature="json-tests")] mod json_tests; -#[cfg(test)] -mod test_helpers_internal; pub use types::*; pub use executive::contract_address; diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index f38f16ce6d2..453b30d8401 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -766,7 +766,7 @@ mod tests { use snapshot::{ManifestData, RestorationStatus, SnapshotService}; use super::*; use tempdir::TempDir; - use test_helpers_internal::restoration_db_handler; + use test_helpers::restoration_db_handler; struct NoopDBRestore; impl DatabaseRestore for NoopDBRestore { diff --git a/ethcore/src/snapshot/tests/proof_of_work.rs b/ethcore/src/snapshot/tests/proof_of_work.rs index 769f7060969..e672e0a8bbd 100644 --- a/ethcore/src/snapshot/tests/proof_of_work.rs +++ b/ethcore/src/snapshot/tests/proof_of_work.rs @@ -27,7 +27,7 @@ use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter}; use parking_lot::Mutex; use snappy; -use kvdb::{DBTransaction}; +use kvdb::DBTransaction; use test_helpers; const SNAPSHOT_MODE: ::snapshot::PowSnapshot = ::snapshot::PowSnapshot { blocks: 30000, max_restore_blocks: 30000 }; diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 6207781f7f0..e7a594ec39d 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -24,8 +24,7 @@ use ids::BlockId; use snapshot::service::{Service, ServiceParams}; use snapshot::{self, ManifestData, SnapshotService}; use spec::Spec; -use test_helpers::{generate_dummy_client_with_spec_and_data}; -use test_helpers_internal::restoration_db_handler; +use test_helpers::{generate_dummy_client_with_spec_and_data, restoration_db_handler}; use io::IoChannel; use kvdb_rocksdb::DatabaseConfig; diff --git a/ethcore/src/test_helpers.rs b/ethcore/src/test_helpers.rs index 8f825416f87..cfef27c4ac5 100644 --- a/ethcore/src/test_helpers.rs +++ b/ethcore/src/test_helpers.rs @@ -16,13 +16,16 @@ //! Set of different helpers for client tests +use std::path::Path; +use std::fs; use account_provider::AccountProvider; use ethereum_types::{H256, U256, Address}; use block::{OpenBlock, Drain}; -use blockchain::{BlockChain, BlockChainDB, Config as BlockChainConfig, ExtrasInsert}; +use blockchain::{BlockChain, BlockChainDB, BlockChainDBHandler, Config as BlockChainConfig, ExtrasInsert}; use bytes::Bytes; use client::{Client, ClientConfig, ChainInfo, ImportBlock, ChainNotify, ChainMessageType, PrepareOpenBlock}; use ethkey::KeyPair; +use error::Error; use evm::Factory as EvmFactory; use factory::Factories; use hash::keccak; @@ -39,6 +42,7 @@ use transaction::{Action, Transaction, SignedTransaction}; use views::BlockView; use blooms_db; use kvdb::KeyValueDB; +use kvdb_rocksdb; use tempdir::TempDir; /// Creates test block with corresponding header @@ -296,6 +300,53 @@ pub fn new_db() -> Arc { Arc::new(db) } +/// Creates new instance of KeyValueDBHandler +pub fn restoration_db_handler(config: kvdb_rocksdb::DatabaseConfig) -> Box { + struct RestorationDBHandler { + config: kvdb_rocksdb::DatabaseConfig, + } + + struct RestorationDB { + blooms: blooms_db::Database, + trace_blooms: blooms_db::Database, + key_value: Arc, + } + + impl BlockChainDB for RestorationDB { + fn key_value(&self) -> &Arc { + &self.key_value + } + + fn blooms(&self) -> &blooms_db::Database { + &self.blooms + } + + fn trace_blooms(&self) -> &blooms_db::Database { + &self.trace_blooms + } + } + + impl BlockChainDBHandler for RestorationDBHandler { + fn open(&self, db_path: &Path) -> Result, Error> { + let key_value = Arc::new(kvdb_rocksdb::Database::open(&self.config, &db_path.to_string_lossy())?); + let blooms_path = db_path.join("blooms"); + let trace_blooms_path = db_path.join("trace_blooms"); + fs::create_dir(&blooms_path)?; + fs::create_dir(&trace_blooms_path)?; + let blooms = blooms_db::Database::open(blooms_path).unwrap(); + let trace_blooms = blooms_db::Database::open(trace_blooms_path).unwrap(); + let db = RestorationDB { + blooms, + trace_blooms, + key_value, + }; + Ok(Arc::new(db)) + } + } + + Box::new(RestorationDBHandler { config }) +} + /// Generates dummy blockchain with corresponding amount of blocks pub fn generate_dummy_blockchain(block_number: u32) -> BlockChain { let db = new_db(); diff --git a/ethcore/src/test_helpers_internal.rs b/ethcore/src/test_helpers_internal.rs deleted file mode 100644 index d8fd93d97e4..00000000000 --- a/ethcore/src/test_helpers_internal.rs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -//! Internal helpers for client tests - -use std::fs; -use std::path::Path; -use std::sync::Arc; -use kvdb::{KeyValueDB}; -use kvdb_rocksdb::{Database, DatabaseConfig}; -use blockchain::{BlockChainDBHandler, BlockChainDB}; -use blooms_db; -use error::Error; - -/// Creates new instance of KeyValueDBHandler -pub fn restoration_db_handler(config: DatabaseConfig) -> Box { - struct RestorationDBHandler { - config: DatabaseConfig, - } - - struct RestorationDB { - blooms: blooms_db::Database, - trace_blooms: blooms_db::Database, - key_value: Arc, - } - - impl BlockChainDB for RestorationDB { - fn key_value(&self) -> &Arc { - &self.key_value - } - - fn blooms(&self) -> &blooms_db::Database { - &self.blooms - } - - fn trace_blooms(&self) -> &blooms_db::Database { - &self.trace_blooms - } - } - - impl BlockChainDBHandler for RestorationDBHandler { - fn open(&self, db_path: &Path) -> Result, Error> { - let key_value = Arc::new(Database::open(&self.config, &db_path.to_string_lossy())?); - let blooms_path = db_path.join("blooms"); - let trace_blooms_path = db_path.join("trace_blooms"); - fs::create_dir(&blooms_path)?; - fs::create_dir(&trace_blooms_path)?; - let blooms = blooms_db::Database::open(blooms_path).unwrap(); - let trace_blooms = blooms_db::Database::open(trace_blooms_path).unwrap(); - let db = RestorationDB { - blooms, - trace_blooms, - key_value, - }; - Ok(Arc::new(db)) - } - } - - Box::new(RestorationDBHandler { config }) -} diff --git a/ethcore/sync/src/tests/helpers.rs b/ethcore/sync/src/tests/helpers.rs index 407f699e0e6..b873af343dc 100644 --- a/ethcore/sync/src/tests/helpers.rs +++ b/ethcore/sync/src/tests/helpers.rs @@ -29,6 +29,7 @@ use ethcore::snapshot::SnapshotService; use ethcore::spec::Spec; use ethcore::account_provider::AccountProvider; use ethcore::miner::Miner; +use ethcore::test_helpers; use sync_io::SyncIo; use io::{IoChannel, IoContext, IoHandler}; use api::WARP_SYNC_PROTOCOL_ID; @@ -384,7 +385,7 @@ impl TestNet> { let client = EthcoreClient::new( ClientConfig::default(), &spec, - Arc::new(::kvdb_memorydb::create(::ethcore::db::NUM_COLUMNS.unwrap_or(0))), + test_helpers::new_db(), miner.clone(), channel.clone() ).unwrap(); diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 26117471cee..a65d81197f5 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -26,11 +26,11 @@ use ethcore::ethereum; use ethcore::ids::BlockId; use ethcore::miner::Miner; use ethcore::spec::{Genesis, Spec}; +use ethcore::test_helpers; use ethcore::views::BlockView; use ethjson::blockchain::BlockChain; use ethjson::state::test::ForkSpec; use io::IoChannel; -use kvdb_memorydb; use miner::external::ExternalMiner; use parking_lot::Mutex; @@ -108,7 +108,7 @@ impl EthTester { let client = Client::new( ClientConfig::default(), &spec, - Arc::new(kvdb_memorydb::create(::ethcore::db::NUM_COLUMNS.unwrap_or(0))), + test_helpers::new_db(), miner_service.clone(), IoChannel::disconnected(), ).unwrap(); From fd06dcaaeb2fda20137cbe378cc236a27f202f7d Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 4 Jun 2018 12:16:39 +0200 Subject: [PATCH 15/29] kvdb-rocksdb uses fs-swap crate --- util/kvdb-rocksdb/Cargo.toml | 3 ++- util/kvdb-rocksdb/src/lib.rs | 31 +++---------------------------- 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/util/kvdb-rocksdb/Cargo.toml b/util/kvdb-rocksdb/Cargo.toml index 07016b68a2d..8ff2c5aaab6 100644 --- a/util/kvdb-rocksdb/Cargo.toml +++ b/util/kvdb-rocksdb/Cargo.toml @@ -6,13 +6,14 @@ authors = ["Parity Technologies "] [dependencies] elastic-array = "0.10" ethereum-types = "0.3" +fs-swap = "0.1" +interleaved-ordered = "0.1.0" kvdb = { path = "../kvdb" } log = "0.3" num_cpus = "1.0" parking_lot = "0.5" regex = "0.2" rocksdb = { git = "https://github.com/paritytech/rust-rocksdb" } -interleaved-ordered = "0.1.0" [dev-dependencies] tempdir = "0.3" diff --git a/util/kvdb-rocksdb/src/lib.rs b/util/kvdb-rocksdb/src/lib.rs index 60524682984..fb7931565f5 100644 --- a/util/kvdb-rocksdb/src/lib.rs +++ b/util/kvdb-rocksdb/src/lib.rs @@ -18,6 +18,7 @@ extern crate log; extern crate elastic_array; +extern crate fs_swap; extern crate interleaved_ordered; extern crate num_cpus; extern crate parking_lot; @@ -590,34 +591,8 @@ impl Database { pub fn restore(&self, new_db: &str) -> Result<()> { self.close(); - let mut backup_db = PathBuf::from(&self.path); - backup_db.pop(); - backup_db.push("backup_db"); - - let existed = match fs::rename(&self.path, &backup_db) { - Ok(_) => true, - Err(e) => if let io::ErrorKind::NotFound = e.kind() { - false - } else { - return Err(e.into()); - } - }; - - match fs::rename(&new_db, &self.path) { - Ok(_) => { - // clean up the backup. - if existed { - fs::remove_dir_all(&backup_db)?; - } - } - Err(e) => { - // restore the backup. - if existed { - fs::rename(&backup_db, &self.path)?; - } - return Err(e.into()) - } - } + fs_swap::swap(&self.path, new_db)?; + fs::remove_dir_all(new_db)?; // reopen the database and steal handles into self let db = Self::open(&self.config, &self.path)?; From bac4638ad5fabdafbced2e08228b69e5a43281a5 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 4 Jun 2018 12:19:24 +0200 Subject: [PATCH 16/29] update Cargo.lock --- Cargo.lock | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 680b9606ec0..87e223834c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1113,6 +1113,11 @@ name = "fnv" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fs-swap" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -1500,6 +1505,7 @@ version = "0.1.0" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fs-swap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3888,6 +3894,7 @@ dependencies = [ "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" +"checksum fs-swap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8aa1edbe0b31d35059b5a61a780c31885c692024edaf24bfd8e6393b520c6888" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" From db2740ea0af447a0a27f1378277a8fbe8d3dd14b Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 5 Jun 2018 14:08:23 +0200 Subject: [PATCH 17/29] use fs::rename --- Cargo.lock | 7 ------- util/kvdb-rocksdb/Cargo.toml | 1 - util/kvdb-rocksdb/src/lib.rs | 11 ++++++----- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87e223834c7..680b9606ec0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1113,11 +1113,6 @@ name = "fnv" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "fs-swap" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -1505,7 +1500,6 @@ version = "0.1.0" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fs-swap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3894,7 +3888,6 @@ dependencies = [ "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" -"checksum fs-swap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8aa1edbe0b31d35059b5a61a780c31885c692024edaf24bfd8e6393b520c6888" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" diff --git a/util/kvdb-rocksdb/Cargo.toml b/util/kvdb-rocksdb/Cargo.toml index 8ff2c5aaab6..023b59c5b01 100644 --- a/util/kvdb-rocksdb/Cargo.toml +++ b/util/kvdb-rocksdb/Cargo.toml @@ -6,7 +6,6 @@ authors = ["Parity Technologies "] [dependencies] elastic-array = "0.10" ethereum-types = "0.3" -fs-swap = "0.1" interleaved-ordered = "0.1.0" kvdb = { path = "../kvdb" } log = "0.3" diff --git a/util/kvdb-rocksdb/src/lib.rs b/util/kvdb-rocksdb/src/lib.rs index fb7931565f5..e9f90f88616 100644 --- a/util/kvdb-rocksdb/src/lib.rs +++ b/util/kvdb-rocksdb/src/lib.rs @@ -18,7 +18,6 @@ extern crate log; extern crate elastic_array; -extern crate fs_swap; extern crate interleaved_ordered; extern crate num_cpus; extern crate parking_lot; @@ -31,8 +30,8 @@ extern crate kvdb; use std::cmp; use std::collections::HashMap; use std::marker::PhantomData; -use std::path::{PathBuf, Path}; -use std::{fs, io, mem, result}; +use std::path::Path; +use std::{fs, mem, result}; use parking_lot::{Mutex, MutexGuard, RwLock}; use rocksdb::{ @@ -591,8 +590,10 @@ impl Database { pub fn restore(&self, new_db: &str) -> Result<()> { self.close(); - fs_swap::swap(&self.path, new_db)?; - fs::remove_dir_all(new_db)?; + // rename is guaranteed to be atomic on unix + // on windows is guaranteed to be atomic if it is the same volume + // if it is not, then os crates a backup for us + fs::rename(new_db, &self.path)?; // reopen the database and steal handles into self let db = Self::open(&self.config, &self.path)?; From 50aa947b09d4210fc6cb4479d35719e3d917ef04 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 5 Jun 2018 14:30:58 +0200 Subject: [PATCH 18/29] fixed failing test on linux --- util/kvdb-rocksdb/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/kvdb-rocksdb/src/lib.rs b/util/kvdb-rocksdb/src/lib.rs index e9f90f88616..c685da4ea45 100644 --- a/util/kvdb-rocksdb/src/lib.rs +++ b/util/kvdb-rocksdb/src/lib.rs @@ -49,6 +49,8 @@ use regex::Regex; use std::process::Command; #[cfg(target_os = "linux")] use std::fs::File; +#[cfg(target_os = "linux")] +use std::path::PathBuf; const DB_DEFAULT_MEMORY_BUDGET_MB: usize = 128; @@ -76,7 +78,6 @@ impl Default for CompactionProfile { } /// Given output of df command return Linux rotational flag file path. -#[cfg(target_os = "linux")] pub fn rotational_from_df_output(df_out: Vec) -> Option { use std::str; str::from_utf8(df_out.as_slice()) From 7edca53c8583e81888f5956c74cafd650030d60c Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 12 Jun 2018 08:12:27 +0200 Subject: [PATCH 19/29] fix tests --- ethcore/src/snapshot/tests/service.rs | 3 +++ util/kvdb-rocksdb/src/lib.rs | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 55cb0e8338b..1c1bc9dd0e7 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -40,6 +40,9 @@ impl snapshot::DatabaseRestore for NoopDBRestore { #[test] fn restored_is_equivalent() { + use ::ethcore_logger::init_log; + init_log(); + const NUM_BLOCKS: u32 = 400; const TX_PER: usize = 5; diff --git a/util/kvdb-rocksdb/src/lib.rs b/util/kvdb-rocksdb/src/lib.rs index c685da4ea45..e7eda12aa34 100644 --- a/util/kvdb-rocksdb/src/lib.rs +++ b/util/kvdb-rocksdb/src/lib.rs @@ -50,7 +50,7 @@ use std::process::Command; #[cfg(target_os = "linux")] use std::fs::File; #[cfg(target_os = "linux")] -use std::path::PathBuf; +use std::path::Path; const DB_DEFAULT_MEMORY_BUDGET_MB: usize = 128; @@ -78,6 +78,7 @@ impl Default for CompactionProfile { } /// Given output of df command return Linux rotational flag file path. +#[cfg(target_os = "linux")] pub fn rotational_from_df_output(df_out: Vec) -> Option { use std::str; str::from_utf8(df_out.as_slice()) From 914aec579fe1224a998a2e259fa43d34f292cf63 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 12 Jun 2018 15:42:20 +0200 Subject: [PATCH 20/29] use fs_swap --- Cargo.lock | 11 +++++++++++ util/kvdb-rocksdb/Cargo.toml | 1 + util/kvdb-rocksdb/src/lib.rs | 14 ++++++++++---- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60565f17585..cbd997f778d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1112,6 +1112,15 @@ name = "fnv" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fs-swap" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -1499,6 +1508,7 @@ version = "0.1.0" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fs-swap 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3835,6 +3845,7 @@ dependencies = [ "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" +"checksum fs-swap 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "18c72c2e124a7f8cf6966d72143940885a0936f30cabe807001552126a50737d" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" diff --git a/util/kvdb-rocksdb/Cargo.toml b/util/kvdb-rocksdb/Cargo.toml index 023b59c5b01..d49d8385d22 100644 --- a/util/kvdb-rocksdb/Cargo.toml +++ b/util/kvdb-rocksdb/Cargo.toml @@ -6,6 +6,7 @@ authors = ["Parity Technologies "] [dependencies] elastic-array = "0.10" ethereum-types = "0.3" +fs-swap = "0.2.1" interleaved-ordered = "0.1.0" kvdb = { path = "../kvdb" } log = "0.3" diff --git a/util/kvdb-rocksdb/src/lib.rs b/util/kvdb-rocksdb/src/lib.rs index e7eda12aa34..cd3bfab9fce 100644 --- a/util/kvdb-rocksdb/src/lib.rs +++ b/util/kvdb-rocksdb/src/lib.rs @@ -18,6 +18,7 @@ extern crate log; extern crate elastic_array; +extern crate fs_swap; extern crate interleaved_ordered; extern crate num_cpus; extern crate parking_lot; @@ -41,6 +42,7 @@ use rocksdb::{ use interleaved_ordered::{interleave_ordered, InterleaveOrdered}; use elastic_array::ElasticArray32; +use fs_swap::{swap, swap_nonatomic}; use kvdb::{KeyValueDB, DBTransaction, DBValue, DBOp, Result}; #[cfg(target_os = "linux")] @@ -592,10 +594,14 @@ impl Database { pub fn restore(&self, new_db: &str) -> Result<()> { self.close(); - // rename is guaranteed to be atomic on unix - // on windows is guaranteed to be atomic if it is the same volume - // if it is not, then os crates a backup for us - fs::rename(new_db, &self.path)?; + // swap is guaranteed to be atomic + if let Err(err) = swap(new_db, &self.path) { + warn!("DB atomic swap failed: {}", err); + if let Err(err) = swap_nonatomic(new_db, &self.path) { + warn!("DB nonatomic atomic swap failed: {}", err); + return Err(err.into()); + } + } // reopen the database and steal handles into self let db = Self::open(&self.config, &self.path)?; From 3bc7a8c54cd227c807507db3a8688bcf66fef211 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 13 Jun 2018 00:01:05 +0200 Subject: [PATCH 21/29] fixed failing test on linux --- util/kvdb-rocksdb/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/kvdb-rocksdb/src/lib.rs b/util/kvdb-rocksdb/src/lib.rs index cd3bfab9fce..baf41f28172 100644 --- a/util/kvdb-rocksdb/src/lib.rs +++ b/util/kvdb-rocksdb/src/lib.rs @@ -52,7 +52,7 @@ use std::process::Command; #[cfg(target_os = "linux")] use std::fs::File; #[cfg(target_os = "linux")] -use std::path::Path; +use std::path::PathBuf; const DB_DEFAULT_MEMORY_BUDGET_MB: usize = 128; From bfc744b547eb36984c5ead98e15a506b1a536edf Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 13 Jun 2018 10:42:40 +0200 Subject: [PATCH 22/29] cleanup after swap --- util/kvdb-rocksdb/src/lib.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/util/kvdb-rocksdb/src/lib.rs b/util/kvdb-rocksdb/src/lib.rs index baf41f28172..f25b333d238 100644 --- a/util/kvdb-rocksdb/src/lib.rs +++ b/util/kvdb-rocksdb/src/lib.rs @@ -595,11 +595,23 @@ impl Database { self.close(); // swap is guaranteed to be atomic - if let Err(err) = swap(new_db, &self.path) { - warn!("DB atomic swap failed: {}", err); - if let Err(err) = swap_nonatomic(new_db, &self.path) { - warn!("DB nonatomic atomic swap failed: {}", err); - return Err(err.into()); + match swap(new_db, &self.path) { + Ok(_) => { + // ignore errors + let _ = fs::remove_dir_all(new_db); + }, + Err(err) => { + warn!("DB atomic swap failed: {}", err); + match swap_nonatomic(new_db, &self.path) { + Ok(_) => { + // ignore errors + let _ = fs::remove_dir_all(new_db); + }, + Err(err) => { + warn!("DB nonatomic atomic swap failed: {}", err); + return Err(err.into()); + } + } } } From fdc943a73f29e0cf9d8002698c673e59b1c3594d Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 13 Jun 2018 15:28:07 +0200 Subject: [PATCH 23/29] fix tests --- ethcore/src/tx_filter.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ethcore/src/tx_filter.rs b/ethcore/src/tx_filter.rs index c1e9adb0c38..585dc7e3d38 100644 --- a/ethcore/src/tx_filter.rs +++ b/ethcore/src/tx_filter.rs @@ -156,14 +156,14 @@ mod test { fn transaction_filter() { let spec_data = include_str!("../res/tx_permission_tests/contract_ver_2_genesis.json"); + let db = test_helpers::new_db(); let tempdir = TempDir::new("").unwrap(); let spec = Spec::load(&tempdir.path(), spec_data.as_bytes()).unwrap(); - let client_db = Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); let client = Client::new( ClientConfig::default(), &spec, - client_db, + db, Arc::new(Miner::new_for_tests(&spec, None)), IoChannel::disconnected(), ).unwrap(); @@ -233,7 +233,6 @@ mod test { let db = test_helpers::new_db(); let tempdir = TempDir::new("").unwrap(); let spec = Spec::load(&tempdir.path(), spec_data.as_bytes()).unwrap(); - //let client_db = Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); let client = Client::new( ClientConfig::default(), From f82f599053633f3f7fc37560e0d01605be0aba0d Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 14 Jun 2018 14:16:42 +0200 Subject: [PATCH 24/29] fixed osx permissions --- ethstore/src/accounts_dir/disk.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethstore/src/accounts_dir/disk.rs b/ethstore/src/accounts_dir/disk.rs index a5ce9c1a9c6..a9253cff06f 100644 --- a/ethstore/src/accounts_dir/disk.rs +++ b/ethstore/src/accounts_dir/disk.rs @@ -42,7 +42,7 @@ fn create_new_file_with_permissions_to_owner(file_path: &Path) -> io::Result io::Result Date: Thu, 14 Jun 2018 15:18:48 +0200 Subject: [PATCH 25/29] simplify parity database opening functions --- parity/blockchain.rs | 8 +++-- parity/db/mod.rs | 2 +- parity/db/rocksdb/mod.rs | 56 +++++++-------------------------- parity/export_hardcoded_sync.rs | 2 +- parity/run.rs | 5 +-- parity/snapshot.rs | 3 +- 6 files changed, 24 insertions(+), 52 deletions(-) diff --git a/parity/blockchain.rs b/parity/blockchain.rs index d33ac1eacba..af5373b3994 100644 --- a/parity/blockchain.rs +++ b/parity/blockchain.rs @@ -208,7 +208,7 @@ fn execute_import_light(cmd: ImportBlockchain) -> Result<(), String> { let db = db::open_db(&client_path.to_str().expect("DB path could not be converted to string."), &cmd.cache_config, &cmd.compaction, - cmd.wal)?; + cmd.wal).map_err(|e| format!("Failed to open database: {:?}", e))?; // TODO: could epoch signals be avilable at the end of the file? let fetch = ::light::client::fetch::unavailable(); @@ -362,8 +362,9 @@ fn execute_import(cmd: ImportBlockchain) -> Result<(), String> { client_config.queue.verifier_settings = cmd.verifier_settings; - let client_db = db::open_client_db(&client_path, &client_config)?; let restoration_db_handler = db::restoration_db_handler(&client_path, &client_config); + let client_db = restoration_db_handler.open(&client_path) + .map_err(|e| format!("Failed to open database {:?}", e))?; // build client let service = ClientService::start( @@ -552,8 +553,9 @@ fn start_client( true, ); - let client_db = db::open_client_db(&client_path, &client_config)?; let restoration_db_handler = db::restoration_db_handler(&client_path, &client_config); + let client_db = restoration_db_handler.open(&client_path) + .map_err(|e| format!("Failed to open database {:?}", e))?; let service = ClientService::start( client_config, diff --git a/parity/db/mod.rs b/parity/db/mod.rs index 39f43fd145e..a5d66339826 100644 --- a/parity/db/mod.rs +++ b/parity/db/mod.rs @@ -19,7 +19,7 @@ #[path="rocksdb/mod.rs"] mod impls; -pub use self::impls::{open_db, open_client_db, restoration_db_handler, migrate}; +pub use self::impls::{open_db, restoration_db_handler, migrate}; #[cfg(feature = "secretstore")] pub use self::impls::open_secretstore_db; diff --git a/parity/db/rocksdb/mod.rs b/parity/db/rocksdb/mod.rs index 7dafdaeb051..7f8bcae6fc5 100644 --- a/parity/db/rocksdb/mod.rs +++ b/parity/db/rocksdb/mod.rs @@ -66,28 +66,6 @@ pub fn open_secretstore_db(data_path: &str) -> Result, String> { Ok(Arc::new(Database::open_default(&db_path).map_err(|e| format!("Error opening database: {:?}", e))?)) } -/// Open a new client DB. -pub fn open_client_db(client_path: &Path, client_config: &ClientConfig) -> Result, String> { - let client_db_config = helpers::client_db_config(client_path, client_config); - let blooms_path = client_path.join("blooms"); - let trace_blooms_path = client_path.join("trace_blooms"); - fs::create_dir(&blooms_path).map_err(|e| e.to_string())?; - fs::create_dir(&trace_blooms_path).map_err(|e| e.to_string())?; - - let client_db = Arc::new(Database::open( - &client_db_config, - &client_path.to_str().expect("DB path could not be converted to string.") - ).map_err(|e| format!("Client service database error: {:?}", e))?); - - let db = AppDB { - key_value: client_db, - blooms: blooms_db::Database::open(blooms_path).map_err(|e| e.to_string())?, - trace_blooms: blooms_db::Database::open(trace_blooms_path).map_err(|e| e.to_string())?, - }; - - Ok(Arc::new(db)) -} - /// Create a restoration db handler using the config generated by `client_path` and `client_config`. pub fn restoration_db_handler(client_path: &Path, client_config: &ClientConfig) -> Box { let client_db_config = helpers::client_db_config(client_path, client_config); @@ -98,18 +76,7 @@ pub fn restoration_db_handler(client_path: &Path, client_config: &ClientConfig) impl BlockChainDBHandler for RestorationDBHandler { fn open(&self, db_path: &Path) -> Result, Error> { - let blooms_path = db_path.join("blooms"); - let trace_blooms_path = db_path.join("trace_blooms"); - fs::create_dir(&blooms_path)?; - fs::create_dir(&trace_blooms_path)?; - - let db = AppDB { - key_value: Arc::new(Database::open(&self.config, &db_path.to_string_lossy())?), - blooms: blooms_db::Database::open(blooms_path)?, - trace_blooms: blooms_db::Database::open(trace_blooms_path)?, - }; - - Ok(Arc::new(db)) + open_database(&db_path.to_string_lossy(), &self.config) } } @@ -119,7 +86,7 @@ pub fn restoration_db_handler(client_path: &Path, client_config: &ClientConfig) } /// Open a new main DB. -pub fn open_db(client_path: &str, cache_config: &CacheConfig, compaction: &DatabaseCompactionProfile, wal: bool) -> Result, String> { +pub fn open_db(client_path: &str, cache_config: &CacheConfig, compaction: &DatabaseCompactionProfile, wal: bool) -> Result, Error> { let path = Path::new(client_path); let db_config = DatabaseConfig { @@ -129,20 +96,21 @@ pub fn open_db(client_path: &str, cache_config: &CacheConfig, compaction: &Datab .. DatabaseConfig::with_columns(NUM_COLUMNS) }; - let key_value = Arc::new(Database::open( - &db_config, - client_path - ).map_err(|e| format!("Failed to open database: {}", e))?); + open_database(client_path, &db_config) +} + +fn open_database(client_path: &str, config: &DatabaseConfig) -> Result, Error> { + let path = Path::new(client_path); let blooms_path = path.join("blooms"); let trace_blooms_path = path.join("trace_blooms"); - fs::create_dir(&blooms_path).map_err(|e| e.to_string())?; - fs::create_dir(&trace_blooms_path).map_err(|e| e.to_string())?; + fs::create_dir(&blooms_path)?; + fs::create_dir(&trace_blooms_path)?; let db = AppDB { - key_value, - blooms: blooms_db::Database::open(blooms_path).map_err(|e| e.to_string())?, - trace_blooms: blooms_db::Database::open(trace_blooms_path).map_err(|e| e.to_string())?, + key_value: Arc::new(Database::open(&config, client_path)?), + blooms: blooms_db::Database::open(blooms_path)?, + trace_blooms: blooms_db::Database::open(trace_blooms_path)?, }; Ok(Arc::new(db)) diff --git a/parity/export_hardcoded_sync.rs b/parity/export_hardcoded_sync.rs index 008a5b9ecda..80ffc593987 100644 --- a/parity/export_hardcoded_sync.rs +++ b/parity/export_hardcoded_sync.rs @@ -90,7 +90,7 @@ pub fn execute(cmd: ExportHsyncCmd) -> Result { let db = db::open_db(&db_dirs.client_path(algorithm).to_str().expect("DB path could not be converted to string."), &cmd.cache_config, &cmd.compaction, - cmd.wal)?; + cmd.wal).map_err(|e| format!("Failed to open database {:?}", e))?; let service = light_client::Service::start(config, &spec, UnavailableDataFetcher, db, cache) .map_err(|e| format!("Error starting light client: {}", e))?; diff --git a/parity/run.rs b/parity/run.rs index 793b03f5c62..de5628eac0f 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -219,7 +219,7 @@ fn execute_light_impl(cmd: RunCmd, logger: Arc) -> Result(cmd: RunCmd, logger: Arc, on_client_rq: // set network path. net_conf.net_config_path = Some(db_dirs.network_path().to_string_lossy().into_owned()); - let client_db = db::open_client_db(&client_path, &client_config)?; let restoration_db_handler = db::restoration_db_handler(&client_path, &client_config); + let client_db = restoration_db_handler.open(&client_path) + .map_err(|e| format!("Failed to open database {:?}", e))?; // create client service. let service = ClientService::start( diff --git a/parity/snapshot.rs b/parity/snapshot.rs index 90ae8327a61..77271925011 100644 --- a/parity/snapshot.rs +++ b/parity/snapshot.rs @@ -182,8 +182,9 @@ impl SnapshotCommand { true ); - let client_db = db::open_client_db(&client_path, &client_config)?; let restoration_db_handler = db::restoration_db_handler(&client_path, &client_config); + let client_db = restoration_db_handler.open(&client_path) + .map_err(|e| format!("Failed to open database {:?}", e))?; let service = ClientService::start( client_config, From 447950e7c160b8ee2c886d3659007fc7cf50567f Mon Sep 17 00:00:00 2001 From: debris Date: Thu, 14 Jun 2018 16:39:34 +0200 Subject: [PATCH 26/29] added migration to blooms-db --- parity/db/rocksdb/blooms.rs | 84 ++++++++++++++++++++++++++++++++++ parity/db/rocksdb/migration.rs | 31 ++++++++++--- parity/db/rocksdb/mod.rs | 3 +- 3 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 parity/db/rocksdb/blooms.rs diff --git a/parity/db/rocksdb/blooms.rs b/parity/db/rocksdb/blooms.rs new file mode 100644 index 00000000000..eba8eb896f7 --- /dev/null +++ b/parity/db/rocksdb/blooms.rs @@ -0,0 +1,84 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Blooms migration from rocksdb to blooms-db + +use std::path::Path; +use ethereum_types::Bloom; +use ethcore::error::Error; +use rlp; +use super::kvdb_rocksdb::DatabaseConfig; +use super::open_database; + +pub fn migrate_blooms>(path: P, config: &DatabaseConfig) -> Result<(), Error> { + // init + let db = open_database(&path.as_ref().to_string_lossy(), config)?; + + // possible optimization: + // pre-allocate space on disk for faster migration + + // iterate over header blooms and insert them in blooms-db + // Some(3) -> COL_EXTRA + // 3u8 -> ExtrasIndex::BlocksBlooms + // 0u8 -> level 0 + let blooms_iterator = db.key_value() + .iter_from_prefix(Some(3), &[3u8, 0u8]) + .filter(|(key, _)| key.len() == 6) + .take_while(|(key, _)| { + key[0] == 3u8 && key[1] == 0u8 + }) + .map(|(key, group)| { + let number = + (key[2] as u64) << 24 | + (key[3] as u64) << 16 | + (key[4] as u64) << 8 | + (key[5] as u64); + + let blooms = rlp::decode_list::(&group); + (number, blooms) + }); + + for (number, blooms) in blooms_iterator { + db.blooms().insert_blooms(number, blooms.iter())?; + } + + // iterate over trace blooms and insert them in blooms-db + // Some(4) -> COL_TRACE + // 1u8 -> TraceDBIndex::BloomGroups + // 0u8 -> level 0 + let trace_blooms_iterator = db.key_value() + .iter_from_prefix(Some(4), &[1u8, 0u8]) + .filter(|(key, _)| key.len() == 6) + .take_while(|(key, _)| { + key[0] == 1u8 && key[1] == 0u8 + }) + .map(|(key, group)| { + let number = + (key[2] as u64) | + (key[3] as u64) << 8 | + (key[4] as u64) << 16 | + (key[5] as u64) << 24; + + let blooms = rlp::decode_list::(&group); + (number, blooms) + }); + + for (number, blooms) in trace_blooms_iterator { + db.trace_blooms().insert_blooms(number, blooms.iter())?; + } + + Ok(()) +} diff --git a/parity/db/rocksdb/migration.rs b/parity/db/rocksdb/migration.rs index e92a9db0356..834bfa0e811 100644 --- a/parity/db/rocksdb/migration.rs +++ b/parity/db/rocksdb/migration.rs @@ -19,10 +19,12 @@ use std::io::{Read, Write, Error as IoError, ErrorKind}; use std::path::{Path, PathBuf}; use std::fmt::{Display, Formatter, Error as FmtError}; use super::migration_rocksdb::{self, Manager as MigrationManager, Config as MigrationConfig, ChangeColumns}; -use super::kvdb_rocksdb::CompactionProfile; +use super::kvdb_rocksdb::{CompactionProfile, DatabaseConfig}; use ethcore::client::DatabaseCompactionProfile; +use ethcore::{self, db}; use super::helpers; +use super::blooms::migrate_blooms; /// The migration from v10 to v11. /// Adds a column for node info. @@ -43,9 +45,9 @@ pub const TO_V12: ChangeColumns = ChangeColumns { /// Database is assumed to be at default version, when no version file is found. const DEFAULT_VERSION: u32 = 5; /// Current version of database models. -const CURRENT_VERSION: u32 = 12; -/// First version of the consolidated database. -const CONSOLIDATION_VERSION: u32 = 9; +const CURRENT_VERSION: u32 = 13; +/// A version of database at which blooms-db was introduced +const BLOOMS_DB_VERSION: u32 = 13; /// Defines how many items are migrated to the new version of database at once. const BATCH_SIZE: usize = 1024; /// Version file name. @@ -62,6 +64,8 @@ pub enum Error { MigrationImpossible, /// Internal migration error. Internal(migration_rocksdb::Error), + /// Blooms-db migration error. + BloomsDB(ethcore::error::Error), /// Migration was completed succesfully, /// but there was a problem with io. Io(IoError), @@ -74,6 +78,7 @@ impl Display for Error { Error::FutureDBVersion => "Database was created with newer client version. Upgrade your client or delete DB and resync.".into(), Error::MigrationImpossible => format!("Database migration to version {} is not possible.", CURRENT_VERSION), Error::Internal(ref err) => format!("{}", err), + Error::BloomsDB(ref err) => format!("blooms-db migration error: {}", err), Error::Io(ref err) => format!("Unexpected io error on DB migration: {}.", err), }; @@ -212,9 +217,23 @@ pub fn migrate(path: &Path, compaction_profile: &DatabaseCompactionProfile) -> R } // Further migrations - if version >= CONSOLIDATION_VERSION && version < CURRENT_VERSION && exists(&consolidated_database_path(path)) { - println!("Migrating database from version {} to {}", ::std::cmp::max(CONSOLIDATION_VERSION, version), CURRENT_VERSION); + if version < CURRENT_VERSION && exists(&consolidated_database_path(path)) { + println!("Migrating database from version {} to {}", version, CURRENT_VERSION); migrate_database(version, consolidated_database_path(path), consolidated_database_migrations(&compaction_profile)?)?; + + if version < BLOOMS_DB_VERSION { + println!("Migrating blooms to blooms-db..."); + let db_config = DatabaseConfig { + max_open_files: 64, + memory_budget: None, + compaction: compaction_profile, + columns: db::NUM_COLUMNS, + wal: true, + }; + + migrate_blooms(path, &db_config).map_err(Error::BloomsDB)?; + } + println!("Migration finished"); } diff --git a/parity/db/rocksdb/mod.rs b/parity/db/rocksdb/mod.rs index 7f8bcae6fc5..782bf8886f9 100644 --- a/parity/db/rocksdb/mod.rs +++ b/parity/db/rocksdb/mod.rs @@ -30,6 +30,7 @@ use self::kvdb_rocksdb::{Database, DatabaseConfig}; use cache::CacheConfig; +mod blooms; mod migration; mod helpers; @@ -99,7 +100,7 @@ pub fn open_db(client_path: &str, cache_config: &CacheConfig, compaction: &Datab open_database(client_path, &db_config) } -fn open_database(client_path: &str, config: &DatabaseConfig) -> Result, Error> { +pub fn open_database(client_path: &str, config: &DatabaseConfig) -> Result, Error> { let path = Path::new(client_path); let blooms_path = path.join("blooms"); From f37f5e749ed8c1e372f2eb34dc81be236c0b8819 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 20 Jun 2018 11:26:45 +0200 Subject: [PATCH 27/29] address @niklasad1 grumbles --- ethcore/src/blockchain/blockchain.rs | 11 +++++++++-- ethcore/src/snapshot/service.rs | 1 - ethcore/src/trace/db.rs | 9 ++++++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index c28bc4104fe..fa79bd74556 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -170,7 +170,11 @@ pub trait BlockProvider { /// Returns numbers of blocks containing given bloom. fn blocks_with_bloom<'a, B, I, II>(&self, blooms: II, from_block: BlockNumber, to_block: BlockNumber) -> Vec - where BloomRef<'a>: From, II: IntoIterator + Copy, I: Iterator, Self: Sized; + where + BloomRef<'a>: From, + II: IntoIterator + Copy, + I: Iterator, + Self: Sized; /// Returns logs matching given filter. fn logs(&self, blocks: Vec, matches: F, limit: Option) -> Vec @@ -336,7 +340,10 @@ impl BlockProvider for BlockChain { /// Returns numbers of blocks containing given bloom. fn blocks_with_bloom<'a, B, I, II>(&self, blooms: II, from_block: BlockNumber, to_block: BlockNumber) -> Vec - where BloomRef<'a>: From, II: IntoIterator + Copy, I: Iterator { + where + BloomRef<'a>: From, + II: IntoIterator + Copy, + I: Iterator { self.db.blooms() .filter(from_block, to_block, blooms) .expect("Low level database error. Some issue with disk?") diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index 1c4851285d0..14d9be8f4bb 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -621,7 +621,6 @@ impl Service { match is_done { true => { - // TODO: flush also blooms? db.key_value().flush().map_err(UtilError::from)?; drop(db); return self.finalize_restoration(&mut *restoration); diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index 1e85993f9ea..b74ff7d55b4 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -56,6 +56,7 @@ impl Key for H256 { pub struct TraceDB where T: DatabaseExtras { /// cache traces: RwLock>, + /// hashes of cached traces cache_manager: RwLock>, /// db db: Arc, @@ -209,8 +210,9 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { }) .collect(); - // TODO: replace it with database for trace blooms - self.db.trace_blooms().insert_blooms(range_start, enacted_blooms.iter()).expect("TODO: blooms pr"); + self.db.trace_blooms() + .insert_blooms(range_start, enacted_blooms.iter()) + .expect("Low level database error. Some issue with disk?"); } // insert new block traces into the cache and the database @@ -310,7 +312,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { fn filter(&self, filter: &Filter) -> Vec { let possibilities = filter.bloom_possibilities(); let numbers = self.db.trace_blooms() - .filter(filter.range.start as u64, filter.range.end as u64, &possibilities).expect("TODO: blooms pr"); + .filter(filter.range.start as u64, filter.range.end as u64, &possibilities) + .expect("Low level database error. Some issue with disk?"); numbers.into_iter() .flat_map(|n| { From 26c45cd31fa0bf52bdc1eac17f2deaf6fa5a0305 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 20 Jun 2018 11:29:41 +0200 Subject: [PATCH 28/29] fix license and authors field of blooms-db Cargo.toml --- util/blooms-db/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/util/blooms-db/Cargo.toml b/util/blooms-db/Cargo.toml index 2abf03cba0e..da6bb154c57 100644 --- a/util/blooms-db/Cargo.toml +++ b/util/blooms-db/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "blooms-db" version = "0.1.0" -authors = ["debris "] +license = "GPL-3.0" +authors = ["Parity Technologies "] [dependencies] byteorder = "1.2" From f1ead7df0b3a4401c2dc1f854ba545e1568eeaf7 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 20 Jun 2018 12:09:04 +0200 Subject: [PATCH 29/29] restore blooms-db after snapshot --- ethcore/src/client/client.rs | 3 ++- util/blooms-db/src/db.rs | 13 ++++++++++++- util/blooms-db/src/lib.rs | 5 +++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 22a9215a47e..3858b484a2e 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1296,8 +1296,9 @@ impl snapshot::DatabaseRestore for Client { self.importer.miner.clear(); let db = self.db.write(); db.key_value().restore(new_db)?; + db.blooms().reopen()?; + db.trace_blooms().reopen()?; - // TODO: restore blooms properly let cache_size = state_db.cache_size(); *state_db = StateDB::new(journaldb::new(db.key_value().clone(), self.pruning, ::db::COL_STATE), cache_size); *chain = Arc::new(BlockChain::new(self.config.blockchain.clone(), &[], db.clone())); diff --git a/util/blooms-db/src/db.rs b/util/blooms-db/src/db.rs index cb88927c7d0..faeb038f296 100644 --- a/util/blooms-db/src/db.rs +++ b/util/blooms-db/src/db.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::{io, fmt}; -use std::path::Path; +use std::path::{Path, PathBuf}; use ethbloom; @@ -53,6 +53,8 @@ pub struct Database { /// /// Every bloom is an ethereum header bloom bot: File, + /// Database path + path: PathBuf, } impl Database { @@ -63,11 +65,20 @@ impl Database { top: File::open(path.join("top.bdb"))?, mid: File::open(path.join("mid.bdb"))?, bot: File::open(path.join("bot.bdb"))?, + path: path.to_owned(), }; Ok(database) } + /// Reopens the database at the same location. + pub fn reopen(&mut self) -> io::Result<()> { + self.top = File::open(self.path.join("top.bdb"))?; + self.mid = File::open(self.path.join("mid.bdb"))?; + self.bot = File::open(self.path.join("bot.bdb"))?; + Ok(()) + } + /// Insert consecutive blooms into database starting with positon from. pub fn insert_blooms<'a, I, B>(&mut self, from: u64, blooms: I) -> io::Result<()> where ethbloom::BloomRef<'a>: From, I: Iterator { diff --git a/util/blooms-db/src/lib.rs b/util/blooms-db/src/lib.rs index 597012e064a..c638154229b 100644 --- a/util/blooms-db/src/lib.rs +++ b/util/blooms-db/src/lib.rs @@ -54,6 +54,11 @@ impl Database { Ok(result) } + /// Reopens database at the same location. + pub fn reopen(&self) -> io::Result<()> { + self.database.lock().reopen() + } + /// Inserts one or more blooms into database. /// /// # Arguments